戌印-INUJIRUSHI- (Androidあれこれ)

Androidのプログラミングをメインにしてます。記事に貼られたソースコードはダブルクリックすることで行番号をはずしてコピーすることができます。

 
1
2
5
8
9
10
12
13
14
15
16
17
19
20
21
22
23
24
25
26
30
31
07

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

adb (Android Debug Bridge)

Android SDK のツールの一つである adb (Android Debug Bridge) を使って携帯端末を操作することが出来ます。

■ adb実行 --------------------------------------------------
コマンドプロンプトを起動し下記のコマンドを実行します。
※環境変数を設定していることが前提(開発環境構築③ Android編参照)
ほんの一部だけ紹介。

adb devices
 現在接続中の端末一覧を取得。
 デバイスが2つ接続しているとき(実機接続中にエミュレータ起動等)に使います。

adb shell
 シェルを起動。下のシェルコマンドに移ります。


■ シェルコマンド --------------------------------------------------
シェル起動時に実行。シェルコマンドはLinuxコマンド集参照。
自分が使う一部のコマンドだけ紹介。

monkey -p [パッケージ名] [実行回数]
 モンキーテストを実行。
 例)monkey -p jp.inujirushi.test 100

printenv
set
 環境変数を取得。
 これを使ってSDカードのパス(EXTERNAL_STORAGE)を知ることが出来ます。
スポンサーサイト

日本Androidの会に入会してみた

日本Androidの会
http://www.android-group.jp/


技術情報とか色々お世話になっているし、勉強会とか参加したいということで入会してみました。

とはいえ、勉強会に関しては実機持ってないから凄く行きづらいので行くかは不明です。
買えって話ですね。すみません。

掲示板で「GALAXY S等の外部SDカードのパスの取得」の記事が未解決(?)であったので
先日書いた記事の内容を返信しようか悩み中。

リアルタイムならともかく2ヶ月近く前の記事への返信って抵抗あるんだよなー。
単純に輪の中に入るのが苦手ってのもあるけど。

SDカードのパス取得:Environment と System.getenv

------------------------------------------------------------
(2012/11/27 追記)
この記事では外部ストレージのパスは取得しきれませんでした。
最新の『外部ストレージのパスを取得する(Android 2.2~?)』を参照してください。
------------------------------------------------------------

SDカードのパスは Android API を使って取得することが出来ます。

// Environmentクラスから取得
File file = Environment.getExternalStorageDirectory();
String sdcard = file.getPath();

// 文字列で指定するのはダメ絶対
// String sdcard = "/sdcard";

機種によってはパスが変わるので文字列で指定するのは辞めて下さい。

と、パスが変わるだけなら良かったのですが、実は機種によって取得する方法自体が違うという問題があります。

以降の記事は下記のサイトを参考、追記しています。
three hundred and seventy-five 「SDカードへのパスの取得方法 」
理ろぐ 「Galaxy SとGalaxy Tabのカメラ画像とかが保存される場所意識してますか?」

取得する方法が違うのは、内部SDカードと外部SDカードの2つを持っているサムスン製(GALAXY Tab他)等の一部の携帯です。
※今後これが主流になってくるかもしれませんが、パスがメーカー依存なのは勘弁してほしい…

Sumsung GALAXY Tab SC-01C
Sumsung GALAXY SⅡ SC-02C
Sumsung GALAXY Note SC-05D
・データフォルダ /data
・内部SDカード /mnt/sdcard
・外部SDカード /mnt/sdcard/external_sd

MOTOROLA Photon ISW11M
・データフォルダ /data
・内部SDカード /mnt/sdcard
・外部SDカード /mnt/sdcard-ext

HTC J ISW13HT
・データフォルダ /data
・内部SDカード /mnt/sdcard
・外部SDカード /mnt/sdcard/ext_sd

(追記:2012/11/27修正)
※GALAXY Tab SC-02D(Android 3.2) は内部と外部にわかれていませんでした。
SDカードのパスは /mnt/sdcard です

GALAXY Tab 7.0 Plus SC-02D
・データフォルダ /data
・内部SDカード /mnt/sdcard
・外部SDカード /mnt/sdcard/extStorages


これらの携帯は先に述べた方法だと内部SDカードのパスを取得してしまい、ユーザーが挿した(外部)SDカードのパスは取得できません

Android APIには取得する術がないので環境変数からパスを取得します。
環境変数を呼び出すには System#getenv(String name) を使用します。

// 環境変数から外部SDカードのパスを取得(旧)
String sdcard = System.getenv("EXTERNAL_STORAGE");
GALAXY Sではこれで外部SDカードのパスが取得できる、と色々なサイトでは書かれているのですが GALAXY Tabで実行したところEnvironment#getExternalStorageDirectory() と同じパスが返ってきてしまいました
Android 2.2 のソースコードを見ても内部で同じ事をしているので別のが変えるはずないのですが…。
(日本Androidの会の掲示板参照…自分も確認しました)
GALAXY Tabの仕様なのか、Androidのバージョンアップで変わったのかは分かりません。

で、色々調べたところ外部SDカード用の環境変数が追加されていました。
情報元は(ドメインがfrなのでたぶん)フランスの掲示板です。
書いた当初は日本語のサイトでは見つからなかったのでここを参考にしましたが、最近(2011/12/12)では日本語のサイトでも機種依存のSDカードパスの取得について書かれているところも出てきましたね。

Sumsung GALAXY Tab SC-01C(Android 2.3.3 バージョンアップ済)で確認
// 環境変数から外部SDカードのパスを取得(新)
String sdcard = System.getenv("EXTERNAL_STORAGE2");
ぱっと見、違いはわかりませんが EXTERNAL_STORAGE2 と 2 が追加されています。
MOTOROLA Photon ISW11M の場合は EXTERNAL_ALT_STORAGE でした。

環境変数が存在しなければ null を返却します。

それを利用して、この問題は下記のようなメソッドを作って対応できそうです。
パスの違う機種が出たらその都度追加する形で。
現在の機種がバージョンアップで変更されることもあるかもしれません…
/**
* 外部ストレージ(SDカード)のパスを取得する。
*
* @return 外部ストレージのパス
*/
public static String getExternalStoragePath() {
String path;

// MOTOROLA 対応
path = System.getenv("EXTERNAL_ALT_STORAGE");
if (path != null)
return path;

// Sumsung 対応
path = System.getenv("EXTERNAL_STORAGE2");
if (path != null)
return path;

// 旧 Sumsung + 標準 対応
path = System.getenv("EXTERNAL_STORAGE");
if (path == null)
path = Environment.getExternalStorageDirectory().getPath();

// HTC 対応
File file = new File(path + "/ext_sd");
if (file.exists())
path = file.getPath();

// その他機種
return path;
}

HTCの対応がなかったので Palesky 普通の日記。 - HTC J を参考に若干修正しました。
if で深くなるの好きじゃないのでところどころで return してます。

ちなみに、機種の環境変数を確認したいのであれば、携帯とPCをUSBケーブルで繋いでスタートメニューからコマンドプロンプトを立ち上げます。
コマンドプロンプトが起動したら adb shell と実行して、次に printenv と入力すれば携帯に設定されている環境変数が見れます。

アプリを作って確認したいのであれば『環境変数の一覧を取得してみる:System.getenv()』の記事を参考にするのも有りです。

もし別のパスが設定されている機種を見つけたらご報告いただけると嬉しいです。

アクティビティ、アプリの終了方法

アクティビティ、または、アプリを終了させるには複数の方法が存在します。

この記事を書くにあたり、てくめも様のSystem.exit() を使ってはいけない理由と、終了方法のまとめを参考にさせて頂きました。

①Activity#finish()
アクティビティをライフサイクルに沿って正しく終了させる唯一の方法
起動アクティビティの場合は、アプリを終了する(※)。
終了と書いてあるが、Android OSに対して終了通知を送るだけで、呼び出された直後に終了するわけではない
そのため、finish()以降に処理が記述されていれば記述された処理は実行されてしまう。
なお、Android端末の戻るボタン押下時にも呼ばれている。

※ここでのアプリ終了はアクティビティが全て閉じられた状態であり、プロセスを完全に終了させるわけではない。プロセス終了のタイミングはAndroidのOSに依存する。

②Activity#moveTaskToBack(boolean nonRoot)
アプリをバックグラウンドへ移動させる。
アプリ自体は生きており、再度アプリを実行すれば前回終了したところから始まる
Android端末のホームボタンを押下した時と同じ状態?

③(android.os.)Process#killProcess(int pid)
引数に強制終了させたいプロセスIDを指定する。
実行中のプロセスを対象にすると、呼び出し元のアクティビティのみを閉じる
ライフサイクルを無視して終了するため推奨されていない。

④System#exit(int)
バーチャルマシンの実行を停止してプログラムを終了する。
Process#killProcess()と概ね同じ動作となる。
やっぱり推奨されていない。

⑤ActivityManager#killBackgroundProcesses(String packageName)
Android2.2から実装されたメソッド。
バックグラウンドにある指定したアプリを終了する。
自分自身はバックグラウンドではないため終了させることが出来ない。
このメソッドを呼ぶにはパーミッションに android.permission.KILL_BACKGROUND_PROCESSES を追加する必要がある。

⑥ActivityManager#restartPackage(String packageName)
Android2.1以前で呼び出すと指定したアプリを終了する。
複数のアクティビティが起動されていても、全て閉じてくれる
ただし、2.2以降は#killBackgroundProcesses()がラップされており、そちらが実行されてしまう。
このメソッドを呼ぶにはパーミッションに android.permission.RESTART_PACKAGES を追加する必要がある(2.1以前のみ)

⑦Intent#setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) (2012/04/26追加)
Activity#startActivity(Intent intent) でアクティビティを開始させる際に Intent に FLAG_ACTIVITY_CLEAR_TOP を設定することでタスクに積まれたアクティビティを再開させることができる(タスクに積まれていなければ新しく開始される)。
このとき、再開されたアクティビティより上に詰まれた(新しい)アクティビティはすべてが破棄される
つまり、アプリ実行時に最初に起動されるアクティビティを呼び出すことで最初の状態に戻すことができる。
【関連記事】タスク管理 - インテントフラグ:Intent#setFlags
タイトルの終了方法とは若干異なる内容ですが、アプリ終了として使える手法なので追加しました。

記述方法(Activityクラスでの記述を前提にしています)
// ①アクティビティを正しく終了する
finish();

// ②アクティビティをバックグラウンドに移動する
moveTaskToBack(true);

// ③指定したアクティビティのプロセスを殺す
// Process.myPid() で自身のプロセスIDを取得
Process.killProcess(Process.myPid());

// ④システムを終了する
System.exit(0);

// ⑤バックグラウンドのアプリを終了する(2.2以降)
// getPackageName() で自身のパッケージ名を取得
ActivityManager manager = (ActivityManager)
getSystemService(Context.ACTIVITY_SERVICE);
manager.killBackgroundProcesses(getPackageName());

// ⑥アプリを終了する(2.1以前)
ActivityManager manager = (ActivityManager)
getSystemService(Context.ACTIVITY_SERVICE);
manager.restartPackage(getPackageName());

// ⑦アクティビティを再開させる
Intent intent = new Intent(this, StartActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

回線トラブルから復帰!

お久しぶりです。とむです。
お久しぶりといっても1週間ほどですが。

今回更新が止まった理由の1つには、暑くてPCに向かっていられない!
というのもありますが一番の理由はネット回線のトラブルでした。
あまりに暑かった所為か、回線不調(10分程度繋ぐとで回線が落ちる)に陥る状態になっていました。
原因はルーターで、一部が焼けてしまった様子(顔を近づけると微かに焦げ臭いにおいがする)

とりあえずルーターを外すだけで回線復帰したので、これから更新開始します。
(原因究明やら暑さで記事にできるようなことをしていませんでした…)

Androidに関してまだ触りの部分すら書ききれておらず、書くことは沢山あるので当分ネタ切れにはならなさそうです。
とはいえ、基礎的な部分ばかりじゃつまらないので合間合間に応用的な使い方とか色々かけたらなーと思っています。

拙い記事ですが、今後も読んでいただければ幸いです。
プロフィール

とむ・やむくん

Author:とむ・やむくん
管理人について

Windows 7 / 64bit
Eclipse 4.2 Juno (日本語パッチ済)

スポンサーサイト
最新トラックバック
検索フォーム
ブロとも申請フォーム
QRコード
QR
Twitter
2013/01/04 19:00 カウント開始

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。