Android 5.0以下系统进程守活

由于Andoid NDK守护进程只适用于5.0的系统以下,所以分开来写。


#include <android/log.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h> // for opendir(), readdir(), closedir()
#include <sys/stat.h> // for stat()
#include <stdarg.h>

#define BUFFER_LENGTH 1024

#define MAX_TIME 15

#define TAG "monitor"

#define PACKET_NAME "应用的包名"

#define PATH "/data/data/应用的包名"

#define RESTART_PATH "/data/data/应用的包名/restart"

#define SERVICE_NAME "应用的包名/应用的包名.service.MonitorService"

#define RUN_SERVICE "am startservice --user 0 -n 应用的包名/应用的包名.service.MonitorService"

#define LOGE(...) __android_log_print(2,TAG,__VA_ARGS__)

#define PROC_DIRECTORY "/proc/"
#define CASE_SENSITIVE    1
#define CASE_INSENSITIVE  0
#define EXACT_MATCH       1
#define INEXACT_MATCH     0

int main(int argc, char* argv[]) {
	FILE *fp1;
	char ch;

	int count = 0;
	LOGE("start run");

	int pid=fork();

	while (1) {
		if (access(PATH, 0) == -1) {
			LOGE("android unistall,program will quit");
			exit(-1);
		}

		if (access(RESTART_PATH, 0) != -1) {
			LOGE("need restart");
			exit(-1);
		}

		if (count > MAX_TIME) {
			count = 0;

			pid_t pid = GetPIDbyName_Wrapper(PACKET_NAME) ; // If -1 = not found, if -2 = proc fs access error
			if(pid!=-1 && pid!=-2)
			{
				LOGE("process exists ");
			}else
			{
				LOGE("process not exists ");
				myexec(RUN_SERVICE);
			}
		}

		count = count + 1;

		sleep(1);
	}
	return 0;
}

int32_t myexec(const char *cmd) {
	FILE *pp = popen(cmd, "r");
	if (!pp) {
//		LOGE("run cmd fail");
		return -1;
	}
//	char tmp[1024];
//	while (fgets(tmp, sizeof(tmp), pp) != NULL ) {
//		if (tmp[strlen(tmp) - 1] == '\n') {
//			tmp[strlen(tmp) - 1] = '\0';
//		}
//	}
	pclose(pp);
	LOGE("run cmd success");
	return 0;
}

int findProcess(char *processName) {
	FILE *ptr;
	char buff[512];
	char ps[128];
	sprintf(ps, "ps | grep -c %s", processName);
	strcpy(buff, "ABNORMAL");
	if ((ptr = popen(ps, "r")) != NULL) {
		while (fgets(buff, 512, ptr) != NULL ) {
			if (atoi(buff) >= 2) {
				pclose(ptr);
				return 1;
			}
		}
	}
	if (strcmp(buff, "ABNORMAL") == 0) /*ps command error*/
		return 0;
	pclose(ptr);
	return 2;
}

//是不是数字
int IsNumeric(const char* ccharptr_CharacterList)
{
    for ( ; *ccharptr_CharacterList; ccharptr_CharacterList++)
        if (*ccharptr_CharacterList < '0' || *ccharptr_CharacterList > '9')
            return 0; // false
    return 1; // true
}

//intCaseSensitive=0大小写不敏感
int strcmp_Wrapper(const char *s1, const char *s2, int intCaseSensitive)
{
    if (intCaseSensitive)
        return !strcmp(s1, s2);
    else
        return !strcasecmp(s1, s2);
}

//intCaseSensitive=0大小写不敏感
int strstr_Wrapper(const char* haystack, const char* needle, int intCaseSensitive)
{
    if (intCaseSensitive)
        return (int) strstr(haystack, needle);
    else
        return (int) strcasestr(haystack, needle);
}

pid_t GetPIDbyName_implements(const char* cchrptr_ProcessName, int intCaseSensitiveness, int intExactMatch)
{
    char chrarry_CommandLinePath[1000]  ;
    char chrarry_NameOfProcess[1000]  ;
    char* chrptr_StringToCompare = NULL ;
    pid_t pid_ProcessIdentifier = (pid_t) -1 ;
    struct dirent* de_DirEntity = NULL ;
    DIR* dir_proc = NULL ;

    int (*CompareFunction) (const char*, const char*, int) ;

    if (intExactMatch)
        CompareFunction = &strcmp_Wrapper;
    else
        CompareFunction = &strstr_Wrapper;


    dir_proc = opendir(PROC_DIRECTORY) ;
    if (dir_proc == NULL)
    {
        perror("Couldn't open the " PROC_DIRECTORY " directory") ;
        return (pid_t) -2 ;
    }

    // Loop while not NULL
    while ( (de_DirEntity = readdir(dir_proc)) )
    {
        if (de_DirEntity->d_type == DT_DIR)
        {
            if (IsNumeric(de_DirEntity->d_name))
            {
                strcpy(chrarry_CommandLinePath, PROC_DIRECTORY) ;
                strcat(chrarry_CommandLinePath, de_DirEntity->d_name) ;
                strcat(chrarry_CommandLinePath, "/cmdline") ;
                FILE* fd_CmdLineFile = fopen (chrarry_CommandLinePath, "rt") ;  //open the file for reading text
                if (fd_CmdLineFile)
                {
                    fscanf(fd_CmdLineFile, "%s", chrarry_NameOfProcess) ; //read from /proc/<NR>/cmdline
                    fclose(fd_CmdLineFile);  //close the file prior to exiting the routine

                    if (strrchr(chrarry_NameOfProcess, '/'))
                        chrptr_StringToCompare = strrchr(chrarry_NameOfProcess, '/') +1 ;
                    else
                        chrptr_StringToCompare = chrarry_NameOfProcess ;

                    //printf("Process name: %s\n", chrarry_NameOfProcess);
                    //这个是全路径,比如/bin/ls
                    //printf("Pure Process name: %s\n", chrptr_StringToCompare );
                    //这个是纯进程名,比如ls

                    //这里可以比较全路径名,设置为chrarry_NameOfProcess即可
                    if ( CompareFunction(chrptr_StringToCompare, cchrptr_ProcessName, intCaseSensitiveness) )
                    {
                        pid_ProcessIdentifier = (pid_t) atoi(de_DirEntity->d_name) ;
                        closedir(dir_proc) ;
                        return pid_ProcessIdentifier ;
                    }
                }
            }
        }
    }
    closedir(dir_proc) ;
    return pid_ProcessIdentifier ;
}

    //简单实现
    pid_t GetPIDbyName_Wrapper(const char* cchrptr_ProcessName)
    {
            return GetPIDbyName_implements(cchrptr_ProcessName, 0,0);//大小写不敏感
    }
编译此代码生成SO文件,并将SO文件放入资产文件中。

Android Service代码

</pre><p><pre name="code" class="java">import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;



/**
 * Created by liyan on 15/3/9.
 */
public class MonitorService extends Service {

    private static final String PROCESS_NAME = "monitor";

    @Override
    public void onCreate() {
        super.onCreate();
        restartMonitor();
    }

    private void restartMonitor() {
        final File file = new File("/data/data/" + getPackageName() + "/restart");

        if (!file.exists()) {
            file.mkdir();
        }

        new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
            @Override
            public void run() {
                try {
                    file.delete();
//                    //运行监控程序
                    runMonitor();
                } catch (Exception e) {

                }

            }
        }, 1500);
    }

    private void runMonitor() {
        try {
            copy();
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
        runWatcher();

    }

    private void runWatcher() {
        String path = "/data/data/" + getPackageName() + "/files";
        String cmd2 = path + "/" + PROCESS_NAME;
        String cmd3 = "chmod 777 " + cmd2;
        rootCommand(cmd3);
        rootCommand(cmd2);
    }

    public void copy() throws IOException {
        // 看这里,设置你要copy到的路径,下面是我举的一个例子
        File file = new File("/data/data/" + getPackageName() + "/files");
        file.mkdir();

        InputStream is = this.getAssets().open(PROCESS_NAME);
        // 打开文件
        FileOutputStream os = new FileOutputStream(
                "/data/data/" + getPackageName() + "/files/" + PROCESS_NAME);
        byte[] buffer = new byte[1024];
        int count = 0;
        // 将文件拷贝到目的地
        while ((count = is.read(buffer)) > 0) {
            // 写入即拷贝
            os.write(buffer, 0, count);
        }
        is.close();
        os.close();
    }

    public boolean rootCommand(String command) {

        boolean result = false;

        java.lang.Process process = null;

        DataOutputStream outputStream = null;
        try {
            process = Runtime.getRuntime().exec("sh");  //获得shell.
            outputStream = new DataOutputStream(process.getOutputStream());

            outputStream.writeBytes("cd /data/data/" + getPackageName() + "\n");   //保证在command在自己的数据目录里执行,才有权限写文件到当前目录

            outputStream.writeBytes(command + " &\n"); //让程序在后台运行,前台马上返回
            outputStream.writeBytes("exit\n");
            outputStream.flush();
            process.waitFor();

            result = true;
        } catch (Exception e) {
            e.printStackTrace();
            result = false;
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }

        return result;
    }


    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

 

原理就是MonitorService 从资产文件中复制出守护程序到FILES目录,并启动守护Monitor,Monitor负责15秒检查一下主进程是否被杀死,如果被杀死,则重新启动MonitorService



  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值