高效的Android NDK开发:
为了开发的APK更加安全,防止其反编译;为了利用更高效的C/C++库,提高运行速度;为了更好的移植你的APP,应用在多平台上,请跟我一起使用Android NDK吧!
Android的NDK开发入门指南.首先说为什么写Android项目要用到NDK开发,这里简单介绍一下其中优点:使用Android NDK主要就是为了提升应用的性能,对于那些对性能要求比较高的app 而言可以使用Android NDK,同时NDK绕过了Android的虚拟机的限制,可以使用一些更加底层的方法或是权限,但是使用Android NDK无论设计的多好,都会增加app的复杂性。
但是这里我们只是单纯的说一下怎么通过Android进行NDK编程,而不去探讨更深层次的内容,创建一个Android NDK项目一般遵循一下步骤:
系统环境
Version : 1.0
Development platform : Android Studio 1.4 preview2
Gradle Version : 2.5
Gradle Plugin Version : 1.3.1
简介
1.创建一个空项目; 2.在配置NDK
路径; 3.在入口Activity
中定义一个native
方法; 4.利用javah
生成c
的头文件; 5.在jni
目录下新建一个c
文件; 6.引用so
文件(没看到so
文件); 7.加载so
文件; 8.配置布局文件和入口文件。
功能介绍 创建一个空的project
; 在local.properties
中配置NDK
路径:
1 2 ndk.dir=D\:\\ComSoftwares\\android-ndk sdk.dir=D\:\\ComSoftwares\\android-sdk
在入口Activity
中定义一个native
方法:
1 public native String getStringFromNative () ;
利用javah
生成c
文件: 根据项目路径和编译环境写出下面功能命令行,
1 javah -d jni -classpath D:\ComSoftwares\android-sdk\platforms\android-22\android.jar;..\..\build\intermediates\classes\debug com.ndktest.MainActivity
在Android Studio中的Terminal控制台中先用cd ../../
返回到前两级文件夹,粘贴上面的长串代码,回车执行。会在jni
中生成相应的头文件:com_ndktest_MainActivity.h
. 打开com_ndktest_MainActivity.h
可以看到:
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 #include <jni.h> #ifndef _Included_com_ndktest_MainActivity #define _Included_com_ndktest_MainActivity #ifdef __cplusplus extern "C" {#endif #undef com_ndktest_MainActivity_BIND_ABOVE_CLIENT #define com_ndktest_MainActivity_BIND_ABOVE_CLIENT 8L #undef com_ndktest_MainActivity_BIND_ADJUST_WITH_ACTIVITY #define com_ndktest_MainActivity_BIND_ADJUST_WITH_ACTIVITY 128L #undef com_ndktest_MainActivity_BIND_ALLOW_OOM_MANAGEMENT #define com_ndktest_MainActivity_BIND_ALLOW_OOM_MANAGEMENT 16L #undef com_ndktest_MainActivity_BIND_AUTO_CREATE #define com_ndktest_MainActivity_BIND_AUTO_CREATE 1L #undef com_ndktest_MainActivity_BIND_DEBUG_UNBIND #define com_ndktest_MainActivity_BIND_DEBUG_UNBIND 2L #undef com_ndktest_MainActivity_BIND_IMPORTANT #define com_ndktest_MainActivity_BIND_IMPORTANT 64L #undef com_ndktest_MainActivity_BIND_NOT_FOREGROUND #define com_ndktest_MainActivity_BIND_NOT_FOREGROUND 4L #undef com_ndktest_MainActivity_BIND_WAIVE_PRIORITY #define com_ndktest_MainActivity_BIND_WAIVE_PRIORITY 32L #undef com_ndktest_MainActivity_CONTEXT_IGNORE_SECURITY #define com_ndktest_MainActivity_CONTEXT_IGNORE_SECURITY 2L #undef com_ndktest_MainActivity_CONTEXT_INCLUDE_CODE #define com_ndktest_MainActivity_CONTEXT_INCLUDE_CODE 1L #undef com_ndktest_MainActivity_CONTEXT_RESTRICTED #define com_ndktest_MainActivity_CONTEXT_RESTRICTED 4L #undef com_ndktest_MainActivity_MODE_APPEND #define com_ndktest_MainActivity_MODE_APPEND 32768L #undef com_ndktest_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING #define com_ndktest_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING 8L #undef com_ndktest_MainActivity_MODE_MULTI_PROCESS #define com_ndktest_MainActivity_MODE_MULTI_PROCESS 4L #undef com_ndktest_MainActivity_MODE_PRIVATE #define com_ndktest_MainActivity_MODE_PRIVATE 0L #undef com_ndktest_MainActivity_MODE_WORLD_READABLE #define com_ndktest_MainActivity_MODE_WORLD_READABLE 1L #undef com_ndktest_MainActivity_MODE_WORLD_WRITEABLE #define com_ndktest_MainActivity_MODE_WORLD_WRITEABLE 2L #undef com_ndktest_MainActivity_DEFAULT_KEYS_DIALER #define com_ndktest_MainActivity_DEFAULT_KEYS_DIALER 1L #undef com_ndktest_MainActivity_DEFAULT_KEYS_DISABLE #define com_ndktest_MainActivity_DEFAULT_KEYS_DISABLE 0L #undef com_ndktest_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL #define com_ndktest_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL 4L #undef com_ndktest_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL #define com_ndktest_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL 3L #undef com_ndktest_MainActivity_DEFAULT_KEYS_SHORTCUT #define com_ndktest_MainActivity_DEFAULT_KEYS_SHORTCUT 2L #undef com_ndktest_MainActivity_RESULT_CANCELED #define com_ndktest_MainActivity_RESULT_CANCELED 0L #undef com_ndktest_MainActivity_RESULT_FIRST_USER #define com_ndktest_MainActivity_RESULT_FIRST_USER 1L #undef com_ndktest_MainActivity_RESULT_OK #define com_ndktest_MainActivity_RESULT_OK -1L JNIEXPORT jstring JNICALL Java_com_ndktest_MainActivity_getStringFromNative (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
在jni
中新建一个c
文件,将名字命名为:main.c
,输入以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 #include "com_ndktest_MainActivity.h" JNIEXPORT jstring JNICALL Java_com_ndktest_MainActivity_getStringFromNative (JNIEnv * env, jobject obj){ return (*env)->NewStringUTF(env,"I'm comes from to Native Function!" ); }
如果编译出错,请在jni文件夹中新建一个空的.c
文件,比如utils.c
。在此我没有碰到错误,所以没有添加空文件
在app目录下的build.gradle
中设置库文件名(生成的so
文件名–但是我在项目中并未看到有so
文件生成); 找到defaultConfig
项,添加以下内容:
1 2 3 ndk{ moduleName "MyJni" }
加载so
文件:
1 2 3 static { System.loadLibrary("MyJni" ); }
配置布局文件和入口文件 在此贴出布局的完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <RelativeLayout xmlns:android ="http://schemas.android.com/apk/res/android" xmlns:tools ="http://schemas.android.com/tools" android:layout_width ="match_parent" android:layout_height ="match_parent" android:paddingLeft ="@dimen/activity_horizontal_margin" android:paddingRight ="@dimen/activity_horizontal_margin" android:paddingTop ="@dimen/activity_vertical_margin" android:paddingBottom ="@dimen/activity_vertical_margin" tools:context =".MainActivity" > <TextView android:text ="@string/hello_world" android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:id ="@+id/myJni" /> </RelativeLayout >
MainActivity的完整代码:
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 package com.ndktest;import android.app.Activity;import android.os.Bundle;import android.view.Menu;import android.view.MenuItem;import android.widget.TextView;public class MainActivity extends Activity { private TextView tv=null ; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv=(TextView)findViewById(R.id.myJni); tv.setText(getStringFromNative()); } @Override public boolean onCreateOptionsMenu (Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); return true ; } @Override public boolean onOptionsItemSelected (MenuItem item) { int id = item.getItemId(); if (id == R.id.action_settings) { return true ; } return super .onOptionsItemSelected(item); } public native String getStringFromNative () ; static { System.loadLibrary("MyJni" ); } }
运行结果 编译运行可以看到从native方法传过来的值:
上一篇:Markdown学习入门
下一篇:Git安装与配置