Commit 12188c75 authored by Evan W. Patton's avatar Evan W. Patton Committed by Jeffrey Schiller

Fix error 1101 on Android versions before Nougat (#1526)

Installing a package via the QR code scanner fails on Android versions
before SDK 24. The issue is that we switched to using content: URIs,
which is required on SDK 24+, but this fails to resolve the package
installer activity on SDK < 24. This commit adds a helper method for
constructing the correct URI based on the device's SDK version.

Change-Id: Ieaec37b79d6189f75535b5a9be4d0f38b756e63a
parent df4f4e8a
// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2009-2011 Google, All Rights reserved
// Copyright 2011-2018 MIT, All rights reserved
// Copyright 2011-2019 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0
......@@ -245,7 +245,10 @@ public final class ErrorMessages {
// Phone Call Errors
public static final int ERROR_NO_CALL_PERMISSION = 3501;
// Start the next group of errors at 3600
// REPL Errors
public static final int ERROR_UNABLE_TO_INSTALL_PACKAGE = 3601;
// Start the next group of errors at 3700
// Mapping of error numbers to error message format strings.
private static final Map<Integer, String> errorMessages;
......@@ -614,6 +617,10 @@ public final class ErrorMessages {
// Phone Call errors
errorMessages.put(ERROR_NO_CALL_PERMISSION,
"You do not have permission to make phone calls.");
// REPL errors
errorMessages.put(ERROR_UNABLE_TO_INSTALL_PACKAGE,
"Unable to launch the package installer for %1$s.");
}
private ErrorMessages() {
......
// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2019 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0
package com.google.appinventor.components.runtime.util;
import android.net.Uri;
import android.os.Build;
import android.support.v4.content.FileProvider;
import android.util.Log;
import com.google.appinventor.components.runtime.Form;
import java.io.File;
public final class NougatUtil {
private static final String LOG_TAG = NougatUtil.class.getSimpleName();
private NougatUtil() {
}
public static Uri getPackageUri(Form form, File apk) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
// Use file: URI on versions of Android older the Nougat
return Uri.fromFile(apk);
} else {
// File provider used for SDK 24+ to get a content: URI
String packageName = form.$context().getPackageName();
Log.d(LOG_TAG, "packageName = " + packageName);
return FileProvider.getUriForFile(form.$context(), packageName + ".provider", apk);
}
}
}
// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2011-2018 MIT, All rights reserved
// Copyright 2011-2019 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0
// This work is licensed under a Creative Commons Attribution 3.0 Unported License.
package com.google.appinventor.components.runtime.util;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.support.v4.content.FileProvider;
......@@ -41,6 +43,7 @@ public class PackageInstaller {
AsynchUtil.runAsynchronously(new Runnable() {
@Override
public void run() {
Uri packageuri = null;
try {
URL url = new URL(inurl);
URLConnection conn = url.openConnection();
......@@ -48,7 +51,7 @@ public class PackageInstaller {
InputStream instream = new BufferedInputStream(conn.getInputStream());
File apkfile = new File(rootDir + "/package.apk");
FileOutputStream apkOut = new FileOutputStream(apkfile);
byte [] buffer = new byte[32768];
byte[] buffer = new byte[32768];
int len;
while ((len = instream.read(buffer, 0, 32768)) > 0) {
apkOut.write(buffer, 0, len);
......@@ -58,12 +61,14 @@ public class PackageInstaller {
// Call Package Manager Here
Log.d(LOG_TAG, "About to Install package from " + inurl);
Intent intent = new Intent(Intent.ACTION_VIEW);
String packageName = form.$context().getPackageName();
Log.d(LOG_TAG, "packageName = " + packageName);
Uri packageuri = FileProvider.getUriForFile(form.$context(), packageName + ".provider", new File(rootDir + "/package.apk"));
packageuri = NougatUtil.getPackageUri(form, apkfile);
intent.setDataAndType(packageuri, "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
form.startActivity(intent);
} catch (ActivityNotFoundException e) {
Log.e(LOG_TAG, "Unable to install package", e);
form.dispatchErrorOccurredEvent(form, "PackageInstaller",
ErrorMessages.ERROR_UNABLE_TO_INSTALL_PACKAGE, packageuri);
} catch (Exception e) {
Log.e(LOG_TAG, "ERROR_UNABLE_TO_GET", e);
form.dispatchErrorOccurredEvent(form, "PackageInstaller",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment