Android Studio NDK 入門教程(1)--來自C 語言的String
概述
本文講述如何使用Android Studio 進行NDK開發,適合略有了解C語言的人以及NDK入門開發。
環境配置
- 安裝Android Studio,目前版本是2.1.2。可以去官方下載最新安裝包,也可以百度上下載安裝之後線上更新,這部分網上教程比較多,學習NDK開發的道友應該不會卡在這裡。
- Android Studio安裝完成之後Android SDK也包含在其中,但是不包含NDK。
- 開啟File->Settings->Appearance & Behavior->System Settings->Android SDK
- 選擇SDK Tools ,等待檢查更新完成,然後勾上LLDB2.1、NDK、CMAKE工具,然後點選Apply,等待下載安裝完成,完成之後ndk-bundle在你Android SDK資料夾下。
注意:如果使用其他位置的NDK,需要在專案設定裡面配置NDK路徑,如果沒有CMake可以不下載,CMake並不是NDK的必須外掛
建立一個Android程式
1.建立一個名為HelloJni的Android應用程式。此部分和建立正常的Android應用沒有區別,過程略。
2.新建HelloJNI.java;
package com.example.wastrel.hellojni;
/**
* Created by wastrel on 2016/8/4.
*/
public class HelloJNI {
static {
System.loadLibrary("helloJNI");
}
//Native方法
public static native String getFormCString();
}
3.利用javah生成C語言標頭檔案。在執行javah命令之前,應先編譯java檔案為class檔案,執行選單欄上的Building->Make Project即可。然後開啟Android Studio底部的Terminal執行命令:
javah -d src\main\jni\ -classpath build\intermediates\classes\debug com.example.wastrel.hellojni.HelloJNI
注意:最後一個引數改成你對應的包名,也可以參照我另外一篇文章配置一鍵生成標頭檔案:http://blog.csdn.net/venusic/article/details/51087945
4.完成第三步之後將在jni目錄下生成對應的.h標頭檔案。
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_wastrel_hellojni_HelloJNI */
#ifndef _Included_com_example_wastrel_hellojni_HelloJNI
#define _Included_com_example_wastrel_hellojni_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_wastrel_hellojni_HelloJNI
* Method: getFormCString
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_wastrel_hellojni_HelloJNI_getFormCString
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
注:我們可以看到生成.h檔案方法上面的註釋包含了Class、Method、Signature三個屬性值,函式名命名也有非常嚴格的規則,包名+方法名的形式命名的。
5.正常情況下生成的標頭檔案開啟會有錯誤,提示找不到jni.h,並且編輯器上方會有英文提示“ndk support is an experimental feature…”。這是因為正式版gradle不能很好的支援NDK開發(事實上AS1.5版本的時候沒有問題的,升級到2.0才出現的毛病)。這時候我們需要把gradle版本換成experimental版本的。
- 開啟Project的build.gradle,修改gradle為如下版本。
classpath 'com.android.tools.build:gradle-experimental:0.7.0'
- 這個版本的gradle配置和正式版的有很大區別,開啟app的build.gradle修改如下:
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.2"
defaultConfig {
//包名
applicationId "com.example.wastrel.hellojni"
minSdkVersion.apiLevel 15
targetSdkVersion.apiLevel 23
versionCode 1
versionName "1.0.1"
}
}
android.ndk {
//生成so檔案的名字,不需要lib字首
moduleName "helloJNI"
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles.add(file("proguard-rules.txt"))
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.4.0'
}
注:可以把上面的模板複製過去修改一下即可。
詳情請參考:http://tools.android.com/tech-docs/new-build-system/
6.編寫cpp檔案,上面已經用javah工具生成了標頭檔案。接下來我們要實現標頭檔案裡面的方法。在jni目錄下新建檔案HelloJNI.cpp:
#include "com_example_wastrel_hellojni_HelloJNI.h"
JNIEXPORT jstring JNICALL Java_com_example_wastrel_hellojni_HelloJNI_getFormCString
(JNIEnv *env, jclass clazz){
//通過env裡面的轉換方法,將字串轉成UTF格式的jstring
return env->NewStringUTF("I am from C String!");
}
JNIEnv是JNI的核心資料,env指向JNIEnv結構的指標。可以理解為JNIEnv提供了一些列方法來完成JAVA與Native之間的資料轉換與傳遞工作。
7.在Activity中佈局一個TextView用來顯示字串,佈局程式碼就不貼了。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv= (TextView) findViewById(R.id.text);
tv.setText(HelloJNI.getFormCString());
}
8.執行程式,不出現編譯錯誤,手機上將會看到結果圖:
可能遇到的問題
- 為什麼我生成的C函式引數是(JNIEnv , jobject)而不是(JNIEnv , jclass);
答:這和java程式碼中對Native函式的宣告有關,宣告為static,這裡的引數就是jclass,即代表該函式所在的類(如HelloJNI.getFromString(),這是jclass接收的是HelloJNI.class)。如果沒有宣告static,這裡的引數就是jobject,表示呼叫者的實體物件,(如HelloJNI t=new HelloJNI();t.getFromCString(),這裡jobject就代表就是t這個物件)。 - 報java.lang.UnsatisfiedLinkError錯誤;
答:此類錯誤一般後面有詳細的解釋,此處列出常見的錯誤:
- could’t find “xxx.so” 此類錯誤表示找不到對應的so檔案,請檢視自己的gradle配置是否有ndk標籤,函式實現檔案要用標準的字尾.cpp或.c,不然gradle編譯ndk的時候不會加入編譯的。
- Native method not found 此類問題表明你在JAVA中宣告的函式沒有對應的Native實現,如果已經實現了,請確保執行了System.loadLibary(“xxx.so”);一般來說用javah生成的函式定義是不會出現簽名不一致的情況的。
- Can’t load 64-bit .so on 32-bit platform 也就是說不能在32位環境中載入64位的so。一般來說把so移到armeabi-v8a 資料夾下即可。該資料夾存放的是arm64位so檔案。
相關文章
- Android Studio NDK 入門教程(3)--Java與C++之間的型別簽名AndroidJavaC++型別
- 《C 語言入門教程》釋出了
- Mac之Android Studio開發NDK入門MacAndroid
- Android Studio Grade Groovy語言入門篇Android
- R語言的入門教程R語言
- c語言入門C語言
- Android-NDK-11-C語言編譯原理AndroidC語言編譯原理
- C語言_入門例題_PAGE1C語言
- Android Studio NDK 入門教程(2)--Java與C++之間的簡單資料轉換與傳遞AndroidJavaC++
- C語言快速入門教程1快速入門 2指令 3條件選擇C語言
- Android NDK入門:C++ 基礎知識AndroidC++
- Android谷歌官方語言Kotlin用法入門教程Android谷歌Kotlin
- go語言快速入門教程Go
- Prolog 語言入門教程
- 組合語言入門教程組合語言
- Swift 程式語言入門教程Swift
- Android 音視訊入門:C語言基礎AndroidC語言
- 零基礎看得懂的C語言入門教程C語言
- Android -- NDK開發入門Android
- C語言入門基礎C語言
- 《C語言開發從入門到精通》一第1章C語言之定位1.1 C語言的誕生C語言
- Go 語言入門教程:變數Go變數
- Android Studio ndk-Jni開發詳細入門,Aes加密demoAndroid加密
- 《零基礎看得懂的C語言入門教程 》瞭解C語言的邏輯運算C語言
- Android Studio教程從入門到精通2.0Android
- Apple Swift程式語言入門教程APPSwift
- NDK探究之旅《二》——C語言的基本認識C語言
- Android NDK開發之旅5 C語言基礎 結構體AndroidC語言結構體
- 幾十種程式語言的快速入門教程
- C語言入門題-7-1 最大和最小 (10分)C語言
- Android Studio 從入門到精通視訊教程Android
- [C語言] 第一章|C語言入門第一課C語言
- C語言入門很簡單pdfC語言
- 入門輸出Hello World!——C語言C語言
- C++語言菜鳥快速入門C++
- C語言(Visual Studio)C語言
- Rust入門系列之語言特性 - 1Rust
- Android Studio NDK :一、基礎入門(基於gradle-experimental外掛)AndroidGradle