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