zoukankan      html  css  js  c++  java
  • [Android NDK/JNI-1A]-开发环境搭建

    NDK简介

       NDK能干什么:NDK使得在android中,java可以调用C 函数库。

    1.Android平台从诞生起,就已经支持C、C++开发。众所周知,Android的SDK基于Java实现,这意味着基于Android SDK进行开发的第三方应用都必须使用Java语言。但这并不等同于“第三方应用只能使用Java”。

    2.在Android SDK首次发布时,Google就宣称其虚拟机Dalvik支持JNI编程方式,也就是第三方应用完全可以通过JNI调用自己的C动态库,即在Android平台上,“Java+C”的编程方式是一直都可以实现的。

    3.NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。这些工具对开发者的帮助是巨大的。

    4.NDK集成了交叉编译器,并提供了相应的mk文件隔离CPU、平台、ABI等差异,开发人员只需要简单修改mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以创建出so。

    5.NDK可以自动地将so和Java应用一起打包,极大地减轻了开发人员的打包工作。

    6.NDK提供了一份稳定、功能有限的API头文件声明

    7.Google明确声明该API是稳定的,在后续所有版本中都稳定支持当前发布的API。从该版本的NDK中看出,这些API支持的功能非常有限,包含有:C标准库(libc)、标准数学库(libm)、压缩库(libz)、Log库(liblog)。

    Today

    1.NDK并不能显著提升应用效率。我们都觉得C语言比起java来说效率要高出很多,一方面,随着jdk的不断更新,java的效率也随之提高;另一方面,即便使用C语言编码提高了应用效率,但是在java与C相互调用时平白又增大了开销。

    2.今天折腾了大半天,才编译出自己想要的so文件。但是android studio集成开发环境中还没尝试。

    3.关于Cygwin下载问题,官方放在的step.exe国内今天根本没发弄下来,下载了一个老版本的exe,但是又不给更新。

    http://www.redhat.com/services/custom/cygwin/ 在红帽试过,虽然exe能弄下来,但是Cygwin需要的下载的文件根本没法下载(网速太慢,比蜗牛还慢,况且有好几个G的)

    http://mirrors.163.com/  网易开源镜像站

    http://www.cygwin.cn/site/info/show.php?IID=1003 Cygwin中文网

    4.由于Java中的本地方法名称及包路径都是写死在C语言中的,因此本地相关代码不能混淆

    5.项目中的JNI目录时编写c/c++的代码区,执行ndk-build命令后会在libs下生成so文件,在运行项目时,也是调用so文件中的相关资源。

    为什么要使用NDK

    java是半解释型语言,很容易被反汇编后拿到源代码文件,在开发一些重要协议时,我们为了安全起见,使用C语言来编写这些重要的部分,来增大系统的安全性。还有,在一些接近硬件环境下,相信大家都清楚C与java的优劣。

    1.代码的保护。由于apk的java层代码很容易被反编译,而C/C++库反汇难度较大。

    2.可以方便地使用现存的开源库。大部分现存的开源库都是用C/C++代码编写的。

    3.提高程序的执行效率。将要求高性能的应用逻辑使用C开发,从而提高应用程序的执行效率。

    4.便于移植。用C/C++写得库可以方便在其他的嵌入式平台上再次使用。

    5.Eclipse中ndk配置

    NDK开发所需要的环境

    1.Android应用开发所需要的开发集成环境(环境变量自己百度)

    2.NDK所需要的开发包(C:javaandroid-ndk-r7b)

    3.linux环境需要下载cygwin(C:javacygwinin)

    4.配置各自的环境变量(JDK,SDK,NDK,cygwin)

    JNI编码

    1.新建一个android工程

    2.在工程目录下添加名为 jni 的文件夹(必须)如下图:

    3.在jni文件夹下新建你的.c和.h文件文件(JNI_Demo.c和JNI_Demo.h)

    4.在jni文件夹下新建名字为Android.mk文件(文件名符合命名规则都行)

    5.在上述.mk文件中加入如下代码:

    LOCAL_PATH := $(call my-dir)//当前路径(如果你了解shell语言,应该可以很轻松的理解)
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE    := JNI_Demo //要生成的.so库名
    LOCAL_SRC_FILES := JNI_Demo.c //jni文件夹下的c文件名
    
    include $(BUILD_SHARED_LIBRARY)

    6.在JNI_Demo.c文件中加入如下代码:

    #include <stdio.h>
    #include "JNI_Demo.h"
    
    
    const char keyValue[] = {
        119,119,119,46,104,111,109,105,108,121,46,99,110
    };
    
    
    JNIEXPORT jbyteArray JNICALL Java_com_homily_SecurityUtil_getKeyValue
      (JNIEnv *env, jclass obj)
    {
        jbyteArray kvArray = (*env)->NewByteArray(env, sizeof(keyValue));
        jbyte *bytes = (*env)->GetByteArrayElements(env,kvArray,0);
        int i;
        for (i = 0; i < sizeof(keyValue);i++)
        {
            bytes[i] = (jbyte)keyValue[i];
        }
    
        (*env)->SetByteArrayRegion(env,kvArray, 0, sizeof(keyValue),bytes);
        (*env)->ReleaseByteArrayElements(env,kvArray,bytes,0);
        return kvArray;
    }

     7.在JNI_Demo.h文件中加入如下代码:

    #include <jni.h>
    
    #ifndef _Included_com_homily_SecurityUtil
    #define _Included_com_homily_SecurityUtil
    #ifdef __cplusplus
    extern "C" {
    #endif
    JNIEXPORT jbyteArray JNICALL Java_com_homily_SecurityUtil_getKeyValue
      (JNIEnv *, jclass);
    
    
    #ifdef __cplusplus
    }
    #endif
    #endif

    8.然后就是写C对应的Java代码

    Java_com_homily_SecurityUtil_getKeyValue

    这个是Java类对应的路径,必须以Java开头,com.homily.SeturityUtil.java类下的getKeyValue方法。JNI桥接代码如下:

     1 package com.homily;
     2 
     3 public class SecurityUtil {
     4     private static byte[] keyValue;
     5     
     6     static {
     7         System.loadLibrary("JNI_Demo");
     8         keyValue = getKeyValue();
     9     }  
    10     
    11     public static String getValue() {
    12         return new String(keyValue);
    13     }
    14     
    15     public static native byte[] getKeyValue();
    16     
    17 }

    9.android调用代码如下   

     1 package com.homily;
     2 import android.app.Activity;
     3 import android.os.Bundle;
     4 import android.util.Log;
     5 
     6 public class MainActivity extends Activity {
     7     
     8     private static final String TAG = "MainActivity";
     9     
    10     @Override
    11     protected void onCreate(Bundle savedInstanceState) {
    12         super.onCreate(savedInstanceState);
    13         
    14         setContentView(R.layout.activity_main);
    15         String enstr = SecurityUtil.getValue();
    16         Log.d(TAG, "web address[" + enstr +"]");
    17     }
    18 
    19 }

    NDK编译结果       

    1.生成so文件

            打开cmd,使用cd等相关命令进入该工程目录下  ,运行下面的命令,完成后点击右键刷新下项目,在libs下面就会生成so文件,如下:

    E:android_workspaceJNI_Demo>NDK-build
    Android NDK: WARNING: APP_PLATFORM android-19 is larger than android:minS
    [armeabi] Compile thumb  : JNI_Demo <= JNI_Demo.c
    [armeabi] SharedLibrary  : libJNI_Demo.so
    [armeabi] Install        : libJNI_Demo.so => libs/armeabi/libJNI_Demo.so

    so文件如下图:

    2.最后运行下项目,输出日志如下:

    参考资料:

    http://mobile.51cto.com/aprogram-434525.htm

    http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html

  • 相关阅读:
    iSCSI又称为IPSAN
    文档类型定义DTD
    HDU 2971 Tower
    HDU 1588 Gauss Fibonacci
    URAL 1005 Stone Pile
    URAL 1003 Parity
    URAL 1002 Phone Numbers
    URAL 1007 Code Words
    HDU 3306 Another kind of Fibonacci
    FZU 1683 纪念SlingShot
  • 原文地址:https://www.cnblogs.com/royi123/p/5510801.html
Copyright © 2011-2022 走看看