耍流氓式的保活service

news/2024/7/9 22:28:46

QQ为什么一直常驻后台?
(白名单,双进程守护)
应用正在运行,这个时候内存不足回收杀进程

  • 1.提高进程的优先级,其实就是减小进程的p->oomkilladj(越小越重要),如启动Service调用startForeground()尽量提高进程的优先级;
  • 2.当应用退到后台适当释放资源然后降低APP的内存占用量,因为在oom_adj相同的时候,会优先干掉内存消耗大的进程;

双进程守护
MessageService

public class MessageService extends Service {
    private static final String TAG = MessageService.class.getSimpleName();

    @Override
    public void onCreate() {
        super.onCreate();
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    Log.e("TAG", "等待接收消息");
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //提高进程优先级
        //提高进程的优先级,其实就是减小进程的p->oomkilladj(越小越重要),
        // 如启动Service调用startForeground()尽量提高进程的优先级;
        startForeground(1, new Notification());
        //绑定服务
        bindService(new Intent(this, GuardService.class), mConnService, BIND_IMPORTANT);
        return START_STICKY;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new ProcessAidl.Stub() {
        };
    }

    private ServiceConnection mConnService = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //绑定连接
            Toast.makeText(MessageService.this, "建立连接", Toast.LENGTH_LONG).show();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            //解绑   重新启动 绑定服务
            startService(new Intent(MessageService.this, GuardService.class));
            //绑定服务
            bindService(new Intent(MessageService.this, GuardService.class), mConnService, Context.BIND_IMPORTANT);
        }
    };
}

GuardService

public class GuardService extends Service {
    private static final String TAG = GuardService.class.getSimpleName();

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new ProcessAidl.Stub() {
        };
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //提高进程优先级
        //提高进程的优先级,其实就是减小进程的p->oomkilladj(越小越重要),
        // 如启动Service调用startForeground()尽量提高进程的优先级;
        startForeground(1, new Notification());
        //绑定服务
        bindService(new Intent(this, MessageService.class), mConnService, BIND_IMPORTANT);
        return START_STICKY;
    }

    private ServiceConnection mConnService = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //绑定连接
            Toast.makeText(GuardService.this, "建立连接", Toast.LENGTH_LONG).show();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            //解绑   重新启动 绑定服务
            startService(new Intent(GuardService.this, MessageService.class));
            //绑定服务
            bindService(new Intent(GuardService.this, MessageService.class), mConnService, BIND_IMPORTANT);
        }
    };
}

ProcessAidl:空的Aidl

interface ProcessAidl {
}

此时我们可以发现我们软件是有双进程的,我们停止停不了,用了系统自带或者第三方的清理软件,也不会杀我们的进程,但是各大Rom厂商在应用退出的时候会清理杀进程。解决方法可以使用ndk,这里使用电量优化的方法

JobWakeUpService

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class JobWakeUpService extends JobService {
    private final int jobWakeUpId = 1;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        JobInfo.Builder builder = new JobInfo.Builder(jobWakeUpId,
                new ComponentName(this, JobWakeUpService.class));
        builder.setPeriodic(2000);
        // 开启一个轮寻
        JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);

        jobScheduler.schedule(builder.build());
        return START_STICKY;
    }

    @Override
    public boolean onStartJob(JobParameters params) {
        // 开启定时任务,定时轮寻 , 看MessageService有没有被杀死
        // 如果杀死了启动  轮寻onStartJob
        boolean messageServiceAlive = serviceAlive(MessageService.class.getName());
        if (!messageServiceAlive) {
            startService(new Intent(this, MessageService.class));
        }
        return false;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        return false;
    }

    /**
     * 判断某个服务是否正在运行的方法
     *
     * @param serviceName 是包名+服务的类名(例如:net.loonggg.testbackstage.TestService)
     * @return true代表正在运行,false代表服务没有正在运行
     */
    private boolean serviceAlive(String serviceName) {
        boolean isWork = false;
        ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        List<ActivityManager.RunningServiceInfo> myList = manager.getRunningServices(100);
        if (myList.size() < 0) {
            return false;
        }
        for (ActivityManager.RunningServiceInfo info : myList) {
            if (info.service.getClassName().equals(serviceName)) {
                isWork = true;
                return true;
            }
        }
        return isWork;
    }
}

配置manifest.xml文件

   <service
            android:name=".MessageService"
            android:enabled="true"
            android:exported="true" />
        <!--android:process=":guardProgress" 新建一个线程-->
        <service
            android:name=".GuardService"
            android:process=":guardService" />
        <service
            android:name=".JobWakeUpService"
            android:permission="android.permission.BIND_JOB_SERVICE" />

一定要添加权限:<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />


http://www.niftyadmin.cn/n/3648838.html

相关文章

[收藏]说声放弃太容易-Sunny

说声放弃太容易 原创&#xff1a;梁宁[Sunny]( 2004-04-16 14:14:16) 细草穿沙雪半消&#xff0c;吴官烟冷水迢迢。 梅花竹里无人见&#xff0c;一夜吹香过石桥。一个同事辞职了&#xff0c;她辞职的原因是不喜欢同单位的另外一个同事。她跑来和我说她将离去以及必须离去的原因…

如何安装svelte_Svelte的可读写商店入门

如何安装svelteIf you’re familiar with Redux or Vuex, then the Svelte stores offer a similar feature for state management. If your app is getting complicated, then it becomes difficult for components to relay data between themselves. Moving it to a global …

Android URI详解

就Android平台而言&#xff0c;URI主要分三个部分&#xff1a;scheme, authority and path。其中authority又分为host和port。格式如下&#xff1a; scheme://host:port/path 举个实际的例子&#xff1a; content://com.example.project:200/folder/subfolder/etc \---------/ …

Fragment的使用封装

封装类 public class FragmentManagerHelper {// 管理类FragmentManagerprivate FragmentManager mFragmentManager;// 容器布局id containerViewIdprivate int mContainerViewId;/*** 构造函数* param fragmentManager 管理类FragmentManager* param containerViewId 容器布局…

android APN解析

APN整理 前段时间&#xff0c;为公司项目添加APN设置功能。现在做一些整理&#xff0c;作为分享&#xff0c;作为笔记。 APN的字段 不同的手机&#xff0c;他们存放apn相关数据的字段是不一样的&#xff0c;这里表示出来的字段都是他们公有的部分。 publicclass APN { …

Symbian中的iScanCode和iCode

我们知道在Symbian的按键事件处理中使用以下方法:TKeyResponse CMegajoyContainer::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType)这个方法是在CCoeControl(Control base class from which all other controls are derived)中定义的虚函数,其定义如下:Off…

如何在Ubuntu 18.04上使用Apache设置密码身份验证

介绍 (Introduction) As a web administrator, you may find it valuable to restrict some parts of a website from visitors, whether temporarily or on a permanent basis. While web applications may provide their own authentication and authorization methods, you …

Java疑惑点解析(二)

用过C的人都知道,C中有个"拷贝构造函数"的概念。这个概念是为了解决C中把一个对象指针赋值给另外一个对象指针,从而两个指针指向同一块内存区域而提出的。 同样,Java做为一门高级语言,它也无法避免这样的问题。Java中没有"拷贝构造函数"的概念,而是…