Commit 3b97aa4a by Sebastián Katzer

Fix android.os.FileUriExposedException with Android 7 or newer

parent 69914bc6
...@@ -104,6 +104,16 @@ ...@@ -104,6 +104,16 @@
</config-file> </config-file>
<config-file target="AndroidManifest.xml" parent="/manifest/application"> <config-file target="AndroidManifest.xml" parent="/manifest/application">
<provider
android:name="de.appplant.cordova.plugin.notification.util.AssetProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true" >
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/localnotification_provider_paths"/>
</provider>
<receiver <receiver
android:name="de.appplant.cordova.plugin.localnotification.TriggerReceiver" android:name="de.appplant.cordova.plugin.localnotification.TriggerReceiver"
android:exported="false" /> android:exported="false" />
...@@ -132,6 +142,10 @@ ...@@ -132,6 +142,10 @@
</config-file> </config-file>
<source-file <source-file
src="src/android/xml/localnotification_provider_paths.xml"
target-dir="res/xml" />
<source-file
src="src/android/LocalNotification.java" src="src/android/LocalNotification.java"
target-dir="src/de/appplant/cordova/plugin/localnotification" /> target-dir="src/de/appplant/cordova/plugin/localnotification" />
...@@ -192,6 +206,10 @@ ...@@ -192,6 +206,10 @@
target-dir="src/de/appplant/cordova/plugin/notification/trigger" /> target-dir="src/de/appplant/cordova/plugin/notification/trigger" />
<source-file <source-file
src="src/android/notification/util/AssetProvider.java"
target-dir="src/de/appplant/cordova/plugin/notification/util" />
<source-file
src="src/android/notification/util/AssetUtil.java" src="src/android/notification/util/AssetUtil.java"
target-dir="src/de/appplant/cordova/plugin/notification/util" /> target-dir="src/de/appplant/cordova/plugin/notification/util" />
......
...@@ -25,6 +25,8 @@ import android.app.PendingIntent; ...@@ -25,6 +25,8 @@ import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.MessagingStyle.Message; import android.support.v4.app.NotificationCompat.MessagingStyle.Message;
...@@ -88,15 +90,22 @@ public final class Builder { ...@@ -88,15 +90,22 @@ public final class Builder {
* @return The final notification to display. * @return The final notification to display.
*/ */
public Notification build() { public Notification build() {
int smallIcon = options.getSmallIcon();
NotificationCompat.Builder builder; NotificationCompat.Builder builder;
if (options.isSilent()) { if (options.isSilent()) {
return new Notification(context, options); return new Notification(context, options);
} }
int smallIcon = options.getSmallIcon();
Uri sound = options.getSound();
Bundle extras = new Bundle();
extras.putString(Options.EXTRA, options.toString());
extras.putString(Options.SOUND_EXTRA, sound.toString());
builder = new NotificationCompat.Builder(context, Manager.CHANNEL_ID) builder = new NotificationCompat.Builder(context, Manager.CHANNEL_ID)
.setDefaults(options.getDefaults()) .setDefaults(options.getDefaults())
.setExtras(extras)
.setChannelId(options.getChannel()) .setChannelId(options.getChannel())
.setContentTitle(options.getTitle()) .setContentTitle(options.getTitle())
.setContentText(options.getText()) .setContentText(options.getText())
...@@ -105,7 +114,7 @@ public final class Builder { ...@@ -105,7 +114,7 @@ public final class Builder {
.setAutoCancel(options.isAutoClear()) .setAutoCancel(options.isAutoClear())
.setOngoing(options.isSticky()) .setOngoing(options.isSticky())
.setColor(options.getColor()) .setColor(options.getColor())
.setSound(options.getSound()) .setSound(sound)
.setVisibility(options.getVisibility()) .setVisibility(options.getVisibility())
.setPriority(options.getPriority()) .setPriority(options.getPriority())
.setShowWhen(options.getShowWhen()) .setShowWhen(options.getShowWhen())
......
...@@ -29,6 +29,7 @@ import android.app.PendingIntent; ...@@ -29,6 +29,7 @@ import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
...@@ -189,17 +190,16 @@ public final class Notification { ...@@ -189,17 +190,16 @@ public final class Notification {
* Present the local notification to user. * Present the local notification to user.
*/ */
public void show () { public void show () {
// TODO Show dialog when in foreground if (builder == null)
showNotification(); return;
}
/** String sound = builder.getExtras().getString(Options.SOUND_EXTRA);
* Show as local notification when in background. Uri soundUri = Uri.parse(sound);
*/
private void showNotification () { context.grantUriPermission("com.android.systemui", soundUri,
if (builder != null) { Intent.FLAG_GRANT_READ_URI_PERMISSION);
getNotMgr().notify(getId(), builder.build());
} getNotMgr().notify(getId(), builder.build());
} }
// /** // /**
......
...@@ -56,6 +56,9 @@ public final class Options { ...@@ -56,6 +56,9 @@ public final class Options {
// Key name for bundled extras // Key name for bundled extras
public static final String EXTRA = "NOTIFICATION_OPTIONS"; public static final String EXTRA = "NOTIFICATION_OPTIONS";
// Key name for bundled sound extra
public static final String SOUND_EXTRA = "NOTIFICATION_SOUND";
// Default icon path // Default icon path
private static final String DEFAULT_ICON = "res://icon"; private static final String DEFAULT_ICON = "res://icon";
......
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package de.appplant.cordova.plugin.notification.util;
import android.support.v4.content.FileProvider;
public class AssetProvider extends FileProvider {
// Nothing to do here
}
\ No newline at end of file
...@@ -112,7 +112,7 @@ public final class AssetUtil { ...@@ -112,7 +112,7 @@ public final class AssetUtil {
return Uri.EMPTY; return Uri.EMPTY;
} }
return Uri.fromFile(file); return getUriFromFile(file);
} }
/** /**
...@@ -142,7 +142,7 @@ public final class AssetUtil { ...@@ -142,7 +142,7 @@ public final class AssetUtil {
outStream.flush(); outStream.flush();
outStream.close(); outStream.close();
return Uri.fromFile(file); return getUriFromFile(file);
} catch (Exception e) { } catch (Exception e) {
Log.e("Asset", "File not found: assets/" + resPath); Log.e("Asset", "File not found: assets/" + resPath);
...@@ -213,7 +213,7 @@ public final class AssetUtil { ...@@ -213,7 +213,7 @@ public final class AssetUtil {
outStream.flush(); outStream.flush();
outStream.close(); outStream.close();
return Uri.fromFile(file); return getUriFromFile(file);
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
Log.e("Asset", "Incorrect URL"); Log.e("Asset", "Incorrect URL");
...@@ -347,6 +347,18 @@ public final class AssetUtil { ...@@ -347,6 +347,18 @@ public final class AssetUtil {
} }
/** /**
* Get content URI for the specified file.
*
* @param file The file to get the URI.
*
* @return content://...
*/
private Uri getUriFromFile(File file) {
String authority = context.getPackageName() + ".provider";
return AssetProvider.getUriForFile(context, authority, file);
}
/**
* Package name specified by the resource bundle. * Package name specified by the resource bundle.
*/ */
private String getPkgName (Resources res) { private String getPkgName (Resources res) {
......
<?xml version="1.0" encoding="utf-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment