Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/201.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android:不是文件URI:下载.apk文件时_Java_Android - Fatal编程技术网

Java Android:不是文件URI:下载.apk文件时

Java Android:不是文件URI:下载.apk文件时,java,android,Java,Android,我想下载.apk文件并安装它。当我不使用FileProvider时,一切都很顺利,但当我使用FileProvider从文件创建uri时,我得到了IllegalArgumentException:不是文件uri:content://pl.rasztabiga.klasa1a.provider/external_storage_root/klasa1a.apk 在线 final long downloadId = manager.enqueue(request); 我尝试了stackoverflo

我想下载.apk文件并安装它。当我不使用FileProvider时,一切都很顺利,但当我使用FileProvider从文件创建uri时,我得到了IllegalArgumentException:不是文件uri:content://pl.rasztabiga.klasa1a.provider/external_storage_root/klasa1a.apk 在线

final long downloadId = manager.enqueue(request);
我尝试了stackoverflow的所有方法,但没有任何效果。这是我的密码:

File file = new File(Environment.getExternalStorageDirectory(), "klasa1a.apk");
final Uri uri = FileProvider.getUriForFile(MainActivity.this, getApplicationContext().getPackageName() + ".provider", file);

        //Delete update file if exists
        //File file = new File(destination);
        if (file.exists())
            file.delete();

        //get url of app on server
        String url = "http://rasztabiga.ct8.pl/klasa1a.apk";

        //set downloadmanager
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
        request.setDescription("Downloading new version");
        request.setTitle(MainActivity.this.getString(R.string.app_name));

        //set destination
        request.setDestinationUri(uri);

        // get download service and enqueue file
        final DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
        final long downloadId = manager.enqueue(request);

        //set BroadcastReceiver to install app when .apk is downloaded
        BroadcastReceiver onComplete = new BroadcastReceiver() {
            public void onReceive(Context ctxt, Intent intent) {
                Intent install = new Intent(Intent.ACTION_VIEW);
                install.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                install.setDataAndType(uri,
                        manager.getMimeTypeForDownloadedFile(downloadId));
                startActivity(install);

                unregisterReceiver(this);
                finish();
            }
        };
        //register receiver for when .apk download is compete
        registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));

ACTION\u视图
ACTION\u安装程序包
仅支持自Android 7.0起的
内容
方案。在此之前,您别无选择,只能使用
文件
。因此,改变:

final Uri uri = FileProvider.getUriForFile(MainActivity.this, getApplicationContext().getPackageName() + ".provider", file);
致:


问题出在DownloadManager中。它无法将uri解析为“content://”,而只能解析为“file://”,因此由于sdk24,我们无法使用它。使用常见的IOStreams和HttpURLConnection,一切正常。感谢@commonware为我展示了他的项目。 这就是现在的情况:

        File file = new File(Environment.getExternalStorageDirectory(), "klasa1a.apk");
        final Uri uri = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) ?
                FileProvider.getUriForFile(MainActivity.this, BuildConfig.APPLICATION_ID + ".provider", file) :
                Uri.fromFile(file);

        //Delete update file if exists
        //File file = new File(destination);
        if (file.exists())
            //file.delete() - test this, I think sometimes it doesnt work
            file.delete();

        //get url of app on server
        String url = "http://rasztabiga.ct8.pl/klasa1a.apk";

        InputStream input = null;
        OutputStream output = null;
        HttpURLConnection connection = null;
        try {
            URL sUrl = new URL(url);
            connection = (HttpURLConnection) sUrl.openConnection();
            connection.connect();

            // download the file
            input = connection.getInputStream();
            output = new FileOutputStream(file);

            byte data[] = new byte[4096];
            int count;
            while ((count = input.read(data)) != -1) {
                // allow canceling with back button
                if (isCancelled()) {
                    input.close();
                    return null;
                }

                output.write(data, 0, count);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (output != null)
                    output.close();
                if (input != null)
                    input.close();
            } catch (IOException ignored) {
            }

            if (connection != null)
                connection.disconnect();
        }

        Intent install = new Intent(Intent.ACTION_INSTALL_PACKAGE)
                .setData(uri)
                .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        startActivity(install);

        return null;
    }

对于那些仍然想使用
DownloadManager
并发现Commonware的答案无法解决问题的用户,您需要为APK文件添加一个异常

final Uri uri = (!file.getAbsolutePath().endsWith(".apk") && Build.VERSION.SDK_INT>=Build.VERSION_CODES.N) ?
    FileProvider.getUriForFile(MainActivity.this, BuildConfig.APPLICATION_ID + ".provider", file) :
    Uri.fromFile(file);
request.setDestinationUri(uri);
哪一个是较短的版本

if (!file.getAbsolutePath().endsWith(".apk") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    request.setDestinationUri(FileProvider.getUriForFile(MainActivity.this,  BuildConfig.APPLICATION_ID + ".provider", download));
} else {
    request.setDestinationUri(Uri.fromFile(file));
}
这可能更容易遵循

简单的回答是,apk文件应该使用
Uri.fromFile
处理,但这不必以更改整个过程为代价


不过,如果您想彻底了解,还可以捕获
非文件URI的
非法argumentexception
,并使用它尝试
URI.fromFile

,不幸的是,这在7.1上不起作用。它抛出相同的:不是文件URI:content://pl.rasztabiga.klasa1a.provider/external_storage_root/klasa1a.apk@BartłomiejRasztabiga:它在运行7.1.1的Nexus9上为我工作。你在测试什么设备?小米Redmi Note 3 Pro,安卓7.1。1@BartłomiejRasztabiga:那就是那个设备的问题了。股票安卓的安装程序处理
内容
现在。您需要使用
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().build())禁用
FileUriExposedException
。然后,切换到所有Android版本的
Uri.fromFile()
,至少在几年内如此。我在sdk25 emulator上运行了这个程序,它仍然抛出相同的异常。
if (!file.getAbsolutePath().endsWith(".apk") && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    request.setDestinationUri(FileProvider.getUriForFile(MainActivity.this,  BuildConfig.APPLICATION_ID + ".provider", download));
} else {
    request.setDestinationUri(Uri.fromFile(file));
}