This article describes how to open default Android Gallery in Qt using a mixture of Android’ Java and Qt (C++) code. It is specially useful if you are working with images, for example if you want to open a Mat Image in OpenCV using imread function or if you are just writing some kind of image viewer program. Unfortunately Qt does not offer this (yet) by default so I thought I could share it with you.
I have made a few assumptions such as:
- You have successfully installed Qt (with Android) on your Computer
- You have an Android phone or an Emulator (Genymotion and so on) to run Qt Android projects on it.
What it does?
This example project allows you to open an image from Android Gallery and displays it on a QLabel widget. Following screenshot shows Qt Project called QtAndroidGallery that I have shared at the bottom of this post.
Note: This project (source code) can also be used as a working example of my previous post titled how to mix Android and Qt (C++) code.
How its done?
The idea simply consists of Qt (C++) and Android (Java) code interacting with each other through JNI (Java Native Interface)
Explained in detail:
Below I will explain parts and pieces of the source code that might seem confusing but if you have any questions or facing any issues regarding build or running of this project please start a discussion by commenting down below.
This function allows retrieving of selected file name (from Gallery) after the selection is completed. Note that it is essential to use the exact same pattern seen below in function names for JNI access. Your Domain name, Package name, Java Class and function name all must be separated with “_” as seen here.
JNIEXPORT void JNICALL
Java_com_amin_QtAndroidGallery_QtAndroidGallery_fileSelected(JNIEnv*/*env*/,
jobject /*obj*/,
jstring results)
{
selectedFileName = QAndroidJniObject(results).toString();
}
This part of the code is used to call an static function in the Java code. “openAnImage” is the name of Java function that takes no parameters and returns the selected file name.
QAndroidJniObject::callStaticMethod<void>("com/amin/QtAndroidGallery/QtAndroidGallery",
"openAnImage",
"()V");
I will not go into the details of Java code but something that I have seen all over the internet that people have a hard time understanding is how to call a non static function from inside a static function. Simple! 🙂 First create an instance of the same class inside itself, like this (this already exists in the example code)
private static QtAndroidGallery m_instance;
public QtAndroidGallery()
{
m_instance = this;
}
And then, inside that static function, call the non-static function using the instance of the class you created!
static void openAnImage()
{
m_instance.dispatchOpenGallery();
}
I won’t go into details of “dispatchOpenGallery” function cause that is pure Android code and you can easily use Android SDK Documentation to get more information on that.
You can download the example project source code from here. It contains all required files for running the project provided that you already have a correct Qt for Android installation.
hi Amin,
first thanks for your tutorials,
when i use your code with qt standard component (like Camera or PositionSource) the app crashed.
QT: 5.12
android jdk: 8
ndk: 16 – 17 – 18
android api: 28 – 23 – 24
That is correct MoS, the code shared here will have issues with more recent APIs. You need to do the tweaks yourself.
I use Android SDK 26.1.1 and API 19. Qt version which I use is 5.10.1. Android NDK version is 16.1.4479499. I try to build app with target API 23,24 and get the same exception.
Unfortunately the sample code I shared in this post seems to be incompatible with more recent versions of Android SDK, which is something I haven’t tried myself to be honest, but was reported a few times by fellow developers like yourself. I would suggest using lower target APIs and trying again. Especially 20 and 21 were the ones I tested with a few years back when this post was more up-to-date. Otherwise I’m afraid you need to debug the code by yourself.
But let me know if you need a thought or if you find a simpler solution.
Hello, your example working very well, but when I try to use it in other project, function return this: System.err: java.lang.NullPointerException: Attempt to invoke direct method ‘void com.amin.QtAndroidGallery.QtAndroidGallery.dispatchOpenGallery()’ on a null object reference. I don’ t have much experience to understand what is wrong and why static method retrurn this exception.
Which Android SDK and API version are you using?
Hi, I run your example and it is working very well. But I change something and my function is return like /external/images/media/78 . How to convert real path from it? like /gallery/images/Y.jpg .. Can you help me?
I don’t think I can give a correct answer unless I know exactly what you’re changing and where.
However, you should note that the path returned is not necessarily wrong.
Didn’t work it, Omid answer also not work!
in omid answer i get path like /storage/emulated/0/myfile/myimage.jpg and QFile exist is correct but QImage can’t load that.
also Omid code in Recent gallery , when I select image the App get out and show not responding messgage.
can you help me?
Unfortunately this is happening with recent Android versions since they’re updating some part of the OS and other parts become deprecated. Have you checked my most recent app which I also shared its source code? Maybe that can give you a hint?
http://amin-ahmadi.com/2017/02/10/how-to-use-cqtqmlopencv-to-write-mobile-applications/
http://amin-ahmadi.com/quick-camera-cv
Thanks for the tutorial. I need same implementation on IOS can you please help me with that.
Thanks in advance
Manu
iOS version of this code is quite irrelevant to the Android version. You need to use iOS API and Objective-C code. I’ll try to write a tutorial for that in the upcoming days.
String filePath = getRealPathFromURI(getApplicationContext(), data.getData());
System.out.println(“debug 123456789”);
System.out.println(filePath);
fileSelected(filePath);
I System.out: debug 123456789
I System.out: null
W libQtAndroidGallery.so: (null):0 ((null)): Can’t find surface 1
W libQtAndroidGallery.so: (null):0 ((null)): Can’t find surface 1
filePath is null. Dosent Work :/
Have you checked Omid’s reply above? Which version of Android are you using?
Your java code doesn’t work with recently image and some gallery apps. I change it to this code which is working fine now : http://coliru.stacked-crooked.com/a/44727e48a45d3afc
Possible. Haven’t checked it in a while. Thanks for sharing!
Thanks for your explanation. I wanna ask something more maybe you can write something about it.
I search internet how to use android studio speciality by Qt but there is nothing.
I wanna use alarm clock, backround running, connect with google api to use my program google analitics, adwords, google game play etc.
If you can explain something about these topics it will really useful for me.
Thanks.
Thanks for the suggestion. I will write a tutorial for that, soon hopefully.
I tried with Qt 5.5 on mac and Qt 5.4 on windows both with phone. Kit armeabi and armeabi v7a.
Ye i see output, and when i put System.out.println(filePath); debug is null.
One more thing. What Android Api version are you using? Try setting to a lower Api. You can change it in AndroidManifest.xml. Also try testing with a phone that has lower Api if you’re phone doesn’t. You can easily install and test this code with Genymotion. It’s free. You just need to build for x86.
The problem you’re facing sounds like it is because of some change in Api or inconsistence between the devices we are using to test. I’m not sure btw. It would be great if you can test this and let me know the results.
Hi,
I ran your example, Image gallery work but i can open an image. When i selected an image i have this error : W/libQtAndroidGallery.so(25290): (null):0 ((null)): Can’t find surface 1.
Thank you
You must have a correct Qt Android installation. What is the OpenCV version that you are using?
Can you please clarify if you are able to see Android Default Gallery showing up or not? Or does it just crash as soon as you try to open?
It doesn’t crash, when is selected an image it close gallery and nothing happend.
In onActivityResult method, getRealPathFromURI() return me null value.
Sometimes selecting an image from recent pictures in gallery causes such a problem. Did you try selecting a picture from the albums? do not use recent pictures folder
Its same…
I just double checked and it’s totally working fine. Please let me know your Qt version. And, are you testing with a phone? Emulator? or Genymotion?
Ty this:
Go to java code and change it as I have shown below. Run the code and see if you see the output.
String filePath = getRealPathFromURI(getApplicationContext(), data.getData());
// insert this line
System.out.println(“debug 123456789”);
fileSelected(filePath);