2016-12-23 35 views
0

我想下載.apk文件並安裝它。當我不使用FileProvider時,一切都很順利,但是當我使用FileProvider從文件創建uri時,我得到了IllegalArgumentException:不是文件URI:content://pl.rasztabiga.klasa1a.provider/external_storage_root/klasa1a。 apk上線Android:不是文件URI:下載.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)); 

回答

2

ACTION_VIEWACTION_INSTALL_PACKAGE只支持content方案由於Android 7.0的。在此之前,你別無選擇,只能使用file。因此,更改:

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

到:

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

不幸的是,這不適用於7.1。它會拋出相同的:不是文件的URI:內容://pl.rasztabiga.klasa1a.provider/external_storage_root/klasa1a.apk –

+0

@BartłomiejRasztabiga:它正在運行7.1.1的Nexus 9上爲我工作。你正在測試什麼設備? – CommonsWare

+0

Xiaomi Redmi Note 3 Pro,Android 7.1.1 –

0

這個問題在下載管理器。它不能將uri解析爲「content://」,只能作爲「file://」,因爲從sdk24開始,我們不能使用它。使用常見IOStreams和HttpURLConnection一切正常。感謝@CommonsWare向我展示他的項目。 這就是它現在的樣子:

 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; 
    }