1、Android NDK
这篇博客写的非常详细
http://bbs.51cto.com/thread-1316339-1-1.html
NDK是一个android开发工具(google在developer官网上也是把它放到tools介绍的),可以实现调用本地的c/c++代码。对于某些应用程序,用java实现不了,或者难以实现。用NDK可以利用现有的代码库(c/c++库)。
典型的的NDK的使用的场景,CPU密集型操作无法分配足够的内存,如信号处理、物理模拟等。比如做游戏开发,游戏场景特效,或者是有比较成熟的c/c++库能够很好的利用。
概括来说主要分为以下几种情况:
- 代码的保护,由于apk的java层代码很容易被反编译,而C/C++库反汇难度较大。
- 在NDK中调用第三方C/C++库,因为大部分的开源库都是用C/C++代码编写的。
- 便于移植,用C/C++写的库可以方便在其他的嵌入式平台上再次使用。
2、JNI与NDK
JNI表示Java Native Inteface,是Java中定义的一种用于连接Java和C/C++接口的一种实现方式。
NDK表示Native Development Kit,是Google在Android开发中提供的一套用于快速创建native工程的一个工具。使用这个工具可以很方便的编写,调试JNI的代码。
在android早期并没有ndk。如果我们想要调用c/c++库或者代码就得用java的jni去调用c/c++。耍小聪明走后门一样。而ndk的出现就意味着jni调用的这种方法转正了变成官方支持的一样。
可是这样还是没有说到为什么要有ndk啊。是的我只想说的就是如果你要操作底层直接操作内存。操作地址那你不得不去使用c/c++因为java这块想做这些(java与c/c++相对,效率有点低,而且不能操作内存)。那恐怕有点困难。所以ndk是必须需要出现的。
2、Android Sutido下环境搭建
如果使用的NDK是r7之前的版本,必须要安装Cygwin才能使用NDK。而在NDKr7开始,Google的Windows版的NDK提供了一个ndk-build.cmd的脚本,这样,就可以直接利用这个脚本编译,而不需要使用Cygwin了。这样极大的简化的环境搭建的配置。
1、下载ndk(android-ndk-r10d下面附上下载地址)
2、as关联ndk: file->project structure->sdk location->选择ndk的路径关系
3、NDK需要的配置文件(比较繁琐,需耐心配置,出错的地方比较多,一步一步来)
3.1、新建项目
3.2 、目前的NDK只支持gradle2.5,版本高了或者低了都不行,因此要首先下载gradle2.5的版本,并且把当前的版本改成gradle2.5(下面附上gradle2.5的下载地址)
复制代码
#Sun May 29 18:01:10 CST 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.5-all.zip
3.3、修改project下的buide.gradle文件
复制代码:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle-experimental:0.2.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
3.4、修改app下的build.gradle文件(重点,这个地方配置比较多,要看清楚修改的哪个地方)
复制代码
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion = 22
buildToolsVersion = "22.0.1"
defaultConfig.with {
applicationId = "com.example.administrator.myapplication" //这是程序包名
minSdkVersion.apiLevel = 15
targetSdkVersion.apiLevel = 22
versionCode = 1
versionName = "1.0"
}
tasks.withType(JavaCompile) {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
}
}
android.ndk {
moduleName = "lb"
}
android.buildTypes {
release {
minifyEnabled = true
proguardFiles.add(file("proguard-rules.pro"))
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.1'
compile 'com.android.support:design:22.2.1'
}
3.5 gradle版本报错解决:点击gradle settins(注意要首先下载gradle2.5版本)
这样NDK的环境基本就搭建完成
4、完成第一个NDK demo
4.1、 创建jni文件
在app/src/main文件夹上点右键,在弹出菜单中选择“New”、“Folder”、“JNI Folder”,按提示进行。
有一个“Change Folder Location”选项,不需要勾选,因为jni文件夹采用默认的位置(在main文件夹中)就行。
然后main目录下会出现jni文件夹。
4.2、 创建c++
在jni文件夹上点右键,在弹出菜单中选择“New”、“C/C++ Source File”。
在出现的对话框中,给即将创建的C++文件取名(不要加后缀,软件会自动加上的)。
有一个选项“Create associated header”,不要勾选它,现在不需要创建头文件。
创建my_library后在jni目录下出现一个c++文件
4.3、创建一个Java文件,调用用于调用c++库
复制代码
public class Load {
static {
System.loadLibrary("lb");
}
public native int addInt(int a, int b);
}
4.4、生成.h头文件,打开Terminal命令框
第一步:进入debug模式下
cd app/build/intermediates/classes/debug
第二步:用javah生成头文件(注意自己的包名)
javah -jni com.example.administrator.myapplication.Load
这样,就生成.h头文件了
然后把这个文件右键cut->我们jni目录下最终成这样
打开查看代码如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_administrator_myapplication_Load */
#ifndef _Included_com_example_administrator_myapplication_Load
#define _Included_com_example_administrator_myapplication_Load
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_administrator_myapplication_Load
* Method: addInt
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_example_administrator_myapplication_Load_addInt
(JNIEnv *, jobject, jint, jint);
#ifdef __cplusplus
}
#endif
#endif
4.5、编辑源文件
加入我们需要调用的方法在my_library中(在实际开发中,就是我们需要调用的c/c++库)
代码如下(一个方法,传入两个int值,返回它们的和):
//
// Created by Administrator on 2016/5/29.
//
#include "com_example_administrator_myapplication_Load.h"
JNIEXPORT jint JNICALL Java_com_example_administrator_myapplication_Load_addInt (JNIEnv *, jobject, jint a, jint b) {
return a * b;
}
4.6、这样一切都已经完成了,只需要调用一下,去现我们这个方法就可以了
package com.example.administrator.myapplication;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
private Button btn;
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn= (Button) findViewById(R.id.btn);
tv= (TextView) findViewById(R.id.tv);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Load load=new Load();
int count=load.addInt(10,20);
tv.setText(""+count);
}
});
}
}
Gradle-2.5下载地址
http://download.csdn.net/detail/androidxiaogang/9534777