capacitor-plugins icon indicating copy to clipboard operation
capacitor-plugins copied to clipboard

feat: capacitor localnotification image is not showing

Open armanhadifatah opened this issue 5 years ago • 14 comments

Bug Report

Latest Dependencies:

@capacitor/cli: 1.4.0

@capacitor/core: 1.4.0

@capacitor/android: 1.4.0

@capacitor/ios: 1.4.0

Affected Platform(s)

I tested it on Android and web also

  • [x] Android
  • [ ] iOS
  • [ ] Electron
  • [x] Web

Current Behavior

when showing notification no image is shown in the notification

Expected Behavior

when adding url and id to attachments it should show image in notification

Sample Code or Sample Application Repo

 LocalNotifications.schedule({
      notifications: [
        {
          title: "aaaa",
          body: "Body",
          id: 1,
          actionTypeId: 'OPEN_PRODUCT',
          attachments: [
            { id: 'face', url: 'https://khanoo.com/wp-content/uploads/estate_images/house/77-1576179614/230174.jpg' }
          ],
          schedule: {
            every: "minute"
          },
         
          extra: null
        }
      ]
    });

Reproduction Steps

Just test my code which i provided to see if you can see image or not

Other Technical Details

npm --version output: 6.13.4

node --version output: v12.13.1

pod --version output (iOS issues only): 1.9.0.beta.2

armanhadifatah avatar Jan 04 '20 11:01 armanhadifatah

http/https urls are not supported by iOS (native API limitation)

on Android and Web the attachments are not shown as images, should be implemented

jcesarmobile avatar Jan 16 '20 18:01 jcesarmobile

i think attachments is not work for android.... for android you can use "largeIcon:" property to show your image first copy your image in res/drawable folder (not in 'res' only) and then write the name of your image in largeIcon........for example: i copy my 'manager.png' in 'android\app\src\main\res\drawable' then in my code: LocalNotifications.schedule({ notifications: [ { title: 'the title', body: 'msg body', id: 1, largeIcon:'manager', smallIcon:'manager' } ] }); it's look small but i think it much better than nothing.....

malekian78 avatar Oct 17 '21 05:10 malekian78

If someone wants to show big image with notification then you need to add this code at line 185 in LocalNotificationManager.java:

if (localNotification.getAttachments() != null) {
  mBuilder.setStyle(
    new NotificationCompat.BigPictureStyle()
      .bigPicture(localNotification.getBigImage(context))
    );
}

And this code at line 386 in LocalNotifications.java:

import android.net.Uri;
...
public Bitmap getBigImage(Context context) {
  if (attachments != null && attachments.size() > 0) {
    try {
      LocalNotificationAttachment bp = attachments.get(0);
      String bpUrl = bp.getUrl();
      final AssetUtil assets = AssetUtil.getInstance(context);
      Uri uri = assets.parse(bpUrl);
      if (uri != Uri.EMPTY) {
        return assets.getIconFromUri(uri);
      }
    } catch (Exception e){
      e.printStackTrace();
    }
  }
  return null;
}

And also you need to fix a bug in a capacitor file node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/plugin/util/AssetUtil.java at line 328:

change from

String authority = context.getPackageName() + ".provider";

to

String authority = context.getPackageName() + ".fileprovider";

And at line 106:

change from

String resPath = path.replaceFirst("file:/", "www").replaceFirst("\\?.*$", "");

to

String resPath = path.replaceFirst("file:/", "public").replaceFirst("\\?.*$", "");

Then these links (url: 'file://assets/notifications/preview.jpg') will work in your javascript scheduling code:

{
    id: 666,
    largeIcon: bigIcon,
    schedule: { at: rem },
    title: title,
    body: text,
    largeBody: text,
    attachments: [{ id: 'my_preview', url: 'file://assets/notifications/preview.jpg' }]
}

Also that plugin architecture is too ill-considered and I see error !!! FAILED BINDER TRANSACTION !!! when load standard images that worked fine with katzer plugin.

In order to fix somehow, I added compression in capacitor file node_modules/@capacitor/android/capacitor/src/main/java/com/getcapacitor/plugin/util/AssetUtil.java at line 259:

InputStream stream = context.getContentResolver().openInputStream(uri);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
return BitmapFactory.decodeStream(stream, null, options);

Instead of that:

InputStream input = context.getContentResolver().openInputStream(uri);
return BitmapFactory.decodeStream(input);

P.S.: But bigImage should be no more then 512x256 and largeIcon no more then 256x256

ivanov84 avatar Jan 10 '22 16:01 ivanov84

for android you can use "largeIcon:" property to show your image first copy your image in res/drawable folder (not in 'res' only) and then write the name of your image in largeIcon.

Is there any way to use a base64 encoded image from a variable instead? I'd like to display a profile picture as largeImage that was previously uploaded by the user and stored in Vuex as a bas64 encoded string.

frederikheld avatar Feb 16 '22 15:02 frederikheld

@frederikheld yes. Just edit the source code like I did for bigImage.

ivanov84 avatar Feb 22 '22 11:02 ivanov84

So I need to fork the repo and build my own version of the plugin you say? That's something I tried to avoid tbh because I'm not that much into Java. Would you care to submit your code as a PR to this repo in order to fix the issue / add this feature?

frederikheld avatar Feb 22 '22 14:02 frederikheld

@frederikheld I edited code directly in node_modules.

All you need - it's just pass base64 string via any property and convert it with java code:

byte[] decodedString = Base64.decode(base64ImageString, Base64.DEFAULT);
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
return decodedByte;

ivanov84 avatar Feb 22 '22 21:02 ivanov84

Editing the code directly in node_modules is the worst advice you could give to anyone who tries to write software on a level that is above script kiddie 😖 How would you deal with updates? How would you make that portable? How would you make it reproducible? The whole point of packaging systems like npm is to only share a list of well defined dependencies which makes it easy to update, move around and reproduce. Fiddling around in node_modules breaks all of this...

frederikheld avatar Feb 22 '22 22:02 frederikheld

But apart from that: your code only needs some if clause that checks what image format is incoming in order to make it compatible with the current source, then you could submit it as a pull request so it could go into the package in the regular way. I would appreciate that very much!

frederikheld avatar Feb 22 '22 22:02 frederikheld

@frederikheld I am entrepreneur and I need that things works. Then I look at revenue. I just said how to make things work. I really want to make PR but I have no time...

ivanov84 avatar Feb 23 '22 21:02 ivanov84

Is there any sensible progress on this issue?

alexd2580-sf avatar Oct 18 '22 01:10 alexd2580-sf

I am entrepreneur and I need that things works. Then I look at revenue. I just said how to make things work.

Doesn't look like a good strategy to generate long-term revenue tbh. Beware of the day when all of this falls on your feet and you're in full fire fighting mode :-P But you do you ...

@alexd2580-sf: I'm currently working on a different project, but if I get back to this one, I might submit the PR. But can't say how long until then, so if you need it, go ahead ;-)

frederikheld avatar Oct 18 '22 14:10 frederikheld

How would you deal with updates? How would you make that portable? How would you make it reproducible?

Actually, there's an easy way with e.g. pnpm, you have the patch command. So you can make changes to modules that get applied as a patch every time (reproducible) even with updates, yet are stored locally in your project (portable).

Erudition avatar May 10 '23 02:05 Erudition

Any news here?

MarcelSchuermann avatar Apr 28 '24 19:04 MarcelSchuermann