[Android NDK]Android JNI开发例子 ---1 静态加载JNI lib

10 篇文章 1 订阅
5 篇文章 0 订阅

JNI函数的注册有两种方法,一种是静态方法,需要用javah为每个声明了native函数的java类编译出的class文件生成一个头文件,另一种是动态注册,通过数据结构保存关联关系实现注册,这里主要介绍静态注册。


1. 创建一个Android Activity 项目, 我的项目有三个Class, 主要是用来显是gl surface view的东西。

package com.example.nativeegl;

import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.Window;
import android.view.WindowManager;

public class MainActivity extends Activity {
    GLSurfaceView mGLView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.requestWindowFeature(Window.FEATURE_NO_TITLE); 
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN); // (NEW)

        mGLView = new MyGLSurfaceView(this);
        
        setContentView(mGLView);
    }
}

GLSurfaceView在有touch事件时更新颜色。

package com.example.nativeegl;

import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.SurfaceHolder;

public class MyGLSurfaceView extends GLSurfaceView {

    GLSurfaceView.Renderer mRenderer;
    /**
     * TODO Put here a description of what this constructor does.
     *
     * @param context
     */
    public MyGLSurfaceView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub.
        mRenderer = new MyRenderer();
     // Set the Renderer for drawing on the GLSurfaceView
        setRenderer(mRenderer);
    }
    @Override
    public boolean onTouchEvent(final MotionEvent event) {
        // TODO Auto-generated method stub.
        queueEvent(new Runnable() {  
            public void run() {  
                ((MyRenderer)mRenderer).setColor(event.getX() / getWidth(), event.getY() / getHeight(), 1.0f);  
            }
        });  
        return true;
    }
}

Renderer

public class MyRenderer implements GLSurfaceView.Renderer {

    private static final String TAG = "bbaiagl";
    private float _red = 0.9f;
    private float _green = 0.2f;
    private float _blue = 0.2f;
   
//加载库文件
    static {
        System.loadLibrary("myegl_jni");
    }
//声明native方法,返回String
    public native String nativeGetHelloString();
    
    @Override
    public void onDrawFrame(GL10 gl) {
       // onNativeDrawFrame();
//使用native方法
 Log.d(TAG, "onDrawFrame "+ nativeGetHelloString());
        // define the color we want to be displayed as the "clipping wall"
        gl.glClearColor(_red, _green, _blue, 1.0f);
        // clear the color buffer to show the ClearColor we called above...
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        //onNativeSurfaceChanged(width,height);
        Log.d(TAG, "onSurfaceChanged");
        // Sets the current view port to the new size.
        gl.glViewport(0, 0, width, height);// OpenGL docs.

        // Select the projection matrix
        gl.glMatrixMode(GL10.GL_PROJECTION);// OpenGL docs.

        // Reset the projection matrix
        gl.glLoadIdentity();// OpenGL docs.]
        //gl.glOrthof(0, width,0,height,0,10);
        // Calculate the aspect ratio of the window
        GLU.gluPerspective(gl, 45.0f, (float) width / (float) height, 0.1f, 100.0f);

        // Select the modelview matrix
        gl.glMatrixMode(GL10.GL_MODELVIEW);// OpenGL docs.

        // Reset the modelview matrix
        gl.glLoadIdentity();// OpenGL docs.
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        //onNativeSurfaceCreated();
        Log.d(TAG, "onSurfaceCreate");
        // Set the background color to black ( rgba ).
        gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // OpenGL docs.

        // Enable Smooth Shading, default not really needed.
        gl.glShadeModel(GL10.GL_SMOOTH);// OpenGL docs.

        // Depth buffer setup.
        gl.glClearDepthf(1.0f);// OpenGL docs.

        // Enables depth testing.
        gl.glEnable(GL10.GL_DEPTH_TEST);// OpenGL docs.

        // The type of depth testing to do.
        gl.glDepthFunc(GL10.GL_LEQUAL);// OpenGL docs.

        // Really nice perspective calculations.
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
    }

    public void setColor(float r, float g, float b) {
        _red = r;
        _green = g;
        _blue = b;
    }
}

2. 在项目路径下执行会在项目目录下生成jni文件夹和头文件

javah -classpath bin/classes -d jni com.example.nativeegl.MyRenderer

最后面的参数是 包名.需要native库的类名。


3. 根据头文件做cpp文件。

com_example_nativeegl_MyRenderer.h

可以看到自动生成的函数

Java_com_example_nativeegl_MyRenderer_nativeGetHelloStrin

Java_ + 包名+类名+接口名:必须按照这个规则来定义JNI接口的函数名

#include <jni.h>
/* Header for class com_example_nativeegl_MyRenderer */
#include <string.h>
//因为我们的实现是用cpp,而不是c, 所以要定义__cplusplus宏。
#define __cplusplus

#ifndef _Included_com_example_nativeegl_MyRenderer //这个宏在cpp实现中要删除。 如果不删除的话,当cpp文件包含这个头文件时,因为这个宏在头文件中已经被定义过,所以会导致cpp里面的内容不执行。作用是防止该头文件被重复引用
#define _Included_com_example_nativeegl_MyRenderer

#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_nativeegl_MyRenderer
 * Method:    nativeGetHelloString
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_nativeegl_MyRenderer_nativeGetHelloString
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

在jni文件夹下, 

mkdir include
mv a.h include/
cp include/a.h a.cpp

在头文件的基础上修改成cpp

#include "com_example_nativeegl_MyRenderer.h" //添加头文件
extern "C" {
/*
 * Class:     com_example_nativeegl_MyRenderer
 * Method:    nativeGetHelloString
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_nativeegl_MyRenderer_nativeGetHelloString
  (JNIEnv *env, jobject obj) {
      return env->NewStringUTF((char*)" This is calling from JNI suckers!");
  }
}


添加Android.mk文件。Android.mk的语法,请查看链接

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_CFLAGS    := -Wall    //gcc编译的参数。 man gcc 查询
LOCAL_MODULE    := myegl_jni
LOCAL_C_INCLUDES :=$(LOCAL_PATH)/include
LOCAL_CPP_EXTENSION := .cpp
LOCAL_SRC_FILES := com_example_nativeegl_MyRenderer.cpp

include $(BUILD_SHARED_LIBRARY)


在项目的根目录执行

ndk-build

编译出动态库。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值