GoogleMapAPI

MainActivity

public class MainActivity extends Activity {
    private static final String SCHEME = "https";
    private static final String AUTHORITY = "maps.googleapis.com";
    private static final String PATH = "maps/api/geocode/json";
    private static final String TAG = "MainActivity";
    ArrayAdapter<Location> adapter;
    TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitAll().build());
        textView = (TextView)findViewById(R.id.text_result);
    }

    public void onClickButton(View v){
        Builder builder = new Builder();
        builder.scheme(SCHEME);
        builder.authority(AUTHORITY);
        builder.path(PATH);
        
        builder.appendQueryParameter("address", "東京");
        builder.appendQueryParameter("sensor", "true");
        builder.appendQueryParameter("region", "jp");
        builder.appendQueryParameter("language", "ja");

        String uri = Uri.decode(builder.build().toString());
        Log.v(TAG, uri);
        
        try {
            String responce = HttpHelper.getResponseContent(uri);
            textView.setText(responce);
            
            ArrayList<Location> list = JsonHelper.toLocations(responce);
            adapter = new ArrayAdapter<Location>(this, android.R.layout.simple_list_item_1, list);
            
            AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
            dialogBuilder.setTitle("Title");
            dialogBuilder.setSingleChoiceItems(adapter, 0, new OnClickListener() {
                
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    Toast.makeText(MainActivity.this, adapter.getItem(which).name + ":" + adapter.getItem(which).lat, Toast.LENGTH_SHORT).show();
                    dialog.dismiss();
                }
            });
            dialogBuilder.setNegativeButton(android.R.string.cancel, null);
            dialogBuilder.show();
        } catch (HttpHelperException e) {
            Log.e(TAG, e.getMessage(), e);
        } catch (JSONException e) {
            Log.e(TAG, e.getMessage(), e);
        }
    }
}

HttpHelper

public class HttpHelper {
    public static final int TIME_OUT = 30000;
    private static final String TAG = "HttpHelper";

    public static String getResponseContent(String url) throws HttpHelperException {
        Log.v(TAG, ">>>>>>>> Start HttpRequest <<<<<<<<");
        Log.v(TAG, "request for " + url);
        String responce = null;
        try {
            DefaultHttpClient client = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(url);
            HttpResponse httpResponse = client.execute(httpGet);
            // レスポンスチェック
            int statusCode = httpResponse.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_OK) {
                HttpEntity entity = httpResponse.getEntity();
                 responce = EntityUtils.toString(entity);
                Log.v(TAG, "__Responce:" + responce);

            } else {
                Log.e(TAG, "## Request error. url:" + url + " code:" + statusCode);
                throw new HttpHelperException("Connection Failed");
            }
        } catch (Exception e) {
            Log.e(TAG, e.getMessage(), e);
            throw new HttpHelperException("Connection Failed:" + e.getMessage());
        }
        Log.v(TAG, ">>>>>>>> End HttpRequest <<<<<<<<");
        return responce;
    }
}

JsonHelper

public class JsonHelper {

    private static final String TAG = "JsonHelper";
    private static final String PREFIX = "日本, ";

    public static JSONObject toJson(String str) throws JSONException {
        if (TextUtils.isEmpty(str)) {
            throw new JSONException("string is null");
        }

        JSONObject json = null;
        try {
            json = new JSONObject(str);
        } catch (JSONException e) {
            Log.e(TAG, "-toJson- ", e);
        }
        return json;
    }

    public static ArrayList<Location> toLocations(String s) throws JSONException {
        ArrayList<Location> locations = new ArrayList<Location>();
        JSONObject json = toJson(s);
        JSONArray results = json.getJSONArray("results");
        for (int i = 0; i < results.length(); i++) {
            JSONObject result = results.getJSONObject(i);
            locations.add(toLocation(result));
        }
        for(Location location:locations){
            Log.v("", location.toStr());
        }
        return locations;

    }

    public static Location toLocation(JSONObject result) throws JSONException {
        Location location = new Location();
        String formatted_address = result.getString("formatted_address");
        if (formatted_address.startsWith(PREFIX)) {
            location.name = formatted_address.replace(PREFIX, "");
        } else {
            location.name = formatted_address;
        }
        JSONObject geometry = result.getJSONObject("geometry");
        JSONObject jsonLocation = geometry.getJSONObject("location");
        location.lat = jsonLocation.getDouble("lat");
        location.lng = jsonLocation.getDouble("lng");
        return location;
    }
}

Location

public class Location {

    public String name;
    public double lat;
    public double lng;

    public String toStr() {
        return "Location [name=" + name + ", lat=" + lat + ", lng=" + lng + "]";
    }
    
    @Override
    public String toString() {
        return name;
    }
}

Adapterを使ったSIngleChoiceDialog

public class AlertDialogSingleChoice extends Activity {
    String[] ar = { "red", "green", "bule", "white" , "apple" };
    ArrayAdapter<Location> adapter;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        adapter = new ArrayAdapter<AlertDialogSingleChoice.Location>(this, android.R.layout.select_dialog_singlechoice);
        
        int i =0;
        for(String s : ar){
            adapter.add(new Location(s, i+ 1.1f, i+ 1.2f));
            i++;
        }
       
    }

    public void onClickButton(View v) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Title");
        builder.setSingleChoiceItems(adapter, 0, new OnClickListener() {
            
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(AlertDialogSingleChoice.this, adapter.getItem(which).name + ":" + adapter.getItem(which).lat, Toast.LENGTH_SHORT).show();
                dialog.dismiss();
                
            }
        });
        builder.show();
    }
    
    class Location{
        String name;
        float lat;
        float lng;
        public Location(String name, float lat, float lng) {
            super();
            this.name = name;
            this.lat = lat;
            this.lng = lng;
        }
        
        @Override
        public String toString() {
            return name;
        }
    }
}

ボブとアリスのgit-flow(和訳)

登場人物

( ゚⊇゚):ボブ。PL。趣味はボスのフェラーリでこっそりドライブすること
(・∠・`)乙:アリス。PG。最近流行りのgit系女子。今回のプロジェクトでgit-flowを初めて使う
ボス:ボス。愛車フェラーリ

git-flowの導入

( ゚⊇゚)「Hi、アリス。今度のプロジェクトでgit-flowを使ってみようと思うんだけど、どうだい?」
(・∠・`)乙「git-flow? なにそれ?」
( ゚⊇゚)「git-flowは最もクールなgitブランチワークの補助ツールさ!」
(・∠・`)乙「。。。」
( ゚⊇゚)「これを使えば勝手なブランチやリリースタグがどれとかいった混乱を防ぐことができるんだよ」
(・∠・`)乙「面白そうね。ぜひ使ってみましょう!」
( ゚⊇゚)「じゃ、git-flowのインストールからだ。インストールは簡単だよ。portコマンドで一発さ」

$ sudo port install git-flow

git-flowの利用開始

( ゚⊇゚)「インストールができたら、git-flowプロジェクトを作成しよう。」

$ git flow init

Which branch should be used for bringing forth production releases?
   - master
Branch name for production releases: [master] 
Branch name for "next release" development: [develop] 

How to name your supporting branch prefixes?
Feature branches? [feature/] 
Release branches? [release/] 
Hotfix branches? [hotfix/] 
Support branches? [support/] 
Version tag prefix? [] 

(・∠・`)乙「なんか聞いてきたけどどうすればいいのかしら?」
( ゚⊇゚)「git flowは決められた名前でブランチを作成してくれるんだ。initでは、その時の設定を決めることができるのさ。特に理由がないならそのままEnterでOKだよ」
(・∠・`)乙「OKボブ。全部Enterするわ」

機能を追加する

( ゚⊇゚)「これで準備は整った。作業を始めるよ。作業開始もgit flowコマンドを使うんだ。作業用のブランチを作成して、サクッとHelloWorldを作ってくれ。ブランチ名はhelloだ」

$ git flow feature start hello
Switched to a new branch 'feature/hello'

Summary of actions:
- A new branch 'feature/hello' was created, based on 'develop'
- You are now on branch 'feature/hello'

Now, start committing on your feature. When done, use:

     git flow feature finish hello

(・∠・`)乙「git branchを使ってないけど、ブランチって作成されるのかしら?」
( ゚⊇゚)「yes! git-flowを使ったらブランチワークは概ねgit flowで作業するんだよ。ブランチも自動的に作成されているよ。git branchで確かめてごらん。」

$ git branch
  develop
* feature/hello
  master

(・∠・`)乙「ブランチが3ついるわ。helloじゃなくてfeature/helloになっているけど、あとdevelopというブランチもいるわ」
( ゚⊇゚)「OKアリス。ここで各ブランチについて説明しよう。」
( ゚⊇゚)「git-flowではブランチ名にお約束があって、勝手なブランチは作ることができないんだ。使えるブランチは以下のとおりだ」

  • master
  • develop
  • feature/***
  • hotfix/***
  • rerease/***

( ゚⊇゚)「このうち、masterとdevelopはメインブランチと呼ばれ、開発者全員で共有すべきブランチなんだ。feature、hotfix、rereaseはサポートブランチと呼ばれ、開発者がローカルで管理するブランチだ。git-flowではこれらのブランチを機能追加、バグフィクス、リリースのタイミングで使い分けるんだよ。もっと詳しく知りたかくなったら、ここを見ておくといいよ。
http://nvie.com/posts/a-successful-git-branching-model/

(・∠・`)乙「なるほど。各ブランチの役割がわかったわ。開発者はmaster以外にもdevelopも触っちゃダメなのね。従来のtopicブランチがその他のブランチに位置づけられるわけね。」
( ゚⊇゚)「That's right アリス。それだけでなくブランチの作成方法やマージ方法もgit flowコマンドで管理するのさ。各ブランチの役割と作成方法を以下にまとめといたから見といてくれ。各ブランチがどこから分岐して、どこにマージされるかを知っておくことが重要だよ。」

masterブランチ

リリースの状態を常に維持しているブランチ。このブランチを勝手に弄ってはだめ。

developブランチ

開発者用のブランチ。最新の開発結果を常に保持する。破棄しちゃだめ。開発者はこのブランチからローカルブランチを切って作業を行う。直接いじっちゃだめ。

作成コマンド
git flow initコマンドを実行すると作成される。

$ git flow init
featureブランチ

新しい機能を追加する時に使われるブランチ。developから分岐し、developにマージされる。マージしたタイミングで破棄される。

作成コマンド

$ git flow feature start xxx

マージ

$ git flow feature finish xxx
hotfixブランチ

不具合修正を行うのに使われるブランチ。masterから分岐し、develop、masterにマージされる。

作成コマンド

$ git flow hotfix start xxx

マージ

$ git flow hotfix finish xxx
releaseブランチ

リリースの準備を行うのに使われるブランチ。developから分岐し、masterとdevelopにマージされる。

作成コマンド

$ git flow release start xxx
$ git flow release finish xxx

機能追加が終わったら

(・∠・`)乙「作業完了。えーとコミットまでの作業は通常通りだったわね。」

$ git add --all
$ git commit -m"add hello"

(・∠・`)乙「ボブ。機能追加が終わったんだけど、この後はどうすればいいのかしら?」
( ゚⊇゚)「OKアリス。まずはfeatureブランチをマージしよう。一応現在のブランチを確認してからにしてくれ。」

現在のブランチを確認

$ git flow feature
* hello

マージ

$ git flow feature finish hello
Switched to branch 'develop'
Updating e86c07d..5ccc6e6
Fast-forward
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 helloworld.py
Deleted branch feature/hello (was 5ccc6e6).

Summary of actions:
- The feature branch 'feature/hello' was merged into 'develop'
- Feature branch 'feature/hello' has been removed
- You are now on branch 'develop'

(・∠・`)乙「ボブ。マージできたわ。この後はブランチを削除すればいいのかしら?」
( ゚⊇゚)「Noアリス。git-flowでマージしたブランチは自動的に削除されるのさ。メッセージにも出てるだろ。」

$ git branch
* develop
  master

(・∠・`)乙「本当だ。削除されてるわ。これならブランチの削除忘れも未然に防げて便利ね。私よく削除忘れるのよ(・ω<)」

リリースする

( ゚⊇゚)「よしアリス、マージが終わったら今度はreleaseブランチの作成だ」

$ git flow release start 1.0.0
Switched to a new branch 'release/1.0.0'

Summary of actions:
- A new branch 'release/1.0.0' was created, based on 'develop'
- You are now on branch 'release/1.0.0'

Follow-up actions:
- Bump the version number now!
- Start committing last-minute fixes in preparing your release
- When done, run:

     git flow release finish '1.0.0'

$ git branch
  develop
  master
* release/1.0.0

( ゚⊇゚)「ブランチができたら、リリースノートを追加しよう。」

$ emacs README.md

HISTORY
=======

- 1.0.0: Echo "hello world"

( ゚⊇゚)「コミットしたらfinishだ。」

$ git add README.md
$ git commit -m "Update README for release 1.0.0."
$ git flow release finish 1.0.0
Switched to branch 'master'
Merge made by recursive.
 README.md     |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)
 create mode 100644 README.md
 create mode 100644 helloworld.py
Switched to branch 'develop'
Merge made by recursive.
 README.md |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)
 create mode 100644 README.md
Deleted branch release/1.0.0 (was 1819ae8).

Summary of actions:
- Latest objects have been fetched from 'origin'
- Release branch has been merged into 'master'
- The release was tagged '1.0.0'
- Release branch has been back-merged into 'develop'
- Release branch 'release/1.0.0' has been deleted

( ゚⊇゚)「エディタが起動したら1.0.0などを入力して閉じよう。」
(・ω・`)乙「これもdevelopにマージされるのね。この後はmasterにマージするのかしら?」
( ゚⊇゚)「その必要はないよアリス。rerease finishではmasterブランチのマージも勝手にやってくれるのさ。それだけでなくタグも打ってくれるのさ。メッセージにもでてるだろ。」

Summary of actions:
- Latest objects have been fetched from 'origin'
- Release branch has been merged into 'master'
- The release was tagged '1.0.0'

$ git tag
1.0.0

(・ω・`)乙「Greate!! なんて素敵なの。マージ、リムーブ、タグ打ちまでやってくれるなんて!」
( ゚⊇゚)「その通り。コマンド一発で複数の作業をやってくれて、さらに人為的ミスも防げるクールなツールがgit-flowだよ。さすがにリモートのpushまではしてくれないけどね。」

$ git push origin 1.0.0

( ゚⊇゚)「ところでアリス。付け鼻はやめたのかい?そっちの方が似合ってるね。」
(・ω・`)乙「べ、べつにあんたのためにやったんじゃないんだからね(///)!変換してから治すのがめんどくさいだけなんだからね!」
( ゚⊇゚)「( ´_ゝ`)フーン」

機能を追加する(まとめ)

( ゚⊇゚)「ヘイ!アリス。ボスがhelpページ追加してくれだって。機能追加の手順は覚えただろ。今度は一人でやってみな。」
(・ω・`)乙「OKボブ。まかせてちょうだい☆(ゝω・)vキャピ」

$ git flow feature start 1.1.0-help
...ゴニョゴニョ
$ git commit -m"add help"
$ git flow feature finish 1.1.0-help
$ git flow release start 1.1.0-help
...ゴニョゴニョ
$ git flow release finish 1.1.0-help
$ git tag
1.0.0
1.1.0-help
$ git push origin 1.1.0-help

(・ω・`)乙「ボブ。できたわよ。」
( ゚⊇゚)「乙」

git flow hotfix

( ゚⊇゚)「Hey!アリス。ボスがヘルプページがクレイジーすぎるから直してくれって言ってたぜ」
(・ω・`)乙「なんだってー!!どこが変なのかしら?」
( ゚⊇゚)「(-_-;ウーンさすがにMSDNに飛ばすのはないんじゃないかな。。。」
(・ω・`)乙「そう言われてみるとそうね。何かいい案ないかしら?」
( ゚⊇゚)「ここはやっぱりgoogle先生がクールだと思うよ。」
(・ω・`)乙「それだ!」
( ゚⊇゚)「よし!じゃ、不具合修正だ。git-flowでは不具合修正のときはhotfixブランチを使うんだよ。」

$ git flow hotfix start 1.1.1-helpfix
Branches 'master' and 'origin/master' have diverged.
And local branch 'master' is ahead of 'origin/master'.
Switched to a new branch 'hotfix/1.1.1-helpfix'

Summary of actions:
- A new branch 'hotfix/1.1.1-helpfix' was created, based on 'master'
- You are now on branch 'hotfix/1.1.1-helpfix'

Follow-up actions:
- Bump the version number now!
- Start committing your hot fixes
- When done, run:

     git flow hotfix finish '1.1.1-helpfix'

$ git branch
  develop
* hotfix/1.1.1-helpfix
  master

( ゚⊇゚)「修正して、finishだ」

...ゴニョゴニョ
$ git flow hotfix finish 1.1.1-helpfix
Branches 'master' and 'origin/master' have diverged.
And local branch 'master' is ahead of 'origin/master'.
Switched to branch 'master'
Merge made by recursive.
 help.py |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
Switched to branch 'develop'
Merge made by recursive.
 help.py |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
Deleted branch hotfix/1.1.1-helpfix (was 4666118).

Summary of actions:
- Latest objects have been fetched from 'origin'
- Hotfix branch has been merged into 'master'
- The hotfix was tagged '1.1.1-helpfix'
- Hotfix branch has been back-merged into 'develop'
- Hotfix branch 'hotfix/1.1.1-helpfix' has been deleted

$ git tag
1.0.0
1.1.0-help
1.1.1-helpfix

(・ω・`)乙「hotfixもmasterにマージされるのね。」
( ゚⊇゚)「yes! hotfixはmasterから分岐されてmasterとdevelopにマージされるんだ。リリースブランチを作成する必要がないから直後にリリースというパターンになるから慎重にね。」

コマンドまとめ

$ git flow hotfix start 1.1.1-helpfix
$ git branch
  develop
* hotfix/1.1.1-helpfix
  master
$ git flow hotfix finish 1.1.1-helpfix
$ git tag
1.0.0
1.1.0-help
1.1.1-helpfix

作業ブランチを違うマシンでやりたいそうです

(・ω・`)乙「ねぇボブ。作業の続きを持ち帰ってやりたいんだけど、この場合はどうやるのかしら?」
( ゚⊇゚)「OKアリス。その場合はgit flow feature publishコマンドを使うんだ。そして、自宅PCではgit flow feature pullコマンドでpullするんだよ。」

会社PC

$ git flow feature publish xxx

自宅PC

$ git flow feature pull xxx

(・ω・`)乙「なるほど。feature ごにょごにょコマンドが用意されてるのね。これならPCが変わってもfinishで怒られないのね」
( ゚⊇゚)「たぶんね。怒られてもこまかいことは気にすんんな。(o^-')b グッ!」
(・ω・`)乙「・・・」
( ゚⊇゚)「・・・」

featureいじってる時にhotfixしたくなったら

(・ω・`)乙「ボブ。featureをいじってる最中なんだけど、hotfixをいじりたくなったんだけどどうすればいいのかしら?」
( ゚⊇゚)「ぐっと我慢・・(のほうがいい)」
(・ω・`)乙「・・・」
( ゚⊇゚)「・・・」

( ゚⊇゚)(・ω・`)乙

ー病院ー
(・ω・`)乙「ガチャ(ドアあける)」
( ゚⊇゚)@ベッド「クソッタレ!捨て犬の気分さ」
(・ω・`)乙「どうしたんだいボビィ?随分荒れてるじゃないか。そのケガはハニーにやられたのかい?」
( ゚⊇゚)「ぜひそうありたいもんだよ。だけど残念なことにボス公の奴さ」
(・ω・`)乙「そういえばボスがすごい形相で出て行ったわよ。何かあったの?」
( ゚⊇゚)「ボス公のフェラーリで限界に挑戦したんだ。そしたら真っ赤なフェラーリが真っ黒になっちまったよ・・・。」
(・ω・`)乙「無茶しやがって・・・(`・ω・´)ゞ。(・・・だから焦げてるのね)」
( ゚⊇゚)「そしたら、お前はクビだって。・・・(´;ω;`)ブワッ」
(・ω・`)乙「かわいそうなボブ。そのくらいでクビになるなんて・・・(´;ω;`)ブワッ」
( ゚⊇゚)「僕はプロジェクトから抜けることになったけど、きっと君ならやっていけるよね(´;ω;`)ブワッ」
(・ω・`)乙「厳しいスケジュールになるけど心配しないで。git-flowなら極めたわ。(`・ω・´)キリッ」
( ゚⊇゚)「安心したよ。僕のスケジュールは真っ白だけどね・・・(´;ω;`)ブワッ」

ー翌日ー

(・ω・`)乙「今日の作業おわり。コミットコミット」

$ svn commit -m"daily commit ☆(ゝω・)vキャピ"
すぺしゃるさんくす

@Surgo
@六畳的一間

Libraryプロジェクトのテスト

Libraryテストでハマったので覚書
通常のLibraryプロジェクトからテストプロジェクトを作成して実行するとエラーが発生する

Could not find XXX.apk!

テストプロジェクトではapkファイルが作成されないので見つかんないってエラーが起きる
調べるとdeveloperサイトにはライブラリのテスト方法が書かれていた
http://developer.android.com/tools/projects/index.html#testing

Testing a Library Project
There are two recommended ways of setting up testing on code and resources in a library project:

You can set up a test project that instruments an application project that depends on the library project. You can then add tests to the project for library-specific features.
You can set up a standard application project that depends on the library and put the instrumentation in that project. This lets you create a self-contained project that contains both the tests/instrumentations and the code to test.

要約すると方法は2つあるんでどっちか選んで
# ライブラリ使ってるアプリケーションのテストプロジェクトを作成するとOK
# 普通のプロジェクト作成してtestケースとinstrumentations入れといて

前者はアプリのテストで一緒にライブラリもテストしてくれってことらしいが、そんなのライブラリプロジェクトの意味がいない

      r‐z´   /         `ヽL_ 
       |/|/ / /|  |   ト、 \ \ヽト \ 
      V/|/| /‐|<|_,l  |_>‐ヽ| ト、|| ト、| 
      イ|イ |/y'´(.j`´|\|´ヒ)`'v|ノN`| |  あんた バカァ? 
      || | |∧      ・      /k)  | | 
      || | |ヽヘ、  「  ̄`|  イ-'|  | |  別アプリでライブラリテストなんてなんて信じられない 
      || | |:|:|:|:l\. |_  ノ.///:::|  | | 
       |{< ̄ ̄\´\ ̄ 7/ ̄〉´ ̄\l.|  どう考えても底辺プログラマの発想だわ
      ノ/ー(⌒ヽ:.:.:\ \/ .イ:.:.:.:.://、| 
      //  ヽ::::ハ:.:.:.:.:| >Xく |:.:.:.:.|/ \ 
     /〈  / ̄}::::::\:.:.ト、/∧ .>|:.:.:.:.}∠   \ 
     { :}/´l  .::|/::::: ̄ ̄`)ハ〉|:.:.:./:::::<   > 
     |Kl  |..:::::ヘ / ̄| ̄/  ./:.:./\::::::::..../\

なので後者の手法でやってみるが、これが色々と問題がありすぎて困る
devサイトももう少しドキュメントを詳しくしたほうがいいだろ

ライブラリプロジェクトのテストプロジェクトの作成方法

手順
  1. 普通にライブラリプロジェクトを作成する
  2. テストプロジェクトを普通のアプリケーションプロジェクトとして作成する
    1. パッケージはライブラリと同一にする
  3. テストプロジェクトにライブラリを追加
  4. Manifestにinstrumentationとuses-library追加
  5. TestCase作成
普通にライブラリプロジェクトを作成する

MyLibというライブラリを作成して、Utilクラスを作成

package com.example.lib;

public class Util {
	public static String echo(String message){
		return message;
	}
}
テストプロジェクトを普通のアプリケーションプロジェクトとして作成する

テストプロジェクトを標準のアプリケーションプロジェクトとして作成

パッケージ名はライブラリと同一にする
[ライブラリのパッケージ].testとしたくなるが、別名にするとはまるので注意

テストプロジェクトにライブラリを追加


Manifestにinstrumentationとuses-library追加

android:targetPackageの値はライブラリプロジェクトのパッケージ=テストプロジェクトのパッケージとなる

TestCase作成

普通にテストケースを作成する

package com.example.lib;

import junit.framework.TestCase;

public class UtilTest extends TestCase {

	public void testEcho() {
		String send = "Hello";
		String res = Util.echo(send);
		assertEquals(res, send);
	}
}
実行する

SDカードパスまとめ

Androidの会MLより抜き出し

型番/パス

  • F-05D /mnt/sdcard/external_sd/
  • IS12S /mnt/ext_card/
  • ISW11M /mnt/sdcard-ext/
  • N-04D /mnt/sdcard/external_sd/
  • T-01D /mnt/sdcard/external_sd/
  • SC-02C /mnt/sdcard/external_sd/
  • SO-03D /mnt/sdcard/external_sd/
  • ISW11F /mnt/sdcard/external_sd/
  • F-08D /mnt/sdcard/external_sd/
  • SC-02B /mnt/sdcard/external_sd/
  • ISW11SC /mnt/sdcard/external_sd/
  • SC-03D /mnt/sdcard/external_sd/

端末名

Xperia acro HDはAUDocomoでパスが違う

  • IS12S /mnt/ext_card/
  • SO-03D /mnt/sdcard/external_sd/

VirtualBoxでICS的

手順

  1. VirtualBox用のICSイメージを取得する
  2. 起動確認できたら終了
  3. VM設定画面でネットワークアダプタを「ブリッジアダプタ」に変更
  4. 起動する
  5. VMIPアドレス確認
  6. ADBHOSTの設定
  7. バイスが見れるのを確認

VirtualBox用のICSイメージを取得する

このサイトでVirtualBoxのイメージを取得する
http://www.borncity.com/blog/2011/11/28/testing-android-x86-ice-cream-sandwich-image-from-vmlite/

少し下の「for free download.」リンクからDL
ファイル名:Android-v4.7z


ICS VirtualBoxを起動

DLしたファイルを解凍して「Android-v4.vbox」をダブルクリックで起動

起動確認できたら終了する
VM一覧にいるのを確認

ネットワーク設定の変更

VM設定画面でネットワークアダプタを「ブリッジアダプタ」に変更
起動する

IPアドレスの確認

開発機とVMを接続するため、VMのIPを確認する。

以下のコードを適当なサーバに上げて、VMでDLしてインストールして実行
書くのメンドクサイやつはこっからもってけ
http://bit.ly/wtolVw

package com.hidecheck.ipaddress;

import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class IPAddressSampleActivity extends Activity {
	
	public static final String BR = System.getProperty("line.separator");
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        TextView tv = (TextView)findViewById(R.id.text_ipaddress);
        
        StringBuilder sb = new StringBuilder();
        try {
			sb.append(getIpAddress());
		} catch (IOException e) {
			e.printStackTrace();
		}
        tv.setText(sb.toString());
    }
    
    private String getIpAddress() throws IOException{
    	
    	StringBuilder sb = new StringBuilder();
    	
        Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
            
        while(interfaces.hasMoreElements()){
            NetworkInterface network = interfaces.nextElement();
            Enumeration<InetAddress> addresses = network.getInetAddresses();
                
            while(addresses.hasMoreElements()){
                String address = addresses.nextElement().getHostAddress();
                    
                //127.0.0.1と0.0.0.0以外のアドレスが見つかったらそれを返す
                if(!"127.0.0.1".equals(address) && !"0.0.0.0".equals(address)){
                    sb.append(address);
                    sb.append(BR);
                }
            }
        }
            
        return sb.toString();
    }
}


ADBHOSTの設定

adbhostを設定してadb-serverの再起動
バイスが見れたらOK
ついでにEclipseから見れることも確認してみよう

export ADBHOST=[ip address]
$ adb kill-server
$ adb devices
* daemon not running. starting it now on port 5037 *
* daemon started successfully *
List of devices attached 
emulator-5554	device
2/25 wPhone勉強会もよろしくね

AndroidだらけのwPhone(ウーフォン)勉強会
お題「x86エミュレータをビルドする」