<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Android性能 之 服務優(yōu)化

          共 8786字,需瀏覽 18分鐘

           ·

          2021-07-14 04:40

          和你一起終身學習,這里是程序員Android

          經典好文推薦,通過閱讀本文,您將收獲以下知識點:

          一、Service 介紹
          二、Service 優(yōu)先級
          三、Service 回收過程
          四、Service 保活方法

          一、Service 介紹

          service:是一個后臺服務,專門用來處理常駐后臺的工作的組件。
          服務的優(yōu)化 主要體驗在兩個方面:一·服務的保活,二·服務后臺對于執(zhí)行任務的集中管理.

          下面我們主要對服務的保活方面進行講解,至于任務集中管理執(zhí)行,在電量優(yōu)化中已經講過,這里就不再累贅。

          開始先來說下我們實現(xiàn)的方式:

          1.提高進程優(yōu)先級
          2.java層雙進程守護
          3.1個像素的Activity保活
          4.JobScheduler輪詢
          5.native層雙進程守護

          今天我們只寫前三種方式,第四種native層雙進程守護將在NDK章節(jié)講解。

          二、Service 優(yōu)先級

          1. 前臺進程

          • Activity已調用onResume()方法

          • Service服務已調用startForeground()

          • 生命周期回調的Service (onCreate() 、onStart()或onDestroy())

          • 正執(zhí)行其onReceive()方法的BroadcastReceiver

          2. 可見進程

          • 不在前臺、但仍對用戶可見的Activity(比如調用其onPause()方法)

          • 綁定到可見(或前臺)Activity 的Service

          3. 服務進程

          • startService()方法啟動的服務,且不屬于上面兩類

          4. 后臺進程

          • 對用戶不可見的 Activity 的進程已調用 Activity 的onStop()方法

          5. 空進程

          • 不含任何活動應用組件的進程

          三、Service 回收過程

          1.應用內存不足,回收進程

          提高進程優(yōu)先級,減少進程oom_adj值,如啟動進程的setForeground()提高進程優(yōu)先級
          當應用程序退到后臺時,釋放占用的資源,因為當oom_adj相同時,優(yōu)先釋放內存消耗大的進程一直在后臺運行的進程一定要輕

          2.系統(tǒng)第三方清理軟件,殺死進程

          使用aidl,實現(xiàn)雙進程守護
          白名單

          3.各大rom廠商在應用退出時,會清理殺死進程

          使用NDK,輪詢查看指定進程是否被殺死,如果殺死fork進程,啟動
          使用JobScheduler,輪詢查看指定進程是否被殺死,如果殺死,啟動

          四、Service 保活方法

          雙進程守護(基于java層)

          這里我們將用到aidl,有不了解的同學可以自己去了解下,我們先來上代碼:

          1.編寫aidl接口

              interface ProcessConnect {

          }

          接口里面什么都沒有,這個只是用來監(jiān)聽是否斷開連接,如果斷開,就代碼啟動服務。

          2.工作服務

          public class MessageService extends Service {

          private String TAG = "MessageService";

          private int ID=0X00022;
          private static Context mContext;

          @Override
          public void onCreate() {
          super.onCreate();
          mContext = this;

          new Thread(new Runnable() {
          @Override
          public void run() {
          while (true) {
          Log.e(TAG, "MessageService====>print");

          try {
          Thread.sleep(5000);
          } catch (InterruptedException e) {
          e.printStackTrace();
          }
          }
          }
          }).start();

          }

          @Override
          public int onStartCommand(Intent intent, int flags, int startId) {
          //assert uri
          String path = "file:///android_asset/xiaoxin.wav";
          Notification.Builder builder = new Notification.Builder(mContext);
          Notification notification = builder
          .setContentText("messageservice")
          .setSmallIcon(R.drawable.ting)
          .setSound(Uri.parse(path))
          .build();

          startForeground(ID,notification);

          bindService(new Intent(MessageService.this,GuardService.class),mServiceConnection,BIND_WAIVE_PRIORITY);

          return START_STICKY;
          }
          public ServiceConnection mServiceConnection = new ServiceConnection() {

          @Override
          public void onServiceConnected(ComponentName name, IBinder service) {
          Log.e(TAG, "MessageService====>onServiceConnected");
          }

          @Override
          public void onServiceDisconnected(ComponentName name) {

          startService(new Intent(MessageService.this,GuardService.class));
          bindService(new Intent(MessageService.this,GuardService.class),mServiceConnection,BIND_WAIVE_PRIORITY);
          }
          };

          @Nullable
          @Override
          public IBinder onBind(Intent intent) {
          return new ProcessConnect.Stub() {

          };
          }
          }

          3.守護服務

              public class GuardService extends Service {
          private Context mContext;
          private int ID=0X00021;
          @Override
          public void onCreate() {
          super.onCreate();
          mContext = this;

          }

          @Override
          public int onStartCommand(Intent intent, int flags, int startId) {
          //assert uri
          String path = "file:///android_asset/xiaoxin.wav";
          Notification.Builder builder = new Notification.Builder(mContext);
          Notification notification = builder
          .setContentText("GuardService")
          .setSmallIcon(R.drawable.ting)
          .setSound(Uri.parse(path))
          .build();

          startForeground(ID,notification);

          bindService(new Intent(GuardService.this,MessageService.class),mServiceConnection,BIND_WAIVE_PRIORITY);

          return START_STICKY;
          }

          @Nullable
          @Override
          public IBinder onBind(Intent intent) {
          return new ProcessConnect.Stub(){

          };
          }

          public ServiceConnection mServiceConnection = new ServiceConnection() {

          @Override
          public void onServiceConnected(ComponentName name, IBinder service) {
          Log.e("GuardService", "GuardService====>onServiceConnected");
          }

          @Override
          public void onServiceDisconnected(ComponentName name) {

          startService(new Intent(GuardService.this,MessageService.class));
          bindService(new Intent(GuardService.this,MessageService.class),mServiceConnection,BIND_WAIVE_PRIORITY);
          }
          };

          }

          從上面兩個服務可以看到,每當一個服務結束,另一個服務就會啟動它,來實現(xiàn)進程不被關閉。

          4.MainActivity開啟服務

              startService(new Intent(this,MessageService.class));
          startService(new Intent(this,GuardService.class));

          5.配置

               <service android:name=".MessageService"></service>
          //新的進程中運行
          <service android:name=".GuardService" android:process=":guardservice"></service>

          主要五步就搞定了,很簡單吧,但是不要高興的太早,因為這種雙進程守護的方法,只能對4.0以下有效,對于4.0以上機型,只能部分有用,這個問題最后再說,我們先來看下使用JobScheduler,輪詢啟動被殺死的進程。

          1個像素的Activity保活

          啟動一個1個像素的Activity,當用戶解鎖以后將這個Activity結束掉(順便同時把自己的核心服務再開啟一次)。被用戶發(fā)現(xiàn)了就不好了。
          重點就是對屏幕進行監(jiān)聽,下面我們來分析代碼:

          1個像素的Activity實現(xiàn):

              Window window = getWindow();
          window.setGravity(Gravity.LEFT|Gravity.TOP);
          LayoutParams params = window.getAttributes();
          params.height = 1;
          params.width = 1;
          params.x = 0;
          params.y = 0;
          window.setAttributes(params);

          對屏幕進行監(jiān)聽

              private void registerListener() {
          IntentFilter filter = new IntentFilter();
          filter.addAction(Intent.ACTION_SCREEN_ON);
          filter.addAction(Intent.ACTION_SCREEN_OFF);
          filter.addAction(Intent.ACTION_USER_PRESENT);
          mContext.registerReceiver(mScreenReceiver, filter);
          }

          JobScheduler

          在android開發(fā)中,會存在這么些場景 : 你需要在稍后的某個時間點或者當滿足某個特定的條件時執(zhí)行一個任務,例如當設備接通電源適配器或者連接到WIFI。幸運的是在API 21 ( Android 5.0,即Lollipop )中,google提供了一個新叫做JobScheduler API的組件來處理這樣的場景。

          當一系列預置的條件被滿足時,JobScheduler API為你的應用執(zhí)行一個操作。與AlarmManager不同的是這個執(zhí)行時間是不確定的。除此之外,JobScheduler API允許同時執(zhí)行多個任務。這允許你的應用執(zhí)行某些指定的任務時不需要考慮時機控制引起的電池消耗。

          下面我們就使用JobScheduler來啟動我們被殺死的服務:

          @TargetApi(Build.VERSION_CODES.LOLLIPOP)
          public class JobWakeUpService extends JobService {

          private JobScheduler service;
          private int JobId=100;
          @Override
          public int onStartCommand(Intent intent, int flags, int startId) {
          JobInfo info = new JobInfo.Builder(JobId,new ComponentName(this,JobWakeUpService.class))
          .setPeriodic(2000)
          .build();

          service = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);

          service.schedule(info);
          return START_STICKY;
          }

          @Override
          public boolean onStartJob(JobParameters params) {
          Log.e("JobWakeUpService", "JobWakeUpService====>print");
          //開始定時任務
          if(!isServiceWork(this,MessageService.class.getName())){
          //
          startService(new Intent(this,MessageService.class));
          }

          return false;
          }

          @Override
          public boolean onStopJob(JobParameters params) {
          //停止
          service.cancel(JobId);
          // service.cancelAll();
          return false;
          }

          private boolean isServiceWork(Context context,String serviceName){
          ActivityManager am= (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
          List<ActivityManager.RunningServiceInforunningServices = am.getRunningServices(100);
          if(runningServices == null){
          return false;
          }
          for (ActivityManager.RunningServiceInfo service : runningServices) {
          String className = service.service.getClassName();
          if(className.equals(serviceName)){
          return true;
          }
          }
          return false;

          }
          }

          我們看到這邊就是使用JobScheduler服務來進行循環(huán)調用我們的JobWakeUpService的onStartJob。

          我們接下來看下配置:

              <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>

          <service android:name=".JobWakeUpService"
          android:enabled="true"
          android:permission="android.permission.BIND_JOB_SERVICE"
          >
          </service>

          調用:

              if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
          startService(new Intent(this, JobWakeUpService.class));
          }

          這個就能實現(xiàn)輪詢查看指定進程是否被殺死,如果殺死,啟動的功能。

          可能你們想問這種方式是否可以解決5.0以上進程不被殺死嗎?我只能遺憾的告訴你,不能,我在華為7.0上的測試,沒有能夠起來。

          我們看了這么多的方式,也不能解決進程不被殺死的情況,那有沒有更好的辦法呢?

          native層雙進程守護

          關于NDK來實現(xiàn)雙進程守護將在ndk文章中講解。

          下載地址:NoDieService-Demo

          原文鏈接:https://www.jianshu.com/p/1d176d1cedb5

          友情推薦:

          Android 開發(fā)干貨集錦

          至此,本篇已結束。轉載網絡的文章,小編覺得很優(yōu)秀,歡迎點擊閱讀原文,支持原創(chuàng)作者,如有侵權,懇請聯(lián)系小編刪除,歡迎您的建議與指正。同時期待您的關注,感謝您的閱讀,謝謝!

          點個在看,方便您使用時快速查找!

          瀏覽 74
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  一本色道无码道 | 爱爱爱网| 欧美色图亚洲第一 | 123好逼| 人人色在线 |