NDK是Google提供的一套开发支持Native代码的应用程序的工具。因为Android用了自己改写的C库(Bionic),并应用自己的compiler和linker,所以如果想用通用的toolchain编译Android应用中C/C++代码就比较麻烦。之前的方法是,可以把自己的代码整合到整个Android系统中,利用Android Build System的编译工具进行编译(具体例子可以参看<android source>/development/samples/下的PlatformLibrary和SimpleJNI两个例子)。但是缺点是要建立整个的Build的环境,第一次Build所有的代码时间很长。
NDK则提供了一个相对简单Build System。只要按它的要求提供应用和Native代码位置及要编译的模块等基本信息,然后用它提供的工具就可以很方便的生成Shared Librare,并自动将其拷贝到SDK应用开发的环境下方便生成apk。具体的介绍在<android NDK>/docs/下。
以下是我应用NDK做的一个小实验。其实前面基本上就是在Eclipse下建立一个Service应用,只是在Service中用到的share library是用NDK生成的。与NDK相关部分用红色标注,在工程中加入*.mk,jni等只是为了方便编辑。
实验环境:
Ubuntu, SDK 1.5r2, NDK 1.5r1, Eclipse3.4 (ADT plugin)
具体步骤记录如下:
1.在Eclipse下新建Android-Project项目MyServer,Package为ndk.sample.myservice;
2.在MyServer/src/ndk.sample.myservice下:
a)添加aidl文件:IMyService.aidl,之后在gen/sample.ndk.myserver下会自动生成IMyService.java;
# package ndk.sample.myservice;
# interface IMyService {
# String getGreetings(in String toName);
# }
b)实现MyService;
2. package ndk.sample.myservice;
3. import android.app.Service;
4. import android.content.Intent;
5. import android.os.IBinder;
6. import android.util.Log;
7. public class MyService extends Service {
8. private final IMyService.Stub binder = new IMyService.Stub() {
9. public String getGreetings(String toName) {
10. return get_greetings(toName);
11. }
12. };
13.
14. @Override
15. public void onCreate() {
16. Log.v("MyService", "Lifecycle - onCreate");
17. }
18.
19. @Override
20. public void onDestroy() {
21. Log.v("MyService", "Lifecycle - onDestroy");
22. }
23.
24. @Override
25. public void onStart(Intent intent, int startId) {
26. Log.v("MyService", "Lifecycle - onStart: id = " + Integer.toString(startId));
27. }
28.
29. @Override
30. public IBinder onBind(Intent intent) {
31. Log.v("MyService", "Lifecycle - onBind");
32. return this.binder;
33. }
34. @Override
35. public void onRebind(Intent intent) {
36. Log.v("MyService", "Lifecycle - onRebind");
37. }
38.
39. @Override
40. public boolean onUnbind(Intent intent) {
41. Log.v("MyService", "Lifecycle - onUnbind");
42. return false;
43. }
44.
45. static {
46. System.loadLibrary("mynativecodes");
47. }
48.
49. public native String get_greetings(String toName);
50. }
c)实现TestClient;
2. package ndk.sample.myservice;
3. import android.app.Activity;
4. import android.content.ComponentName;
5. import android.content.Intent;
6. import android.content.ServiceConnection;
7. import android.os.Bundle;
8. import android.os.IBinder;
9. import android.os.RemoteException;
10. import android.util.Log;
11. import android.view.View;
12. import android.widget.Button;
13. import android.widget.EditText;
14. import android.widget.TextView;
15. public class TestClient extends Activity {
16. private TextView tvGreetings;
17. private EditText etName;
18. private IMyService service;
19.
20. private ServiceConnection connection = new ServiceConnection () {
21. @Override
22. public void onServiceConnected(ComponentName className, IBinder iservice) {
23. service = IMyService.Stub.asInterface(iservice);
24. }
25.
26. @Override
27. public void onServiceDisconnected(ComponentName className) {
28. service = null;
29. }
30. };
31.
32. @Override
33. public void onCreate(Bundle savedInstanceState) {
34. super.onCreate(savedInstanceState);
35. setContentView(R.layout.main);
36.
37. tvGreetings = (TextView)findViewById(R.id.tvGreetings);
38. etName = (EditText)findViewById(R.id.etName);
39.
40. Button btnHello = (Button)findViewById(R.id.btnHello);
41. btnHello.setOnClickListener(new View.OnClickListener () {
42. @Override
43. public void onClick(View view) {
44. String toName = etName.getText().toString();
45. try {
46. String greetings = service.getGreetings(toName);
47. tvGreetings.setText(greetings);
48. etName.setText("");
49. }
50. catch (RemoteException e) {
51. Log.e("TestClient", "error", e);
52. }
53. }
54. });
55. }
56.
57. @Override
58. public void onStart() {
59. super.onStart();
60.
61. boolean rc = bindService(
62. new Intent(IMyService.class.getName()),
63. connection, BIND_AUTO_CREATE);
64. if (rc == false)
65. Log.v("TestClient", "Fail to bindService");
66. }
67.
68. @Override
69. public void onStop() {
70. super.onStop();
71.
72. unbindService(connection);
73. }
74. }
d)修改AndroidManifest.xml,添加service
# <?xml version="1.0" encoding="utf-8"?>
# <manifest xmlns:android="http://schemas.android.com/apk/res/android"
# package="ndk.sample.myservice"
# android:versionCode="1"
# android:versionName="1.0">
# <application android:icon="@drawable/icon" android:label="@string/app_name">
# <activity android:name=".TestClient"
# android:label="@string/app_name">
# <intent-filter>
# <action android:name="android.intent.action.MAIN" />
# <category android:name="android.intent.category.LAUNCHER" />
# </intent-filter>
# </activity>
# <service android:name=".MyService">
# <intent-filter>
# <action android:name="ndk.sample.myservice.IMyService" />
# </intent-filter>>
# </service>>
# </application>
# <uses-sdk android:minSdkVersion="3" />
# </manifest>
e)添加Application.mk文件
1. APP_PROJECT_PATH := $(call my-dir)
2. APP_MODULES := mynativecodes
3.在MyService下添加目录jni:
a)从Terminal:
$ cd MyServer/jni
$ javah -jni -classpath ../bin ndk.sample.myservice.MyService
自动生成头文件ndk_sample_myservice_MyService.h
b)在MyServer/jni下添加mynative.c,实现
2. #include "ndk_sample_myservice_MyService.h"
3. #include <stdio.h>
4. #include <string.h>
5. JNIEXPORT jstring JNICALL Java_ndk_sample_myservice_MyService_get_1greetings
6. (JNIEnv *env, jobject obj, jstring name)
7. {
8. // fixed buffer size for test
9. char buf[128];
10. const jbyte *str;
11. str = (*env)->GetStringUTFChars(env, name, NULL);
12. if (str == NULL) {
13. return NULL;
14. }
15. if (strlen (str) == 0)
16. sprintf (buf, "Who are you?");
17. else
18. sprintf (buf, "Hello, %s!!!", str);
19. (*env)->ReleaseStringUTFChars(env, name, str);
20. return (*env)->NewStringUTF(env, buf);
21. }
c)在MyServer/jni下添加Android.mk
# LOCAL_PATH := $(call my-dir)
# include $(CLEAR_VARS)
# LOCAL_MODULE := mynativecodes
# LOCAL_SRC_FILES := mynative.c
# include $(BUILD_SHARED_LIBRARY)
4.在Terminal下,进入NDK目录,建立指向应用和share library的链接(可以不把自己的代码放在NDK的目录下,但必须在NDK中加入指向存放Application.mk和Android.mk的路径的链接)
$ cd <androi ndk>
$ cd sources
$ ln -s <my service dir>/ myservice
$ cd ../apps
$ ln -s <my service dir>/jni/ mynativecodes
$ cd ../
$ make APP=myservice V=1
APP部分指明要编译的应用名(路径名),必须有。V=1指定显示编译命令,可以没有。编译成功后,可以在libs\armeabi下生成了libmynativecodes.so,Eclipse环境中也可以看到。
5.最后按正常的方法生成MyService的apk即可。
分享到:
相关推荐
解决eclipse无NDK选项设置问题,复制下载文件到eclipse目录的“plugins”下面。如我的复制到"\eclipse\plugins\com.android.ide.eclipse.ndk_23.0.2.1259578.jar"。
android开发有时需要开发c/c++插件,这就需要用到NDK(Native Development Kit),如果eclipse中没有配置NDK的选项则需要此...解压后对应放入eclipse目录下的features和plugins文件夹重启eclipse就可以看到NDK的选项了。
Eclipse集成Android NDK说明 1 2 为什么要用NDK? 2 3 为什么要集成? 2 4 怎样操作? 2 4.1 预备条件 2 4.1.1 Cygwin 2 4.1.2 Eclipse 2 4.1.3 Eclipse CDT 3 4.1.4 Android SDK 3 4.1.5 Android NDK 3 ...
详细介绍了在eclipse中android项目下c/c++代码的自动编译,和在eclipse中用ant生成ndk需要的jni头文件,加速ndk的开发,因为是原创,费了不少心力和时间,所以设了6分,有人反映太贵了,现在调成3分,这下大家满意了...
关于Eclipse 中ndk 开发环境变量的详细配置,so 文件的自动生成。请详细按文中步骤配置,若有疑问请加qq:451148163 为您详细解答
ADT22.0.6配置ndk-r10,配置过程中出现很多问题,总结成文章分享给大家吧,写博客配插图太麻烦了,直接上传PDF吧
解决eclipse无NDK选项设置问题。复制到eclipse目录的“plugins”下面。如我的复制到"\eclipse\plugins\com.android.ide.eclipse.ndk_23.0.2.1259578.jar"
eclipse中ndk 自动编译配置
Eclipse配置NDK开发环境
但是adt bundle中自带的eclipse没有NDK选项,原因是缺少一个包: com.android.ide.eclipse.ndk_23.0.2.1259578.jar 将这个包放在eclipse的plugins文件夹下,重启eclipse,就可以看到NDK的选项了。
android adt自带eclipse无法设置ndk路径,需要下载com.android.ide.eclipse.ndk_23.0.2.1259578.jar文件,然后复制到sdk 只带的eclipse目录的“plugins”下面,如我的复制到"D:\Android\adt-bundle-windows-x86_64-...
eclipse adt ndk插件
完美解决eclipse中Android选项中没有NDK设置的问题,按照教程来即可解决
解决eclipse无NDK选项设置问题。复制到eclipse目录的“plugins”下面。如我的复制到"\eclipse\plugins\com.android.ide.eclipse.ndk_23.0.4.1468518.jar" 然后重启Eclipse
此为较老的NDK开发官方参考,Eclipse开发环境的例子,如果是用最新的Android Studio去官网参照最新的帮助文档即可。
eclipse ndk Hello-jnieclipse ndk Hello-jnieclipse ndk Hello-jnieclipse ndk Hello-jni
这是一个ndk入门实例,使用eclipse实现的,很简单且具有参考意义 参考黄书《Android应用安全防护和逆向分析》第二章Android NDK开发2.1.1节以及百度经验 Android NDK入门开发实例...
eclipse NDk插件 如果在eclipse里配置ndk却发现没有配置的选项,则需要此插件,放置在eclipse/plugins下,重启eclipse即可。