Time for action – handling primitives in the native store

  1. In StoreType.java, add the newly managed integer type to the enumeration:
    public enum StoreType {
        Integer,
        String
    }
  2. Open Store.java and define the new integer functionalities our native store provides:
    public class Store {
        ...
        public native int getCount();
        
        public native int getInteger(String pKey);
        public native void setInteger(String pKey, int pInt);
    
        public native String getString(String pKey);
        public native void setString(String pKey, String pString);
    }
  3. In the StoreActivity class, update the onGetValue() method to retrieve integer entries from the store when they are selected in the GUI:
    public class StoreActivity extends Activity {
        ...
        public static class PlaceholderFragment extends Fragment {
            ...
            private void onGetValue() {
                ...
                switch (type) {
                case Integer:
                    mUIValueEdit.setText(Integer.toString(mStore
                                    .getInteger(key)));
                    break;
                case String:
                    mUIValueEdit.setText(mStore.getString(key));
                    break;
                }
            }
            ...
  4. Also, insert or update integer entries in the store in the onSetValue() method. The entry data needs to be parsed before being passed to the native side:
            ...
            private void onSetValue() {
                ...
                try {
                    switch (type) {
                    case Integer:
                        mStore.setInteger(key, Integer.parseInt(value));
                        break;
                    case String:
                        mStore.setString(key, value);
                        break;
                    }
                } catch (Exception eException) {
                    displayMessage("Incorrect value.");
                }
                updateTitle();
            }
            ...
        }
    }
  5. In jni/Store.h, append the integer type in the native StoreType enumeration and the StoreValue union:
    ...
    typedef enum {
        StoreType_Integer,
        StoreType_String
    } StoreType;
    typedef union {
        int32_t   mInteger;
        char*     mString;
    } StoreValue;
    ...
  6. Refresh the JNI header file jni/com_packtpub_Store.h with javah. Two new methods Java_com_packtpub_store_Store_getInteger() and Java_com_packtpub_store_Store_getInteger() should appear.
  7. In jni/com_packtpub_Store.cpp, implement getInteger() with the help of the generated JNI header. This method simply returns the integer value of an entry without doing any specific conversion other than an implicit cast from int32_t to jint. If any problem occurs, during retrieval, a default value is returned:
    ...
    JNIEXPORT jint JNICALL Java_com_packtpub_store_Store_getInteger
      (JNIEnv* pEnv, jobject pThis, jstring pKey) {
        StoreEntry* entry = findEntry(pEnv, &gStore, pKey);
        if (isEntryValid(pEnv, entry, StoreType_Integer)) {
            return entry->mValue.mInteger;
        } else {
            return 0;
        }
    }
    ...
  8. The second method setInteger() stores the given integer value in the allocated entry. Note how here too that the passed JNI integer can be reversely cast to a C/C++ integer:
    ...
    JNIEXPORT void JNICALL Java_com_packtpub_store_Store_setInteger
      (JNIEnv* pEnv, jobject pThis, jstring pKey, jint pInteger) {
        StoreEntry* entry = allocateEntry(pEnv, &gStore, pKey);
        if (entry != NULL) {
            entry->mType = StoreType_Integer;
            entry->mValue.mInteger = pInteger;
        }
    }

What just happened?

Run the application. Try to save a few entries with different keys, types, and values. Then try to get them back from the native store. We have this time managed to pass and retrieve integer primitives from Java to C/C++.

Integer primitives wear several dresses during native calls; first, int in Java code, then jint during transfer from/to Java code, and finally, int or int32_t in native code. Obviously, we could have kept the JNI representation jint in native code if we wanted to, since all of these types are simply equivalent. In other words, jint is simply an alias.

Tip

The int32_t type is typedef introduced by the C99 standard library with the aim at more portability. The difference with the standard int type is that its size-in-bytes is fixed for all compilers and platforms. More numeric types are defined in stdint.h (in C) or cstdint (in C++).

All primitive types have their proper alias in JNI:

Java type

JNI type

C type

Stdint C type

boolean

Jboolean

unsigned char

uint8_t

byte

Jbyte

signed char

int8_t

char

Jchar

unsigned short

uint16_t

double

Jdouble

double

N/A

float

jfloat

float

N/A

int

jint

Int

int32_t

long

jlong

long long

int64_t

short

jshort

Short

int16_t

You can use them exactly the same way we used integers in this part. More information about primitive types in JNI can be found at http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/types.html

Have a go hero – passing and returning other primitive types

The current store deals only with integers and strings. Based on this model, try to implement store methods for other primitive types: boolean, byte, char, double, float, long, and short.

Note

The resulting project is provided with this book under the name Store_Part6_Full.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.5.239