Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. Save Image to Android device
QtWS25 Last Chance

Save Image to Android device

Scheduled Pinned Locked Moved Solved Mobile and Embedded
androidqurlimagesaveqt 5.7
24 Posts 5 Posters 14.4k Views
  • 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.
  • eirihamE Offline
    eirihamE Offline
    eiriham
    wrote on last edited by
    #14

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

    1 Reply Last reply
    0
    • M Offline
      M Offline
      mvuori
      wrote on last edited by
      #15

      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
      0
      • eirihamE Offline
        eirihamE Offline
        eiriham
        wrote on last edited by
        #16

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

        1 Reply Last reply
        0
        • QojoteQ Offline
          QojoteQ Offline
          Qojote
          wrote on last edited by
          #17

          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
          1
          • eirihamE Offline
            eirihamE Offline
            eiriham
            wrote on last edited by eiriham
            #18

            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
            0
            • eirihamE 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 Offline
              D Offline
              Devopia53
              wrote on last edited by
              #19

              @eiriham

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

              1 Reply Last reply
              0
              • QojoteQ Offline
                QojoteQ Offline
                Qojote
                wrote on last edited by Qojote
                #20

                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
                3
                • eirihamE Offline
                  eirihamE Offline
                  eiriham
                  wrote on last edited by eiriham
                  #21

                  Thanks! While following your steps I get an error. In the application output it says; "Unable to start "pdapp.mediascanner"."

                  Using logcat I get:

                  I/ActivityManager(  712): START u0 {flg=0x10000000 cmp=pdapp.mediascanner/.MediaScanner} from uid 2000 on display 0
                  W/ActivityManager(  712): Permission Denial: starting Intent { flg=0x10000000 cmp=pdapp.mediascanner/.MediaScanner } from null (pid=21117, uid=2000) not exported from uid 10104
                  I/art     (21117): System.exit called, status: 1
                  I/AndroidRuntime(21117): VM exiting with result code 1.
                  
                  

                  And also this:

                  W/PackageManager( 1369): Failure retrieving resources for pdapp.mediascanner: Resource ID #0x0
                  
                  

                  I followed your steps to the point.

                  1 Reply Last reply
                  1
                  • QojoteQ Offline
                    QojoteQ Offline
                    Qojote
                    wrote on last edited by
                    #22

                    Please make sure that you set the permissions to read and write external storage. Furthermore check consitent naming of your package and class names.
                    Which android version ar you targeting? Do you have installed the android sdk?

                    1 Reply Last reply
                    0
                    • eirihamE Offline
                      eirihamE Offline
                      eiriham
                      wrote on last edited by
                      #23

                      Thanks!

                      I had forgotten permissions for reading externally.
                      Your solution works perfectly.

                      1 Reply Last reply
                      0
                      • QojoteQ 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 Offline
                        M Offline
                        mvuori
                        wrote on last edited by
                        #24

                        @Qojote Thank you and congratulations for giving all the details for solving this old and apparently common problem! Without the smallest details, this kind of things are never solved.

                        1 Reply Last reply
                        0

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved