前言:

  从Android Studio开始,就支持jni和.so库调用了。

环境:

  Windows 7+Android Studio2.1.2+NDK版本:android-ndk-r10e

准备工作:

  1) ndk文件:

    1,可以根据需求,从网上下载, 网址(科学上网): https://developer.android.com/ndk/downloads/index.html

    2,可以查找下当前电脑是否已有ndk包,我的在目录:

      C:\ProgramData\Microsoft\AndroidNDK64\android-ndk-r10e

  2)配置环境变量:

    选中System的path变量,进行编辑,把  ;C:\ProgramData\Microsoft\AndroidNDK64\android-ndk-r10e添加到最后,保存:

      

      

       

开始:

  Step1:新建一个项目

  Step2:添加C代码和Android.mk文件

   Demo中我们直接使用ndk包自带的C代码做示例,此处我使用hello-jni的代码:

  a) 将jni文件夹整体copy,粘贴到main文件夹下:

    

  b)在activity_main.xml中添加一个Button:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="me.jnidemo.myjnidemo.MainActivity"
android:orientation="vertical"> <TextView
android:id="@+id/edv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" /> <Button
android:id="@+id/clickId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="clickBtn"/>
</LinearLayout>

  d)新建一个class为NdkJniUtils,在内部声明native方法(jni使用的定义,使用关键字native)  

package me.jnidemo.myjnidemo;

/**
* Created by c-yangx on 6/22/2016.
*/
public class NdkJniUtils {
static{
System.loadLibrary("hello-jni");//.so文件格式为:lib+库名+.so
}
public static native String stringFromJNI();//函数名与C代码的函数名保持一致
}

  c)修改hello-jni.c文件中的函数名称,格式为:Java_包名_类名_函数名( Java_me_jnidemo_myjnidemo_NdkJniUtils_stringFromJNI)

  d) jni文件夹 右键=>show in Explorer 进入目录;cmd进入此文件夹中,ndk-build命令进行编译:

    此编译会触发gradle,项目中会自动多出libs文件夹:

      

  e)此时在MainActivity.java中添加Button的点击事件:

package me.jnidemo.myjnidemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView; public class MainActivity extends AppCompatActivity { TextView ev1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); ev1=(TextView)findViewById(R.id.edv) ; Button btn=(Button)findViewById(R.id.clickId);
btn.setOnClickListener(new Button.OnClickListener(){
@Override
public void onClick(View v) {
String res=NdkJniUtils.stringFromJNI();
ev1.setText(res);
}
});
}
}

  f) 在gradle.properties中添加配置: android.useDeprecatedNdk=true;

   在local.properties中添加 ndk.dir=C\:\\ProgramData\\Microsoft\\AndroidNDK64\\android-ndk-r10e

   否则gradle会抛异常

  g)运行,触发click事件时,会抛异常:

- ::04.174 -/me.jnidemo.myjnidemo E/AndroidRuntime: FATAL EXCEPTION: main
Process: me.jnidemo.myjnidemo, PID:
java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/me.jnidemo.myjnidemo-1/base.apk"],nativeLibraryDirectories=[/vendor/lib64, /system/lib64]]] couldn't find "libhello-jni.so"
at java.lang.Runtime.loadLibrary(Runtime.java:)
at java.lang.System.loadLibrary(System.java:)
at me.jnidemo.myjnidemo.NdkJniUtils.<clinit>(NdkJniUtils.java:)
at me.jnidemo.myjnidemo.MainActivity$.onClick(MainActivity.java:)
at android.view.View.performClick(View.java:)
at android.view.View$PerformClick.run(View.java:)
at android.os.Handler.handleCallback(Handler.java:)
at android.os.Handler.dispatchMessage(Handler.java:)
at android.os.Looper.loop(Looper.java:)
at android.app.ActivityThread.main(ActivityThread.java:)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:)

  因此我们还需进行配置----在build.gradle中做一个资源路径指定即可:

// build.gradle
android {
//
//...
sourceSets {
main {
//你的源码目录
jniLibs.srcDirs 'src/main/libs'
}
}
}

  重新编译运行,ok了:

补录:

  a)指定生成基于哪些CPU架构的.so文件:

    1) Application.mk文件配置方式:

      本文配置项,生成的为全架构平台的.so文件,缺点是会使得apk包变大:

    可以修改,指定多个平台。如: APP_ABI := armeabi armeabi-v7a x86 mips

   b)build.gradle配置方式:在app module目录下的build.gradle中设置库文件名(生成的so文件名),找到gradle文件的defaultConfig这项,在里面添加如下内容:

defaultConfig {
......
ndk{
//moduleName "YanboberJniLibName" //生成的so名字
abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库。目前可有可无。
}
}

  b) Android.mk配置含义:

LOCAL_PATH := $(call my-dir)     #提定当前路径

include $(CLEAR_VARS)            #清除全局配置变量,LOCAL_XXX,除了LOCAL_PATH

LOCAL_MODULE    := hello        #指定生成动态库名hello,生成的动态库文件libhello.so
LOCAL_SRC_FILES := hello.c #指定生成动态库的源文件 include $(BUILD_SHARED_LIBRARY) #提定生成动态库

后续:

  a) Bug 1 =>  app:compileDebugNdk FAILED

    

    最近在研究WebRtc的APM(Audio_Processing_Module)音频处理模块,将所有的C代码文件导入项目,通过ndk-build命令在cmd窗口编译时,一切ok。

  但是项目编译时却报此错误,最后(科学上网)找到了解决方案(网址:http://stackoverflow.com/questions/27453085/execution-failed-for-task-appcompiledebugndk-failed-to-run-this-command-ndk),

    

    大体意思就是说gradle尝试自己编译你的源文件,而不是使用你编译好的.so文件。既然在cmd中编译通过了,那么咱们可以通过配置,禁用gradle的ndk调用行为

  ,而使用你配置的路径下的.so文件。于是,我在app build.gradle中添加了 =>  jni.srcDirs = [],然后编译运行,一切ok了。

       

    

Android Studio--NDK编译C代码为.so文件,JNI调用的更多相关文章

  1. Android studio NDK 编译 "$USE_DEPRECATED_NDK=true" 异常问题解决

    我的项目是https://github.com/leixiaohua1020/simplest_ffmpeg_mobile/tree/master/simplest_ffmpeg_android_st ...

  2. Android Studio NDK 学习之接受Java传入的字符串

    本博客是基于Android Studio 1.3 preview版本,且默认你已经安装了Android SDK, Android NDK. 用Android Studio新建一个工程叫Prompt,其 ...

  3. Android Studio NDK环境配置

    本文参考:Android Studio NDK环境配置及JNI使用方法:http://blog.csdn.net/tongseng/article/details/53005123 并添加自己的实践: ...

  4. Android Studio NDK编程初探

    继上一篇学习了如何使用NDK编译FFMPEG后,接下来就是要学习如何在Android Studio中使用了. 经过参考和一系列的摸索,记录下具体步骤. 创建C++ Support的Android St ...

  5. Android studio 加速编译方法

    JRebel for Android 是一个Android Studio的插件,可以大大加速Android Studio的编译速度,对于小项目来说或许不明显:但是当项目达到一定的规模时,它对于Andr ...

  6. 【Android】Android Studio NDK 开发

    Android Studio NDK 开发 记录在Android Studio中NDK简单开发的步骤 用到的Android Studio版本为3.5. 配置NDK 下载NDK 一般在SDK下已经有自带 ...

  7. Android 使用NDK编译二进制文件并运行

    Android 使用NDK编译二进制文件并运行本文介绍如何编译可以在Android平台上运行的二进制可执行文件. 首先我们,知道,Android是基于Linux的,而在Linux上,可以执行二进制文件 ...

  8. 使用Android Studio向GitHub提交代码

    使用Android Studio向GitHub提交代码 在GitHub上创建一个仓库 填写仓库名称.描述.类型(公有.私有)等信息,点击创建 到此,成功创建了我们的仓库,并且初始化创建了README. ...

  9. 加快Android Studio的编译速度

    从Eclipse切换到Android Studio后,感觉Android Studio的build速度比Eclipse慢很多,以下几个方法可以提高Android Studio的编译速度 使用Gradl ...

随机推荐

  1. OpenDigg - 挖掘优质开源项目库

    OpenDigg - 挖掘优质开源项目库 OpenDigg专注于挖掘优质的开源项目库,通过技术和人工将软件项目分类整理,同时辅助简要的编译,方便广大程序员便捷地找到需要的开源项目. OpenDigg刚 ...

  2. python 操作solr索引数据

    测试代码1: def test(self): data = {", "*字段名*": u"我是一个大好人"}}} params = {"bo ...

  3. mac更新系统后Git不能用,提示missing xcrun at

    今天更新了mac系统,然后就踩了这个坑. 启动AndroidStudio 右上角提示: can't start git: /usr/bin/git probably the path to git e ...

  4. Android实现批量照片上传至server,拍照或者从相冊选择

    近期因为项目需求,须要完毕批量照片上传,折腾了一段时间,最终完毕了,达到了例如以下效果 主界面主要有GridView组成和button组成,当按下一个格点时,会调用相机或者相冊,拍照或者选择相冊照片, ...

  5. 集成方法:渐进梯度回归树GBRT(迭代决策树)

    http://blog.csdn.net/pipisorry/article/details/60776803 单决策树C4.5由于功能太简单.而且非常easy出现过拟合的现象.于是引申出了很多变种决 ...

  6. UVALive 3971 Assemble(模拟 + 二分)

    UVALive 3971 题意:有b块钱.想要组装一台电脑,给出n个配件的种类,名字,价格,品质因子.若各种类配件各买一个,总价格<=b,求最差品质配件的最大品质因子. 思路: 求最大的最小值一 ...

  7. SEO优化100条

    1.准备个好域名.①.尽量在5位数内,当然也不一定,反正要让用户好记.(看个人):②.尽量用顶级的域名,搜索排名感觉好一点.③.做中文站最好用拼音注册,不要问为什么.看百度(baidu.com)就是很 ...

  8. vue 预渲染 prerender-spa-plugin

    1.预渲染说明 https://ssr.vuejs.org/zh/#为什么使用服务器端渲染-ssr-? 如果你调研服务器端渲染(SSR)只是用来改善少数营销页面(例如 /, /about, /cont ...

  9. 提高PAAS安全性的一点尝试

    云服务已经成为现代人生活的一部分.手机中的照片会自己主动同步到云中:你的邮件内容保存在云中.办公软件执行在云中:你的健康数据会实时上传到云中.你每天的生活轨迹消耗的卡路里也会上传到云中:云服务也会逐渐 ...

  10. Jenkins spring boot 自动部署方案

    原文地址:http://www.cnblogs.com/skyblog/p/5632869.html 现在主流的自动部署方案大都是基于Docker的了,但传统的自动部署方案比较适合中小型公司,下面的方 ...