編輯:關於Android編程
首先介紹一下android的進程. Android 進程分為兩種 :其一,java層的進程,也就是在虛擬機裡運行的進程,他們的父進程是zygote進程,我們平時調用的AM裡面的類似getrunningprocess()方法,返回的就是這類進程信息,這類進程很容易被殺死。其二,native層的原生進程 也就是linux c的進程,這類進程比較安全,其中父進程是init進程的更加安全,很難殺死,在linux裡叫守護進程,像surfaceflinger(控制界面呈現)進程,一旦啟動會在底層一直運行。
那麼 我們的目的就是要寫一個守護進程 實時監視自己app java層進程的情況 如果被殺死 就立即創建。
首先是最重要的守護程序代碼 linuxC的 帶注釋
#include上面這個程序不能用arm-linux-gcc編譯 因為不支持 android新版的 程序調用接口,用 ndk-build命令編譯 源碼放在名叫的jni目錄下#include #include #include #include #include #include #include /** *守護進程的名字"/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判斷一次 自己定 } }
接下來就是實現把編譯好的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#include #include JNIEXPORT jint JNICALL Java_com_gy_textndk_HelloJni_startproc() { system("/data/data/com.gy.textndk/app_data/gyarmdeomproc"); }
Android ActionBar應用實戰,高仿微信主界面的設計
經過前面兩篇文章的學習,我想大家對ActionBar都已經有一個相對較為深刻的理解了。唯一欠缺的是,前面我們都只是學習了理論知識而已,雖然知識點已經掌握了,
我的Android進階之旅------)Android Activity的singleTask加載模式和onActivityResult方法之間的沖突
今天調試一個bug的時候,情景如下:一個Activity A,需要用startActivityForResult方法開啟Activity B。Activity B的lau
RecyclerView綜合解析
什麼是RecyclerView?RecyclerView其實就是一個在5.0推出的控件,可以用它來代替ListView和GridView,從這一點也能看出來它的特性和Li
Android的事件分發與消費機制
一、Touch的三個重要方法在Android中,與觸摸事件也就是 Touch 相關的有三個重要方法,這三個方法共同完成觸摸事件的分發。public boolean dis