一.Android開發之Eclipse環境搭建
補充:Eclipse版本:到Eclipse官方網站下載Ecplise For Java EE;如果想在eclipse里開發C /C++,可以安裝CDT,安裝方法同ADT
安裝JDK1.6,配置環境變量JAVA_HOME 、CLASSPATH、 path-->解壓Eclipse-->安裝ADT 插件-->解壓完整版(指解壓后即可使用無需安裝)SDK並配置android環境變量-->Eclipse中配置SDK路徑
部分步驟拆分:
1>JDK安裝后環境變量配置: 安裝JDK到H:\Program Files (x86)\Java\jdk1.6.0_32
右擊“我的電腦”-->點擊“屬性”-->選擇“高級”選項卡-->點擊“環境變量” -->在“系統變量”中設置3項屬性,JAVA_HOME,PATH,CLASSPATH(大小寫無所謂),若已存在則點擊“編輯”,不存在則點擊“新建”
JAVA_HOME變量值設為: H:\Program Files (x86)\Java\jdk1.6.0_32
PATH變量值設為:在最前面加入%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;
CLASSPATH變量值在最前面加.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar;
檢測JDK配置是否成功:
開始 -> 運行 ,輸入cmd,進入dos系統界面然后打java -version,如果安裝成功系統會顯示java的版本信息
安裝android的SDK后為了方便也可以設置環境變量比如路徑為:
H:\android-sdk-windows
環境變量配置:
ANDROID_HOME變量值設為:H:\android-sdk-windows
PATH設置:在最前面加入: %ANDROID_HOME%\tools;%ANDROID_HOME%\platform-tools\;
3>ADT安裝步驟
1)打開Eclipse,Help -->Install New Software... -->選擇Work with:后的Add...。
2)在Local選項中輸入ADT,在Archive中瀏覽到你的ADT壓縮包,點擊OK,然后在下 面勾選Name中的選項即可。安裝是否成功測試:
1)安裝完ADT插件后,關閉Eclipse,然后重啟。
2)打開File ->New,看有無出現Android Project選項,沒出現先別着急,再點擊Other...選項 ,看看General選項下是否有Android選項,有,則安裝成功,無,則安裝失敗4>Eclipse中配置SDK路徑
Window-->preference-->左側Android選項卡-->右側SDK Location中瀏覽到你的SDK解壓路徑-->apply-->ok
加入ANDROID_NDK_HOME=/cygdrive/d/android_soft/android-ndk-r4b-windows/android-ndk-r4b
export ANDROID_NDK_HOME保存(linux下配置環境變量,只有使用export關鍵字定義后才能使用,類似於windows下配置環境變量)
2>eclipse中進行如下配置(使用Cygwin)對C/C++進行編譯得到*.so(C或C++編譯出來動態鏈接庫,該庫的名字會在Android.mk中通過LOCAL_MODULE進行配置)文件
備注:將ndk目錄下的samples中的hello-jni文件夾拷貝到自己的工作空間中,我的目錄為d:\Users\wanghu\workspace
1)在新建的 android工程名上點右鍵->properties->Builders 右邊選擇New->Program
location和Working Directory地址為Cygwin地址 分別為 C:\cygwin\bin\bash.exe C:\cygwin\bin
Arguments:
--login -c "cd /cygdrive/d/Users/wanghu/workspace/hello-jni && $ANDROID_NDK_HOME/ndk-build"
d/Users/wanghu/workspace/hello-jni這部分根據你的工程地址和名稱改變,這里$ANDROID_NDK_HOME與/ndk-build之間沒空格,之前寫錯了
2)Refresh選項卡:勾選第一項Refresh resources upon completion.如下圖
3)操作如下圖,然后點擊OK
Specify Resources選擇c/c++源碼路徑 下圖:
三.(window環境下)Cygwin中編譯so庫環境的搭建(NDK+Cygwin)
1>安裝Cygwin 見<二.(window環境下)Eclipse中編譯so庫環境的搭建(Eclipse+NDK+Cygwin)>中步驟1
2>開始編譯
1)將ndk目錄下的samples中的hello-jni文件夾拷貝到自己的工作空間中,我的目錄為d:\Users\wanghu\workspack
2)運行Cygwin,cd命令進入到hello-jni的目錄
cd d:/Users/wanghu/workspace/hello-jni
3)輸入如下命令然后回車進行編譯,
$ANDROID_NDK_HOME/ndk-build
四.(window環境下)Android Studio中編譯so庫環境的搭建(NDK+Android Studio)
1).新建項目 JniDemo
2).切到project視圖
3).創建jni目錄
切到project,在項目的app工程右擊->New->Folder->Jni Folder->保持默認選擇finish
4).使項目支持NDK
修改根目錄下gradle.properties文件,添加如下代碼
#支持NDK編譯C/C++源碼 android.useDeprecatedNdk=true
5).設置NDK路徑
修改根目錄下local.properties文件,添加自己的NDK路徑我的存放在D:\android-ndk-r12b-windows-x86_64\android-ndk-r12b
ndk.dir=D\:\\android-ndk-r12b-windows-x86_64\\android-ndk-r12b
6).build.gradle文件中在尾部追加如下代碼並根據喜好修改"useCustomMk"的值即可
// ################# 需要編譯C/C++源碼的加入該代碼(只需根據喜好修改useCustomMk的值) start ################
android{
// 不要修改此變量的值,表示使用NDK編譯功能,注意:gradle.properties中的android.useDeprecatedNdk的值必須設置成true
def openNdk = true;
// 是否用自己的mk文件(Android.mk和Application.mk),為true時必須(在src/main/jni目錄)寫自己的mk文件。根據自己喜好修改此變量
def useCustomMk = false
if(openNdk){
// 如果用自己寫的mk文件編譯so生成目錄 "app/src/libs"
if(useCustomMk){
// 得到ndk路徑見 local.properties中定義的ndk.src
def ndkDir = project.plugins.findPlugin('com.android.application').sdkHandler.getNdkFolder()
sourceSets.main{
//set .so files directory to libs
jniLibs.srcDir 'src/main/libs'
//disable automatic ndk-build call禁用自動執行ndk-build
jni.srcDirs = []
}
// 定義編譯的task
task buildNative(type: Exec) {
//路徑為自己NDK所在位置,見 local.properties中定義的ndk.src
commandLine "$ndkDir/ndk-build.cmd", '-C', file('src/main').absolutePath
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn buildNative
}
}else{// 如果用自己寫的mk文件編譯so生成目錄 "app/build/intermediaters/ndk/debug"
defaultConfig {
// 如果不用自己寫的mk文件編譯
if(openNdk && !useCustomMk){
// ndk不用自定義mk文件自動編譯(系統會自動在app/build/intermediaters/ndk/debug目錄生成Android.mk文件,並自動關聯app/src/main/jni下的c/c++源碼,編譯完成后的so和臨時文件也會在這個目錄下生成)的配置
ndk{
stl "gnustl_static" // 設置支持標准的C++庫比如#include <string>中的一些方法
moduleName "jniTest" //修改此處:生成的so名字,同Android.mk中的LOCAL_MODULE
abiFilters "armeabi", "armeabi-v7a", "x86", "mips", "arm64-v8a", "mips64", "x86_64" //輸出指定三種abi體系結構下的so庫(armeabi,armeabi-v7a,x86,mips,arm64-v8a,mips64,x86_64)。同Application.mk中的APP_ABI
}
}
}
}
}
}
// ################# 需要編譯C/C++源碼的加入該代碼 end ################
7).java中寫自己的native方法,app項目中新建包名jnimanager,並在里面聲明一個專門用來存放native方法的單例類JniManager.java,源碼如下
package jnimanager; /** * Created by bravestarr on 2016/9/28. * * SingleInstance class for JNI native method */ public class JniManager { private static JniManager mInstance = null; static{ System.loadLibrary("jniTest"); } private JniManager(){ } /** * @return */ public static JniManager getInstance(){ if(null == mInstance){ synchronized (JniManager.class){ if(null == mInstance){ mInstance = new JniManager(); } } } return mInstance; } /**############################################################### * can add your Native methods below *################################################################*/ /** * getContent * @param pName */ public native String getContent(String pName); }
8).Android Studio生成*.h頭文件
進入Terminal,進入到java源碼路徑,通過 javah -d ../jni -jni 類名 命令生成頭文件(注意:1.類名不加class而且要用完整包名;2.前提是已配好java環境變量,否則javah命令不可用)見如下Terminal窗口信息
D:\workspaces\git_workspace\JniDemo> D:\workspaces\git_workspace\JniDemo>cd app/src/main/java D:\workspaces\git_workspace\JniDemo\app\src\main\java>javah -d ../jni -jni jnimanager.JniManager
運行上面命令后,會在jni目錄中自動生成一個頭文件jnimanager_JniManager.h,格式如下
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class jnimanager_JniManager */ #ifndef _Included_jnimanager_JniManager #define _Included_jnimanager_JniManager #ifdef __cplusplus extern "C" { #endif /* * Class: jnimanager_JniManager * Method: getContent * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_jnimanager_JniManager_getContent (JNIEnv *, jobject, jstring); #ifdef __cplusplus } #endif #endif
9).jni目錄新建C/C++ class 例如此處創建C++的class jnimanager_JniManager.cpp
右擊jni文件夾->New->C/C++ Source File->Type選擇.cpp,錄入名字jnimanager_JniManager->OK->將頭文件jnimanager_JniManager.h中需要實現的方法拷貝到jnimanager_JniManager.cpp中,並加上如下代碼
#include "jnimanager_JniManager.h"
注意:C++類與C的源文件有區別,native方法的實現需要放在extern "C" { }中,例如:
jnimanager_JniManager.cpp的完整源碼如下:
// // Created by bravestarr on 2016/9/28. // #include "jnimanager_JniManager.h" #include <string> extern "C" { /* * Class: jnimanager_JniManager * Method: getContent * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_jnimanager_JniManager_getContent (JNIEnv * env, jobject, jstring jName){ const char *jnameStr1 = env->GetStringUTFChars(jName, NULL); // 定義拼接后的結果內容 char jnameStr[100] = ""; // 標准拼接的方法 須#include <string> strcat(jnameStr,jnameStr1); strcat(jnameStr,",你好"); return env->NewStringUTF(jnameStr); } }
10).jni目錄新建Android.mk和Application.mk文件,格式如下:
Android.mk內容:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) #關聯的本地C++源碼 LOCAL_SRC_FILES := jnimanager_JniManager.cpp LOCAL_C_INCLUDES += $(LOCAL_PATH) LOCAL_LDLIBS += -llog -ldl #編譯后的so庫的名字 LOCAL_MODULE := jniTest include $(BUILD_SHARED_LIBRARY)
Application.mk內容如下:
#設置使用標准的C++庫 APP_STL := gnustl_static #C++代碼的編譯選項 APP_CPPFLAGS := -frtti -fexceptions
#設置要生成的架構的.so文件(armeabi,armeabi-v7a,x86,mips,arm64-v8a,mips64,x86_64),想生成多個so,可以修改APP_ABI后再進行打包
APP_ABI := armeabi-v7a #這句是設置最低安卓平台,可以不弄 APP_PLATFORM := android-18
11),在MainActivity中調用調用native方法,MainActivity完整源碼
package enterprisedigital.hiko.com.jnidemo; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.Toast; import jnimanager.JniManager; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String _content = JniManager.getInstance().getContent("張三"); Toast.makeText(this,_content,Toast.LENGTH_LONG).show(); } }
11).Build->Make Project編譯出so,並啟動程序