Android NDK编译
记录下ndk如何编译.so文件 按部就班的说下: 首先下载NDK,这个我是直接在Android studio里面下载的,也没去官网下载,下载好了,就是配置环境变量了,因为我是从Android studio里面下载的,所以就直接在path中配置D:android_sdk/ndk-bundle这个路径了,配好了后我们可以用ndk-build去cmd命令台检测下看下是否配置成功 接下来就是在Android studio中配置了,需要在sdklocation中配置下,还有local.properties以及gradle.properties中去配置,具体配置网上一大堆,这里没有难点 首先我们想要打出一个.so文件来,我们肯定是要先写Java代码
第一步: 解释一下这里代码的意思: native这个就是我们提供出去的方法,这个方法到时候要和.c文件里面或者.cc文件里面的方法名一致,我们再静态中去加载我们打出来的.so文件, 这里的参数名字不是.so文件的名字,而是我们在打包的时候配置的名字,这个配置下面介绍
[code]public class JniKit { //这里的方法名如果报错那是正常的,不影响 public static native int calculate(int num); static { System.loadLibrary("JniDemo"); } }
第二步: 我们需要根据这个写好的Java文件来生成一个.h文件,生成.h文件是通过javah来执行的,这里我之前尝试了各种办法,但是网上说的办法都没办法成功,都是报错说找不到类文件,我觉得这里可能和我的文件的方法有点问题,等会我把我现在成功的文件目录贴出来,执行的代码
[code]javah -classpath D:\360PhoneInfo\small-video-record-master\SmallVideoRecord2\testndk\build\intermediates\classes\debug -d jni com.example.testndk.JniKit
根据这个代码我得到了.h文件,包括这个jni文件夹也是通过-d jni这个生成出来的,不是自己创建的
第三步: 现在我们有了.h文件了,接下来就是写.c文件了,当然了我不会c语言,所以这里拿了一个测试的来用,c这部分的不用关注太多 include中指向你创建的.h头文件 Java_com_example_testndk_JniKit_calculate;Java_包名_类名_方法名(参数)
[code]#include "com_example_testndk_JniKit.h" JNIEXPORT jint JNICALL Java_com_example_testndk_JniKit_calculate(JNIEnv *env, jclass cls, jint num) { return num * num; }
第四步: 现在.h.c文件我们都有了,接下来就是最关键的一步了,生成.so文件了,这一步,我查阅了很多资料,折磨了两个小时,才弄出来,这里我不知道是不是我的配置有问题,还是什么问题,反正我在build.gradle配置,然后去Make Project生成了很久没有生成出来,这里我是用命令行中的ndk-build来解决的
解决方式如下:
1.建立一个Android.mk文件 LOCAL_MODULE表示模块名称 LOCAL_SRC_FILES表示需要参与编译的源文件,就是我们的c 除了这两个,其他照搬即可
[code]LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := JniDemo LOCAL_SRC_FILES := jni_test.c LOCAL_LDLIBS +=-L$(SYSROOT)/usr/lib -lm -llog include $(BUILD_SHARED_LIBRARY)
2.建立一个Application.mk文件 需要注意的东西都写在里面了,以逗号分割cpu指令
[code]APP_STL := gnustl_static APP_CPPFLAGS := -frtti -fexceptions APP_ABI := armeabi-v7a #这句是设置生成的cpu指令类型,提示,目前绝大部分安卓手机支持armeabi,libs下太多类型,编译进去 apk 包会过大 APP_PLATFORM := android-8 #这句是设置最低安卓平台,可以不弄
3.因为我的这两个文件是和.h.c放在同一个文件夹中-jni,所以我们要执行ndk-build命令需要进入到jni文件夹下再去执行,比如说D:\360PhoneInfo\small-video-record-master\SmallVideoRecord2\testndk\src\main\jni>ndk-build 如此执行完后就会在 main目录下生成一个libs文件夹,里面有我们配置好的.so文件 ,如下:
好了,大功告成,测试下吧,我新建了一个工程,将.so包都拷过去了,还有Jnikit.Java文件也拷过去了,因为这是我们当初定义的Java文件,必须拷过去嘛,这里要注意的是,移到其他项目使用,必须把含有native方法的java文件放在与生成so文件的同包名下,也就是说我们当初在打.h文件时候是什么包路径,现在也应该是,我把我测试工程的路径贴上
这里可以看到我的Jnikit之前就是在com.example.testndk包下的,现在也是在这个包下,然后就是在build.gradle中配置了,这个配置不难
[code] sourceSets {//在Android的根目录下配置 main { //你的源码目录 jniLibs.srcDirs 'src/main/libs' } }
接下来我把我成功调用了的方法贴出来
[code]package com.example.test; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.TextView; import com.example.testndk.JniKit; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final TextView viewById = (TextView) findViewById(R.id.tv); findViewById (R.id.btn).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { try { int i=JniKit.calculate(4); Log.w("aaa", "---"+i); viewById.setText(i+""); } catch (Exception e) { Log.w("aaa", "---"+e.toString()); } } }); } }
如果你看到了这里,觉得文章写得不错就给个赞呗!欢迎大家评论讨论!如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足,定期免费分享技术干货。谢谢!
- 用Android NDK编译FFmpeg
- Android底层连接库的编译过程及其Android NDK开发实例
- Android NDK编译带STL的 C/C++ 程序
- Android NDK 交叉编译C++代码生成.so共享库详细步骤
- android NDK 多线程编译加速
- android NDK开发、编译、调试环境搭建与操作入门
- Android NDK 编译FFmpeg(不需要复杂的环境变量设置)
- [cocos2d-x 学习] 第一个cocos2d-x win32程序和Android NDK交叉编译
- Android Ndk 编译
- android ndk 编译方式,静态库、动态库、可执行文件
- Windows7 下Eclipse集成Cygwin配置Android NDK环境编译JNI库(1)
- android ndk开发之 extern "C" 编译出错
- 在 Ubuntu 下使用 Android NDK r4b 编译 FFmpeg 0.6.3
- windows下用ADT进行android NDK开发的详细教程(从环境搭建、配置到编译全过程)
- Android NDK一键编译
- Android NDK 编译选项设置
- eclipse里配置Android ndk环境,直接用eclipse编译.so文件
- [Android NDK]命令行编译C++代码(JNI)的方式(windows和linux通用)
- 【iOS-cocos2d-X 游戏开发之四】Cocos2dX创建Android NDK新项目并编译导入Eclipse中正常运行!
- android NDK编译(导入).a文件和编译多个so文件(转)