今天写一下用提高app的进程等级来实现应用保活。想看直接调用系统方法保活应用的可以点击Android进程守护,让APP在系统内存中常驻(一)进行跳转。
一:第一种实现思路,创建广播接收者来监听系统关屏亮屏操作。当手机关屏时,显示一个透明的一像素的activity,此时用户时看不见的;当手机亮屏时,把这个activity给finish掉。好了,有了思路就开始实现吧。
1.首先新建一个广播接收者:来判断当前的屏幕状态来进行一些操作。
public class AppBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())){ AppReciver.getInstance().startApp(context); }else { AppReciver.getInstance().finishApp(); } } }
2.创建一个1像素的activity。
@SuppressLint("RtlHardcoded") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_null); //设置1像素 Window window = getWindow(); window.setGravity(Gravity.LEFT | Gravity.TOP); WindowManager.LayoutParams params = window.getAttributes(); params.x = 0; params.y = 0; params.height = 1; params.width = 1; window.setAttributes(params); //用来给单例传过去activity,能让它finish掉。 AppReciver.getInstance().setActivity(this); }
3.为这个活动创建一个空的透明的主题。
<style name="KeepLive" parent="AppTheme"> <item name="windowBackground">@null</item> <item name="android:windowIsTranslucent">true</item> </style>
4.为这个活动修改AndroidManifest中的内容,把它单独放入一个栈中。让他使用刚刚为他创建的主题。
<activity android:name=".NullActivity" android:launchMode="singleInstance" android:theme="@style/KeepLive"/>
5.创建一个单例,用来完成开始和结束活动任务的逻辑操作。
class AppReciver { private static final AppReciver ourInstance = new AppReciver(); private WeakReference<NullActivity> weakReference; private AppReciver() { } static AppReciver getInstance() { return ourInstance; } public void startApp(Context context) { context.startActivity(new Intent(context, NullActivity.class)); } public void registerReceiver(Context context) { AppBroadcastReceiver appBroadcastReceiver = new AppBroadcastReceiver(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("android.intent.action.SCREEN_OFF"); intentFilter.addAction("android.intent.action.SCREEN_ON"); intentFilter.addAction("android.intent.action.USER_PRESENT"); context.registerReceiver(appBroadcastReceiver, intentFilter); } public void finishApp() { if (weakReference != null && weakReference.get() != null) { weakReference.get().finish(); } } public void setActivity(NullActivity activity) { weakReference = new WeakReference(activity); } }
6.注意上面的单例中使用了WeakReference来保存activity。这里为了避免内存泄漏使用了弱引用。最后在活动中调用一下就完成了。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //1.系统拉活service进程 //startService(new Intent(this,StickService.class)); //2.通过jobScheduler拉活 //startJob(); //3.通过bindService,通过ServiceConnection来拉活 //bindService(); //4.通过activity来提升app的进程等级 AppReciver.getInstance().registerReceiver(this); }
二:service提升app的进程等级
1.首先新建一个服务。
public class ForegroundService extends Service { private static final int SERVICE_ID = 1; public ForegroundService() { } @Override public IBinder onBind(Intent intent) { return null; } }
2.如果是安卓4.0以下可以直接构建一个空的通知。安卓8.0以上,通知需要设置channel ,还需要设置通知的重要级别 ,安卓9.0以上,通知会直接显示出来。所以要进行版本的判断,来实现通知的设置方式。4.0以下的可以直接通过下面一行代码调用。
if (Build.VERSION.SDK_INT < 18) { //安卓4.0以下可以直接构建一个空的通知。 //设置成前台服务,并且去除通知栏消息 startForeground(SERVICE_ID,new Notification()); }
3.安卓8.0以下的就需要先设置成前台服务,然后再去通过新的服务去除通知栏的消息。好了,废话不说,直接上代码。
else if (Build.VERSION.SDK_INT < 26) { //设置成前台服务 startForeground(SERVICE_ID,new Notification()); //并且去除通知栏消息 startService(new Intent(this,InnerService.class)); }
4.InnerService直接写一个内部服务就行。在里面进行去除通知栏的消息。
private class InnerService extends Service{ @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { startForeground(SERVICE_ID,new Notification()); stopForeground(true); stopSelf(); return super.onStartCommand(intent, flags, startId); } }
5.下面是这个服务的完整代码。
public class ForegroundService extends Service { private static final int SERVICE_ID = 1; public ForegroundService() { } @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (Build.VERSION.SDK_INT < 18) { //安卓4.0以下可以直接构建一个空的通知。 //设置成前台服务,并且去除通知栏消息 startForeground(SERVICE_ID,new Notification()); } else if (Build.VERSION.SDK_INT < 26) { //设置成前台服务 startForeground(SERVICE_ID,new Notification()); //并且去除通知栏消息 startService(new Intent(this,InnerService.class)); } else { //安卓8.0以上,通知需要设置channel //还需要设置通知的重要级别 //安卓9.0以上,通知会直接显示出来。 NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); if (manager!=null){ NotificationChannel channel = new NotificationChannel("channel","xxx",NotificationManager.IMPORTANCE_NONE); manager.createNotificationChannel(channel); Notification notification = new NotificationCompat.Builder(this,"channel").build(); startForeground(SERVICE_ID,notification); } } return super.onStartCommand(intent, flags, startId); } private class InnerService extends Service{ @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { startForeground(SERVICE_ID,new Notification()); stopForeground(true); stopSelf(); return super.onStartCommand(intent, flags, startId); } } }
6.在活动中启动一下就大功告成了。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //1.系统拉活service进程 //startService(new Intent(this,StickService.class)); //2.通过jobScheduler拉活 //startJob(); //3.通过bindService,通过ServiceConnection来拉活 //bindService(); //4.通过activity来提升app的进程等级 //AppReciver.getInstance().registerReceiver(this); //5.通过Service来提升app的进程等级 startService(new Intent(this,ForegroundService.class)); }