2011年4月3日日曜日

Android のスレッドの使い方を調べる

わからないなりに、スレッドの使い方を調べてみました。

スタート地点

まずは Android Developers のサイトから。 それっぽいトピックがあるので、ここから始めてみます。

Processes and Threads | Android Developers

簡単な例も載っています。 ここ からそのまま引用です。

public void onClick(View v) {
    new Thread(new Runnable() {
        public void run() {
            Bitmap b = loadImageFromNetwork("http://example.com/image.png");
            mImageView.setImageBitmap(b);
        }
    }).start();
}

処理を新しく作ったスレッドで実行する例のようです。

このやり方だと、できる事は限られますね。

もう少し柔軟なやり方

さらに読んでいくとこんな記述がありました。

To handle more complex interactions with a worker thread, you might consider using a Handler in your worker thread, to process messages delivered from the UI thread.

複雑なやりとりが必要な場合は Handler というものを使えばよさそうです。

さらりと見てみた限り

  • スレッドを生成
  • 新しく作ったスレッド上で Handler を生成
  • Handler に対して sendMessage() を行う
  • handleMessage() が新しいスレッド上で実行される!

という感じになりそうです。

コードを書いてみる

さっそくコードを書いてみます。 まずは ThreadTest というクラスを作って、 コンストラクタ内でスレッドと Handler を生成します。

public class ThreadTest {
    private Thread mThread;
    private Handler mHandler;
    public ThreadTest() {
        Log.d("TEST", "+ ThreadTest() " + Thread.currentThread().toString());
        // スレッド生成
        mThread = new Thread(new Runnable() {
                public void run() {
                    Log.d("TEST", "+ run() " + Thread.currentThread().toString());
                    // Handler 生成
                    mHandler = new MyHandler();
                    Log.d("TEST", "- run() " + Thread.currentThread().toString());
                }
            });
        // スレッド開始
        mThread.start();
        Log.d("TEST", "- ThreadTest() " + Thread.currentThread().toString());
    }
}

次は Handler に対して Message を送るコードです。

Handler には Message を送るやり方と、 Runnable を送るやり方が用意されているようです。 今回は Message を送るやり方を試してみます。

public void doInMyThread() {
    Log.d("TEST", "+ DoInMyThread() " + Thread.currentThread().toString());
    // Bundle を生成して文字列をセット
    Bundle bundle = new Bundle();
    bundle.putString("mystring", "Hello!");
    // 空の Message (what=1) を取得 (new するより低コストらしい)
    Message msg = mHandler.obtainMessage(1);
    // Message に Bundle をセット
    msg.setData(bundle);
    // Message 送信
    mHandler.sendMessage(msg);
    Log.d("TEST", "- DoInMyThread() " + Thread.currentThread().toString());
}

次は Handler のコードです。

class MyHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        Log.d("TEST", "+ handleMessage() what=" + msg.what + " " + Thread.currentThread().toString());
        if (msg.what == 1) {
            Bundle bundle = msg.getData();
            Log.d("TEST", bundle.getString("mystring"));
        }
        Log.d("TEST", "- handleMessage() " + Thread.currentThread().toString());
    }
}

呼び出し側のコードです。

:
mThreadTest = new ThreadTest();
mThreadTest.doInMyThread();
:

メッセージループが必要

さっそく実行すると、 Handler 生成のところでいきなりコケます。

例外の内容を見てみると、新しく作ったスレッドに、メッセージ処理のためのメッセージループが用意されていない事が原因のようです。 メッセージループを準備するには Looper を使えばよさそうです。

mThread = new Thread(new Runnable() {
        public void run() {
            Log.d("TEST", "+ run() " + Thread.currentThread().toString());
            // メッセージループの準備
            Looper.prepare();
            // Handler 生成
            mHandler = new MyHandler();
            Log.d("TEST", "new mHandler" + mHandler.toString());
            // メッセージループ開始
            Looper.loop();
            Log.d("TEST", "- run() " + Thread.currentThread().toString());
        }
    });

まだうまくいかない

これでうまく行くはずなんですが、またコケます。

obtainMessage() のところで、 NullPointerException です。 新しく作ったスレッド上で Handler を生成する前(mHandler == null の状態)にここに到達しているようです。

呼び出し側のスレッドをセマフォを使って待たせる必要がありそうです。

Semaphore が使えそうです。

public ThreadTest() {
    Log.d("TEST", "+ ThreadTest() " + Thread.currentThread().toString());
    // セマフォ生成
    mSemaphore = new Semaphore(0);
    // スレッド生成
    mThread = new Thread(new Runnable() {
            public void run() {
                Log.d("TEST", "+ run() " + Thread.currentThread().toString());
                // メッセージループの準備
                Looper.prepare();
                // Handler 生成
                mHandler = new MyHandler();
                // 待ちを解除
                mSemaphore.release();
                // メッセージループ開始
                Looper.loop();
                Log.d("TEST", "- run() " + Thread.currentThread().toString());
            }
        });
    // スレッド開始
    mThread.start();
    // 新しいスレッドの準備が整うまで待つ
    mSemaphore.acquire();
    Log.d("TEST", "- ThreadTest() " + Thread.currentThread().toString());
}

ようやく動いた

ようやく動きました。

D/TEST    (19983): + ThreadTest() Thread[main,5,main]
D/TEST    (19983): + run() Thread[Thread-10,5,main]
D/TEST    (19983): - ThreadTest() Thread[main,5,main]
D/TEST    (19983): + DoInMyThread() Thread[main,5,main]
D/TEST    (19983): - DoInMyThread() Thread[main,5,main]
D/TEST    (19983): + handleMessage() what=1 Thread[Thread-10,5,main]
D/TEST    (19983): Hello!
D/TEST    (19983): - handleMessage() Thread[Thread-10,5,main]

ログを見ると、 handleMessage() が新しく作ったスレッド(Thread[Thread-10,5,main])で動いている事がわかります。

わかった事

  • Handler を介して、スレッド間でメッセージのやりとりができる
  • Handler を使うにはスレッドにメッセージループが必要 (Looper を使う)
  • 同期が必要な場合は Semaphore が使える

もう少し簡単なやり方はありそうですね。あと、メッセージループから抜けていないようなんですが。 これはリソースリークになってそう…。その内調べたいと思います。

2011年3月21日月曜日

Amazon S3 を Android から使ってみる

AWS SDK for Android を試してみました。

下記を参考にしました。

AWS SDK for Android の入手

このページ(AWS SDK for Android (Beta)) から aws-android-sdk-0.1.0.zip をダウンロードします。

ワークスペースに展開します。

$ 7z x aws-android-sdk-0.1.0.zip

必要な前準備

  • いつものようにプロジェクトを新規作成します。(File => New => Android Project)
  • ライブラリに aws-android-sdk-0.1.0-obfuscated.jar を追加します。(Properties => Java Build Path => Libraries => Add External JARs…) SDK を展開した場所の lib の下にあります。
  • インターネット通信を行うので、 AndroidManifest.xms の uses-resources に INTERNET を追加しておきます。

クライアントの生成

さっそく API を呼んでいきます。まずは S3 クライントを生成します。

// AccessKey と Secret Key を設定
AWSCredentials credentials = new BasicAWSCredentials("accesskey", "secretkey");
// S3 クライアントを生成
AmazonS3 s3 = new AmazonS3Client(credentials);

自分の AccessKey は アカウントのページ から確認できます。

Bucket の作成

S3 のオブジェクトはすべて Bucket に格納されます。まずはその Bucket を作ります。

// Bucket 生成
Bucket backet = s3.createBucket("takutless.testbucket");

Bucket 名に "_" を含んでいると例外が発生するので注意。(?) また S3 全体でユニークでないといけないようです。

Bucket名の決まりは クイックスタートガイド に下記のように記載されています。

Bucket names must comply with the following requirements. Bucket names:

  • Can contain lowercase letters, numbers, periods (.), underscores (_), and dashes (-)
  • Must start with a number or letter
  • Must be between 3 and 255 characters long
  • Must not be formatted as an IP address (e.g., 265.255.5.4)

オブジェクトの作成

作成した Bucket にオブジェクトを作成します。

// オブジェクトを作成
s3.putObject("takutless.testbucket", "mydir/myfile1.txt", inputStream, null);

Bucket "takutless.testbucket" に "mydir/myfile1.txt" という名前で inputStream の内容が保存されます。一緒に MetaData も指定できますが、省略(null)しました。

Management Console で確認すると Bucket が作成されて、ディレクトリ(mydir)とファイル(myfile1.txt)ができています。

オブジェクトのリスト取得

Bucket に格納されているオブジェクトのリストを取得してみます。

// Bucket に格納されているオブジェクトのリストを取得
ObjectListing objectListing = s3.listObjects("takutless.testbucket");
List<S3ObjectSummary> summaryList = objectListing.getObjectSummaries();

S3ObjectSummary にはオブジェクト名などの情報が格納されています。

ObjectListing objectListing = s3.listObjects("takutless.testbucket", "mydir/");

とすると、オブジェクト名が "mydir/" から始まるもののみ取得できます。

のはずなんですが、 listObjects() を実行すると例外が発生してしまいます。

Unable to unmarshall response (Couldn't initialize a sax driver for the XMLReader)

google 先生におうかがいを立ててみると こんな解決策 が…。理由はよくわかりませんが、下記のコードを追加してこの場をしのぎます。

System.setProperty("org.xml.sax.driver", "org.xmlpull.v1.sax2.Driver");

オブジェクトの取得

オブジェクトの中身は下記にようにして取得できます。

// オブジェクトを取得
S3Object object = s3.getObject("takutless.testbucket", "mydir/myfile.txt");
// オブジェクトの中身を取得
InputStream content = object.getObjectContent();

content から read() してファイルに保存するなりできます。

今回は最も手抜きなやり方を紹介しましたが、 S3 には Bucket のアクセス件や、オブジェクトのメタデータなども細かく管理でき、 API も色々用意されています。これだけ簡単だと、もっと使ってみたくなりますね!

2011年3月12日土曜日

Facebook Android SDK を使ってみる

Facebook Android SDK とは

Android アプリから Facebook の機能(認証、Graph API、プラットフォームダイアログなど)を使うためのライブラリです。

Facebook DevelopersMobile Apps のところに説明があります。ここの情報に従って進めていきます。

Facebook Android SDK の入手

Facebook Android SDK は github で公開されています。

git でソースをダウンロードします。

$ git clone git://github.com/facebook/facebook-android-sdk.git

facebook-android-sdk というディレクトリができます。 ちなみに git を使わなくても、 github のページからダウンロード可能です。

eclipse にプロジェクトを追加

eclipse で、先ほど入手したライブラリからにプロジェクトを作ります。

  • [File] => [New] => [Android Project]
  • [Create project from existing source] にチェック
  • パスは先程入手した facebook-android-sdk の下の facebook

これで eclipse から Facebook Android SDK が使用可能になりました。

Facebook Android SDK を使ったアプリの作成

早速、 Facebook Android SDK を使ったアプリを作ってみます。

まずは新規のプロジェクトを作成します。

使用するライブラリに Facebook Android SDK を加えます。

  • プロジェクトの [Properties] を開き、左のリストから [Android] を選びます。
  • Library の [Add] ボタンを押して、 最初に作成した Facebook Android SDK のプロジェクトを指定する。

Facebook を使うからには通信を行うので、 uses-permission に INTERNET を追加します。

  • AndroidManifest.xml を開く
  • [Permissions] タブをクリック
  • [Add] ボタンをクリック
  • [Uses Permission] 選択して OK をクリック
  • 右側の [Name] ドロップダウンから [INTERNET] を選択

これで Facebook Android SDK を使ったアプリの原型ができました。

Facebook 側での準備

Facebook 側にも準備が必要です。

  • Developer App を開き、 [Set Up New App] ボタンをクリック
  • 好きなアプリケーション名を入力して、 [Create App] をクリック

名前に Facebook とかが入ってるとダメみたいなので注意

  • 左側のリストから [Mobile and Devices] をクリックし、 Key Hash を入力します。

Eclipse ではビルドするとデフォルトでデバッグ用のキーで署名されるので、ここではデバッグ用のキーから Key Hash を作ります。

keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64

パスワードは android です。

これで準備が整いました。

コードを追加する

ではコードを追加してみます。

Facebook Developer のサンプルコードを少し変更してビルドします。

 1:  package com.myfirstfacebookapp;
 2:  
 3:  import android.app.Activity;
 4:  import android.content.Intent;
 5:  import android.os.Bundle;
 6:  
 7:  import com.facebook.android.DialogError;
 8:  import com.facebook.android.Facebook;
 9:  import com.facebook.android.Facebook.DialogListener;
10:  import com.facebook.android.FacebookError;
11:  
12:  public class MyFirstFacebookApp extends Activity {
13:      // 引数は Facebook から取得した App ID
14:      Facebook facebook = new Facebook("135741723160602");
15:  
16:      /** Called when the activity is first created. */
17:      @Override
18:      public void onCreate(Bundle savedInstanceState) {
19:          super.onCreate(savedInstanceState);
20:          setContentView(R.layout.main);
21:  
22:          facebook.authorize(this, new DialogListener() {
23:              @Override
24:              public void onComplete(Bundle values) {}
25:  
26:              @Override
27:              public void onFacebookError(FacebookError error) {}
28:  
29:              @Override
30:              public void onError(DialogError e) {}
31:  
32:              @Override
33:              public void onCancel() {}
34:          });
35:      }
36:  
37:      @Override
38:      protected void onActivityResult(int requestCode, int resultCode, Intent data) {
39:          super.onActivityResult(requestCode, resultCode, data);
40:  
41:          facebook.authorizeCallback(requestCode, resultCode, data);
42:      }

14 行の App ID は Developer App から確認できます。

起動したら認証を行うだけのアプリですね。

実行してみる

では実機で試してみます。

起動すると、ログイン画面が現われました。

アプリにアクセスを許可するか聞かれます。

まだ認証しかしていませんが、まずは意図通り動いているようです。 次は Graph API を使ってみたいと思います。

追記

Facebook Android SDK の認証機能は Facebook for Android (Facebook 公式の Android アプリ) の機能を使っているようです。 このアプリがサインオン状態を覚えておく事で Android でのシングルサインオンを実現しているのでしょうか。 なので、アプリを入れていないと挙動が変わります。

  • 画面が違う
  • 毎回ログインを求められる

2011年3月6日日曜日

MobileOrg for Android を使ってみる

はじめに

私は自宅では emacs の org-mode を使って個人的な Todo などを管理しています。

外に持ち出す時は、整形したテキストをメールで携帯(android)に送るという めんどくさい事をしていたのですが、最近 MobileOrg という Android アプリを見付けました。

試してみたので紹介します。

MobileOrg for Android

この MobileOrg なんですが、 org ファイルを見易く表示してくれるだけでなく、 TODO の状態を変更(TODO=>DONE など)したり、ちょっとしたメモを取ったりできます。

さらにすごい事に、最近の org-mode には、 MobileOrg と連携する機能が あり、 MobileOrg 側での変更を取り込む事ができます。

MobileOrg は マーケット から入手できます。

Dropbox を使って PC <=> Android 連携

MobileOrg は PC の org-mode と連携するために、 WebDAV と Dropbox (オンラインストレージサービス) をサポートしています。 私は手軽そうな Dropbox を使いました。

Dropbox の Android 用クライントは マーケット から入手できます。 PC用のクライアントは各種ありますが、私は ここ に書かれているもの(Linux 用)を使いました。簡単そうなので。なんでもいいと思います。

これで PC に DropBox フォルダができるので、その下に mobileorg フォルダを作りました。(これだけで Dropbox にも反映されます。不思議。)

org-mode

MobileOrg を正しく使うには、 MobileOrg をサポートしたバージョンの org-mode が必要なようです。 emacs 23.2.1 に付属のものは古かったので、最新版をゲットしました。

私の org-mode 設定は下記のとおりです。

;; org-mode
(setq load-path (cons "/usr/local/share/emacs/site-lisp/org" load-path))
(require 'org-install)
(setq org-use-fast-todo-selection t)
(global-set-key "\C-cl" 'org-store-link)
(global-set-key "\C-ca" 'org-agenda)
(global-set-key "\C-cb" 'org-iswitchb)

(setq org-directory "~/org")                            ; orgディレクトリ
(setq org-agenda-files `("~/org/main.org"))             ; orgファイル
(setq org-mobile-directory "~/Dropbox/mobileorg")       ; MobileOrg用ディレクトリ

(setq org-todo-keywords '((type "TODO(t)" "STARTED(s)" "WAITING(w)" "APPT(a)" "|" "DONE(d)" "CANCELLED(c)" "DEFERRED(f)")))
(setq org-tag-alist '(("ANY" . ?a) ("HOME" . ?h) ("WORK" . ?w) ("OUTGO" . ?o)))

さっそく org ファイルを

実験用に簡単な org ファイルを作ってみました。

# -*- org -*-
#+STARTUP: overview hidestars

* ToDo
** APPT 「江~姫たちの戦国~」見る
   SCHEDULED: <2011-03-06 日 20:00>
* Projects
** MobileOrg紹介記事を書く
   DEADLINE: <2011-03-06 日>
*** TODO DropBox アカウント入手
*** TODO 最新版 org-mode をゲット
*** TODO MobileOrg 設定
*** TODO MobileOrg 紹介記事をブログにアップする
* Reminder
** ホワイトデー
   SCHEDULED: <2011-03-14 月>

MobileOrg へ push

下記のコマンドで ~/Dropbox/mobileorg に MobileOrg 用の org ファイルが作られます。

M-x org-mobile-push

MobileOrg を設定

  1. Synchronization Mode を Dropbox に設定

    [Settings] => [Synchronization Mode] => [Dropbox]

  2. Dropbox にログイン

    [Settings] => [Configure Synchronizer Settings…] => [Login]

  3. org ファイルのパスを指定

    [Settings] => [Configure Synchronizer Settings…] => [Path] => [/mobileorg/index.org]

    index.org は org-mode が生成

  4. Sync

表示できました!

MobileOrg 側での変更を反映

MobileOrg で TODO アイテムをタップすると状態を変更できます。 いくつか DONE に変更してみます。

このままでは Dropbox に反映されないので、 Sync を行います。

さらに、 emcas で、次のコマンドを実行します。

M-x org-mobile-pull

Dropbox から変更を取ってきて org-mode の方に反映してくれます。

org-mode の活用の幅が一気にひろがりそうです。

その他

最初 main.org に下記のような行を入れていたのですが、 MobileOrg 側の TODO 状態が重複してしまいました。

#+TODO: TODO(t) STARTED(s) WAITING(w) APPT(a) | DONE(d) CANCELLED(c) DEFERRED(f)

代わりに、 .emacs に下記を加える事で解決しました。

(setq org-todo-keywords '((type "TODO(t)" "STARTED(s)" "WAITING(w)" "APPT(a)" "|" "DONE(d)" "CANCELLED(c)" "DEFERRED(f)")))

もうひとつ、

MobileOrg で Sync を行うと、表示が前回 Sync したときの状態に戻ってしまいます。(変更が戻ってしまう) org-mode で pull => push してから再度 Sync すると整合が取れた状態になります。

org-mode で pull するまでは Sync は行わない方がいいですね。

2011年2月27日日曜日

Debian lenny に android 開発環境をインストールしたときのメモ

はじめに

自分のPCにAndroid開発環境を入れたときのメモです。 環境は下記のとおりです。

  • モデル: ASUS EeePC 901-16G
  • CPU: Intel Atom 1.5GHz
  • メモリ: 2GByte
  • ディスク: SSD 16GByte
  • OS: Debian GNU/Linux 5.0.8 (lenny)

サンプルをビルドして、私のGalaxy Sで動作させたいと思います。 Eclipseはここではインストールしません。

JDKとAndroid SDKのインストール

まずはSDKのインストール。 Android DevelopersのWEBページに行き、インストールについてのドキュメントを探す。

http://developer.android.com/index.html

SDKのインストール手順はここに書かれていた。

http://developer.android.com/sdk/installing.html

JDKが必要との事だが、私のPCにはJDKが入っていなかったので、ここで一緒インストールする。 リンクされているJDKのダウンロードページに飛ぶ。

http://www.oracle.com/technetwork/java/javase/downloads/index.html

ここでLinux用のJDKをダウンロード。 ダウンロードしてきたファイルを実行すれば、JDKが展開される。

takuya@takuya-netbook:~/android$ chmod +x jdk-6u23-linux-i586.bin
takuya@takuya-netbook:~/android$ ./jdk-6u23-linux-i586.bin
:
Press Enter to continue.....
Done.

takuya@takuya-netbook:~/android$ ls
jdk-6u23-linux-i586.bin  jdk1.6.0_23

開発環境に必要なファイルは~/android/以下にインストールし、~/android/bin/以下に実行ファイルへのリンクを作成する事にする。 環境変数を設定するスクリプトも用意しておく。

#!/bin/bash

# ~/.bashrc に下記を加えないとプロンプトが変更されない
# # CUSTOM_PS1
# if [ -n "$CUSTOM_PS1" ]; then
#     PS1="$CUSTOM_PS1"
# fi

export PATH="$HOME/android/bin:$PATH"
export JAVA_HOME="$HOME/android/jdk1.6.0_23"
export CUSTOM_PS1="\u[android]@\h:\w\$ "
/bin/bash -i

AndroidのSDKダウンロードページからLinux用のSDKをダウンロードする。

http://developer.android.com/sdk/index.html

ダウンロードしたファイルを展開し、SDK and AVD Managerを起動する。

takuya@takuya-netbook:~/android$ tar zxf android-sdk_r09-linux_x86.tgz
takuya@takuya-netbook:~/android$ cd android-sdk-linux_x86/tools/
takuya@takuya-netbook:~/android/android-sdk-linux_x86/tools$ ./android

「Available packages」から、必要なパッケージを選び、ダウンロード&インストールする。 自分のGalaxy Sは2.2なので、2.2用のパッケージを選んだ。

これでインストール完了。

エミュレータの起動

さきほどのSDK and AVD Managerで「Virtual Devices」→「New」を選ぶと、新しく作成するAVDの設定を聞いてくるので適当に入れて「Create ADV」を押す。しばらく待つと完了する。

作成したAVDが一覧に現れた。選択して、「Start」を押すとエミュレータが起動する。

ブラウザも動作する。

「Start」を押したときに出るダイアログで「Scale display to real size」をチェックすると、縮小表示もできる。

これでエミュレータが使えるようになった。

サンプルのビルド

ビルドにはantというツールが要るので、下記のページから取ってきてインストールした。 http://ant.apache.org/ http://ant.apache.org/bindownload.cgi

下記を参考に、サンプルのビルドを行った。

http://developer.android.com/guide/developing/other-ide.html#Building http://developer.android.com/resources/samples/get.html

サンプルは~/android/android-sdk-linux_x86/samples/android-8/ApiDemosを適当な場所にコピーしてからビルドした。

takuya[android]@takuya-netbook:~/task/android/samples$ android update project -s -n API_Demos -t 1 -p ApiDemos/
takuya[android]@takuya-netbook:~/task/android/samples/ApiDemos$ ant debug
Buildfile: /home/takuya/task/android/samples/ApiDemos/build.xml
    [setup] Android SDK Tools Revision 9
    [setup] Project Target: Android 2.2
:
:
:
BUILD SUCCESSFUL
Total time: 1 minute 31 seconds
takuya[android]@takuya-netbook:~/task/android/samples/ApiDemos$ 
takuya[android]@takuya-netbook:~/task/android/samples/ApiDemos$ ls bin/
API_Demos-debug-unaligned.apk  API_Demos-debug.apk  API_Demos.ap_  classes  classes.dex

API_Demos-debug.apkというファイルができた。

エミュレータでの実行

さきほどビルドしたサンプルをエミュレータへインストールする。エミュレータを立ち上げた状態でadb installを実行した。

takuya[android]@takuya-netbook:~/task/android/samples/ApiDemos$ adb install bin/API_Demos-debug.apk
242 KB/s (2459699 bytes in 9.910s)
        pkg: /data/local/tmp/API_Demos-debug.apk
Success

エミュレータのアプリ一覧に「API Demos」が追加された。

実機を接続する

所有しているGalaxy SをUSBで接続した。OSの種類やバージョンによって設定が異なるが、私の場合は、

/etc/udev/rules.d/51-android.rules

というファイルを作り、

SUBSYSTEMS=="usb", ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="681c", GROUP="takuya", SYMLINK+="android%n"

の一行を書き込む事で接続できるようになった。IdVendorとidProductはGalaxy S用である。adb devicesで接続されているか確認できる。

takuya[android]@takuya-netbook:~/android$ adb devices
List of devices attached
10004682a26c    device

実機にインストールする

実機へのインストールはadb -d installを実行すればよい。

takuya[android]@takuya-netbook:~/task/android/samples/ApiDemos$ adb -d install bin/API_Demos-debug.apk
947 KB/s (2459699 bytes in 2.536s)
        pkg: /data/local/tmp/API_Demos-debug.apk
Success