zoukankan      html  css  js  c++  java
  • Qt for Android (二) Qt打开android的相册

    以下有一个可以用的Demo

    https://files.cnblogs.com/files/wzxNote/Qt-Android-Gallery-master.zip

    网盘地址:

    https://pan.baidu.com/s/1DY7N50NcVSLanBeFw0WhvQ&shfl=sharepset

    提取码:

    ccy5

    例子中的widgets程序可以直接跑起来,但是移植到自己的工程之后总是出现问题,提示找不到调用的class。

    总的来说,Qt调用Android的原生相册需要三个步骤:

    • 编写操作相册的类,这里使用到QAndroidJniObject类的静态方法
    #include <QFile>
    #include <QDebug>
    #include <QtAndroidExtras>
    #include "androidgallery.h"
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    QString selectedFileName;
    
    JNIEXPORT void JNICALL
    Java_com_amin_QtAndroidGallery_QtAndroidGallery_fileSelected(JNIEnv */*env*/,
                                                                 jobject /*obj*/,
                                                                 jstring results)
    {
        selectedFileName = QAndroidJniObject(results).toString();
         qDebug() << "============5============";
    }
    
    #ifdef __cplusplus
    }
    #endif
    
    AndroidGallery::AndroidGallery(QObject *parent) : QObject(parent)
    {
    
    }
    
    QString AndroidGallery::openGalley()
    {
        selectedFileName = "#";
        QAndroidJniObject::callStaticMethod<void>("com/amin/QtAndroidGallery/QtAndroidGallery",
                                                  "openAnImage",
                                                  "()V");
    
        while(selectedFileName == "#")
              qApp->processEvents();
    
        qDebug()<<"file name:"<<selectedFileName;
        if(QFile(selectedFileName).exists())
        {
            return  selectedFileName;
        }
    }
    com/amin/QtAndroidGallery/QtAndroidGallery

    这个是“openAnImage"方法所在的java包。运行的时候我就总是碰到说找不到这个包的错误提示,搞了一两天还没弄明白;

     原因:QAndroidJniObject::callStaticMethod<void>("org/qtproject/example/OpenAndroidAlbum/OpenAndroidAlbum",
                                                  "openAnImage",
    "()V");
    这个地方的路径没有写完整,前面的OpenAndroidAlbum表示文件夹,后面的OpenAndroidAlbum表示java文件,只不过省略的.java后缀。我开始只写了一个,粗心大意
    • 编写java文件
    // http://www.amin-ahmadi.com
    
    package com.amin.QtAndroidGallery;
    
    import org.qtproject.qt5.android.bindings.QtApplication;
    import org.qtproject.qt5.android.bindings.QtActivity;
    
    import android.content.Context;
    import android.content.Intent;
    import android.database.Cursor;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.net.Uri;
    import android.os.Bundle;
    import android.os.Environment;
    import android.provider.MediaStore;
    import android.util.Log;
    import android.os.Build;
    import android.os.Build.VERSION;
    
    import java.io.File;
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    import android.provider.DocumentsContract;
    import     android.content.ContentUris;
    
    public class QtAndroidGallery extends QtActivity
    {
    
        public static native void fileSelected(String fileName);
    
        static final int REQUEST_OPEN_IMAGE = 1;
    
        private static QtAndroidGallery m_instance;
    
        public QtAndroidGallery()
        {
            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)
        {
           if (resultCode == RESULT_OK)
            {
                if(requestCode == REQUEST_OPEN_IMAGE)
                {
                //    String filePath = getRealPathFromURI(getApplicationContext(), data.getData());
                     String filePath = getPath(getApplicationContext(), data.getData());
    //                System.out.println("debug 123456789");
    //                System.out.println(filePath);
                    fileSelected(filePath);
                }
            }
            else
            {
                fileSelected(":(");
            }
    
            super.onActivityResult(requestCode, resultCode, data);
        }
    
        private void dispatchOpenGallery()
        {
            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            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();
                return cursor.getString(column_index);
            }
            finally
            {
                if (cursor != null)
                {
                    cursor.close();
                }
            }
        }
    
    
    
    /**
         * Get a file path from a Uri. This will get the the path for Storage Access
         * Framework Documents, as well as the _data field for the MediaStore and
         * other file-based ContentProviders.
         *
         * @param context The context.
         * @param uri The Uri to query.
         * @author paulburke
         */
        public static String getPath(final Context context, final Uri uri) {
    
            final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
    
            // DocumentProvider
            if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
                // ExternalStorageProvider
                if (isExternalStorageDocument(uri)) {
                    final String docId = DocumentsContract.getDocumentId(uri);
                    final String[] split = docId.split(":");
                    final String type = split[0];
    
                    if ("primary".equalsIgnoreCase(type)) {
                        return Environment.getExternalStorageDirectory() + "/" + split[1];
                    }
    
                    // TODO handle non-primary volumes
                }
                // DownloadsProvider
                else if (isDownloadsDocument(uri)) {
    
                    final String id = DocumentsContract.getDocumentId(uri);
                    final Uri contentUri = ContentUris.withAppendedId(
                            Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
    
                    return getDataColumn(context, contentUri, null, null);
                }
                // MediaProvider
                else if (isMediaDocument(uri)) {
                    final String docId = DocumentsContract.getDocumentId(uri);
                    final String[] split = docId.split(":");
                    final String type = split[0];
    
                    Uri contentUri = null;
                    if ("image".equals(type)) {
                        contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                    } else if ("video".equals(type)) {
                        contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                    } else if ("audio".equals(type)) {
                        contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                    }
    
                    final String selection = "_id=?";
                    final String[] selectionArgs = new String[] {
                            split[1]
                    };
    
                    return getDataColumn(context, contentUri, selection, selectionArgs);
                }
            }
            // MediaStore (and general)
            else if ("content".equalsIgnoreCase(uri.getScheme())) {
                return getDataColumn(context, uri, null, null);
            }
            // File
            else if ("file".equalsIgnoreCase(uri.getScheme())) {
                return uri.getPath();
            }
    
            return null;
        }
    
        /**
         * Get the value of the data column for this Uri. This is useful for
         * MediaStore Uris, and other file-based ContentProviders.
         *
         * @param context The context.
         * @param uri The Uri to query.
         * @param selection (Optional) Filter used in the query.
         * @param selectionArgs (Optional) Selection arguments used in the query.
         * @return The value of the _data column, which is typically a file path.
         */
        public static String getDataColumn(Context context, Uri uri, String selection,
                String[] selectionArgs) {
    
            Cursor cursor = null;
            final String column = "_data";
            final String[] projection = {
                    column
            };
    
            try {
                cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                        null);
                if (cursor != null && cursor.moveToFirst()) {
                    final int column_index = cursor.getColumnIndexOrThrow(column);
                    return cursor.getString(column_index);
                }
            } finally {
                if (cursor != null)
                    cursor.close();
            }
            return null;
        }
    
    
        /**
         * @param uri The Uri to check.
         * @return Whether the Uri authority is ExternalStorageProvider.
         */
        public static boolean isExternalStorageDocument(Uri uri) {
            return "com.android.externalstorage.documents".equals(uri.getAuthority());
        }
    
        /**
         * @param uri The Uri to check.
         * @return Whether the Uri authority is DownloadsProvider.
         */
        public static boolean isDownloadsDocument(Uri uri) {
            return "com.android.providers.downloads.documents".equals(uri.getAuthority());
        }
    
        /**
         * @param uri The Uri to check.
         * @return Whether the Uri authority is MediaProvider.
         */
        public static boolean isMediaDocument(Uri uri) {
            return "com.android.providers.media.documents".equals(uri.getAuthority());
        }
    
    }

    点击open按钮调用的就是

    static void openAnImage()
    {
        m_instance.dispatchOpenGallery();
    }

    这个方法

    • AndroidManifest.xml的编写

    关于AndroidManifest.xml文件的作用介绍在

    https://www.jianshu.com/p/3b5b89d4e154 这篇博客里面有详细的介绍。简单来讲就是这个文件里面配置了一些jar包路径,资源路径,packageName,屏幕方向,是否全屏等Android程序加载需要的各种配置属性。现在怀疑问题就出在这个文件里。

    项目的目录结构如下:

    终于找到解决办法,崩溃的原因是android 6.0之后

        protected void onActivityResult(int requestCode, int resultCode, Intent data)
        {
    
         /**用于打开READ_EXTERNAL_STORAGE权限**/
            if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
    
                // Should we show an explanation?
                if (shouldShowRequestPermissionRationale(
                        Manifest.permission.READ_EXTERNAL_STORAGE)) {
                    // Explain to the user why we need to read the contacts
                }
    
                requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                    9);
    
                // MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE is an
                // app-defined int constant that should be quite unique
    
                return;
            }
         /**用于打开READ_EXTERNAL_STORAGE权限**/

    ...
    }

    在回调函数中添加上面所示代码块。用来动态添加”存储权限“

  • 相关阅读:
    C#多线程之旅(1)——介绍和基本概念
    C#多线程之旅(3)——线程池
    C# 插入或删除word分页符
    JavaScript里的类和继承
    CSS学习笔记——定位position属性的学习
    从零开始搭建架构实施Android项目
    ES5新特性:理解 Array 中增强的 9 个 API
    JQuery datepicker 用法
    客户端验证的极品--jQuery.validator
    兼容iefirefoxchrome的cursor
  • 原文地址:https://www.cnblogs.com/wzxNote/p/11693822.html
Copyright © 2011-2022 走看看