前言:

  从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. 通过Roslyn动态生成程序集

    之前写过篇文章如何通过Roslyn构建自己的C#脚本,今天本来打算测试一下这部分API在新的版本中的变化,结果发现它的脚本引擎找不到了,翻了一下官方文档,貌似说暂时性的移除了.便看了一下它动态生成程序 ...

  2. java工具类获取properties文件的配置

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.i ...

  3. coco2dx-2.2.2 win32启动过程(opengl 和 窗口大小初始化部分) - 学习笔记 1

    因为最近要做不同分辩率的适配,所于看了下引擎这方面的代码,记录一下当是学习笔记,cocos2d-x 版本 2.2.2 , 例子是samples\Cpp\TestCpp下的 TestCpp. 先看下ma ...

  4. CSS实现四种loading动画效果

    四种loading加载效果: <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...

  5. Spark Streaming揭秘 Day2-五大核心特征

    Spark Streaming揭秘 Day2 五大核心特征 引子 书接上回,Streaming更像Spark上的一个应用程序,会有多个Job的配合,是最复杂的Spark应用程序.让我们先从特征角度进行 ...

  6. [Linux]屏幕输出控制

    专门的术语叫做ANSI Escape sequences(ANSI Escape codes),题目并不恰当,与其说是屏幕输出控制,不如说是通过bash在兼容VT100的终端上进行输出. 主要有以下类 ...

  7. Linux文件夹、分区

    必须明确,硬盘分区的存在,是由硬盘的物理特性决定的,不会因为操作系统的不同而有所改变 所以不用对为根目录/挂载分区的同时还为/usr挂载分区感到惊讶   ====分区的概念==== 可以把一个硬盘比成 ...

  8. Dubbo超时机制导致的雪崩连接

    Bug影响:Dubbo服务提供者出现无法获取Dubbo服务处理线程异常,后端DB爆出拿不到数据库连接池,导致前端响应时间异常飙高,系统处理能力下降,核心基础服务无法提供正常服务. ​Bug发现过程: ...

  9. POJ Cow Exhibition

    题目链接:Click Here~ 题目意思自己看吧. 算法分析: 对我来想是没有想到,最后看别人的博客才知道的.要把当中的一个条件当作体积.由于两个条件都存在负数,所以还要先保证最后不会再体积中出现负 ...

  10. 使用zbar 解码二维码 条形码

    #!/usr/bin/env python # coding: u8 import os import zbar import Image import urllib import uuid def ...