【Android论文栏目提醒】:网学会员在Android论文频道为大家收集整理了“ANDROID上NDK开发初探 - 其它资料“提供大家参考,希望对大家有所帮助!
ANDROID 上 NDK 开发初探 (虽然经过一番不算复杂的折腾发现 NDK总的来说
ANDROID 的 NDK 远不及其应用开发的 SDK 完善用起来很方便),而且它本身也不推荐使用这种做法,至少目前也不将此作为重点。
但是某些中间层面系统测试(主要如多媒体和 OpenGL ES 的测试和演示等)必须通过本地代码实现,因此 NDK 应当是必由之路。
目前将 JNI 部分基本理顺最近尝试了一下, 如 (而后续则需要链接相关的
ANDROID 本地库, OpenCore系统)。
网上这方面相关介绍也有不少,但是多不太完整,此处权作工作记录。
1 NDK 使用1.1 配置 NDK本处讨论在 Windows 下使用 cygwin 处理 NDK 的 Windows 版本。
Linux 下的使用方法基本一致。
根据 unix 系系统的规范,所有讨论中涉及名称的字符串均大小写敏感。
这里仅 NDK 的配置和 C 代码编译须用 cygwin,此后的
ANDROID 调试等均可使用普通的命令行操作。
参考链接:http://developer.
android.com/sdk/ndk/1.5_r1/index.html收到 NDK 后首先在 NDK 的主目录(其中包含 apps build docs …文件夹)下,输入命令:build/host-setup.sh用来配置 NDK 工具(例如编译器的使用,目标平台等),最终生成 out/host/config-host。
由于 out 必须在主目录中,因此上述命令须在主目录中输入。
1.2 编译本地源码本地源码(主要如 C 文件)均放在 sources 下。
NDK 提供了两个示例,放在 sources/sample 目录下。
编译只需要在主目录中输入命令:make APP对于上述示例,分别为 hello-jni 和 two-libs。
1. sources 文件夹配置由于 NDK 已将 MAKE 生成系统建立妥善,所以只需要在 sources 中建立包含源文件的文件夹。
由于 NDK 的配置是以 sources 目录作为源文件工程的根节点,因此如果要将源文件工程放在更深的目录,例如 sourcespackage1proj1,那么就需要在中间的目录中加入一个
Android.mk 文件,用以转到更深的目录其内容示例可见 sourcessamplesAndroid.mk。
上述文件夹 proj1 名称建议以源文件模块的名称命名。
在源文件工程文件夹中需要有至少一个
Android.mk 文件用以定义源文件编译信息。
可以参照sourcessamples 中的两个工程中的示例。
其中 LOCAL_MODULE 变量必须定义成指定源文件工程(模块)的名称。
2. C 源程序 JNI 入口C 源程序的入口遵照 JNI 规范:Java___其中包名称和
Android 的 JAVA 类所属包需要保持一致,只是“.”用“_”替换;JAVA 类即是包含这个(实例)方法的类;FuncName 则是呈现在 JAVA 中使用的方法名称。
3. apps 文件夹配置在 apps 文件夹中创建一个 ADNROID 工程文件夹,名称为 APP 工程(JAVA)名称,在其中新建一个 Application.mk 的配置文件,参照两个示例工程设置。
主要设置两个变量:APP_PROJECT_PATH,这个是
ANDROID 工程路径和相应指定库生成目录(复制而来,名称为“lib源文件模块名”),一般设置成callmy-dir/project,即当前目录下 project 中,而库生成目录就是 project/libs。
APP_MODULES 则是这个
ANDROID 将包含的上述源文件工程,填入涉及的一个或多个源文件工程名称。
最后在主目录中用 make APP1.3 创建工程NDK 两个例程已经含有完整的
ANDROID 例程,可以在 Eclipse 中直接导入打开。
如果新建一个工程,只需要仿照
ANDROID 工程的一般过程开始,由于本地库 so 处于工程目录下,Eclipse 会自动将其包含在工程中,并最终一并链入 apk。
1.4 关于 JAVA 本地(Native)接口 JNI一些参考文档:1. http://java.sun.com/docs/books/jni/2. http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/functions.html3. http://journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/method.html有几个注意点:1. 不能在本地代码中跨线程使用 JNI 量,而目前又暂没找到联入正确 JNI 环境量和对象或者 JVM 的方法,因此只能在调用线程中使用回调,意味着设计需要让回调发生在 JAVA 调用者线程中。
2. CallXXXMethodXenv obj methodid va_arg中,va_arg 必须输入指针(对象的指针如 jstring ,原子的指针如 int )。
3. 对于跨线程的 UI 操作侧需要用 runOnUiThread。
2
ANDROID 工具使用2.1 虚拟设备创建AVD使用
android 命令创建:
android create avd –n -t在通常情况下接受默认选项不建立 hardware profile删除:
android delete avd –n列印:
android list2.2 (在命令行)运行虚拟机命令:emulator –avd2.3 ADB 常用命令参考:http://oxen.javaeye.com/blog/142373安装程序:adb install运行命令 SHELL:adb shell ,进入 SHELL,可以操作访问设备文件系统adb shell ,直接执行命令(SHELL 中可以执行 logcat)复制文件:adb push ,复制入文件adb pull ,复制出文件adb devices ,查看运行的模拟器/设备状态【示例程序】一个简单的在屏幕上间歇打印的程序。
本地 C 代码仅用于示例,不保证正确性和安全性 1. include 2. include 3. include 4. include5. include6. include7.8. typedef struct9. 10. JNIEnv env11. jobject thiz12. jclass cls13. UpdateTextContext14.15. static int gRunnerRunning 016.17. static int update_textUpdateTextContext context char buf18. 19. JNIEnv env context-env20. jobject thiz context-thiz21. jclass cls context-cls22. jmethodID mid env-GetMethodIDenv cls appendText Ljava/lang/StringV23. if mid NULL24. return -125. jstring s env-NewStringUTFenv buf26. env-CallVoidMethodVenv thiz mid s27. return 028. 29.30. void Java_com_eden_sample_Sample_initTextGeneratorJNIEnv env jobject thiz31. 32. gRunnerRunning 0 33. 34. void Java_com_eden_sample_Sample_runTextGeneratorJNIEnv env jobject thiz 35. 36. char buf64 37. int counter 0 38. UpdateTextContext context 39. context.env env 40. context.thiz thiz 41. context.cls env-GetObjectClassenv thiz 42. gRunnerRunning 1 43. whilegRunnerRunning 44. 45. sprintfbuf sample counting: dn counter 46. int r update_textcontext buf 47. if r 0 48. break 49. counter 50. sleep1 51. 52. gRunnerRunning 0 53. 54. void Java_com_eden_sample_Sample_stopTextGeneratorJNIEnv env jobject thiz 55. 56. gRunnerRunning 0 57. JAVA 程序JAVA 本不十分熟悉,权当 c写了1:packagecom.vendor.sample 2: 3: import
android.app.Activity 4: import
android.os.Bundle 5: import
android.widget.TextView 6: import java.util. 7: 8: public class Sample extends Activity 9: 10: enum UpdateType 11: Modify 12: Append 13: 14: 15: private class UpdateTextRunner implements Runnable 16: public UpdateTextRunnerString s UpdateType type 17: mS s 18: mType type 19: 20: 21: public void run 22: if mType UpdateType.Modify 23: mLines.clear 24: mLines.addmS 25: mTV.setTextmS 26: else 27: mLines.addmS 28: 33: while mLines.size mMaxLineCount 34: mLines.remove0 35: 36: StringBuilder sb new StringBuilder 37: for int i 0 i mLines.size i 38: sb.appendmLines.geti 39: mTV.setTextsb.toString 40: 41: 42: 43: private String mS 44: private UpdateType mType45: 46:47:48: Override49: public void onCreateBundle savedInstanceState 50: super .onCreatesavedInstanceState51:52: mTV new TextViewthis 53: mTV.setText initial text 54: setContentViewmTV55:56: initTextGenerator57:58:62: mThread new TextUpdatorThreadthis 63: mThread.start64: 65:66: Override67: public void onDestroy 68: stopTextGenerator69:70: try 71: mThread.join72: catch InterruptedException e 73: e.printStackTrace74: 75: super .onDestroy76: 77:78: public void modifyTextString s 79: this .runOnUiThreadnew UpdateTextRunners UpdateType.Modify80: 81:82: public void appendTextString s 83: this .runOnUiThreadnew UpdateTextRunners UpdateType.Append84: 85:86: public native void initTextGenerator87: public native void stopTextGenerator88: public native void runTextGenerator89:90: private TextView mTV91: private ArrayList mLines new ArrayList 92: private int mMaxLineCount 20 93: 94: private TextUpdatorThread mThread 95: 96: static 97: System.loadLibrarysample // the corresponding C library is libsample.so 98: 99: