Android 开发之NDK
白羽 2018-06-15 来源 :网络 阅读 975 评论 0

摘要:本文将带你了解Android 开发之NDK,希望本文对大家学Android有所帮助。



class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource

显示视图,提供图形绘制函数、触屏事件、按键事件函数等,在UI主线程内更新画面,用于被动更新画面

 

class SurfaceView extends View

适合游戏的开发,类似使用双缓机制,在新的线程中更新画面,主动更新画面

SDL2 使用 SurfaceView,在 SurfaceView 创建完成后,起一个线程来初始化 SDL 并开始主循环

 

class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback

专用于游戏开发的视图,OpenGL专用,主动更新画面

cocos2dx 使用 GLSurfaceView,在 GLSurfaceView 的 onDrawFrame 函数中驱动主循环

 

class NativeActivity extends Activity implements SurfaceHolder.Callback2, InputQueue.Callback, OnGlobalLayoutListener

完全用 NDK 开发应用,使用 EGL 在 activity 上创建 Opengl 的画布,起一个线程开始主循环

使用示例:NVIDIAGameWorks/OpenGLSamples

 

JNI 调用示例:

package com.foobar.helloapp;

import android.view.Surface;import android.app.Activity;

public class JNIWrapper {

 

    static {

        System.loadLibrary("main");

    }

 

    public static native void load_activity(Activity activity);

 

    public static native void on_surface_created(Surface surface);

    public static native void on_surface_changed(int width, int height);

 

    public static native void on_draw_frame(long current);

 

    public static native void on_touch_event(int touch_device_id_in, int pointer_finger_id_in, int action, float x, float y, float p);

 

    public static native void on_pause();

    public static native void on_resume();

}

 

将 java 代码编译成 class 文件,然后使用 javah 导出 c 的头文件

# -classpath 指定class路径,-bootclasspath 指定 android sdk,-d 指定输出目录

javah -classpath HelloApp/app/build/intermediates/classes/debug -bootclasspath android/sdk/platforms/android-19/android.jar -d jni com.foobar.helloapp.JNIWrapper

 

使用 c 调用 java 方法:

// android display metricsstruct DisplayMetrics

{

    int widthPixels;

    int heightPixels;

    float density;

    int densityDpi;

    float scaledDensity;

    float xdpi;

    float ydpi;

};

 

void JNICALL Java_com_foobar_helloapp_JNIWrapper_load_1activity(JNIEnv * env, jclass clazz, jobject activity)

{

    //从对象获取 class

    jclass classActivity = env->GetObjectClass(activity);

 

    

    //从 class 获取方法ID

    jmethodID getAssets = env->GetMethodID(classActivity, "getAssets", "()Landroid/content/res/AssetManager;");

    jmethodID getWindowManager = env->GetMethodID(classActivity, "getWindowManager", "()Landroid/view/WindowManager;");

 

 

    //调用对象方法

    jobject assetManager = env->CallObjectMethod(activity, getAssets);

    //这里调用 android ndk 的方法获得 AAssetManager

    AAssetManager *manager = AAssetManager_fromJava(env, assetManager);

 

 

    //下面的代码等价于:

    //DisplayMetrics metrics = new DisplayMetrics();

    //activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);

    //

    jobject windowManager = env->CallObjectMethod(activity, getWindowManager);

    jclass classWindowManager = env->GetObjectClass(windowManager);

    jmethodID getDefaultDisplay = env->GetMethodID(classWindowManager, "getDefaultDisplay", "()Landroid/view/Display;");

 

 

    jobject display = env->CallObjectMethod(windowManager, getDefaultDisplay);

    jclass classDisplay = env->GetObjectClass(display);

    jmethodID getMetrics = env->GetMethodID(classDisplay, "getMetrics", "(Landroid/util/DisplayMetrics;)V");

 

 

    //调用构造函数实例一个对象

    jclass classDisplayMetrics = env->FindClass("android/util/DisplayMetrics");

    jmethodID displayMetricsConstructor = env->GetMethodID(classDisplayMetrics, "<init>", "()V");

    jobject displayMetrics = env->NewObject(classDisplayMetrics, displayMetricsConstructor);

    env->CallVoidMethod(display, getMetrics, displayMetrics);

 

    

    //读取 java 中的字段

    DisplayMetrics dm;

 

    jfieldID idDisplayMetrics_widthPixels = env->GetFieldID( classDisplayMetrics, "widthPixels", "I");

    jfieldID idDisplayMetrics_heightPixels = env->GetFieldID( classDisplayMetrics, "heightPixels", "I");

    jfieldID idDisplayMetrics_density = env->GetFieldID( classDisplayMetrics, "density", "F");

    jfieldID idDisplayMetrics_densityDpi = env->GetFieldID( classDisplayMetrics, "densityDpi", "I");

    jfieldID idDisplayMetrics_scaledDensity = env->GetFieldID( classDisplayMetrics, "scaledDensity", "F");

    jfieldID idDisplayMetrics_xdpi = env->GetFieldID(classDisplayMetrics, "xdpi", "F");

    jfieldID idDisplayMetrics_ydpi = env->GetFieldID(classDisplayMetrics, "ydpi", "F");

 

 

    if ( idDisplayMetrics_widthPixels ) dm.widthPixels = env->GetIntField(displayMetrics, idDisplayMetrics_widthPixels);

    if ( idDisplayMetrics_heightPixels ) dm.heightPixels = env->GetIntField(displayMetrics, idDisplayMetrics_heightPixels);

    if ( idDisplayMetrics_density ) dm.density = env->GetFloatField(displayMetrics, idDisplayMetrics_density);

    if ( idDisplayMetrics_densityDpi) dm.densityDpi = env->GetIntField(displayMetrics, idDisplayMetrics_densityDpi);

    if ( idDisplayMetrics_scaledDensity) dm.scaledDensity = env->GetFloatField(displayMetrics, idDisplayMetrics_scaledDensity);

    if ( idDisplayMetrics_xdpi ) dm.xdpi = env->GetFloatField(displayMetrics, idDisplayMetrics_xdpi);

    if ( idDisplayMetrics_ydpi ) dm.ydpi = env->GetFloatField(displayMetrics, idDisplayMetrics_ydpi);

}

 

 

void JNICALL Java_com_foobar_helloapp_JNIWrapper_on_1surface_1created(JNIEnv * env, jclass clazz, jobject surface)

{

    //调用 android ndk 方法

    ANativeWindow * window = ANativeWindow_fromSurface(env, surface);

}

 


本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之Android频道


本文由 @白羽 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程