‘壹’ 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 }