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());
 | 
			
		||||
        if (TextUtils.isEmpty(fileExtension)) return path;
 | 
			
		||||
        MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
 | 
			
		||||
        String[] mimeType = mimeTypeMap.getMimeTypeFromExtension(fileExtension).split("/");
 | 
			
		||||
        String topLevelType;
 | 
			
		||||
        if (mimeType.length == 0) {
 | 
			
		||||
            topLevelType = "";
 | 
			
		||||
        } else {
 | 
			
		||||
            topLevelType = mimeType[0];
 | 
			
		||||
        String mimeType = mimeTypeMap.getMimeTypeFromExtension(fileExtension);
 | 
			
		||||
        String topLevelType = null;
 | 
			
		||||
        if (!TextUtils.isEmpty(mimeType)) {
 | 
			
		||||
            String[] mimeTypeSections = mimeType.split("/");
 | 
			
		||||
            if (mimeTypeSections.length == 0) {
 | 
			
		||||
                topLevelType = "";
 | 
			
		||||
            } else {
 | 
			
		||||
                topLevelType = mimeTypeSections[0];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if ("audio".equals(topLevelType)) {
 | 
			
		||||
            path = Environment.getExternalStoragePublicDirectory(
 | 
			
		||||
 | 
			
		||||
@ -5,8 +5,12 @@ import android.content.DialogInterface;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.content.pm.PackageManager;
 | 
			
		||||
import android.net.Uri;
 | 
			
		||||
import android.os.Build;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.os.StrictMode;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
import android.view.ContextThemeWrapper;
 | 
			
		||||
import android.webkit.MimeTypeMap;
 | 
			
		||||
import android.widget.Toast;
 | 
			
		||||
import androidx.annotation.NonNull;
 | 
			
		||||
import androidx.appcompat.app.AlertDialog;
 | 
			
		||||
@ -21,6 +25,7 @@ import org.fdroid.fdroid.data.Apk;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.lang.reflect.Method;
 | 
			
		||||
 | 
			
		||||
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.LENGTH_LONG).show();
 | 
			
		||||
            installer.sendBroadcastInstall(canonicalUri, Installer.ACTION_INSTALL_COMPLETE);
 | 
			
		||||
            postInstall(path);
 | 
			
		||||
        } else {
 | 
			
		||||
            installer.sendBroadcastInstall(canonicalUri, Installer.ACTION_INSTALL_INTERRUPTED);
 | 
			
		||||
        }
 | 
			
		||||
        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) {
 | 
			
		||||
        if (apk.isMediaInstalled(activity.getApplicationContext())) {
 | 
			
		||||
            File file = apk.getInstalledMediaFile(activity.getApplicationContext());
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,6 @@ package org.fdroid.fdroid.data;
 | 
			
		||||
 | 
			
		||||
import android.content.ContextWrapper;
 | 
			
		||||
import android.os.Environment;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
import android.webkit.MimeTypeMap;
 | 
			
		||||
import androidx.test.core.app.ApplicationProvider;
 | 
			
		||||
import org.apache.commons.io.FileUtils;
 | 
			
		||||
@ -58,6 +57,16 @@ public class ApkTest {
 | 
			
		||||
        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
 | 
			
		||||
    public void testGetMediaInstallPathWithObfZip() throws IOException {
 | 
			
		||||
        Apk apk = new Apk();
 | 
			
		||||
 | 
			
		||||
@ -54,5 +54,9 @@ public class ApkCacheTest {
 | 
			
		||||
                new File(cacheDir, "example.com--1/Norway_bouvet_europe_2.obf.zip"),
 | 
			
		||||
                ApkCache.getApkDownloadPath(context,
 | 
			
		||||
                        "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