1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Android Service 性能優(yōu)化

        共 7666字,需瀏覽 16分鐘

         ·

        2024-04-11 09:29

        255fafbe946f6230c51fca2b88408743.webp

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

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

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

        一、Service 介紹

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

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

        開始先來說下我們實現(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)用程序退到后臺時,釋放占用的資源,因為當(dāng)oom_adj相同時,優(yōu)先釋放內(nèi)存消耗大的進(jìn)程一直在后臺運行的進(jìn)程一定要輕

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

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

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

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

        四、Service ?;罘椒?/h2>

        雙進(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ù)就會啟動它,來實現(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)程中運行
        <service android:name=".GuardService" android:process=":guardservice"></service>

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

        1個像素的Activity保活

        啟動一個1個像素的Activity,當(dāng)用戶解鎖以后將這個Activity結(jié)束掉(順便同時把自己的核心服務(wù)再開啟一次)。被用戶發(fā)現(xiàn)了就不好了。
        重點就是對屏幕進(jì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);

        對屏幕進(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ā)中,會存在這么些場景 : 你需要在稍后的某個時間點或者當(dāng)滿足某個特定的條件時執(zhí)行一個任務(wù),例如當(dāng)設(shè)備接通電源適配器或者連接到WIFI。幸運的是在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));
        }

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

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

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

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

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

        下載地址:NoDieService-Demo

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

        友情推薦:

        Android 開發(fā)干貨集錦

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

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

        瀏覽 41
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            巨大阳根挺进美女稚嫩花 | 欧美成人做爱视频 | 日撸撸 | 91久久人澡人妻人人做人人爽97 | 男人操女人在线观看 | 啊灬啊灬啊灬快灬高潮了玉子 | 乖再深一点h别揉了 | 午夜精品久久久久久久99蜜桃乐播 | chinese麻豆videosex | 国产精品911 |