編輯:關於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]獲取網絡狀態
使用React Native,可以使用NetInfo API獲取手機當前的各個網絡狀態。 componentWillMount() { NetInfo
Android apk增量升級
前言別看本文看上去很簡單,實際在實驗過程中遇到了很多問題,比如andorid studio下ndk編譯報錯,而本文呈現給大家的都是最終可行的方法.所需資源bzip2 bs
Android 微信6.1 tab欄圖標和字體顏色漸變的實現
相信大家都見到了微信圖標顏色漸變的過程,是不是感覺很牛逼?不得不說微信團隊確實是很厲害的團隊,不管是從設計還是開發人員。今天我帶大家來看看,微信 tab 欄圖標和字體顏色
Android NDK初步涉獵
大致分是這幾步: (1)新建Android工程: HelloJni.java代碼 package com.panpass.main; public c