标签:
首先介绍一下android的进程. Android 进程分为两种 :其一,java层的进程,也就是在虚拟机里运行的进程,他们的父进程是zygote进程,我们平时调用的AM里面的类似getrunningprocess()方法,返回的就是这类进程信息,这类进程很容易被杀死。其二,native层的原生进程 也就是linux c的进程,这类进程比较安全,其中父进程是init进程的更加安全,很难杀死,在linux里叫守护进程,像surfaceflinger(控制界面呈现)进程,一旦启动会在底层一直运行。
那么 我们的目的就是要写一个守护进程 实时监视自己app java层进程的情况 如果被杀死 就立即创建。
首先是最重要的守护程序代码 linuxC的 带注释
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <dirent.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> /** *守护进程的名字"/proc/pid/status"文件的第一行 linux内核把所有进程信息的节点映射在了"/proc"下 *注意不同android版本 status里进程名字格式可能不一样 *楼主的4.0.3是下面这行 具体的自己到/proc里看一下 **/ char *procdeam = "Name: com.gy.textndk"; //判断进程是否还在运行 int ifprocrun(char *rootpath) { DIR *dir; struct dirent *ptr; //遍历文件夹需要dirent结构体 int bufsize = strlen(procdeam); if((dir = opendir(rootpath)) == NULL) { perror("dir opened failed\n"); exit(1); } //遍历"/proc"下所有文件夹 while((ptr = readdir(dir)) != NULL) { if(ptr->d_type == 4) { char path[128]; memset(path,'\0',sizeof(path)); strcpy(path,rootpath); strcat(path,"/"); strcat(path,ptr->d_name); strcat(path,"/status"); //判断是否存在"status" 文件 if(access(path,F_OK) != -1) { int fd = open(path,O_RDONLY); char tmp_buf[bufsize]; read(fd,tmp_buf,bufsize); close(fd); printf(tmp_buf,"\n"); //判断进程名是否相等 if(strcmp(tmp_buf,procdeam) == 0) { printf("-----------------proc is running------------------\n"); return 1; } } } } return 0; } int main() { int i; int fd; //1.创建子进程,结束父进程,子进程由init接管成为守护进程 pid_t pid = fork(); if(pid<0) exit(1); else if(pid>0) exit(0); //设置新的 session setsid(); //2.关闭所有fd管道 for(i=0;i<=48608;i++) { close(i); } //3.改变工作目录到跟文件夹 chdir("/"); //4.umask umask(0); //5.do sth while(1) { if(ifprocrun("/proc") == 0) { //调用app_process 的命令 "com.gy.Autostart_Activity"这个实在manifest里注册的 intent-filter action //自己定义 这样AMS才能根据action启动你app组件 类似注册表 system("am start -a com.gy.Autostart_Activity"); } sleep(10); //10s判断一次 自己定 } }上面这个程序不能用arm-linux-gcc编译 因为不支持 android新版的 程序调用接口,用 ndk-build命令编译 源码放在名叫的jni目录下
接下来就是实现把编译好的linux
c守护程序打包进apk并在安装时将其释放到data目录下,便于运行。
首先将编译好的linux
c程序放进assets文件夹
下面就是java层释放assets资源文件并且运行的代码,涉及jni
package com.gy.textndk; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import android.app.Activity; import android.content.Context; import android.util.Log; import android.widget.TextView; import android.os.Bundle; public class HelloJni extends Activity { /** Called when the activity is first created. */ private static String TAG = "gy"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /* Create a TextView and set its content. * the text is retrieved by calling a native * function. */ TextView tv = new TextView(this); tv.setText( stringFromJNI() ); setContentView(tv); StringBuilder sb = new StringBuilder(); sb.append(getAppPrivateDir(this)).append("/gyarmdeomproc"); copyAsset(HelloJni.this, "gyarmdeomproc", sb.toString()); startproc(); } /* A native method that is implemented by the * 'hello-jni' native library, which is packaged * with this application. */ public native String stringFromJNI(); /* This is another native method declaration that is *not* * implemented by 'hello-jni'. This is simply to show that * you can declare as many native methods in your Java code * as you want, their implementation is searched in the * currently loaded native libraries only the first time * you call them. * * Trying to call this function will result in a * java.lang.UnsatisfiedLinkError exception ! */ public native String unimplementedStringFromJNI(); public native int startproc(); /* this is used to load the 'hello-jni' library on application * startup. The library has already been unpacked into * /data/data/com.example.hellojni/lib/libhello-jni.so at * installation time by the package manager. */ static { System.loadLibrary("hello-jni"); } //文件复制 public static boolean copyStream(InputStream in, OutputStream out) { Log.d(TAG, "copyStream("+ in + " ," + out+ ")"); try { byte[] buf = new byte[8192]; int len; while ((len = in.read(buf)) > 0) out.write(buf, 0, len); } catch (Exception e) { e.printStackTrace(); return false; } return true; } //获得app私有文件夹路径 public static String getAppPrivateDir(Context ctx) { File dataDir = ctx.getDir("data", Context.MODE_PRIVATE); return dataDir.getAbsolutePath(); } //拷贝assets资源文件到data私有文件夹下 public static boolean copyAsset(Context ctx, String assetFile, String saveToFile) { Log.d(TAG, "copyAssets(" + assetFile + " -> " + saveToFile); File outputFile = new File(saveToFile); if (outputFile.exists()) { return true; } // init output stream(file) OutputStream out; try { out = new FileOutputStream(outputFile); } catch (FileNotFoundException e1) { e1.printStackTrace(); return false; } boolean copyResult = false; InputStream in = null; try { in = ctx.getAssets().open(assetFile); copyResult = copyStream(in, out); Log.d(TAG, "copy " + assetFile + " - " + copyResult); } catch (IOException e1) { e1.printStackTrace(); } finally { // close input stream(file) try { if (in != null) in.close(); } catch (IOException e) { } } // close output stream (file) try { if (out != null) out.close(); } catch (IOException e) { e.printStackTrace(); } // return copy result // add file execute permission File fs = new File(saveToFile); try { //这句很重要 赋予文件可执行权限 不然文件无法执行 fs.setExecutable(true, true); } catch (Exception e) { e.printStackTrace(); } Log.d(TAG, "copyAsset() return " + copyResult); return copyResult; } }最后 是jni的c代码 很简单 直接调用
/* * deomproc.c * * Created on: 2015年2月9日 * Author: gy #include <jni.h> #include <unistd.h> #include <stdlib.h> JNIEXPORT jint JNICALL Java_com_gy_textndk_HelloJni_startproc() { system("/data/data/com.gy.textndk/app_data/gyarmdeomproc"); }
标签:
原文地址:http://blog.csdn.net/ganyao939543405/article/details/51729326