definition Java Native Interface how it works http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html JavaVM and JNIEnv JavaVM one process can only create one JavaVM in Android JNIEnv provides most of JNI functions. Your native functions all receive a JNIEnv as first argument used for thread-local, so you cannot share a JNIEnv between threads (GetEnv can be used to discover the thread’s JNIEnv when no other way) Threads a thread will have no JNIEnv unless it’s attached, before this it cannot make JNI calls (all threads are Linux threads, scheduled by the kernel) Threads attached through JNI must call DetachCurrentThread before they exit jclass, jmethodID, and jfieldID steps to access an object’s field from native code FindClass:—> get the class object reference for the class GetFieldID:—>Get the field ID for the field with GetFieldID GetIntField:—>Get the contents of the field with something appropriate call a method—> get a class object reference and then a method ID it’s useful to look the values up once and cache the results in your native code. Because there is a limit of one JAVAVM per process if want to cache IDs when a class is loaded, add a piece of code that allow the native code to cache field offsets Local and Global Reference almost every object returned by a JNI function is a “local reference”—>it’s valid for the duration of the current native method in the current thread. Even if the object itself continues to live on after the native method returns, the reference is not valid the only way to get non-local references is via the functions NewGlobalRef and NewWeakGlobalRef (the global reference is guaranteed to be valid until you call DeleteGlobalRef) to see if two reference refer to the same object, you must use the IsSameObject function, never use == in native code jfieldIDs, jmethod are opaque types, not object references, should not be passed to NewGlobalRef if you attach a native thread with AttachCurrentThread, the code you are running will never automatically free local references until the thread detaches. Any local references you create will have to be deleted manually. UTF-8 and UTF-16 Strings java use UTF-16, JNI provides methods that work with Modified UTF-8 as well. you cannot pass arbitrary UTF-8 data to JNI and expect it to work correctly Android currently does not require a copy in GetStringChars,however GetStringUTFChars requires an allocation and a conversion to UTF-8. UTF-16 strings are not zero-terminated, \u0000 is allowed, so you need to hang on to the string length like jchar pointer Don’t forget to Release the strings you Get. the string functions return jchar or jbyte Data passed to NewStringUTF must be in Modified UTF-8 format Primitive Arrays You must Release every array you Get release mode arguments alternative values 0 buffer freed JNI_COMMIT do nothing/ buffer not freed JNI_ABORT buffer freed, Earlier wirtes are not aborted Region calls advantages reducing overhead by reducing JNI call requirements do not require pinning or extra data copies reduces the risk of programmer error–> no risk of forgetting to call Release Exception your must not call JNI functions while an exception is pending, except several special kinds of API: delete/ exception process/stack process/ release process … Extended Checking JNI does very little error checking ~~! Android offers a mode called CheckJNI array, bad pointers, Class names, Critical call,Direct ByteBuffers, Exceptions, JNIEnvs, jmethodIDs, References,Release modes, Type safety, UTF-8 Native Libraries steps call System.loadLibrary provide a native function : jint JNI_OnLoad(JavaVM vm void* reserved) in JNI_OnLoad, register all your native methods 64-bit Considerations you need to stash your native pointers in a long field rather than an int Unsupported Features/ Backwards Compatibility Define class dynamic lookup of native functions detaching threads weak global references Local references determining reference type with GetObjectRefType
# For more information about using CMake with Android Studio, read the # documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC # or SHARED, and provides the relative paths to its source code. # You can define multiple libraries, and CMake builds them for you. # Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library. native-lib
# Sets the library as a shared library. SHARED
# Provides a relative path to your source file(s). src/main/cpp/native-lib.cpp )
# Searches for a specified prebuilt library and stores the path as a # variable. Because CMake includes system libraries in the search path by # default, you only need to specify the name of the public NDK library # you want to add. CMake verifies that the library exists before # completing its build.
find_library( # Sets the name of the path variable. log-lib
# Specifies the name of the NDK library that # you want CMake to locate. log )
# Specifies libraries CMake should link to your target library. You # can link multiple libraries, such as libraries you define in this # build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library. native-lib
# Links the target library to the log library # included in the NDK. ${log-lib} )
publicclassCppTest{ /** * A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ publicnative String stringFromJNI();
// Used to load the 'native-lib' library on application startup. static { System.loadLibrary("native-lib"); } }
class Response<T> { int code(); String message(); Headers headers();
boolean isSuccess(); T body(); ResponseBody errorBody(); com.squareup.okhttp.Response raw(); }
同时还提供了一个很方便的函数来帮助你判断请求是否成功完成,其实就是检查了下响应码是不是 200。然后就拿到了响应的 body 部分,另外有一个单独的方法获取 error body。基本上就是出现一个返回码,然后调用相对应的函数的。只有当响应成功以后,我们会去做反序列化操作,然后将反序列化的结果放到 body 回调中去。如果出现了返回了网络成功响应(返回码:200)却最终返回 false 的情况,我们实际上是无法判断返回到底是什么的,只能将 ResponseBody(简单封装的了 content-type,length,以及 raw body部分) 类型交给你去处理。