在通常的APP項目中,都不用用到C++ 因此當咱們須要使用C++(也就是JNI)的時候 須要在 Android studio 中進行以下設置java
(這裏須要特別注意下 若是你的 Android studio版本是3.0及以上時,那麼原來3.0如下的版本 在運行項目時會提示 「No toolchains found in the NDK toolchains folder for ABI with prefix: arm-linux-androideabi」 linux
個人解決方法是 在3.0如下的版本點擊安裝 CMAKE,NDK,3.0以上的項目也沒有報錯)android
補充:https://developer.android.google.cn/ndk/downloads/ 下載替換 本身sdk 中 toolchains 文件夾,及android-ndk-r16b-windows-x86_64\android-ndk-r16b\toolchains 中的文件就能夠解決上面的問題windows
方法有兩種:app
(1)File --> Settings --> Appearance & Behavior --> System Settings --> Android SDK -->勾選CMAKE,NDKide
(2)ctrl+alt+S -->搜索框中 輸入 SDK -->勾選CMAKE,NDK函數
以下圖:this
配置作完後 在擼代碼以前 咱們來對 java類型與C++類型的比較google
/* * * Java類型 別名 C++本地類型 字節(bit) boolean jboolean unsigned char 8, unsigned byte jbyte signed char 8 char jchar unsigned short 16, unsigned short jshort short 16 int jint long 32 long jlong __int64 64 float jfloat float 32 double jdouble double 64 void void n/a * * */
開始正式擼代碼 (若是你們想快速生成JNI範例 在新建項目時勾選 include C++ 就能夠)idea
MainActivity.java
public class MainActivity extends AppCompatActivity { // Used to load the 'native-lib' library on application startup. static { System.loadLibrary("native-lib");//此.so名稱名稱能夠在 CMakeLists.txt 中修改 } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Example of a call to a native method TextView tv = (TextView) findViewById(R.id.sample_text); tv.setText(stringFromJNI()); tv.setText(testNativeFunction()); } /** * A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ public native String stringFromJNI(); public native String testNativeFunction();
public native String cCallJava();
public native String cCallJavaParm();
/* * java調用有參方法 */ public static Object cByJava(int b){ Log.i("cByJava", "cByJava: 我被調用了 b:"+b); return "ssssss"; } public static void cByJavaf(){ Log.i("cByJava1", "cByJava: 我被調用了 "); }
public void addffffff(int b,int c,int d){
Log.i("bbbbb","fffffff");
}
}
native-lib.cpp
#include <jni.h> #include <string> #define NativeStr(name)Java_com_example_android_testc_##name /* * * 類型 相應的簽名:(就是後面的 GetStaticMethodID(mMain,"cByJava","(I)Ljava/lang/Object;") 的 (I)Ljava/lang/Object;) boolean Z byte B char C short S int I long J float F double D void V object L用/分隔包的完整類名: Ljava/lang/String; Array [簽名 [I [Ljava/lang/Object; Method (參數1類型簽名 參數2類型簽名···)返回值類型簽名 * * */ extern "C" JNIEXPORT jstring JNICALL NativeStr(MainActivity_stringFromJNI)( JNIEnv *env, jobject /* this */) { //C++調用java 帶參數 有返回值(當返回值爲String時用Object代替) //----------------beigin---------------- // static const char* const DL_CLASS_NAME = "com/example/android/testc/MainActivity"; // jclass mMain = (env)->FindClass(DL_CLASS_NAME); // jmethodID cByJava =(env)->GetStaticMethodID(mMain,"cByJava","(I)Ljava/lang/Object;");//java中有參數返回的方法的時候;必定要加上 ";" 否則會調用失敗 // jstring result =(jstring)(env)->CallStaticObjectMethod(mMain, cByJava,1111); //----------------end---------------- // return result; // std::string hello = ""; // return env->NewStringUTF(hello.c_str()); //C++調用java 帶參數 無返回值 static const char* const DL_CLASS_NAME = "com/example/android/testc/MainActivity"; jclass mMain = (env)->FindClass(DL_CLASS_NAME); jmethodID cByJavaf =(env)->GetStaticMethodID(mMain,"cByJavaf","()V");//在方法名爲void的狀況下 V後面不能加上 ';' 否則會運行異常 報找不到方法 ()後面必定要大寫 (env)->CallStaticVoidMethod(mMain, cByJavaf); jstring js =env->NewStringUTF("ssssssss"); return js; }
extern "C" JNIEXPORT jstring JNICALL NativeStr(MainActivity_testNativeFunction)( JNIEnv *env, jobject /* this */) { static const char* const DL_CLASS_NAME = "com/example/android/testc/MainActivity"; jclass mMain = (env)->FindClass(DL_CLASS_NAME); jmethodID cByJavaf =(env)->GetStaticMethodID(mMain,"cByJavaf","()V");//在方法名爲void的狀況下 V後面不能加上 ';' 否則會運行異常 報找不到方法 ()後面必定要大寫 (env)->CallStaticVoidMethod(mMain, cByJavaf); jstring js =env->NewStringUTF("sssffffsssss"); return js; }
//C 調用Java普通方法
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_myapplication_MainActivity_cCallJava(JNIEnv *env, jobject instance) {
// TODO C調用java
static const char* const DL_CLASS_NAME ="com/example/myapplication/MainActivity";
jclass mMain = env->FindClass(DL_CLASS_NAME);
jmethodID addMethod = env->GetMethodID(mMain,"add","()V");
env->CallVoidMethod(instance,addMethod);
return env->NewStringUTF("ffff");
}
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_myapplication_MainActivity_cCallJavaParm(JNIEnv *env, jobject instance) {
static const char* const DL_CLASS_NAME ="com/example/myapplication/MainActivity";
jclass mMain = env->FindClass(DL_CLASS_NAME);
jmethodID addMethod = env->GetMethodID(mMain,"addffffff","(III)V");
env->CallVoidMethod(instance,addMethod,22,33,44);
return env->NewStringUTF("調用有參的函數");
}
此處有個坑: 在studio3.2 中 每一個C++方法都須要加上 extern "C" JNIEXPORT 前綴 否則會提示找不到 第二個方法 NativeStr(MainActivity_testNativeFunction)
打完收工
}