Android 5.0以下系统进程守活

来源:互联网 发布:顶级域名的两大类 编辑:程序博客网 时间:2024/05/16 13:41

由于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     0int 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 errorif(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



1 0