本文介绍了如何使用新的FileProvider共享当前应用的APK(或其他已安装的应用)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

过去,使用一个简单的命令可以很容易地与您想要的任何应用共享APK文件:

In the past, it was easy to share an APK file with any app you wanted, using a simple command:

startActivity(new Intent(Intent.ACTION_SEND,Uri.fromFile(filePath)).setType("*/*"));

问题

如果您的应用程序针对Android API 24(Android Nougat)或更高版本,则以上代码将导致崩溃,这是由FileUriExposedException引起的(有关它的内容在此处共享文件到文件提供程序的访问权限"> 此处 ,以及用于打开APK文件的示例解决方案可以在 此处 )中找到.

The problem

If your app targets Android API 24 (Android Nougat) or above, the above code will cause a crash, caused by FileUriExposedException (written about it here, and an example solution for opening an APK file can be found here) .

使用以下代码,这实际上对我来说很好:

This actually worked for me fine, using below code:

    File apkFile = new File(apkFilePathFromSomewhereInExternalStorage);
    Intent intent = new Intent(Intent.ACTION_SEND);
    Uri fileUri = FileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".provider", apkFile);
    intent.setType("text/plain");
    intent.putExtra(Intent.EXTRA_STREAM, fileUri);
    intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    startActivity(intent);

但是,问题是我也希望能够共享当前应用的APK(以及其他已安装的应用).

However, the problem is that I also wish to be able to share the current app's APK (and also other installed apps).

要获取当前应用的APK的路径,我们使用以下方法:

For getting the path of the current app's APK, we use this:

        final PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
        File apkFile=new File(packageInfo.applicationInfo.publicSourceDir);
        ...

无需任何许可,所有应用程序都可以访问此APK,每个已安装应用程序的APK都可以访问.

This APK is accessible to all apps without the need of any permission, and so does the APK of every installed app.

但是当我将此文件与上面的代码一起使用FileProvider共享时,会出现此异常:

But when I use this file with the above code for sharing using the FileProvider, I get this exception:

IllegalArgumentException: Failed to find configured root that contains ...

当我将符号链接文件用于APK时,情况也是如此:

The same goes for when I use a symlinked file to the APK, as such:

        File apkFile=new File(packageInfo.applicationInfo.publicSourceDir);
        final String fileName = "symlink.apk";
        File symLinkFile = new File(getFilesDir(), fileName);
        if (!symLinkFile.exists())
            symLinkPath = symLinkFile.getAbsolutePath();
        createSymLink(symLinkPath, apkFile.getAbsolutePath());
        Uri fileUri= FileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".provider", symLinkFile);
        ...

public static boolean createSymLink(String symLinkFilePath, String originalFilePath) {
    try {
        if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
            Os.symlink(originalFilePath, symLinkFilePath);
            return true;
        }
        final Class<?> libcore = Class.forName("libcore.io.Libcore");
        final java.lang.reflect.Field fOs = libcore.getDeclaredField("os");
        fOs.setAccessible(true);
        final Object os = fOs.get(null);
        final java.lang.reflect.Method method = os.getClass().getMethod("symlink", String.class, String.class);
        method.invoke(os, originalFilePath, symLinkFilePath);
        return true;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}

我尝试过的

我尝试使用我认为有帮助的各种组合来配置provider_paths.xml文件,例如其中的任何一个:

What I've tried

I tried to configure the provider_paths.xml file with various combinations of what I thought would help, such as any of those :

<external-path name="external_files" path="."/>
<external-path path="Android/data/lb.com.myapplication/" name="files_root" />
<external-path path="." name="external_storage_root" />
<files-path name="files" path="." />
<files-path name="files" path="" />

我还尝试禁用与此机制关联的strictMode:

I also tried to disable the strictMode that's associated with this mechanism:

    StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
    StrictMode.setVmPolicy(builder.build());

问题

如何通过我的应用可访问的所有可能路径(包括使用符号链接文件)共享任何APK文件?

The question

How can I share any APK file, from every possible path that's accessible to my app, including using symlinked files ?

推荐答案

这是因为packageInfo.applicationInfo.publicSourceDir不在FileProvider的可能根目录之一之下.

That is because packageInfo.applicationInfo.publicSourceDir is not underneath one of the possible roots for FileProvider.

也许符号链接在这里不起作用.您的<files-path>元素之一—或您完全不使用path的一个—可以提供getFilesDir()以外的普通文件.

Perhaps symlinks don't work here. One of your <files-path> elements — or one where you leave path off entirely — can serve ordinary files out of getFilesDir().

由于没有官方支持的符号链接,所以我在这里不能为您提供帮助.

Since there is no official support for symlinks, I can't help you there.

否则,您有三个主要选择:

Otherwise, you have three main options:

  1. FileProvider喜欢的地方复制APK文件的副本

  1. Make a copy of the APK file someplace that FileProvider likes

尝试使用我的StreamProvider 和一些自定义扩展来教它从packageInfo.applicationInfo.publicSourceDir

编写您自己的ContentProvider,该ContentProviderpackageInfo.applicationInfo.publicSourceDir

这篇关于如何使用新的FileProvider共享当前应用的APK(或其他已安装的应用)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-23 10:02