Android For JNI(六)——交叉编译,NDK概述以及文件结构,编写自己的第一个JNI工程

Android For JNI(六)——交叉编译,NDK概述以及文件结构,编写自己的第一个JNI工程


终于回到我们的android了,我们先要配置这个NDK的环境,但是之前,我们还要了解一下基本的术语

一.交叉编译

  • 在一个平台下编译出另一个平台可以执行的二进制程序
  • CPU平台:ARM X86 MIPS(指令集)
  • 系统平台:windows linux mac
  • 原理:模拟另一个平台的特性去编译程序
    • 源代码——>预编译——>编译——>链接——>可执行程序
  • 工具链:一个工具使用自动调用下一个

二.JNI常用工具

  • NDK : Native Developer Kits
  • CDT : C/C++ Developer Tools(插件/高亮显示C关键字)
  • Cygwin:Windows下的linux模拟器(ROM系列有讲)

三.NDK配置

NDK下载地址:下载地址:http://wear.techbrood.com/tools/sdk/ndk/

1.NDK产生的背景

Android平台从诞生起,就已经支持C、C++开发。众所周知,Android的SDK基于Java实现,这意味着基于Android SDK进行开发的第三方应用都必须使用Java语言。但这并不等同于“第三方应用只能使用Java”。在Android SDK首次发布时,Google就宣称其虚拟机Dalvik支持JNI编程方式,也就是第三方应用完全可以通过JNI调用自己的C动态库,即在Android平台上,“Java+C”的编程方式是一直都可以实现的。

不过,Google也表示,使用原生SDK编程相比Dalvik虚拟机也有一些劣势,Android SDK文档里,找不到任何JNI方面的帮助。即使第三方应用开发者使用JNI完成了自己的C动态链接库(so)开发,但是so如何和应用程序一起打包成apk并发布?这里面也存在技术障碍。比如程序更加复杂,兼容性难以保障,无法访问Framework API,Debug难度更大等。开发者需要自行斟酌使用。

于是NDK就应运而生了。NDK全称是Native Development Kit。

NDK的发布,使“Java+C”的开发方式终于转正,成为官方支持的开发方式。NDK将是Android平台支持C开发的开端。

2.为什么使用NDK

  • 1.代码的保护。由于apk的java层代码很容易被反编译,而C/C++库反汇难度较大。
  • 2.可以方便地使用现存的开源库。大部分现存的开源库都是用C/C++代码编写的。
  • 3.提高程序的执行效率。将要求高性能的应用逻辑使用C开发,从而提高应用程序的执行效率。
  • 4.便于移植。用C/C++写得库可以方便在其他的嵌入式平台上再次使用。

3.NDK简介

  • 1.NDK是一系列工具的集合

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

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

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

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

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


我们先下载安装NDK吧!

4.NDK目录结构

我们下载好之后就直接解压

我们来分析一下

  • docs:帮助文档
  • build/tools:Linux批处理文件
  • platforms:存放JNI用到的h头文件和so类库
  • prebuilt:预编译使用的工具
  • samples:小例子
  • sources:NDK的部分源码
  • toolchains:工具链
  • ndk-build.cmd:编译打包C代码

其实跟SDK还是类似的,我们就不细说了

四.HelloJNI

我们来创建自己的第一个jni工程,我们在eclipse中新建一个工程——HelloJNI,额,问我为什么不用android studio,这个…..还不是很熟练,因为工作需要,一直用的是eclipse,看NDK的文件夹下的例子我们知道,首先,我们要创建一个jni的目录,我们新建

我们新建一个C类,再次之前,我们先看一下api里的哪个hello-jni的例子中c程序是怎么写的

/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#include <string.h>
#include <jni.h>

/* This is a trivial JNI example where we use a native method
 * to return a new VM String. See the corresponding Java source
 * file located at:
 *
 *   apps/samples/hello-jni/project/src/com/example/hellojni/HelloJni.java
 */
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                                  jobject thiz )
{
#if defined(__arm__)
  #if defined(__ARM_ARCH_7A__)
    #if defined(__ARM_NEON__)
      #if defined(__ARM_PCS_VFP)
        #define ABI "armeabi-v7a/NEON (hard-float)"
      #else
        #define ABI "armeabi-v7a/NEON"
      #endif
    #else
      #if defined(__ARM_PCS_VFP)
        #define ABI "armeabi-v7a (hard-float)"
      #else
        #define ABI "armeabi-v7a"
      #endif
    #endif
  #else
   #define ABI "armeabi"
  #endif
#elif defined(__i386__)
   #define ABI "x86"
#elif defined(__x86_64__)
   #define ABI "x86_64"
#elif defined(__mips64)  /* mips64el-* toolchain defines __mips__ too */
   #define ABI "mips64"
#elif defined(__mips__)
   #define ABI "mips"
#elif defined(__aarch64__)
   #define ABI "arm64-v8a"
#else
   #define ABI "unknown"
#endif

    return (*env)->NewStringUTF(env, "Hello from JNI !  Compiled with ABI " ABI ".");
}

这里,前面是注释,不用管,我们看最后的return,我们在jni的目录下写一个c文件

#include <stdio.h>
#include <stdlib.h>
#include <jni.h>
/**
 * 计算相加
 * 定义一个本地函数
 * env:结构体二级指针,该结构体封装了大量的函数指针,方便我们开发某些功能
 * thiz:本地方法调用者的对象,这里值MainActvity的对象
 */
jstring Java_com_lgl_hellojni_MainActivity_HelloJNI(JNIEnv* env, jobject thiz) {

    char* cstr = "hello jni";
    //把C字符串转换成java字符串
    /**
     * 官方文档:return (*env)->NewStringUTF(env, "Hello from JNI !  Compiled with ABI " ABI ".");
     */
    jstring jstr = (*env)->NewStringUTF(env,cstr);
    return jstr;
}

写完之后,我们运行是没用的,我们这里是需要手动编译的

我们进入我们的源文件目录下,打开cmd,输入ndk-build.cmd去编译,他会报一个错误,原因是路径,我们缺少了一个mk文件,要创建这个文件,我们需要查看一下android-mk.html的文档,我们在jni目录下新建一个Android.mk文件,把这段话复制进去

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello_jni   //生成的文件名
LOCAL_SRC_FILES := hello_jni.c   //要编译的文件

include $(BUILD_SHARED_LIBRARY)

现在,我们可以编译了,编译完成之后,libs目录下会有一个动态的链接库

我们执行的就是这个库

当然,我们现在还需要去加载动态链接库,我们回到MainActivity


    static{
        //模块名字
        System.loadLibrary("hello-jni");
    }

然后我们可以使用了

Toast.makeText(this, HelloJNI(), Toast.LENGTH_LONG).show();

但是这里运行的话需要arm平台的,你在X86平台上是没用的,文章前面也说了,如果大家编译晕倒困难,那就是相关配置没配好,这里推荐

http://www.cnblogs.com/skyseraph/p/3979238.html

配置环境百度很多的

Demo下载:http://download.csdn.net/detail/qq_26787115/9501088

时间: 2024-11-07 07:58:41

Android For JNI(六)——交叉编译,NDK概述以及文件结构,编写自己的第一个JNI工程的相关文章

Android jni开发资料--NDK环境搭建

谷歌改良了ndk的开发流程,对于Windows环境下NDK的开发,如果使用的NDK是r7之前的版本,必须要安装Cygwin才能使用NDK.而在NDKr7开始,Google的Windows版的NDK提供了一个ndk-build.cmd的脚本,这样,就可以直接利用这个脚本编译,而不需要使用Cygwin了.只需要为Eclipse Android工程添加一个Builders,而为Eclipse配置的builder,其实就是在执行Cygwin,然后传递ndk-build作为参数,这样就能让Eclipse自

史上最易懂的Android jni开发资料--NDK环境搭建

谷歌改良了ndk的开发流程,对于Windows环境下NDK的开发,如果使用的NDK是r7之前的版本,必须要安装Cygwin才能使用NDK.而在NDKr7开始,Google的Windows版的NDK提供了一个ndk-build.cmd的脚本,这样,就可以直接利用这个脚本编译,而不需要使用Cygwin了.只需要为Eclipse Android工程添加一个Builders,而为Eclipse配置的builder,其实就是在执行Cygwin,然后传递ndk-build作为参数,这样就能让Eclipse自

使用Android Studio自带的NDK编译JNI

/********************************************************************************** * 使用Android Studio自带的NDK编译JNI * 说明: * 省得自己另外去下载NDK,编译JNI,麻烦. * * 2017-4-30 深圳 龙华民治樟坑村 曾剑锋 ****************************************************************************

【Android】Eclipse自动编译NDK/JNI的三种方法

[Android]Eclipse自动编译NDK/JNI的三种方法 SkySeraph Sep. 18th  2014 Email:[email protected] 一.Eclipse关联cygwin 1. 工程->右击选择Properties->选择Builders,在Builders中选择New创建一个Program 2. 参数配置 二.Eclipse关联ndk-build(自建Builder方法)  1. Project->Properties->Builders->N

【译】NDK概述

翻译自官方文档NDK概述 NDK概述 On this page NDK使用前 介绍 NDK怎样工作 Native Activitie和应用程序 开始前 本指南假设已经熟悉安卓开发中的本地程序的概念. 介绍 本节提供了NDK如何工作的高级说明.Android NDK是一组高级工具,允许你的Android应用程序中嵌入C或C++("native code&rdquo).在Android应用中使用本地代码的功能对于希望执行以下一项或多项操作的开发人员尤其有用: 移植应用. 重用现有库, 或提供

Android系统移植与驱动开发概述读书心得

第一章是Android系统移植与驱动开发概述,包含了Android系统架构.Android系统移植的主要工作.查看Linux内核版本.Linux内核版本号的定义规则.如何学习Linux驱动开发以及Linux设备驱动等六方面内容 Android系统架构分为四层,分别是Linux内核.C/C++代码库.Android SDK API和应用程序.Linux内核这一层主要包括Linux的驱动程序以及内存管理.进程管理.电源管理等程序. Android移植可分为两部分:应用移植和系统移植.应用移植是指将应

Android学习笔记—Windows下NDK开发简单示例

该示例假设Android开发环境已经搭建完成,NDK也配置成功: 1.在Eclipse上新建Android工程,名称为ndkdemo.修改res\layout\activity_main.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layo

Android群英传笔记——摘要,概述,新的出发点,温故而知新,能够为师矣!

Android群英传笔记--摘要.概述,新的出发点,温故而知新.能够为师矣! 当工作的越久,就越感到力不从心了,基础和理解才是最重要的,所以买了两本书,医生的<Android群英传>和主席的<Android开发艺术探索>.主要是再全面点的把自己所学的知识消化,这样也就不枉自己天天熬夜学习了,如今群英传快看完了.准备又一次再看一遍,同一时候把笔记以博客的形式记录下来,这样或许更加的深刻,然后再消磨一下主席的那本书,这本书有视频解说,更加好,所以估计以后应该非常少再写其它的博客,只是工

Android JNI编程(七)——使用AndroidStudio编写第一个JNI程序

目录(?)[+] 1.简单介绍一下NDK和JNI NDK:NDK是Native Development Kit的缩写,是Google提供的一套工具集,可以让你其他语言(C.C++或汇编)开发 Android的 JNI.NDK可以编译多平台的so,开发人员只需要简单修改 mk 文件说明需要的平台,不需要改动任何代码,NDK就可以帮你编译出所需的so库. JNI:JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信(主要是C&C++) NDK网