【移動應(yīng)用開發(fā)技術(shù)】Android性能優(yōu)化電量的方法是什么_第1頁
【移動應(yīng)用開發(fā)技術(shù)】Android性能優(yōu)化電量的方法是什么_第2頁
【移動應(yīng)用開發(fā)技術(shù)】Android性能優(yōu)化電量的方法是什么_第3頁
【移動應(yīng)用開發(fā)技術(shù)】Android性能優(yōu)化電量的方法是什么_第4頁
【移動應(yīng)用開發(fā)技術(shù)】Android性能優(yōu)化電量的方法是什么_第5頁
已閱讀5頁,還剩4頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

【移動應(yīng)用開發(fā)技術(shù)】Android性能優(yōu)化電量的方法是什么

本文在下為大家詳細(xì)介紹“Android性能優(yōu)化電量的方法是什么”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“Android性能優(yōu)化電量的方法是什么”文章能幫助大家解決疑惑,下面跟著在下的思路慢慢深入,一起來學(xué)習(xí)新知識吧。1)UnderstandingBatteryDrain手機(jī)各個硬件模塊的耗電量是不一樣的,有些模塊非常耗電,而有些模塊則相對顯得耗電量小很多。電量消耗的計算與統(tǒng)計是一件麻煩而且矛盾的事情,記錄電量消耗本身也是一個費(fèi)電量的事情。唯一可行的方案是使用第三方監(jiān)測電量的設(shè)備,這樣才能夠獲取到真實(shí)的電量消耗。當(dāng)設(shè)備處于待機(jī)狀態(tài)時消耗的電量是極少的,以N5為例,打開飛行模式,可以待機(jī)接近1個月??墒屈c(diǎn)亮屏幕,硬件各個模塊就需要開始工作,這會需要消耗很多電量。使用WakeLock或者JobScheduler喚醒設(shè)備處理定時的任務(wù)之后,一定要及時讓設(shè)備回到初始狀態(tài)。每次喚醒蜂窩信號進(jìn)行數(shù)據(jù)傳遞,都會消耗很多電量,它比WiFi等操作更加的耗電。2)BatteryHistorianBatteryHistorian是Android5.0開始引入的新API。通過下面的指令,可以得到設(shè)備上的電量消耗信息:$

adb

shell

dumpsys

batterystats

>

xxx.txt

//得到整個設(shè)備的電量消耗信息

$

adb

shell

dumpsys

batterystats

>

>

xxx.txt

//得到指定app相關(guān)的電量消耗信息得到了原始的電量消耗數(shù)據(jù)之后,我們需要通過Google編寫的一個python腳本把數(shù)據(jù)信息轉(zhuǎn)換成可讀性更好的html文件:$

python

historian.py

xxx.txt

>

xxx.html打開這個轉(zhuǎn)換過后的html文件,可以看到類似TraceView生成的列表數(shù)據(jù),這里的數(shù)據(jù)信息量很大,這里就不展開了。3)TrackBatteryStatus&BatteryManager我們可以通過下面的代碼來獲取手機(jī)的當(dāng)前充電狀態(tài)://

It

is

very

easy

to

subscribe

to

changes

to

the

battery

state,

but

you

can

get

the

current

//

state

by

simply

passing

null

in

as

your

receiver.

Nifty,

isn't

that?

IntentFilter

filter

=

new

IntentFilter(Intent.ACTION_BATTERY_CHANGED);

Intent

batteryStatus

=

this.registerReceiver(null,

filter);

int

chargePlug

=

batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED,

-1);

boolean

acCharge

=

(chargePlug

==

BatteryManager.BATTERY_PLUGGED_AC);

if

(acCharge)

{

Log.v(LOG_TAG,“The

phone

is

charging!”);

}在上面的例子演示了如何立即獲取到手機(jī)的充電狀態(tài),得到充電狀態(tài)信息之后,我們可以有針對性的對部分代碼做優(yōu)化。比如我們可以判斷只有當(dāng)前手機(jī)為AC充電狀態(tài)時才去執(zhí)行一些非常耗電的操作。/**

*

This

method

checks

for

power

by

comparing

the

current

battery

state

against

all

possible

*

plugged

in

states.

In

this

case,

a

device

may

be

considered

plugged

in

either

by

USB,

AC,

or

*

wireless

charge.

(Wireless

charge

was

introduced

in

API

Level

17.)

*/

private

boolean

checkForPower()

{

//

It

is

very

easy

to

subscribe

to

changes

to

the

battery

state,

but

you

can

get

the

current

//

state

by

simply

passing

null

in

as

your

receiver.

Nifty,

isn't

that?

IntentFilter

filter

=

new

IntentFilter(Intent.ACTION_BATTERY_CHANGED);

Intent

batteryStatus

=

this.registerReceiver(null,

filter);

//

There

are

currently

three

ways

a

device

can

be

plugged

in.

We

should

check

them

all.

int

chargePlug

=

batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED,

-1);

boolean

usbCharge

=

(chargePlug

==

BatteryManager.BATTERY_PLUGGED_USB);

boolean

acCharge

=

(chargePlug

==

BatteryManager.BATTERY_PLUGGED_AC);

boolean

wirelessCharge

=

false;

if

(Build.VERSION.SDK_INT

>=

Build.VERSION_CODES.JELLY_BEAN_MR1)

{

wirelessCharge

=

(chargePlug

==

BatteryManager.BATTERY_PLUGGED_WIRELESS);

}

return

(usbCharge

||

acCharge

||

wirelessCharge);

}4)WakelockandBatteryDrain高效的保留更多的電量與不斷促使用戶使用你的App會消耗電量,這是矛盾的選擇題。不過我們可以使用一些更好的辦法來平衡兩者。假設(shè)你的手機(jī)里面裝了大量的社交類應(yīng)用,即使手機(jī)處于待機(jī)狀態(tài),也會經(jīng)常被這些應(yīng)用喚醒用來檢查同步新的數(shù)據(jù)信息。Android會不斷關(guān)閉各種硬件來延長手機(jī)的待機(jī)時間,首先屏幕會逐漸變暗直至關(guān)閉,然后CPU進(jìn)入睡眠,這一切操作都是為了節(jié)約寶貴的電量資源。但是即使在這種睡眠狀態(tài)下,大多數(shù)應(yīng)用還是會嘗試進(jìn)行工作,他們將不斷的喚醒手機(jī)。一個最簡單的喚醒手機(jī)的方法是使用PowerManager.WakeLock的API來保持CPU工作并防止屏幕變暗關(guān)閉。這使得手機(jī)可以被喚醒,執(zhí)行工作,然后回到睡眠狀態(tài)。知道如何獲取WakeLock是簡單的,可是及時釋放WakeLock也是非常重要的,不恰當(dāng)?shù)氖褂肳akeLock會導(dǎo)致嚴(yán)重錯誤。例如網(wǎng)絡(luò)請求的數(shù)據(jù)返回時間不確定,導(dǎo)致本來只需要10s的事情一直等待了1個小時,這樣會使得電量白白浪費(fèi)了。這也是為何使用帶超時參數(shù)的wakelock.acquice()方法是很關(guān)鍵的。但是僅僅設(shè)置超時并不足夠解決問題,例如設(shè)置多長的超時比較合適?什么時候進(jìn)行重試等等?解決上面的問題,正確的方式可能是使用非精準(zhǔn)定時器。通常情況下,我們會設(shè)定一個時間進(jìn)行某個操作,但是動態(tài)修改這個時間也許會更好。例如,如果有另外一個程序需要比你設(shè)定的時間晚5分鐘喚醒,***能夠等到那個時候,兩個任務(wù)捆綁一起同時進(jìn)行,這就是非精確定時器的核心工作原理。我們可以定制計劃的任務(wù),可是系統(tǒng)如果檢測到一個更好的時間,它可以推遲你的任務(wù),以節(jié)省電量消耗。這正是JobSchedulerAPI所做的事情。它會根據(jù)當(dāng)前的情況與任務(wù),組合出理想的喚醒時間,例如等到正在充電或者連接到WiFi的時候,或者集中任務(wù)一起執(zhí)行。我們可以通過這個API實(shí)現(xiàn)很多免費(fèi)的調(diào)度算法。5)NetworkandBatteryDrain下面內(nèi)容來自官方Training文檔中高效下載章節(jié)關(guān)于手機(jī)(Radio)蜂窩信號對電量消耗的介紹。通常情況下,使用3G移動網(wǎng)絡(luò)傳輸數(shù)據(jù),電量的消耗有三種狀態(tài):Fullpower:能量***的狀態(tài),移動網(wǎng)絡(luò)連接被激活,允許設(shè)備以***的傳輸速率進(jìn)行操作。Lowpower:一種中間狀態(tài),對電量的消耗差不多是Fullpower狀態(tài)下的50%。Standby:***的狀態(tài),沒有數(shù)據(jù)連接需要傳輸,電量消耗最少。下圖是一個典型的3GRadioStateMachine的圖示總之,為了減少電量的消耗,在蜂窩移動網(wǎng)絡(luò)下,***做到批量執(zhí)行網(wǎng)絡(luò)請求,盡量避免頻繁的間隔網(wǎng)絡(luò)請求。通過前面學(xué)習(xí)到的BatteryHistorian我們可以得到設(shè)備的電量消耗數(shù)據(jù),如果數(shù)據(jù)中的移動蜂窩網(wǎng)絡(luò)(MobileRadio)電量消耗呈現(xiàn)下面的情況,間隔很小,又頻繁斷斷續(xù)續(xù)的出現(xiàn),說明電量消耗性能很不好:經(jīng)過優(yōu)化之后,如果呈現(xiàn)下面的圖示,說明電量消耗的性能是良好的:另外WiFi連接下,網(wǎng)絡(luò)傳輸?shù)碾娏肯囊纫苿泳W(wǎng)絡(luò)少很多,應(yīng)該盡量減少移動網(wǎng)絡(luò)下的數(shù)據(jù)傳輸,多在WiFi環(huán)境下傳輸數(shù)據(jù)。那么如何才能夠把任務(wù)緩存起來,做到批量化執(zhí)行呢?下面就輪到JobScheduler出場了。6)UsingJobScheduler使用JobScheduler,應(yīng)用需要做的事情就是判斷哪些任務(wù)是不緊急的,可以交給JobScheduler來處理,JobScheduler集中處理收到的任務(wù),選擇合適的時間,合適的網(wǎng)絡(luò),再一起進(jìn)行執(zhí)行。下面是使用JobScheduler的一段簡要示例,需要先有一個JobService:public

class

MyJobService

extends

JobService

{

private

static

final

String

LOG_TAG

=

"MyJobService";

@Override

public

void

onCreate()

{

super.onCreate();

Log.i(LOG_TAG,

"MyJobService

created");

}

@Override

public

void

onDestroy()

{

super.onDestroy();

Log.i(LOG_TAG,

"MyJobService

destroyed");

}

@Override

public

boolean

onStartJob(JobParameters

params)

{

//

This

is

where

you

would

implement

all

of

the

logic

for

your

job.

Note

that

this

runs

//

on

the

main

thread,

so

you

will

want

to

use

a

separate

thread

for

asynchronous

work

//

(as

we

demonstrate

below

to

establish

a

network

connection).

//

If

you

use

a

separate

thread,

return

true

to

indicate

that

you

need

a

"reschedule"

to

//

return

to

the

job

at

some

point

in

the

future

to

finish

processing

the

work.

Otherwise,

//

return

false

when

finished.

Log.i(LOG_TAG,

"Totally

and

completely

working

on

job

"

+

params.getJobId());

//

First,

check

the

network,

and

then

attempt

to

connect.

if

(isNetworkConnected())

{

new

SimpleDownloadTask()

.execute(params);

return

true;

}

else

{

Log.i(LOG_TAG,

"No

connection

on

job

"

+

params.getJobId()

+

";

sad

face");

}

return

false;

}

@Override

public

boolean

onStopJob(JobParameters

params)

{

//

Called

if

the

job

must

be

stopped

before

jobFinished()

has

been

called.

This

may

//

happen

if

the

requirements

are

no

longer

being

met,

such

as

the

user

no

longer

//

connecting

to

WiFi,

or

the

device

no

longer

being

idle.

Use

this

callback

to

resolve

//

anything

that

may

cause

your

application

to

misbehave

from

the

job

being

halted.

//

Return

true

if

the

job

should

be

rescheduled

based

on

the

retry

criteria

specified

//

when

the

job

was

created

or

return

false

to

drop

the

job.

Regardless

of

the

value

//

returned,

your

job

must

stop

executing.

Log.i(LOG_TAG,

"Whelp,

something

changed,

so

I'm

calling

it

on

job

"

+

params.getJobId());

return

false;

}

/**

*

Determines

if

the

device

is

currently

online.

*/

private

boolean

isNetworkConnected()

{

ConnectivityManager

connectivityManager

=

(ConnectivityManager)

getSystemService(Context.CONNECTIVITY_SERVICE);

NetworkInfo

networkInfo

=

connectivityManager.getActiveNetworkInfo();

return

(networkInfo

!=

null

&&

networkInfo.isConnected());

}

/**

*

Uses

AsyncTask

to

create

a

task

away

from

the

main

UI

thread.

This

task

creates

a

*

HTTPUrlConnection,

and

then

downloads

the

contents

of

the

webpage

as

an

InputStream.

*

The

InputStream

is

then

converted

to

a

String,

which

is

logged

by

the

*

onPostExecute()

method.

*/

private

class

SimpleDownloadTask

extends

AsyncTask<JobParameters,

Void,

String>

{

protected

JobParameters

mJobParam;

@Override

protected

String

doInBackground(JobParameters...

params)

{

//

cache

system

provided

job

requirements

mJobParam

=

params[0];

try

{

InputStream

is

=

null;

//

Only

display

the

first

50

characters

of

the

retrieved

web

page

content.

int

len

=

50;

URL

url

=

new

URL("");

HttpURLConnection

conn

=

(HttpURLConnection)

url.openConnection();

conn.setReadTimeout(10000);

//10sec

conn.setConnectTimeout(15000);

//15sec

conn.setRequestMethod("GET");

//Starts

the

query

conn.connect();

int

response

=

conn.getResponseCode();

Log.d(LOG_TAG,

"The

response

is:

"

+

response);

is

=

conn.getInputStream();

//

Convert

the

input

stream

to

a

string

Reader

reader

=

null;

reader

=

new

InputStreamReader(is,

"UTF-8");

char[]

buffer

=

new

char[len];

reader.read(buffer);

return

new

String(buffer);

}

catch

(IOException

e)

{

return

"Unable

to

retrieve

web

page.";

}

}

@Override

protected

void

onPostExecute(String

result)

{

jobFinished(mJobParam,

false);

Log.i(LOG_TAG,

result);

}

}

}然后模擬通過點(diǎn)擊Button觸發(fā)N個任務(wù),交給JobService來處public

class

FreeTheWakelockActivity

extends

ActionBarActivity

{

public

static

final

String

LOG_TAG

=

"FreeTheWakelockActivity";

TextView

mWakeLockMsg;

ComponentName

mServiceComponent;

@Override

protected

void

onCreate(Bundle

savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_wakelock);

mWakeLockMsg

=

(TextView)

findViewById(R.id.wakelock_txt);

mServiceComponent

=

new

ComponentName(this,

MyJobService.class);

Intent

startServiceIntent

=

new

Intent(this,

MyJobService.class);

startService(startServiceIntent);

Button

theButtonThatWakelocks

=

(Button)

findViewById(R.id.wakelock_poll);

theButtonThatWakelocks.setText(R.string.poll_server_button);

theButtonThatWakelocks.setOnClickListener(new

View.OnClickListener()

{

@Override

public

void

onClick(View

v)

{

pollServer();

}

});

}

/**

*

This

method

polls

the

server

via

the

JobScheduler

API.

By

scheduling

the

job

with

this

API,

*

your

app

can

be

confident

it

will

execute,

but

without

the

need

for

a

wake

lock.

Rather,

the

*

API

will

take

your

network

jobs

and

execute

them

in

batch

to

best

take

advantage

of

the

*

initial

network

connection

cost.

*

*

The

JobScheduler

API

works

through

a

background

service.

In

this

sample,

we

have

*

a

simple

service

in

MyJobService

to

get

you

started.

The

job

is

scheduled

here

in

*

the

activity,

but

the

job

itself

is

executed

in

MyJ

溫馨提示

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

評論

0/150

提交評論