編輯:關於Android編程
.
jni.h文件 : 了解 JNI 需要配合 jni.h 文件, jni.h 是 Google NDK 中的一個文件, 位置是 $/android-ndk-r9d/platforms/android-19/arch-arm/usr/include/jni.h ;
JNIEnv 概念 : 是一個線程相關的結構體, 該結構體代表了 Java 在本線程的運行環境 ;
JNIEnv 與 JavaVM : 注意區分這兩個概念;
-- JavaVM : JavaVM 是 Java虛擬機在 JNI 層的代表, JNI 全局只有一個;
-- JNIEnv : JavaVM 在線程中的代表, 每個線程都有一個, JNI 中可能有很多個 JNIEnv;
JNIEnv 作用 :
-- 調用 Java 函數 : JNIEnv 代表 Java 運行環境, 可以使用 JNIEnv 調用 Java 中的代碼;
-- 操作 Java 對象 : Java 對象傳入 JNI 層就是 Jobject 對象, 需要使用 JNIEnv 來操作這個 Java 對象;
JNIEnv 創建 和 釋放 : 從 JavaVM 獲得 : 下面是 JavaVM 結構體的代碼,
-- C語言 中來源 : JNIInvokeInterface 是 C 語言環境中的 JavaVM 結構體, 調用 (*AttachCurrentThread)(JavaVM*, JNIEnv**, void*) 方法, 可以獲取 JNIEnv結構體;
-- C++ 中來源 : _JavaVM 是 C++ 中的 JavaVM 結構體, 調用 jint AttachCurrentThread(JNIEnv** p_env, void* thr_args) 方法, 可以獲取 JNIEnv 結構體;
-- C語言 中釋放 : 調用 JavaVM結構體 (JNIInvokeInterface) 中的 (*DetachCurrentThread)(JavaVM*)方法, 可以釋放本線程中的 JNIEnv;
-- C++ 中釋放 : 調用 JavaVM 結構體 (_JavaVM) 中的 jint DetachCurrentThread(){ return functions->DetachCurrentThread(this); } 方法, 即可釋放 本線程中的 JNIEnv ;
/* * JNI invocation interface. */ struct JNIInvokeInterface { void* reserved0; void* reserved1; void* reserved2; jint (*DestroyJavaVM)(JavaVM*); /* 創建 JNIEnv , 每個線程創建一個 */ jint (*AttachCurrentThread)(JavaVM*, JNIEnv**, void*); /* 釋放本線程的 JNIEnv */ jint (*DetachCurrentThread)(JavaVM*); jint (*GetEnv)(JavaVM*, void**, jint); jint (*AttachCurrentThreadAsDaemon)(JavaVM*, JNIEnv**, void*); }; /* * C++ version. */ struct _JavaVM { const struct JNIInvokeInterface* functions; #if defined(__cplusplus) jint DestroyJavaVM() { return functions->DestroyJavaVM(this); } /* 創建 JNIEnv , 每個線程創建一個 , 調用的C語言結構提中的方法, C 與 C++ 方法相同 */ jint AttachCurrentThread(JNIEnv** p_env, void* thr_args) { return functions->AttachCurrentThread(this, p_env, thr_args); } /* 釋放本線程的 JNIEnv , 調用的C語言結構提中的方法, C 與 C++ 方法相同 */ jint DetachCurrentThread() { return functions->DetachCurrentThread(this); } jint GetEnv(void** env, jint version) { return functions->GetEnv(this, env, version); } jint AttachCurrentThreadAsDaemon(JNIEnv** p_env, void* thr_args) { return functions->AttachCurrentThreadAsDaemon(this, p_env, thr_args); } #endif /*__cplusplus*/ };
線程相關 : JNIEnv 是線程相關的, 即 在 每個線程中 都有一個 JNIEnv 指針, 每個JNIEnv 都是線程專有的, 其它線程不能使用本線程中的 JNIEnv, 線程 A 不能調用 線程 B 的 JNIEnv;
JNIEnv 不能跨線程 :
-- 當前線程有效 : JNIEnv 只在當前線程有效, JNIEnv 不能在 線程之間進行傳遞, 在同一個線程中, 多次調用 JNI層方法, 傳入的 JNIEnv 是相同的;
-- 本地方法匹配多JNIEnv : 在 Java 層定義的本地方法, 可以在不同的線程調用, 因此 可以接受不同的 JNIEnv;
JNIEnv 結構 : 由上面的代碼可以得出, JNIEnv 是一個指針, 指向一個線程相關的結構, 線程相關結構指向 JNI 函數指針 數組, 這個數組中存放了大量的 JNI 函數指針, 這些指針指向了具體的 JNI 函數;
<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD48aDI+NC4gt9bO9iBKTklFbnYgz+C52LT6wus8L2gyPjxwPjxiciAvPjwvcD48cD48L3A+PHA+PHN0cm9uZz5KTklFbnYgtqjS5bXEz+C52LT6wus8L3N0cm9uZz4gOiA8L3A+PHA+PC9wPjxwcmUgY2xhc3M9"brush:java;">/* 聲明結構體, 以便在下面能夠使用 */
struct _JNIEnv;
struct _JavaVM;
/* 聲明 C 語言環境中的 JNIEnv 為 C_JNIEnv 指針, 指向 JNINativeInterface 結構體 */
typedef const struct JNINativeInterface* C_JNIEnv;
#if defined(__cplusplus)
/* C++環境下, JNIEnv 是結構體 */
typedef _JNIEnv JNIEnv;
typedef _JavaVM JavaVM;
#else
/* C語言環境下, JNIEnv是指針 */
typedef const struct JNINativeInterface* JNIEnv;
typedef const struct JNIInvokeInterface* JavaVM;
#endif
-- JNINativeInterface 結構體 : 該結構體中定義了大量的函數指針, 這些函數指針 指向 與 Java 相關的變量有關的函數, 如果是 C 語言環境中, JNIEnv 就是指向 該結構體的指針;
-- _JNIEnv 結構體 : C++ 環境中的 JNIEnv 就是該結構體, 該結構體中封裝了 一個 JNINativeInterface 結構體指針, 即 C++ 中的 JNIEnv 要比 C 語言中的要多, 並且 完全兼容 C 語言中的 JNIEnv;
-- _JavaVM 結構體 : 該結構體 是 Java 虛擬機 在 JNI 中的代表, 整個 JNI 層 只存在一個 該 虛擬機映射;
JNINativeInterface 源碼(刪減過) : 省略後的, 其中定義了 與 Java 有關的相關方法, 都是 指向對應函數的函數指針;
-- 解析 JNIEnv* : C語言環境中的 typedef const struct JNINativeInterface* JNIEnv , JNIEnv* env 等價於 JNINativeInterface** env1 (指向結構體地址的指針), 要想 根據 二級指針 env1 獲取 JNINativeInterface 結構體中定義的函數指針, 首先獲取 指向結構體的一級指針, 獲取方法是 (*env1), 因此調用其中的函數指針指向的方法要這樣 : (*env1)->FindClass(JNIEnv*, const char*);
/* * Table of interface function pointers. */ struct JNINativeInterface { void* reserved0; void* reserved1; void* reserved2; void* reserved3; jint (*GetVersion)(JNIEnv *); ... ... jobject (*NewDirectByteBuffer)(JNIEnv*, void*, jlong); void* (*GetDirectBufferAddress)(JNIEnv*, jobject); jlong (*GetDirectBufferCapacity)(JNIEnv*, jobject); /* added in JNI 1.6 */ jobjectRefType (*GetObjectRefType)(JNIEnv*, jobject); };
_JNIEnv 源碼(刪減過) : 該源碼中有一個 JNINativeInterface 結構體指針, 說明 C++ 環境的 JNIEnv 是在 C 語言環境的 JNIEnv 下擴展的;
-- 解析 JNIEnv* : 定義是這樣的 typedef _JNIEnv JNIEnv, JNIEnv* env 等價於 _JNIEnv* env1, 因此調用 _JNIEnv 中定義的函數指針指向的函數的時候, 只需要 使用 env1->FindClass(JNIEnv*, const char*) 即可;
/* * C++ object wrapper. * * This is usually overlaid on a C struct whose first element is a * JNINativeInterface*. We rely somewhat on compiler behavior. */ struct _JNIEnv { /* do not rename this; it does not seem to be entirely opaque */ const struct JNINativeInterface* functions; #if defined(__cplusplus) jint GetVersion() { return functions->GetVersion(this); } ... ... jlong GetDirectBufferCapacity(jobject buf) { return functions->GetDirectBufferCapacity(this, buf); } /* added in JNI 1.6 */ jobjectRefType GetObjectRefType(jobject obj) { return functions->GetObjectRefType(this, obj); } #endif /*__cplusplus*/ };
現在市場的Http框架很多,比如我們熟知的NoHttp、Retrofit、Volley、android-async-http等上層框架,HttpURLConnection
新建一個布局文件 my_dialog.xml 以下是strings.xml文件: demo091801 Sett
實現目標 相信大家都知道毛玻璃效果是怎樣的,也可以說是高斯模糊效果。效果圖如下: 這是一個透明,且會對背景進行高斯模糊的效果,看起來就像是毛玻璃一樣,其實不光是側滑
public class TvControlActivity extends Activity { private TvControlActivity tvCont