Android Ndk 學習筆記(目錄)
// 1 靜態注冊 native 函式
public native void staticRegister();
// ---------------------------靜態注冊---------------------------------
extern "C"
JNIEXPORT void JNICALL
Java_com_cn_mynativestudy_MainActivity2_staticRegister(JNIEnv *env, jobject thiz) {
// 靜態注冊: 優點:開發簡單
// 缺點
// 1.JNI函式名非常長
// 2.捆綁 上層 包名 + 類名
// 3.運行期 才會去 匹配JNI函式,性能上 低于 動態注冊
LOGI("我是靜態注冊的函式 Java_com_cn_mynativestudy_MainActivity2_staticRegister...");
}
// ---------------------------靜態注冊---------------------------------
public void test01(View view) {
staticRegister();
}
// 2 動態注冊 native 函式
public native void dynamicRegister();
public native int dynamicRegister2(String valueStr);
// ---------------------------動態注冊----------------------------------
JavaVM *jvm = nullptr; // 定義一個 區域變數 jvm 并賦null
void jni_dynamicRegister(JNIEnv *env, jobject thiz){
LOGI("我是動態注冊的函式 dynamicMethod01...");
}
int jni_dynamicRegister2(JNIEnv *env, jobject thiz, jstring value_str){
char * str = const_cast<char *>(env->GetStringUTFChars(value_str, NULL));
LOGI("我是動態注冊的函式 dynamicMethod01...%s",str);
env->ReleaseStringUTFChars(value_str,str);
return 100 ;
}
JNINativeMethod jniNativeMethod[] = {
{"dynamicRegister","()V",(void *)(jni_dynamicRegister)},
{"dynamicRegister2","(Ljava/lang/String;)I",(int *)(jni_dynamicRegister2)}
};
// 類似 java 的建構式 ,C++ 初始化時 static { System.loadLibrary("native-lib"); } 呼叫 JNI_OnLoad方法
extern "C"
JNIEXPORT jint JNI_OnLoad(JavaVM * javaVm ,void *){
::jvm = javaVm ;// 賦值,獲取行程唯一 javaVM物件
JNIEnv *jnienv = nullptr;// 宣告一個當前jnienv ;
// 通過 javavm 獲取 jnienv 并賦值 ,回傳 0 為成功
int result = javaVm->GetEnv(reinterpret_cast<void **>(&jnienv), JNI_VERSION_1_6);
if(result != JNI_OK){
return -1 ;
}
// 獲取 activity class 物件
jclass main2_class = jnienv->FindClass("com/cn/mynativestudy/MainActivity2");
jnienv->RegisterNatives(main2_class,jniNativeMethod,
sizeof(jniNativeMethod)/sizeof(JNINativeMethod));
return JNI_VERSION_1_6; // // AS的JDK在JNI默認最高1.6
}
// ---------------------------動態注冊----------------------------------
public void test02(View view) {
dynamicRegister();
}
public void test03(View view) {
int string_valueStr = dynamicRegister2("String valueStr");
Log.i("info",string_valueStr+"");
}
/** log列印
* 我是靜態注冊的函式 Java_com_cn_mynativestudy_MainActivity2_staticRegister...
* 我是動態注冊的函式 dynamicMethod01...
* 我是動態注冊的函式 dynamicMethod01...String valueStr
* 100
*/
// 3JNI 執行緒 實體
public native void naitveThread(); // Java層 呼叫 Native層 的函式,完成JNI執行緒
public native void closeThread(); // 釋放全域參考
// ---------------------------JNI 執行緒----------------------------------
// JNIEnv 執行緒系結 不能跨執行緒
// jobject 執行緒系結 不能跨執行緒
class MyContext{
public:
JNIEnv * jniEnv = nullptr;
jobject j_obj = nullptr;
};
void * runTask(void *pVoid){
MyContext * myContext = static_cast<MyContext *>(pVoid);
// 全新的JNIEnv 異步執行緒里面操作
JNIEnv *jniEnv = nullptr;
// 附加當前異步執行緒后,會得到一個全新的 env,此env相當于是子執行緒專用env
jint attachResult = ::jvm->AttachCurrentThread(&jniEnv, nullptr);
if (attachResult != JNI_OK) {
return 0; // 附加失敗,回傳了
}
// 1.拿到class
jclass mainActivityClass = jniEnv->GetObjectClass(myContext->j_obj);
// 2.拿到方法
jmethodID updateActivityUI = jniEnv->GetMethodID(mainActivityClass, "updateActivityUI", "()V");
// 3.呼叫
jniEnv->CallVoidMethod(myContext->j_obj, updateActivityUI);
::jvm->DetachCurrentThread(); // 必須解除附加,否則報錯
return nullptr;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_cn_mynativestudy_MainActivity2_naitveThread(JNIEnv *env, jobject thiz) {
MyContext * myContext = new MyContext();
myContext->jniEnv = env ;
myContext->j_obj = env->NewGlobalRef(thiz);//提升成全域變數;
pthread_t pid ;
pthread_create(&pid, nullptr, runTask, myContext);
pthread_join(pid, nullptr);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_cn_mynativestudy_MainActivity2_closeThread(JNIEnv *env, jobject thiz) {
}
// ---------------------------JNI 執行緒----------------------------------
public void test04(View view) {
naitveThread();
}
/**
* TODO 下面是 被native代碼呼叫的 Java方法
* 第二部分 JNI執行緒
*/
public void updateActivityUI() {
if (Looper.getMainLooper() == Looper.myLooper()) { // TODO C++ 用主執行緒呼叫到此函式 ----> 主執行緒
new AlertDialog.Builder(MainActivity2.this)
.setTitle("UI")
.setMessage("updateActivityUI Activity UI ...")
.setPositiveButton("知道了", null)
.show();
} else { // TODO C++ 用異步執行緒呼叫到此函式 ----> 異步執行緒
Log.i("info", "updateActivityUI 所屬于子執行緒,只能列印日志了..");
runOnUiThread(new Runnable() { // 哪怕是異步執行緒 UI操作 正常下去 runOnUiThread
@Override
public void run() {
// 可以在子執行緒里面 操作UI
new AlertDialog.Builder(MainActivity2.this)
.setTitle("updateActivityUI")
.setMessage("所屬于子執行緒,只能列印日志了..")
.setPositiveButton("知道了", null)
.show();
}
});
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/292527.html
標籤:其他
下一篇:iOS多執行緒概念總結
