美文网首页
Android 进程保活之—— startForeground保

Android 进程保活之—— startForeground保

作者: Batashi | 来源:发表于2018-05-21 11:29 被阅读0次

    一、MainActivity.java

        @Override
        protected void onPause() {
            super.onPause();
    // 这是前提——你的app至少运行了一个service。这里表示当进程不在前台时,马上开启一个service
            Intent intent = new Intent(this, MyService.class);
            startService(intent);
        }
    

    二、MyService.java

    package com.wei.wanandroid.service;
    
    import android.app.Notification;
    import android.app.PendingIntent;
    import android.app.Service;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Build;
    import android.os.IBinder;
    import android.support.v4.app.NotificationCompat;
    import android.util.Log;
    
    import com.wei.wanandroid.activity.MainActivity;
    
    public class MyService extends Service
    {
        private final static String TAG = MyService.class.getSimpleName();
        // 启动notification的id,两次启动应是同一个id
        private final static int NOTIFICATION_ID = android.os.Process.myPid();
        private AssistServiceConnection mServiceConnection;
    
        public MyService() {
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            // 测试线程,判断Service是否在工作
            new Thread(mRunnable).start();
            // 设置为前台进程,降低oom_adj,提高进程优先级,提高存活机率
            setForeground();
    
            return START_STICKY;
    
        }
    
        // 要注意的是android4.3之后Service.startForeground() 会强制弹出通知栏,解决办法是再
        // 启动一个service和推送共用一个通知栏,然后stop这个service使得通知栏消失。
        private void setForeground() {
            if (Build.VERSION.SDK_INT < 18)
            {
                startForeground(NOTIFICATION_ID, getNotification());
                return;
            }
    
            if (mServiceConnection == null)
            {
                mServiceConnection = new AssistServiceConnection();
            }
            // 绑定另外一条Service,目的是再启动一个通知,然后马上关闭。以达到通知栏没有相关通知
            // 的效果
            bindService(new Intent(this, AssistService.class), mServiceConnection, 
                        Service.BIND_AUTO_CREATE);
        }
    
        private class AssistServiceConnection implements ServiceConnection
        {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Service assistService = ((AssistService.LocalBinder)service)
                                                     .getService();
                MyService.this.startForeground(NOTIFICATION_ID, getNotification());
                assistService.startForeground(NOTIFICATION_ID, getNotification());
                assistService.stopForeground(true);
    
                MyService.this.unbindService(mServiceConnection);
                mServiceConnection = null;
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
    
            }
        }
    
        private Notification getNotification()
        {
            Intent intent = new Intent(this, MainActivity.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 
    PendingIntent.FLAG_UPDATE_CURRENT);
            NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "")
                    .setContentTitle("服务运行于前台")
                    .setContentText("service被设为前台进程")
                    .setTicker("service正在后台运行...")
                    .setPriority(NotificationCompat.PRIORITY_MAX)
                    .setWhen(System.currentTimeMillis())
                    .setDefaults(NotificationCompat.DEFAULT_ALL)
                    .setContentIntent(pendingIntent);
            Notification notification = builder.build();
            notification.flags = Notification.FLAG_AUTO_CANCEL;
            return notification;
        }
    
        Runnable mRunnable = new Runnable() {
            @Override
            public void run() {
                while (true)
                {
                    Log.e(TAG, "" + System.currentTimeMillis());
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            stopForeground(true);
        }
    }
    
    

    三、AssistService.java

    package com.wei.wanandroid.service;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.IBinder;
    
    public class AssistService extends Service {
        public AssistService() {
        }
    
        public class LocalBinder extends Binder
        {
            public AssistService getService()
            {
                return AssistService.this;
            }
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return new LocalBinder();
        }
    }
    
    

    四、测试结果
    app退回桌面后(还没调用startForeground):

    shell@libra:/ $ cat proc/29346/oom_adj
    7
    

    app退回桌面后(调用startForeground):

    shell@libra:/ $ cat proc/6338/oom_adj
    2
    

    结论:很明显通过startForeground,oom_adj从7降到2。能把进程优先级提高到接近前台进程的高度。能有效地保活app。

    相关文章

      网友评论

          本文标题:Android 进程保活之—— startForeground保

          本文链接:https://www.haomeiwen.com/subject/vilfjftx.html