打算写一个FbSetApp去操作framebuffer的设备文件,以便能够去设置FB的一些参数。
新建两个class
FbParams.java:
package org.trident.fbset;
public class FbParams {
 int pos_x;
    int pos_y;
    int size_x;//Width
    int size_y;//Height
}
 
用于传递FB起始位置和大小的参数。
 
FbSetControl.java:
 
package org.trident.fbset;
public class FbSetControl {
 
 static {
  System.loadLibrary("fbset");
 }
 
 public native int Init();
 public native int SetPosition();
}

然后在FbSetApp下,执行:
javac -d bin src\org\trident\app\FbParams.java
javac -d bin src\org\trident\app\FbSetControl.java
然后转到FbSetApp\bin\classes下
javah -d ../../jni org.trident.app.FbSetControl
这样就会在FbSetApp\jni目录下生成org_trident_app_FbSetControl.h:
如果报文件无法访问和找不到类,那么多半是环境变量设置有问题:
 
java_home:C:\Program Files\Java\jdk1.7.0_01(java安装好后的路径),
Path变量中添加 %java_home%/bin,
classpath:.;%java_home%/lib 
 加入我们自己要用到的结构cnxtfb_position

org_trident_app_FbSetControl.h:
 
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_trident_fbset_FbSetControl */
#ifndef _Included_org_trident_fbset_FbSetControl
#define _Included_org_trident_fbset_FbSetControl
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     org_trident_fbset_FbSetControl
 * Method:    Init
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_org_trident_fbset_FbSetControl_Init
  (JNIEnv *, jobject);
/*
 * Class:     org_trident_fbset_FbSetControl
 * Method:    GetResolution
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_org_trident_fbset_FbSetControl_GetResolution
 (JNIEnv *, jobject, jobject tparam);
/*
 * Class:     org_trident_fbset_FbSetControl
 * Method:    SetPosition
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_org_trident_fbset_FbSetControl_SetPosition
  (JNIEnv *, jobject, jobject tparam);


typedef struct _cnxtfb_position{
  int nPosX;
  int nPosY;
  int nSizeX;
  int nSizeY;
}cnxtfb_position;
typedef struct _cnxtfb_resolution{
  int uWidth;
  int uHeight;
}cnxtfb_resolution;
#ifdef __cplusplus
}
#endif
#endif
 
 

在FbSetApp/jni创建一个C文件,org_trident_fbset_FbSetControl.c:
#include <jni.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <android/log.h>
#include <org_trident_fbset_FbSetControl.h>
#define  DEVICE_NAME  "/dev/fb0"  //device point
#define FBIO_SET_POSITION      0x4637
#define FBIO_GETFBRESOLUTION      0x4626
#define  OMX_HAL_IOCTL_SET_SCREEN_POS_HW_CURSOR 0x12
static cnxtfb_position fb_pos;
static cnxtfb_resolution fb_res;
//#define DBG 0
#define  LOG_TAG    "fbset"
#define  printf(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     FbSetControl
 * Method:    Init
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_org_trident_fbset_FbSetControl_Init
  (JNIEnv * env, jobject  obj)
{
 fb_pos.nPosX = 0;
 fb_pos.nPosY = 0;
 fb_pos.nSizeX = 0;
 fb_pos.nSizeX = 0;
 printf("%d %d,%d %d",fb_pos.nPosX,fb_pos.nPosY,fb_pos.nSizeX,fb_pos.nSizeY); 
}
/*
 * Class:     FbSetControl
 * Method:    GetResolution
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_org_trident_fbset_FbSetControl_GetResolution
  (JNIEnv * env, jobject  obj, jobject tparam)
{
 jfieldID fid;
 jclass tprm = (*env)->GetObjectClass(env, tparam);
 static int fbfd = -1;
 if (fbfd < 0)
 {
     if ( ( fbfd = open( "/dev/fb0", O_RDWR ) ) < 0 )
  {
         printf(stderr, "open %s error!\n",DEVICE_NAME);
         //return -1;
     }
     if (ioctl(fbfd, FBIO_GETFBRESOLUTION, &fb_res)) {
         printf(stderr, "error FBIO_SET_POSITION screeninfo!\n");
         //return -1;
     }
     fid = (*env)->GetFieldID(env, tprm, "width", "I");
     (* env)->SetIntField(env,tparam, fid, fb_res.uWidth);
     printf("uWidth is %d",fb_res.uWidth);
     fid = (*env)->GetFieldID(env, tprm, "height", "I");
     (* env)->SetIntField(env,tparam, fid, fb_res.uHeight);
     printf("uHeight is %d",fb_res.uWidth);
     close(fbfd);
     fbfd=-1;
 }
}
JNIEXPORT jint JNICALL Java_org_trident_fbset_FbSetControl_SetPosition
  (JNIEnv * env, jobject  obj, jobject tparam)
{
 jfieldID fid;
    jclass tprm = (*env)->GetObjectClass(env, tparam);
 static int fbfd = -1;
    static int cursorfd = -1;
   
    fid = (*env)->GetFieldID(env, tprm, "pos_x", "I");
    fb_pos.nPosX = (*env)->GetIntField(env, tparam, fid);
    printf("nPosX is %d",fb_pos.nPosX);
    fid = (*env)->GetFieldID(env, tprm, "pos_y", "I");
    fb_pos.nPosY = (*env)->GetIntField(env, tparam, fid);
    printf("nPosY is %d",fb_pos.nPosY);
    fid = (*env)->GetFieldID(env, tprm, "size_x", "I");
    fb_pos.nSizeX = (*env)->GetIntField(env, tparam, fid);
    printf("nSizeX is %d",fb_pos.nSizeX);
    fid = (*env)->GetFieldID(env, tprm, "size_y", "I");
    fb_pos.nSizeY = (*env)->GetIntField(env, tparam, fid);
    printf("%d %d,%d %d",fb_pos.nPosX,fb_pos.nPosY,fb_pos.nSizeX,fb_pos.nSizeY);
#ifdef DBG
  //printf("%d %d,%d %d",fb_pos.nPosX,fb_pos.nPosY,fb_pos.nSizeX,fb_pos.nSizeY); 
#else
    if (fbfd < 0)
    {
     if ( ( fbfd = open( "/dev/fb0", O_RDWR ) ) < 0 )
    {
         printf(stderr, "open %s error!\n",DEVICE_NAME);
         //return -1;
     }
     if (ioctl(fbfd, FBIO_SET_POSITION, &fb_pos)) {
         printf(stderr, "error FBIO_SET_POSITION screeninfo!\n");
         //return -1;
     }
   
     close(fbfd);
     fbfd=-1;
 }
 if (cursorfd < 0)
 {
     if ((cursorfd = open("/dev/HW_CURSOR", O_RDWR))<0)
  {
      printf("Failed to open HD cursor node warnerye.\n");
      //return ;
     }
     if(ioctl(cursorfd, OMX_HAL_IOCTL_SET_SCREEN_POS_HW_CURSOR, &fb_pos) < 0)
  {
   printf("change Cursor FB POSITION failed: %s\n", strerror(errno));
   close(cursorfd);
   cursorfd = -1;
   //return;
  }
  close(cursorfd);
     cursorfd=-1;
    }
#endif
}
#ifdef __cplusplus
}
#endif
 
对于jni部分参数传递的方法,在此有必要说明一下:
jfieldID fid;
jclass tprm = (*env)->GetObjectClass(env, tparam);
作用是拿到传递的env中我们添加的tparam结构的指针
fid = (*env)->GetFieldID(env, tprm, "pos_x", "I");
作用是拿到tparam结构中pos_x的ID,"I"表示是int,如果我们要传递字符串变量,比如IP地址,可以这样写:
const char *ip;
jfieldID fid;
jstring jstr;
jclass tprm = (*env)->GetObjectClass(env, tparam);
 
fid = (*env)->GetFieldID(env, tparam, "ipadd", "Ljava/lang/String;");
jstr = (*env)->GetObjectField(env,tparam, fid);
ip = (*env)->GetStringUTFChars(env, jstr, NULL);
//strcpy(param.pszSrcAddr,ip);
(*env)->ReleaseStringUTFChars(env,jstr,ip);
printf("ip is %s",params.pszSrcAddr);
 
然后再增加一个Android.mk:
 
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := fbset
LOCAL_SRC_FILES := org_trident_fbset_FbSetControl.c
LOCAL_C_INCLUDES := inc
LOCAL_LDLIBS    := -lm -llog -ljnigraphics
LOCAL_LDLIBS    += -LD:/Android/workspace/fbset/jni/lib
include $(BUILD_SHARED_LIBRARY)

然后就可以使用ndk-build编译生成so,要做这一步,你需要安装NDK,安装步骤你可以参照:
安装完成以后你就可以在cygwin下面编译jni部分的代码生成so文件了。