当前位置:   article > 正文

Android 原生保活_android 保活

android 保活

目录

方案一、前台服务+Notification

方案二、加入白名单

方案三、双进程守护 + JobScheduler 保活

1、JobService 代码

2、判定服务运行工具类

3、清单文件

4、MainActivity 代码

方案四、使用系统服务的return START_STICKY

方案五、一像素

1、Activity

2.注册清单文件:

3、监听锁屏和解锁通知,不能静态注册广播,只能动态注册:

4、分别在解锁和锁屏时唤醒我的HooliganActivity:

5、在最近使用的列表中隐藏应用

方案六、无声音乐

方案七、推送互相唤醒复活

方案八、app相互拉活


        Android保活众所周知,完全保活除非加入白名单,否则只能保住一段时间。下面一一介绍Android保活方案。由于时间有限,保活方案文章的编写,采用的是逐步完善的方式。在保证内容可用的条件下逐步晚上文字,不足之处还请见谅。完善所有代码后,会写成uni-app插件。

方案一、前台服务+Notification

代码

a、首先在AndroidManifest.xml添加以下权限

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

b、前台服务代码

  1. public class KeepServices extends Service {
  2. private NotificationManager notificationManager;
  3. private String notificationId = "serviceid";
  4. private String notificationName = "servicename";
  5. @Override
  6. public void onCreate() {
  7. super.onCreate();
  8. notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
  9. //创建NotificationChannel
  10. if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
  11. NotificationChannel channel = new NotificationChannel(notificationId, notificationName, NotificationManager.IMPORTANCE_HIGH);
  12. notificationManager.createNotificationChannel(channel);
  13. }
  14. startForeground(1,getNotification());
  15. }
  16. private Notification getNotification() {
  17. Notification.Builder builder = new Notification.Builder(this)
  18. .setSmallIcon(R.mipmap.amin_pic)
  19. .setContentTitle("title")
  20. .setContentText("text");
  21. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
  22. builder.setChannelId(notificationId);
  23. }
  24. Notification notification = builder.build();
  25. return notification;
  26. }
  27. @Override
  28. public int onStartCommand(Intent intent, int flags, int startId) {
  29. new Thread(new Runnable() {
  30. @Override
  31. public void run() {
  32. while (true){
  33. try {
  34. Thread.sleep(2000);
  35. Log.d("Services","====保活服务===数据支持====");
  36. } catch (InterruptedException e) {
  37. e.printStackTrace();
  38. }
  39. }
  40. }
  41. }).start();
  42. return super.onStartCommand(intent, flags, startId);
  43. }
  44. @Nullable
  45. @Override
  46. public IBinder onBind(Intent intent) {
  47. return null;
  48. }
  49. @Override
  50. public void onDestroy() {
  51. super.onDestroy();
  52. }
  53. }

c、在AndroidManifest.xml中注册服务

  1. <service
  2. android:name="com.xiaoya.keepalive.KeepServices"// 找到自己的服务路径
  3. android:enabled="true"
  4. android:exported="true" />

d、启动服务

  1. Intent intent=new Intent(this, KeepServices.class);
  2. startService(intent);

方案二、加入白名单

这里借鉴其他博主的国内厂商白名单跳转工具

  1. public class SettingUtils {
  2. public static void enterWhiteListSetting(Context context) {
  3. try {
  4. context.startActivity(getSettingIntent());
  5. } catch (Exception e) {
  6. context.startActivity(new Intent(Settings.ACTION_SETTINGS));
  7. }
  8. }
  9. private static Intent getSettingIntent() {
  10. ComponentName componentName = null;
  11. String brand = android.os.Build.BRAND;
  12. switch (brand.toLowerCase()) {
  13. case "samsung":
  14. componentName = new ComponentName("com.samsung.android.sm",
  15. "com.samsung.android.sm.app.dashboard.SmartManagerDashBoardActivity");
  16. break;
  17. case "huawei":
  18. componentName = new ComponentName("com.huawei.systemmanager",
  19. "com.huawei.systemmanager.startupmgr.ui.StartupNormalAppListActivity");
  20. break;
  21. case "xiaomi":
  22. componentName = new ComponentName("com.miui.securitycenter",
  23. "com.miui.permcenter.autostart.AutoStartManagementActivity");
  24. break;
  25. case "vivo":
  26. componentName = new ComponentName("com.iqoo.secure",
  27. "com.iqoo.secure.ui.phoneoptimize.AddWhiteListActivity");
  28. break;
  29. case "oppo":
  30. componentName = new ComponentName("com.coloros.oppoguardelf",
  31. "com.coloros.powermanager.fuelgaue.PowerUsageModelActivity");
  32. break;
  33. case "360":
  34. componentName = new
  35. ComponentName("com.yulong.android.coolsafe",
  36. "com.yulong.android.coolsafe.ui.activity.autorun.AutoRunListActivity");
  37. break;
  38. case "meizu":
  39. componentName = new ComponentName("com.meizu.safe",
  40. "com.meizu.safe.permission.SmartBGActivity");
  41. break;
  42. case "oneplus":
  43. componentName = new ComponentName("com.oneplus.security",
  44. "com.oneplus.security.chainlaunch.view.ChainLaunchAppListActivity");
  45. break;
  46. default:
  47. break;
  48. }
  49. Intent intent = new Intent();
  50. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  51. if (componentName != null) {
  52. intent.setComponent(componentName);
  53. } else {
  54. intent.setAction(Settings.ACTION_SETTINGS);
  55. }
  56. return intent;
  57. }
  58. }

方案三、双进程守护 + JobScheduler 保活

参考(【Android 进程保活】应用进程拉活 ( 双进程守护 + JobScheduler 保活 | 成功率最高 | 推荐使用 )-CSDN博客

1、JobService 代码

  1. public class KeepAliveJobService extends JobService {
  2. @Override
  3. public boolean onStartJob(JobParameters params) {
  4. Log.i("KeepAliveJobService", "JobService onStartJob 开启");
  5. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
  6. // 如果当前设备大于 7.0 , 延迟 5 秒 , 再次执行一次
  7. startJob(this);
  8. }
  9. // 判定本地前台进程是否正在运行
  10. boolean isLocalServiceRunning =
  11. ServiceUtils.isServiceRunning(this, LocalForegroundService.class.getName());
  12. if (!isLocalServiceRunning){
  13. startService(new Intent(this, LocalForegroundService.class));
  14. }
  15. // 判定远程前台进程是否正在运行
  16. boolean isRemoteServiceRunning =
  17. ServiceUtils.isServiceRunning(this, RemoteForegroundService.class.getName());
  18. if (!isRemoteServiceRunning){
  19. startService(new Intent(this, RemoteForegroundService.class));
  20. }
  21. return false;
  22. }
  23. @Override
  24. public boolean onStopJob(JobParameters params) {
  25. Log.i("KeepAliveJobService", "JobService onStopJob 关闭");
  26. return false;
  27. }
  28. public static void startJob(Context context){
  29. // 创建 JobScheduler
  30. JobScheduler jobScheduler =
  31. (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
  32. // 第一个参数指定任务 ID
  33. // 第二个参数指定任务在哪个组件中执行
  34. // setPersisted 方法需要 android.permission.RECEIVE_BOOT_COMPLETED 权限
  35. // setPersisted 方法作用是设备重启后 , 依然执行 JobScheduler 定时任务
  36. JobInfo.Builder jobInfoBuilder = new JobInfo.Builder(10,
  37. new ComponentName(context.getPackageName(), KeepAliveJobService.class.getName()))
  38. .setPersisted(true);
  39. // 7.0 以下的版本, 可以每隔 5000 毫秒执行一次任务
  40. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N){
  41. jobInfoBuilder.setPeriodic(5_000);
  42. }else{
  43. // 7.0 以上的版本 , 设置延迟 5 秒执行
  44. // 该时间不能小于 JobInfo.getMinLatencyMillis 方法获取的最小值
  45. jobInfoBuilder.setMinimumLatency(5_000);
  46. }
  47. // 开启定时任务
  48. jobScheduler.schedule(jobInfoBuilder.build());
  49. }
  50. }

2、判定服务运行工具类

  1. public class ServiceUtils {
  2. /**
  3. * 判定 Service 是否在运行
  4. * @param context
  5. * @return
  6. */
  7. public static boolean isServiceRunning(Context context, String serviceName){
  8. if(TextUtils.isEmpty(serviceName)) return false;
  9. ActivityManager activityManager =
  10. (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
  11. // 最多获取 200 个正在运行的 Service
  12. List<ActivityManager.RunningServiceInfo> infos =
  13. activityManager.getRunningServices(200);
  14. // 遍历当前运行的 Service 信息, 如果找到相同名称的服务 , 说明某进程正在运行
  15. for (ActivityManager.RunningServiceInfo info: infos){
  16. if (TextUtils.equals(info.service.getClassName(), serviceName)){
  17. return true;
  18. }
  19. }
  20. return false;
  21. }
  22. }

3、清单文件

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="kim.hsl.two_progress_alive">
  4. <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
  5. <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
  6. <application
  7. android:allowBackup="true"
  8. android:icon="@mipmap/ic_launcher"
  9. android:label="@string/app_name"
  10. android:roundIcon="@mipmap/ic_launcher_round"
  11. android:supportsRtl="true"
  12. android:theme="@style/Theme.Two_Progress_Alive">
  13. <activity android:name=".MainActivity">
  14. <intent-filter>
  15. <action android:name="android.intent.action.MAIN" />
  16. <category android:name="android.intent.category.LAUNCHER" />
  17. </intent-filter>
  18. </activity>
  19. <!-- 本地提权前台服务 Service -->
  20. <service
  21. android:name=".LocalForegroundService"
  22. android:enabled="true"
  23. android:exported="true"></service>
  24. <!-- 本地服务 , API 18 ~ 25 以上的设备, 关闭通知到专用服务 -->
  25. <service
  26. android:name=".LocalForegroundService$CancelNotificationService"
  27. android:enabled="true"
  28. android:exported="true"></service>
  29. <!-- 远程提权前台服务 Service -->
  30. <service
  31. android:name=".RemoteForegroundService"
  32. android:enabled="true"
  33. android:exported="true"
  34. android:process=":remote"></service>
  35. <!-- 远程服务 , API 18 ~ 25 以上的设备, 关闭通知到专用服务 -->
  36. <service
  37. android:name=".RemoteForegroundService$CancelNotificationService"
  38. android:enabled="true"
  39. android:exported="true"
  40. android:process=":remote"></service>
  41. <!-- JobScheduler 拉活 -->
  42. <service
  43. android:name=".KeepAliveJobService"
  44. android:enabled="true"
  45. android:exported="true"
  46. android:permission="android.permission.BIND_JOB_SERVICE"></service>
  47. </application>
  48. </manifest>

4、MainActivity 代码

  1. package kim.hsl.two_progress_alive;
  2. import android.content.Intent;
  3. import android.os.Build;
  4. import android.os.Bundle;
  5. import androidx.appcompat.app.AppCompatActivity;
  6. public class MainActivity extends AppCompatActivity {
  7. @Override
  8. protected void onCreate(Bundle savedInstanceState) {
  9. super.onCreate(savedInstanceState);
  10. setContentView(R.layout.activity_main);
  11. // 通过前台 Service 提升应用权限
  12. // 启动普通 Service , 但是在该 Service 的 onCreate 方法中执行了 startForeground
  13. // 变成了前台 Service 服务
  14. startService(new Intent(this, LocalForegroundService.class));
  15. startService(new Intent(this, RemoteForegroundService.class));
  16. // JobScheduler 拉活
  17. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  18. KeepAliveJobService.startJob(this);
  19. }
  20. }
  21. }

方案四、使用系统服务的return START_STICKY

START_STICKY:

“粘性”。如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。

START_NOT_STICKY:

“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。

START_REDELIVER_INTENT:

重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。

START_STICKY_COMPATIBILITY:

START_STICKY的兼容版本,但不保证服务被kill后一定能重启。

只要 targetSdkVersion 不小于5,就默认是 START_STICKY。 但是某些ROM 系统不会拉活。并且经过测试,Service 第一次被异常杀死后很快被重启,第二次会比第一次慢,第三次又会比前一次慢,一旦在短时间内 Service 被杀死4-5次,则系统不再拉起。

原文链接:Android 给App保活(10种方案)_android app保活_zhang_senlin的博客-CSDN博客

public int onStartCommand(Intent intent, int flags, int startId) {

......

return START_STICKY;

}

优点:利用services自身的api,可靠。

缺点:很多手机厂商已经做限制,导致很多类似华为、小米手机无效。只会重启5次。被系统强制停止也无法重启。

方案五、一像素

参考(Android 传说中的1像素保活大法-面圈网

1、Activity

  1. public class HooliganActivity extends Activity {
  2. private static HooliganActivity instance;
  3. @Override
  4. protected void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6. instance = this;
  7. Window window = getWindow();
  8. window.setGravity(Gravity.LEFT | Gravity.TOP);
  9. WindowManager.LayoutParams params = window.getAttributes();
  10. params.x = 0;
  11. params.y = 0;
  12. params.height = 1;
  13. params.width = 1;
  14. window.setAttributes(params);
  15. }
  16. /**
  17. * 开启保活页面
  18. */
  19. public static void startHooligan() {
  20. Intent intent = new Intent(DWApplication.getAppContext(), HooliganActivity.class);
  21. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  22. DWApplication.getAppContext().startActivity(intent);
  23. }
  24. @Override
  25. protected void onDestroy() {
  26. super.onDestroy();
  27. instance = null;
  28. }
  29. /**
  30. * 关闭保活页面
  31. */
  32. public static void killHooligan() {
  33. if(instance != null) {
  34. instance.finish();
  35. }
  36. }
  37. }

2.注册清单文件:

  1. <activity android:name=".activity.HooliganActivity"
  2. android:configChanges="keyboardHidden|orientation|screenSize|navigation|keyboard"
  3. android:excludeFromRecents="true"
  4. android:exported="false"
  5. android:finishOnTaskLaunch="false"
  6. android:launchMode="singleInstance"
  7. android:theme="@style/HooliganActivityStyle"/>
  1. <style name="HooliganActivityStyle">
  2. <item name="android:windowBackground">@color/transparent</item>
  3. <item name="android:windowContentOverlay">@null</item>
  4. <item name="android:windowIsTranslucent">true</item>
  5. <item name="android:windowNoDisplay">false</item>
  6. <item name="android:windowDisablePreview">true</item>
  7. </style>

3、监听锁屏和解锁通知,不能静态注册广播,只能动态注册:

  1. IntentFilter filter = new IntentFilter();
  2. filter.addAction(Intent.ACTION_SCREEN_ON);
  3. filter.addAction(Intent.ACTION_SCREEN_OFF);
  4. registerReceiver(new BootCompleteReceiver(),filter);

4、分别在解锁和锁屏时唤醒我的HooliganActivity:

  1. public class BootCompleteReceiver extends BroadcastReceiver {
  2. @Override
  3. public void onReceive(Context context, Intent intent) {
  4. if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
  5. HooliganActivity. startHooligan();
  6. } else if(intent.getAction().equals(Intent.ACTION_SCREEN_ON)){
  7. HooliganActivity. killHooligan();
  8. }
  9. }
  10. }

5、在最近使用的列表中隐藏应用

  1. Intent intent = new Intent(Intent.ACTION_MAIN);
  2. intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  3. intent.addCategory(Intent.CATEGORY_HOME);
  4. getAppContext().startActivity(intent);

<code class="language-plaintext hljs">android:excludeFromRecents="true"</code>

至此,整个的保活就结束了 这样你在后台每次锁屏,实际上都会吊起一个一像素的页面,假装app在前台,拥有最高进程优先级。

方案六、无声音乐


<code class="language-plaintext hljs">import android.media.MediaPlayer;
import java.io.File;
import java.io.IOException;
import java.io.FileOutputStream;
import android.util.Base64;
import java.io.FileInputStream;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class MySer extends Service {
    MediaPlayer mediaplayer=null;
    //转base64的音频文件
    String base64 = "AAAAGGZ0eXBtcDQyAAAAAG1wNDFpc29tAAAAKHV1aWRcpwj7Mo5CBahhZQ7KCpWWAAAADDEwLjAuMTgzNjMuMAAAAG5tZGF0AAAAAAAAABAnDEMgBAIBAIBAIBAIBAIBAIBAIBAIBAIBAIBAIBAIBAIBAIBAIBAIBAIBAIBAIBAIBAIBAIBAIBAIBDSX5AAAAAAAAB9Pp9Pp9Pp9Pp9Pp9Pp9Pp9Pp9Pp9Pp9Pp9AAAC/m1vb3YAAABsbXZoZAAAAADeilCc3opQnAAAu4AAAAIRAAEAAAEAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAHBdHJhawAAAFx0a2hkAAAAAd6KUJzeilCcAAAAAgAAAAAAAAIRAAAAAAAAAAAAAAAAAQAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAABXW1kaWEAAAAgbWRoZAAAAADeilCc3opQnAAAu4AAAAIRVcQAAAAAAC1oZGxyAAAAAAAAAABzb3VuAAAAAAAAAAAAAAAAU291bmRIYW5kbGVyAAAAAQhtaW5mAAAAEHNtaGQAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAAMxzdGJsAAAAZHN0c2QAAAAAAAAAAQAAAFRtcDRhAAAAAAAAAAEAAAAAAAAAAAACABAAAAAAu4AAAAAAADBlc2RzAAAAAAOAgIAfAAAABICAgBRAFQAGAAACM2gAAjNoBYCAgAIRkAYBAgAAABhzdHRzAAAAAAAAAAEAAAABAAACEQAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAAYc3RzegAAAAAAAAAAAAAAAQAAAF4AAAAUc3RjbwAAAAAAAAABAAAAUAAAAMl1ZHRhAAAAkG1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXIAAAAAAAAAAAAAAAAAAAAAY2lsc3QAAAAeqW5hbQAAABZkYXRhAAAAAQAAAADlvZXpn7MAAAAcqWRheQAAABRkYXRhAAAAAQAAAAAyMDIyAAAAIWFBUlQAAAAZZGF0YQAAAAEAAAAA5b2V6Z+z5py6AAAAMVh0cmEAAAApAAAAD1dNL0VuY29kaW5nVGltZQAAAAEAAAAOABUA2rD/dVfYAQ==";
    
    @Override
    public void onCreate() {
        super.onCreate();
        
        if(mediaplayer==null){
            new Thread(new Runnable(){

                    @Override
                    public void run() {
                        mediaplayer=new MediaPlayer();
                        try {
                            byte[] mp3SoundByteArray = Base64.decode(base64, Base64.DEFAULT);// 将字符串转换为byte数组
                            File tempMp3 = File.createTempFile("s", ".mp3");
                            tempMp3.deleteOnExit();
                            FileOutputStream fos = new FileOutputStream(tempMp3);
                            fos.write(mp3SoundByteArray);
                            fos.close();
                            FileInputStream fis = new FileInputStream(tempMp3);
                            mediaplayer.setDataSource(fis.getFD());
                            mediaplayer.setLooping(true);
                            mediaplayer.prepareAsync ();//异步准备播放 这部必须设置不然无法播放
                            mediaplayer.start();//开始播放
                        } catch (IllegalStateException e) {
                            System.out.print("出错了="+e);
                        } catch (SecurityException e) {} catch (IOException e) {
                            System.out.print("出错了="+e);
                        } catch (IllegalArgumentException e) {}
                    }
                }).start();

        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        //停止
        mediaplayer.stop();
        mediaplayer=null;
    }
    @Override
    public IBinder onBind(Intent intent) {

        return null;
    }
}</code>

方案七、推送互相唤醒复活

......

方案八、app相互拉活

.......

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/587237
推荐阅读
相关标签
  

闽ICP备14008679号