Android进程保活

本文详细介绍了Android进程保活的三种常见策略:黑色保活、白色保活和灰色保活,包括开启一像素Activity、启动前台Service及双进程互相唤起的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android进程保活

进程划分

前台进程(Foreground process)

用户正在使用的程序,一般系统是不会杀死前台进程的,除非用户强制停止应用或者系统内存不足等极端情况会杀死。

可见进程(Visible process)

用户正在使用,看得到,但是摸不着,没有覆盖到整个屏幕,只有屏幕的一部分可见进程不包含任何前台组件,一般系统也是不会杀死可见进程的,除非要在资源吃紧的情况下,要保持某个或多个前台进程存活

服务进程(Service process)

在内存不足以维持所有前台进程和可见进程同时运行的情况下,服务进程会被杀死

后台进程(Background process)

系统可能随时终止它们,回收内存

空进程(Empty process)

 

 

常见保活手段

黑色保活:开启一像素Act,监测系统提供的广播

白色保活:启动前台Service

灰色保活:双进程互相唤起

黑色保活

开启一个像素的Activity

基本思想:系统一般是不会杀死前台进程的。所以要使得进程常驻,我们只需要在锁屏的时候在本进程开启一个Activity,为了欺骗用户,让这个Activity的大小是1像素,并且透明无切换动画,在开屏幕的时候,把这个Activity关闭掉,所以这个就需要监听系统锁屏广播。

创建1像素activity

public class LiveActivity extends Activity {
​
    public static final String TAG = LiveActivity.class.getSimpleName();
​
    public static void actionToLiveActivity(Context pContext) {
        Intent intent = new Intent(pContext, LiveActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        pContext.startActivity(intent);
    }
​
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate");
        setContentView(R.layout.activity_live);
​
        Window window = getWindow();
        //放在左上角
        window.setGravity(Gravity.START | Gravity.TOP);
        WindowManager.LayoutParams attributes = window.getAttributes();
        //宽高设计为1个像素
        attributes.width = 1;
        attributes.height = 1;
        //起始坐标
        attributes.x = 0;
        attributes.y = 0;
        window.setAttributes(attributes);
​
        ScreenManager.getInstance(this).setActivity(this);
    }
​
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy");
    }
}

为了做的更隐藏,最好设置一下这个Activity的主题

   <style name="LiveStyle">
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowAnimationStyle">@null</item>
        <item name="android:windowNoTitle">true</item>
   </style>

在关闭屏幕的时候把LiveActivity开启,在关屏的时候把LiveActivity关闭。这个通过监听锁屏广播实现。

public class ScreenBroadcastListener {
​
    private Context mContext;
​
    private ScreenBroadcastReceiver mScreenReceiver;
​
    private ScreenStateListener mListener;
​
    public ScreenBroadcastListener(Context context) {
        mContext = context.getApplicationContext();
        mScreenReceiver = new ScreenBroadcastReceiver();
    }
​
    interface ScreenStateListener {
​
        void onScreenOn();
​
        void onScreenOff();
    }
​
    /**
     * screen状态广播接收者
     */
    private class ScreenBroadcastReceiver extends BroadcastReceiver {
        private String action = null;
​
        @Override
        public void onReceive(Context context, Intent intent) {
            action = intent.getAction();
            if (Intent.ACTION_SCREEN_ON.equals(action)) { // 开屏
                mListener.onScreenOn();
            } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { // 锁屏
                mListener.onScreenOff();
            }
        }
    }
​
    public void registerListener(ScreenStateListener listener) {
        mListener = listener;
        registerListener();
    }
​
    private void registerListener() {
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_SCREEN_ON);
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        mContext.registerReceiver(mScreenReceiver, filter);
    }
}

白色保活

开启前台服务

基本思想:前台服务相当于一个没有window的前台activity。所以回收几率会很低。只是会在通知栏有通知显示。

public class ForegroundService extends Service {
​
    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }
​
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        Intent activityIntent = new Intent(this, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(getApplication(), 0, activityIntent, 0);
        Notification notification = new Notification.Builder(getApplication()).setAutoCancel(true).
                setSmallIcon(R.drawable.ic_launcher).setTicker("前台Service启动").setContentTitle("前台Service运行中").
                setContentText("这是一个正在运行的前台Service").setWhen(System.currentTimeMillis()).setContentIntent(pendingIntent).build();
        startForeground(1, notification);
        return START_STICKY;
    }
​
}
​
public class MainActivity extends ActionBarActivity {
​
    Button startService;
    Intent intent;
​
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        startService = (Button)findViewById(R.id.start);
        startService.setOnClickListener(new OnClickListener() {
​
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                intent = new Intent(MainActivity.this, ForegroundService.class);
                startService(intent);
            }
        });
    }
​
    @Override
    protected void onStop() {
        // TODO Auto-generated method stub
        super.onStop();
        stopService(intent);
    }
​
}
​

灰色保活手段

双进程唤起

思路:设计AB两个不同服务进程,A进程的服务轮询检查B进程的服务是否存活,没存活的话将其拉起,同样B进程服务轮询检查A进程服务是否存活,没存活的话也将其拉起

  <service
        android:name=".FirstService"
        android:enabled="true"
        android:exported="true"
        android:process=":first"/>
    <service
​
        android:name=".SecondService"
        android:enabled="true"
        android:exported="true"
        android:process=":secon"/>
    <service
        android:name=".ThirdService"
        android:enabled="true"
        android:exported="true"/>

 

public class FirstService extends Service {
​
    private MyBinder binder; //绑定服务需要Binder进行交互
    private MyConn conn;
​
    @Override
    public IBinder onBind(Intent intent) {
​
        return binder;
    }
​
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    @Override
    public void onCreate() {
        super.onCreate();
        binder = new MyBinder();
        if(conn==null)
            conn = new MyConn();
​
    }
​
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
​
        // 与SecondSevice绑定
        FirstService.this.bindService(new Intent(this,SecondService.class),conn, Context.BIND_IMPORTANT);
    }
​
​
    //使用aidl实现进程通信
​
    class MyBinder extends ProcessService.Stub{
​
        @Override
        public String getServiceName() throws RemoteException {
            return "I am FirstService";
        }
    }
​
    //建立相互绑定时的连接
    class  MyConn implements ServiceConnection {
​
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
​
            Log.i("Info","与SecondService连接成功");
​
        }
​
        //在异常断开的回调方法进行拉起对方服务并绑定
        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Toast.makeText(FirstService.this,"SecondService被杀死",Toast.LENGTH_SHORT).show();
            // 启动FirstService
            FirstService.this.startService(new Intent(FirstService.this,SecondService.class));
            //绑定FirstService
            FirstService.this.bindService(new Intent(FirstService.this,SecondService.class),conn, Context.BIND_IMPORTANT);
        }
    }
}

SecondService的设计和FirstService的设计差不多,都是在onStart中与对方相互绑定,在异常断开时重启对方并绑定。 SecondService多了一层服务进程提权设计(FirstService也可以加上这层设计)

public class SecondService extends Service {
​
    private MyBinder binder;
    private MyConn conn;
​
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return binder;
    }
​
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    @Override
    public void onCreate() {
        super.onCreate();
        binder = new MyBinder();
        if(conn==null)
            conn = new MyConn();
​
    }
​
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
​
        //创建通知栏
        Notification.Builder builder = new Notification.Builder(this);
        builder.setSmallIcon(R.mipmap.ic_launcher);
​
        //显示通知栏,服务进程提权为前台服务。
        startForeground(250, builder.build());//使用id:250标记该通知栏
​
        // 启动第三个服务ThirdService来消除通知栏
        startService(new Intent(this,ThirdService.class));
​
        SecondService.this.bindService(new Intent(this,FirstService.class),conn, Context.BIND_IMPORTANT);
    }
​
    class MyBinder extends ProcessService.Stub{
​
        @Override
        public String getServiceName() throws RemoteException {
            return "I am SecondService";
        }
    }
​
    class  MyConn implements ServiceConnection {
​
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Log.i("Info","与FirtService连接成功"+SecondService.this.getApplicationInfo().processName);
        }
​
        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Toast.makeText(SecondService.this,"FirstService被杀死",Toast.LENGTH_SHORT).show();
            // 启动FirstService
            SecondService.this.startService(new Intent(SecondService.this,FirstService.class));
            //绑定FirstService
            SecondService.this.bindService(new Intent(SecondService.this,FirstService.class),conn, Context.BIND_IMPORTANT);
        }
    }
​
}

 

public class ThirdService extends Service {
​
​
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return null;
    }
​
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
​
        // 被启动后创建相互id的通知栏,并提权服务
        Notification.Builder builder = new Notification.Builder(this);
        builder.setSmallIcon(R.mipmap.ic_launcher);
        startForeground(250, builder.build());
​
        //开启新的线程消除通知栏
        new Thread(new Runnable() {
            @Override
            public void run() {
                SystemClock.sleep(1000);
                stopForeground(true);//停止前台
                NotificationManager manager =
                        (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
                manager.cancel(250); // 消除通知栏
                stopSelf(); // 停止服务
            }
        }).start();
        return super.onStartCommand(intent, flags, startId);
    }
}

最后在MainActivity或其他适当的地方启动FirstService和SecondService这两个服务:

    this.startService(new Intent(this,FirstService.class));
    this.startService(new Intent(this,SecondService.class));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值