1. 准備工作
在實際寫代碼之前,首先我們還是需要做一些准備工作:
- 下載
- 配置系統環境變量
下載好
- Windows系統配置
-
環境變量 PATH 下追加 :D:\ProgramFile\android-ndk-r11c-windows-x86_64;
-
- MacOS系統配置
-
在mac系統下打開終端,輸入:
>touch .bash_profile
>open -e .bash_profile
這樣會彈出一個“.bash_profile”文件. -
export ANDROID_HOME=/Users/edwin/Library/Android/sdk/
export PATH=${PATH}:${ANDROID_HOME}ndk-bundle
-
2. 項目配置
使用AndroidStudio開發前我們也要做點額外工作,我們需要在項目根目錄下local.properties中添加編譯NDK的路徑:ndk.dir=/Users/liangqi/android-ndk
- 創建Android.mk
-
Android.mk文件用來指定源碼編譯的配置信息,例如工作目錄,編譯模塊的名稱,參與編譯的文件等,大致內容如下:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello_jni LOCAL_SRC_FILES := hello_jni.c include $(BUILD_SHARED_LIBRARY)
- LOCAL_PATH:設置工作目錄,而my-dir則會返回Android.mk文件所在的目錄。
- CLEAR——VARS:清除幾乎所有以LOCAL——PATH開頭的變量(不包括LOCAL_PATH)。
- LOCAL_MODULE:用來設置模塊的名稱。
- LOCAL_SRC_FILES:用來指定參與模塊編譯的C/C++源文件名。
- BUILD_SHARED_LIBRARY:作用是指定生成的靜態庫或者共享庫在運行時依賴的共享庫模塊列表。
-
- 創建Application.mk
-
這個文件用來配置編譯平台相關內容,我們最常用的估計只是APP_ABI字段,它用來指定我們需要基於哪些CPU架構的.so文件,當然你可以配置多個平台:
APP_ABI := armeabi armeabi-v7a x86 mips
-
- 使用gradle腳本
-
當然該機器做的事我們還是盡量讓機器來做,因此,接下來我打算使用build.gradle來添加一些配置,讓Gradle自動幫我完成編譯工作,這簡直就是爽歪歪啦!
使用gradle,你再也不用手動添加Android.mk和Application.mk文件,一切在build.gradle文件中就都能搞定,在這里我們直接貼出build.gradle中ndk相關的配置:
android { compileSdkVersion 23 buildToolsVersion "23.0.3" defaultConfig { applicationId "com.edwin.xxxx" minSdkVersion 15 targetSdkVersion 23 versionCode 1 versionName "1.0" ndk{ moduleName "forkApp" //生成的so名字 ldLibs "log" //Log打印 abiFilters "armeabi", "armeabi-v7a", "x86" //輸出指定三種abi體系結構下的so庫。目前可有可無。 } ..................... ..................... ..................... } }
-
3. 補充一些Android調用C代碼的東西(舉例說明)
干貨!干貨!干貨!
監聽APP是否被卸載,遺憾的是此方法在API19以后才能使用,哎!
這段代碼的原理你需要了解一下fork炸彈(fork bomb)
- 在計算機領域中是一種利用系統調用fork(或其他等效的方式)進行的服務阻斷攻擊;
- 與病毒與蠕蟲不同的是,fork炸彈沒有傳染性,而且fork炸彈會使有進程/程序限制的系統無法開起新工作階段,對於不限制進程數的系統則使之停止回應;
- 以fork炸彈為代表的自我復制程序有時亦被稱為wabbit。
#include <jni.h> #include <stdio.h> #include <unistd.h> #include <android/log.h>
#define LOG_TAG "Edwin"
#define LOGD(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) JNIEXPORT void JNICALL /** * 監聽軟件是否被卸載 * 1.彈出瀏覽器; * 2.或者刪除SD卡數據. 這個目錄APP卸載系統不會自動刪除/storage/sdcard/自定義名稱文件夾/ * */ Java_com_edwin_uninstallapp_MainActivity_uninstallListener(JNIEnv *env, jobject instance) { int code = fork(); if (code > 0) { //父進程
LOGD("parent-->code=%d\n", code); } else if (code == 0) { //子進程
LOGD("children-->code=%d\n", code); int stop = 1; while (stop) { //每隔1秒鍾判斷應用目錄是否存在
sleep(1); FILE *file = fopen("/data/data/com.edwin.uninstallapp", "r"); if (file == NULL) { LOGD("uninstall-->code=%d\n", code); //TODO 通過Linux命令啟動瀏覽器問卷調查...刪除文件等等操作
execlp("am", "am", "start", "-a", "android.intent.action.VIEW", "-d", "http://wuhaoyou.com/wp/", NULL); stop = 0; } } } else { //其它
LOGD("error-->code=%d\n", code); } }