Android FileProvider 将 URI 传递给 Notification 的问题
Issue with Android FileProvider passing URI to Notification
我对 Android FileProvider 有一个奇怪的问题。我有 Retrofit 2 下载的文件并写下来做 InternalStorage(安全原因),然后我为此文件创建 URI 并将其传递给 Intent。根据这个意图,我正在创建传递给 Notification 的 PendingIntent。目标是通过单击通知打开文件。到目前为止一切顺利。
问题是尝试使用下面列出的代码几次后我发生了 SecurityException。现在在 logcat 我看不到任何错误和异常,但文件似乎是空的(文件已正确下载 - 我通过用相同的方法写入外部 public 目录来检查它)。这是pdf文件,我在查看器中看到的只有文件名和黑色内容。
我创建 uri 和传递 intent 的代码:
filesWebService.getFileFromUrl(url).subscribe((ResponseBody body) -> {
String filename = URLUtil.guessFileName (url,null, null);
Log.d("WebService","File received: " +filename);
FileOutputStream fos = null;
try {
fos = openFileOutput(filename, Context.MODE_PRIVATE);
InputStream inputStream = body.byteStream();
byte[] buffer = new byte[1024];
int bufferLength = 0;
while((bufferLength = inputStream.read(buffer)) > 0) {
fos.write(buffer, 0, bufferLength);
}
fos.close();
File downloadedFile = new File(PdfDownloadService.this.getFilesDir(), filename);
Log.d("DownloadService", downloadedFile.toString());
Uri contentUri = FileProvider.getUriForFile(PdfDownloadService.this, "fantom.obtainpdf.fileprovider", downloadedFile);
Log.d("DownloadService", contentUri.toString());
Intent intent = new Intent(Intent.ACTION_VIEW, contentUri);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent openFileIntent = PendingIntent.getActivity(PdfDownloadService.this, notif_id, intent , PendingIntent.FLAG_UPDATE_CURRENT);
mNotificationUtil.cancelNotification(notif_id);
mNotificationUtil.createNotificiationWithIntent(openFileIntent, "Pobrano plik", android.R.drawable.sym_def_app_icon, notif_id, true);
} catch (IOException e) {
e.printStackTrace();
}
});
清单:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="fantom.obtainpdf">
...
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="fantom.obtainpdf.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
文件路径:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="files"/>
</paths>
通知:
private NotificationCompat.Builder createNotification(String contentTitle, String contentText, @DrawableRes int icon, int notifID, boolean autoCancel){
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(mContext)
.setSmallIcon(icon)
.setContentTitle(contentTitle)
.setContentText(contentText)
.setAutoCancel(autoCancel);
return mBuilder;
}
public void createNotificiationWithIntent(PendingIntent intent, String contentTitle, @DrawableRes int icon, int notifID, boolean autoCancel){
NotificationCompat.Builder builder = createNotification(contentTitle,"", icon, notifID, autoCancel);
builder.setContentIntent(intent);
mNotificationManager.notify(notifID, builder.build());
}
您的 FileProvider 未导出。当 exported 标志为 false 时,其他应用无法访问它。
好的,
我设法发现了问题所在 - 我正在 KitKat 上进行测试,并且存在需要解决方法的错误,如下所述:。添加这样的块后一切顺利。
我对 Android FileProvider 有一个奇怪的问题。我有 Retrofit 2 下载的文件并写下来做 InternalStorage(安全原因),然后我为此文件创建 URI 并将其传递给 Intent。根据这个意图,我正在创建传递给 Notification 的 PendingIntent。目标是通过单击通知打开文件。到目前为止一切顺利。
问题是尝试使用下面列出的代码几次后我发生了 SecurityException。现在在 logcat 我看不到任何错误和异常,但文件似乎是空的(文件已正确下载 - 我通过用相同的方法写入外部 public 目录来检查它)。这是pdf文件,我在查看器中看到的只有文件名和黑色内容。
我创建 uri 和传递 intent 的代码:
filesWebService.getFileFromUrl(url).subscribe((ResponseBody body) -> {
String filename = URLUtil.guessFileName (url,null, null);
Log.d("WebService","File received: " +filename);
FileOutputStream fos = null;
try {
fos = openFileOutput(filename, Context.MODE_PRIVATE);
InputStream inputStream = body.byteStream();
byte[] buffer = new byte[1024];
int bufferLength = 0;
while((bufferLength = inputStream.read(buffer)) > 0) {
fos.write(buffer, 0, bufferLength);
}
fos.close();
File downloadedFile = new File(PdfDownloadService.this.getFilesDir(), filename);
Log.d("DownloadService", downloadedFile.toString());
Uri contentUri = FileProvider.getUriForFile(PdfDownloadService.this, "fantom.obtainpdf.fileprovider", downloadedFile);
Log.d("DownloadService", contentUri.toString());
Intent intent = new Intent(Intent.ACTION_VIEW, contentUri);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent openFileIntent = PendingIntent.getActivity(PdfDownloadService.this, notif_id, intent , PendingIntent.FLAG_UPDATE_CURRENT);
mNotificationUtil.cancelNotification(notif_id);
mNotificationUtil.createNotificiationWithIntent(openFileIntent, "Pobrano plik", android.R.drawable.sym_def_app_icon, notif_id, true);
} catch (IOException e) {
e.printStackTrace();
}
});
清单:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="fantom.obtainpdf">
...
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="fantom.obtainpdf.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
文件路径:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="files"/>
</paths>
通知:
private NotificationCompat.Builder createNotification(String contentTitle, String contentText, @DrawableRes int icon, int notifID, boolean autoCancel){
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(mContext)
.setSmallIcon(icon)
.setContentTitle(contentTitle)
.setContentText(contentText)
.setAutoCancel(autoCancel);
return mBuilder;
}
public void createNotificiationWithIntent(PendingIntent intent, String contentTitle, @DrawableRes int icon, int notifID, boolean autoCancel){
NotificationCompat.Builder builder = createNotification(contentTitle,"", icon, notifID, autoCancel);
builder.setContentIntent(intent);
mNotificationManager.notify(notifID, builder.build());
}
您的 FileProvider 未导出。当 exported 标志为 false 时,其他应用无法访问它。
好的, 我设法发现了问题所在 - 我正在 KitKat 上进行测试,并且存在需要解决方法的错误,如下所述:。添加这样的块后一切顺利。