【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中StrictMode如何使用_第1頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中StrictMode如何使用_第2頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中StrictMode如何使用_第3頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中StrictMode如何使用_第4頁
【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中StrictMode如何使用_第5頁
已閱讀5頁,還剩9頁未讀 繼續(xù)免費(fèi)閱讀

付費(fèi)下載

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中StrictMode如何使用

本篇文章給大家分享的是有關(guān)Android中StrictMode如何使用,在下覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著在下一起來看看吧。StrictMode具體能檢測(cè)什么嚴(yán)苛模式主要檢測(cè)兩大問題,一個(gè)是線程策略,即TreadPolicy,另一個(gè)是VM策略,即VmPolicy。ThreadPolicy線程策略檢測(cè)線程策略檢測(cè)的內(nèi)容有自定義的耗時(shí)調(diào)用使用detectCustomSlowCalls()開啟磁盤讀取操作使用detectDiskReads()開啟磁盤寫入操作使用detectDiskWrites()開啟網(wǎng)絡(luò)操作使用detectNetwork()開啟VmPolicy虛擬機(jī)策略檢測(cè)Activity泄露使用detectActivityLeaks()開啟未關(guān)閉的Closable對(duì)象泄露使用detectLeakedClosableObjects()開啟泄露的Sqlite對(duì)象使用detectLeakedSqlLiteObjects()開啟檢測(cè)實(shí)例數(shù)量使用setClassInstanceLimit()開啟工作原理

其實(shí)StrictMode實(shí)現(xiàn)原理也比較簡(jiǎn)單,以IO操作為例,主要是通過在open,read,write,close時(shí)進(jìn)行監(jiān)控。libcore.io.BlockGuardOs文件就是監(jiān)控的地方。以open為例,如下進(jìn)行監(jiān)控。@Override

public

FileDescriptor

open(String

path,

int

flags,

int

mode)

throws

ErrnoException

{

BlockGuard.getThreadPolicy().onReadFromDisk();

if

((mode

&

O_ACCMODE)

!=

O_RDONLY)

{

BlockGuard.getThreadPolicy().onWriteToDisk();

}

return

os.open(path,

flags,

mode);

}其中onReadFromDisk()方法的實(shí)現(xiàn),代碼位于StrictMode.java中。public

void

onReadFromDisk()

{

if

((mPolicyMask

&

DETECT_DISK_READ)

==

0)

{

return;

}

if

(tooManyViolationsThisLoop())

{

return;

}

BlockGuard.BlockGuardPolicyException

e

=

new

StrictModeDiskReadViolation(mPolicyMask);

e.fillInStackTrace();

startHandlingViolationException(e);

}常見用法

嚴(yán)格模式的開啟可以放在Application或者Activity以及其他組件的onCreate方法。為了更好地分析應(yīng)用中的問題,建議放在Application的onCreate方法中。

其中,我們只需要在app的開發(fā)版本下使用StrictMode,線上版本避免使用StrictMode,這里定義了一個(gè)布爾值變量DEV_MODE來進(jìn)行控制。private

boolean

DEV_MODE

=

true;

public

void

onCreate()

{

if

(DEV_MODE)

{

StrictMode.setThreadPolicy(new

StrictMode.ThreadPolicy.Builder()

.detectCustomSlowCalls()

//API等級(jí)11,使用StrictMode.noteSlowCode

.detectDiskReads()

.detectDiskWrites()

.detectNetwork()

//

or

.detectAll()

for

all

detectable

problems

.penaltyDialog()

//彈出違規(guī)提示對(duì)話框

.penaltyLog()

//在Logcat

中打印違規(guī)異常信息

.penaltyFlashScreen()

//API等級(jí)11

.build());

StrictMode.setVmPolicy(new

StrictMode.VmPolicy.Builder()

.detectLeakedSqlLiteObjects()

.detectLeakedClosableObjects()

//API等級(jí)11

.penaltyLog()

.penaltyDeath()

.build());

}

super.onCreate();

}

其中Android3.0引入的方法包括detectCustomSlowCalls()和noteSlowCode(),它們都是用來檢測(cè)應(yīng)用中執(zhí)行緩慢代碼的或者潛在的緩慢代碼。查看報(bào)告結(jié)果

嚴(yán)格模式有很多種報(bào)告違例的形式,但是想要分析具體違例情況,還是需要查看日志,終端下過濾StrictMode就能得到違例的具體stacktrace信息。adb

logcat

|

grep

StrictMode當(dāng)然也可以選擇彈窗形式來簡(jiǎn)明提醒開發(fā)者彈窗警告ThreadPolicy詳解StrictMode.ThreadPolicy.Builder主要方法如下detectNetwork()用于檢查UI線程中是否有網(wǎng)絡(luò)請(qǐng)求操作檢測(cè)UI線程中網(wǎng)絡(luò)請(qǐng)求案例:public

class

MainActivity

extends

AppCompatActivity

implements

View.OnClickListener

{

Button

btnTest;

@Override

protected

void

onCreate(Bundle

savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

StrictMode.setThreadPolicy(new

StrictMode.ThreadPolicy.Builder()

.detectNetwork()

.penaltyLog()

.build());

btnTest

=

(Button)

findViewById(R.id.btn_test);

btnTest.setOnClickListener(this);

}

@Override

public

void

onClick(View

v)

{

int

id

=

v.getId();

switch

(id)

{

case

R.id.btn_test:

postNetwork();

break;

}

}

/**

*

網(wǎng)絡(luò)連接的操作

*/

private

void

postNetwork()

{

try

{

URL

url

=

new

URL("");

HttpURLConnection

conn

=

(HttpURLConnection)

url.openConnection();

conn.connect();

BufferedReader

reader

=

new

BufferedReader(new

InputStreamReader(

conn.getInputStream()));

String

lines

=

null;

StringBuffer

sb

=

new

StringBuffer();

while

((lines

=

reader.readLine())

!=

null)

{

sb.append(lines);

}

}

catch

(Exception

e)

{

e.printStackTrace();

}

}

}運(yùn)行后,觸發(fā)的警告如下detectDiskReads()和detectDiskWrites()是磁盤讀寫檢查磁盤讀寫檢查案例:public

class

MainActivity

extends

AppCompatActivity

implements

View.OnClickListener

{

Button

btnTest;

@Override

protected

void

onCreate(Bundle

savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

StrictMode.setThreadPolicy(new

StrictMode.ThreadPolicy.Builder()

.detectDiskWrites()

.detectDiskReads()

.penaltyLog()

.build());

btnTest

=

(Button)

findViewById(R.id.btn_test);

btnTest.setOnClickListener(this);

}

@Override

public

void

onClick(View

v)

{

int

id

=

v.getId();

switch

(id)

{

case

R.id.btn_test:

writeToExternalStorage();

break;

}

}

/**

*

文件系統(tǒng)的操作

*/

public

void

writeToExternalStorage()

{

File

externalStorage

=

Environment.getExternalStorageDirectory();

File

mbFile

=

new

File(externalStorage,

"castiel.txt");

try

{

OutputStream

output

=

new

FileOutputStream(mbFile,

true);

output.write("".getBytes());

output.flush();

output.close();

}

catch

(FileNotFoundException

e)

{

e.printStackTrace();

}

catch

(IOException

e)

{

e.printStackTrace();

}

}

}運(yùn)行后,觸發(fā)的警告如下noteSlowCall針對(duì)執(zhí)行比較耗時(shí)的檢查

StrictMode從API11開始允許開發(fā)者自定義一些耗時(shí)調(diào)用違例,這種自定義適用于自定義的任務(wù)執(zhí)行類中,比如我們有一個(gè)進(jìn)行任務(wù)處理的類,為TaskExecutor。public

class

TaskExecutor

{

public

void

execute(Runnable

task)

{

task.run();

}

}

先需要跟蹤每個(gè)任務(wù)的耗時(shí)情況,如果大于500毫秒需要提示給開發(fā)者,noteSlowCall就可以實(shí)現(xiàn)這個(gè)功能,如下修改代碼public

class

TaskExecutor

{

private

static

long

SLOW_CALL_THRESHOLD

=

500;

public

void

executeTask(Runnable

task)

{

long

startTime

=

SystemClock.uptimeMillis();

task.run();

long

cost

=

SystemClock.uptimeMillis()

-

startTime;

if

(cost

>

SLOW_CALL_THRESHOLD)

{

StrictMode.noteSlowCall("slowCall

cost="

+

cost);

}

}

}執(zhí)行一個(gè)耗時(shí)2000毫秒的任務(wù)TaskExecutor

executor

=

new

TaskExecutor();

executor.executeTask(new

Runnable()

{

@Override

public

void

run()

{

try

{

Thread.sleep(2000);

}

catch

(InterruptedException

e)

{

e.printStackTrace();

}

}

});

得到的違例日志,注意其中~duration=20ms并非耗時(shí)任務(wù)的執(zhí)行時(shí)間,而我們的自定義信息msg=slowCallcost=2000才包含了真正的耗時(shí)。penaltyDeath(),當(dāng)觸發(fā)違規(guī)條件時(shí),直接Crash掉當(dāng)前應(yīng)用程序。penaltyDeathOnNetwork(),當(dāng)觸發(fā)網(wǎng)絡(luò)違規(guī)時(shí),Crash掉當(dāng)前應(yīng)用程序。penaltyDialog(),觸發(fā)違規(guī)時(shí),顯示對(duì)違規(guī)信息對(duì)話框。penaltyFlashScreen(),會(huì)造成屏幕閃爍,不過一般的設(shè)備可能沒有這個(gè)功能。penaltyDropBox(),將違規(guī)信息記錄到dropbox系統(tǒng)日志目錄中(/data/system/dropbox),你可以通過如下命令進(jìn)行插件:adb

shell

dumpsys

dropbox

dataappstrictmode

--printpermitCustomSlowCalls()、permitDiskReads()、permitDiskWrites()、permitNetwork:如果你想關(guān)閉某一項(xiàng)檢測(cè),可以使用對(duì)應(yīng)的permit*方法。VMPolicy詳解StrictMode.VmPolicy.Builder主要方法如下detectActivityLeaks()用戶檢查Activity的內(nèi)存泄露情況內(nèi)存泄露檢查案例:public

class

MainActivity

extends

AppCompatActivity

implements

View.OnClickListener

{

@Override

protected

void

onCreate(Bundle

savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

StrictMode.setVmPolicy(new

StrictMode.VmPolicy.Builder()

.detectActivityLeaks()

.penaltyLog()

.build()

);

new

Thread()

{

@Override

public

void

run()

{

while

(true)

{

SystemClock.sleep(1000);

}

}

}.start();

}

}我們反復(fù)旋轉(zhuǎn)屏幕就會(huì)輸出提示信息(重點(diǎn)在instances=2;limit=1這一行)

這時(shí)因?yàn)椋覀冊(cè)贏ctivity中創(chuàng)建了一個(gè)Thread匿名內(nèi)部類,而匿名內(nèi)部類隱式持有外部類的引用。而每次旋轉(zhuǎn)屏幕是,Android會(huì)新創(chuàng)建一個(gè)Activity,而原來的Activity實(shí)例又被我們啟動(dòng)的匿名內(nèi)部類線程持有,所以不會(huì)釋放,從日志上看,當(dāng)先系統(tǒng)中該Activty有4個(gè)實(shí)例,而限制是只能創(chuàng)建1各實(shí)例。我們不斷翻轉(zhuǎn)屏幕,instances的個(gè)數(shù)還會(huì)持續(xù)增加。detectLeakedClosableObjects()用于資源沒有正確關(guān)閉時(shí)提醒//

資源引用沒有關(guān)閉檢查案例

public

class

MainActivity

extends

AppCompatActivity

implements

View.OnClickListener

{

@Override

protected

void

onCreate(Bundle

savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

StrictMode.setVmPolicy(new

StrictMode.VmPolicy.Builder()

.detectLeakedClosableObjects()

.penaltyLog()

.build()

);

File

newxmlfile

=

new

File(Environment.getExternalStorageDirectory(),

"castiel.txt");

try

{

newxmlfile.createNewFile();

FileWriter

fw

=

new

FileWriter(newxmlfile);

fw.write("猴子搬來的救兵WooYun");

//fw.close();

我們?cè)谶@里特意沒有關(guān)閉

fw

}

catch

(IOException

e)

{

e.printStackTrace();

}

}

}運(yùn)行后觸發(fā)警告如下detectLeakedSqlLiteObjects()和detectLeakedClosableObjects()的用法類似,只不過是用來檢查SQLiteCursor或者其他SQLite對(duì)象是否被正確關(guān)閉detectLeakedRegistrationObjects()用來檢查BroadcastReceiver或者ServiceConnection注冊(cè)類對(duì)象是否被正確釋放setClassInstanceLimit(),設(shè)置某個(gè)類的同時(shí)處于內(nèi)存中的實(shí)例上限,可以協(xié)助檢查內(nèi)存泄露檢測(cè)內(nèi)存泄露案例public

class

MainActivity

extends

AppCompatActivity

implements

View.OnClickListener

{

private

static

class

CastielC

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論