post-install Intent to tell OsmAnd to import "installed" OBF
OsmAnd will import map files from a file:// URL pointing to an OBF file, but this currently only works for file:// and not the proper content://. This uses a hack to disable the warning about file:// URIs but only for the final stage of installing the .obf file. Hopefully in the future, this can be changed to use a proper content:// URL as I suggested to them in this merge request: https://github.com/osmandapp/OsmAnd/pull/10043
This commit is contained in:
parent
8cf267ea6c
commit
b316eab85d
@ -569,12 +569,15 @@ public class Apk extends ValueObject implements Comparable<Apk>, Parcelable {
|
|||||||
String fileExtension = MimeTypeMap.getFileExtensionFromUrl(this.getCanonicalUrl());
|
String fileExtension = MimeTypeMap.getFileExtensionFromUrl(this.getCanonicalUrl());
|
||||||
if (TextUtils.isEmpty(fileExtension)) return path;
|
if (TextUtils.isEmpty(fileExtension)) return path;
|
||||||
MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
|
MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
|
||||||
String[] mimeType = mimeTypeMap.getMimeTypeFromExtension(fileExtension).split("/");
|
String mimeType = mimeTypeMap.getMimeTypeFromExtension(fileExtension);
|
||||||
String topLevelType;
|
String topLevelType = null;
|
||||||
if (mimeType.length == 0) {
|
if (!TextUtils.isEmpty(mimeType)) {
|
||||||
|
String[] mimeTypeSections = mimeType.split("/");
|
||||||
|
if (mimeTypeSections.length == 0) {
|
||||||
topLevelType = "";
|
topLevelType = "";
|
||||||
} else {
|
} else {
|
||||||
topLevelType = mimeType[0];
|
topLevelType = mimeTypeSections[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ("audio".equals(topLevelType)) {
|
if ("audio".equals(topLevelType)) {
|
||||||
path = Environment.getExternalStoragePublicDirectory(
|
path = Environment.getExternalStoragePublicDirectory(
|
||||||
|
@ -5,8 +5,12 @@ import android.content.DialogInterface;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.StrictMode;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.ContextThemeWrapper;
|
import android.view.ContextThemeWrapper;
|
||||||
|
import android.webkit.MimeTypeMap;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
@ -21,6 +25,7 @@ import org.fdroid.fdroid.data.Apk;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
public class FileInstallerActivity extends FragmentActivity {
|
public class FileInstallerActivity extends FragmentActivity {
|
||||||
|
|
||||||
@ -161,12 +166,44 @@ public class FileInstallerActivity extends FragmentActivity {
|
|||||||
Toast.makeText(this, String.format(this.getString(R.string.app_installed_media), path.toString()),
|
Toast.makeText(this, String.format(this.getString(R.string.app_installed_media), path.toString()),
|
||||||
Toast.LENGTH_LONG).show();
|
Toast.LENGTH_LONG).show();
|
||||||
installer.sendBroadcastInstall(canonicalUri, Installer.ACTION_INSTALL_COMPLETE);
|
installer.sendBroadcastInstall(canonicalUri, Installer.ACTION_INSTALL_COMPLETE);
|
||||||
|
postInstall(path);
|
||||||
} else {
|
} else {
|
||||||
installer.sendBroadcastInstall(canonicalUri, Installer.ACTION_INSTALL_INTERRUPTED);
|
installer.sendBroadcastInstall(canonicalUri, Installer.ACTION_INSTALL_INTERRUPTED);
|
||||||
}
|
}
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run any file-type-specific processes after the file has been copied into place.
|
||||||
|
* <p>
|
||||||
|
* When this was written, OsmAnd only supported importing OBF files via a
|
||||||
|
* {@code file:///} URL, so this disables {@link android.os.FileUriExposedException}.
|
||||||
|
*/
|
||||||
|
private void postInstall(File path) {
|
||||||
|
if (path.getName().endsWith(".obf")) {
|
||||||
|
if (Build.VERSION.SDK_INT >= 24) {
|
||||||
|
try {
|
||||||
|
Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
|
||||||
|
m.invoke(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("obf");
|
||||||
|
intent.setDataAndType(Uri.fromFile(path), mimeType);
|
||||||
|
if (Build.VERSION.SDK_INT >= 23) {
|
||||||
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
|
}
|
||||||
|
if (intent.resolveActivity(getPackageManager()) != null) {
|
||||||
|
startActivity(intent);
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, "No Activity available to handle " + intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void uninstallPackage(Apk apk) {
|
private void uninstallPackage(Apk apk) {
|
||||||
if (apk.isMediaInstalled(activity.getApplicationContext())) {
|
if (apk.isMediaInstalled(activity.getApplicationContext())) {
|
||||||
File file = apk.getInstalledMediaFile(activity.getApplicationContext());
|
File file = apk.getInstalledMediaFile(activity.getApplicationContext());
|
||||||
|
@ -2,7 +2,6 @@ package org.fdroid.fdroid.data;
|
|||||||
|
|
||||||
import android.content.ContextWrapper;
|
import android.content.ContextWrapper;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.util.Log;
|
|
||||||
import android.webkit.MimeTypeMap;
|
import android.webkit.MimeTypeMap;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
@ -58,6 +57,16 @@ public class ApkTest {
|
|||||||
assertEquals(new File(context.getApplicationInfo().dataDir + "/ota"), path);
|
assertEquals(new File(context.getApplicationInfo().dataDir + "/ota"), path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetMediaInstallPathWithObf() {
|
||||||
|
Apk apk = new Apk();
|
||||||
|
apk.apkName = "Norway_bouvet_europe_2.obf";
|
||||||
|
apk.repoAddress = "https://example.com/fdroid/repo";
|
||||||
|
assertFalse(apk.isApk());
|
||||||
|
File path = apk.getMediaInstallPath(context);
|
||||||
|
assertEquals(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), path);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetMediaInstallPathWithObfZip() throws IOException {
|
public void testGetMediaInstallPathWithObfZip() throws IOException {
|
||||||
Apk apk = new Apk();
|
Apk apk = new Apk();
|
||||||
|
@ -54,5 +54,9 @@ public class ApkCacheTest {
|
|||||||
new File(cacheDir, "example.com--1/Norway_bouvet_europe_2.obf.zip"),
|
new File(cacheDir, "example.com--1/Norway_bouvet_europe_2.obf.zip"),
|
||||||
ApkCache.getApkDownloadPath(context,
|
ApkCache.getApkDownloadPath(context,
|
||||||
"https://example.com/fdroid/repo/Norway_bouvet_europe_2.obf.zip"));
|
"https://example.com/fdroid/repo/Norway_bouvet_europe_2.obf.zip"));
|
||||||
|
assertEquals("Should work for OBF files also",
|
||||||
|
new File(cacheDir, "example.com--1/Norway_bouvet_europe_2.obf"),
|
||||||
|
ApkCache.getApkDownloadPath(context,
|
||||||
|
"https://example.com/fdroid/repo/Norway_bouvet_europe_2.obf"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user