・この機能を実装すると、StrictMode はアプリケーションのパフォーマンスを低下させる accidental disk や network activity を捕捉し、開発者にしらせてくれる
・例えば、メインスレッド上での accidental disk や network activity など
・開発者は StrictMode が補足した network や disk usages の問題を評価し、必要ならば修正できる
・これにより、メインスレッドは応答性を維持し、ANRダイアログがユーザーに表示されることを防げる
- StrictMode
core class であり、システムとVMを統合する主要なポイント。
このクラスは、インスタンスに応用するスレッドとVMのポリシーを
管理するための便利なメソッドを提供する
- StrictMode.ThreadPolicy と StrictMode.VmPolicy
スレッドとVMのインスタンスに応用するための(自分の)
ポリシーを保持する
---------------------------------------------------------
New Gingerbread API: StrictMode - Android developers Blog より
・StrictMode は Thread のポリシーに、どの操作を違反とし、違反があったときに何をするかを定義する
・デフォルトでは、全ての操作が許可されている
・thread ポリシーに含むことができるフラグとして、例えば以下のものがある
・detect disk writes
・detect disk reads
・detect network usage
・on a violation: log
> adb logcat で見ることが可能
・on a violation: crash
・on a violation: dropbox
DropBoxManager に書き込まれ、後から抽出できる
> adb shell dumpsys dropbox data_app_strictmode --print
・on a violation: show an annoying dialog
・StrictMode の強力な点は、スレッドあたりのポリシーは他の Serivces や Providers によって Binder IPC コールが作成されるたびに伝搬し、スタックトレースは任意の数のプロセスでつなぎあわされたものになること
・メインスレッドでネットワークリクエストをしてはいけない。Honeycomb リリースでは、メインスレッドでのネットワークリクエストは fatal error になるように作られている(らしい)
・Android Market にリリースする前に StrictMode を除くのを忘れずに!
StrictMode を使うには、 onCreate() で
public void onCreate() {
if (DEVELOPER_MODE) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.build());
}
super.onCreate();
}
もっと簡単に
public void onCreate() {
if (DEVELOPER_MODE) {
StrictMode.enableDefaults();
}
super.onCreate();
}
・Gingerbread 以前の API をターゲットにしたアプリケーションを Gingerbread 以降の端末やエミュータで実行する場合、reflection や 他の方法 を使って StrictMode を有効にできる
・問題が見つかったら、Thread や java.util.concurrent.* に加えて Handler, AsyncTask, AsyncQueryHandler, IntentService なども活用する
・Android 2.3 から SharedPreference.Editor() に apply() メソッドが追加された。commit() の戻りを使わない場合は apply() に置き換えられる。
# commit() は永続化ストレージに設定を同期して書き込むが、apply()は in-memory の SharedPreferences にすぐにコミットし、ディスクへのコミットは非同期に行われる。そのため、UIスレッドをブロックしない。
---------------------------------------------------------
■ StrictMode.ThreadPolicy
特定のスレッドに適用するポリシー
setThreadPolicy(StrictMode.ThreadPolicy) メソッドで有効にする
現在のポリシーは getThreadPolicy() で取得する
注意: 複数のペナルティを設定することは可能だが、検出された異なる
アクションに異なるペナルティを選択することは現状ではできない。
StrictMode.ThreadPolicy.Builder を使ってインスタンスを生成する
・ Nested Classes
- StrictMode.ThreadPolicy.Builder
StrictMode.ThreadPolicy インスタンスを生成する
・ Constants
- LAX
デフォルトのポリシー。lax policy は何も捕捉しない
■ StrictMode.ThreadPolicy.Builder
StrictMode.ThreadPolicy インスタンスを生成する
"detect" から始まるメソッドで補足したい問題の検出を有効にする
"permit" から始まるメソッドで捕捉したい問題の検出を無効にする
"penalty" から始まるメソッドで問題を検出したときにすべきことを指定する
複数の detect と penalty メソッドを呼ぶことができる
順番は問題に関係く、全てのペナルティは全ての検出された問題に適用される
全てを検出して、すべてをログに出すには次のようにする
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyLog()
.build();
StrictMode.setThreadPolicy(policy);
・ Public Methods
- build ()
ThreadPolicy instance を生成
build メソッドが呼ばれるまえに、ペナルティがなにも
セットされていない場合は、penaltyLog() が暗黙に
セットされる
- detectAll ()
可能性のある候補すべてを検出する
Gingerbread release では、 SQLiner cursor leaks だけ
含まれるが、将来の release で拡張される
- detectDiskReads ()
disk reads の検出を有効にする
- detectDiskWrites ()
disk writes の検出を有効にする
- detectNetwork()
ネットワーク操作の検出を有効にする
- penaltyDeath ()
違反によって全てのプロセスをクラッシュする
このペナルティは全ての有効なペナルティの最後に行われる。
そのため、プロセスが終了する前にログや他の違反を
取ることが可能
- penaltyDialog ()
違反を検出するとダイアログを表示する
これにより、少しレートが制限される
- penaltyDropBox ()
検出された違反のスタックトレースとタイミングデータを
DropBox にログとして出すことを有効にする
ベータユーザーのフィールドデータ収集する platform
integrator を主な対象としている
- penaltyLog ()
検出された違反をシステムログに出す
- permitAll ()
全ての検出を無効にする
- permitDiskReads ()
disk reads の検出を無効にする
- permitDiskWrites ()
disk writes の検出を無効にする
- permitNetwork ()
ネットワーク操作の検出を無効にする
■ StrictMode.VmPolicy
virtual machine 上のプロセスの全てのスレッドに適用するポリシー
setVmPolicy(StrictMode.VmPolicy) メソッドで有効にする
StrictMode.VmPolicy.Builder を使ってインスタンスを生成する
・ Nested Classes
- StrictMode.VmPolicy.Builder
StrictMode.VMPolicy インスタンスを生成する
・ Constants
- LAX
デフォルトのポリシー。lax policy は何も捕捉しない
■ StrictMode.Vmpolicy.Builder
StrictMode.VmPolicy インスタンスを生成する
"detect" から始まるメソッドで補足したい問題を指定する
"penalty" から始まるメソッドで問題を検出したときに
すべきことを指定する
複数の detect と penalty メソッドを呼ぶことができる
順番は問題に関係く、全てのペナルティは全ての検出された
問題に適用される
全てを検出して、すべてをログに出すには次のようにする
StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder()
.detectAll()
.penaltyLog()
.build();
StrictMode.setVmPolicy(policy);
・ Public Methods
- build ()
VmPolicy instance を生成
build メソッドが呼ばれるまえに、ペナルティがなにも
セットされていない場合は、penaltyLog() が暗黙に
セットされる
- detectAll ()
可能性のある候補すべてを検出する
Gingerbread release では、 SQLiner cursor leaks だけ
含まれるが、将来の release で拡張される
- detectLeakedSqlLiteObjects ()
SQLiteCursor や他の SQLite object がクローズされずに
finalize されたときに検出する
不要なデータベースの競合と一時的なメモリリークを防ぐ
ために、SQLite cursor は明示的にクローズするべき
- penaltyDeath ()
違反によって全てのプロセスをクラッシュする
このペナルティは全ての有効なペナルティの最後に行われる。
そのため、プロセスが終了する前にログや他の違反を
取ることが可能
- penaltyDropBox ()
検出された違反のスタックトレースとタイミングデータを
DropBox にログとして出すことを有効にする
ベータユーザーのフィールドデータ収集する platform
integrator を主な対象としている
- penaltyLog ()
検出された違反をシステムログに出す
試しにUIスレッドでインターネットダウンロードしてみました。
package yanzm.example.strictmodesample;
import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.StrictMode;
public class MyActivity extends Activity {
private boolean DEVELOPER_MODE = true;
@Override
public void onCreate(Bundle savedInstanceState) {
if (DEVELOPER_MODE) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.penaltyLog()
.penaltyDeath()
.build());
}
super.onCreate(savedInstanceState);
downloadFromInternet();
}
private void downloadFromInternet() {
String url = "https://sites.google.com/site/yukianzm/tmp/image1.png";
try {
Bitmap bmp = null;
final DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet hg = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(hg);
if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
bmp = BitmapFactory.decodeStream(httpResponse.getEntity().getContent());
hg.abort();
}
}
catch (ClientProtocolException e) {}
catch (IOException e) {}
}
}
Logcat の出力の一部
D/StrictMode( 387): StrictMode policy violation; ~duration=1456 ms: android.os.StrictMode$StrictModeNetworkViolation: policy=23 violation=4
D/StrictMode( 387): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:758)
D/StrictMode( 387): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLInputStream.read(OpenSSLSocketImpl.java:774)
D/StrictMode( 387): at org.apache.http.impl.io.AbstractSessionInputBuffer.fillBuffer(AbstractSessionInputBuffer.java:103)
D/StrictMode( 387): at org.apache.http.impl.io.AbstractSessionInputBuffer.read(AbstractSessionInputBuffer.java:134)
D/StrictMode( 387): at org.apache.http.impl.io.ContentLengthInputStream.read(ContentLengthInputStream.java:174)
D/StrictMode( 387): at org.apache.http.impl.io.ContentLengthInputStream.read(ContentLengthInputStream.java:188)
D/StrictMode( 387): at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:178)
D/StrictMode( 387): at java.io.BufferedInputStream.fillbuf(BufferedInputStream.java:140)
D/StrictMode( 387): at java.io.BufferedInputStream.read(BufferedInputStream.java:324)
D/StrictMode( 387): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
D/StrictMode( 387): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:460)
D/StrictMode( 387): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:515)
D/StrictMode( 387): at yanzm.example.strictmodesample.MyActivity.downloadFromInternet(MyActivity.java:49)
D/StrictMode( 387): at yanzm.example.strictmodesample.MyActivity.onCreate(MyActivity.java:34)
D/StrictMode( 387): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
D/StrictMode( 387): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1586)
D/StrictMode( 387): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1638)
D/StrictMode( 387): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
D/StrictMode( 387): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:928)
D/StrictMode( 387): at android.os.Handler.dispatchMessage(Handler.java:99)
D/StrictMode( 387): at android.os.Looper.loop(Looper.java:123)
D/StrictMode( 387): at android.app.ActivityThread.main(ActivityThread.java:3647)
D/StrictMode( 387): at java.lang.reflect.Method.invokeNative(Native Method)
D/StrictMode( 387): at java.lang.reflect.Method.invoke(Method.java:507)
D/StrictMode( 387): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
D/StrictMode( 387): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
D/StrictMode( 387): at dalvik.system.NativeStart.main(Native Method)
0 件のコメント:
コメントを投稿