Android Studio2.0搭建NDK环境

现在使用Ndk开发的场景还蛮多,游戏引擎、音视频开发等都能涉及到,以前的工程大部分都是Eclipse的工程目录,但是App开发现在大部分都是在AndroidStudio开发工具中进行的,那就有个问题了?怎么在As中搭建Ndk的环境呢。这就是本篇文章所要解答的,并且会创建一个小例子,编译成.so文件,且在项目中使用。Come on….

在没具体动手之前我们想一想怎么实现比较好吧,假如我们新建一个As2.0的工程,然后按照他的目录结构把jni层文件放到指定的目录下,然后进行开发,固然可行,可行是可行,但是代价就是Sdk开发和Ndk开发就分离了,不在一个工程目录下,不符合我们的预期,那就换种思路吧。庆幸的是,As的gradle脚本功能比较强大,可以指定源码文件,操作任务等。如果只是修改一下配置文件,就把事情给做好了,那岂不是皆大欢喜。好吧 开始做了。

首先在工程Module的src目录下新建一个jni目录(存放我们的c、c++源码及mk文件)
\
然后最关键的是要在build.gradle配置一下说明jni里面的代码是咱们的ndk编译代码位置,及做一些编译任务的处理 下面配置代码由 成都 小妖 提供,特别感谢他

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<code class = "hljs mel" >task buildNative(type: Exec, description: 'Compile JNI source via NDK' ) {
     def ndkDir = android.ndkDirectory
 
     if (Os.isFamily(Os.FAMILY_WINDOWS)) {
         commandLine "$ndkDir/ndk-build.cmd" ,
                 '-C' , file( 'src/jni' ).absolutePath, // Change src/main/jni the relative path to your jni source
                 '-j' , Runtime.runtime.availableProcessors(),
                 'all' ,
                 'NDK_DEBUG=1'
     } else {
         commandLine "$ndkDir/ndk-build" ,
                 '-C' , file( 'src/jni' ).absolutePath, // Change src/main/jni the relative path to your jni source
                 '-j' , Runtime.runtime.availableProcessors(),
                 'all' ,
                 'NDK_DEBUG=1'
     }
}
//在 mac 中 commandLine "$ndkDir/ndk-build", 但是在windows中 commandLine "$ndkDir/ndk-build.cmd",额,坑
//
task cleanNative(type: Exec, description: 'Clean JNI object files' ) {
     def ndkDir = android.ndkDirectory
     if (Os.isFamily(Os.FAMILY_WINDOWS)) {
         commandLine "$ndkDir/ndk-build.cmd" ,
                 '-C' , file( 'src/jni' ).absolutePath, // Change src/main/jni the relative path to your jni source
                 'clean'
     } else {
         commandLine "$ndkDir/ndk-build.cmd" ,
                 '-C' , file( 'src/jni' ).absolutePath, // Change src/main/jni the relative path to your jni source
                 'clean'
     }
}
//
clean.dependsOn 'cleanNative'
 
tasks.withType(JavaCompile) {
     compileTask -> compileTask.dependsOn buildNative
}</code>

注意上面的有一个变化的地方就是jni的路径在哪,src/jni 如果跟我不一样的,应该写你的具体位置

然后在我们的代码中添加一个Native方法,就让他打印一个helloworld吧

public native void printHelloworld(); 

然后使用javah命令 生成对应的.h头文件
\
这样会在下面目录生成2个文件,当然下面的那个文件不用管它了

然后把生成的这俩文件放到刚才创建的jni里面
下面就是编写cpp文件Android.mk Application.mk文件了

.h文件代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<code class = "hljs vala" > /* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_qbao_ticket_MainActivity */
 
#ifndef _Included_com_qbao_ticket_MainActivity
#define _Included_com_qbao_ticket_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
  * Class:     com_qbao_ticket_MainActivity
  * Method:    add
  * Signature: ()V
  */
JNIEXPORT void JNICALL Java_com_qbao_ticket_MainActivity_printHelloworld
   (JNIEnv *, jobject);
 
#ifdef __cplusplus
}
#endif
#endif</jni.h></code>

.cpp文件代码

?
1
2
3
4
5
6
7
8
9
10
11
<code class = "hljs vala" >#include <jni.h>
#include
#include "com_qbao_ticket_MainActivity.h"
#define LOG_TAG "System.out.c"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
 
JNIEXPORT void JNICALL Java_com_qbao_ticket_MainActivity_printHelloworld
   (JNIEnv *, jobject){
   LOGI( "hello world! come from jni" );
}</android></jni.h></code>

注意新建写的时候 一定要加上

?
1
<code class = "hljs ruleslanguage" >#include "com_qbao_ticket_MainActivity.h" </code>

然后写咱们的mk文件,先来Android.mk

?
1
2
3
4
5
6
7
8
9
10
11
<code class = "hljs ruby" >LOCAL_PATH := $(call my-dir)
 
include $(CLEAR_VARS)
 
LOCAL_MODULE    := lalala
 
LOCAL_SRC_FILES := com_qbao_ticket_MainActivity.cpp
 
LOCAL_LDLIBS += -llog
 
include $(BUILD_SHARED_LIBRARY)</code>

要改的地方是咱们的module名称源文件列表 这里根据自己的代码设置就好了

接下来Application.mk

?
1
2
<code class = "hljs makefile" >APP_ABI := all
APP_PLATFORM := android- 8 </code>

设置了全平台,当然不设置也可以 默认就行了

点击这个按钮 开始编译
\
编译成功会在src目录下生成一个libs和obj.local目录
然后就生成了咱们命名的liblalala.so文件 格式为lib{模块名}.so

下面是怎么在代码中使用咱们生成的.so文件了

把我们的编译生成好的.so文件拷贝到代码的libs中armeabi目录下

然后是在我们的代码中使用它

?
1
2
3
4
<code class = "hljs java" > static {
    System.loadLibrary( "lalala" );
}
public native  void printHelloworld();</code>

注意load的时候写模块名 不是文件名 这里是lalala 然后在MainActivity里面调用这个printHelloworld方法
打印一下log

好了到这里在As2.0中搭建Ndk环境并且编译so文件,并使用so文件的介绍已经讲完了,后面会在这个基础上编译一些音视频模块的代码,然后封装使用。期待吧。。。

build.gradle全部配置查看

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
<code class = "hljs r" > import org.apache.tools.ant.taskdefs.condition.Os
 
apply plugin: 'com.android.application'
 
dependencies {
     compile fileTree(dir: 'libs' , include: '*.jar' )
}
 
android {
     compileSdkVersion 21
     buildToolsVersion "22.0.1"
     sourceSets {
         main {
             manifest.srcFile 'AndroidManifest.xml'
             java.srcDirs = [ 'src' ]
             resources.srcDirs = [ 'src' ]
             aidl.srcDirs = [ 'src' ]
             renderscript.srcDirs = [ 'src' ]
             res.srcDirs = [ 'res' ]
             assets.srcDirs = [ 'assets' ]
             jniLibs.srcDirs = [ 'libs' ]
         }
 
         // Move the tests to tests/java, tests/res, etc...
         instrumentTest.setRoot( 'tests' )
 
         // Move the build types to build-types/<type>
         // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
         // This moves them out of them default location under src/<type>/... which would
         // conflict with src/ being used by the main source set.
         // Adding new build types or product flavors should be accompanied
         // by a similar customization.
         debug.setRoot( 'build-types/debug' )
         release.setRoot( 'build-types/release' )
     }
     buildTypes {
         debug {
             //proguardFile '/Users/xuchuang/Desktop/Stifler/WorkSpace/QBaoTicket_2.0/qbaoticket_2.0/proguard-project.txt'
             //signingConfig signingConfigs.qbaoticket
         }
         release {
             //signingConfig signingConfigs.qbaoticket
             //minifyEnabled true
             //proguardFile '/Users/xuchuang/Desktop/Stifler/WorkSpace/QBaoTicket_2.0/qbaoticket_2.0/proguard-project.txt'
         }
     }
     compileOptions {
         sourceCompatibility JavaVersion.VERSION_1_7
         targetCompatibility JavaVersion.VERSION_1_7
     }
     dexOptions {
         jumboMode true
     }
}
 
task buildNative(type: Exec, description: 'Compile JNI source via NDK' ) {
     def ndkDir = android.ndkDirectory
 
     if (Os.isFamily(Os.FAMILY_WINDOWS)) {
         commandLine "$ndkDir/ndk-build.cmd" ,
                 '-C' , file( 'src/jni' ).absolutePath, // Change src/main/jni the relative path to your jni source
                 '-j' , Runtime.runtime.availableProcessors(),
                 'all' ,
                 'NDK_DEBUG=1'
     } else {
         commandLine "$ndkDir/ndk-build" ,
                 '-C' , file( 'src/jni' ).absolutePath, // Change src/main/jni the relative path to your jni source
                 '-j' , Runtime.runtime.availableProcessors(),
                 'all' ,
                 'NDK_DEBUG=1'
     }
}
//在 mac 中 commandLine "$ndkDir/ndk-build", 但是在windows中 commandLine "$ndkDir/ndk-build.cmd",额,坑
//
task cleanNative(type: Exec, description: 'Clean JNI object files' ) {
     def ndkDir = android.ndkDirectory
     if (Os.isFamily(Os.FAMILY_WINDOWS)) {
         commandLine "$ndkDir/ndk-build.cmd" ,
                 '-C' , file( 'src/jni' ).absolutePath, // Change src/main/jni the relative path to your jni source
                 'clean'
     } else {
         commandLine "$ndkDir/ndk-build.cmd" ,
                 '-C' , file( 'src/jni' ).absolutePath, // Change src/main/jni the relative path to your jni source
                 'clean'
     }
}
//
clean.dependsOn 'cleanNative'
 
tasks.withType(JavaCompile) {
     compileTask -> compileTask.dependsOn buildNative
}</type></type></code>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值