Open schoettler opened 8 years ago
Second! Just looking for a way to do this too.
+1
I can't figure out a way to display an icon on my received push notifications.
+1
I use phonegap-plugin-push
plugin https://github.com/phonegap/phonegap-plugin-push for push notifications
I generate "old" icons with ionic resources
command even if I don't use ionic in my project at all.
After that I generate a new png with a new name with this tool: http://romannurik.github.io/AndroidAssetStudio/icons-notification.html and paste all the generated folders in the platforms/android/res
folder with the "merge" options. The notification icon must have a different name, not icon.png
and when I init the push plugin I use the name of my new file here:
"android": {
senderID: vv.params.googleGCMProjectNumber,
icon: "ic_stat_icon_material",
iconColor: "grey"
},
and the large icon from the JSON sent as push:
"GCM": {
title: "Large Icon",
message: "Loaded from drawables folder",
image: "icon"
}
where icon
is the name of the file generated by ionic.
Tested on two devices so far. Works fine.
+1
+1
+1
+1
+1
+1
Here is a solution
#!/usr/bin/env node
var fs = require('fs');
var path = require('path');
var inputFolder = path.join(__dirname, '../../', 'resources/android/push_icon/');
var outputFolder = path.join(__dirname, '../../', '/platforms/android/res/');
console.log('------------------------------------------------------------------------------------------');
console.log("Running hook: "+path.basename(process.env.CORDOVA_HOOK));
console.log('------------------------------------------------------------------------------------------');
fs.readdir(inputFolder, function(err, list) {
list.forEach(function(file){
if (file.indexOf('drawable') === 0) {
var destFolder = file.replace('-icon.png','');
fs.createReadStream(inputFolder+file)
.pipe(fs.createWriteStream(outputFolder + destFolder + '/notify.png'));
console.log('# ' + file + ' --> ' + destFolder);
}
});
console.log('-----------------------------------------------------------------------------------------');
});
+1. please let us know if you consider the feature valuable, so maybe someone from community will send a PR for that
If you're unfamiliar with the context: in Android 5.0+, push notification icon has to be two-color: transparent background + white foreground; otherwise the default app icon is taken, and anything non-transparent is displayed as white (so very likely, the user will see a white square)
Now, to prevent that, you can have a separate icon only for push notifications, and pass that name to the cordova push plugin.
I'm for now using a combination of solutions from @adyz and @awebdeveloper i.e. generate icons via a website, commit them to git to a custom folder, then copy the images to platform/android/res
in a hook.
+1
+1
+1
+1
For anyone here for ionic2, you can:
Put your icons in resources/android/ic_notification/
. It should look like this:
- resources/android/ic_notification/drawable-hdpi-v11/ic_notification.png
- resources/android/ic_notification/drawable-hdpi/ic_notification.png
- resources/android/ic_notification/drawable-mdpi-v11/ic_notification.png
- resources/android/ic_notification/drawable-mdpi/ic_notification.png
- resources/android/ic_notification/drawable-xhdpi-v11/ic_notification.png
- resources/android/ic_notification/drawable-xhdpi/ic_notification.png
- resources/android/ic_notification/drawable-xxhdpi-v11/ic_notification.png
- resources/android/ic_notification/drawable-xxhdpi/ic_notification.png
- resources/android/ic_notification/drawable-xxxhdpi-v11/ic_notification.png
- resources/android/ic_notification/drawable-xxxhdpi/ic_notification.png
stick this into gulpfile.js
gulp.task('ic_notification', function() {
gulp.src('./resources/android/ic_notification/**')
.pipe(gulp.dest('./platforms/android/res'));
});
Add the 'ic_notification' task to the runSequence
calls for 'build' and 'watch':
gulp.task('watch', ['clean'], function(done){
runSequence(
['sass', 'html', 'fonts', 'scripts', 'ic_notification'],
function(){
gulpWatch('app/**/*.scss', function(){ gulp.start('sass'); });
gulpWatch('app/**/*.html', function(){ gulp.start('html'); });
buildBrowserify({ watch: true }).on('end', done);
}
);
});
gulp.task('build', ['clean'], function(done){
runSequence(
['sass', 'html', 'fonts', 'scripts', 'ic_notification'],
function(){
buildBrowserify().on('end', done);
}
);
});
I think this whole process can be generalized and put into a plugin that should be included in https://github.com/driftyco/ionic-gulp-tasks.
am i the only one experiencing this but all the icons generated via http://romannurik.github.io/AndroidAssetStudio/icons-notification.html are just all white circles. i dont see my icon at all. @wli
@boyfunky notification icons are only two colors - white or transparent. The white circle implies that your icon has a circle shape. You probably want some kind of transparency so you get some kind of shape.
+1
+1
Another way to prevent notification icon to be white-transparent is to set the Target SDK to any value below 20.. (lollipop)..
Without hackery like lowering the target SDK just save the icon in 8bit Grayscale with Alpha-Channel.
I created the hook below, based on this code, that you can set as an after prepare hook
, without the need of external libraries:
#!/usr/bin/env node
var ROOT_DIR = process.argv[2];
var DIRS_TO_COPY = [{
srcDir: "resources/other/android/res/",
destDir: "platforms/android/res/"
}];
var fs = require('fs');
var path = require('path');
function copyFileSync(srcFile, target) {
var destFile = target;
//if target is a directory a new file with the same name will be created inside it
if (fs.existsSync(target)) {
if (fs.lstatSync(target).isDirectory()) {
destFile = path.join(target, path.basename(srcFile));
}
}
//console.log('copying ' + srcFile + ' to ' + destFile);
fs.writeFileSync(destFile, fs.readFileSync(srcFile));
}
function copyFolderRecursiveSync(sourceFolder, targetFolder) {
var files = null;
if (!fs.existsSync(targetFolder)) {
fs.mkdirSync(targetFolder);
}
//copy
if (fs.lstatSync(sourceFolder).isDirectory()) {
files = fs.readdirSync(sourceFolder) || [];
files.forEach(function (curSource) {
var curSourceFull = path.join(sourceFolder, curSource);
if (fs.lstatSync(curSourceFull).isDirectory()) {
var curTargetFolder = path.join(targetFolder, path.basename(curSource));
copyFolderRecursiveSync(curSourceFull, curTargetFolder);
} else {
copyFileSync(curSourceFull, targetFolder);
}
});
}
}
DIRS_TO_COPY.forEach(function (dirInfo) {
var srcDirFull = path.join(ROOT_DIR, dirInfo.srcDir);
var destDirFull = path.join(ROOT_DIR, dirInfo.destDir);
copyFolderRecursiveSync(srcDirFull, destDirFull);
});
Just create a .js
file with the above code called, for instance, my_hook.js
, and put it inside the [YOUR_PROJECT]/hooks/after_prepare/
folder (it works just like that with Ionic2
). I don't know if Ionic1
or a non-ionic cordova project will run the hook automatically, but you can add it to the config.xml
in these cases:
<hook type="after_prepare" src="hooks/after_prepare/my_hook.js" />
The hook copies all files and directories recursively inside resources/other/android/res/
(I created this folder, where I put all drawables I use, except the app icon and splash screen that are already generated by Ionic
) into platforms/android/res/
(where all drawables are put in android). I don't need to specify each file to be copied, because it will copy the entire folder.
Just make sure that the icons are in the correct directories. The utility below already does that for you (it creates a zip file with the correct folders, just paste it inside resources/other/android/res/
). You can add another directory for iOS too (in the DIRS_TO_COPY
array).
You can create a notification icon for android in https://romannurik.github.io/AndroidAssetStudio/icons-generic.html.
Don't forget that once you add these icons to the res/ folder, you need to configure the push plugin to use them:
E.g. If you have res/other/android/res/:
./drawable-hdpi/ic_notify.png
./drawable-mdpi/ic_notify.png
./drawable-xhdpi/ic_notify.png
./drawable-xxhdpi/ic_notify.png
./drawable-xxxhdpi/ic_notify.png
You'd still need need:
const cloudSettings: CloudSettings = {
'core': {
'app_id': '...'
},
'push': {
'sender_id': '...',
'pluginConfig': {
'ios': {
'badge': true,
'sound': true,
},
'android': {
'iconColor': '#343434',
'icon': 'ic_notify', <--- this is required to specify which icon to use - otherwise it will be blank.
}
}
}
};
+1
Hi Guys,
I'm having some issues, and can't seem to get the combination of images/folders and config right here to get the small icon working in the notification bar of Android - I'm simply shown a square,
In my app.js I have:
$ionicCloudProvider.init({
"core": {
"app_id": "APPIDHERE"
},
"push": {
"sender_id": "SENDERIDHERE",
"pluginConfig": {
"ios": {
"badge": true,
"sound": true
},
"android": {
"iconColor": "#00AEED",
"icon":"ic_notify"
}
}
}
});`
I can see that this config is being used, by changing "iconColor" I am able to get a little blue or red square!
Within my \android\res\drawable-resolution folders, I have the png's as generated by the AndroidAssetStudio generator tool, as white on alpha png's
What am I missing?
The folders containing the icon files need to end up here:
platforms/android/res/
Make sure your build is putting them there. I use this 'after_prepare' hook script:
#!/usr/bin/env node
var ROOT_DIR = process.argv[2];
var DIRS_TO_COPY = [{
srcDir: "resources/other/android/res/",
destDir: "platforms/android/res/"
}];
var fs = require('fs');
var path = require('path');
function copyFileSync(srcFile, target) {
var destFile = target;
//if target is a directory a new file with the same name will be created inside it
if (fs.existsSync(target)) {
if (fs.lstatSync(target).isDirectory()) {
destFile = path.join(target, path.basename(srcFile));
}
}
//console.log('copying ' + srcFile + ' to ' + destFile);
fs.writeFileSync(destFile, fs.readFileSync(srcFile));
}
function copyFolderRecursiveSync(sourceFolder, targetFolder) {
var files = null;
if (!fs.existsSync(targetFolder)) {
fs.mkdirSync(targetFolder);
}
//copy
if (fs.lstatSync(sourceFolder).isDirectory()) {
files = fs.readdirSync(sourceFolder) || [];
files.forEach(function(curSource) {
var curSourceFull = path.join(sourceFolder, curSource);
if (fs.lstatSync(curSourceFull).isDirectory()) {
var curTargetFolder = path.join(targetFolder, path.basename(curSource));
copyFolderRecursiveSync(curSourceFull, curTargetFolder);
} else {
copyFileSync(curSourceFull, targetFolder);
}
});
}
}
DIRS_TO_COPY.forEach(function(dirInfo) {
var srcDirFull = path.join(ROOT_DIR, dirInfo.srcDir);
var destDirFull = path.join(ROOT_DIR, dirInfo.destDir);
copyFolderRecursiveSync(srcDirFull, destDirFull);
});
It's a real pain to get right. And the error messaging is non-existent. Lots of trial and error.
Is just manually putting them into location not enough? Would a Gulp task do the job?
I think that the hook file does a good job in copying the files after execution but i think the real problem lies in the android firmware unable to detect the location of the icon from its root
If your only problem is with the notifications icons appearing correctly on Android, the following worked for me - take the drawable-xhdpi-icon icon (size 96x96), rename it icon.png and place it in two places:
/src/assets/img
/platforms/android/res/drawable
The drawable folder is a new folder which can be created by copying platforms/android/res/mipmap-xhdpi to platforms/android/res/drawable manually or with the aid of a hook. In your code, the local or geofence notification is referenced as follows:
smallIcon: 'res://icon',
icon: 'file://assets/img/icon.png'
If ionic cordova resources is part of the problem, you can do your own one-time setup by taking your largest icon and, with the help of a resizing tool such as resizeimage.net, create a set of icons for iOS and Android.
The Excel here https://github.com/dovk/howto_resources-folder has a list of the sizes and names of the .png files to create. You then place them in their respective resources folder just like ionic cordova resources would have done - for example in resources/android/icon, resources/ios/splash and so on.
If you do so, then ionic cordova platform add android or ionic cordova platform add ios should not be used anymore, as this also does ionic cordova resources - What you need to do is cordova platform add ... --save (without the ionic in the beginning).
I can't make this work...My recipe...
1) used https://romannurik.github.io/AndroidAssetStudio/icons-generic.html to generate the icons 2) Placed the icons in this way...(ic_notify, in white)
3) Created android_icons at hooks/after_prepare
4) Added
5) Executed ionic cordova run android
6) got an error: Running command: _/Users/marcojr/Projects/munkat/app/hooks/after_prepare/android_icons.js /Users/marcojr/Projects/munkat/app fs.js:994 binding.lstat(pathModule._makeLong(path), statValues); ^
Error: ENOENT: no such file or directory, lstat
'/Users/marcojr/Projects/munkat/app/resources/other/android/res/'_
7) Changed line 5 of the hook file from srcDir: "resources/other/android/res/" to srcDir: "resources/android/"
8) Executed ionic cordova run android
9) Got another error : Error: ENOENT: no such file or directory, mkdir 'run/platforms/android/res/'
10) Dropped the hook from the config.xml, got another error: /Users/marcojr/Projects/munkat/app/platforms/android/res/icon/drawable-hdpi-ic_notify.png:1:1: Error: O conteúdo não é permitido no prólogo. (The content is not allowed on prologue)
11) Decided to try awebdeveloper's solution. Got an error: Error: Path must be a string. Received undefined
any suggestions ?
@marcojr I recommend you not rename the files generated at https://romannurik.github.io/AndroidAssetStudio/icons-generic.html , but keep them with the same name and inside the created folders. What should be done is copying all the folders inside srcDir
to destDir
.
I defined srcDir
as resources/other/android/res/
instead of resources/android/res/
because ionic creates the icon and splashscreen inside resources/android/
and that might (possibly) cause some conflicts, or erase the contents inside this folder. You could use another folder instead of resources/other/
, but I recommend not to use resources/android/
(I'm not certain, but your last error may be because of this).
Like I said before, the contents inside srcDir
should be folders with icons, the folders names should be like drawable-hdpi
, drawable-mdpi
, and so on... The notification icon should have the same name across the folders (like ic_notif.png
, the same name for all icons, the utility in the link above (to create the icons) already does all that, creating the folders with the correct name and the icons, you just need to copy and paste it inside your srcDir
). Look at the location of my icons, their names and the folder names:
My notification icon is ic_99.png
, the other icons are for other reasons.
The hook just copy the contents inside srcDir
to destDir
, so it create those folders inside platforms/android/res/
:
First I'd recommend to use the same paths as mine to see if it works (if it works you can move your folders to another loaction and change the srcDir
path accordingly).
The only error you got that I don't know why is that with mkdir 'run/platforms/android/res/'
, it should be mkdir 'platforms/android/res/'
, I've never got this error, don't know why this happened.
I don't recommend putting the icons manually inside the platforms folder, because the hook is basically to avoid that (the platforms folder should be such that you could delete it and generate it again without doing any manual changes).
Ty, guys ! But looks like the solution provided by dovk really works and it's insanely simple !
Hey Ionic!
Would be nice if we could automatically set an icon for multiple resolutions as a custom push notification icon, as an addition to the app's icon & splash screen.