Chinaunix首页 | 论坛 | 博客
  • 博客访问: 79109
  • 博文数量: 8
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 599
  • 用 户 组: 普通用户
  • 注册时间: 2013-06-27 16:46
个人简介

哎……马上就要毕业了!求工作啊^0^

文章分类

全部博文(8)

文章存档

2013年(8)

我的朋友

分类: Android平台

2013-06-27 20:50:39

在本章我们将学习以下东西:

1.在java与本地代码之间传递与接收基本类型、对象、数组

2.在本地代码里面处理java对象

3.从本地代码中引起异常

与java基本类型的联系

    一个简单的Java GUI是由一个关键字(一个特殊的字符串),类型(整形,字符串等等)和一个与所选类型有关的值所定义的接口。接口被插入或者修改的数据将会驻留在本地代码里面。接口也可以被Java客户端回调。程序类似一个键值对,按照指定的Key来去相应的Value,而Value分为Integer和String类型;下面的图片展示了一个程序大概会被怎样构架:
程序的界面:

动手时间——建立一个本地值/关键字Store

首先实现Java方面的代码:

  1.建立一个Java/C++的混合项目

命名为Store
主包为cn.StoreActivity
主Activity为StoreActivity
不要忘了在根目录下面创建Jni文件夹
java方面将会包含三个源文件 Store.java    StoreType.java  和 StoreActivity.java

  2.在res/layout/main.xml文件里面按照下面的图片建立Java GUI。


点击(此处)折叠或打开

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android=""
  3.     android:orientation="vertical"
  4.     android:layout_width="match_parent"
  5.     android:layout_height="match_parent"
  6.     >
  7. <TextView
  8.     android:layout_width="match_parent"
  9.     android:layout_height="wrap_content"
  10.     android:text="Save or retrieve a value from the store:"
  11.     />
  12.     <!-- android:layout_width="wrap_content"-->
  13.     <!-- android:layout_height="match_parent" -->
  14.     <!-- 如果TableLayout头两句写成这样,两个按钮会显示不出来 -->
  15.  <TableLayout
  16.     android:layout_width="match_parent"
  17.     android:layout_height="wrap_content"
  18.     android:stretchColumns="1" >
  19.     <TableRow>
  20.        <TextView
  21.           android:id="@+id/ui_KeyLable"
  22.           android:text="Key:"/>
  23.        <EditText
  24.           android:id="@+id/et_Key">
  25.           <requestFocus></requestFocus>
  26.        </EditText>
  27.     </TableRow>
  28.     <TableRow>
  29.        <TextView
  30.           android:id="@+id/ui_valueLabale"
  31.           android:text="Value:"/>
  32.        <EditText
  33.           android:id="@+id/et_Value"/>
  34.           
  35.     </TableRow>
  36.     <TableRow>
  37.        <TextView
  38.           android:id="@+id/ui_TypeLable"
  39.           android:layout_height="match_parent"
  40.           android:gravity="center_vertical"
  41.           android:text="Type:"/>
  42.        <Spinner
  43.           android:id="@+id/sp_type"/>
  44.     </TableRow>
  45.  </TableLayout>
  46.   <LinearLayout
  47.     android:layout_width="wrap_content"
  48.     android:layout_height="wrap_content"
  49.     android:gravity="right">
  50.     <Button
  51.        android:id="@+id/bt_getValue"
  52.        android:layout_width="wrap_content"
  53.        android:layout_height="wrap_content"
  54.        android:text="Get value"/>
  55.     <Button
  56.        android:id="@+id/bt_setValue"
  57.        android:layout_width="wrap_content"
  58.        android:layout_height="wrap_content"
  59.        android:text="Set Value"/>
  60.    </LinearLayout>
  61. </LinearLayout>

3.以enum建立StoreType.java支持ui中type指定的几种数据类型

点击(此处)折叠或打开

  1. package cn.StoreActivity;
  2. public enum StoreType {
  3.    Integer,String;
  4. }

4.建立一个新的Store类导入与本地library同名的库,定义我们store将要听过的函数。Store是我们本地代码 的前端。它仅仅支持整型和字符串型

点击(此处)折叠或打开

  1. package cn.StoreActivity;
  2. public class Store {
  3.     public native int getInteger(String key);
  4.     public native void setInteger(String key,int Kint);
  5.     
  6.     public native String getString(String key);
  7.     public native void setString(String key,String string);
  8. }

5.在Jni目录下面,创建定义了数据结构体的Store.h。创建一个StoreType枚举出匹配java方面的类型。
同时创建Store。StoreEntry包含了一个关键字(C字符串),类型和一个值。StoreValue就是一个包含所有可能值
的集合体:


点击(此处)折叠或打开

  1. #ifndef _STORE_H_
  2. #define _STORE_H_

  3. #include "jni.h"
  4. #include <stdint.h>

  5. /*
  6.  * Constants.
  7.  */
  8. #define STORE_MAX_CAPACITY 16


  9. /*
  10.  * Types handled by the store.
  11.  */
  12. typedef enum {
  13.     StoreType_Integer, StoreType_String
  14. } StoreType;

  15. /**
  16.  * Store data structures.
  17.  */
  18. typedef union {
  19.     int32_t mInteger;
  20.     char* mString;
  21. } StoreValue;

  22. typedef struct {
  23.     char* mKey;
  24.     StoreType mType;
  25.     StoreValue mValue;
  26. } StoreEntry;

  27. typedef struct {
  28.     StoreEntry mEntries[STORE_MAX_CAPACITY];
  29.     int32_t mLength;
  30. } Store;

  31. /*
  32.  * Store helper methods.
  33.  */
  34. int32_t isEntryValid(JNIEnv* pEnv, StoreEntry* pEntry,
  35.                      StoreType pType);

  36. StoreEntry* allocateEntry(JNIEnv* pEnv, Store* pStore, jstring pKey);

  37. StoreEntry* findEntry(JNIEnv* pEnv, Store* pStore, jstring pKey,
  38.                       int32_t* pError);

  39. void releaseEntryValue(JNIEnv* pEnv, StoreEntry* pEntry);

  40. #endif

  6.在jni目录下创建定义了数据结构体的Store.h对应的工具类Store.c

点击(此处)折叠或打开

  1. #include "Store.h"
  2. #include <string.h>

  3. int32_t isEntryValid(JNIEnv* pEnv, StoreEntry* pEntry,
  4.     StoreType pType) {
  5.     if ((pEntry != NULL) && (pEntry->mType == pType)) {
  6.         return 1;
  7.     }
  8.     return 0;
  9. }

  10. StoreEntry* findEntry(JNIEnv* pEnv, Store* pStore, jstring pKey,
  11.                       int32_t* pError) {
  12.     StoreEntry* lEntry = pStore->mEntries;
  13.     StoreEntry* lEntryEnd = lEntry + pStore->mLength;

  14.     // Compare requested key with every entry key currently stored
  15.     // until we find a matching one.
  16.     const char* lKeyTmp = (*pEnv)->GetStringUTFChars(pEnv, pKey,
  17.                                                      NULL);
  18.     if (lKeyTmp == NULL) {
  19.         if (pError != NULL) {
  20.             *pError = 1;
  21.         }
  22.         return;
  23.     }

  24.     while ((lEntry < lEntryEnd)
  25.         && (strcmp(lEntry->mKey, lKeyTmp) != 0)) {
  26.         ++lEntry;
  27.     }
  28.     (*pEnv)->ReleaseStringUTFChars(pEnv, pKey, lKeyTmp);

  29.     return (lEntry == lEntryEnd) ? NULL : lEntry;
  30. }

  31. StoreEntry* allocateEntry(JNIEnv* pEnv, Store* pStore, jstring pKey){
  32.     // If entry already exists in the store, releases its content
  33.     // and keep its key.
  34.     int32_t lError = 0;
  35.     StoreEntry* lEntry = findEntry(pEnv, pStore, pKey, &lError);
  36.     if (lEntry != NULL) {
  37.         releaseEntryValue(pEnv, lEntry);
  38.     }
  39.     // If entry does not exist, create a new entry right after
  40.     // already allocated entries.
  41.     else if (!lError) {
  42.         // Checks store can accept a new entry.
  43.         if (pStore->mLength >= STORE_MAX_CAPACITY) {
  44.             return NULL;
  45.         }
  46.         lEntry = pStore->mEntries + pStore->mLength;

  47.         // Copies the new key into its final C string buffer.
  48.         const char* lKeyTmp = (*pEnv)->GetStringUTFChars(pEnv, pKey,
  49.                                                          NULL);
  50.         if (lKeyTmp == NULL) {
  51.             return;
  52.         }

  53.         lEntry->mKey = (char*) malloc(strlen(lKeyTmp));
  54.         strcpy(lEntry->mKey, lKeyTmp);
  55.         (*pEnv)->ReleaseStringUTFChars(pEnv, pKey, lKeyTmp);

  56.         ++pStore->mLength;
  57.     }
  58.     return lEntry;
  59. }
  60. void releaseEntryValue(JNIEnv* pEnv, StoreEntry* pEntry) {
  61.     int i;
  62.     switch (pEntry->mType) {
  63.         case StoreType_String:
  64.             free(pEntry->mValue.mString);
  65.             break;
  66.     }
  67. }


 7.使用javah编译cn.StoreActivity.Store生成的JNI的头文件→jni/cn_StoreActivity_Store.h


 8.功能函数和JNI头文件已生成,现在需要写jni源文件→StoreActivity.c


点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <string.h>
  4. #include "cn_StoreActivity_Store.h"
  5. #include "Store.h"

  6. static Store mStore = { {}, 0 };

  7. JNIEXPORT jint JNICALL Java_cn_StoreActivity_Store_getInteger
  8.   (JNIEnv * pEnv, jobject pThis, jstring pKey){
  9.     StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
  10.     if (isEntryValid(pEnv, lEntry, StoreType_Integer)) {
  11.      return lEntry->mValue.mInteger;
  12.     } else {
  13.      return 0;
  14.     }
  15. }

  16. /*
  17.  * Class: cn_StoreActivity_Store
  18.  * Method: setInteger
  19.  * Signature: (Ljava/lang/String;I)V
  20.  */
  21. JNIEXPORT void JNICALL Java_cn_StoreActivity_Store_setInteger
  22. (JNIEnv* pEnv, jobject pThis, jstring pKey, jint pInteger) {
  23.    StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);
  24.    if (lEntry != NULL) {
  25.        lEntry->mType = StoreType_Integer;
  26.        lEntry->mValue.mInteger = pInteger;
  27.    }
  28. }
  29. /*
  30.  * Class: cn_StoreActivity_Store
  31.  * Method: getString
  32.  * Signature: (Ljava/lang/String;)Ljava/lang/String;
  33.  */
  34. JNIEXPORT jstring JNICALL Java_cn_StoreActivity_Store_getString
  35. (JNIEnv* pEnv, jobject pThis, jstring pKey) {
  36.     StoreEntry* lEntry = findEntry(pEnv, &mStore, pKey, NULL);
  37.     if (isEntryValid(pEnv, lEntry, StoreType_String)) {
  38.         // Converts a C string into a Java String.
  39.         return (*pEnv)->NewStringUTF(pEnv, lEntry->mValue.mString);
  40.     } else {
  41.         return NULL;
  42.     }
  43. }
  44. /*
  45.  * Class: cn_StoreActivity_Store
  46.  * Method: setString
  47.  * Signature: (Ljava/lang/String;Ljava/lang/String;)V
  48.  */
  49. JNIEXPORT void JNICALL Java_cn_StoreActivity_Store_setString
  50. (JNIEnv* pEnv, jobject pThis, jstring pKey, jstring pString) {
  51.     // Turns the Java string into a temporary C string.
  52.     // GetStringUTFChars() is used here as an example but
  53.     // Here, GetStringUTFChars() to show
  54.     // the way it works. But as what we want is only a copy,
  55.     // GetBooleanArrayRegion() would be be more efficient.
  56.     const char* lStringTmp = (*pEnv)->GetStringUTFChars(pEnv, pString, NULL);
  57.     if (lStringTmp == NULL) {
  58.         return;
  59.     }

  60.     StoreEntry* lEntry = allocateEntry(pEnv, &mStore, pKey);
  61.     if (lEntry != NULL) {
  62.         lEntry->mType = StoreType_String;
  63.         // Copy the temporary C string into its dynamically allocated
  64.         // final location. Then releases the temporary string.
  65.         // Malloc return value should theoretically be checked...
  66.         jsize lStringLength = (*pEnv)->GetStringUTFLength(pEnv, pString);
  67.         lEntry->mValue.mString =
  68.             (char*) malloc(sizeof(char) * (lStringLength + 1));
  69.         strcpy(lEntry->mValue.mString, lStringTmp);
  70.     }
  71.     (*pEnv)->ReleaseStringUTFChars(pEnv, pString, lStringTmp);
  72. }


阅读(1824) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:第三章笔记(2)

给主人留下些什么吧!~~