日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android NDK之静态/动态注册Native方法

發布時間:2023/12/13 Android 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android NDK之静态/动态注册Native方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、簡介

關于NDK有兩種方法注冊:靜態注冊和動態注冊。

  • 靜態注冊: 就是直接在Java文件里寫個native方法 然后再c/c++文件中實現這個方法就行了;
  • 動態注冊: 就是為了不要寫很長的方法名,用JNI_OnLoad方法實現預注冊,即當執行System.LoadLibrary()方法時候就把需要調用的方法給注冊了,效率要高 Android就是采用此方法;

下面就以示例來說明靜態注冊、動態注冊以及C層調用Java層方法。

二、代碼實現

Github:NDKDemo

Java層Native方法定義

package com.cloudwise.ndk; import android.util.Log;public class NDKUtil {// 靜態注冊Native方法public native static String stringFromJNI();// 靜態注冊Native方法public native static void setJNILogEnable(int type);// 動態注冊Native方法public native static int getVersionCode();// 動態注冊Native方法public native static String getVersion(int code);// 動態注冊Native方法,并且C回調Java方法public native static void callJavaString();// 動態注冊Native方法,并且C回調Java方法public native static void callJavaVoid();// C調用Java方法(帶返回值)public static String getStringToC(String name){Log.e("CLOUDWISE", "name : " + name);return "C From Java";}// C調用Java方法(不帶返回值)public static void getVoidToC(int id, String name){Log.e("CLOUDWISE", "id : " + id + " ---- name : " + name);} }

C層代碼

common.h

#ifndef NDKDEMO_COMMON_H #define NDKDEMO_COMMON_H#ifdef __cplusplus extern "C" { #endif#define LOGOPEN 1 //日志開關,1為開,其它為關 #define LOG_TAG "[CLOUDWISE-NDK]" #if(LOGOPEN==1)#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)#define LOGD(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) #else #define LOGI(...) NULL#define LOGE(...) NULL#define LOGD(...) NULL #endif#ifdef __cplusplus } #endif#endif //NDKDEMO_COMMON_H

native-lib.c

#include <jni.h> #include <string.h> #include <android/log.h> #include <pthread.h> #include <signal.h> #include <unistd.h> #include <stdlib.h> #include "common.h"static JavaVM *j_vm = NULL; static jclass j_class = NULL;static jint debug = 1;/*** 靜態注冊的Native方法* @param env* @param arg* @return*/ JNIEXPORT jstring JNICALL Java_com_cloudwise_ndk_NDKUtil_stringFromJNI(JNIEnv *env,jclass arg) {jstring hello = "Hello ---- from ---- C";if(debug == 1){LOGE("stringFromJNI ---- Hello ---- from ---- C");}return (*env)->NewStringUTF(env, hello); }/*** 靜態注冊的Native方法* @param env* @param arg* @param type*/ JNIEXPORT void JNICALL Java_com_cloudwise_ndk_NDKUtil_setJNILogEnable(JNIEnv *env,jclass arg, jint type){if(type == 1){debug = 1;} else {debug = 0;} }/*** 動態注冊的Native方法* @param env* @param arg* @return*/ JNIEXPORT jint JNICALL getVersionCode(JNIEnv *env, jclass arg){if(debug == 1){LOGE("getVersionCode ----------- 10");}return 10; }/*** 動態注冊的Native方法* @param env* @param arg* @param code* @return*/ JNIEXPORT jstring JNICALL getVersion(JNIEnv *env, jclass arg, jint code){if(debug == 1){LOGE("getVersion ----------- 1.2.6");}jstring ver = "1.2.6";return (*env)->NewStringUTF(env, ver); }/*** C調用Java方法(帶參數不帶返回值)*/ void callVoidFromJava(){JNIEnv *env;(*j_vm)->AttachCurrentThread(j_vm, &env, NULL);jmethodID methodid = (*env)->GetStaticMethodID(env, j_class, "getVoidToC", "(ILjava/lang/String;)V");(*env)->CallStaticVoidMethod(env, j_class, methodid, 10, (*env)->NewStringUTF(env, "C-Name"));if(debug == 1) {LOGE("callVoidFromJava Java To C");} }/*** C調用Java方法(帶參數帶返回值)*/ void callStringFromJava(){JNIEnv *env;(*j_vm)->AttachCurrentThread(j_vm, &env, NULL);jmethodID methodid = (*env)->GetStaticMethodID(env, j_class, "getStringToC", "(Ljava/lang/String;)Ljava/lang/String;");jstring str = (jstring)(*env)->CallStaticObjectMethod(env, j_class, methodid,(*env)->NewStringUTF(env, "C-Name"));char* java = (char*)(*env)->GetStringUTFChars(env, str, NULL);if(debug == 1) {LOGE("callStringFromJava Java To C : %s", java);} }/*** 動態注冊的Native方法,然后調用Java方法* @param env* @param arg*/ JNIEXPORT void JNICALL callJavaString(JNIEnv *env, jclass arg) {callStringFromJava(); }/*** 動態注冊的Native方法,然后調用Java方法* @param env* @param arg*/ JNIEXPORT void JNICALL callJavaVoid(JNIEnv *env, jclass arg) {callVoidFromJava(); }static JNINativeMethod mMethods[] = {{"getVersionCode", "()I", (void*)getVersionCode},{"getVersion", "(I)Ljava/lang/String;", (void*)getVersion},{"callJavaString", "()V", (void*)callJavaString},{"callJavaVoid", "()V", (void*)callJavaVoid} };static int registerNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods){jclass clazz;clazz = (*env)->FindClass(env, className);if(clazz == NULL){return -1;}j_class = (jclass)(*env) -> NewGlobalRef(env, (jobject)clazz);if((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0){return -1;}return 0; }static int registerNative(JNIEnv* env){return registerNativeMethods(env, "com/cloudwise/ndk/NDKUtil", mMethods, sizeof(mMethods)/ sizeof(mMethods[0])); }JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved){LOGE("JNI_OnLoad ------------------------------ ");JNIEnv* env = NULL;jint result = -1;/** JavaVM::GetEnv 原型為 jint (*GetEnv)(JavaVM*, void**, jint);* GetEnv()函數返回的 Jni 環境對每個線程來說是不同的,* 由于Dalvik虛擬機通常是Multi-threading的。每一個線程調用JNI_OnLoad()時,* 所用的JNI Env是不同的,因此我們必須在每次進入函數時都要通過vm->GetEnv重新獲取*/if((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_4) != JNI_OK){return -1;}if(registerNative(env) != JNI_OK){return -1;}j_vm = vm;//cloudwise_init(1);result = JNI_VERSION_1_4;return result; }

Java層調用代碼

package com.cloudwise.ndk;import android.app.ProgressDialog; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView;import java.io.InputStream;public class CrashActivity extends AppCompatActivity implements View.OnClickListener {TextView txt;Button btn, btn_debug, btn_close, btn_ver_code, btn_ver, btn_logcat;// Used to load the 'native-lib' library on application startup.static {System.loadLibrary("native-lib");}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_crash);// Example of a call to a native methodtxt = (TextView) findViewById(R.id.sample_text);btn = (Button)findViewById(R.id.btn);btn.setOnClickListener(this);btn_debug = (Button)findViewById(R.id.btn_debug);btn_debug.setOnClickListener(this);btn_close = (Button)findViewById(R.id.btn_close);btn_close.setOnClickListener(this);btn_ver = (Button)findViewById(R.id.btn_ver);btn_ver.setOnClickListener(this);btn_ver_code = (Button)findViewById(R.id.btn_ver_code);btn_ver_code.setOnClickListener(this);btn_logcat = (Button)findViewById(R.id.btn_string);btn_logcat.setOnClickListener(this);btn = (Button)findViewById(R.id.btn_void);btn.setOnClickListener(this);}private void btnClick(){txt.setText(NDKUtil.stringFromJNI());//Log.e("CLOUDWISE", "stringFromJNI-------");}private void btnDebug(){NDKUtil.setJNILogEnable(1);}private void btnClose(){NDKUtil.setJNILogEnable(0);}private void btnVer(){txt.setText(NDKUtil.getVersion(1));}private void btnVerCode(){txt.setText(NDKUtil.getVersionCode()+"");}private void btnString(){NDKUtil.callJavaString();}private void btnVoid(){NDKUtil.callJavaVoid();}@Overridepublic void onClick(View v) {switch (v.getId()){case R.id.btn:btnClick();break;case R.id.btn_debug:btnDebug();break;case R.id.btn_close:btnClose();break;case R.id.btn_ver:btnVer();break;case R.id.btn_ver_code:btnVerCode();break;case R.id.btn_string:btnString();break;case R.id.btn_void:btnVoid();break;}} }

Java層布局代碼

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><ScrollViewandroid:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextViewandroid:id="@+id/sample_text"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="10dp"android:text="" /><Buttonandroid:layout_width="match_parent"android:layout_height="50dp"android:text="JNI調用"android:id="@+id/btn"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"android:layout_marginTop="10dp"/><Buttonandroid:layout_width="match_parent"android:layout_height="50dp"android:text="VersionCode"android:id="@+id/btn_ver_code"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"android:layout_marginTop="10dp"/><Buttonandroid:layout_width="match_parent"android:layout_height="50dp"android:text="Version"android:id="@+id/btn_ver"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"android:layout_marginTop="10dp"/><Buttonandroid:layout_width="match_parent"android:layout_height="50dp"android:text="開啟JNI日志"android:id="@+id/btn_debug"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"android:layout_marginTop="10dp"/><Buttonandroid:layout_width="match_parent"android:layout_height="50dp"android:text="關閉JNI日志"android:id="@+id/btn_close"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"android:layout_marginTop="10dp"/><Buttonandroid:layout_width="match_parent"android:layout_height="50dp"android:text="C調Java(帶返回值)"android:id="@+id/btn_string"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"android:layout_marginTop="10dp"/><Buttonandroid:layout_width="match_parent"android:layout_height="50dp"android:text="C調Java(不帶返回值)"android:id="@+id/btn_void"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"android:layout_marginTop="10dp"/></LinearLayout></ScrollView></LinearLayout>

布局界面

運行結果

[CLOUDWISE-NDK]: stringFromJNI ---- Hello ---- from ---- C [CLOUDWISE-NDK]: getVersionCode ----------- 10 [CLOUDWISE-NDK]: getVersion ----------- 1.2.6 CLOUDWISE: name : C-Name [CLOUDWISE-NDK]: callStringFromJava Java To C : C From Java CLOUDWISE: id : 10 ---- name : C-Name [CLOUDWISE-NDK]: callVoidFromJava Java To C

總結

以上是生活随笔為你收集整理的Android NDK之静态/动态注册Native方法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。