2016-10-01
10:43 AM
由於 Android N 加入了 intent 開啟檔案的權限判斷
所有使用 file:// 開頭的 uri 將會出現 FileUriExposedException
必須改為使用 content:// 開頭的 uri
也就是會用到 FileProvider
以下將以點擊通知開啟外部檔案為範例說明須修改的部分
首先在 res/xml 內建立一個 file_paths.xml 的檔案(名稱自訂)
程式碼範例
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="folderName" path="."/> </paths> // external-path: 等同於 Environment.getExternalStorageDirectory() // name="folderName": 任意名稱 點擊後顯示的路徑資料夾名稱 // path=".": 實際要分享權限的資料夾路徑 使用 "." 代表根目錄
建立完成後再到 AndroidManifest.xml 加入 porvider 節點
<application> ... <provider android:name="android.support.v4.content.FileProvider" android:authorities="your.package.name.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> ... </application>
接著建立 Uri Intent
Intent intent = new Intent(); intent.setAction(android.content.Intent.ACTION_VIEW); intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); File file = new File(dir, filename); // API 24 之前使用的方式 會出現 FileUriExposedException // Uri.fromFile(file) // API 24 使用的方式 Uri uri = FileProvider.getUriForFile(getActivity(), "your.package.name.fileprovider", file); intent.setDataAndType(uri, MimeTypeMap.getSingleton().getMimeTypeFromExtension("html")); int flags = PendingIntent.FLAG_UPDATE_CURRENT; PendingIntent pIntent = PendingIntent.getActivity(getActivity(), REQEUST_CODE, intent, flags); // 取得系統的通知服務 NotificationManagerCompat notificationManager = NotificationManagerCompat.from( getActivity() ); // 建立通知 final Notification notification = new NotificationCompat.Builder( getActivity() ) .setSmallIcon( R.drawable.ic_notification ) .setLargeIcon( BitmapFactory.decodeResource(getResources(), R.drawable.ic_notification_large) ) .setContentTitle( notificationTitle ) .setContentText( filename ) .setContentIntent(pIntent) .setOngoing(false) .setDefaults(Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS) .setPriority(Notification.PRIORITY_MAX) .build(); // 發送通知 notificationManager.notify(NID, notification);
各項資料連結
Android - FileProvider