Android筆記之使用CMake進行JNI開發(Android Studio)
不知道有多少朋友像我一樣,被Android NDK開發的環境配置折騰到吐,然後放棄。從事Android工作幾年了,也不太願意接觸NDK開發。不過福利終於來了,新的AS中開始使用CMake開發jni,開發c跟開發java一樣簡單,你只需單純的執著於業務目標,跟折騰環境說拜拜。那我們現在就開始吧!
環境需求
要進行jni開發,AS需要以下環境:
方式一、在工程建立的時候新增
首先使用AS(3.0)新建一個JniTest工程
在建立工程的過程中就有是否支援jni呼叫的選項
當你把這個選項勾選上後,你會發現專案的App模組下自動就把cmake相關的內容配置好了,我們來看看與無jni呼叫的工程有什麼不同。
首先,app目錄下多了CMakeLists.txt檔案,內容如下:
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
# 配置so庫資訊
add_library( # Sets the name of the library.
# 生成的so庫名稱,此處生成的so檔名稱是libnative-lib.so
native-lib
# Sets the library as a shared library.
# STATIC:靜態庫,是目標檔案的歸檔檔案,在連結其它目標的時候使用
# SHARED:動態庫,會被動態連結,在執行時被載入
# MODULE:模組庫,是不會被連結到其它目標中的外掛,但是可能會在執行時使用dlopen-系列的函式動態連結
SHARED
# Provides a relative path to your source file(s).
# 資原始檔,可以多個,
# 資源路徑是相對路徑,相對於本CMakeLists.txt所在目錄
src/main/cpp/native-lib.cpp )
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
# 從系統查詢依賴庫
find_library( # Sets the name of the path variable.
# android系統每個型別的庫會存放一個特定的位置,而log庫存放在log-lib中
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
# android系統在c環境下打log到logcat的庫
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
# 配置庫的連結(依賴關係)
target_link_libraries( # Specifies the target library.
# 目標庫
native-lib
# Links the target library to the log library
# included in the NDK.
# 依賴於
${log-lib} )
程式碼已經新增比較清晰的註釋,使用的時候只需要拷貝到模組目錄下,上方程式碼刪除註釋後一目瞭然,無需發愁!再看看app/build.gradle下又有什麼變化:
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.test.jnitest2"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
}
主要的多了關於CMake的兩項配置:
// android下
externalNativeBuild {
cmake {
path "CMakeLists.txt" // cmake配置檔案路徑
}
}
// defaultConfig下
cmake {
cppFlags ""
// 生成多個版本的so檔案
abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'
}
具體的更多配置,請詳查官方文件,根據需要修改。ok,配置就這麼多,是不是很簡單。接著我們看看資源目錄:
我們發現系統已經幫我們把native-lib.cpp原始檔寫好了,根據函式名可以知道,函式的native申明是在MainActivity中。我們再看看MainActivity檔案,與以前的jni呼叫方式完成一樣:
// Used to load the 'native-lib' library on application startup.
static {
// 載入庫
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = (TextView) findViewById(R.id.sample_text);
tv.setText(stringFromJNI()); // 發生jni呼叫
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI(); // native申明
上面的過程包括了庫的載入、native方法申明、jni方法呼叫三個過程。跟以往不同的是,你可以按住ctrl鍵滑鼠左鍵點選native方法,也能像java一樣跳轉到方法的定義了,即native-lib.cpp檔案中的Java_com_test_jnitest2_MainActivity_stringFromJNI方法。
現在我們在MainActivity中再宣告一個方法:
public native String getStr(String s);
我們選中函式名,然後alt+enter:
自動就出現了建立jni方法的選項,確定後你會在native-lib.cpp中發現函式定義框架已經寫好:
so easy!你在函式中輸入env->居然提示:
方式二、在專案開發過程中新增
有時候,我們的專案已經在進行中或者維護中了,突然需要使用jni呼叫怎麼辦呢?AS已經提供了相對便捷的方法。首先在要使用jni呼叫的工程模組下新建一個CMakeLists.txt:
程式碼:
cmake_minimum_required(VERSION 3.6)
add_library( # Sets the name of the library.
xjni
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/jni/XJni.c )
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
target_link_libraries( # Specifies the target library.
xjni
# Links the target library to the log library
# included in the NDK.
${log-lib} )
CMakeLists.txt具體配置上面已經說過了,這個地方是去掉了註釋了的。需要注意的是,如果我們不在c原始碼檔案中輸出日誌到logcat,那麼我們是不需要依賴log庫的,也就是說find_library、target_link_libraries不是必須的。
接著配置模組支援jni呼叫,對專案模組右鍵:
在彈出的提示框中選擇剛新建配置的CMakeLists.txt檔案:
我們看看app/build.gradle有什麼變化:
編譯完成,編譯器會報找不到XJni.c檔案錯誤。ok,那我們新建一個/app/src/main/jni/XJni.c:
#include <jni.h>
只有一行程式碼,ok,再編譯,沒問題!接下來新建jni呼叫java檔案XJni.java:
package com.test.jnitest4;
public class XJni {
static {
System.loadLibrary("xjni");
}
public native String getStr(String s);
}
getStr方法顯示錯誤紅色,不用著急,我們選中函式名,按快捷鍵alt+enter:
選擇create function後,函式就自動在XJni.c檔案中生成了
#include <jni.h>
JNIEXPORT jstring JNICALL
Java_com_test_jnitest4_XJni_getStr(JNIEnv *env, jobject instance, jstring s_) {
const char *s = (*env)->GetStringUTFChars(env, s_, 0);
// TODO
(*env)->ReleaseStringUTFChars(env, s_, s);
return (*env)->NewStringUTF(env, returnValue);
}
需要注意的是,你最好讓.java檔名與.c檔名同名,否則你可能快捷鍵不會出現create function選項。修改.c檔名的時候記得對應將CMakeLists.txt中修改。
總之,JNI入門難度大大降低,AS在這方面還有很多適用的功能提供,例如debug、在c程式碼中輸入日誌到logcat等,只需簡單操作就可完成,非常人性。
相關推薦
Android筆記之使用CMake進行JNI開發(Android Studio)
不知道有多少朋友像我一樣,被Android NDK開發的環境配置折騰到吐,然後放棄。從事Android工作幾年了,也不太願意接觸NDK開發。不過福利終於來了,新的AS中開始使用CMake開發jni,開發c跟開發java一樣簡單,你只需單純的執著於業務目標,跟折騰
手把手教你如何在Android下進行JNI開發(入門)
在進行Android開發的過程中,我們必定會遇到視訊影象處理、高強度密集運算、特殊演算法等場景,這時我們就不得不需要去接觸一些C/C++程式碼,進行JNI開發。下面我將從Android.mk和CMake這兩種方式教大家如何進行開發。文章結尾將給出演示的專案程式碼,如果你能耐心地仔細看完,相信你一定能掌握
AndroidStudio3.0使用Cmake進行JNI開發
前言 最近專案上做到了直播和音視訊的播放,這裡不可避免的涉及到了Android JNI開發。於是去市面上找到一本資料《音視訊開發進階指南》,我看出版時間很近是2017年12月。結果遇到了大坑,裡面的所有demo都是基於eclipse。包括作者提供的原始碼也是e
Android之VideoView 進行播放視訊 (不更新)
Android自帶了VideoView 一個可以播放本地視訊和網路視訊的類 所以說許可權我們一定不要忘記新增 <uses-permission android:name="android.permission.INTERNET"></uses-permi
在androidstudio中用cmake進行jni開發
首先在建立專案的時候勾選c++支援 在建立好的專案中stuido會自動給gradle配置cmake 接下來只需要在main下面的cpp目錄中編寫你想要的c程式碼,然後引用就可以 直接通過System.loadLibrary("nati
JavaSE 學習筆記之網絡編程(二十三)
-c 可能 nbsp blog col accept 接收 存儲 pri 端口: 物理端口: 邏輯端口:用於標識進程的邏輯地址,不同進程的標識;有效端口:0~65535,其中0~1024系統使用或保留端口。 java 中ip對象:InetAddress. import
Linux學習筆記之四————Linux常用命令 ( 待補充)
-h http “.” 現實 人性化 快捷 我們 包括 無法 一、Linux命令——文件、磁盤管理 1.文件管理 <1>查看文件信息:ls ls是英文單詞list的簡寫,其功能為列出目錄的內容,是用戶最常用的命令之一,它類似於DOS下的dir命令。 Linu
ES6系列_13之Proxy進行預處理(簡單學習)
預處理 當我 con bubuko 上下文對象 prope {} ons ive 1.理解什麽是預處理? 當我們在操作一個對象或者方法時會有幾種動作,比如:在運行函數前初始化一些數據,在改變對象值後做一些善後處理。這些都算鉤子函數,Proxy的存在就可以讓我們給函數加上這樣
《機器學習實戰》學習筆記之樸素貝葉斯(Naive Bayes)
原理 假如郵箱中有n個單詞, 如果returnVec[i]=0代表這個單詞在這封郵件中不出現, returnVec[i]=1代表這個單詞在郵件中出現了。 設訓練集中每個郵件都有標記為是垃圾郵件和不是垃圾郵件,是垃圾郵件的分類為1,不是垃圾郵件的分類為0。 演算法原理:
Android專案開發筆記之登入註冊模組實現(客戶端+服務端)
寫在前面 斷斷續續開發了幾個月的App終於告一段落,雖然它可能還很不完美,不過作為上手Android的第一個完整專案,確實從中學到了蠻多,所以開個系列記錄一下~本篇先從基本上每個App都會有的登入註冊講起,包含自動登入、記住密碼功能的實現=w= 實現
Android開發之CriminalIntent項目開發(其一)
開發項目 1.0 enc 增加 委派 其他 date 應用 module 前言 這次的開發項目是一個叫做CriminalIntent的應用,該應用可以詳細記錄各種辦公室陋習。這個應用記載的陋習記錄包括標題、日期和圖片,支持在聯系人中查找當事人,通過E-mail、Twit
IDEA 學習筆記之 Java項目開發深入學習(1)
java項目 bsp 重構 str 代碼提示 log pan ora tro Java項目開發深入學習(1): 定義編譯輸出路徑: 繼承以上工程配置 重新定義新的項目編譯路徑 添加source目錄:點擊添加,再點擊移除: 編譯項目: 常用快捷鍵總結: Ctr
android開發 之OkHttp二次封裝(android 訪問網路)
這個是本人在使用的一個網路請求,根據自己的需求進行修改的,對於自己完全夠用。大家有需要可以根據自己的專案修改成自己需要的。如果有什麼問題,還希望告知。 使用時繼承該類即可 import android.os.Handler; import android.os.Message;
【Visual C++】遊戲開發筆記之十 基礎動畫顯示(三) 透明動畫的實現
作者:毛星雲 郵箱: [email protected] 歡迎郵件交流程式設計心得"透明動畫”是遊戲中一定會用到的基本技巧,它通過圖案的連續顯示及圖案本身背景的透明化處理,在背景圖上產生出栩栩如生的動畫效果。看過之前筆記的朋友們應該知道,在筆記六裡我們介紹
AndroidNDK初步開發之安裝eclipse外掛支援jni開發(一)
因為初次使用AndroidNDK開發,而且使用的是Google近乎遺棄的Eclipse,去jni開發,實在是一件實為苦惱的事,花了我2天的時間~下面把我會分2節來“完美”的說明使用eclipse進行jni開發的步驟。 首先當然是安裝NDK,這裡要說明一
Android Studio Jni開發(二)實現Native呼叫java方法和Native呼叫Android API
這一篇主要內容是Native呼叫java方法和Native呼叫Android API,以及External Tools快速生成.h檔案,依然是使用NDK方式編譯,如果是複製貼上黨,建議跟本文用一樣的工程名,本文後面會提供demo連結 一、建立工程 1.建立名為Jnites
Android筆記之(圖片高斯+Glide實現微信圖片載入策略+仿微信進度條)
很久以前就想自己實現一下仿微信圖片載入的那種策略了,先載入一張模糊的圖片,然後再載入清晰大圖,今天研究了一下,不過要是Glide支援進度條顯示就好了,不得不說Glide很強大, 不囉嗦了,直接上程式碼了。 首先看看高斯模糊到底怎麼實現,你問我我也不會(^__
Android基礎學習筆記之-ListView進階用法(item圓角效果實現)
今天簡單用快取優化方式實現了listview的功能,下面讓我們實現一下上篇文章留下來的改進方案: 1).實現item佈局的圓角效果 2).對listview的item進行監聽
android使用CMake進行jni編寫遇到的一些問題
前言 android studio 2.2之後出的CMake 讓jni的編寫方便了很多,使用CMake讓我們不在煩惱函式的定義,以前我們需要通過javah命令生成,jni規定的函式名
【Visual C++】遊戲開發筆記之四——遊戲畫面繪圖(一)基本圖形繪製
毛星雲,網路ID「淺墨」,90後,熱愛遊戲開發、遊戲引擎、計算機圖形、實時渲染等技術,就職於騰訊互娛。 微軟最有價值專家 著作《Windows遊戲程式設計之從零開始》、《OpenCV3程式設計入門》 碩士就讀於南京航空航天大學航天學院(2013級碩士研究生),已於2016年三月畢業。本科