android电池电量优化

#android电池电量优化
在09年Google IO大会Jeffrey Sharkey指出android应用的耗电量主要在以下三个方面:

  • 大数据量的传输
  • 不停地在网络间切换
  • 解析大量的文本数据

并提出了相关的优化建议:

  • 在需要网络连接的程序中, 首先检查网络连接是否正常,如果没有网络连接,就不要执行相应的程序
  • 使用效率高的数据格式和解析方法,推荐使用JSON和Protobuf
  • 在进行大数据量下载时,尽量使用GZIP方式下载
  • 其他:回收java对象,特别是较大的java对象,使用reset方法;对定位要求不是太高的话尽量不要使用GPS定位;尽量不要使用浮点运算;获取屏幕尺寸等信息可以使用缓存技术,不需要进行多次请求;使用AlarmManager来定时启动服务替代使用sleep方式的定时任务

作为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!”);
}

优化的建议

  • 任何App包括后台Service应该尽可能减少唤醒CPU的次数
  • 每次唤醒CPU执行的代码应该尽可能少,从而让CPU迅速恢复休眠
  • Wi-Fi比2G、3G更省电
  • 尽量在Wi-Fi下传输数据,在有Wi-Fi的时候做预加载,比如应用中心的zip包、离线资源等
  • 非Wi-Fi下,尽量减少网络访问,每一次后台交互都要考虑是否必须
  • 使用推送,代替循环请求
  • 对于自定义控件,通过canvas.clipRect()来帮助系统识别那些可见的区域,这个方法可以指定一块矩形区域,只有在这个区域内才会被绘制,其他的区域会被忽视
  • 避免嵌套太多层控件
  • 合理使用include、merge
  • 避免大量对象被创建又在短时间内马上被释放
  • 避免在for循环,onDraw中创建对象,无法避免的可以创建对象池,然后在不使用的时候释放
  • 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);
                }
            }
        }
    
  • 在移动网络下,最好做到批量执行网络请求,尽量避免频繁的间隔网络请求

你可能感兴趣的:(实用技能学习)