【Android】锁屏后应用保活、拉活、双进程守护 您所在的位置:网站首页 手机锁屏句子霸气 【Android】锁屏后应用保活、拉活、双进程守护

【Android】锁屏后应用保活、拉活、双进程守护

2024-01-18 06:51| 来源: 网络整理| 查看: 265

最近在使用高德地图实时获取定位时遇到了个问题,锁屏后一段时间(5~10分钟左右)后程序会被系统杀死,为了保活,特研究了下进程保活机制。

0、基本操作和概念

针对root过的手机,可以通过下列命令查看内存阈值:

adb shell su cat /sys/module/lowmemorykiller/parameters/minfree 会出现6个数字,从小到大

某个数字 * 4KB / 1024KB = 某某MB; 这里的4kb是Linux中一页(one page)的大小; 得到的某某MB就是当系统内存小于某某M的时候,就杀死某些等级的进程。—俗称内存阈值

6个等级分别对应: 前台进程——可见进程——服务进程——后台进程——空进程

1、WakeLock 配合 PowerManager

从源头上把控,不让界面锁屏。

https://blog.csdn.net/IO_Field/article/details/49591429

WakeLock mWakeLock; //申请设备电源锁 public static void acquireWakeLock(Context context) { if (null == mWakeLock) { PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE, "WakeLock"); if (null != mWakeLock) { mWakeLock.acquire(); } } } //释放设备电源锁 public static void releaseWakeLock() { if (null != mWakeLock) { mWakeLock.release(); mWakeLock = null; }

此法于我无效,继续探索。

2、后台播放无声音乐

这个方法在持续进行位置获取上使用过了,有效,但是仍不能保证我的主进程活着,主进程挂了,音乐播放自然也无效了。

3、1像素Activity保活

OnePixelReceiver.java

package com.jsc4.androidcppsafe.onePixelKeepLive; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; /** * 监听屏幕状态的广播 */ public class OnePixelReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { //屏幕关闭启动1像素Activity Intent it = new Intent(context, OnePixelActivity.class); it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(it); } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { //屏幕打开 结束1像素 context.sendBroadcast(new Intent("finish")); Intent main = new Intent(Intent.ACTION_MAIN); main.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); main.addCategory(Intent.CATEGORY_HOME); context.startActivity(main); } } }

OnePixelActivity.java

package com.jsc4.androidcppsafe.onePixelKeepLive; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.os.PowerManager; import android.util.Log; import android.view.Gravity; import android.view.Window; import android.view.WindowManager; /** * Created by Administrator on 2017/7/10. */ public class OnePixelActivity extends Activity { private BroadcastReceiver endReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //设置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); //结束该页面的广播 endReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { finish(); } }; registerReceiver(endReceiver, new IntentFilter("finish")); //检查屏幕状态 checkScreen(); } @Override protected void onResume() { super.onResume(); checkScreen(); Log.i("djtest", "OnePixelActivity: onResume"); } @Override protected void onStop() { super.onStop(); Log.i("djtest", "OnePixelActivity: onStop"); } @Override protected void onDestroy() { super.onDestroy(); Log.i("djtest", "OnePixelActivity: onDestroy"); } /** * 检查屏幕状态 isScreenOn为true 屏幕“亮”结束该Activity */ private void checkScreen() { PowerManager pm = (PowerManager) OnePixelActivity.this.getSystemService(Context.POWER_SERVICE); boolean isScreenOn = pm.isScreenOn(); if (isScreenOn) { finish(); } } }

在MainActivity.java的onCreate中:

//注册监听屏幕开启和关闭的广播 OnePixelReceiver mOnepxReceiver = new OnePixelReceiver(); 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"); registerReceiver(mOnepxReceiver, intentFilter); 4、双服务保活

参考: https://github.com/linliangliang/TwoProcess https://www.cnblogs.com/lulj/p/7161317.html

(1)在main文件夹上右键,新建AIDL文件IMyAidlInterface.aidl:

// IMyAidlInterface.aidl package com.jsc4.androidcppsafe; // Declare any non-default types here with import statements interface IMyAidlInterface { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ // void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, // double aDouble, String aString); String getServiceName(); }

(2)在java文件夹下新建KeepServiceAlive文件夹,下面创建3个文件: 注意:必须点了运行工程,才能自动导入IMyAidlInterface类。 LocalService.java

package com.jsc4.androidcppsafe.KeepServiceAlive; import android.app.Service; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import com.jsc4.df.IMyAidlInterface; import java.util.Timer; import java.util.TimerTask; /** * Created by lenovo on 2019/8/5. */ public class LocalService extends Service { private final static String TAG = LocalService.class.getName(); private static int count = 0; private static Timer timer = null; private MyBinder mBinder; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { IMyAidlInterface iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service); try { Log.i("LocalService", "connected with " + iMyAidlInterface.getServiceName()); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { if (Constans.INSTANCE.isOpenServiceDefend == 1) { Log.i(TAG, "链接断开,重新启动 RemoteService......"); startService(new Intent(LocalService.this, RemoteService.class)); bindService(new Intent(LocalService.this, RemoteService.class), connection, Context.BIND_IMPORTANT); } } }; public LocalService() { } @Override public void onCreate() { super.onCreate(); if (timer == null) { timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { Log.i(TAG, "--" + count++); } }, 0, 1000); } } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (Constans.INSTANCE.isOpenServiceDefend == 1) { Log.i(TAG, "本地服务启动......"); startService(new Intent(LocalService.this, RemoteService.class)); bindService(new Intent(LocalService.this, RemoteService.class), connection, Context.BIND_IMPORTANT); } return START_STICKY; } @Override public IBinder onBind(Intent intent) { mBinder = new MyBinder(); return mBinder; } private class MyBinder extends IMyAidlInterface.Stub { @Override public String getServiceName() throws RemoteException { return LocalService.class.getName(); } } @Override public void onDestroy() { // TODO 自动生成的方法存根 super.onDestroy(); try { if (timer != null) { timer.cancel(); timer=null; } unbindService(connection); } catch (Exception e) { System.exit(0); } } }

RemoteService.java

package com.jsc4.androidcppsafe.KeepServiceAlive; import android.app.Service; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import android.widget.Toast; import com.jsc4.df.IMyAidlInterface; import java.util.Timer; import java.util.TimerTask; /** * Created by lenovo on 2019/8/5. */ public class RemoteService extends Service { private MyBinder mBinder; private static Timer timer = null; private static int count = 0; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { IMyAidlInterface iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service); try { Log.i("RemoteService", "connected with " + iMyAidlInterface.getServiceName()); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { if (Constans.INSTANCE.isOpenServiceDefend == 1) { Toast.makeText(RemoteService.this, "链接断开,重新启动 LocalService", Toast.LENGTH_LONG).show(); startService(new Intent(RemoteService.this, LocalService.class)); bindService(new Intent(RemoteService.this, LocalService.class), connection, Context.BIND_IMPORTANT); } } }; public RemoteService() { } @Override public void onCreate() { super.onCreate(); if (timer == null) { timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { Log.i("RemoteService", "==" + count++); } }, 0, 2000); } } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (Constans.INSTANCE.isOpenServiceDefend == 1) { Log.i("RemoteService", "RemoteService 启动..."); bindService(new Intent(this, LocalService.class), connection, Context.BIND_IMPORTANT); } return START_STICKY; } @Override public IBinder onBind(Intent intent) { mBinder = new MyBinder(); return mBinder; } private class MyBinder extends IMyAidlInterface.Stub { @Override public String getServiceName() throws RemoteException { return RemoteService.class.getName(); } } @Override public void onDestroy() { // TODO 自动生成的方法存根 super.onDestroy(); try { if (timer != null) { timer.cancel(); timer=null; } unbindService(connection); } catch (Exception e) { System.exit(0); } } }

Constans.java

package com.jsc4.androidcppsafe.KeepServiceAlive; /** * Created by lenovo on 2019/8/5. */ public enum Constans { //枚举类型实现单例 INSTANCE; public static int openServiceDefend = 1; public static int stopServiceDefend = 0; public static int isOpenServiceDefend = 1;//是否开启进程守护,默认开启 public static void setIsOpenServiceDefend(int isOpenServiceDefend) { Constans.isOpenServiceDefend = isOpenServiceDefend; } }

(3)在AndroidMenifest.xml中添加:

(4)在MainActivity.java中:

//******************************************************************************************************************************************** // 双进程保活机制 相关函数 //******************************************************************************************************************************************** private void startBackService() { startService(new Intent(this, LocalService.class)); } private void stopBackService() { stopService(new Intent(this, LocalService.class)); } private void stopRemoteService() { stopService(new Intent(this, RemoteService.class)); } private void endAllService() { Constans.INSTANCE.isOpenServiceDefend = Constans.INSTANCE.stopServiceDefend;//结束进程守护 stopRemoteService(); stopBackService(); } 在oncreate里,添加: // 启动双进程保活机制 startBackService(); 在ondestroy里,添加: endAllService();// 结束双进程守护 5、前台服务保活

这是我重点想说的功能,该功能亲测有效。 注意:API>26后无法隐藏通知。

ForegroundService.java

package com.jsc4.androidcppsafe.ForegroundServiceKeepLive; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.Service; import android.content.Intent; import android.os.Build; import android.os.IBinder; import android.util.Log; import androidx.annotation.Nullable; import androidx.core.app.NotificationCompat; import javax.security.auth.login.LoginException; public class ForegroundService extends Service { private static final int SERVICE_ID = 1; @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); Log.i("djtest", "ForegroundService: 前台服务创建了"); if(Build.VERSION.SDK_INT // 4.3-7.0 startForeground(SERVICE_ID, new Notification()); startService(new Intent(this, InnerService.class)); }else{ // 8.0及以上 NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); NotificationChannel channel = new NotificationChannel("channel", "andy", NotificationManager.IMPORTANCE_HIGH); manager.createNotificationChannel(channel); Notification notification = new NotificationCompat.Builder(this, "channel").build(); startForeground(SERVICE_ID, notification); } } public static class InnerService extends Service{ @Override public void onCreate() { super.onCreate(); Log.i("djtest", "ForegroundService: InnerService服务创建了"); startForeground(SERVICE_ID, new Notification()); stopSelf(); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } } }

AndroidMenifest.xml

MainActivity.java的oncreate中:

startService(new Intent(this, ForegroundService.class)); 6、自启动管理

这是纯粹手机上设置。 将启动管理中的你的APP选择为手动控制。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有