#android电池电量优化
在09年Google IO大会Jeffrey Sharkey指出android应用的耗电量主要在以下三个方面:
并提出了相关的优化建议:
作为app开发者,应该限制app对电量的影响,当没有网络连接的时候,禁用后台服务更新,当电池电量低的时候减少更新的频率,当电池充电或者电量比较饱和时,可以最大限度的发挥app的刷新率
获取手机的当前充电状态
//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,“Thephoneischarging!”);
}
优化的建议
JobScheduler API会根据当前的情况与任务,组合出理想的唤醒时间,例如等到正在充电或者连接到WiFi的时候,或者集中任务一起执行,可以通过这个API实现很多免费的调度算法
//示例
public class MyJobService extendsJ obService{
private static final String LOG_TAG="MyJobService";
@Override
public void onCreate(){
super.onCreate();
Log.i(LOG_TAG,"MyJobServi cecreated");
}
@Override
public voidon Destroy(){
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 as eparate thread for asynchronous work
//(as we demonstrate below to establishanet work connection).
//If you use as eparatethread,return true to indicate that you need a "reschedule" to
//return to the job at somepoint in the future to finish processing the work.Otherwise,
//return false whenfinished.
Log.i(LOG_TAG,"Totally and completely working on job"+params.getJobId());
//First,check the network,and the nattempt 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 job Finished() 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 mis behave from the job being halted.
//Return true if the job should be rescheduled based on there try 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 callingiton job"+params.getJobId());
return false;
}
/**
*Determines if the device is currently on line.
*/
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 mainUIthread.This task creates a
*HTTPUrlConnection,and then downloads the content soft heweb page as an InputStream.
*The InputStream is then converted to a String,which is logged by the
*onPostExecute() method.
*/
private class SimpleDownloadTask extends AsyncTask{
protected JobParameters mJobParam;
@Override
protected String doInBackground(JobParameters...params){
//cache system provided job requirements
mJobParam=params[0];
try{
InputStreamis=null;
//Only display the first 50 characters of the retrieved webpage content.
int len=50;
URL url=new URL("https://www.google.com");
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,"Theresponseis:"+response);
is=conn.getInputStream();
//Convert the input stream toastring
Reader reader=null;
reader=new InputStreamReader(is,"UTF-8");
char[] buffer=new char[len];
reader.read(buffer);
return newString(buffer);
}catch(IOExceptione){
return"Unabletoretrievewebpage.";
}
}
@Override
protected void onPostExecute(Stringresult){
jobFinished(mJobParam,false);
Log.i(LOG_TAG,result);
}
}
}
//模拟通过点击Button触发N个任务,交给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(newView.OnClickListener(){
@Override
publicvoidonClick(Viewv){
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 awakelock.Rather,the
*API will take your networkjobs and execute the min 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 isscheduled here in
*the activity,but the jobit self is executed in MyJobService in the start Job() method.For
*example,to poll your server,you would create the network connection,send your GET
*request,and then process the response all in MyJobService.This allows the JobScheduler API
*to invoke your logic without neededtore start your activity.
*
*For brevity in the sample,we are scheduling the same jobsever alt imes in quick succession,
*but again,try to consider similar task so ccurring over time in your applicationth at can
*afford towait and maybe nefit from batching.
*/
publicvoidpollServer(){
JobScheduler scheduler=(JobScheduler)getSystemService(Context.JOB_SCHEDULER_SERVICE);
for(inti=0;i<10;i++){
JobInfo jobInfo=new JobInfo.Builder(i,mServiceComponent)
.setMinimumLatency(5000)//5seconds
.setOverrideDeadline(60000)//60seconds(forbrevityinthesample)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)//WiFiordataconnections
.build();
mWakeLockMsg.append("Schedulingjob"+i+"!n");
scheduler.schedule(jobInfo);
}
}
}
在移动网络下,最好做到批量执行网络请求,尽量避免频繁的间隔网络请求