JNI開始

第一個工具:
NDK (native develop kits)  
交叉編譯的工具鏈:
交叉編譯: 在一個平臺(處理器,操作系統)下 編譯出來另外一個平臺下可以運行的代碼.
windows AMD intel x86 架構-> 手機 android arm處理器
之前想要訪問是這樣:$ ./ndk-build
環境變量的作用: 方便的在任何目錄下 都可以使用 指定目錄裏面的工具
之前必須在liunx下,不過r7b也支持windows,不過現在它正在開發中,不過它
不是很穩定。






.c .java 
1. 編譯  把源代碼(高級語言)編譯成一個低級語言 (彙編語言)
2. 連接  根據具體平臺的特性,(cpu的類型 x86 arm,操作系統的類型) 
         把低級語言連接成一個可以執行的二進制可執行的程序.




第二個工具: 
cygwin: windows下linux環境的模擬器.
cygwin的安裝目錄 不能有空格,最好不要中文 




第三個工具:
cdt : c/c++ develop tools  (主要是用來讓c和c++代碼 完成高亮顯示的作用)
adt : android develop tools 


JNI步驟:
1.創建一個android工程
2.JAVA代碼中寫聲明native 方法 public native String helloFromJNI();
3. 創建jni目錄,編寫c代碼,方法名字要對應
4.編寫Android.mk文件
5.Ndk編譯生成動態庫
6.Java代碼load 動態庫.調用native代碼


Android.mk告訴編譯器,以什麼樣的規則去編譯C代碼。
chen@chen-THINK /cygdrive/e/androidworkspace/ndkhelloworld/jni
$ ndk-build
Cygwin         : Generating dependency file converter script
Compile thumb  : Hello <= Hello.c
SharedLibrary  : libHello.so
Install        : libHello.so => libs/armeabi/libHello.so


chen@chen-THINK /cygdrive/e/androidworkspace/ndkhelloworld/jni


本地代碼裏面的方法名裏面就有代碼。


javah生成JNI文件的簽名。因爲我們自己寫方法簽名太麻煩了,所以我們可以直接用javah去
自動生成,非常牛逼。如果有包名,要有相應的文件夾。


mk文件:交叉編譯器編譯C/c++代碼,依賴的配置文件,linux理makefile的語法 
的子集。


ndk-build clean,清除緩存。obj目錄,libs目錄,手工給它刪除。
來這找:
F:\安卓筆記\JNI\2\ziliao\android-ndk-r7b\docs\ANDROID-MK.html
文件可以知道怎麼寫。


JNI開發中常見的錯誤:








LOCAL_PATH := $(call my-dir) 
# 交叉編譯器 在編譯c代碼/c++代碼依賴的配置文件    linux下 makefile的語法的子集 
# 獲取當前Android.mk的路徑  
#變量的初始化操作 特點: 不會重新初始化LOCAL_PATH 的變量
include $(CLEAR_VARS) 


#libHello.so 加lib前綴 .so後綴 makefile的語法約定的
LOCAL_MODULE    := libHello
LOCAL_SRC_FILES := Hello.c


include $(BUILD_SHARED_LIBRARY)






ndk開發常見錯誤
1. android.mk文件不存在 


$ ndk-build
Android NDK: Your APP_BUILD_SCRIPT points to an unknown file: ./jni/Android.mk  
/cygdrive/h/heima6/jni2/ziliao/android-ndk-r7b/build/core/add-application.mk:133: *** Android NDK: Aborting...    。 停止。


2.android.mk文件 的配置信息有錯誤
$ ndk-build
/cygdrive/h/heima6/jni2/ziliao/android-ndk-r7b/build/core/build-shared-library.mk:23: 
*** Android NDK: Missing LOCAL_MODULE before including BUILD_SHARED_LIBRARY in jni/Android.mk    。 停止。






3.c代碼 語法出現錯誤,編譯不通過 Error 1.  C語言錯誤爲依賴錯誤,一般第一個出現錯誤,之後的就都錯了。
只需要修復第一個錯誤即可。
Compile thumb  : Hello <= Hello.c
jni/Hello.c: In function 'Java_cn_itcast_ndk_DemoActivity_helloFromC':
jni/Hello.c:21: error: 'ctr' undeclared (first use in this function)
jni/Hello.c:21: error: (Each undeclared identifier is reported only once
jni/Hello.c:21: error: for each function it appears in.)
jni/Hello.c:21: error: expected ';' before 'c'
/cygdrive/h/heima6/jni2/ziliao/android-ndk-r7b/build/core/build-binary.mk:240: recipe for target `obj/local/armeabi/objs/Hello/Hello.o' failed
make: *** [obj/local/armeabi/objs/Hello/Hello.o] Error 1


4.java層c代碼庫沒有找到
Caused by: java.lang.UnsatisfiedLinkError: Library Hell0 not found


靜態加載代碼庫的時候 代碼庫沒有找到.


5.c代碼函數簽名出現錯誤
Caused by: java.lang.UnsatisfiedLinkError: hello_from_c




6.邏輯性的錯誤, 使用了已經回收的內存空間, 訪問了不可以被訪問的內存空間,
修改了不能被修改的內存空間 








斷點. ndk-gdb 
通過log 方式來觀察程序執行流程 (NDK本身支持的)
Android.mk文件增加LOCAL_LDLIBS += -llog
C代碼中增加
#include <android/log.h>
#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
 LOGI("info\n");
 LOGD("debug\n");
 
 學會開發OPenGL.




複習 :
第一步:
//第一步
public native String getStringFromC(); 
第二步:
E:\androidworkspace\ndk-utf\bin\classes>javah cn.itcast.utf.DemoActivity
第三步:
把cn_itcast_utf_DemoActivity.h  copy到jni的目錄下。
第四步:
建立C文件
#include <stdio.h>
#include <jni.h>
#include "cn_itcast_utf_DemoActivity.h"


JNIEXPORT jstring JNICALL Java_cn_itcast_utf_DemoActivity_getStringFromC
  (JNIEnv * env, jobject obj){
return (*env)->NewStringUTF(env,"你好中國");
}
第五步:在JNI目錄下建立一個Android.mk,否則無法編譯。
用ndk-build進行編譯。
#mk文件:交叉編譯器編譯C/c++代碼,依賴的配置文件,linux理makefile的語法 的子集。
 
#獲取當前Android.mk的路徑。
   LOCAL_PATH := $(call my-dir)
#變量初始化操作  特點:不會重新初始化LOCAL_PATH的變量。
   include $(CLEAR_VARS)
#生成so文件的名字。  libHello.so,這樣加也是linux下makefile語法所約定的。
   LOCAL_MODULE    := Hello
   LOCAL_SRC_FILES := Hello.c
   include $(BUILD_SHARED_LIBRARY)
   
//第六步,最後一步,加載類庫。
static{
System.loadLibrary("Hello");
}
   


高版本解決中文亂碼問題:
先把Hello.c裏面的東西全部copy出來,
把Hello.c的編碼變成UTF-8,然後再copy進去 。




低版本:
new String(getStringFromC().getBytes("iso-8859-1"),"utf-8");


ndk開發的中文亂碼問題:
1.低版本ndk 不支持中文 ndk-r4-crystal
iso-8859-1 轉碼 


//重要的課程開始啊。。。。。。。。。。。。。。。。。。
java傳遞數據給C,然後C再返回給JAVA。
有參數的方法。默認方法簽名裏面有都會有兩個默認參數。


如果代碼有更改就用ndk-build clean,然後再重建,還要清除項目class文件。
(JNIEnv * env, jobject obj)
第一個參數:指的是java虛擬機結構體C實現的指針包含的有很多JNI方法。
第二個參數:代表的是調用C代碼的JAVA對象代表的是DataProvider對象。
如果是靜態方法,第二個參數變成了 jclass clazz 它是指實例化後的對象。




比較高級一點的東西,讓C代碼調用JAVA的代碼。
1. 當c代碼接受到特定的消息 讓c代碼通知 java代碼


2. c程序員 c代碼想複用java裏面的函數和方法 


第一、E:\androidworkspace\ndkcallback\bin\classes>javah cn.itcast.ndkcallback.DataProv
ider
方法簽名:
E:\androidworkspace\ndkcallback\bin\classes>javap -s cn.itcast.ndkcallback.DataP
rovider
Compiled from "DataProvider.java"
public class cn.itcast.ndkcallback.DataProvider extends java.lang.Object{
public cn.itcast.ndkcallback.DataProvider();
  Signature: ()V
public void helloFromJava();
  Signature: ()V
public int Add(int, int);
  Signature: (II)I
public void printString(java.lang.String);
  Signature: (Ljava/lang/String;)V
public static void printStaticStr(java.lang.String);
  Signature: (Ljava/lang/String;)V
public native void callmethod1();
  Signature: ()V
public native void callmethod2();
  Signature: ()V
public native void callmethod3();
  Signature: ()V
public native void callmethod4();
  Signature: ()V
}


//爲了避免現實中出現這種場景:
在這個裏面調用native裏面的方法,應該把所有的native方法放在一個類中。


























阿里旺旺 : 
登陸的具體實現 c/c++ 
socket http




int login(char* username,char * password){
   //開啓一個socket 連接服務器 , 把username 和 password傳給服務器.
   //服務器返回 200 登陸成功 
   //服務器返回404 登陸失敗 
}






public native int Login(String username, String pwd);


javah 生成native方法的簽名 




jint Java_xxx_xxx_xxx_xxx_Login(JNIENV* env , jobject obj , jstring username, jstring pwd){
   char*  cusername = JStr2Cstr();
   char*  cpwd = JStr2Cstr();
   int result = login(cusername ,cpwd);
    if(result == 200){
    }
}


kiss :  keep it simaple stupid 


int String byte[] 


int[]  
1,2,3,4,5




c代碼寫文件


java讀文件








java jni 粘合劑 膠水


c工程實現 具體的代碼 


jni native ->jni ->.c 






1. 當c代碼接受到特定的消息 讓c代碼通知 java代碼


2. c程序員 c代碼想複用java裏面的函數和方法 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章