首页 > 解决方案 > android app下载apk文件并打开(安装)

问题描述

我想知道您是否可以提供帮助,我正在尝试在版本检查后下载一个 apk 文件作为更新。它正在下载 apk,但它不会打开 apk 文件它在尝试打开 apk 时打印错误

错误 :

E/UpdateAPP: Update error! file:///storage/emulated/0/download/update.apk exposed beyond app through Intent.getData()

代码 :

public class UpdateApp extends AsyncTask<String,Void,Void> {
    private Context context;
    public void setContext(Context contextf){
        context = contextf;
    }

    @Override
    protected Void doInBackground(String... arg0) {
        try {
            URL url = new URL(arg0[0]);
            HttpURLConnection c = (HttpURLConnection) url.openConnection();
            c.setRequestMethod("GET");
            c.setDoOutput(true);
            c.connect();

            String PATH = Environment.getExternalStorageDirectory() + "/download/";
            File file = new File(PATH);
            file.mkdirs();
            File outputFile = new File(file, "update.apk");
            if(outputFile.exists()){
                outputFile.delete();
            }
            FileOutputStream fos = new FileOutputStream(outputFile);

            InputStream is = c.getInputStream();

            byte[] buffer = new byte[1024];
            int len1 = 0;
            while ((len1 = is.read(buffer)) != -1) {
                fos.write(buffer, 0, len1);
            }
            fos.close();
            is.close();

            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/download/" + "/update.apk")), "application/vnd.android.package-archive");
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // without this flag android returned a intent error!
            context.startActivity(intent);


        } catch (Exception e) {
            Log.e("UpdateAPP", "Update error! " + e.getMessage());
        }
        return null;
    }}

我的 targetSdkVersion :

targetSdkVersion 27

谢谢您的帮助

标签: javaandroid

解决方案


从 API 26 开始,“REQUEST_INSTALL_PACKAGES”权限是实现安装 apk 文件的必要权限。

  1. 在 res/xml 文件夹中创建“file_paths.xml”以使用 FileProvider api
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="" path="/" />
</paths>
  1. 在 AndroidManifest.xml 中声明 FileProvider 和权限

笔记。我使用的是 Androidx 版本的 FileProvider,如果你不使用 androidx,请确保 android.support.v4.content.FileProvider

<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

 <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="{PACKAGE_NAME}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />

</provider>
  1. 通过 FileProvider api 获取“Uri”并请求安装权限
private fun openFile(file: File) {
        val uri = if (Build.VERSION.SDK_INT >= 24) {
            val authority = packageName + ".fileprovider"
            FileProvider.getUriForFile(this, authority, file)
        } else {
            Uri.fromFile(file)
        }

        val myMime = MimeTypeMap.getSingleton()
        val mimeType = myMime.getMimeTypeFromExtension(file.extension)

        val intent = Intent(Intent.ACTION_VIEW).apply {
            setDataAndType(uri, mimeType)
            flags = Intent.FLAG_ACTIVITY_NEW_TASK
            addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        }

        if (Build.VERSION.SDK_INT >= 26 && !packageManager.canRequestPackageInstalls()) {
            startActivity(
                Intent(
                    Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES,
                    Uri.parse("package:$packageName")
                )
            )
        } else {
            intent.action = Intent.ACTION_VIEW
            startActivity(intent)
        }
    }

编辑 -> 删除在我的项目中使用的特定方法。


推荐阅读