Android 进程保活之—— startForeground保活

一、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保活)