Qt/C++/Android - How to install an .APK file programmatically? -


i implementing own auto-updater within application. able download .apk file of newer version /download folder on sdcard, can't figure out how open/run file user presented new installation dialog.

the thing come with:

qstring downloadedapk = "/storage/emulated/0/download/latest.apk"; // not hardcoded, wrote here way simplicity qdesktopservices::openurl(qurl(downloadedapk)); 

debugger output:

d/instrumentation(26418): checkstartactivityresult  :intent { act=android.intent.action.view dat=file:///storage/emulated/0/download/latest.apk } d/instrumentation(26418): checkstartactivityresult  inent instance of inent: w/system.err(26418): android.content.activitynotfoundexception: no activity found handle intent { act=android.intent.action.view dat=file:///storage/emulated/0/download/latest.apk } w/system.err(26418):    @ android.app.instrumentation.checkstartactivityresult(instrumentation.java:1660) w/system.err(26418):    @ android.app.instrumentation.execstartactivity(instrumentation.java:1430) w/system.err(26418):    @ android.app.activity.startactivityforresult(activity.java:3532) w/system.err(26418):    @ android.app.activity.startactivityforresult(activity.java:3493) w/system.err(26418):    @ android.app.activity.startactivity(activity.java:3735) w/system.err(26418):    @ android.app.activity.startactivity(activity.java:3703) w/system.err(26418):    @ org.qtproject.qt5.android.qtnative.openurl(qtnative.java:110) w/system.err(26418):    @ dalvik.system.nativestart.run(native method) 

i have looked everywhere never found regarding opening apks qt. thing found solutoin using jni ( don't want use because it's simpler c++ , because have 0 experience whole c++/jni thing ) , not documented didn't understand how make work.

so, easiest way open downloaded apk?



edit:

i have followed tumbus's answer, because of compiling errors had make few modifications on jni code follows:

void updater::installapp(const qstring &apppackagename) {     qdebug() << "[+] app: " << apppackagename; // string ("/storage/emulated/0/download/latest.apk")     qandroidjniobject app = qandroidjniobject::fromstring(apppackagename);     qandroidjniobject::callstaticmethod<jint>("androidintentlauncher",                                        "installapp",                                        "(ljava/lang/string;)i",                                        app.object<jstring>()); } 

when run application on android device, pulls newest .apk file server, nothing happens. why? (i have not made changes on androidmanifest.xml until now).

you have make custom intent install apk. see this question details.

i'm afraid such platform-specific think must require calls platform-specific api. news qt framework has simplified wrap-up on jni , can include java class android project. therefore make own static java function called qt.

example

java class

package io.novikov.androidintentlauncher;  import org.qtproject.qt5.android.qtnative;  import java.lang.string; import java.io.file; import android.content.intent; import android.util.log; import android.net.uri; import android.content.contentvalues; import android.content.context;  public class androidintentlauncher {     protected androidintentlauncher()     {     }      public static int installapp(string apppackagename) {         if (qtnative.activity() == null)             return -1;         try {             intent intent = new intent(intent.action_view);             intent.setdataandtype(uri.fromfile(new file(apppackagename)),                                                 "application/vnd.android.package-archive");             intent.setflags(intent.flag_activity_new_task);             qtnative.activity().startactivity(intent);             return 0;         } catch (android.content.activitynotfoundexception anfe) {             return -3;         }     }  } 

notice startactivity() should called method *qtnative.activity(). have maintain special directory structures java according conventional rules. example @ makefile section below.

jni

the c++ code call method bit tricky.

const static char* my_java_class = "io/novikov/androidintentlauncher/androidintentlauncher";   static void installapp(const qstring &apppackagename) {         qandroidjniobject jstext = qandroidjniobject::fromstring(apppackagename);         qandroidjniobject::callstaticmethod<jint>(my_java_class,                                            "installapp",                                            "(ljava/lang/string;)i",                                            jstext.object<jstring>());    } 

the string literal "(ljava/lang/string;)i" signature of java method. name of java class must @ complete form "my/domain/my_app/myclass"

makefile

the last challenge include java code project properly. below corresponding fragment of .pro file.

android {     qt += androidextras     other_files += android_src/src/io/novikov/androidintentlauncher/androidintentlauncher.java     android_package_source_dir = $$pwd/android_src } 

qmake has special variable android_package_source_dir job. java sources must reside in android_package_source_dir/src/my/domain directories. don't forget add java source other_files , include androidextras qt option.


Comments

Popular posts from this blog

Delphi XE2 Indy10 udp client-server interchange using SendBuffer-ReceiveBuffer -

Qt ActiveX WMI QAxBase::dynamicCallHelper: ItemIndex(int): No such property in -

Enable autocomplete or intellisense in Atom editor for PHP -