編輯:關於Android編程
在使用Jni之前,我們需要對android studio進行一些配置:
有網的時候:在設置 - plugin - Android NDK Support 勾選--install plugin for disk 然後再打開設置---system setting--android SDK --sdk tool ---勾選上NDK 沒網的時候:直接下載下來並進行解壓ndk{ moduleName "Hello" //可根據自己取,表示.so文件的前綴 ldLibs "log" //打印日志 abiFilters "armeabi", "armeabi-v7a", "x86" //指定CPU }注意://如果你編寫的.c文件include的時候報紅,在build.gradle裡添加
sourceSets.main { jni.srcDirs 'src/main/source' }最後build.gradle的代碼:
android { compileSdkVersion 23 buildToolsVersion "23.0.2" defaultConfig { applicationId "com.suixi.ndkproject" minSdkVersion 15 targetSdkVersion 23 versionCode 1 versionName "1.0" ndk{ moduleName "javaCallC" ldLibs "log" //打印日志 abiFilters "armeabi", "armeabi-v7a", "x86" } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.2.1' compile 'com.jakewharton:butterknife:6.0.0' }3、兼容老的NDK 在gradle.properties裡添加: android.useDeprecatedNdk=true 二、若要在C語言中進行LOG日志 在build.gradle
ndk{ moduleName "cCallJava" ldLibs "log" //打印日志 abiFilters "armeabi", "armeabi-v7a", "x86" }在.c文件中添加如下代碼
#include #define LOG_TAG "linzhenxiang" #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 LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)三、編寫java調用c語言的方式 1、寫一個java類JNI(類名可自取),用於寫native代碼
public class JNI { public native String sayHello();//簡單的調用 public native String sayAddHello(String s);//字符串拼接 public native int add(int x,int y);//加法運算 public native int[] increaseArray(int[] arr );//給數組的每個元素都增加10 public native int checkPwd(String s);//檢查密碼是否正確,並返回值 }2、動態的生成你所需要的C的頭文件的兩種方法 1)、在\NDKDEMO\app\src\main\java 執行命令:javah com.suixi.ndkproject.JNI(包名+類名) 2)、在studio底部中的terminal 裡執行javah javah com.suixi.ndkproject.JNI
/* DO NOT EDIT THIS FILE - it is machine generated */ #include3、在java中右鍵新建JniFodler,將上一步生成的.h文件移入改文件夾中/* Header for class com_suixi_ndkproject_JNI */ #ifndef _Included_com_suixi_ndkproject_JNI #define _Included_com_suixi_ndkproject_JNI #ifdef __cplusplus extern "C" { #endif /* * Class: com_suixi_ndkproject_JNI * Method: sayHello * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_suixi_ndkproject_JNI_sayHello (JNIEnv *, jobject); /* * Class: com_suixi_ndkproject_JNI * Method: sayAddHello * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_suixi_ndkproject_JNI_sayAddHello (JNIEnv *, jobject, jstring); /* * Class: com_suixi_ndkproject_JNI * Method: add * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_suixi_ndkproject_JNI_add (JNIEnv *, jobject, jint, jint); /* * Class: com_suixi_ndkproject_JNI * Method: increaseArray * Signature: ([I)[I */ JNIEXPORT jintArray JNICALL Java_com_suixi_ndkproject_JNI_increaseArray (JNIEnv *, jobject, jintArray); /* * Class: com_suixi_ndkproject_JNI * Method: checkPwd * Signature: (Ljava/lang/String;)I */ JNIEXPORT jint JNICALL Java_com_suixi_ndkproject_JNI_checkPwd (JNIEnv *, jobject, jstring); #ifdef __cplusplus } #endif #endif
public class JNI { { System.loadLibrary("javaCallC");//動態加載。so文件,只要在用之前加載就成,不一定在這個類裡加載 } public native String sayHello();//簡單的調用 public native String sayAddHello(String s);//字符串拼接 public native int add(int x,int y);//加法運算 public native int[] increaseArray(int[] arr );//給數組的每個元素都增加10 public native int checkPwd(String s);//檢查密碼是否正確,並返回值 }6、在jni文件夾下新建test.c文件,進行代碼編寫
#include "test.h" #include "com_suixi_ndkproject_JNI.h" #include#include #include #include #define LOG_TAG "linzhenxiang"//打印日志的別名,可自己去 #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 LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) //jstring to char* jString 轉換成 char*指針 char *jstringTochar(JNIEnv *env, jstring jstr) { char *rtn = NULL; jclass clsstring = (*env)->FindClass(env, "java/lang/String"); jstring strencode = (*env)->NewStringUTF(env, "utf-8"); jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes", "(Ljava/lang/String;)[B"); jbyteArray barr = (jbyteArray) (*env)->CallObjectMethod(env, jstr, mid, strencode); jsize alen = (*env)->GetArrayLength(env, barr); jbyte *ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE); if (alen > 0) { rtn = (char *) malloc(alen + 1); memcpy(rtn, ba, alen); rtn[alen] = 0; } (*env)->ReleaseByteArrayElements(env, barr, ba, 0); return rtn; } JNIEXPORT jstring JNICALL Java_com_suixi_ndkproject_JNI_sayHello (JNIEnv *env, jobject jobject1) { // jstring (*NewStringUTF)(JNIEnv*, const char*); char *s = "I AM FROM C"; return (*env)->NewStringUTF(env, s); }; /** * 返回帶有參數的字符串 */ JNIEXPORT jstring JNICALL Java_com_suixi_ndkproject_JNI_sayAddHello (JNIEnv *env, jobject jobject1, jstring js) { char *from = jstringTochar(env, js); char *to = "I am from c"; strcat(from, to);//字符串拼接,會把拼接後的結果放在第一個參數裡 return (*env)->NewStringUTF(env, from); }; /** * 加法運算 */ JNIEXPORT jint JNICALL Java_com_suixi_ndkproject_JNI_add (JNIEnv *env, jobject jobject1, jint x, jint y) { return x + y; }; /** * 給數組的每個元素添加10 */ JNIEXPORT jintArray JNICALL Java_com_suixi_ndkproject_JNI_increaseArray (JNIEnv *env, jobject jobject1, jintArray array) { //jsize (*GetArrayLength)(JNIEnv*, jarray); jsize size = (*env)->GetArrayLength(env,array);//獲取數組的長度 // jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*); jint* jint1 = (*env)->GetIntArrayElements(env,array,JNI_FALSE);//獲取數組中的元素 int i; for(i=0;i 四:在C中調用Java的方式1、寫一個java類JNI(類名可自取),用於寫native代碼 public class JNI { /** * 當執行這個方法的時候,讓C代碼調用 * public void helloFromJava() */ public native void callbackHelloFromJava(); public void helloFromJava() { Log.e("TAG", "helloFromJava()"); } }2、動態的生成你所需要的C的頭文件的兩種方法 1)、在\NDKDEMO\app\src\main\java 執行命令:javah com.suixi.ndkproject.JNI(包名+類名) 2)、在studio底部中的terminal 裡執行javah javah com.suixi.ndkproject.JNI
3、在java中右鍵新建JniFodler,將上一步生成的.h文件移入改文件夾中
4、rebuild Project 下,會在build-->intermediates生成ndk文件夾
5、在JNI類下加載動態鏈接庫public class JNI { { System.loadLibrary("cCallJava"); } /** * 當執行這個方法的時候,讓C代碼調用 * public void helloFromJava() */ public native void callbackHelloFromJava(); public void helloFromJava() { Log.e("TAG", "helloFromJava()"); } }6、編寫.c文件
#include "Test2.h" #include#include #include JNIEXPORT void JNICALL Java_com_suixi_myapplication_JNI_callbackHelloFromJava(JNIEnv *env, jobject instance) { //jclass (*FindClass)(JNIEnv*, const char*); jclass jclazz = (*env)->FindClass(env,"com/suixi/myapplication/JNI");//第二個參數表示的是JNI所在的包名+類名 //第三個參數表示的是你要調用的java類中的方法, //第四個參數表示的是簽名:定位到JNI.class文件的位置,通過命令行:javap -s com/suixi/myapplication/JNI.class // 生成簽名 jmethodID jmethodID1 = (*env)->GetMethodID(env,jclazz,"helloFromJava","()V"); // jobject (*AllocObject)(JNIEnv*, jclass); jobject jobject1 = (*env)->AllocObject(env,jclazz); //通過該方法調用即可 (*env)->CallVoidMethod(env,jobject1,jmethodID1); };
注意:GetMethodID的簽名的生成方法
定位到:build-->intermediates-->classes-->debug
按住 shift+鼠標右鍵 ----->點擊此處打開命令窗口
執行:javap -s com/suixi/myapplication/JNI.class
生成如下簽名:
7、在activity中調用
public class MainActivity extends Activity { private JNI jni; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.inject(this); jni = new JNI(); } @OnClick({R.id.bt1}) public void onClick(View v){ switch (v.getId()){ jni.callbackHelloFromJava(); } } }
使用React Native,可以使用NetInfo API獲取手機當前的各個網絡狀態。 componentWillMount() { NetInfo
前言別看本文看上去很簡單,實際在實驗過程中遇到了很多問題,比如andorid studio下ndk編譯報錯,而本文呈現給大家的都是最終可行的方法.所需資源bzip2 bs
相信大家都見到了微信圖標顏色漸變的過程,是不是感覺很牛逼?不得不說微信團隊確實是很厲害的團隊,不管是從設計還是開發人員。今天我帶大家來看看,微信 tab 欄圖標和字體顏色
大致分是這幾步: (1)新建Android工程: HelloJni.java代碼 package com.panpass.main; public c