Qt5.13 on android alternative to Qcameraviewfinder
-
hi,
I testing the sample from QTCreator Called "Camera Example" on android, but when i deploy to my android phone I get no preview image of the camera, some how the QcameraViewfinder is not compatible with android,
there is some alternative to solve this?Thanks
-
@dedetuga said in Qt5.13 on android alternative to Qcameraviewfinder:
there is some alternative to solve this?
More recent Qt version maybe?
-
-
@dedetuga said in Qt5.13 on android alternative to Qcameraviewfinder:
It works in QML but I don't know programe in QML and my project is in c++ (QTWidgets),
I'm trying to use the Java native alternative but I don't know much of JNI and I'm stuck. Googling quite a lot didn't help much yet. It throw an exception just after on cursor
Probably it is already on uri.
i.e.:QAndroidJniObject uri = data.callObjectMethod("getData", "()Landroid/net/Uri;")
Because logging statement __DV(uri.isValid()); already prints false:
D myapp: CImageCaptureAndroid::shootPicture D myapp: CImageCaptureAndroid::handleActivityResult D myapp: data.isValid() = > true < D myapp: data.toString() = > Intent { act=inline-data (has extras) } < D myapp: uri.isValid() = > false < /// <== Already wrong here D myapp: uri.toString() = > < /// <== thus, meaningless D myapp: data_android.isValid() = > true < D myapp: data_android.toString() = > _data < D myapp: object_data_android = > 0x95 < D myapp: contentResolver.isValid() = > true < D myapp: contentResolver.toString() = > android.app.ContextImpl$ApplicationContentResolver@b813db1 < D myapp: cursor.isValid() = > false < /// <== Wrong here too D myapp: cursor.toString() = > < /// <== Meaningless too D myapp: In If9 F mple.myapp: java_vm_ext.cc:561] JNI DETECTED ERROR IN APPLICATION: JNI GetMethodID called with pending exception java.lang.NullPointerException: uri F mple.myapp: java_vm_ext.cc:561] at java.lang.Object com.android.internal.util.Preconditions.checkNotNull(java.lang.Object, java.lang.Object) (Preconditions.java:128)
My current header file is:
#pragma once #include <QObject> #include <QtAndroidExtras/QAndroidActivityResultReceiver> #include <QtAndroidExtras/QtAndroid> #include <QtAndroidExtras/QAndroidJniEnvironment> #include <QtAndroidExtras/QAndroidJniObject> #include <QDebug> class CImageCaptureAndroid : public QObject, public QAndroidActivityResultReceiver { Q_OBJECT public: CImageCaptureAndroid(); void shootPicture(); void handleActivityResult(int receiverRequestCode, int resultCode, const QAndroidJniObject & data) override; signals: void picturePath(QString); };
And then the source file:
#include "cimagecaptureandroid.h" #include "qt_utils.h" #include <QFile> #include <QDir> #include <QStandardPaths> CImageCaptureAndroid::CImageCaptureAndroid() { } void CImageCaptureAndroid::shootPicture() { __DL("CImageCaptureAndroid::shootPicture"); QAndroidJniObject ACTION_CAPTURE = QAndroidJniObject::fromString("android.provider.MediaStore.ACTION_IMAGE_CAPTURE"); QAndroidJniObject ACTION_IMAGE_CAPTURE = QAndroidJniObject::getStaticObjectField("android/provider/MediaStore", "ACTION_IMAGE_CAPTURE", "Ljava/lang/String;"); QAndroidJniObject intent("android/content/Intent", "(Ljava/lang/String;)V", ACTION_IMAGE_CAPTURE.object<jstring>()); if (ACTION_CAPTURE.isValid() && intent.isValid()) { QtAndroid::startActivity(intent.object<jobject>(), 101, this); } else { assert( false ); } } void CImageCaptureAndroid::handleActivityResult(int receiverRequestCode, int resultCode, const QAndroidJniObject &data) { __DL("CImageCaptureAndroid::handleActivityResult"); __DV(data.isValid()); __DV(data.toString()); jint RESULT_OK = QAndroidJniObject::getStaticField<jint>("android/app/Activity", "RESULT_OK"); if (receiverRequestCode == 101 && resultCode == RESULT_OK) { QAndroidJniObject uri = data.callObjectMethod("getData", "()Landroid/net/Uri;"); __DV(uri.isValid()); __DV(uri.toString()); QAndroidJniObject data_android = QAndroidJniObject::getStaticObjectField("android/provider/MediaStore$MediaColumns", "DATA", "Ljava/lang/String;"); __DV(data_android.isValid()); __DV(data_android.toString()); QAndroidJniEnvironment env; jobjectArray object = (jobjectArray)env->NewObjectArray(1, env->FindClass("java/lang/String"), NULL); jobject object_data_android = env->NewStringUTF(data_android.toString().toStdString().c_str()); __DV(object_data_android); env->SetObjectArrayElement(object, 0, object_data_android); QAndroidJniObject contentResolver = QtAndroid::androidActivity().callObjectMethod("getContentResolver", "()Landroid/content/ContentResolver;"); __DV(contentResolver.isValid()); __DV(contentResolver.toString()); QAndroidJniObject cursor = contentResolver.callObjectMethod("query", "(Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;", uri.object<jobject>(), object, NULL, NULL, NULL); __DV(cursor.isValid()); __DV(cursor.toString()); __DL("In If9"); jint columnIndex = cursor.callMethod<jint>("getColumnIndex", "(Ljava/lang/String;)I", data_android.object<jstring>()); __DL("In If10"); cursor.callMethod<jboolean>("moveToFirst", "()Z"); __DL("In If11"); QAndroidJniObject result = cursor.callObjectMethod("getString", "(I)Ljava/lang/String;", columnIndex); __DL("In If12"); QFile imageFile(result.toString()); QDir dir; if(dir.exists("images")){ __DL("Folder already exists"); }else { dir.mkdir("images"); } QStringList splitedImagePath = result.toString().split("/"); QString imageName = splitedImagePath.value(splitedImagePath.length() - 1); QString dataimgFile = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/images/" + imageName; // /data/data/org.qtproject.feather/files/images/offLight_Button.png if (imageFile.exists()) { QFile cdbfile(dataimgFile); if (!cdbfile.exists()) { if(!imageFile.copy(dataimgFile)) __DL("Error :copy failed"); QFile::setPermissions(dataimgFile, QFile::WriteOwner | QFile::ReadOwner); } else { __DL("image exits already no need to copy"); QFile::setPermissions(dataimgFile, QFile::WriteOwner | QFile::ReadOwner); } } else { __mDV("img Not exit in Assert ", dataimgFile); } QString imagePath = "file://" + dataimgFile; // this->deleteLater(); emit picturePath(imagePath); } }