1. 程式人生 > >Qt for Android (三) 開啟Android相簿並選一個圖片進行顯示

Qt for Android (三) 開啟Android相簿並選一個圖片進行顯示

這兩天弄了一下android相簿的相關功能。還是花了挺長時間的,這裡總結一下,避免以後再踩坑。同時也在這篇文章裡面補齊一些android開發的基礎支援 ## 開啟Android相簿並選一個圖片進行顯示 **分為幾個步驟:** 1. QtCreator新建Android工程 本例使用的是arm64-v8 Android開發套件。 2. 構建工程並在構建目錄中找到AndroidManifest.xml 建立的Android工程build之後都會在**android-build**根目錄下生成一個AndroidManifest.xml檔案。這個檔案是android開發很重要個的一個檔案,是應用清單。專案中引用的java包、app的橫屏和豎屏、app的是否全屏等等很多功能都是在裡面設定的。下面有一些詳細的參考文章: [AndroidManifest.xml詳解](https://www.jianshu.com/p/3b5b89d4e154) 3. 在工程中新增AndroidManifest.xml和java檔案。 java檔案是自己建立的用來寫一些java程式碼呼叫android原生功能的相當於c++中的一個類的檔案。 java檔案可以從網上找一個來參考著寫。等會我會附上gitee的地址供大家參考。 放出java的程式碼簡單看一下吧: ```java public class OpenAndroidAlbum extends QtActivity { public static native void fileSelected(String fileName); static final int REQUEST_OPEN_IMAGE = 1; public String lastCameraFileUri; static final int REQUEST_CAPTURE_IMAGE = 2; private static OpenAndroidAlbum m_instance; public OpenAndroidAlbum() { m_instance = this; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override protected void onDestroy() { super.onDestroy(); } static void openAnImage() { m_instance.dispatchOpenGallery(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { System.out.println("===dispatchOpenGallery1==="); if (resultCode == RESULT_OK) { if(requestCode == REQUEST_OPEN_IMAGE) { String filePath = getRealPathFromURI(getApplicationContext(), data.getData()); fileSelected(filePath); } } else { // fileSelected(":("); } super.onActivityResult(requestCode, resultCode, data); } private void dispatchOpenGallery() { Intent intent = new Intent(Intent.ACTION_PICK); intent.setType("image/*"); startActivityForResult(intent, REQUEST_OPEN_IMAGE); } public String getRealPathFromURI(Context context, Uri contentUri) { Cursor cursor = null; try { String[] proj = { MediaStore.Images.Media.DATA }; cursor = context.getContentResolver().query(contentUri, proj, null, null, null); int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); System.out.println(column_index); return cursor.getString(column_index); } finally { if (cursor != null) { cursor.close(); } } } } ``` * **fileSelected**這個靜態函式是我們在c++程式碼中定義的。java和c++的混合程式設計是通過JNI來實現的, ```c++ #ifdef Q_OS_ANDROID #ifdef __cplusplus extern "C" { #endif JNIEXPORT void JNICALL Java_org_qtproject_example_OpenAndroidAlbum_OpenAndroidAlbum_fileSelected(JNIEnv */*env*/, jobject /*obj*/, jstring results) { selectedFileName = QAndroidJniObject(results).toString(); qDebug() << "fileName = " << selectedFileName; } #ifdef __cplusplus } #endif #endif ``` 名字看起來很長*Java*是固定頭部,*org_qtproject_example_OpenAndroidAlbum*這個是java包名,*OpenAndroidAlbum*是類名,最後*fileSelected*這個才是函式名。需要注意的是**由於jni函式名對映成java函式名的時候是依靠“_”來間隔包、類、方法的,如果你的函式中有“_”字元的話,jni必須能夠區分函式名中的“_”是字元還是分隔符,所以在函式名前面需要加1用於區分。** 由於JNI的函式是c函式,所以要加上`extern "C"`。這樣定義好之後的函式就可以在java中直接呼叫了,還是很方便的。 * **openAnImage**是我們定義開啟圖片按鈕的響應函式 java中定義的函式在c++中呼叫的方法是通過Qt的**QAndroidJniObject**類的一個靜態方法實現的: ```c++ QAndroidJniObject::callStaticMethod("org/qtproject/example/OpenAndroidAlbum/OpenAndroidAlbum", "openAnImage", "()V"); ``` 第一個引數是類名其實也是包名,是在java檔案中通過 `package org.qtproject.example.OpenAndroidAlbum;` 定義的。 * **dispatchOpenGallery**這個方法用來呼叫相簿 通過*Intent*物件和*startActivityForResult*實現呼叫。這裡有一個坑,`Intent intent = new Intent(Intent.ACTION_PICK);`建立物件的時候**ACTION_PICK**這個列舉要用對,4.4以後的版本好像要用這個,我也是之前怎麼都打不開相簿,改了這個列舉之後就可以了。 * **onActivityResult**在相簿中選中一張圖片之後會呼叫這個回撥 很自然就會想到我們在c++中定義的*fileSelected*函式要在這個地方呼叫了。把路徑轉換成java的String型別,呼叫`fileSelected(filePath)`就可以在Qt程式碼中處理圖片路徑了。 4. 在Qt程式碼中呼叫java的開啟相簿的方法,同時利用JNI定義一個c++的處理方法 這個我們在上一條中也提到了。這裡提一下編碼中容易出錯的地方 ```c++ QAndroidJniObject::callStaticMethod("org/qtproject/example/OpenAndroidAlbum/OpenAndroidAlbum", "openAnImage", "()V"); ``` 第一個字串代表java包,相當於一個c++的類。如果遇到編譯過程中遇到**“找不到類"**的類似錯誤提示檢查一下第一個字串,最後是以**OpenAndroidAlbum.java**包的字首結尾的,切記!!! 5. AndroidManifest.xml要做相應的修改 上面也提到了,這個檔案是清單列表可以用來指定要呼叫j的ava包 ```XML
``` 把**package=**這個包名的屬性做對應的修改。 6. 完成了上述5點之後還要修改軟體的許可權,獲取**允許開啟相簿**的許可權之後才能正常的開啟相簿圖片 gitee地址:https://gitee.com/guiguzicom/Demo/tree/master/OpenAndr