『壹』 android studio中怎麼打包.so庫文件
首先在Android Studio工程的app目錄下創建整個jni目錄,jni目錄里寫Android.mk、Application.mk以及各類C/C++和匯編源文件。然後跟原來一樣,用ndk_build工具去編,然後工具會自動生成libs目錄,裡面還有每個你在Application.mk里所指定處理器架構的so文件。
完成之後,編輯你對應mole(類似eclipse中的project)目錄下的build.gradle文件,為其添加以下代碼:
[html] view plain
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
比如本人mole完整的build.gradle文件如下所示:
[html] view plain
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "21.1.1"
defaultConfig {
applicationId "com.example.way.aligesture"
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile project(':acra')
compile project(':hwdroid')
}
最後記得選中對應的mole右擊synchronize同步一下,以便使其生效。如下圖所示,mole目錄下回生成一個jniLibs目錄,再打包生成的apk就會帶上.so了。
『貳』 為什麼Android studio裡面沒有Android.mk只有CmakeList.txt
因為android studio2.2之後的版本就用CMakleLists了,mk拋棄了,CMakeLists文件理解起來更容易也更加容易編寫,並且CMakeLists也能在linux平台進行編譯。
『叄』 android studio 怎樣進行jni開發
方法如下:
1.添加如下代碼在MainActivity類內
static {
System.loadLibrary("hello_jni");
}
public native String getstringfromC();
2.打開終端,android studio已經提供了終端
3.首先進入java目錄執行命令:
javah -d ../jni com.example.root.ndk_sample.MainActivity
com.example.root.ndk_sample.MainActivity是native函數的所在的包名和類名,中間使用「.」號分開
4.添加*.c文件在jni目錄中
5.編寫Android.mk和Application.mk 放在jni目錄下面
6.Android.mk文件的內容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE :=hello_jni
LOCAL_SRC_FILES := hello_jni.c
include $(BUILD_SHARED_LIBRARY)
Application.mk 文件內容為:
APP_ABI := all
APP_OPIM :=debug
『肆』 Android Studio安裝這個問題怎麼辦急求
試試重裝。顯示說,不能創建sd卡。mk是make,sd是模擬機器中sd卡。你試試更改許可權。右鍵,以管理員許可權運行一下。不一定能行。我這是第一次遇到這個報錯的。也有可能文件沒下載全(androidstudio)。
『伍』 android studio android.mk在哪
Android.mk文件首先需要指定LOCAL_PATH變數,用於查找源文件,宏函數』my-dir』, 由編譯系統提供。由於一般情況下Android.mk和需要編譯的源文件在同一目錄下,所以定義成如下形式:
LOCAL_PATH:=$(call my-dir)
上面的語句的意思是 將LOCAL_PATH變數定義成 本文件所在 目錄路徑。
一個 Android.mk中 可以 定義 多個編譯模塊,每個編譯模塊 都是 以include $(CLEAR_VARS)開始
以include $(BUILD_XXX)結束
相關鏈接:http://blog.csdn.net/wh_19910525/article/details/7518190
『陸』 android studio 開發NDK,怎麼使用第三方的C++代碼
使用AndroidStudio的experimental plugin或是傳統的Android.mk,通過jni封裝調用第三方動態鏈接庫的方法有共通之處,也有不同之處。
http://blog.csdn.net/l465659833/article/details/52318740
『柒』 android studio nd開發到底要不要自己配置.mk文件
Android Studio 可以配置build.gradle , main/jni文件夾中的c/c++文件會自動打包成so,但是如果有不同模塊的文件,要編譯出多個so文件,就不知道在gradle文件中咋配置了(可能也可以配置),這時就可以用原來eclipse的寫法;
main/jni文件夾按照原來eclipse的方法去寫Android.mk和Application.mk,然後在main目錄下執行ndk-build命令,該目錄下會創建libs目錄,里邊就是生成的so,將項目配置的jniLibs.srcDirs指向src/main/libs就行;
這時有幾個問題,一個是AS會自動重復編譯jni中的文件,打包後會多一個沒用的so,還有如果用了第三方的so文件會和自己項目的so文件沖突,因為每次ndk-build後都會刪除原來文件夾中的其他so文件.
先去掉 defaultConfig中的ndk配置,然後配置 :
sourceSets{
main{
//指定so庫的位置,前邊的是自己項目的,後邊的是第三方的so
jniLibs.srcDirs=['src/main/libs','libs']
//禁止 android studio 自動編譯
jni.srcDirs=[]
}
}
『捌』 為什麼android studio 打包的程序進程不識別
1,過程感慨(想直接看教程,請跳過此部分) 在寫具體內容之前,我先說下我搞這個東西的過程,由於導師之前說過要搞個圖像匹配的androi APP,具體就是匹配前後兩張圖片的相似度,類似 安卓5/project/opencvlibrary/opencv-android/3%2F&ts=1436167636&use_mirror=nchc 編譯/asmcvc/article/details/9311573,我上面說了,不一定要用它,win 自帶的 cmd 也可以編譯。如果使用 cygwin,要做好心理准備,下載和安裝它,非常非常的久,文件總體積 20 多G!!!!我是用了9個多小時。 3,---opencv for android 的sdk 下載完成後。打開 該文件夾,sdk/native/libs,裡面有很多平台的文件夾,能在裡面出現的,證明你能夠在下面的 Application.mk 中設置生成對應的架構的 .so文件,我舉個例子,我的是: 在下面介紹的 Application.mk 文件中有一句話 ,它是用來設置生成 對應架構的 .so 文件,我這里是armeabi-7a,如果要生所有的,寫出 :=all,注意,這樣很可能會報錯,錯誤信息是,某種架構找不到,所以,我要你看清楚,上面文件夾裡面有哪些架構,這些 坑是網上找不到,如果你要生成兩種,可以輪著來編譯,第二次的編譯,不同的架構是不會覆蓋的。現在打開 sdk/native/jni,如無意外,裡面肯定有個 文件叫做 OpenCV.mk,它就是我們在 android.mk 腳本文件中要引入 opencv C++庫所要參照的文件。請用記事本 或者Notepad++ 打開。 4,---了解 Android.mk 和 Application.mk 文件的基本內容信息:下面我使用默認的 Android.mk 來說明,和我的例子的 Application.mk 來說明。 它們都是腳本文件。 Android.mk Application.mk 4,編譯 .so 使用你的 as 創建一個新項目,然後在你的 項目的 main 目錄下創建一個一個 jni 文件夾,這樣創建: 創建好了之後,是這樣的: 首先編譯 項目的頭文件 .h,一般編譯出來後,它的名字結構是:包名_類名.h 編譯命令如下,請在你的 as 下面的 Terminal 裡面輸入: SourcePath: D:\work\androidstudio\VisualRecognition\app\src\main\java (絕對路徑) TargetPath: D:\work\androidstudio\VisualRecognition\visual\src\main\jni (絕對路徑) TargetClassName: com.yf.visualrecognition.UnityPlayerActivity (你的包名+類名) 格式: javah -d ${SourceFile} -classpath ${TargetPath} ${TargetClassName} 控制台指令:javah -d D:\work\androidstudio\VisualRecognition\visual\src\main\jni -classpath D:\work\androidstudio\VisualRecognition\app\src\main\java io.github.froger.jni.MyActivity 然後在你的jni 文件夾下面 分別創建 Android.mk 、Application.mk 和你要編譯的 .cpp 或者.c 文件,前兩個的 內容可以模仿我上面介紹的, .cpp 我這里提供一個。 Android.mk 、Application.mk 、ImgFuncpp 分別如下,util.c 是空文件,之所以創建它是為了避免另外一個 bug,這不說: Android.mk 文件如下 LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)OPENCV_LIB_TYPE:=STATICifeq ("$(wildcard $(OPENCV_MK_PATH))","")include E:\OpenCV-3.0.0-android-sdk-1\OpenCV-android-sdk\sdk\native\jni\OpenCV.mkelseinclude $(OPENCV_MK_PATH)endifLOCAL_MODULE := ImgFunLOCAL_SRC_FILES := ImgFun.cppLOCAL_LDLIBS += -lm -lloginclude $(BUILD_SHARED_LIBRARY) Application.mk 文件如下 APP_STL := gnustl_staticAPP_CPPFLAGS := -frtti -fexceptionsAPP_ABI := armeabi-v7a #這句是設置生成的cpu指令類型,提示,目前絕大部分安卓手機支持armeabi,libs下太多類型,編譯進去 apk 包會過大APP_PLATFORM := android-8 #這句是設置最低安卓平台,可以不弄 ImgFun.cpp 文件如下 1 #include <io_github_froger_jni_MyActivity.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <opencv2/opencv.hpp> 5usingnamespace cv; 6 IplImage * change4channelTo3InIplImage(IplImage * src); 7 8extern"C" { 9JNIEXPORT jintArray JNICALL Java_io_github_froger_jni_MyActivity_ImgFun(10 JNIEnv* env, jobject obj, jintArray buf, int w, int h);11JNIEXPORT jintArray JNICALL Java_io_github_froger_jni_MyActivity_ImgFun(12 JNIEnv* env, jobject obj, jintArray buf, int w, int h) {1314 jint *cbuf;15 cbuf = env->GetIntArrayElements(buf, false);16if (cbuf == NULL) {17return0;18 }1920 Mat myimg(h, w, CV_8UC4, (unsigned char*) cbuf);21 IplImage image=IplImage(myimg);22 IplImage* image3channel = change4channelTo3InIplImage(&image);2324 IplImage* pCannyImage=cvCreateImage(cvGetSize(image3channel),IPL_DEPTH_8U,1);2526 cvCanny(image3channel,pCannyImage,50,150,3);2728int* outImage=newint[w*h];29for(int i=0;i<w*h;i++)30 {31 outImage[i]=(int)pCannyImage->imageData[i];32 }3334int size = w * h;35 jintArray result = env->NewIntArray(size);36 env->SetIntArrayRegion(result, 0, size, outImage);37 env->ReleaseIntArrayElements(buf, cbuf, 0);38return result;39}40}4142 IplImage * change4channelTo3InIplImage(IplImage * src) {43if (src->nChannels != 4) {44return NULL;45 }4647 IplImage * destImg = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 3);48for (int row = 0; row < src->height; row++) {49for (int col = 0; col < src->width; col++) {50 CvScalar s = cvGet2D(src, row, col);51 cvSet2D(destImg, row, col, s);52 }53 }5455return destImg;56 } 上面 .cpp 文件的有幾句話要說明下,注意 .c 文件和 .cpp 文件是不一樣的: 1,請用 extern "C" { } 包住 你要你的 c++ 函數體的定義和裡面的變數,函數聲明可以在外面。 2,JNIEXPORT jintArray JNICALL Java_io_github_froger_jni_MyActivity_ImgFun(JNIEnv* env, jobject obj, jintArray buf, int w, int h); 3,jintArray 是你定義的函數的返回值,我這里的是int數組,它在類型的前面有一個 j ,如果是字元串,那麼就是 jstring,數組加上Array; 4,JNICALL Java 這句不變,所有都一樣,注意java的 j 是大寫; 5,io_github_froger_jni 這里是你的包名; 6,MyActivity 你的類名,要引用這個這里C++函數的類名; 7,ImgFun 是你要在java中調用的函數名字,哪些不用直接被調用的,不用寫; 8,JNIEnv* env, jobject obj, 這個固定不變,第一個的意思是虛擬機引用,第二個是項目; 9,jintArray buf, int w, int h 函數的參數。 好了,上面該介紹的已經介紹完了,接下來是編譯 .so 的正式操作(我這里使用cmd做例子,因為它更簡單操作,cygwin也可以)。 你可以在 as 的 cmd 中或者 系統的 cmd框中實現編譯,首先使用命令進入到當前的 jni 文件夾的 目錄,例如,我的是 D:asproject/JniDemo/app/main/jni,然後使用命令 ndk-build,(使用ndk-build命令這一步,需要你已經配置好了 ndk 環境,請參照網路上面的教程)然後回車,如無意外,將會生成如下文件: 其中的 .so 文件就是我們所需要的,現在打開你項目app下的 build.gradle 文件,在 android{} 裡面加入: sourceSets {main() {jniLibs.srcDirs = ['src/main/libs']}} 這樣是為了使用 .so文件,上面我們僅僅是生產! OK,到這里基本大功告成了,不過,筆者我就是在這一步之後,運行程序的時候,出現的簡單的致命的 bug,導致我找了近2星期,現在想起來真是蠢.............. 5,遇到的關鍵問題及其解決方法 運行程序,出現,如下錯誤,這里聲明下,不僅僅是 opencv2/opencv.hpp,還可能是其他的 hpp。 出現的原因: 原來是這樣的,android studio 在我們編譯完 .so 文件後,我們在Android.mk 文件中設置引入的opencv 函數庫,是已經被編譯進去.so 動態庫裡面了的,而我們編譯所需要的 cpp 文件,它在 jni 文件夾呢,自然就沒有 opencv 庫可依賴,所以。 解決方法: 在你編譯完.so 文件後,就可以把 cpp 或者 c 文件裡面的內容 注釋或者刪除了,不然在你運行程序的時候就會拋出頭文件找不到的錯誤,哎,真是辛酸淚,這樣一個 bug 搞了我 那麼多時間,不過還好,還是解決了。 6,實現效果截圖。 1package io.github.froger.jni; 2 3import android.app.Activity; 4import android.graphics.Bitmap; 5import android.graphics.drawable.BitmapDrawable; 6import android.os.Bundle; 7import android.view.View; 8import android.widget.Button; 9import android.widget.ImageView;1011publicclass MyActivity extends Activity {12/** Called when the activity is first created. */13 ImageView imgView;14 Button btnNDK, btnRestore;15publicstaticnativeint[] ImgFun(int[] buf, int w, int h);16static {17 System.loadLibrary("ImgFun");18 }19 @Override20publicvoid onCreate(Bundle savedInstanceState) {21super.onCreate(savedInstanceState);22 setContentView(R.layout.activity_my);2324this.setTitle("使用NDK轉換灰度圖");25 btnRestore = (Button) this.findViewById(R.id.btnRestore);26//btnRestore.setText(ImgFun());27 btnRestore.setOnClickListener(new ClickEvent());28 btnNDK = (Button) this.findViewById(R.id.btnNDK);29 btnNDK.setOnClickListener(new ClickEvent());30 imgView = (ImageView) this.findViewById(R.id.ImageView01);31 Bitmap img = ((BitmapDrawable) getResources().getDrawable(32 R.drawable.ic_launcher)).getBitmap();33 imgView.setImageBitmap(img);34 }3536class ClickEvent implements View.OnClickListener {37publicvoid onClick(View v) {38//btnRestore.setText(ImgFun());39if (v == btnNDK) {40long current = System.currentTimeMillis();41 Bitmap img1 = ((BitmapDrawable) getResources().getDrawable(42 R.drawable.ic_launcher)).getBitmap();43int w = img1.getWidth(), h = img1.getHeight();44int[] pix = newint[w * h];45 img1.getPixels(pix, 0, w, 0, 0, w, h);46int[] resultInt = ImgFun(pix, w, h);47 Bitmap resultImg = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);48 resultImg.setPixels(resultInt, 0, w, 0, 0, w, h);49long performance = System.currentTimeMillis() - current;50 imgView.setImageBitmap(resultImg);51 } elseif (v == btnRestore) {52 Bitmap img2 = ((BitmapDrawable) getResources().getDrawable(53 R.drawable.ic_launcher)).getBitmap();54 imgView.setImageBitmap(img2);55 }56 }57 }585960 }