Qt / C ++ / Android — Как программно установить файл .APK?

Я реализую свой собственный автообновление в моем приложении. Я смог успешно загрузить файл .apk новой версии в /Скачать папку на SDCard, но я не могу понять, как открыть / запустить этот файл, чтобы пользователь получил в новом диалоговом окне установки.

Единственное, что я мог придумать:

QString downloadedAPK = "/storage/emulated/0/Download/latest.apk"; // Not hardcoded, but wrote it here this way for simplicity
QDesktopServices::openUrl(QUrl(downloadedAPK));

Вывод отладчика:

D/Instrumentation(26418): checkStartActivityResult  :Intent { act=android.intent.action.VIEW dat=file:///storage/emulated/0/Download/latest.apk }
D/Instrumentation(26418): checkStartActivityResult  inent is instance of inent:
W/System.err(26418): android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=file:///storage/emulated/0/Download/latest.apk }
W/System.err(26418):    at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1660)
W/System.err(26418):    at android.app.Instrumentation.execStartActivity(Instrumentation.java:1430)
W/System.err(26418):    at android.app.Activity.startActivityForResult(Activity.java:3532)
W/System.err(26418):    at android.app.Activity.startActivityForResult(Activity.java:3493)
W/System.err(26418):    at android.app.Activity.startActivity(Activity.java:3735)
W/System.err(26418):    at android.app.Activity.startActivity(Activity.java:3703)
W/System.err(26418):    at org.qtproject.qt5.android.QtNative.openURL(QtNative.java:110)
W/System.err(26418):    at dalvik.system.NativeStart.run(Native Method)

Я искал везде, но никогда не нашел ничего относительно открытия APK из Qt. Единственное, что я обнаружил, это solutoin, использующий JNI (который я не хочу использовать, потому что проще делать это с C ++, и потому что у меня нет опыта работы с C ++ / JNI), и это не было хорошо документировано, поэтому я не понял, как заставить это работать.

Итак, что было бы самым простым способом открыть скачанный APK?



Редактировать:

Я следовал Tumbusответ, но из-за некоторых ошибок компиляции мне пришлось внести несколько изменений в его код JNI следующим образом:

void Updater::InstallApp(const QString &appPackageName)
{
qDebug() << "[+] APP: " << appPackageName; // Which is the string ("/storage/emulated/0/Download/latest.apk")
QAndroidJniObject app = QAndroidJniObject::fromString(appPackageName);
QAndroidJniObject::callStaticMethod<jint>("AndroidIntentLauncher",
"installApp",
"(Ljava/lang/String;)I",
app.object<jstring>());
}

Когда я запускаю свое приложение на моем устройстве Android, оно извлекает новейший файл .apk с моего сервера, тогда ничего не происходит. Зачем? (Я не внес никаких изменений в AndroidManifest.xml до сих пор).

2

Решение

Вы должны сделать пользовательское намерение установить APK. Увидеть этот вопрос для деталей.

Боюсь, что такое платформо-ориентированное мышление должно требовать обращения к платформо-зависимому API. Хорошей новостью является то, что фреймворк Qt упрощает подведение итогов JNI, и вы можете включить класс Java в проект Android. Поэтому я бы сделал свою собственную статическую функцию Java, вызываемую из Qt.

Класс Java

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;
}
}

}

Заметить, что startActivity () должен вызываться как метод из * QtNative.activity (). Мы должны поддерживать специальные структуры каталогов для Java в соответствии с обычными правилами. Пример на Makefile раздел ниже.

JNI

Код C ++ для вызова этого метода немного сложен.

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>());
}

Строковый литерал «(Ljava / lang / String;) I» является сигнатурой метода java.
Имя класса Java должно быть в полной форме «Мой / домен / my_app / MyClass»

Makefile

Последняя задача — правильно включить Java-код в ваш проект. Ниже соответствующий фрагмент .профессионал файл.

android {
QT += androidextras
OTHER_FILES += android_src/src/io/novikov/androidintentlauncher/AndroidIntentLauncher.java
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android_src
}

QMake имеет специальную переменную ANDROID_PACKAGE_SOURCE_DIR для этой работы. Исходники Java должны находиться в ANDROID_PACKAGE_SOURCE_DIR / SRC / мой / домен каталоги.
Также не забудьте добавить исходный код Java в OTHER_FILES и включить androidextras Вариант QT.

3

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector