Qt Java - Get image from gallery



  • I am trying to get an image from Android gallery using Qt. I have already called the intent from Java using a Java file, but I don't know how to return it to Qt.

    I have a Qt class that calls a method from a Java file that opens the Android Image Picker. How can I return the selected image or the selected URI to Qt?

    the .h file

    #ifndef CAMINHOIMAGENS_H
    #define CAMINHOIMAGENS_H
    
    #include <QObject>
    
    #include <QDebug>
    
    class caminhoImagens : public QObject
    {
        Q_OBJECT
    
        Q_PROPERTY(QString imagemCaminho READ imagemCaminho NOTIFY imagemCaminhoChanged)
    
    slots:
        void atualizaImagem();
    
    public:
        QString imagemCaminho();
    
    private:
        QString m_imagemCaminho = "";
    
    signals:
        void imagemCaminhoChanged();
    };
    
    #endif // CAMINHOIMAGENS_H
    

    The .cpp file

    #include "caminhoimagens.h"
    
    #include <QtAndroidExtras>
    
    caminhoImagens::caminhoImagens()
    {
        
    }
    
    void caminhoImagens::atualizaImagem()
    {
        //org.qtproject.example.acessargaleriatest
        QAndroidJniObject intent = QAndroidJniObject::callStaticObjectMethod (
    "org/qtproject/example/AcessarGaleriaTest/ImagePickerAndroid",
     "imagePicker",
     "()Landroid/content/Intent;");
    
        QtAndroid::startActivity(intent, 192837465, 0);
    }
    
    QString caminhoImagens::imagemCaminho()
    {
        return m_imagemCaminho;
    }
    

    The .java file

    package org.qtproject.example.AcessarGaleriaTest;
    
    import org.qtproject.qt5.android.bindings.QtActivity;
    import android.content.Intent;
    import android.app.Activity;
    
    public class ImagePickerAndroid extends QtActivity
    {
        public static Intent imagePicker()
        {
            Intent i = new Intent(Intent.ACTION_PICK);
            i.setType( "image/*");
            return Intent.createChooser(i, "Select Image");
        }
    }


  • Hello,

    In your ImagePickerAndroid you should override the onActivityResult function. With this you get the path name.

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        if (requestCode == "YourCode") {
            if (resultCode == RESULT_OK) {
                String path;
    
                Cursor cursor = getContentResolver().query(data.getData(), null, null, null, null);
                if (cursor == null) { // Source is Dropbox or other similar local file path
                    path = data.getData().getPath();
                } else {
                    cursor.moveToFirst();
                    int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
                    path = cursor.getString(idx);
                    cursor.close();
                }
    
                MyNative. notifyExtra(path);
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }
    

    Then to send this path to Qt side, you need to create a native function like this :
    MyNative.java

    public class MyNative {
        public static native void notifyExtra(String path);
    }
    

    Then in Qt side :
    mynative.h

    #include <QtAndroidExtras/QAndroidJniObject>
    #include <QtAndroidExtras/QAndroidJniEnvironment>
    #include <QtAndroid>
    
    static void notifyExtra(JNIEnv *env, jobject thiz, jstring path) {
        Q_UNUSED(env)
        Q_UNUSED(thiz)
        // emit a signal to your listener
    }
    
    // call this function in your main.cpp
    void registerNativeMethods() {
        JNINativeMethod methods[] {
            {"notifyExtra", "(Ljava/lang/String;)V", reinterpret_cast<void *>(notifyExtra)}
        };
    
        QAndroidJniObject javaClass("path/to/your/MyNative");
        QAndroidJniEnvironment env;
        jclass objectClass = env->GetObjectClass(javaClass.object<jobject>());
        env->RegisterNatives(objectClass, methods, sizeof(methods) / sizeof(methods[0]));
        env->DeleteLocalRef(objectClass);
    }

  • Qt Champions 2016

    An alternative way is to use existing library. e.g ImagePicker from QuickAndroid project.

    quickandroid/ImagePicker.qml at master · benlau/quickandroid
    quickandroid/ImagePicker.java at master · benlau/quickandroid



  • Thanks for the help @Vi67

    I have done my code in Qt using QAndroidJniObject to write a equivalent java code.

    Register the caminhoimages.h as a QML type in the main.cpp and call the method buscaImagem()

    caminhoimagens.h

    #ifndef CAMINHOIMAGENS_H
    #define CAMINHOIMAGENS_H
    
    #include <QObject>
    
    #include "imagepickerandroid.h"
    
    #include <QDebug>
    
    class caminhoImagens : public QObject
    {
        Q_OBJECT
    
        Q_PROPERTY(QString imagemCaminho READ imagemCaminho NOTIFY imagemCaminhoChanged)
    
    public slots:
        void buscaImagem();
        void retornaImagem(QString path);
    
    public:
        caminhoImagens();
    
        QString imagemCaminho();
    
    private:
        QString m_imagemCaminho = "";
    
    signals:
        void imagemCaminhoChanged();
    };
    
    #endif //CAMINHOIMAGENS_H
    

    caminhoimagens.cpp

    #include "caminhoimagens.h"
    
    caminhoImagens::caminhoImagens()
    {
    
    }
    
    void caminhoImagens::buscaImagem()
    {
        imagePickerAndroid *imagePicker = new imagePickerAndroid();
        connect(imagePicker, SIGNAL(imagemCaminhoSignal(QString)), this, SLOT(retornaImagem(QString)));
    
        imagePicker->buscaImagem();
    }
    
    void caminhoImagens::retornaImagem(QString path)
    {
        qDebug() << path;
    
        m_imagemCaminho = path;
    
        emit imagemCaminhoChanged();
    }
    
    QString caminhoImagens::imagemCaminho()
    {
        return m_imagemCaminho;
    }
    

    imagepickerandroid.h

    #ifndef IMAGEPICKERANDROID_H
    #define IMAGEPICKERANDROID_H
    
    
    #include <QObject>
    #include <QtAndroidExtras>
    
    #include <QDebug>
    
    class imagePickerAndroid : public QObject, public QAndroidActivityResultReceiver
    {
        Q_OBJECT
    
    public:
        imagePickerAndroid();
    
        void buscaImagem();
    
        virtual void handleActivityResult(int receiverRequestCode, int resultCode, const QAndroidJniObject & data);
    
    signals:
        void imagemCaminhoSignal(QString);
    };
    
    #endif // IMAGEPICKERANDROID_H
    

    imagepickerandroid.cpp

    #include "imagepickerandroid.h"
    
    imagePickerAndroid::imagePickerAndroid()
    {
    
    }
    
    void imagePickerAndroid::buscaImagem()
    {
        QAndroidJniObject ACTION_PICK = QAndroidJniObject::fromString("android.intent.action.GET_CONTENT");
        QAndroidJniObject intent("android/content/Intent");
        if (ACTION_PICK.isValid() && intent.isValid())
        {
            intent.callObjectMethod("setAction", "(Ljava/lang/String;)Landroid/content/Intent;", ACTION_PICK.object<jstring>());
            intent.callObjectMethod("setType", "(Ljava/lang/String;)Landroid/content/Intent;", QAndroidJniObject::fromString("image/*").object<jstring>());
            QtAndroid::startActivity(intent.object<jobject>(), 101, this);
            qDebug() << "OK";
        }
        else
        {
            qDebug() << "ERRO";
        }
    }
    
    void imagePickerAndroid::handleActivityResult(int receiverRequestCode, int resultCode, const QAndroidJniObject &data)
    {
        qDebug() << "Trabalha com os dados";
    
        jint RESULT_OK = QAndroidJniObject::getStaticField<jint>("android/app/Activity", "RESULT_OK");
        if (receiverRequestCode == 101 && resultCode == RESULT_OK) {
            QString imagemCaminho = data.callObjectMethod("getData", "()Landroid/net/Uri;").callObjectMethod("getPath", "()Ljava/lang/String;").toString();
            emit imagemCaminhoSignal(imagemCaminho);
    
            qDebug() << imagemCaminho;
        }
        else
        {
            qDebug() << "Caminho errado";
        }
    }

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.