<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 Service 性能優(yōu)化

          共 7666字,需瀏覽 16分鐘

           ·

          2024-04-11 09:29

          255fafbe946f6230c51fca2b88408743.webp

          和你一起終身學(xué) 習(xí),這里是程序員Android

          經(jīng)典好文推薦,通過閱讀本文,您將收獲以下知識點(diǎn):

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

          一、Service 介紹

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

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

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

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

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

          二、Service 優(yōu)先級

          1. 前臺進(jìn)程

          • Activity已調(diào)用onResume()方法

          • Service服務(wù)已調(diào)用startForeground()

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

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

          2. 可見進(jìn)程

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

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

          3. 服務(wù)進(jìn)程

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

          4. 后臺進(jìn)程

          • 對用戶不可見的 Activity 的進(jìn)程已調(diào)用 Activity 的onStop()方法

          5. 空進(jìn)程

          • 不含任何活動應(yīng)用組件的進(jìn)程

          三、Service 回收過程

          1.應(yīng)用內(nèi)存不足,回收進(jìn)程

          提高進(jìn)程優(yōu)先級,減少進(jìn)程oom_adj值,如啟動進(jìn)程的setForeground()提高進(jìn)程優(yōu)先級
          當(dāng)應(yīng)用程序退到后臺時,釋放占用的資源,因?yàn)楫?dāng)oom_adj相同時,優(yōu)先釋放內(nèi)存消耗大的進(jìn)程一直在后臺運(yùn)行的進(jìn)程一定要輕

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

          使用aidl,實(shí)現(xiàn)雙進(jìn)程守護(hù)
          白名單

          3.各大rom廠商在應(yīng)用退出時,會清理殺死進(jìn)程

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

          四、Service 保活方法

          雙進(jìn)程守護(hù)(基于java層)

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

          1.編寫aidl接口
                  interface ProcessConnect {

          }

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

          2.工作服務(wù)

              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.守護(hù)服務(wù)

                  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);
          }
          };

          }

          從上面兩個服務(wù)可以看到,每當(dāng)一個服務(wù)結(jié)束,另一個服務(wù)就會啟動它,來實(shí)現(xiàn)進(jìn)程不被關(guān)閉。

          4.MainActivity開啟服務(wù)
                  startService(new Intent(this,MessageService.class));
          startService(new Intent(this,GuardService.class));

          5.配置
                   <service android:name=".MessageService"></service>
          //新的進(jìn)程中運(yùn)行
          <service android:name=".GuardService" android:process=":guardservice"></service>

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

          1個像素的Activity保活

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

          1個像素的Activity實(shí)現(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);

          對屏幕進(jìn)行監(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ā)中,會存在這么些場景 : 你需要在稍后的某個時間點(diǎn)或者當(dāng)滿足某個特定的條件時執(zhí)行一個任務(wù),例如當(dāng)設(shè)備接通電源適配器或者連接到WIFI。幸運(yùn)的是在API 21 ( Android 5.0,即Lollipop )中,google提供了一個新叫做JobScheduler API的組件來處理這樣的場景。

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

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

              @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");
          //開始定時任務(wù)
          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服務(wù)來進(jìn)行循環(huán)調(diào)用我們的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>

          調(diào)用:

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

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

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

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

          native層雙進(jìn)程守護(hù)

          關(guān)于NDK來實(shí)現(xiàn)雙進(jìn)程守護(hù)將在ndk文章中講解。

          下載地址:NoDieService-Demo

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

          友情推薦:

          Android 開發(fā)干貨集錦

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

          點(diǎn)個在看,方便您使用時快速查找!

          瀏覽 41
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <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>
                  俺来也俺去啦欧美www | 成人激情在线视频 | 亚洲不卡在线 | 日本a免费在线观看 | 一级家庭乱伦性淫毛片 |