Android实战技巧之二十三:Android Studio的NDK开发

较新的NDK版本是r10b,Android Studio对NDK开发的支持还处于构思阶段,所以很多工作比如用javah生成头文件等工作还要自己做。今天用一个例子来演示AS中的NDK开发。

新建一个项目SecondNdkTest

在此项目中新建一个Module叫ndklibrary,作为so库单独划出来。在library中新建一个java类SecondLib,内容如下:

package com.linc.ndklibrary;

/**
 * Created by linc on 15-3-29.
 */
public class SecondLib {
    // Native implementation
    static {
    System.loadLibrary("SecondLib");
    }
    //int array
    public static native int[] intMethod();
    //string array
    public static native String[] stringMethod();
}

Build—>Make Module’ndklibrary’,这样SecondLib就编译完成了,通过SecondLib.class,用javah生成C的头文件,如下:

AndroidStudioProjects/SecondNdkTest/ndklibrary/src/main$ javah -d jni -classpath ../../build/intermediates/classes/debug com.linc.ndklibrary.SecondLib
AndroidStudioProjects/SecondNdkTest/ndklibrary/src/main$ ls
AndroidManifest.xml  java  jni  res
AndroidStudioProjects/SecondNdkTest/ndklibrary/src/main$ ls jni/
com_linc_ndklibrary_SecondLib.h

头文件内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_linc_ndklibrary_SecondLib */

#ifndef _Included_com_linc_ndklibrary_SecondLib
#define _Included_com_linc_ndklibrary_SecondLib
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_linc_ndklibrary_SecondLib
 * Method:    intMethod
 * Signature: ()[I
 */
JNIEXPORT jintArray JNICALL Java_com_linc_ndklibrary_SecondLib_intMethod
  (JNIEnv *, jclass);

/*
 * Class:     com_linc_ndklibrary_SecondLib
 * Method:    stringMethod
 * Signature: ()[Ljava/lang/String;
 */
JNIEXPORT jobjectArray JNICALL Java_com_linc_ndklibrary_SecondLib_stringMethod
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

Native代码实现

在jni目录中新建c文件SecondLib.c与头文件对应,分别实现上述两个方法,内容如下:

#include "com_linc_ndklibrary_SecondLib.h"

 const static int length=10;

 //int array
 JNIEXPORT jintArray JNICALL Java_com_linc_ndklibrary_SecondLib_intMethod
   (JNIEnv *env, jclass obj)
 {
    jintArray array;
    array=(*env)->NewIntArray(env,10);
    int i=1;
    for(;i<=10;++i)
    {
        (*env)->SetIntArrayRegion(env,array,i-1,1,&i);
    }

    //get array length
    int len=(*env)->GetArrayLength(env,array);

    //array content
    jint* elems=(*env)->GetIntArrayElements(env,array,0);

    return array;
 }

 //string array
 JNIEXPORT jobjectArray JNICALL Java_com_linc_ndklibrary_SecondLib_stringMethod
   (JNIEnv *env, jclass obj)
 {
    jclass class=(*env)->FindClass(env,"java/lang/String");
    jobjectArray string=(*env)->NewObjectArray(env,(jsize)length,
            class,0);
    jstring jstr;
    char* _char[]={"my ","name ","is ",
                    "linc!!","正在","学习",
                    "JNI","和","NDK","技术!"
                    };
    int i=0;
    for(;i<length;++i)
    {
        jstr=(*env)->NewStringUTF(env,_char[i]);
        (*env)->SetObjectArrayElement(env,string,i,jstr);
    }

    return string;
 }

编译

在local.properties中加入ndk路径:

ndk.dir=/opt/ndk/android-ndk-r10b

然后在ndklibrary的build.gradle中defaultConfig中加入ndk定义,如下:

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
        ndk{
            moduleName "SecondLib"
        }
    }

这样就可以直接编译了,不用自己编写make文件了。

Build—>Make Module’ndklibrary’,生成的so如下:

AndroidStudioProjects/SecondNdkTest$ find -name *.so
./ndklibrary/build/intermediates/ndk/debug/lib/armeabi/libSecondLib.so
./ndklibrary/build/intermediates/ndk/debug/lib/armeabi-v7a/libSecondLib.so
./ndklibrary/build/intermediates/ndk/debug/lib/mips/libSecondLib.so
./ndklibrary/build/intermediates/ndk/debug/lib/x86/libSecondLib.so
./ndklibrary/build/intermediates/ndk/debug/obj/local/armeabi/libSecondLib.so
./ndklibrary/build/intermediates/ndk/debug/obj/local/armeabi-v7a/libSecondLib.so
./ndklibrary/build/intermediates/ndk/debug/obj/local/mips/libSecondLib.so
./ndklibrary/build/intermediates/ndk/debug/obj/local/x86/libSecondLib.so

注:

至于直接在Activity中用native的方法请参考下面的前两个链接。我遇到了问题没有得到解决:

$ javah -d jni -classpath /opt/sdk/platforms/android-5.1/android.jar;../../build/intermediates/classes/debug   com.linc.secondndktest.MainActivity
Error: no classes specified
bash: ../../build/intermediates/classes/debug/: Is a directory

参考:

http://blog.csdn.net/rznice/article/details/42295215

http://blog.csdn.net/sodino/article/details/41946607

http://stackoverflow.com/questions/10483959/javah-error-android-app-activity-not-found

http://blog.csdn.net/lincyang/article/details/6705143

时间: 2024-08-06 19:37:16

Android实战技巧之二十三:Android Studio的NDK开发的相关文章

Android实战技巧之二十七:Maven编译开源二维码扫描项目zxing

拥有自己的手机软件工具箱是件非常有意义的事情.就目前国内Android的生态环境来说,混乱的不能再乱了.由于我们登录不了官网App商店,下软件就只好在国内五花八门的软件市场下载.由于这些市场的监管不力,什么样的软件都有,就拿二维码扫描软件来说,好多都带那种狗皮膏药一样的广告插件,真是特别讨厌. 在开源世界中有很多优秀的软件,其中zxing就是非常好的Android扫碼工具软件.我们可以拿来即用还可以学习内部机制,然后做些定制化个性化.既可以自己享用,又可以跟大家分享.真是不错. zxing在gi

Android实战技巧之十一:Android Studio和Gradle

经过两个多月的AS体验,我认为是时候将Android的开发环境迁移到AS上了.目前最新版本是1.0.2,除了UI控件拖拽偶尔崩溃的问题(Ubuntu),其他功能用来还是十分流畅和高效.打动我的有如下几个特色: 智能感知体验特好,堪比VS 布局预览,手写布局后预览页面即时显示,便于布局调整和优化 编辑速度飞快流畅,毫无eclipse的卡顿 布局或源码中有图标和颜色的预览,十分直观 调试时体验极佳 集成了Terminal,喜欢命令行操作的伙伴不用额外启动终端了. 总之一句话,就是用起来特别爽! An

Android实战技巧之二十九:画布Canvas

Android Framework提供了一些2D画图的API,android.graphics包就是其中之一. 为了画一些东西,需要4个元素(或称组件)协同来完成: * 位图:Bitmap来保持(hold)那些像素 * 画布:Canvas来响应画画(draw)的调用(并将其写入bitmap) * 画笔:paint描述画画的颜色和样式等 * "颜料":drawing primitive,比如矩形.路径.文字.位图等其他元素 而这其中Canvas是比较重要的一环,今天就来演示Canvas的

Android实战技巧之二十四:横竖屏切换

这几年一直在做手机上和电视盒的App,几乎没有考虑过横竖屏切换的问题.电视盒好说,横屏不变,你要是给它设计个竖屏人家也没机会使:而手机上的应用就不好说了,有些界面你设计了横竖屏兼容可能是为了表示你的功能强大.但是按照惯例,或许也是设计师图省事,我们只是做一个方案.就像目前主流的App都只有竖屏一个模式,比如微信.京东和招商银行.我截了几张图表示一下. 但是像地图之类的应用,也许横屏会显示的更友好一些.请看腾讯地图的设计如下: 细心的你会发现,地图的横竖屏的样式几乎是一样的布局,调整起来还是比较容

Android实战技巧之二十五:模拟器如何重启?试试Genymotion!

需要测试Android 5.1系统重启后的一个功能,我手里的设备都没有这么高的版本,那么只好向模拟器求助了.就像大多网友一样,我遇到了一个大问题,如何将Android模拟器重启? 我有几个想法: * 长按模拟器的power kay,调出重启键.可惜的是系统默认只有poweroff一项. * adb reboot或者adb shell进入模拟器再执行reboot.尝试了几个模拟器,都没有成功,只听见我本子的cpu风扇在飞速的运转着. * 自己写一个重启的小应用做重启这件事.这是几年前我就想写的程序

Android实战技巧之二十二:Android 5.1 SDK下载与配置

重要文件下载地址: (1)http://dl-ssl.google.com/android/repository/sources-22_r01.zip (2)http://dl-ssl.google.com/android/repository/tools_r24.1.2-windows.zip (3)http://dl-ssl.google.com/android/repository/android-22_r01.zip (4)http://dl-ssl.google.com/android

Android实战技巧之二十六:persistableMode与Activity的持久化

API 21为Activity增加了一个新的属性,只要将其设置成persistAcrossReboots,activity就有了持久化的能力,另外需要配合一个新的bundle才行,那就是PersistableBundle. 这里的持久化与传统意义的不同,它的具体实现在Activity重载的onSaveInstanceState.onRestoreInstanceState和onCreate方法. public void onSaveInstanceState(Bundle outState, P

Android实战技巧之二十八:启动另一个App/apk中的Activity

Android提供了在一个App中启动另一个App中的Activity的能力,这使我们的程序很容易就可以调用其他程序的功能,从而就丰富了我们App的功能.比如在微信中发送一个位置信息,对方可以点击这个位置信息启动腾讯地图并导航.这个场景在现实中作用很大,尤其是朋友在陌生的环境找不到对方时,这个功能简直就是救星. 本来想把本文的名字叫启动另一个进程中的Activity,觉得这样才有逼格.因为每个App都会运行在自己的虚拟机中,每个虚拟机跑在一个进程中.但仔细一想,能够称为一个进程,前提是这个App

Android实战技巧之二十:两个开源的图表/报表控件

项目中要用饼图和折线图表示数据,重造轮子不是咱风格,先了解一下时下比较流行的开源图表控件吧.调查发现有三个口碑不错的开源项目,它们是MPAndroidChart.AChartEngine.HoloGraphLibrary.由于AChartEngine源码放在code.google上,遂先放弃它,主要研究其他两个在github上的项目. HoloGraphLibrary 项目地址:https://github.com/Androguide/HoloGraphLibrary 简介:这是一个十分简单的