精华内容
下载资源
问答
  • 主要介绍了Android 双进程守护的实现代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • Android实现双进程守护,如何保证Service不被Kill,onStartCommand方法,返回START_STICKY,手动返回START_STICKY,亲测当service因内存不足被kill,当内存又有的时候,service又被重新创建,比较不错,但是不能保证...
  • 【Android 进程保活】应用进程拉活 ( 双进程守护保活 ) https://hanshuliang.blog.csdn.net/article/details/115604667 博客源码快照
  • Android实现双进程守护

    热门讨论 2016-11-15 09:17:59
    详见http://blog.csdn.net/huaxun66/article/details/53158162
  • 博文:http://blog.csdn.net/andrexpert/article/details/53485360 双进程守护Demo
  • 安卓双进程守护

    2016-07-10 18:20:25
    实现安卓的双进程守护,该功能只限学术研究,如果应用于自己的程序,请三思而后行!
  • 它是利用系统的漏洞来启动一个前台的Service进程,与普通的启动方式区别在于,它不会在系统通知栏处出现一个Notification,看起来就如同运行着一个后台Service进程一样。这样做带来的好处就是,用户无法察觉到你运行...
  • 双进程守护

    2016-09-06 10:57:11
    简单的双进程守护,使用了android 5.0的新特性jobservice对app有效的保活。缺点:5.0以上手机难以做到完全保活。
  • 【Android 进程保活】应用进程拉活 ( 双进程守护 + JobScheduler 保活 | 成功率最高 | 推荐使用 ) https://hanshuliang.blog.csdn.net/article/details/115607584 博客源码快照
  • 本源码是根据http://blog.csdn.net/ztemt_sw2/article/details/27101681中整理出来,源码在Android studio 1.5上已编译通过,能正常运行。
  • Android双进程守护

    2017-10-26 23:34:35
    通过定义一个LocalService和RemoteService并且相互绑定,当某个服务即将断开连接的时候启动另外一个服务,并将自己和另外一个服务绑定。为了保险,另外定义一个Jobservice,并在适当时机启动LocalService和Remote...
  • Android 双进程守护

    2016-06-24 11:05:12
    1.实现双进程守护,2,系统清理还是会被杀死,想QQ、微信、他们这些已经被厂家加入白名单了,除非你也去向厂家申明添加白名单(你要有本事哦),3第三方清理软件,像350安全卫士这样的清理软件表面上杀死了,但是...
  • 一、 双进程守护保活 + JobScheduler 原理、 二、 双进程守护保活 + JobScheduler 源码、 1、JobService 代码、 2、判定服务运行工具类、 3、清单文件、 4、MainActivity 代码、 5、运行效果、 三、 源码资源





    一、 双进程守护保活 + JobScheduler 原理



    【Android 进程保活】应用进程拉活 ( JobScheduler 拉活 | JobScheduler 使用流程 | JobService 服务 | 不同版本兼容 | 源码资源 ) 博客中介绍了 JobScheduler 的用法 ;

    【Android 进程保活】应用进程拉活 ( 双进程守护保活 ) 博客中介绍了双进程守护保活用法 ;

    使用 " 双进程守护保活 + JobScheduler " 机制 , 成功率最高 ;


    " 双进程守护保活 + JobScheduler " 整合方法 :

    在 JobService 的 onStartJob 方法中 , 判定 " 双进程守护保活 " 中的双进程是否挂了 , 如果这两个进程挂了 , 就重新将挂掉的进程重启 ;

    判定 Service 进程是否运行 :

        public static boolean isServiceRunning(Context context, String serviceName){
            if(TextUtils.isEmpty(serviceName)) return false;
    
            ActivityManager activityManager =
                    (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    
            // 最多获取 200 个正在运行的 Service
            List<ActivityManager.RunningServiceInfo> infos =
                    activityManager.getRunningServices(200);
    
            // 遍历当前运行的 Service 信息, 如果找到相同名称的服务 , 说明某进程正在运行
            for (ActivityManager.RunningServiceInfo info: infos){
                if (TextUtils.equals(info.service.getClassName(), serviceName)){
                    return true;
                }
            }
            
            return false;
        }
    




    二、 双进程守护保活 + JobScheduler 源码



    大部分代码与 【Android 进程保活】应用进程拉活 ( 双进程守护保活 ) 博客中重复 , 这里只贴出 JobScheduler 相关源码 ;



    1、JobService 代码


    package kim.hsl.two_progress_alive;
    
    import android.app.job.JobInfo;
    import android.app.job.JobParameters;
    import android.app.job.JobScheduler;
    import android.app.job.JobService;
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.os.Build;
    import android.util.Log;
    
    import androidx.annotation.RequiresApi;
    
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public class KeepAliveJobService extends JobService {
        @Override
        public boolean onStartJob(JobParameters params) {
            Log.i("KeepAliveJobService", "JobService onStartJob 开启");
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
                // 如果当前设备大于 7.0 , 延迟 5 秒 , 再次执行一次
                startJob(this);
            }
    
            // 判定本地前台进程是否正在运行
            boolean isLocalServiceRunning =
                    ServiceUtils.isServiceRunning(this, LocalForegroundService.class.getName());
            if (!isLocalServiceRunning){
                startService(new Intent(this, LocalForegroundService.class));
            }
    
            // 判定远程前台进程是否正在运行
            boolean isRemoteServiceRunning =
                    ServiceUtils.isServiceRunning(this, RemoteForegroundService.class.getName());
            if (!isRemoteServiceRunning){
                startService(new Intent(this, RemoteForegroundService.class));
            }
    
            return false;
        }
    
        @Override
        public boolean onStopJob(JobParameters params) {
            Log.i("KeepAliveJobService", "JobService onStopJob 关闭");
            return false;
        }
    
        public static void startJob(Context context){
            // 创建 JobScheduler
            JobScheduler jobScheduler =
                    (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
    
            // 第一个参数指定任务 ID
            // 第二个参数指定任务在哪个组件中执行
            // setPersisted 方法需要 android.permission.RECEIVE_BOOT_COMPLETED 权限
            // setPersisted 方法作用是设备重启后 , 依然执行 JobScheduler 定时任务
            JobInfo.Builder jobInfoBuilder = new JobInfo.Builder(10,
                    new ComponentName(context.getPackageName(), KeepAliveJobService.class.getName()))
                    .setPersisted(true);
    
            // 7.0 以下的版本, 可以每隔 5000 毫秒执行一次任务
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N){
                jobInfoBuilder.setPeriodic(5_000);
    
            }else{
                // 7.0 以上的版本 , 设置延迟 5 秒执行
                // 该时间不能小于 JobInfo.getMinLatencyMillis 方法获取的最小值
                jobInfoBuilder.setMinimumLatency(5_000);
            }
    
            // 开启定时任务
            jobScheduler.schedule(jobInfoBuilder.build());
    
        }
    }
    
    


    2、判定服务运行工具类


    package kim.hsl.two_progress_alive;
    
    import android.app.Activity;
    import android.app.ActivityManager;
    import android.content.Context;
    import android.text.TextUtils;
    
    import org.w3c.dom.Text;
    
    import java.util.List;
    
    public class ServiceUtils {
        /**
         * 判定 Service 是否在运行
         * @param context
         * @return
         */
        public static boolean isServiceRunning(Context context, String serviceName){
            if(TextUtils.isEmpty(serviceName)) return false;
    
            ActivityManager activityManager =
                    (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    
            // 最多获取 200 个正在运行的 Service
            List<ActivityManager.RunningServiceInfo> infos =
                    activityManager.getRunningServices(200);
    
            // 遍历当前运行的 Service 信息, 如果找到相同名称的服务 , 说明某进程正在运行
            for (ActivityManager.RunningServiceInfo info: infos){
                if (TextUtils.equals(info.service.getClassName(), serviceName)){
                    return true;
                }
            }
    
            return false;
        }
    }
    
    


    3、清单文件


    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="kim.hsl.two_progress_alive">
    
        <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    
        <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/Theme.Two_Progress_Alive">
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
    
            <!-- 本地提权前台服务 Service -->
            <service
                android:name=".LocalForegroundService"
                android:enabled="true"
                android:exported="true"></service>
    
            <!-- 本地服务 , API 18 ~ 25 以上的设备, 关闭通知到专用服务 -->
            <service
                android:name=".LocalForegroundService$CancelNotificationService"
                android:enabled="true"
                android:exported="true"></service>
    
            <!-- 远程提权前台服务 Service -->
            <service
                android:name=".RemoteForegroundService"
                android:enabled="true"
                android:exported="true"
                android:process=":remote"></service>
    
            <!-- 远程服务 , API 18 ~ 25 以上的设备, 关闭通知到专用服务 -->
            <service
                android:name=".RemoteForegroundService$CancelNotificationService"
                android:enabled="true"
                android:exported="true"
                android:process=":remote"></service>
    
            <!-- JobScheduler 拉活 -->
            <service
                android:name=".KeepAliveJobService"
                android:enabled="true"
                android:exported="true"
                android:permission="android.permission.BIND_JOB_SERVICE"></service>
    
        </application>
    
    </manifest>
    


    4、MainActivity 代码


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


    5、运行效果


    运行后 , 两个进程成功运行 ;

    即使将启动双进程的代码注释掉 , 也可以成功拉起双进程 ;

    在这里插入图片描述





    三、 源码资源



    源码资源 :

    展开全文
  • android双进程守护,进程很难被杀死demo

    千次下载 热门讨论 2014-12-15 19:18:11
    android双进程守护,进程很难被杀死
  • Windows编程之双进程守护

    千次阅读 2017-12-26 20:25:39
    Windows编程之双进程守护Windows编程之双进程守护 需求分析 设计原理 相关函数 设计详细 方法1 方法2 项目测试情况 方法1 方法2 总结 需求分析设计实现双进程守护程序,当两个进程同时运行时,关闭其中任意一个,另...

    Windows编程之双进程守护


    需求分析

    设计实现双进程守护程序,当两个进程同时运行时,关闭其中任意一个,另一个进程会识别出来并马上打开被关闭的进程。

    设计原理

    相关函数

    CreateEvent( )
    CreateEvent是一个Windows API函数。它用来创建或打开一个命名的或无名的事件对象。如果想为对象指定一个访问掩码,应当使用CreateEventEx函数。
    语法:
    HANDLE CreateEvent(
    LPSECURITY_ATTRIBUTES lpEventAttributes, // 安全属性
    BOOL bManualReset,// 复位方式
    BOOL bInitialState,// 初始状态
    LPCTSTR lpName // 对象名称
    );
    参数:
    lpEventAttributes[输入]
    一个指向SECURITY_ATTRIBUTES结构的指针,确定返回的句柄是否可被子进程继承。如果lpEventAttributes是NULL,此句柄不能被继承。
    bManualReset[输入]
    指定将事件对象创建成手动复原还是自动复原。如果是TRUE,那么必须用ResetEvent函数来手工将事件的状态复原到无信号状态。如果设置为FALSE,当一个等待线程被释放以后,系统将会自动将事件状态复原为无信号状态。
    bInitialState[输入]
    指定事件对象的初始状态。如果为TRUE,初始状态为有信号状态;否则为无信号状态。
    lpName[输入]
    指定事件的对象的名称,是一个以0结束的字符串指针。名称的字符格式限定在MAX_PATH之内。名字是对大小写敏感的。
    如果lpName指定的名字,与一个存在的命名的事件对象的名称相同,函数将请求EVENT_ALL_ACCESS来访问存在的对象。这时候,由于bManualReset和bInitialState参数已经在创建事件的进程中设置,这两个参数将被忽略。如果lpEventAttributes是参数不是NULL,它将确定此句柄是否可以被继承,但是其安全描述符成员将被忽略。
    如果lpName为NULL,将创建一个无名的事件对象。
    如果lpName的和一个存在的信号、互斥、等待计时器、作业或者是文件映射对象名称相同,函数将会失败,在GetLastError函数中将返回ERROR_INVALID_HANDLE。造成这种现象的原因是这些对象共享同一个命名空间。
    终端服务(Terminal Services):名称中可以加入”Global\”或是”Local\”的前缀,这样可以明确的将对象创建在全局的或事务的命名空间。名称的其它部分除了反斜杠( \ ),可以使用任意字符。详细内容可参考Kernel Object Name Spaces。
    返回值:
    如果函数调用成功,函数返回事件对象的句柄。如果对于命名的对象,在函数调用前已经被创建,函数将返回存在的事件对象的句柄,而且在GetLastError函数中返回ERROR_ALREADY_EXISTS。
    如果函数失败,函数返回值为NULL,如果需要获得详细的错误信息,需要调用GetLastError。

    OpenEvent():
    OpenEvent是一个函数,可以用来执行返回事件对象的句柄。
    函数功能:
    打开一个已经存在的命名事件对象
    函数原型
    HANDLE OpenEvent(
    DWORD dwDesiredAccess,
    BOOL bInheritHandle,
    LPCTSTR lpName
    );
    参数说明
    dwDesiredAccess
    指定对事件对象的请求访问权限,如果安全描述符指定的对象不允许要求通过对调用该函数的过程,函数将返回失败。
    该参数必须设置为以下值:
    EVENT_ALL_ACCESS
    指定事件对象所有可能的权限
    bInheritHandle
    指定是否返回的句柄是否继承 。该参数必须设置为false
    lpName
    指向一个以null结束的字符串,即将要打开的事件对象的名字。名称是区分大小写的。
    返回值
    函数执行成功则返回事件对象的句柄;失败则返回NULL,获取错误信息可以使用GetLastError

    WaitForSingleObject( )
    WaitForSingleObject是一种Windows API函数,当等待仍在挂起状态时,句柄被关闭,那么函数行为是未定义的。该句柄必须具有 SYNCHRONIZE 访问权限。
    WaitForSingleObject函数用来检测hHandle事件的信号状态,在某一线程中调用该函数时,线程暂时挂起,如果在挂起的dwMilliseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;如果超时时间已经到达dwMilliseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回。
    DWORD WINAPI WaitForSingleObject(
    __in HANDLE hHandle,
    __in DWORD dwMilliseconds
    );
    hHandle
    对象句柄。可以指定一系列的对象,如Event、Job、Memory resource notification、Mutex、Process、Semaphore、Thread、Waitable timer等。
    dwMilliseconds
    定时时间间隔,单位为milliseconds(毫秒).如果指定一个非零值,函数处于等待状态直到hHandle标记的对象被触发,或者时间到了。如果dwMilliseconds为0,对象没有被触发信号,函数不会进入一个等待状态,它总是立即返回。如果dwMilliseconds为INFINITE,对象被触发信号后,函数才会返回。

    CreateMutex()
    CreateMutex是一个计算机函数,作用是找出当前系统是否已经存在指定进程的实例。如果没有则创建一个互斥体。
    HANDLE CreateMutex(
    LPSECURITY_ATTRIBUTES lpMutexAttributes, // 指向安全属性的指针
    BOOL bInitialOwner, // 初始化互斥对象的所有者
    LPCTSTR lpName // 指向互斥对象名的指针
    );
    返回值:
    Long,如执行成功,就返回互斥体对象的句柄;零表示出错。会设置GetLastError。如果返回的是一个有效句柄,但指定的名字已经存在,GetLastError也会设为ERROR_ALREADY_EXISTS,bInitialOwner的值将会被忽略。如果调用者限制了权限,GetLastError将会返回ERROR_ACCESS_DENIED,这个时候应该使用OpenMutex函数。
    参数:
    lpMutexAttributes SECURITY_ATTRIBUTES
    指定一个SECURITY_ATTRIBUTES结构,或传递零值(将参数声明为ByVal As Long,并传递零值),表示使用不允许继承的默认描述符
    bInitialOwner BOOL,如创建进程希望立即拥有互斥体,则设为TRUE。一个互斥体同时只能由一个线程拥有
    lpName String
    指定互斥体对象的名字。用vbNullString创建一个未命名的互斥体对象。如已经存在拥有这个名字的一个事件,则打开现有的已命名互斥体。这个名字可能不与现有的事件、信号机、可等待计时器或文件映射相符

    OpenMutex()
    OpenMutex函数为现有的一个已命名互斥体对象创建一个新句柄。
    HANDLE OpenMutex(
    DWORD dwDesiredAccess, // access
    BOOL bInheritHandle, // inheritance option
    LPCTSTR lpName // object name
    );
    参数:
    dwDesiredAccess:
    MUTEX_ALL_ACCESS 请求对互斥体的完全访问
    MUTEX_MODIFY_STATE 允许使用 ReleaseMutex 函数
    SYNCHRONIZE 允许互斥体对象同步使用
    bInheritHandle :
    如希望子进程能够继承句柄,则为TRUE
    lpName :
    要打开对象的名字
    返回值:
    如执行成功,返回对象的句柄;零表示失败。

    设计详细

    采用两种方法实现双进程守护。

    方法1.

    创建两个event句柄,使用CreateEvent创建打开事件对象。进入循环监控,如果进程2没有被打开,则使用CreateProcess函数打开进程,并显示其PID,使用WaitForSingleObject函数等待守护的进程被关闭,如果守护的进程被关闭,则Sleep 0.5秒后进入下一次循环,打开守护的进程。
    进程2也使用于进程1同样的原理,两个进程相互守护。(注,编译链接成功后,把工程的Debug文件夹中的exe程序取出,两者分别命名为protect1、protect2,两者需要放在同一个目录下运行)。
    代码:
    守护进程1

    #include <windows.h>
    #include <stdio.h>
    int main()
    {
        HANDLE event1;
        HANDLE event2;
        STARTUPINFO si = { 0 };
        PROCESS_INFORMATION pi = { 0 };
        event1=CreateEvent(NULL, FALSE, TRUE, "Local\\p1");
        while (true)
        {
            if (!(event2 = OpenEvent(EVENT_MODIFY_STATE, FALSE, "Local\\p2")))
            {
                if (!CreateProcess("protect2.exe",
                    NULL,
                    NULL,
                    NULL,
                    NULL,
                    CREATE_NEW_CONSOLE,                                    
                    NULL,
                    NULL,
                    &si,
                    &pi 
                    ))
                {
                    printf("打开守护进程失败!\n");
                }
                else printf("打开守护进程成功!PID:%d \n", pi.dwProcessId);
                WaitForSingleObject(pi.hProcess, INFINITE);
                printf("守护进程被关闭!\n");
                CloseHandle(pi.hProcess);
            }
            CloseHandle(event2);
            Sleep(1000);
        }
        return 0;
    }

    守护进程2:

    #include <windows.h>
    #include <stdio.h>
    int main()
    {
        HANDLE event1;
        HANDLE event2;
        STARTUPINFO si = { 0 };
        PROCESS_INFORMATION pi = { 0 };
        event2 = CreateEvent(NULL, FALSE, TRUE, "Local\\p2");
        while (true)
        {
            if (!(event1 = OpenEvent(EVENT_MODIFY_STATE, FALSE, "Local\\p1")))
            {
                if (!CreateProcess("protect1.exe",
                    NULL,
                    NULL,
                    NULL,
                    NULL,
                    CREATE_NEW_CONSOLE,
                    NULL,
                    NULL,
                    &si,
                    &pi
                    ))
                {
                    printf("打开守护进程失败!\n");
                }
    
                printf("打开守护进程成功!PID:%d \n", pi.dwProcessId);
                WaitForSingleObject(pi.hProcess, INFINITE);
                printf("守护进程被关闭!\n");
                CloseHandle(pi.hProcess);
            }
            CloseHandle(event1);
            Sleep(1000);
        }
        return 0;
    }
    

    方法2:

    本方法使用CreateThread,WaitForSingleObject,CreateMutex与OpenMutex函数
    代码:编写一个DWORD WINAPI函数名为ThreadCheckPro,输入参数为进程名,用来检测守护进程是否被关闭。函数中创建hMutex变量,使用while循环判断能否用OpenMutex打开守护的进程,使用if判断,如果不能打开,意味着守护的进程被关闭,于是使用CreateProcess函数在原目录下创建打开守护的进程,打开成功后再使用WaitForSingleObject监控等待进程被关闭的时候,进程被再次关闭时,关闭pi.hProcess、pi.hThread两个句柄,跳出判断结构,Sleep 0.5秒后进入下一次循环,于是便能再次打开守护的进程。
    程序2原理与程序1 相同。(在VC中代码编译链接成功后,进入两个守护程序工程的Debug文件中找出exe文件,把它们放在同一个目录下并分别命名为test1与test2。)
    守护程序1:

    #include <windows.h>
    #include<stdio.h>
    DWORD WINAPI ThreadCheckProc(LPVOID lParam){
        STARTUPINFO si={sizeof(si)};
        PROCESS_INFORMATION pi={0};
        HANDLE hMutex;
        char *pName=(char *)lParam;
        while(true){
            hMutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,pName);
            if(!hMutex){
                CreateProcess(pName,
                NULL,
                NULL,
                NULL,
                FALSE, 
                CREATE_NEW_CONSOLE, 
                NULL,
                NULL, 
                &si,
                &pi ); 
                WaitForSingleObject( pi.hProcess, INFINITE );
                CloseHandle( pi.hProcess );
                CloseHandle( pi.hThread );
            }
            else{
                CloseHandle(hMutex);
            }
            Sleep(500);
        }
    }
    int main()
    {
        DWORD ThreadId;
        CreateMutex(NULL,TRUE,"test1.exe");
        CreateThread(NULL,0,ThreadCheckProc,(LPVOID *)"test2.exe",0,&ThreadId);
        printf("Protected\n");
        while(1){
        Sleep(500);
        }
        return 0;
    }
    

    守护程序2

    #include <windows.h>
    #include<stdio.h>
    DWORD WINAPI ThreadCheckProc(LPVOID lParam){
        STARTUPINFO si={sizeof(si)};
        PROCESS_INFORMATION pi={0};
        HANDLE hMutex;
        char *pName=(char *)lParam;
        while(true){
            hMutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,pName);
            if(!hMutex){
                CreateProcess(pName,
                NULL,
                NULL,
                NULL, 
                FALSE, 
                CREATE_NEW_CONSOLE, 
                NULL, 
                NULL, 
                &si, 
                &pi ); 
                WaitForSingleObject( pi.hProcess, INFINITE );
                CloseHandle( pi.hProcess );
                CloseHandle( pi.hThread );
            }
            else{
                CloseHandle(hMutex);
            }
            Sleep(500);
        }
    }
    int main()
    {
        DWORD ThreadId;
        CreateMutex(NULL,TRUE,"test2.exe");
        CreateThread(NULL,0,ThreadCheckProc,(LPVOID *)"test1.exe",0,&ThreadId);
        printf("Protected\n");
        while(1){
            Sleep(500);
        }
        return 0;
    }
    

    项目测试情况

    方法1:

    打开protect1程序,protect2被自动打开,并显示守护进程打开成功,进程号为8548
    这里写图片描述
    关闭protect1程序,protect2马上把它再度打开,显示守护进程打开成功,进程号为8200
    这里写图片描述
    再次关闭protect1,protect1被再度打开
    这里写图片描述

    方法2

    打开test1,test2立马被打开,两个进程显示protected,相互守护。
    这里写图片描述
    任意关闭两者之间的一个程序,另一个作为守护进程又马上把被关闭的程序打开。
    这里写图片描述

    总结

    进程守护是保护进程不被错误关闭,保证程序能一直运行的常用手段,同时也可能会被恶意代码所利用,恶意代码可以通过远程线程注入,在合法的程序中为自己设置守护进程,只要守护程序没被关闭,恶意代码就能一直运行。通过这次的双进程守护程序设计实验,我学会了如何使用CreateEvent、OpenEvent、CreateMutex、OpenMutex与CreateProcess、CreateThread这些Windows API函数,成功实现了具有相互守护功能的程序。
    不足之处是,对这些Windows API函数的理解还不是很透彻,只是依据使用说明依次对齐进行参数的设置,并不清楚它们的实现原理和一些错误处理,在以后的学习中,会更加注重Windows编程的基础学习,弄清各种函数的底层原理,以便能更透彻地掌握各种API的用法,能避免更多不必要的错误。

    展开全文
  • android双进程守护(aidl通信)

    千次阅读 2018-07-26 14:34:03
    如果被设置的进程名是以一个冒号开头的,则这个新的进程对于这个应用来说是私有的,当它被需要或者这个服务需要在新进程中运行的时候,这个新进程将会被创建。如果这个进程的名字是以小写字符开头的,则这个服务将...

    该方法不能保证在所有机型上有效,而且除非在必要时,否则不建议写这样的流氓软件。特别是谷歌在android7.0以后对管理加强,想要保活Service其实已经变得不太可能了,谷歌这样做无疑是为了减少流氓软件的数量,这样做也是可取的。

    一、开机广播监听
    Android系统启动完成后会自动发出启动完成广播(android.intent.action.BOOT_COMPLETED),
    所有注册了接收启动完成广播的接收器(BroadcastReceiver)都会收到此广播.
    ①编写一个继承BroadcastReceiver的类,接受系统启动完成广播.

    package com.example.systemtest;
    
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    
    /**
     * 系统启动完成广播接收器
     * #<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
     * @author Lone_Wolf
     */
    public class BootCompletedReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
                //example:启动程序
                Intent start = new Intent(context, MainActivity.class);
                start.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//
                context.startActivity(start);
            }
        }
    }

    ②在AndroidManifest.xml文件里注册广播接收器.

    <receiver android:name="com.example.systemtest.BootCompletedReceiver" >  
        <intent-filter>   
            <!-- 开机广播 -->  
            <action android:name="android.intent.action.BOOT_COMPLETED" />  
        </intent-filter>   
    </receiver>

    ③添加相应权限.

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

    二、android:process属性说明

    在Android应用的声明文件Manifest.xml中有时候会对相关的服务标签设置一个android:process=”:remote”,这个属性有什么作用呢?下面笔者就将自己整理的知识和大家分享。

             在Android的帮助文档中我们可以了解到,一般情况下一个服务没有自己独立的进程,它一般是作为一个线程运行于它所在的应用的进程中。但是也有例外,Android声明文件中的android:process属性却可以为任意组件包括应用指定进程,换句话说,通过在声明文件中设置android:process属性,我们可以让组件(例如Activity, Service等)和应用(Application)创建并运行于我们指定的进程中。下面是相关资料和笔者翻译。

              如果我们需要让一个服务在一个远端进程中运行(而不是标准的它所在的apk的进程中运行),我们可以在声明文件中这个服务的标签中通过android:process属性为其指定一个进程。

              注意:这里选择”remote”这个名字是随意主观的,你能用其他名字来让这个服务在另外的进程中运行。冒号’:’这个前缀将把这个名字附加到你的包所运行的标准进程名字的后面作为新的进程名称。例如:一个应用的包名为com.aoyousatuo.example, 则本例中服务将运行的新进程的名称为com.aoyousatuo.example:remote.(注意,如果声明文件中的组件或者应用没有指定这个属性则默认应用和其组件将相应运行在以其包名命名的进程中).android:process 服务所在进程的名字。通常,一个应用的所有组件都运行在系统为这个应用所创建的默认进程中。这个默认进程是用这个应用的包名来命名的。

            标签的process属性可以设置成和所有组件都不同的默认值。但是这些组件可以通过设置自己的process值来覆写这个默认值,这样可以让你的应用跨多进程运行。

            如果被设置的进程名是以一个冒号开头的,则这个新的进程对于这个应用来说是私有的,当它被需要或者这个服务需要在新进程中运行的时候,这个新进程将会被创建。如果这个进程的名字是以小写字符开头的,则这个服务将运行在一个以这个名字命名的全局的进程中,当然前提是它有相应的权限。这将允许在不同应用中的各种组件可以共享一个进程,从而减少资源的占用。

            例如一个应用运行在进程com.aoyousatuo.example中,android:process属性设置为com.rabbit.run,则新的进程名字为com.rabbit.run.

    三、使用AIDL和.stub

            stub类是为了方便client,service交互而生成出来的代码。
            AIDL(Android Interface Definition Language Android接口定义语言)实现进程间通信,尤其是在涉及多进程并发情况下的进程间通信
            aidl会在gen中自动生成一个同名的IaidlData.java接口文件,该接口文件包含一个抽象类stub,其继承了android.os.Binder、
    实现IaidlData接口故,我们实际需要实现的是Stub抽象类。注意这个Stub抽象类要在生成aidl文件之后,编译一下项目才会产生。

    具体参考:AndroidStudio实现AIDL

    四、完整代码

    1、AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
              package="">
    
        <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
        <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
    
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity>
    
            <service android:name=".LocalService"/>
            <service android:name=".RomoteService" android:process=":romote"/>
    
            <receiver android:name=".BootCompletedReceiver">
                <intent-filter >
                    <action android:name="android.intent.action.BOOT_COMPLETED" />
                    <category android:name="android.intent.category.HOME" />
                </intent-filter>
            </receiver>
    
        </application>
    
    </manifest>

    2、开机广播

    public class BootCompletedReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
                //example:启动程序
                Intent start = new Intent(context, MainActivity.class);
                start.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//
                context.startActivity(start);
            }
        }
    }

    3、AIDL文件

    interface IServiceAidlInterface {
    
        String getServiceName();
    }

    4、本地服务

    public class LocalService extends Service {
        MyBinder binder;
        MyConn conn;
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return binder;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            binder = new MyBinder();
            conn = new MyConn();
        }
    
        class MyBinder extends IServiceAidlInterface.Stub {
            @Override
            public String getServiceName() throws RemoteException {
                return LocalService.class.getSimpleName();
            }
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            show();
            Toast.makeText(LocalService.this, " 本地服务活了", Toast.LENGTH_SHORT).show();
            this.startService(new Intent(LocalService.this,RomoteService.class));
            this.bindService(new Intent(LocalService.this,RomoteService.class),conn, Context.BIND_IMPORTANT);
            return START_STICKY;
        }
    
        class MyConn implements ServiceConnection {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.i("box", "绑定上了远程服务");
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                Log.i("box", "远程服务被干掉了");
                Toast.makeText(LocalService.this, "远程服务挂了", Toast.LENGTH_SHORT).show();
                //开启远程服务
                LocalService.this.startService(new Intent(LocalService.this,RomoteService.class));
                //绑定远程服务
                LocalService.this.bindService(new Intent(LocalService.this,RomoteService.class),conn,Context.BIND_IMPORTANT);
            }
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            //开启远程服务
            LocalService.this.startService(new Intent(LocalService.this,RomoteService.class));
            //绑定远程服务
            LocalService.this.bindService(new Intent(LocalService.this,RomoteService.class),conn,Context.BIND_IMPORTANT);
    
        }
    
        private void show() {
            final Handler handler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    Toast.makeText(LocalService.this, "本地服务正常", Toast.LENGTH_SHORT).show();
                    super.handleMessage(msg);
                }
            };
    
            Timer timer = new Timer();
            TimerTask task = new TimerTask() {
                @Override
                public void run() {
                    Message message = new Message();
                    message.what = 1;
                    handler.sendMessage(message);
                }
            };
            timer.schedule(task, 10000, 10000);
        }
    }

    5、远程服务

    public class RomoteService extends Service {
        MyConn conn;
        MyBinder binder;
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return binder;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            conn = new MyConn();
            binder = new MyBinder();
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            show();
            Toast.makeText(this, " 远程服务活了", Toast.LENGTH_SHORT).show();
            this.bindService(new Intent(this, LocalService.class), conn, Context.BIND_IMPORTANT);
    
            return START_STICKY;
        }
    
        class MyBinder extends IServiceAidlInterface.Stub {
            @Override
            public String getServiceName() throws RemoteException {
                return RomoteService.class.getSimpleName();
            }
        }
    
        class MyConn implements ServiceConnection {
    
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.i("box", "绑定本地服务成功");
                // Toast.makeText(RomoteService.this, "绑定本地服务成功", Toast.LENGTH_SHORT).show();
    
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                Log.i("box", "本地服务被干掉了");
                Toast.makeText(RomoteService.this, "本地服务挂了", Toast.LENGTH_SHORT).show();
    
                //开启本地服务
                RomoteService.this.startService(new Intent(RomoteService.this, LocalService.class));
                //绑定本地服务
                RomoteService.this.bindService(new Intent(RomoteService.this, LocalService.class), conn, Context.BIND_IMPORTANT);
            }
    
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            //开启本地服务
            RomoteService.this.startService(new Intent(RomoteService.this, LocalService.class));
            //绑定本地服务
            RomoteService.this.bindService(new Intent(RomoteService.this, LocalService.class), conn, Context.BIND_IMPORTANT);
    
        }
    
        private void show() {
            final Handler handler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    Toast.makeText(RomoteService.this, "远程服务正常", Toast.LENGTH_SHORT).show();
                    super.handleMessage(msg);
                }
            };
    
            Timer timer = new Timer();
            TimerTask task = new TimerTask() {
                @Override
                public void run() {
                    Message message = new Message();
                    message.what = 1;
                    handler.sendMessage(message);
                }
            };
            timer.schedule(task, 10000, 10000);
        }
    }

    6、MainActivity.java

    public class MainActivity extends ActivityBase {
    
        private ActivityMainBinding mBinding;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            mBinding = ActivityMainBinding.inflate(LayoutInflater.from(this));
            setMainView(mBinding.getRoot());
    
            startService(new Intent(this, LocalService.class));
        }
    }

     

    参考:

    Android Service保活方法总结(不被杀死)双进程守护

    双进程守护

    AndroidStudio实现AIDL

    Android中 .stub类的使用

    展开全文
  • ndk实现双进程守护

    2019-07-16 00:37:42
    ndk实现双进程守护教程(一) 那我们在开发和运行维护app的过程中,应该碰到过例如应用被杀死或者后台服务被回收等,导致的消息无法及时推送传达,那像这种情况下我们很多候选都是发短信啊等等,增加成本的同时也不...

    ndk实现双进程守护教程(一)

    那我们在开发和运行维护app的过程中,应该碰到过例如应用被杀死或者后台服务被回收等,导致的消息无法及时推送传达,那像这种情况下我们很多候选都是发短信啊等等,增加成本的同时也不一定能达到预期的效果。而且一部分社交及时消息类的app这类候选基本都行不通。那这种情况下我们就必要应用保活的问题,当然我们也不可能是在用户明确杀掉应用的情况下,还保留前台页面,那是流氓软件做的事。我们这里做的是服务保活,比如说接收推送消息的服务的保活。

    说到保活,那我们有很多的方式,比如广播,轮询的方式,耗费资源的同时又可能达不到我们需要的效果,往往很轻易就被收拾掉了,这时候我们只能沮丧的望着手机上被杀掉的app沉默,这时候我们来电话了,接完电话突然想到,为什么电话应用没见死过,还有很多的系统服务都没被杀死过,系统应用为什么就杀不死呢?

    我们了解过后发现系统从init一号进程启动开始,系统启动了很多的保活子进程
    init进程是我们android系统最先启动的进程

    父进程是1的都是init启动的进程
    这些init启动的子进程中 名字后面带d (daemon)的就是守护进程了,当然截图只是一部分,

    这些进程间相互监听相互唤醒以一种很巧妙的方式维持住了应用的持续存在,那是一个很复杂的关系,有兴趣的可以在init里面看源码也可以去查相关的资料去了解更多,这个init可以做很多事,比如我们的xpose,很多人觉得这个东西啊,很牛逼,无多不能,其实也是在这个init上面做文章通过替换修改实现自己的目的。

    那我们现在从里面简单的提取出来方案,进程守护来实现保活。那现在很多的进程守护都是在java层调调系统方法开启,配置一下android:process就行,那这种方案比较容易被针对,限制起来也容易。你可能用着用着,哪个版本一升就不好使了,所以我们在native里面做,用c写,系统调linux系统开进程,我们也调linux开进程。

    那我们定了双进程守护,我们两个进程之间怎么才能知道某个被杀掉了,总不能在进程被杀掉的时候喊一声兄弟,我要被干死了吧,这种情况下多半是来不及出声就被灭口了。那我们怎么才能知道了,有人用轮询,我打电话一直问兄弟你挂了没,还好我还活着,,突然有天没人接了,这回应该是挂了。我要救活他。这种方式有点low,也有点耗费资源。那到底要怎么办呢这时候我们就又打开init去找一找,系统居然是用的本地socket的机制来完成的。
    生命周期
    我们可以看到在客户端close的时候我们read()被调用了,这时候我们知道他被干掉了,我们可以救他了。

    哇,一不小心到零点了,不写小说了,直接上代码
    这是native中的方法

    #include <jni.h>
    #include <string>
    #include <unistd.h>
    #include "native-lib.h"
    
    
    
    
    const char *PATH="/data/data/com.zy.serviced/mysock";
    int m_child;
    const char *userId;
    
    void child_do_work() {
        //开始socket 服务端
        if (child_create_channel()){
            child_listen_msg();
        }
    
    }
    
    void child_listen_msg() {
        fd_set rfds;
    
        struct timeval timeout ={3,0};
    
        while(1){
            FD_ZERO(&rfds);
            FD_SET(m_child,&rfds);
            int  r =select(m_child+1,&rfds,NULL,NULL,&timeout);
            LOGE("读取消息前 %d",r);
    
            if (r>0){
                char pkg[256]={0};
    
                if (FD_ISSET(m_child,&rfds)){
                    //接收到阻塞消息
                    int result = read(m_child,pkg, sizeof(pkg));
                    //开启服务
                    execlp("am","am","startservice","--user",userId,"com.zy.serviced/com.zy.serviced.ProcessService",(char*)NULL);
                    break;
                }
            }
        }
    
    }
    
    
    int child_create_channel() {
        int listenFd = socket(AF_LOCAL,SOCK_STREAM,0);
        unlink(PATH);
        struct sockaddr_un addr;
        memset(&addr,0,sizeof(sockaddr_un));
        addr.sun_family=AF_LOCAL;
        strcpy(addr.sun_path,PATH);
    
    
        if (bind(listenFd,(const sockaddr *)&addr, sizeof(sockaddr_un))<0){
            LOGE("绑定错误");
            return 0;
        }
    
        listen(listenFd,5);
    
        int connfd=0;
        while(1){
            if ((connfd=accept(listenFd,NULL,NULL))<0){
                if (errno==EINTR){
                    continue;
                }else{
                    LOGE("读取错误");
                    return 0;
                }
            }
    
            m_child = connfd;
            LOGE("apk父进程连接上了  %d",m_child);
            break;
        }
    
        return 0;
    }
    
    extern "C"
    JNIEXPORT void JNICALL
    Java_com_zy_serviced_Watcher_createWatcher(JNIEnv *env, jobject instance, jstring userId_) {
        userId = env->GetStringUTFChars(userId_, 0);
    
        //开双进程
        pid_t  pid =fork();
        if (pid<0){
    
        } else if (pid == 0){
            //子进程 守护
            child_do_work();
    
    
        } else if (pid>0){
            //父进程
    
        }
    
    
    
    
        env->ReleaseStringUTFChars(userId_, userId);
    }
    
    
    extern "C"
    JNIEXPORT void JNICALL
    Java_com_zy_serviced_Watcher_connectMonitor(JNIEnv *env, jobject instance) {
    
        int socked;
        struct sockaddr_un addr;
       while (1){
           LOGE("客服端 进程开始连接");
           socked=socket(AF_LOCAL,SOCK_STREAM,0);
           if (socked<0){
               LOGE("连接失败");
               return;
           }
    
           memset(&addr,0, sizeof(sockaddr));
           addr.sun_family=AF_LOCAL;
           strcpy(addr.sun_path,PATH);
    
           if (connect(socked,(const sockaddr *)&addr, sizeof(sockaddr_un))<0){
                LOGE("连接失败");
               close(socked);
               sleep(1);
               continue;
           }
            LOGE("连接成功");
           break;
       }
    
    }
    

    主要就是按照图上的步骤我们提供-创建socket->绑定客户端进程->消息监听->直到我们接到客户端服务销毁的阻塞消息-重启客户端服务

    我们的客户端服务在创建的时候就可以调native的方法创建监听服务端守护服务进程,杀死后被守护进程复活。

    测试中我们发现客户端服务被杀死后 轻松复活。

    这里我们只是简单的用两个进程示例在这里耍,守护进程也是可以监听多个客户端进程的。那我们就可以守护多个客户端进程,
    多个产品。
    那如果很不幸的是我们的守护进程被杀掉了怎么办呢,这时候我们是不是需要多个进程来守护呢,那多个被杀掉了呢。
    那我们守护进程之间是不是可以互相监听呢,这种情况下是不是就可以实现我们类似那啥的全家桶套餐了。沉思…

    很多时候时候开发和用户之间都有不同的立场,那我们开发的时候可能需要做一些事,作为用户的时候可能自己都要吐槽。两者兼顾很重要

    展开全文
  • android双进程守护,进程很难被杀死demo
  • NDK双进程守护

    2021-05-10 19:09:41
    NDK层双进程守护系统关键服务杀得死吗?不能!那么系统服务是怎么来的:zygote在Android系统中,所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育(fork)出来的,因为Android系统是基于Linux内核的...
  • Android双进程守护Dnprocessmul.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
  • 实现双进程守护

    千次阅读 2016-11-14 20:13:19
     这里如果需要让自己的服务不被销毁,那么只能使用双进程守护,所以这里也就需要使用到jni,ndk的知识点。  首先说一下怎么让java使用本地的方法。首先在.java文件里面添加如下代码: //...
  • 双进程守护APP保活方案

    千次阅读 2018-07-19 17:32:21
    原地址:http://blog.csdn.net/andrexpert/article/details/53485360 探讨一种新型的双进程守护应用保活方法(转载请声明出处:http://blog.csdn.net/andrexpert/article/details/...
  • C++实现双进程守护

    千次阅读 2019-05-13 21:09:50
    #include"pch.h" #include<iostream>...//创建互斥体对象,守护程序利用OpenMutex()函数检测对方的互斥体对象是否存在,不存在则创建进程 //线程回调函数 //参数:程序名称 DWORDWINAPIThr...
  • 最近在使用高德地图实时获取定位时遇到了个问题,锁屏后一段时间(5~10分钟左右)后程序会被系统杀死,为了保活,特研究了下进程保活机制: 有以下几种常见方式: 1、WakeLock 配合 PowerManager ...
  • ndk层实现双进程守护

    2018-06-24 00:05:14
    在linux 下,利用子进程发起建立Socket 连接,保持主进程达到90%保活率,包含完整C++代码和Java代码,注释详细,可直接用于项目开发
  • Android进程保活拉活视频
  • Android双进程守护service保活

    千次阅读 2016-12-19 23:44:17
    要保证进程不被杀死是不可能的,系统在资源紧缺的情况下回根据进程优先等级杀掉有限等级比较低的进程,所以为了使自己的进程不易于被系统杀死,只能提高进程的优先级,这个进程重要性的层次结构有五个等级,按高到低...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 22,700
精华内容 9,080
关键字:

双进程守护