Issue
I'm trying to use the native local notifications plugin and having troubles changing the default icon for the notification.
So far, I've used two phones to test this, both android devices: the first, Oreo (8.1.0) and the other one, Nougat (7.0). I'm using Ionic CLI 4.5.0, and I'm aware its wrapper is not compatible with the plugin, as stated in the plugin repository.
I've tried many paths for the icon URI, according to what this answer suggested, but nothing seems to work.
In a provider, this is the relevant part of the code:
declare var cordova: any;
...
// inside a function that takes "id", "nome" and "tempo" as parameters:
cordova.plugins.notification.local.schedule({
id: id,
title: nome,
text: "Sua atividade agendada, \"" + nome + "\", está prestes a começar!",
at: new Date(tempo),
foreground: true,
icon: 'res://icone-notif.png',
smallIcon: 'res://icone-notif-24.png'
});
And in my config.xml, I added these lines:
<platform name="android">
...
<resource-file src="resources/android/icon/icone-notif-24.png" target="res/icone-notif-24.png" />
<resource-file src="resources/android/icon/icone-notif.png" target="res/icone-notif.png" />
</platform>
(I've checked every file and they get placed in the "res" folder in my project correctly)
The notification icon should be shown as the images I saved in those folders, but what I get is just the default white square.
Solution
I struggled for a long time, and here is what I did to solve that:
My notification is declared as such:
const notification = {
id: idNotif,
text: this.getNotifText(notifs[0].type),
trigger: {at: dateNotif},
led: 'FF0000',
smallIcon: 'res://ic_stat_notify.png',
icon: 'res://icon.png',
vibrate: true
};
this.localNotifications.schedule(notification);
In that code sample, notice that the links to these icons are prefixed with res://
. These icons are actually located in the platforms/android/app/src/main/res
folder, which is automatically generated when you compile your app (with ionic cordova run android
for instance).
If you want the notifications to work, you should have the following folders in that res
folder:
- drawable-mdpi
- drawable-hdpi
- drawable-xhdpi
- drawable-xxhdpi
- drawable-xxxhdpi
You also need the file icon.png
directly in the folder res
, as it is referenced as the icon
parameter in the local notification declaration.
The folders correspond to the different possible icon sizes in Android, depending on pixel densities. You can find more about it in the icon handbook. When the notification will be triggered, the right size of icon will automatically be chosen among these 5 possible sizes.
Each of these folders must contain the file ic_stat_notify.png
, which needs to be the icon in the right format:
- drawable-mdpi: 24x24
- drawable-hdpi: 36x36
- drawable-xhdpi: 48x48
- drawable-xxhdpi: 72x72
- drawable-xxxhdpi: 96x96
- icon.png: 96x96
Alright, but how do I put these in a folder that is generated only after compiling?
The answer is: by creating a hook.
Put these folders in a folder that you can access and that exists all the time in your app. Personally, I used resources/android/icon
.
Then, create a hook to copy those files into the right folder everytime the app is compiled.
Here is my hook icon_notif.js
(note: it is heavily inspired by this tutorial):
#!/usr/bin/env node
var filestocopy = [];
var filestocopyAndroid = [
{
"resources/android/icon/drawable-mdpi/ic_stat_notify.png":
"platforms/android/app/src/main/res/drawable-mdpi/ic_stat_notify.png"
},
{
"resources/android/icon/drawable-hdpi/ic_stat_notify.png":
"platforms/android/app/src/main/res/drawable-hdpi/ic_stat_notify.png"
},
{
"resources/android/icon/drawable-xhdpi/ic_stat_notify.png":
"platforms/android/app/src/main/res/drawable-xhdpi/ic_stat_notify.png"
},
{
"resources/android/icon/drawable-xxhdpi/ic_stat_notify.png":
"platforms/android/app/src/main/res/drawable-xxhdpi/ic_stat_notify.png"
},
{
"resources/android/icon/drawable-xxxhdpi/ic_stat_notify.png":
"platforms/android/app/src/main/res/drawable-xxxhdpi/ic_stat_notify.png"
},
{
"resources/android/icon/icon.png":
"platforms/android/app/src/main/res/icon.png"
}
];
var fs = require('fs');
var path = require('path');
var rootdir = './';
var androiddir = path.join(rootdir, "platforms/android");
var iosdir = path.join(rootdir, "platforms/ios");
if(fs.existsSync(androiddir)) {
filestocopy = filestocopyAndroid;
console.log("Android platform file recognized");
} else if(fs.existsSync(iosdir)) {
console.log("iOS platform file recognized");
filestocopy = filestocopyiOS;
} else {
console.log("Error: no Android or iOS platform file was recognized.");
filestocopy = [];
}
console.log("~~~~ Start Copying Notification Status Icons");
filestocopy.forEach(function (obj) {
Object.keys(obj).forEach(function (key) {
var val = obj[key];
var srcfile = path.join(rootdir, key);
var destfile = path.join(rootdir, val);
console.log("copying: " + srcfile);
console.log(" to: " + destfile);
var destdir = path.dirname(destfile);
if(!fs.existsSync(destdir)) {
fs.mkdirSync(destdir);
}
if (fs.existsSync(srcfile) && fs.existsSync(destdir)) {
fs.createReadStream(srcfile).pipe(
fs.createWriteStream(destfile));
}
});
});
console.log("~~~~ End Copying Notification Status Icons");
Basically, this script copies the right folders into the newly generated platforms/android/app/src/main/res folder
.
As long as this hook runs properly, everything should work fine!
Answered By - Reyedy
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.