1.android环境的可执行文件的生成
所谓的android下的可执行文件,其实就是一般的c/c++代码使用NDK编译出来的应用程序。它和linux下用gcc编译出来的程序和windows系统下的.exe文件是一样的。要将代码编译成可执行文件只需要将编译so的include $(BUILD_SHARED_LIBRARY)改成include $(BUILD_EXECUTABLE)就行。
Main.cpp
#include
#include
using namespace std;
#define LOG_TAG "JNI_LOG"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
int main(int argc, char **argv)
{
LOGI("NativeFile Begin!");
LOGI("This is a Test!");
LOGI("NativeFile End!");
return 0;
}
Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
Main.cpp
LOCAL_MODULE := NativeFile
LOCAL_LDLIBS := -llog
include $(BUILD_EXECUTABLE)
Application.mk
APP_PLATFORM = android-8
APP_ABI := armeabi
APP_STL := stlport_static
2.android 应用使用JNI执行NDK编译的可执行文件.
1) 将上面生成的NativeFile可执行文件放在android工程的asset目录下面。
2) 将asset中的可执行文件拷贝到应用的data空间中。
3)使用linux的fork函数创建子进程,并使用execlp执行可执行文件.
4)此时apk所在的进程和可执行文件的进程分属于二个不同的进程,拥有不同的进程id,所以就算APK文件卸载了以后这个可执行文件还是在运行状态的,这样我们的应用就可以在apk被卸载了以后仍然能做很多的事情,比如向360一样显示一个卸载调查的网页,或者发送应用被卸载的消息给自己的服务器等等。
下面附上代码.
MainActivity.java
package com.example.testnative;
import android.app.Activity;
import android.app.ActionBar;
import android.app.Fragment;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.os.Build;
public class MainActivity extends Activity {
static
{
System.loadLibrary("TestNative");
}
native void ExecFile(AssetManager asset,String path);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ExecFile(getAssets(),getCacheDir().toString());
}
}
TestNative.cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
extern "C"
{
#define LOG_TAG "JNI_LOG"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
char* Jstring2String(JNIEnv* env, jstring jstr)
{
char* rtn = NULL;
jclass clsstring = env->FindClass("java/lang/String");
jstring strencode = env->NewStringUTF("utf-8");
jmethodID mid = env->GetMethodID(clsstring, "getBytes",
"(Ljava/lang/String;)[B");
jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode);
jsize alen = env->GetArrayLength(barr);
jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
if (alen > 0)
{
rtn = (char*) malloc(alen + 1);
memcpy(rtn, ba, alen);
rtn[alen] = 0;
}
env->ReleaseByteArrayElements(barr, ba, 0);
return rtn;
}
void ExecChildProcess(const char* fileName, const char* param)
{
LOGI("Begin ExecCmdByChildProcess!\n");
pid_t pid = fork();
if (pid == 0)
{
pid_t pid2 = fork();
if (pid2 == 0)
{
if (execlp(fileName, fileName, param, NULL) < 0)
LOGI("ExecChildProcess %s error!\n", fileName);
exit(0);
}
else
{
exit(0);
}
}
else if (pid > 0)
{
int status = 0;
waitpid(pid, &status, 0);
}
else
{
LOGE("ExecChildProcess Error!\n");
}
}
void Java_com_example_testnative_MainActivity_ExecFile(JNIEnv* env, jobject obj,
jobject asset, jstring path)
{
AAssetManager* asMg = AAssetManager_fromJava(env, asset);
AAsset* as = AAssetManager_open(asMg, "NativeFile", AASSET_MODE_UNKNOWN);
char* tmp = Jstring2String(env, path);
char cPath[256] =
{ 0 };
strcpy(cPath, tmp);
strcat(cPath, "/NativeFile");
free(tmp);
if (as != NULL)
{
int len = AAsset_getLength(as);
LOGI("len=%d", len);
int file = open(cPath, O_WRONLY | O_CREAT, 0755);
char* buf = new char[1024];
while (len > 0)
{
int n = AAsset_read(as, buf, 1024);
if (n < 0)
break;
write(file, buf, n);
len -= n;
}
delete[] buf;
AAsset_close(as);
close(file);
}
ExecChildProcess(cPath, " ");
}
}
运行APK后的结果:
源码下载链接:http://download.csdn.net/detail/csdn49532/9436882