Resume pending APK install
This commit is contained in:
parent
fc1cf589a7
commit
67968654cb
@ -174,6 +174,9 @@ In the app:
|
|||||||
SHA-256, and open Android's installer.
|
SHA-256, and open Android's installer.
|
||||||
- If the same version APK was already downloaded and its SHA-256 still matches,
|
- If the same version APK was already downloaded and its SHA-256 still matches,
|
||||||
the app reuses that file instead of downloading it again.
|
the app reuses that file instead of downloading it again.
|
||||||
|
- If Android sends you to the unknown-app install permission screen, return to
|
||||||
|
the app after allowing it; the app continues installing the already downloaded
|
||||||
|
APK without another update check or download.
|
||||||
- Open `More` -> `Open APK download` to download the current public APK in a
|
- Open `More` -> `Open APK download` to download the current public APK in a
|
||||||
browser.
|
browser.
|
||||||
- Open the `Update` page or `More` -> `Permissions / update status` to see the
|
- Open the `Update` page or `More` -> `Permissions / update status` to see the
|
||||||
|
|||||||
@ -2019,6 +2019,14 @@ public final class MainActivity extends Activity {
|
|||||||
super.onBackPressed();
|
super.onBackPressed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
if (updateManager != null) {
|
||||||
|
updateManager.resumePendingInstall();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDestroy() {
|
protected void onDestroy() {
|
||||||
closeTerminalSocket();
|
closeTerminalSocket();
|
||||||
|
|||||||
@ -25,6 +25,8 @@ import java.util.concurrent.ExecutorService;
|
|||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
final class UpdateManager {
|
final class UpdateManager {
|
||||||
|
private static final String PREF_PENDING_INSTALL_APK = "pending_install_apk";
|
||||||
|
|
||||||
interface Callback {
|
interface Callback {
|
||||||
void onChecking(boolean checking);
|
void onChecking(boolean checking);
|
||||||
void onMessage(String message);
|
void onMessage(String message);
|
||||||
@ -34,8 +36,9 @@ final class UpdateManager {
|
|||||||
private final SharedPreferences prefs;
|
private final SharedPreferences prefs;
|
||||||
private final Callback callback;
|
private final Callback callback;
|
||||||
private final ExecutorService executor = Executors.newSingleThreadExecutor();
|
private final ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||||
private boolean checkInProgress;
|
private volatile boolean checkInProgress;
|
||||||
private boolean downloadInProgress;
|
private volatile boolean downloadInProgress;
|
||||||
|
private File pendingInstallApk;
|
||||||
|
|
||||||
UpdateManager(Activity activity, SharedPreferences prefs, Callback callback) {
|
UpdateManager(Activity activity, SharedPreferences prefs, Callback callback) {
|
||||||
this.activity = activity;
|
this.activity = activity;
|
||||||
@ -226,15 +229,19 @@ final class UpdateManager {
|
|||||||
private void installApk(File apk) {
|
private void installApk(File apk) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
|
||||||
&& !activity.getPackageManager().canRequestPackageInstalls()) {
|
&& !activity.getPackageManager().canRequestPackageInstalls()) {
|
||||||
|
pendingInstallApk = apk;
|
||||||
|
prefs.edit().putString(PREF_PENDING_INSTALL_APK, apk.getAbsolutePath()).apply();
|
||||||
Intent settingsIntent = new Intent(
|
Intent settingsIntent = new Intent(
|
||||||
Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES,
|
Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES,
|
||||||
Uri.parse("package:" + activity.getPackageName())
|
Uri.parse("package:" + activity.getPackageName())
|
||||||
);
|
);
|
||||||
activity.startActivity(settingsIntent);
|
activity.startActivity(settingsIntent);
|
||||||
Toast.makeText(activity, "Allow installs, then run update again", Toast.LENGTH_LONG).show();
|
Toast.makeText(activity, "Allow installs, then return to continue", Toast.LENGTH_LONG).show();
|
||||||
postMessage("Install permission required");
|
postMessage("Install permission required");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
pendingInstallApk = null;
|
||||||
|
prefs.edit().remove(PREF_PENDING_INSTALL_APK).apply();
|
||||||
|
|
||||||
Uri apkUri = UpdateFileProvider.getUriForFile(
|
Uri apkUri = UpdateFileProvider.getUriForFile(
|
||||||
activity,
|
activity,
|
||||||
@ -253,6 +260,32 @@ final class UpdateManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void resumePendingInstall() {
|
||||||
|
File apk = pendingInstallApk;
|
||||||
|
if (apk == null) {
|
||||||
|
String path = prefs.getString(PREF_PENDING_INSTALL_APK, "");
|
||||||
|
if (path != null && !path.isEmpty()) {
|
||||||
|
apk = new File(path);
|
||||||
|
pendingInstallApk = apk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (apk == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!apk.exists() || apk.length() <= 0) {
|
||||||
|
pendingInstallApk = null;
|
||||||
|
prefs.edit().remove(PREF_PENDING_INSTALL_APK).apply();
|
||||||
|
postMessage("Downloaded APK is no longer available");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
|
||||||
|
&& !activity.getPackageManager().canRequestPackageInstalls()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
postMessage("Continuing APK install...");
|
||||||
|
installApk(apk);
|
||||||
|
}
|
||||||
|
|
||||||
private static byte[] readAllBytes(InputStream input) throws Exception {
|
private static byte[] readAllBytes(InputStream input) throws Exception {
|
||||||
java.io.ByteArrayOutputStream output = new java.io.ByteArrayOutputStream();
|
java.io.ByteArrayOutputStream output = new java.io.ByteArrayOutputStream();
|
||||||
byte[] buffer = new byte[16 * 1024];
|
byte[] buffer = new byte[16 * 1024];
|
||||||
|
|||||||
@ -106,7 +106,9 @@ provider checks.
|
|||||||
Downloaded APKs are cached by `versionCode`. If a cached APK exists and its
|
Downloaded APKs are cached by `versionCode`. If a cached APK exists and its
|
||||||
SHA-256 matches the manifest, the app reuses it instead of downloading the same
|
SHA-256 matches the manifest, the app reuses it instead of downloading the same
|
||||||
version again. This matters when Android redirects the user to unknown-app
|
version again. This matters when Android redirects the user to unknown-app
|
||||||
install settings before the installer can run.
|
install settings before the installer can run. After the user grants that
|
||||||
|
permission and returns to the app, the app resumes installation of the pending
|
||||||
|
APK instead of asking the user to run update again.
|
||||||
|
|
||||||
Only `v*` tags publish GitHub Releases. Main branch builds are for CI artifacts
|
Only `v*` tags publish GitHub Releases. Main branch builds are for CI artifacts
|
||||||
and should be used to validate grouped changes. Do not publish a new tag for
|
and should be used to validate grouped changes. Do not publish a new tag for
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user