Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Solved Save Image to Android device

    Mobile and Embedded
    android qurl image save qt 5.7
    5
    24
    10754
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • eiriham
      eiriham last edited by

      Hey!

      I have an app where I take a screen shot of a live video stream. The image is a QUrl. How can I save it to the gallery of the Android device?

      Cant find anywhere that says what I can do.

      Also, I have not written any code yet for saving as I cannot find any.

      Please help!

      D 1 Reply Last reply Reply Quote 0
      • D
        Devopia53 @eiriham last edited by

        @eiriham

        Hi.

        You can use a QStandardPaths.

        like this:

        QString path = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
        
        if (path.isEmpty())
            return;
        
        path.append("/yourImage.png");
        yourImage.save(path);
        
        1 Reply Last reply Reply Quote 0
        • eiriham
          eiriham last edited by eiriham

          Thanks! But I cant really get that to work. The pictures dont show in the photo album.

          This is my code:
          @
          void SnapshotController::savePicture()
          {
          QString path = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);

          if(path.isEmpty()){
              return;
          }
          path.append("/yourImage.png");
          m_img.save(path);
          

          }
          @

          The standard path gives this string: "/storage/emulated/0/Pictures"

          I am on a Nexus 7

          raven-worx 1 Reply Last reply Reply Quote 0
          • raven-worx
            raven-worx Moderators @eiriham last edited by raven-worx

            @eiriham said:

            Thanks! But I cant really get that to work. The pictures dont show in the photo album.

            Now the search begins.

            1. on Android you need to trigger the Media scanner to add it to the systems media database so other apps can access it. If it's working after a device restart, then thats the cause.

            2. you should make sure that your app has the correct permission to write to the filesystem. Change your code to the following and check the error (in console):

            QBuffer buffer;
            buffer.open(QIODevice::WriteOnly);
            img.save(&buffer, "PNG");
            buffer.close();
            
            QString path = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + "/image.png";
            QFile f( path  );
            if( file.open( QIODevice::WriteOnly ) )
            {
                file.write( buffer.buffer() );
                file.close();
            }
            if( file.error() != QFileDevice::NoError )
                 qFatal() << QString("Error writing file '%1':").arg(path) <<  file.errorString();
            

            --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
            If you have a question please use the forum so others can benefit from the solution in the future

            1 Reply Last reply Reply Quote 0
            • eiriham
              eiriham last edited by

              Thanks!
              I found my pictures after a device restart. Since it did, do I still need step 2?

              Because I get the following error:
              OpenOnly is not a member of QIODevice.

              And I have included QIODevice

              raven-worx 1 Reply Last reply Reply Quote 0
              • raven-worx
                raven-worx Moderators @eiriham last edited by

                @eiriham said:

                I found my pictures after a device restart. Since it did, do I still need step 2?

                if you want to have it in the media database immediately, then yes.
                If you can live with it being available after a device restart, then no

                Because I get the following error:
                OpenOnly is not a member of QIODevice.

                my mistake. should be "ReadOnly". (Changed it already in my code)

                --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                If you have a question please use the forum so others can benefit from the solution in the future

                1 Reply Last reply Reply Quote 0
                • eiriham
                  eiriham last edited by

                  Thanks!

                  I ran your code and got this error message:
                  "Error writing file '/storage/emulated/0/Pictures/image.png':" "No such file or directory"

                  That was not a problem earlier? What happened?

                  raven-worx 1 Reply Last reply Reply Quote 0
                  • raven-worx
                    raven-worx Moderators @eiriham last edited by

                    @eiriham
                    seems i need some sleep :P
                    Should be "WriteOnly" instead of "ReadOnly" unlike i said before...

                    --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                    If you have a question please use the forum so others can benefit from the solution in the future

                    1 Reply Last reply Reply Quote 0
                    • eiriham
                      eiriham last edited by

                      Thanks!

                      Well, I have not fixed step 1 yet, but I did exactly as in step 2. Again, the picture was showing only after a restart. What is the difference between the code in step 2 that you presented and the code I wrote in the original post?

                      They both seem to do the same thing? Or would your code work with the mediascanner, and mine wont?

                      raven-worx 1 Reply Last reply Reply Quote 0
                      • raven-worx
                        raven-worx Moderators @eiriham last edited by

                        @eiriham
                        i just added my code, so we can check the error message

                        Are you triggering the media scanner already?!

                        --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                        If you have a question please use the forum so others can benefit from the solution in the future

                        1 Reply Last reply Reply Quote 0
                        • eiriham
                          eiriham last edited by

                          No, I am not triggering it! Still trying to understand how one does that.

                          raven-worx 1 Reply Last reply Reply Quote 0
                          • raven-worx
                            raven-worx Moderators @eiriham last edited by

                            @eiriham
                            because you were wondering why it still shows up after a device restart.
                            There is no way around using the media scanner if you want to have it immediately listed in the media db.

                            --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                            If you have a question please use the forum so others can benefit from the solution in the future

                            1 Reply Last reply Reply Quote 0
                            • eiriham
                              eiriham last edited by

                              Any help would be appreciated. I am looking at this post now, but it is not solved: http://lists.qt-project.org/pipermail/interest/2015-April/016263.html.

                              Also, I saw your post about the Android Extra JNI, but how do I call the scanFile from there?

                              This is the start of the code I am trying to write:
                              @
                              void SnapshotController::trigMediaScanner(QString path)
                              {
                              QAndroidJniObject string = QAndroidJniObject::fromString(path);

                              QAndroidJniEnvironment test2;
                              

                              }
                              @

                              1 Reply Last reply Reply Quote 0
                              • eiriham
                                eiriham last edited by

                                Any help? Tried a lot of stuff, but could not make it work

                                1 Reply Last reply Reply Quote 0
                                • M
                                  mvuori last edited by

                                  This is a funny issue. People claim that calling scanFile should work, but I have seen no sign that anyone has actually managed to make it work from Qt...

                                  Yes, I am trying the same thing, but currently, on a personal app, just use Android app media.re.Scan: as needed.

                                  1 Reply Last reply Reply Quote 0
                                  • eiriham
                                    eiriham last edited by

                                    Using an app wont solve my problem, but thanks for the advice.

                                    1 Reply Last reply Reply Quote 0
                                    • Qojote
                                      Qojote last edited by

                                      I had the same issue to show a picture taken by my app immediatly after saving it. And scanFile works for me.

                                      I wrote a java class extending org.qtproject.qt5.android.bindings.QtActivity and declared it in the manifest file.

                                      public class AndroidAccess extends org.qtproject.qt5.android.bindings.QtActivity
                                      {
                                        public static MediaScannerConnection s_mMs;
                                      
                                        @Override
                                        public void onCreate(Bundle savedInstanceState)
                                        {
                                           ...
                                           s_mMs = new MediaScannerConnection(getApplicationContext(), null);
                                           s_mMs.connect();
                                        }
                                      
                                        public static void scanForPicture(String name)
                                        {
                                           s_mMs.scanFile(name, null);
                                        }
                                      }
                                      

                                      and then in my Qt class i simply call:

                                      QAndroidJniObject::callStaticMethod<void>("org/tud/qpcam/AndroidAccess",
                                                                                 "scanForPicture",
                                                                                 "(Ljava/lang/String;)V",
                                                                                 QAndroidJniObject::fromString(this->getSavePicturesDir().absolutePath()).object<jstring>());
                                      

                                      whereas getSavePicturesDir() returns the directory where the pictures were saved to.
                                      Works like charm with Qt 5.6 and android 4.4 - 6.0.

                                      1 Reply Last reply Reply Quote 1
                                      • eiriham
                                        eiriham last edited by eiriham

                                        Thanks! I am trying to get this to work now.
                                        How did you register it in the manifest file?
                                        And how do I know the path? I mean, how did you know you had to put in "org/tud/qpcam/AndroidAccess"?

                                        I try this but the isAvailable returns false:

                                        
                                            qDebug()<< "Is available: " << QAndroidJniObject::isClassAvailable("MediaScanner");
                                        
                                            QAndroidJniObject::callStaticMethod<void>("MediaScanner",
                                                                                       "scanForPicture",
                                                                                       "(Ljava/lang/String;)V",
                                                                                       QAndroidJniObject::fromString(this->getSavePicturesDir().absolutePath()).object<jstring>());
                                        
                                        D 1 Reply Last reply Reply Quote 0
                                        • D
                                          Devopia53 @eiriham last edited by

                                          @eiriham

                                          You can use the sendBroadcast(). MediaScanner is simple to implement only JNI without JAVA code.

                                          1 Reply Last reply Reply Quote 0
                                          • Qojote
                                            Qojote last edited by Qojote

                                            Well, i tried a lot of ways and sendBroadcast() did not work for me. So maybe my way isnt the shortest one, but it works and thats what matters, doesnt it?

                                            • Create the android files "create Android APK"

                                            • set the package name, e.g. "aha.androscanner" in manifest

                                            • open manifest in text mode and replace android:name="org.qtproject.qt5.android.bindings.QtActivity" with android:name="aha.androscanner.AndroScannerInJava"

                                            • Create a subdirectory below the android folder, e.g. ...android/src/aha/androscanner

                                            • Put in a java file, named exactly like in point 3, e.g. AndroScannerInJava.java and add it to project

                                            • add "android: QT += androidextras" to your .pro file

                                            • Fill in the code

                                            AndroScannerInJava.java

                                            package aha.androscanner;
                                            
                                            import android.media.MediaScannerConnection;
                                            import android.os.Bundle;
                                            
                                            public class AndroScannerInJava extends org.qtproject.qt5.android.bindings.QtActivity
                                            {
                                                public static MediaScannerConnection s_mMs;
                                            
                                                @Override
                                                public void onCreate(Bundle savedInstanceState)
                                                {
                                                    System.out.println("in the activity");
                                            
                                                    super.onCreate(savedInstanceState);
                                            
                                                    s_mMs = new MediaScannerConnection(getApplicationContext(), null);
                                                    s_mMs.connect();
                                            
                                                }
                                            
                                                public static void scanForPicture(String name)
                                                {
                                                    System.out.print("scan for picture -> ");
                                                    System.out.println(name);
                                            
                                                    s_mMs.scanFile(name, null);
                                                }
                                            }
                                            

                                            Within Qt code you call:

                                            void MainWindow::saveThatPicture()
                                            {
                                                qDebug() << "saveThatPicture!";
                                            
                                                QPixmap pix(700,700);
                                                pix.fill(Qt::red);
                                            
                                                QDir picDir = QDir(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation));
                                                QDir saveDir = QDir(picDir.filePath("aha"));
                                                if(!saveDir.exists())
                                                    picDir.mkdir("aha");
                                            
                                                QString filePath = saveDir.filePath("test.jpg");
                                                pix.save(filePath);
                                            
                                            
                                                QAndroidJniObject::callStaticMethod<void>("aha/androscanner/AndroScannerInJava",
                                                                                           "scanForPicture",
                                                                                           "(Ljava/lang/String;)V",
                                                                                           QAndroidJniObject::fromString(filePath).object<jstring>());
                                            }
                                            

                                            Manifest.xml

                                            <?xml version='1.0' encoding='utf-8'?>
                                            <manifest package="aha.androscanner" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
                                                <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --">
                                                    <activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation"
                                                              android:name="aha.androscanner.AndroScannerInJava"
                                                              android:label="-- %%INSERT_APP_NAME%% --"
                                                              android:screenOrientation="unspecified"
                                                              android:launchMode="singleTop">
                                                        <intent-filter>
                                                            <action android:name="android.intent.action.MAIN"/>
                                                            <category android:name="android.intent.category.LAUNCHER"/>
                                                        </intent-filter>
                                                        <meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
                                                        <meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
                                                        <meta-data android:name="android.app.repository" android:value="default"/>
                                                        <meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
                                                        <meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
                                                        <!-- Deploy Qt libs as part of package -->
                                                        <meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
                                                        <meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
                                                        <meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
                                                        <!-- Run with local libs -->
                                                        <meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
                                                        <meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
                                                        <meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
                                                        <meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
                                                        <meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
                                                        <!--  Messages maps -->
                                                        <meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
                                                        <meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
                                                        <meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
                                                        <!--  Messages maps -->
                                            
                                                        <!-- Splash screen -->
                                                        <!--
                                                        <meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/>
                                                        -->
                                                        <!-- Splash screen -->
                                            
                                                        <!-- Background running -->
                                                        <!-- Warning: changing this value to true may cause unexpected crashes if the
                                                                      application still try to draw after
                                                                      "applicationStateChanged(Qt::ApplicationSuspended)"
                                                                      signal is sent! -->
                                                        <meta-data android:name="android.app.background_running" android:value="false"/>
                                                        <!-- Background running -->
                                            
                                                        <!-- auto screen scale factor -->
                                                        <meta-data android:name="android.app.auto_screen_scale_factor" android:value="false"/>
                                                        <!-- auto screen scale factor -->
                                                    </activity>
                                                </application>
                                                <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="14"/>
                                                <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
                                            
                                                <!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
                                                     Remove the comment if you do not require these default permissions. -->
                                                <!-- %%INSERT_PERMISSIONS -->
                                            
                                                <!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
                                                     Remove the comment if you do not require these default features. -->
                                                <!-- %%INSERT_FEATURES -->
                                            
                                            <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
                                            <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
                                            
                                            </manifest>
                                            

                                            Works fine.

                                            M 1 Reply Last reply Reply Quote 3
                                            • First post
                                              Last post