Android native应用开发简明教程 (1) - 本地开发武器库概览

Android本地开发武器库概览

Android本地开发支持简史

Android 1.0的时代,没有提供对于C/C++开发本地Android代码的支持,尽管Android系统本身使用了大量的C++做底层开发。

第一个里程碑 - 支持jni开发so库 (Android 1.5)

Android第一次支持本地开发是在Android 1.5版本,对应Android API level 3。这一版本,有了正式的Android NDK的支持,可以通过jni写so库的方式,供Android应用来调用。

Android 1.6增加了对于OpenGL ES 1.x的支持
Android 2.0开始支持OpenGL ES 2.0

第二个里程碑 - 支持本地应用开发 (Android 2.3)

Android 2.3是一个重要的版本,这一版本增加了完全用C++写本地应用的接口。

我们看看这一版提供了什么API头文件:

  • native_activity.h
  • looper.h
  • input.h
  • keycodes.h
  • sensor.h
  • rect.h
  • window.h
  • native_window.h
  • native_window_jni.h
  • configuration.h
  • asset_manager.h
  • storage_manager.h
  • obb.h

直至今天,Android 7.0,API level 24的时代,上面这些仍然构成了我们这系列教程的主要内容。

同时,Android 2.3还开始支持EGL接口。

Android 4.0开始支持OpenMAX AL库。

Android 4.3开始支持Open GL ES 3.0版

Android 6.0开始支持trace库

Android 7.0开始支持Vulkan, Camera, Choreographer和Multinework库,同时对Open GL ES 3.2的支持

本地应用和窗口

本地应用的框架

首先,写native应用需要一个本地应用的框架的支持。
Java应用需要写一个manifest.xml,我们也入乡随俗需要写一个,我们先看一个NDK sample的例子:

<?xml version="1.0" encoding="utf-8"?>
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.native_activity"
          android:versionCode="1"
          android:versionName="1.0">

  <!-- This .apk has no Java code itself, so set hasCode to false. -->
  <application
      android:allowBackup="false"
      android:fullBackupContent="false"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name"
      android:hasCode="false">

    <!-- Our activity is the built-in NativeActivity framework class.
         This will take care of integrating with our NDK code. -->
    <activity android:name="android.app.NativeActivity"
              android:label="@string/app_name"
              android:configChanges="orientation|keyboardHidden">
      <!-- Tell NativeActivity the name of our .so -->
      <meta-data android:name="android.app.lib_name"
                 android:value="native-activity" />
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
  </application>

</manifest>

因为我们没有写Java代码,所以需要将android:hasCode值设为false.

可以使用NDK中的android_native_app_glue定义的类来对本地API进行封装,我们来看一下,先认识一下后面我们会介绍的几个类:

struct android_app {
    // The application can place a pointer to its own state object
    // here if it likes.
    void* userData;

    // Fill this in with the function to process main app commands (APP_CMD_*)
    void (onAppCmd)(struct android_app app, int32_t cmd);

    // Fill this in with the function to process input events.  At this point
    // the event has already been pre-dispatched, and it will be finished upon
    // return.  Return 1 if you have handled the event, 0 for any default
    // dispatching.
    int32_t (onInputEvent)(struct android_app app, AInputEvent* event);

    // The ANativeActivity object instance that this app is running in.
    ANativeActivity* activity;

    // The current configuration the app is running in.
    AConfiguration* config;

    // This is the last instance's saved state, as provided at creation time.
    // It is NULL if there was no state.  You can use this as you need; the
    // memory will remain around until you call android_app_exec_cmd() for
    // APP_CMD_RESUME, at which point it will be freed and savedState set to NULL.
    // These variables should only be changed when processing a APP_CMD_SAVE_STATE,
    // at which point they will be initialized to NULL and you can malloc your
    // state and place the information here.  In that case the memory will be
    // freed for you later.
    void* savedState;
    size_t savedStateSize;

    // The ALooper associated with the app's thread.
    ALooper* looper;

    // When non-NULL, this is the input queue from which the app will
    // receive user input events.
    AInputQueue* inputQueue;

    // When non-NULL, this is the window surface that the app can draw in.
    ANativeWindow* window;

    // Current content rectangle of the window; this is the area where the
    // window's content should be placed to be seen by the user.
    ARect contentRect;

    // Current state of the app's activity.  May be either APP_CMD_START,
    // APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below.
    int activityState;

    // This is non-zero when the application's NativeActivity is being
    // destroyed and waiting for the app thread to complete.
    int destroyRequested;

    // -------------------------------------------------
    // Below are "private" implementation of the glue code.

    pthread_mutex_t mutex;
    pthread_cond_t cond;

    int msgread;
    int msgwrite;

    pthread_t thread;

    struct android_poll_source cmdPollSource;
    struct android_poll_source inputPollSource;

    int running;
    int stateSaved;
    int destroyed;
    int redrawNeeded;
    AInputQueue* pendingInputQueue;
    ANativeWindow* pendingWindow;
    ARect pendingContentRect;
};

我们看下这个结构中都用到了什么:

  • ANativeActivity: 它是本地应用中对应于android.app.NativeActivity的代理类,定义于android/native_activity.h
  • AConfiguration: 处理配置项。定义于android/configuration.h
  • ALooper: 对应于Java中的Looper,用于处理消息队列,每个线程只能有一个. 定义于android/looper.h
  • AInputQueue: 输入事件的队列,定义于android/input.h中
  • ANativeWindow: 处理窗口的类,定义于android/native_window.h中
  • ARect:代表一个矩形,定义于android/rect.h中

武器库鸟瞰

native应用比起Java应用来,跟Android版本的相关性更高一些。
所以,这些API都是根据平台版本号分成不同的目录的。
下面介绍的android下面的API,对应于Android源码中的frameworks/native/include/中。
在NDK中,以r13b为例,Android 7.0,也就是API 24的头文件位于:android-ndk/r13b/platforms/android-24/arch-arm64/usr/include/中。
我们首先通过一张图来看看Android为我们提供了哪些API:

本地应用和本地窗口类

主要包括下面的头文件:

  • android/native_activity.h

    • ANativeActivity结构:对应android.app.NativeActivity
    • ANativeActivityCallback结构,处理回调
  • android/native_window.h
    • ANativeWindow结构
    • ANativeWindow_Buffer结构
  • android/rect.h
    • ARect结构:有left, top, right, bottom四个属性的矩阵的抽象
  • android/native_window_jni.h: 辅助类
  • android/window.h: 辅助类

资源管理类

  • android/asset_manager.h

    • AAssetManager结构
    • AAssetDir结构
    • AAsset结构
  • android/asset_manager_jni.h
    • AAssetManager_fromJava结构

位图类

  • bitmap.h

    • AndroidBitmapInfo结构

配置类

  • configuration.h

    • AConfiguration结构

输入类

  • input.h

    • AInputEvent结构
    • AInputQueue结构
  • keycodes.h:定义了键码的enum

Looper类

  • android/looper.h

    • ALooper结构
    • ALooper_callbackFunc结构

存储类

  • android/storage_manager.h

    • AStorageManager结构
    • AStorageManager_obbCallbackFunc结构
  • android/obb.h
    • AObbInfo结构

传感器类

  • android/sensor.h

    • ASensorVector结构
    • AMetaDataEvent结构
    • AUncalibratedEvent结构
    • AHeartRateEvent结构
    • ADynamicSensorEvent结构
    • AAdditionalInfoEvent结构
    • ASensorEvent结构
时间: 2024-11-01 14:46:22

Android native应用开发简明教程 (1) - 本地开发武器库概览的相关文章

Android native应用开发简明教程 (2) - 本地应用的原理

本地应用原理 从NativeActivity说起 本地App,本质上是一个Java App调用了一个JNI的库,而应用的逻辑通过native代码来实现. NativeActivity是继承自Activity的一个类,代码在:/frameworks/base/core/java/android/app/NativeActivity.java中: public class NativeActivity extends Activity implements SurfaceHolder.Callbac

php版微信公众账号第三方管理工具开发简明教程_php实例

本文讲述了php版微信公众账号第三方管理工具开发方法.分享给大家供大家参考,具体如下: 最近在捣鼓微信公共平台提供的API,等确实一个获取用户信息的API. 所以没有办法,只能自己去获取,手动填写当然可以解决问题,当然编程不就是为了让生活变的更简单么? 当然,远程抓取微信公共平台数据的想法就油然而生,当然第一个想到了CURL. CURL可以远程提交表达,我感觉微信是提议让我们怎么的,只要不是恶意刷接口,就不会出现验证码. 主要注意的几个问题: ① 远程登录接口是时候的HTTPS协议. ② 登录成

php版银联支付接口开发简明教程_php技巧

本文实例讲述了php版银联支付接口开发的方法.分享给大家供大家参考,具体如下: 支付接口现在有第三方的支付接口也有银行的支付接口.这里就来介绍php版本银联支付接口开发的方法. 银联支付,首先要注意二重要的部分: PHP运行环境是5.4.18以上 开了扩展openssl 开发手册上面的列子只做参考,因为基本都是错的.你可以试着去官网下一个demo...注意现在银联开发,没有测试密钥提供,只能在正式环境开发 下面是我用ThinkPHP编写的一个支付类 /** * 银联支付 v0.1 * @auth

php版微信公众账号第三方管理工具开发简明教程

本文讲述了php版微信公众账号第三方管理工具开发方法.分享给大家供大家参考,具体如下: 最近在捣鼓微信公共平台提供的API,等确实一个获取用户信息的API. 所以没有办法,只能自己去获取,手动填写当然可以解决问题,当然编程不就是为了让生活变的更简单么? 当然,远程抓取微信公共平台数据的想法就油然而生,当然第一个想到了CURL. CURL可以远程提交表达,我感觉微信是提议让我们怎么的,只要不是恶意刷接口,就不会出现验证码. 主要注意的几个问题: ① 远程登录接口是时候的HTTPS协议. ② 登录成

GWT 项目开发 1.6.4 本地开发 appengine-tools-api 突破限制

经过研究发现.google 的限制jar 是   appengine-tools-api    修改类:   com.google.appengine.tools.development.DevAppServerFactory   就可以再本地环境适应 hibernate 连接数据库.创建线程,创建文件等操作.(当然你改的是本地环境.google服务器上的是没有办法了.)   这样做主要是为了开发 gwt 应用的.   修改类如下:     /*jadclipse*/// Decompiled

Android Studio的JNI开发快餐教程

Android Studio的JNI开发快餐教程 从eclipse换到Android Studio之后,原来的NDK集成已经不能用了.同时,AndroidStudio也是在快速迭代进步中,不仅支持内置的ndk支持插件,还有支持外部编译系统的plugin. 而且这还是在实验中的结果,在不久的将来,还可能有更新的变化.不过,万变不离其宗,我们打好基础,形式上的东西跟着Android Studio变就好. 旧式的NDK支持 首先说明,既然是Android Studio认为它已经过时了,所以我们需要在g

一看就懂的Android APP开发入门教程

  这篇文章主要介绍了Android APP开发入门教程,从SDK下载.开发环境搭建.代码编写.APP打包等步骤一一讲解,非常简明的一个Android APP开发入门教程,需要的朋友可以参考下 工作中有做过手机App项目,前端和android或ios程序员配合完成整个项目的开发,开发过程中与ios程序配合基本没什么问题,而android各种机子和rom的问题很多,这也让我产生了学习android和ios程序开发的兴趣.于是凌晨一点睡不着写了第一个android程序HelloAndroid,po出

Android编程Widget创建与使用方法简明教程_Android

本文实例讲述了Android编程Widget创建与使用方法.分享给大家供大家参考,具体如下: Android reference中有关于如何建立一个Widget的详细方法,这里简要说明一下,详情可以查看Android SDK中自带的reference. 要建立一个Widget,分为如下几个步骤: (1) 创建一个类,让其继承类AppWidgetProvider,在AppWidgetProvider中有许多方法,例如onDelete(Context,int[]),onEnable(Context)

《Android开发基础教程》——6.2节Gallery界面组件——画廊展示

6.2 Gallery界面组件--画廊展示 Android开发基础教程 Gallery组件的展示方式是将图片从左到右的方式排列,如同画廊放置作品一样.但是较为特殊的是Gallery组件支持手指左右拖曳滑动的效果,并且可以选择指定的图片,从界面布局来看是相当灵活而有用的组件. 6.2.1 Gallery语法示例与常用的属性 例如:我们要创建一个Gallery组件,名称为"Gallery01",Gallery组件和边界的距离是5dp,图片间的间隔是2dp,宽度填满整个屏幕,高度根据图片高度