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. Manual media scan trigger via JNI MediaScannerConnection

Manual media scan trigger via JNI MediaScannerConnection

Scheduled Pinned Locked Moved Solved Mobile and Embedded
6 Posts 3 Posters 2.6k Views 1 Watching
  • 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.
  • PowerNowP Offline
    PowerNowP Offline
    PowerNow
    wrote on last edited by
    #1

    Hi,
    I'm looking for a way to manually trigger a media scan after saving an image e.g. in the folder /DCIM or /Picture. Although the images are correctly saved they are only visible for other apps (gallery, facebook,...) after a refresh via e.g. google+/fotos.

    I tried it described like here https://developer.android.com/reference/android/media/MediaScannerConnection.html
    but I only get an error.

    QAndroidJniObject jCtx("android.content.Context");
    QAndroidJniObject jCtxD = jCtx.callMethod<QAndroidJniObject>("getApplicationContext");
    QAndroidJniObject jCty("android.media.MediaScannerConnection.MediaScannerConnectionClient");
    QAndroidJniObject jMsc("android.media.MediaScannerConnection", "(Landroid.content.Context; Landroid.media.MediaScannerConnection.MediaScannerConnectionClient)V", jCtxD, jCty);
    
    Error:
    313: error: cannot pass objects of non-trivially-copyable type 'class QAndroidJniObject' through '...'
             QAndroidJniObject jMsc("android.media.MediaScannerConnection", "(Landroid.content.Context; Landroid.media.MediaScannerConnection.MediaScannerConnectionClient)V", jCtxD, jCty);
    

    Can maybe someone give me a hint what I'm doing wrong?

    I already read Save Image to Android device , but I want to use only JNI without Java.

    Thxs in andvance...

    1 Reply Last reply
    1
    • Pablo J. RoginaP Offline
      Pablo J. RoginaP Offline
      Pablo J. Rogina
      wrote on last edited by
      #2

      @PowerNow I have a media scan working on a camera application. So far I couldn't avoid the Java part, so this is C++ code in a class receiving the signal of an image already processed by the camera:

      ...
      connect(someObject, &SomeObject::imageProcessed, [this](QString fname)
          {
              QAndroidJniObject::callStaticMethod<void>("com/ path/application/MyActivity,
                  "scanFile",
                  "(Ljava/lang/String;)V",
                  QAndroidJniObject::fromString(fname).object<jstring>()
              );
          });
      

      Then on the Java side I have something like this:

      ...
      public class MyActivity extends QtActivity {
      ...
      public static void scanFile(String path) {
              MediaScannerConnection.scanFile(m_instance,
                  new String[] { path }, null,
                  new MediaScannerConnection.OnScanCompletedListener() {
                      public void onScanCompleted(String path, Uri uri) {
                          // No need to do anything on file actually scanned or not
                      }
                  }
              );
          }
      ...
      }
      

      Upvote the answer(s) that helped you solve the issue
      Use "Topic Tools" button to mark your post as Solved
      Add screenshots via postimage.org
      Don't ask support requests via chat/PM. Please use the forum so others can benefit from the solution in the future

      PowerNowP 1 Reply Last reply
      0
      • Pablo J. RoginaP Pablo J. Rogina

        @PowerNow I have a media scan working on a camera application. So far I couldn't avoid the Java part, so this is C++ code in a class receiving the signal of an image already processed by the camera:

        ...
        connect(someObject, &SomeObject::imageProcessed, [this](QString fname)
            {
                QAndroidJniObject::callStaticMethod<void>("com/ path/application/MyActivity,
                    "scanFile",
                    "(Ljava/lang/String;)V",
                    QAndroidJniObject::fromString(fname).object<jstring>()
                );
            });
        

        Then on the Java side I have something like this:

        ...
        public class MyActivity extends QtActivity {
        ...
        public static void scanFile(String path) {
                MediaScannerConnection.scanFile(m_instance,
                    new String[] { path }, null,
                    new MediaScannerConnection.OnScanCompletedListener() {
                        public void onScanCompleted(String path, Uri uri) {
                            // No need to do anything on file actually scanned or not
                        }
                    }
                );
            }
        ...
        }
        
        PowerNowP Offline
        PowerNowP Offline
        PowerNow
        wrote on last edited by PowerNow
        #3

        @Pablo-J.-Rogina Thxs Pablo for your fast response! I'm just trying your proposal but my Android/Java knowledge is moderate. Please can you explain me how you get the current application context? How is your m_instance defined?

        D Pablo J. RoginaP 2 Replies Last reply
        0
        • PowerNowP PowerNow

          @Pablo-J.-Rogina Thxs Pablo for your fast response! I'm just trying your proposal but my Android/Java knowledge is moderate. Please can you explain me how you get the current application context? How is your m_instance defined?

          D Offline
          D Offline
          Devopia53
          wrote on last edited by Devopia53
          #4

          @PowerNow

          The following example shows how to auto-register an image for the Android Image Gallery app, tested on the Android kitcat.

          First, append permission:
          android.permission.READ_EXTERNAL_STORAGE
          android.permission.WRITE_EXTERNAL_STORAGE

          Java Code:

          android.content.Context.sendBroadcast(Intent intent)
          

          To conversion C++/JNI

          auto    imagePath = QString(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + "/myImage.jpeg");
          QAndroidJniEnvironment  env;
          QAndroidJniObject   activity = QtAndroid::androidActivity();
          QAndroidJniObject   context = activity.callObjectMethod("getApplicationContext", "()Landroid/content/Context;");
          QAndroidJniObject   intent("android/content/Intent");
          QAndroidJniObject   action = QAndroidJniObject::fromString("android.intent.action.MEDIA_SCANNER_SCAN_FILE");
          QAndroidJniObject   jpath = QAndroidJniObject::fromString(QUrl::fromLocalFile(imagePath).toString());
          QAndroidJniObject   uri = QAndroidJniObject::callStaticObjectMethod("android/net/Uri", "parse", "(Ljava/lang/String;)Landroid/net/Uri;", jpath.object<jstring>());
          	
          intent = intent.callObjectMethod("setData", "(Landroid/net/Uri;)Landroid/content/Intent;", uri.object());
          intent = intent.callObjectMethod("setAction", "(Ljava/lang/String;)Landroid/content/Intent;", action.object());
          	
          context.callMethod<void>("sendBroadcast", "(Landroid/content/Intent;)V", intent.object());
          	
          if (env->ExceptionCheck()) {
              env->ExceptionDescribe();
              env->ExceptionClear();
          }
          

          (*) A validation check on all JNI objects is required.

          1 Reply Last reply
          1
          • PowerNowP PowerNow

            @Pablo-J.-Rogina Thxs Pablo for your fast response! I'm just trying your proposal but my Android/Java knowledge is moderate. Please can you explain me how you get the current application context? How is your m_instance defined?

            Pablo J. RoginaP Offline
            Pablo J. RoginaP Offline
            Pablo J. Rogina
            wrote on last edited by
            #5

            @PowerNow this is the whole Java code:

            package com.yourname.yourproject;
            
            import org.qtproject.qt5.android.bindings.QtActivity;
            import org.qtproject.qt5.android.bindings.QtApplication;
            import android.os.Bundle;
            import android.media.MediaScannerConnection;
            import android.net.Uri;
            
            public class MyActivity extends QtActivity
            {
                private static MyActivity m_instance;
            
                public MyActivity()
                {
                    m_instance = this;
                }
            
                @Override
                public void onCreate(Bundle savedInstanceState) {
                    super.onCreate(savedInstanceState);
                }
            
                @Override
                protected void onDestroy() {
                    super.onDestroy();
                }
            
                public static void scanFile(String path) {
                    MediaScannerConnection.scanFile(m_instance,
                        new String[] { path }, null,
                        new MediaScannerConnection.OnScanCompletedListener() {
                            public void onScanCompleted(String path, Uri uri) {
                                // No need to do anything on file actually scanned or not
                            }
                        }
                    );
                }
            }
            

            Upvote the answer(s) that helped you solve the issue
            Use "Topic Tools" button to mark your post as Solved
            Add screenshots via postimage.org
            Don't ask support requests via chat/PM. Please use the forum so others can benefit from the solution in the future

            1 Reply Last reply
            1
            • PowerNowP Offline
              PowerNowP Offline
              PowerNow
              wrote on last edited by PowerNow
              #6

              Thxs a lot to @Pablo-J-Rogina and @Devopia53 !!!

              @Devopia53 This was exactly I was looking for...

              Afterwards only a littlebit simplified version.

              QString ImgFilePath = "/.../Image.jpg";
              
              QAndroidJniEnvironment env;
              QAndroidJniObject context = QtAndroid::androidContext();
              QAndroidJniObject intent("android/content/Intent");
              QAndroidJniObject action = QAndroidJniObject::fromString("android.intent.action.MEDIA_SCANNER_SCAN_FILE");
              QAndroidJniObject jpath = QAndroidJniObject::fromString(QUrl::fromLocalFile(ImgFilePath).toString());
              QAndroidJniObject uri = QAndroidJniObject::callStaticObjectMethod("android/net/Uri", "parse", "(Ljava/lang/String;)Landroid/net/Uri;", jpath.object<jstring>());
              
              intent = intent.callObjectMethod("setData", "(Landroid/net/Uri;)Landroid/content/Intent;", uri.object());
              intent = intent.callObjectMethod("setAction", "(Ljava/lang/String;)Landroid/content/Intent;", action.object());
              
              context.callMethod<void>("sendBroadcast", "(Landroid/content/Intent;)V", intent.object());
              
              if (env->ExceptionCheck()) {
                    env->ExceptionDescribe();
                    env->ExceptionClear();
              }
              
              1 Reply Last reply
              1

              • Login

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