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. Android auto update

Android auto update

Scheduled Pinned Locked Moved Unsolved Mobile and Embedded
13 Posts 5 Posters 1.7k 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.
  • KutyusK Offline
    KutyusK Offline
    Kutyus
    wrote on last edited by
    #1

    Hi!

    I want to make an automatic update solution on Android, the apk download works, but I can't start it. I found this solution for it:

    QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;");
                if (activity.isValid())
                {
                    QAndroidJniObject kindOfActivity    = QAndroidJniObject::fromString("android.intent.action.VIEW");
                    QAndroidJniObject apkFile           = QAndroidJniObject::fromString(QString("file://%1/latest.apk").arg(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation)));
                    QAndroidJniObject apkUri            = QAndroidJniObject::callStaticObjectMethod("android/net/Uri", "parse", "(Ljava/lang/String;)Landroid/net/Uri;", apkFile.object());
                    QAndroidJniObject mimetype          = QAndroidJniObject::fromString("application/vnd.android.package-archive");
    
                    QAndroidJniObject intent("android/content/Intent", "(Ljava/lang/String;)V", kindOfActivity.object());
    
                    intent = intent.callObjectMethod("setDataAndType", "(Landroid/net/Uri;Ljava/lang/String;)Landroid/content/Intent;", apkUri.object(), mimetype.object());
                    intent = intent.callObjectMethod("setFlags", "(I)Landroid/content/Intent;", FLAG_ACTIVITY_NEW_TASK);
                    activity.callMethod<void>("startActivity", "(Landroid/content/Intent;)V", intent.object());
                }
    
                QApplication::exit();
    

    But gives error message:

    JNI DETECTED ERROR IN APPLICATION: JNI GetStaticMethodID called with pending exception android.os.FileUriExposedException: file: ///storage/emulated/0/Download/latest.apk exposed beyond app through Intent.getData ()
    

    Thanks in advance for the answers.

    1 Reply Last reply
    0
    • sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by
      #2

      You need to process the URI through FileProvider. It's an awfully awkward and tedious thing, but Android requires it since version 6 IIRC.

      Basically you need to:

      1. Add file provider to res/xml/fileprovider.xml. Example contents:
      <?xml version="1.0" encoding="utf-8"?>
      <paths>
          <cache-path name="exports" path="." />
          <!--Uncomment below to share the entire application specific directory -->
          <!--<external-path name="all_dirs" path="."/>-->
      </paths>
      
      1. Register that provider in your manifest:
      <provider
          android:name="android.support.v4.content.FileProvider"
          android:authorities="your.application.domain.fileprovider"
          android:exported="false"
          android:grantUriPermissions="true">
            <meta-data
                  android:name="android.support.FILE_PROVIDER_PATHS"
                  android:resource="@xml/fileprovider" />
          </provider>
      
      1. In every place in Java you need to use the file provider to "access" that file, instead of regular File/ Intent. I don't have Qt code for this, only some Java (and written for different purpose so it might be incorrect for your case):
      import android.support.v4.content.FileProvider;
      // ...
      Uri providerUri = FileProvider.getUriForFile(
                      this,
                      "your.application.domain.fileprovider",
                      fileName);
      

      You probably need to do the opposite (get file for URI). Not sure. I wrote this ages ago and APIs in Android keep changing all the time :-(

      1. You may also need to add the v4 compat library in gradle config, I'm not sure. It could be something like this:
      dependencies {
          implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
          compile 'com.android.support:support-v4:23.+'
      }
      

      I hope this will help you at least a bit. And sorry for not being more specific, I'm not sure about any of it :D This won't be easy, good luck!

      (Z(:^

      KutyusK 2 Replies Last reply
      0
      • sierdzioS sierdzio

        You need to process the URI through FileProvider. It's an awfully awkward and tedious thing, but Android requires it since version 6 IIRC.

        Basically you need to:

        1. Add file provider to res/xml/fileprovider.xml. Example contents:
        <?xml version="1.0" encoding="utf-8"?>
        <paths>
            <cache-path name="exports" path="." />
            <!--Uncomment below to share the entire application specific directory -->
            <!--<external-path name="all_dirs" path="."/>-->
        </paths>
        
        1. Register that provider in your manifest:
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="your.application.domain.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
              <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/fileprovider" />
            </provider>
        
        1. In every place in Java you need to use the file provider to "access" that file, instead of regular File/ Intent. I don't have Qt code for this, only some Java (and written for different purpose so it might be incorrect for your case):
        import android.support.v4.content.FileProvider;
        // ...
        Uri providerUri = FileProvider.getUriForFile(
                        this,
                        "your.application.domain.fileprovider",
                        fileName);
        

        You probably need to do the opposite (get file for URI). Not sure. I wrote this ages ago and APIs in Android keep changing all the time :-(

        1. You may also need to add the v4 compat library in gradle config, I'm not sure. It could be something like this:
        dependencies {
            implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
            compile 'com.android.support:support-v4:23.+'
        }
        

        I hope this will help you at least a bit. And sorry for not being more specific, I'm not sure about any of it :D This won't be easy, good luck!

        KutyusK Offline
        KutyusK Offline
        Kutyus
        wrote on last edited by
        #3

        @sierdzio
        Thanks for the reply, it's a little complicated for me, I absolutely don't understand the java, maybe I'll try it later.

        ekkescornerE 1 Reply Last reply
        0
        • KutyusK Kutyus

          @sierdzio
          Thanks for the reply, it's a little complicated for me, I absolutely don't understand the java, maybe I'll try it later.

          ekkescornerE Offline
          ekkescornerE Offline
          ekkescorner
          Qt Champions 2016
          wrote on last edited by
          #4

          @Kutyus my share example has implemented Android FileProvider https://github.com/ekke/ekkesSHAREexample

          ekke ... Qt Champion 2016 | 2024 ... mobile business apps
          5.15 --> 6.8 https://t1p.de/ekkeChecklist
          QMake --> CMake https://t1p.de/ekkeCMakeMobileApps

          K 1 Reply Last reply
          2
          • ekkescornerE ekkescorner

            @Kutyus my share example has implemented Android FileProvider https://github.com/ekke/ekkesSHAREexample

            K Offline
            K Offline
            koahnig
            wrote on last edited by
            #5

            @ekkescorner said in Android auto update:

            @Kutyus my share example has implemented Android FileProvider https://github.com/ekke/ekkesSHAREexample

            Great example.
            Got it to work immediately with Qt5.12.7, but failure with Qt5.14.2.
            Are you interested to get a bug report? And when where?

            Vote the answer(s) that helped you to solve your issue(s)

            ekkescornerE 1 Reply Last reply
            0
            • K koahnig

              @ekkescorner said in Android auto update:

              @Kutyus my share example has implemented Android FileProvider https://github.com/ekke/ekkesSHAREexample

              Great example.
              Got it to work immediately with Qt5.12.7, but failure with Qt5.14.2.
              Are you interested to get a bug report? And when where?

              ekkescornerE Offline
              ekkescornerE Offline
              ekkescorner
              Qt Champions 2016
              wrote on last edited by
              #6

              @koahnig said in Android auto update:

              Got it to work immediately with Qt5.12.7, but failure with Qt5.14.2.
              Are you interested to get a bug report? And when where?

              please report at gihub issues https://github.com/ekke/ekkesSHAREexample/issues

              unfortunately most of my examples are 3 years or more old and last 2 years I had to develop so many mobile business apps, so I didn't found enough spare time

              the good thing: starting with Qt 5.15 I'll rework all my examples and blogs to get mobile apps ready for Qt6 / strict QML 3. will reduce work for customers next months and concentrate on 5.15 / 6.0. with some luck all of this will finally end in a book (fingers crossed)

              ekke ... Qt Champion 2016 | 2024 ... mobile business apps
              5.15 --> 6.8 https://t1p.de/ekkeChecklist
              QMake --> CMake https://t1p.de/ekkeCMakeMobileApps

              K 1 Reply Last reply
              3
              • ekkescornerE ekkescorner

                @koahnig said in Android auto update:

                Got it to work immediately with Qt5.12.7, but failure with Qt5.14.2.
                Are you interested to get a bug report? And when where?

                please report at gihub issues https://github.com/ekke/ekkesSHAREexample/issues

                unfortunately most of my examples are 3 years or more old and last 2 years I had to develop so many mobile business apps, so I didn't found enough spare time

                the good thing: starting with Qt 5.15 I'll rework all my examples and blogs to get mobile apps ready for Qt6 / strict QML 3. will reduce work for customers next months and concentrate on 5.15 / 6.0. with some luck all of this will finally end in a book (fingers crossed)

                K Offline
                K Offline
                koahnig
                wrote on last edited by
                #7

                @ekkescorner

                Thanks. Report created

                Vote the answer(s) that helped you to solve your issue(s)

                ekkescornerE 1 Reply Last reply
                0
                • K koahnig

                  @ekkescorner

                  Thanks. Report created

                  ekkescornerE Offline
                  ekkescornerE Offline
                  ekkescorner
                  Qt Champions 2016
                  wrote on last edited by
                  #8

                  @koahnig thx reporting. will test when I've done my switch from 5.13 --> 5.15

                  ekke ... Qt Champion 2016 | 2024 ... mobile business apps
                  5.15 --> 6.8 https://t1p.de/ekkeChecklist
                  QMake --> CMake https://t1p.de/ekkeCMakeMobileApps

                  1 Reply Last reply
                  1
                  • sierdzioS sierdzio

                    You need to process the URI through FileProvider. It's an awfully awkward and tedious thing, but Android requires it since version 6 IIRC.

                    Basically you need to:

                    1. Add file provider to res/xml/fileprovider.xml. Example contents:
                    <?xml version="1.0" encoding="utf-8"?>
                    <paths>
                        <cache-path name="exports" path="." />
                        <!--Uncomment below to share the entire application specific directory -->
                        <!--<external-path name="all_dirs" path="."/>-->
                    </paths>
                    
                    1. Register that provider in your manifest:
                    <provider
                        android:name="android.support.v4.content.FileProvider"
                        android:authorities="your.application.domain.fileprovider"
                        android:exported="false"
                        android:grantUriPermissions="true">
                          <meta-data
                                android:name="android.support.FILE_PROVIDER_PATHS"
                                android:resource="@xml/fileprovider" />
                        </provider>
                    
                    1. In every place in Java you need to use the file provider to "access" that file, instead of regular File/ Intent. I don't have Qt code for this, only some Java (and written for different purpose so it might be incorrect for your case):
                    import android.support.v4.content.FileProvider;
                    // ...
                    Uri providerUri = FileProvider.getUriForFile(
                                    this,
                                    "your.application.domain.fileprovider",
                                    fileName);
                    

                    You probably need to do the opposite (get file for URI). Not sure. I wrote this ages ago and APIs in Android keep changing all the time :-(

                    1. You may also need to add the v4 compat library in gradle config, I'm not sure. It could be something like this:
                    dependencies {
                        implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
                        compile 'com.android.support:support-v4:23.+'
                    }
                    

                    I hope this will help you at least a bit. And sorry for not being more specific, I'm not sure about any of it :D This won't be easy, good luck!

                    KutyusK Offline
                    KutyusK Offline
                    Kutyus
                    wrote on last edited by
                    #9

                    @sierdzio
                    Hi!
                    I made the settings, but on this line, there is always an error:

                    QAndroidJniObject uri       = QAndroidJniObject::callStaticObjectMethod("android.support.v4.content.FileProvider", "FileProvider.getUriForFile", "(Landroid/content/Context;Ljava/lang/String;Ljava.io.File;)Landroid/net/Uri;", activity.object(), authority.object(), file.object());
                    
                    
                    System.err: java.lang.NoSuchMethodError: no static method "Landroid/support/v4/content/FileProvider;.FileProvider.getUriForFile(Landroid/content/Context;Ljava/lang/String;Ljava.io.File;)Landroid/net/Uri;"
                    

                    I also tried the getUriForFile method without the FileProvider prefix, the same error anyway.

                    KroMignonK 1 Reply Last reply
                    0
                    • sierdzioS Offline
                      sierdzioS Offline
                      sierdzio
                      Moderators
                      wrote on last edited by
                      #10

                      I don't know JNI enough to answer, for me it's always a bunch of trial and error to get it to work :D

                      (Z(:^

                      1 Reply Last reply
                      0
                      • KutyusK Kutyus

                        @sierdzio
                        Hi!
                        I made the settings, but on this line, there is always an error:

                        QAndroidJniObject uri       = QAndroidJniObject::callStaticObjectMethod("android.support.v4.content.FileProvider", "FileProvider.getUriForFile", "(Landroid/content/Context;Ljava/lang/String;Ljava.io.File;)Landroid/net/Uri;", activity.object(), authority.object(), file.object());
                        
                        
                        System.err: java.lang.NoSuchMethodError: no static method "Landroid/support/v4/content/FileProvider;.FileProvider.getUriForFile(Landroid/content/Context;Ljava/lang/String;Ljava.io.File;)Landroid/net/Uri;"
                        

                        I also tried the getUriForFile method without the FileProvider prefix, the same error anyway.

                        KroMignonK Offline
                        KroMignonK Offline
                        KroMignon
                        wrote on last edited by KroMignon
                        #11

                        @Kutyus Your JNI call is not correct, you pass wrong method name!
                        It should be:

                        QAndroidJniObject uri = QAndroidJniObject::callStaticObjectMethod(
                                "android.support.v4.content.FileProvider", 
                                "getUriForFile",  // only the function name!!
                                "(Landroid/content/Context;Ljava/lang/String;Ljava.io.File;)Landroid/net/Uri;",
                                activity.object(), 
                                authority.object(), 
                                file.object());
                        
                        

                        It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                        KutyusK 1 Reply Last reply
                        0
                        • KroMignonK KroMignon

                          @Kutyus Your JNI call is not correct, you pass wrong method name!
                          It should be:

                          QAndroidJniObject uri = QAndroidJniObject::callStaticObjectMethod(
                                  "android.support.v4.content.FileProvider", 
                                  "getUriForFile",  // only the function name!!
                                  "(Landroid/content/Context;Ljava/lang/String;Ljava.io.File;)Landroid/net/Uri;",
                                  activity.object(), 
                                  authority.object(), 
                                  file.object());
                          
                          
                          KutyusK Offline
                          KutyusK Offline
                          Kutyus
                          wrote on last edited by
                          #12

                          @KroMignon said in Android auto update:
                          I tried anyway. The error in the second parameter was slashes instead of periods in the java.io.File section.
                          If I log out after the call, I get an error that there is no activity handling the intent, if I don't log out immediately, there is no error, but nothing happens. I don't know where the error might be.

                          KroMignonK 1 Reply Last reply
                          0
                          • KutyusK Kutyus

                            @KroMignon said in Android auto update:
                            I tried anyway. The error in the second parameter was slashes instead of periods in the java.io.File section.
                            If I log out after the call, I get an error that there is no activity handling the intent, if I don't log out immediately, there is no error, but nothing happens. I don't know where the error might be.

                            KroMignonK Offline
                            KroMignonK Offline
                            KroMignon
                            wrote on last edited by KroMignon
                            #13

                            @Kutyus You are right, there are many typos!

                            QAndroidJniObject uri = QAndroidJniObject::callStaticObjectMethod(
                                    "android/support/v4/content/FileProvider", 
                                    "getUriForFile",  // only the function name!!
                                    "(Landroid/content/Context;Ljava/lang/String;Ljava/io/File;)Landroid/net/Uri;",
                                    activity.object(), 
                                    authority.object(), 
                                    file.object());
                            

                            It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                            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