Android进程保活主流方案

window.setAttributes(params);

//KeepAliveManager中的保活Activity初始化为本Activity
KeepAliveManager.getInstance().setKeepLiveActivity(this);
}

@Override
protected void onStart() {
Log.d(MainActivity.TAG, “OnePieceActivity onStart”);
super.onStart();
}

@Override
protected void onRestart() {
Log.d(MainActivity.TAG, “OnePieceActivity onRestart”);
super.onRestart();
}

@Override
protected void onStop() {
Log.d(MainActivity.TAG, “OnePieceActivity onStop”);
super.onStop();
}

@Override
protected void onDestroy() {
Log.d(MainActivity.TAG, “OnePieceActivity onDestroy”);
super.onDestroy();
}
}

MainActivity :主要用于控制广播的注册与注销。

package com.zyc.onepiece;

import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
public static String TAG = “MyLog”;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(MainActivity.TAG, “MainActivity onCreate”);

KeepAliveManager.getInstance().registerKeepLiveReceiver(this);
}

@Override
protected void onStart() {
Log.d(MainActivity.TAG, “MainActivity onStart”);
super.onStart();
}

@Override
protected void onRestart() {
Log.d(MainActivity.TAG, “MainActivity onRestart”);
super.onRestart();
}

@Override
protected void onStop() {
Log.d(MainActivity.TAG, “MainActivity onStop”);
super.onStop();
}

@Override
protected void onDestroy() {
KeepAliveManager.getInstance().unregisterKeepLiveReceiver(this);
super.onDestroy();
}
}

运行,发现在笔者的一加6T(Android 10)下应用内熄屏可以拉起1像素保活Activity,但按Home回到主页后,再熄屏虽然可以接到广播,但无法拉起Activity:

设置前台Service

本方案原理是拥有前台Service的进程将拥有更高的优先级,也就更难被回收掉。注意:部分Android版本前台Service会在顶部通知栏露出“马脚”:

可以试着在前台Service创建通知后立马清除它来隐藏自己。利用相同id前台Service会使用同一条通知的特性,创建一个与前台Service有相id的“替罪羊”前台Service,然后结束它,这样通知会被随之清除,但原本的Service可以继续工作。

项目结构如下。

AndroidManifest.xml

//不加该权限会报错:java.lang.SecurityException: Permission Denial: startForeground from pid=XXX, uid=XXX requires android.permission.FOREGROUND_SERVICE


ForegroundService :模拟工作的(前台)线程,如有必要会开启ScapegoatService来清除通知栏通知。由于缺乏更多高版本系统样本,Android 8.0以上部分可能不靠谱,不过推荐还是老老实实按谷歌要求发出通知为妙。

package com.zyc.foregroundservice;

import android.app.Notification;
import android.app.Service;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;

import androidx.annotation.RequiresApi;

import java.util.Timer;
import java.util.TimerTask;

public class ForegroundService extends Service {
private static final int SERVICE_ID = 1;
private Timer timer;
private TimerTask timerTask;
public static int count;

public ForegroundService() {
}

@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public void onCreate() {
super.onCreate();
Log.d(MainActivity.TAG, “创建前台服务”);
}

@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
startTask();

//判断版本
if (Build.VERSION.SDK_INT < 18) {//Android4.3以下版本
//直接调用startForeground即可,不会在通知栏创建通知
startForeground(SERVICE_ID, new Notification());

} else if (Build.VERSION.SDK_INT < 24) {//Android4.3 - 7.0之间
Intent scapegoatIntent = new Intent(this, ScapegoatService.class);
startService(scapegoatIntent);

} else {//Android 8.0以上
//经测试,本人的一加6T(Android 10)这样写并不会在通知栏创建通知,其他机型与版本效果仍需考证
startForeground(SERVICE_ID, new Notification());
}
return START_STICKY;
}

/**

  • 开启定时任务,count每秒+1
    */
    private void startTask() {
    timer = new Timer();
    timerTask = new TimerTask() {
    @Override
    public void run() {
    Log.d(MainActivity.TAG, "服务运行中,count: " + count);
    count++;
    }
    };
    timer.schedule(timerTask, 0, 1000);
    }

/**

  • 结束定时任务
    */
    private void stopTask() {
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值