Android Studio NDK-獲取JavaVM

Android Studio NDK-獲取JavaVM
Android Studio NDK-獲取JavaVM

『JavaVM』指『Java虛擬機』, 壹進程『Process』壹『JavaVM』, 冚辦爛線程『Thread』共用壹『JavaVM』.

係原生代碼獲得『Java虛擬機』, 通過『JNI_OnLoad ()』函式, 載入共享庫『System.loadLibrary(“lib”);』,載入『LIB.SO』 會自動調用『JNI_OnLoad ()』. 將javaVm以全域變量儲存.

緩存JavaVM接口指針

JavaVM javaVm;
jint JNI_OnLoad (JavaVM* vm, void* reserved){

javaVm = vm;

return JNI_VERSION_1_4;

}

加入『jni.h』頭文檔聲明『Java原生接口』

#include <jni.h>

『JNI』指『Java Native Interface』『Java原生接口』,實現『JavaVM』同『Native』通信.『Java代碼』同『原生代碼』調用.

『JNIEnv』指向當前『線程局部數據』, 『線程局部數據』內含『原生函式指針列表』. 壹線程『thread』壹『JNIEnv』. 唔得跨線程『thread』傳遞彼此獨立,

事因『POSIX線程』唔屬于『JAVA』平臺, 導致『JAVA虛擬機』冇發識別『POSIX線程』,  為咗訪問『JAVA虛擬機』,『POSIX線程』線程先附係『JAVA虛擬機』再行.

  1. 將線程附著係JAVA虛擬機,獲得屬於本線程JNIEnv接口. 返回『零』成功,非『零』為錯誤碼
    if(javaVm->AttachCurrentThread(&env,NULL) == 0)
  1. 係JAVA虛擬機分離綫程.返回『零』成功,非『零』為錯誤碼
    if(javaVm->DetachCurrentThread() == 0)

 

Android Studio NDK-POSIX線程

Android Studio NDK-POSIX線程
Android Studio NDK-POSIX線程

Android_Studio_NDK_POSIX_Thread

Android Studio NDK-POSIX線程

『Android Studio NDK』生成『C/C++』線程,使用 POSIX線程簡稱『Pthreads』. 儒略歷1995年發布POSIX.1c『標准』『擴展』綫程.為線程定義『創建』『處理』API.『Micrsoft Windows』『Mac OS X』『Linux』冚辬蘭支持POSIX線程.

事因『POSIX線程』唔屬于『JAVA』平臺, 導致『JAVA虛擬機』冇發識別『POSIX線程』,  為咗訪問『JAVA虛擬機』,『POSIX線程』線程先附係『JAVA虛擬機』再行.

  1. 係『NDK』原生代碼用POSIX線程, 加入『h』頭文檔聲明『POSIX Thread APIs』, 係『Android』實現係『Bionic API』庫
#include <pthread.h> // POSIX線程
#include <jni.h>
  1. 用pthread_create()創建線程
int pthread_create(pthread_t * thread,

pthread_attr_t const * attr,

void *(* start_routine)(void *),

void * arg);

  1. 參數
參數 簡介
thread 返回新建綫程句柄
attr 指定線程屬性,傅NULL使用默認值.
start_routine 指向綫程函式地址,
args 線程函式參數
  1. 返回值
0 線程啟動
Error code 錯誤碼
  1. 線程句柄
pthread_t      threadID;
  1. 線程函式參數,要全域變量,若傳多參數要『struct』蒞封裝.
typedef struct OPENGL_TYP{

JNIEnv *env;//   JNI

AAssetManager * aassetManager;// 資源管理

EGLDisplay display ;

EGLSurface surface;// 內核渲染表層

int Width, Height;// 熒屏寬高

}OPENGL,*OPENGL_PTR;

  1. 綫程函式樣板
void * start_rountine (void * args)
  1. 游戲運行綫程實例
void * run_game(void * param){

while (run == true)    {

Update_World();// 更新

Draw_World();// 繪畫

}

}

  1. 緩存JavaVM接口指針
jint JNI_OnLoad (JavaVM* vm, void* reserved){

javaVm = vm;

return JNI_VERSION_1_4;

}

  1. 將線程附著係JAVA虛擬機,獲得屬於本線程JNIEnv接口. 返回『零』成功,非『零』為錯誤碼
    if(javaVm->AttachCurrentThread(&env,NULL) == 0)
  1. 係JAVA虛擬機分離綫程.返回『零』成功,非『零』為錯誤碼
    if(javaVm->DetachCurrentThread() == 0)
  1. 啟動線程
 if( pthread_create(&threadID,  NULL, run_game, openGL) == 0)

return true;

else

return false;

  1. 游戲運行綫程
void * run_game(void * param){

// 將線程附著係JAVA虛擬機,

if(javaVm->AttachCurrentThread(&env,NULL) != 0)

return NULL;

Init_Engine( ); // 初此引擎

Init_World( );  // 初此游戲世界

while (run == true)    {

Update_World();// 更新

Draw_World();// 繪畫

}

Shutdown_World();// 閂游戲世界

Shutdown_Engine();  // 閂引擎

// 係JAVA虛擬機分離綫程

javaVm->DetachCurrentThread();

return NULL;

}

之前係『JAVA Thread』行『ANativeWindow_fromSurface()』冇事,係『C/C++ Thread』行『ANativeWindow_fromSurface()』死機. 暈得壹陣陣.

Android Java 線程Thread()

Android Java 線程Thread()
Android Java 線程Thread()
  1. 係『Java』啟動線程
new Thread(this).start();
  1. 係『Java class』 加入『implements Runnable』愛蒞行線程代碼,
public class GameView extends SurfaceView implements   Runnable {}
  1. 運行線程代碼
@Override

public void run() {

while (true) {

//  Thread Code

}

}

 

Android Studio NDK-OpenGL ES封裝SurfaceView

Android Studio NDK-OpenGL ES封裝SurfaceView
Android Studio NDK-OpenGL ES封裝SurfaceView

係『Android OpenGL ES』用『SurfaceView』蒞畀『OpenGL ES』渲染. 之前『SurfaceView』代碼擺係『MainActivity.java』.更佳方法係『SurfaceView』『Runnable』『SurfaceHolder.Callback』封裝成單獨『GameView calss』.以保持代碼『簡潔』同埋『重用』.

  1. 新建『java』
『File->New->Java Class』
  1. 封裝『Runnable』『Callback』
public class GameView extends SurfaceView implements Runnable,SurfaceHolder.Callback{
  1. 『SurfaceView』變量
int view_width,view_height;

public SurfaceHolder surfaceHolder;

public Surface surface;//用蒞渲染

  1. 構造函數
public GameView(Context context) {

super(context);

init(context);// 設置渲染

}

public GameView(Context context, AttributeSet attrs) {

super(context);

init(context);// 設置渲染

}

public GameView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context);

init(context);// 設置渲染

}

  1. 初此渲染设置
public void init(Context context){

this.surfaceHolder = getHolder();

this.surfaceHolder.addCallback(this);

this.surface = surfaceHolder.getSurface();

}

  1. 創建表層,啟動渲染線程 run()
@Override

public void surfaceCreated(SurfaceHolder surfaceHolder){

new Thread(this).start();

}

  1. 表層改變, 當手機方向改變触發, 係游戲要禁止旋轉方向.
 @Override

public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height){

view_width = width;

view_height = height;

}

  1. 表層銷毀
@Override

public void surfaceDestroyed(SurfaceHolder surfaceHolder) {

}

  1. 游戲運算渲染線程
@Override

public void run() {

AssetManager assetManager = getContext().getAssets();

Lib.init(assetManager, surface, view_width, view_height);

while (true) {// 請求渲染

Lib.update();

}

}

 

Android Studio NDK-Java原生接口(JNI)

Android Studio NDK-Java原生接口(JNI)
Android Studio NDK-Java原生接口(JNI)

Android Java原生接口(JNI) 令 『Java』 同『C\C++』代碼相互調用. 之前係『MainActivity.java』声明『native』原生代碼接口.

static public native String stringFromJNI();

『native-lib.cpp』『C\C++』代碼, 它編譯共享庫『.so』檔

extern “C” JNIEXPORT jstring JNICALL

Java_net_bookcard_compass_MainActivity_stringFromJNI(JNIEnv* env,jobject  this) {

return env->NewStringUTF(“native-lib”) ;

}

缺點係只能『MainActivity.java』調用, 更佳方發係將原生代碼接口擺係單獨『Java Class』. 并声明為『static』, 可係任意位置調用『C\C++』代碼.

  1. 新建『Class』
『File』->『New』->『Java Class』
  1. 新『Java Class』填『java』
  2. 載入共享庫”geomanticcompass.so”
static {

System.loadLibrary(“geomanticcompass”);

}

  1. 声明『native』原生『static』代碼接口.
static public native String stringFromJNI();

 

Android LocationManager.getBestProvider()返回NULL

Android LocationManager.getBestProvider()返回NULL
Android LocationManager.getBestProvider()返回NULL

『GPS』全球定位代碼,係『eclipse』移過蒞『Android Studio』, 發現getBestProvider()返回NULL. 源於冇『權限』 , 而『Android 6』後要人手獲得授權, 冇『權限』getBestProvider()永遠返回null. 係程式啟動檢查『權限』, 若冇『權限』提出請求伸請.

string GetBestProvider (Criteria criteria, bool enabledOnly)

『GPS』定位伸請『權限』

<uses-permission android:name=”android.permission.ACCESS_FINE_LOCATION”/>
<uses-permission android:name=”android.permission.ACCESS_COARSE_LOCATION”/>

『權限』

Manifest.permission.ACCESS_FINE_LOCATION 高精度定位
Manifest.permission.ACCESS_COARSE_LOCATION 低精度定位

檢查『權限』

int coarse = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION);
int fine = ContextCompat.checkSelfPermission(context,Manifest.permission.ACCESS_FINE_LOCATION);

返回值判斷係咪獲得『權限』

PackageManager.PERMISSION_GRANTED 有『權限』
PackageManager.PERMISSION_DENIED 冇『權限』

判斷有冇『權限』

if(coarse == PackageManager.PERMISSION_DENIED || fine == PackageManager.PERMISSION_DENIED )

請求伸請. context必需係Activity

String permission[] = new String[] { Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION};
ActivityCompat.requestPermissions((Activity) context,permission,REQUEST_CODE_GPS);

GPS權限請求碼

public static int REQUEST_CODE_GPS = 156;

處理GPS授權回調, 係MainActivity判斷授權

@Override

public void onRequestPermissionsResult(int requestCode,String[] permissions,int[] grantResults){

requestCode係權限請求碼

if(requestCode == GPS.REQUEST_CODE_GPS) {// 羅盤權限請求碼

判斷『權限』係咪獲得

if(grantResults[0] == PackageManager.PERMISSION_GRANTED &&

grantResults[1] == PackageManager.PERMISSION_GRANTED) { // 獲得授權

再次定位

GPS.UpdatesLocation();

交翻畀onRequestPermissionsResult()處理

   super.onRequestPermissionsResult(requestCode,permissions,grantResults);

}

 

 

Android Studio代碼提示失效

Android Studio代碼提示失效
Android Studio代碼提示失效

編寫『Android』高效歸功於『Android Studio』代碼提示, 近排『Android Studio』冇咗提示, 令『import』冇發自動填寫,源於啟用『Power Save Mode』造成提示失效. 要啟用『代碼提示』禁用『Power Save Mode』.

『File』->『Power Save Mode』

 

Android Studio NDK-OpenGL ES 『正交投影』

Android Studio NDK-OpenGL ES 『正交投影』
Android Studio NDK-OpenGL ES 『正交投影』

3D游戲基于『透視投影』產生立體效果, 而2D游戲戲用『正交投影』產生平面效果, 生成等比例游戲.

  1. 指定視區像素尺碼, 『x』 『y』視區左下角,『width』 『height』視區寬高
glViewport(0,0,width, height);
  1. 設定『矩陣堆栈』為『投影矩陣堆栈』
glMatrixMode(GL_PROJECTION);
  1. 載入單位矩陣, 清除『堆栈』残留『矩陣』,以此唔受先前變换運算影响.
glLoadIdentity();
  1. 『正交投影』運算, Y軸視角『fovy』,Z軸視角『aspect』, 『zNear』近裁剪面距离约摸箱機方向Y軸加 『zFar』远裁剪面距离設較大数值.
gluOrtho( fovy, aspect, zNear, zFar );
  1. 設定『矩陣堆栈』為『模型視圖矩陣堆栈』
glMatrixMode(GL_MODELVIEW);
  1. 載入單位矩陣
glLoadIdentity();

 

基於視角『正交投影』

void gluOrtho(double  fovy,double aspect,double zNear,double zFar){

double  xmin, xmax, ymin, ymax;

ymax = zNear * tan(fovy * 3.141592654f / 360.0f);

ymin = -ymax;

xmin = ymin * aspect;

xmax = ymax * aspect;

glOrthof(xmin, xmax, ymin, ymax, zNear, zFar);

}

 

Android Studio折叠代碼

Android Studio折叠代碼
Android Studio折叠代碼

Android Studio冇喇喇唔得『折叠』代碼.長代碼睇到氹氹轉,按以下指令撳恢复代碼折叠.

『Code』->『Folding』-> 『Collapse Doc Comments』

 

Android Studio 展現『Structure』

Android Studio 展現『Structure』
Android Studio 展現『Structure』

係『VC6』有『struct』同『Function』检索下拉窗口,可迅速定位代碼. 令工作事半工倍.

係『Android Studio』『struct』同『Function』检索視窗默認收埋.

  1. 撳『View』->『Tool Windows』->『Structure』展現『Structure』視窗
  2. 撳『Alt+7』展現『Structure』視窗
  3. 撳『Show Options Menu』->『Move To』->『Right Top』置於右上角