2016-10-12 90 views
9

由於FileProvider的變化,我必須修復Android N的應用程序。我已經基本閱讀了最後一篇關於這個話題的所有內容,但沒有找到解決方案爲我工作。使用FileProvider在Android N上打開下載的文件

下面是從我們的應用程序開始下載我們之前的代碼,並將其存儲於Download文件夾,並調用一個ACTION_VIEW意圖作爲soons爲DownloadManager告訴他完成下載:

BroadcastReceiver onComplete = new BroadcastReceiver() { 
    public void onReceive(Context ctxt, Intent intent) { 
     Log.d(TAG, "Download commplete"); 

     // Check for our download 
     long referenceId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); 
     if (mDownloadReference == referenceId) { 
      DownloadManager.Query query = new DownloadManager.Query(); 
      query.setFilterById(mDownloadReference); 
      Cursor c = mDownloadManager.query(query); 
      if (c.moveToFirst()) { 
       int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS); 
       if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) { 
        String localUri = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)); 
        String fileExtension = MimeTypeMap.getFileExtensionFromUrl(localUri); 
        String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension); 

        if (mimeType != null) { 
         Intent openFileIntent = new Intent(Intent.ACTION_VIEW); 
         openFileIntent.setDataAndTypeAndNormalize(Uri.parse(localUri), mimeType); 
         openFileIntent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); 

         try { 
          mAcme.startActivity(openFileIntent); 
         } 
         catch (ActivityNotFoundException e) { 
          // Ignore if no activity was found. 
         } 
        } 
       } 
      } 
     } 
    } 
}; 

這適用於Android男,但因受歡迎的FileUriExposedException而在N上休息。我現在試圖通過使用FileProvider來解決這個問題,但我無法實現它。當我嘗試獲取內容URI它打破:

Failed to find configured root that contains /file:/storage/emulated/0/Download/test.pdf

localUriDownloadManager返回的文件是:

file:///storage/emulated/0/Download/test.pdf

Environment.getExternalStorageDirectory()回報/storage/emulated/0,這是代碼轉換:

File file = new File(localUri); 
Log.d(TAG, localUri + " - " + Environment.getExternalStorageDirectory()); 
Uri contentUri = FileProvider.getUriForFile(ctxt, "my.file.provider", file); 

AndroidManifest.xml

<provider 
     android:name="android.support.v4.content.FileProvider" 
     android:authorities="my.file.provider" 
     android:exported="false" 
     android:grantUriPermissions="true"> 
     <meta-data 
      android:name="android.support.FILE_PROVIDER_PATHS" 
      android:resource="@xml/file_paths"/> 
    </provider> 

file_paths.xml

<?xml version="1.0" encoding="utf-8"?> 
<paths xmlns:android="http://schemas.android.com/apk/res/android"> 
    <external-path name="external_path" path="." /> 
</paths> 

我已經嘗試了所有值我能找到該XML文件。 :(

+0

確保你是在Android支持庫的最新版本。如果你是這樣的話,那麼感覺就像當前'FileProvider'中的一個錯誤。 – CommonsWare

+3

'file:/// storage/emulated/0/Download/test.pdf'。你不能按原樣使用它。從中刪除「file://」。您必須使用有效的文件路徑:'/ storage/emulated/0/Download/test.pdf'。 – greenapps

+0

@CommonsWare我在v24.2上運行。1 – althaus

回答

6

感謝@greenaps我是能夠解決這一問題,當地URI檢索從DownlodManager是前綴爲file://。必須刪除新的FileProvider

if (localUri.substring(0, 7).matches("file://")) { 
    localUri = localUri.substring(7); 
} 
File file = new File(localUri); 
+2

下次當您在評論中找到答案時,請邀請海報將其評論發佈爲答案。 – greenapps

+0

隨時發佈您的答案。我還沒有接受我的目的。 – althaus

+0

你能發表完整的答案嗎? – emaillenin

3

這裏的變化在AndroidManifest.xml

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

改變文件路徑

Uri contentUri; 
if(Build.VERSION.SDK_INT == 24){ 
     contentUri = FileProvider.getUriForFile(MainActivity.this, 
       getApplicationContext().getPackageName() + ".provider", 
        file); 
} else{ 
     contentUri = Uri.fromFile(file); 
     } 
+0

這不是真的增加任何價值,因爲我已經這樣做了。 – althaus

1

我有一個類似的問題,並通過不自動打開文件,但顯示「下載完成」通知,然後讓Android系統在用戶單擊通知時打開文件來解決。

要另外通知用戶,我會在下載完成時顯示Toast。

DownloadManager mManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); 

String url = "your URL"; 
String filename = "file.pdf"; 

// Set up the request. 
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)) 
      .setTitle("Test") 
      .setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename) 
      .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) 
      .setDescription("Downloading...") 
      .setMimeType("application/pdf"); 

request.allowScanningByMediaScanner(); 
mManager.enqueue(request); 

廣播接收器:

public class DownloadReceiver extends BroadcastReceiver { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     switch (intent.getAction()) { 
      case DownloadManager.ACTION_DOWNLOAD_COMPLETE: 
       Toast.makeText(context, "Download completed", Toast.LENGTH_SHORT).show(); 
       break; 
     } 
    } 

} 
相關問題