invertase / notifee

βš›οΈ A feature rich notifications library for React Native.
https://notifee.app
Apache License 2.0
1.76k stars 201 forks source link

Android: Fullscreen notification bypasses lockscreen and presents entire app (Incoming Calls) #501

Closed frozencap closed 1 year ago

frozencap commented 1 year ago

Hi everyone and thanks to the authors for open-sourcing and maintaining this

Use case: Incoming Call on Lock Screen.

After this exact sequence 1- killing the app 2- awakening it with server-sent high importance notification below 3- dismissing the notification 4- locking the screen 5- resending the same notification

The notification bypasses lockscreen and just opens the app on top of it, every time, without entering passcode, with full access to the app (but not past the lock screen). Seems like a big footgun.

Is this a bug or a feature ?

More generally: Is it possible today with notifee to get basic Incoming Call notifications going? With similar behavior users expect: turns on lock screen, occupies it full screen and displays/vibrates/rings until interacted with.

mainComponent sounds like a good lead but it isn't quite clear in the docs what it can or cannot do (props? navigate back to main app?)

const displayCallNotificationAndroid = async ({
  callId,
  callerName,
  hasVideo,
}: {
  callId: string;
  callerName: string;
  hasVideo: boolean;
}) => {
  console.log('πŸ“ž πŸ“₯  displayCallNotificationAndroid: ', callId);

  const channelId = await notifee.createChannel({
    id: 'nugget-calls',
    name: 'nugget-calls',
    importance: AndroidImportance.HIGH,
  });

  const dnr = await notifee.displayNotification({
    title: callerName,
    body: `is calling you on ${hasVideo ? 'video' : 'voice'}...`,
    id: callId,
    android: {
      channelId,
      smallIcon: 'ic_launcher_round',
      color: '#dedede',
      category: AndroidCategory.CALL,
      importance: AndroidImportance.HIGH,
      fullScreenAction: {
        id: 'default',
      },
      actions: [
        {
          title: 'Decline',
          pressAction: {
            id: 'decline-call',
          },
        },
        {
          title: 'Answer',
          pressAction: {
            id: 'answer-call',
          },
        },
      ],
      lightUpScreen: true,
      // asForegroundService: true,
      colorized: true,
    },
  });
  console.log('πŸ”­ displayNotification result: ', dnr);
};
Samsung s10e 
Android 12
compileSdkVersion = 31
"react-native": "^0.68.0",
"@react-native-firebase/app": "^13.0.1",
"@react-native-firebase/messaging": "^13.0.1",
"@notifee/react-native": "^5.4.1",

Thanks!

frozencap commented 1 year ago

Not sure what kind of work this would entail, but an Incoming Call UI as described above would fill a massive, gaping void in the ecosystem. Basically all calling apps need this, and there is no credible js-only solution

Even react-native-callkeep does not solve this, as the native call UI on Android doesn't work on all devices (?). It is left for us to build:

When showIncomingCallUi is fired, you must show an incoming call UI. This would be a high priority notification

Sounds like notifee is on the cusp of filling that void, but 1- launchActivity requires writing native and 2- docs are unclear wrt purpose/behavior/usage of mainComponent (as mentioned above)

If this is just a docs issue, and mainComponent actually addresses this use case, I will 100% be making a PR to the docs if someone can explain to me how it is used.

Otherwise I guess this is a Feature Request :)

Community packages proving the pain point/blind spot

https://github.com/bharathselva28/react-native-incoming-call-android https://github.com/linhvovan29546/react-native-full-screen-notification-incoming-call https://github.com/bkdev98/react-native-incoming-call#readme

mikehardy commented 1 year ago

This is vague, my apologies in advance, but I believe some people are using notifee to handle incoming calls. How it interacts with the lock screen, I'm not sure.

Is this the gap you are talking about?

The notification bypasses lockscreen and just opens the app on top of it, every time, without entering passcode, with full access to the app (but not past the lock screen). Seems like a big footgun.

Is there anything else? I think it is either a docs issue, or perhaps a minor missing bit where we can grant some indication of whether the screen is locked or not so you can handle navigation differently in the "received a call on a locked phone" case, similar to people handling navigation differently in the "app is open but user is not logged in" case, with different navigation sets

frozencap commented 1 year ago

Hm did not think of that, since it's still just the app being presented, you could just use getInitialNotification to route navigation on mount. We would then be missing like you mentioned an un/locked flag, but also a means to close the fullscreened notification/app to go back to the lockscreen.

However I still think that's a foot gun. I may be totally wrong but I don't think it's expected behavior that a full screen notification just opens your app passed the lock screen.

An actual fullscreen notification UI element, with the same semantics as all other notifications would be much more intuitive imho wrt separation of concerns. In fact that's pretty much what the wording in the docs seems to indicate, that notifee has a physical/native "full screen notification"

You may want to display a full-screen notification for time-sensitive, urgent notifications. For example, an ongoing alarm or an incoming call. Full-screen actions have the same properties as press actions

Is there such a thing or are we in fact talking about the actions on the non-fullscreen, heads-up state of the fullscreen notification (that android renders if device is open)? Because the only fullscreen I get, is the app itself when it bypasses device lock, which obviously doesn't have any of the notifee press actions.

Also what does mainComponent do?

frozencap commented 1 year ago

Turns out getInitialNotification returns null when the app is loaded as a fullscreen notification (it doesn't return itself). Resorted to passing a flag in data to loop thru getDisplayedNotifications.

The solution is def the one you mentioned, to

grant some indication of whether the screen is locked or not

alexander01202 commented 1 year ago

Hello. I am having a problem using this fullscreen notification. I have set mine but it just shows up as a normal notification. I have properly edited my androidManifest.xml and it shows... But it still doesn't send a full screen notification... This is my code:

const channelId = await notifee.createChannel({
      id: 'default',
      name: 'Default Channel',
    });
    notifee.displayNotification({
        // title: 'Notification Title',
        body: 'Full-screen notification',
        android: {
            channelId,
          // Recommended to set a category
          category: AndroidCategory.CALL,
          // Recommended to set importance to high
          importance: AndroidImportance.HIGH,
          fullScreenAction: {
            id: 'default',
          },
        },
    });

Please is there anything I'm doing wrong?

frozencap commented 1 year ago

AFAICT android only displays it fullscreen when the phone is locked/closed

mikehardy commented 1 year ago

That's my experience with whatsapp at least as well - only fullscreen if locked/closed

frozencap commented 1 year ago

mikehardy, would the lockscreen check be something that you guys would consider integrating into notifee? It's really the only piece missing for the Incoming Call feature if we use this approach

If so, is there perhaps a means to place a bounty on this feature to speed things up?

I'd also be willing to try my hand at writing the native module myself but I've never written Android. If you don't think the feature itself is all that complicated, I may just give it a shot πŸ˜„ along with a nice PR to the docs

alexander01202 commented 1 year ago

So are you saying I can only do fullscreen while listening for background notification and displaying it using notifee?

mikehardy commented 1 year ago

So are you saying I can only do fullscreen while listening for background notification and displaying it using notifee?

Careful with the terms! "notification" is easily confused as the term is overloaded. Let's use:

"FCM" / "Cloud Message" - this is a block of JSON from a server to the device, could contain anything "notification" (or "notification FCM") - this is an FCM *that contains a notification block" "mixed content message" - this is an FCM with notification and data block "data-only message" - this is an FCM with no notification block, just data.

That's important because you have to be able to speak accurately/precisely in order to test and offer advice on delivery reliability expectations.

In this case I think you mean a data-only message? If that's the case then yes, I think you are right (though @shawarmaz has more recent testing here...) and it should be reliable on android. But not iOS, you'll need a notification extension handler there and to use a "notification FCM"

You can see how if you say "background notification" it's confusing, is that data-only? Does it have a notification block? The answers to those questions could go either way and would result in maybe unreliable advice for iOS

mikehardy commented 1 year ago

mikehardy, would the lockscreen check be something that you guys would consider integrating into notifee? It's really the only piece missing for the Incoming Call feature if we use this approach

Absolutely, that's really useful in combination with intentional / intended support for this use case

If so, is there perhaps a means to place a bounty on this feature to speed things up?

Not sure that would actually help, I think we're all about 300% utilized at the moment :laughing: - along with you I'm sure

I'd also be willing to try my hand at writing the native module myself but I've never written Android. If you don't think the feature itself is all that complicated, I may just give it a shot smile along with a nice PR to the docs

It looks trivial as a bit of code - https://stackoverflow.com/a/8668648/9910298

The hard part will be to implement it well here. I think this belongs in the core library as a feature really, then with react-native wrapping it.

@helenaford if you could wave a wand and say: "drop a boolean method right here in android/.... and then call it from right here in packages/react-native/... where would you put them?

alexander01202 commented 1 year ago

@mikehardy does notifee listen for onesignal notifications? I am using onesignal to send notifications and I can't see any way in the docs to handle to onesignal notifications. Or does the docs still apply when using onesignal? Do you understand what I'm saying?

mikehardy commented 1 year ago

This still feels like imprecise language, so I am not sure I understand.

OneSignal documents their setup as requiring a Firebase FCM setup step for Android: https://documentation.onesignal.com/docs/mobile-sdk-setup#android (and APNS push certificate on iOS)

Technically, it's important to understand that each vendor (android/google, iOS/apple, android/huawei) has one way to send cloud messages to a device. And everyone else just funnels into that.

For Android, that's FCM. For iOS that's APNS. For Huawei it's HMS (or whatever they call it now, important part is that it's one way)

So here's the thing - it doesn't matter what vendor you are using to generate the cloud message. In the end they will be sending a message that follows the format of the system cloud messaging service. For Android that's FCM

At that point, you can refer back to my definitions above, or read the google upstream docs on FCM.

Now, does Notifee listen for those? Notifee listens for local on-device notification events. So anything that posts an actual user-visible notification should trigger a notifee event. Notifee does not listen for cloud messages then. Just the notifications that may be triggered by them, if that makes sense? It's the second step / side effect of sending a cloud message with a notification block

@react-native-firebase/messaging listens for the actual incoming cloud message, and if it's a data-only message, you'll get the background handler called.

Hopefully that all makes sense

helenaford commented 1 year ago

@shawarmaz if I'm following correctly, you only want a limited view of the app if the device is locked? What is the proposed solution in regard to:

mikehardy, would the lockscreen check be something that you guys would consider integrating into notifee? It's really the only piece missing for the Incoming Call feature if we use this approach

Would this be a API endpoint like notifee.isLocked() ? (cc @mikehardy )

I think you could use a different activity or mainComponent to achieve your overall goal of only showing a limited view of your app when someone rings.

mikehardy commented 1 year ago

Could definitely use a different activity, but then you have a native code requirement on android, whereas a notifee.isLocked() would allow for pure javascript solutions / nav subsets.

frozencap commented 1 year ago

That's a workable option for sure.

Dispatching un/locked events is another, if possible and maybe safer (avoids stale values). That way we could just wrap it in a hook in declarative react fashion

EDIT: I guess either way you still need to get the value imperatively at some point, so event listeners would just be complimentary.

Thanks for the quick turnarounds, you guys are great

@helenaford

mikehardy commented 1 year ago

event listeners are also possible - just a technical note - on android at least. You listen for the system dispatch of some combination of these intents via an intent filter to maintain a state diagram:

        intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
        intentFilter.addAction(Intent.ACTION_SCREEN_ON);
        intentFilter.addAction(Intent.ACTION_USER_PRESENT);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
        }

I'm not saying this is what we want to do, but it is technically possible. For my part, if we support full screen notifications, and the behavior is different when the screen is locked/unlocked, this seems like something to support. At the system level, the behavior / APIs here have been really stable for years (I've used them for about 3 personally) so it actually seems easier versus the constant churn that is notification display options and permissions...

frozencap commented 1 year ago

Definitely looking forward to this, our workaround is super flaky. I think this could even be released standalone, as of today there is no lib solving this in react-native land.

frozencap commented 1 year ago

Also @helenaford mentioned mainComponent for this use case. For completeness's sake, what exactly is mainComponent used for? I've managed to display it, but haven't been able to get it to integrate with/navigate to the rest of my app. Maybe there's a nugget in there that can help with Incoming Calls

mikehardy commented 1 year ago

With apologies, this is not a use case of mine and I am on a strict deadline for a project that's incredibly important to me. I won't have any time to dedicate to an actual working implementation. I've shared everything that I know about the "how to do it", the likely "where to do it".

https://notifee.app/react-native/reference/notificationpressaction#maincomponent https://notifee.app/react-native/docs/android/interaction#advanced-custom-component

The documentation (I just read it) appears to cover it. I believe it would be a completely separate set of components loaded just for the notification, as Helena mentioned up above if I am remembering correctly

With apologies I just set up the task board for the week and realize I'm a week behind, so I won't be able to collaborate on this unless further for a while

frozencap commented 1 year ago

Apologies appreciated but entirely unnecessary, the fact you guys are even answering like you are is outstanding.

Many thanks for your continued contributions

frozencap commented 1 year ago

So have been at this for over 2 weeks. On top of the original issue which is a massive security footgun, there is also no way to close the activity once it's been opened (short of closing app itself or using BackHandler.exitApp()). We've tried every permutation of launchActivityFlags possible to achieve this behavior to no avail.

Our exhaustively tested conclusion is notifee can not be used for Incoming Calls.

Hopefully this will be addressed in the future. In the meantime we will most likely use a react-native-callkeep fork.

mikehardy commented 1 year ago

Interesting - thanks for the analysis. For us, incoming calls is a useful but low-percentage case, so it is not something that we or others are likely to pour a lot (or any ?) time into. Which is another way of saying, that if there were some roadmap proposed that closes whatever feature gaps exist, and there were PRs, we'd merge them, but I want to manage expectations around the "will be addressed in the future" sentiment - that would be nice but I think it will need contribution from an interested party

frozencap commented 1 year ago

Makes sense -- don't want to spread resources too thin. Our team does not have Android experience, but if the callkeep implementation doesn't end up working, we will be contracting an Android engineer to bridge this gap in notifee.

pierguinzani commented 1 year ago

@shawarmaz I had some issues with callkeep and have been working with notifee to solve this problem. In my case, I created a custom activity - CustomActivity.java in android/app/java/com/MyApp :

package com.myapp;

import com.facebook.react.ReactActivity;

public class CustomActivity extends ReactActivity {
  @Override
  protected String getMainComponentName() {
    return "custom";
  }
}

Next, I created a simple incoming call notification with notifee:

        title: '(21) 1234-1234',
        body: 'Incoming call',
        android: {
            channelId: 'call',
            category: AndroidCategory.CALL,
            visibility: AndroidVisibility.PUBLIC,
            importance: AndroidImportance.HIGH,
            smallIcon: 'myapp_icon',
            timestamp: Date.now(),
            showTimestamp: true,
            pressAction: {
                id: "default",
                launchActivity: 'com.myapp.CustomActivity',
            },
            actions: [{
                title: "Accept",
                pressAction: {
                    id: "accept",
                    launchActivity: 'default',
                }
            }, {
                title: 'Decline',
                pressAction: {
                    id: "reject",
                }
            }],
            fullScreenAction: {
                id: 'default',
                launchActivity: 'com.myapp.CustomActivity',
            },
        },

The fullScreenAction, which calls a customActivity, is an important part of this implementation.

And then, I needed to register this component in my index.js:

import { AppRegistry } from 'react-native';
import React from 'react';
import App from './src';
import IncomingCall from './src/screens/IncomingCall';

AppRegistry.registerComponent(appName,  App);

AppRegistry.registerComponent('custom', IncomingCall); //A custom component with two buttons to attend and decline the incoming call

I also configured my AndroidManifest.xml this way:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.myapp">

    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />
    <uses-feature android:name="android.hardware.audio.output" />
    <uses-feature android:name="android.hardware.microphone" />

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- Permission configs -->
    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL" />
    <uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
    <uses-permission android:name="android.permission.READ_CALL_LOG" />
    <uses-permission android:name="android.permission.USE_SIP" />
    <!-- Xiaomi and similar devices overlay configs -->
    <uses-permission android:name="android.permission.ACTION_MANAGE_OVERLAY_PERMISSION" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

    <application
      android:name=".MainApplication"
      android:label="@string/app_name"
      android:icon="@mipmap/ic_launcher"
      android:roundIcon="@mipmap/ic_launcher_round"
      android:allowBackup="false"
      android:theme="@style/AppTheme">
      <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
        android:launchMode="singleTask"
        android:windowSoftInputMode="adjustResize"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
      </activity>
      <activity
        android:name="com.myapp.CustomActivity"
        android:showWhenLocked="true"
        android:turnScreenOn="true"
        android:launchMode="singleTop"
        android:showOnLockScreen="true"
      />
    </application>
</manifest>

This part will probably solve your problem because you will give permission to show only the custom component (Incoming Call) on the locked screen.

<activity
        android:name="com.myapp.CustomActivity"
        android:showWhenLocked="true"
        android:turnScreenOn="true"
        android:launchMode="singleTop"
        android:showOnLockScreen="true"
      />
frozencap commented 1 year ago

@pierguinzani thanks a ton for taking the time to write this up, by the looks of it you may have just saved our feature πŸ˜„

Before I get to testing this out (not at desk atm), could you describe how you then switch Activities (from custom component to App ), while ensuring that the passcode lockscreen gets presented in between?

frozencap commented 1 year ago

@pierguinzani just spent many hours trying to get the steps to work, keep getting

09-19 02:53:14.205 18719 19667 E NOTIFEE : (ReceiverService): Launch Activity for notification does not exist ('com.myappco.myapp.IncomingCallActivity').
09-19 02:53:14.207 18719 19667 E NOTIFEE : (NotificationManager): Launch Activity for full-screen action does not exist ('com.myappco.myapp.IncomingCallActivity').

are these in any way related to bundle identifier? because ours differ per env (.dev or .staging suffices) Otherwise we tried a bunch of other stuff (e.g. .IncomingCallActivity without the package before like .MainActivity) Any suggestions ?

pierguinzani commented 1 year ago

@pierguinzani thanks a ton for taking the time to write this up, by the looks of it you may have just saved our feature πŸ˜„

Before I get to testing this out (not at desk atm), could you describe how you then switch Activities (from custom component to App ), while ensuring that the passcode lockscreen gets presented in between?

@shawarmaz It's simple. See I have two activities in my AndroidManifest.xml: android:name="com.myapp.CustomActivity " and android:name=".MainActivity ", but only my first one has the permissions to show on the locked screen. So, when you call BackHandler.exitApp() on your IncomingCallScreen (locked screen) the device will ask for password to show the AppScreen (mainComponent)

pierguinzani commented 1 year ago

com.myapp

@shawarmaz You need to replace com.myapp with your package name

frozencap commented 1 year ago

@pierguinzani yeah that much was obvious πŸ˜„

the issue on my side was the path for the Activity: android/app/java/com/MyApp

I had to stick it in android/app/src/main/java/com/MyApp (I suppose since we're using multiple build types?)

Wrapping the feature up right now, fingers crossed there will be no surprises, but happy to say the approach is working so far πŸ₯³

If everything goes well I'll do a PR to the docs for Incoming Calls cause this is πŸ”₯

Thanks again to everyone

mikehardy commented 1 year ago

If everything goes well I'll do a PR to the docs for Incoming Calls cause this is

Really hope the feature works for you, and some docs on how to do it would be a major advance in the react-native ecosystem, full screen notifications for this kind of case (also useful for alarm clocks etc...) will be frontier / leading-edge stuff for the ecosystem :crossed_fingers:

abdoutech19 commented 1 year ago

@shawarmaz Hello mate, thanks for all these insights in this thread and all the other related threads. I'm trying to implement an incoming call screen just like you are, after implementing @pierguinzani's solution I managed to open a custom activity when I press on the full-screen notification, but the behavior I want is for the activity to be auto-opened, and that's not what I'm currently getting, it's just a normal notification that opens a custom activity when pressed. So I'm wondering if it's the same behavior you get too or if the notification fills the entire screen automatically? Thanks in advance.

pierguinzani commented 1 year ago

@shawarmaz Hello mate, thanks for all these insights in this thread and all the other related threads. I'm trying to implement an incoming call screen just like you are, after implementing @pierguinzani's solution I managed to open a custom activity when I press on the full-screen notification, but the behavior I want is for the activity to be auto-opened, and that's not what I'm currently getting, it's just a normal notification that opens a custom activity when pressed. So I'm wondering if it's the same behavior you get too or if the notification fills the entire screen automatically? Thanks in advance.

Hi @abdoutech19. In my case, I have 3 different behaviours:

Check if your app has the same behaviours.

abdoutech19 commented 1 year ago

@pierguinzani Thanks for your response. I'm having the exact same behavior now, the issue is with the app's permissions, in order to be able to open a full-screen notification you need to have the SYSTEM_ALERT_WINDOW added to AndroidManifest.xml, not only that but I also had to manually toggle the Show as pop-up setting in apps> myApp> Notifications> channel-name > Show as pop-up. Which is not ideal cuz I can't seem to find a way to request this permission from within my app, any idea ?

pierguinzani commented 1 year ago

@pierguinzani Thanks for your response. I'm having the exact same behavior now, the issue is with the app's permissions, in order to be able to open a full-screen notification you need to have the SYSTEM_ALERT_WINDOW added to AndroidManifest.xml, not only that but I also had to manually toggle the Show as pop-up setting in apps> myApp> Notifications> channel-name > Show as pop-up. Which is not ideal cuz I can't seem to find a way to request this permission from within my app, any idea ?

If you're using a pure Android device you don't need this permission. For me works normally. But if you're using a Xiaomi/Similar device you can get this permission with this library: https://github.com/avodevelopment/rn-android-overlay-permission

abdoutech19 commented 1 year ago

@pierguinzani Yes indeed you're right the SYSTEM_ALERT_WINDOW permission is not needed, but Show as pop-up switch still has to be toggled manually for it to work, was this setting automatically toggled in your device you didn't have to do it manually?

pierguinzani commented 1 year ago

@pierguinzani Yes indeed you're right the SYSTEM_ALERT_WINDOW permission is not needed, but Show as pop-up switch still has to be toggled manually for it to work, was this setting automatically toggled in your device you didn't have to do it manually?

There is no way to get this permission automatically, only manually.

frozencap commented 1 year ago

@abdoutech19 what device / OS is it failing on specifically? I tested on 2 Xiaomi phones, one running Android One, the other running MIUI 11 and 12, and have not encountered this issue yet. Would be good to know on which setups it doesn't work to handle errors.

abdoutech19 commented 1 year ago

@shawarmaz I'm testing on Samsung A50 and moto e40.

frozencap commented 1 year ago

@abdoutech19 I have it working on Samsung A52 as well as a whole swath of devices, without having to manually toggle the setting you guys are talking about.

Could you confirm you're getting this bug on Samsung A50 using latest version of notifee?

Could also be the Android version. Which version are you on?

frozencap commented 1 year ago

I'm just wrapping up a release for my app and will get to writing an article on Incoming Calls with notifee based on @pierguinzani's suggestion

I'm getting another unintended behavior tho: a blank screen before the Activity renders the react-native component (IncomingCall.Screen)

Could this be a splash screen issue where RNBootSplash/react-native-splash-screen would need to be configured to work with this new Activity?

EDIT: updated Incoming Call Activity according to RNBootSplash

import android.os.Bundle;
import com.facebook.react.ReactActivity;
import com.zoontek.rnbootsplash.RNBootSplash;

public class IncomingCallActivity extends ReactActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    RNBootSplash.init(this); // <- initialize the splash screen
    super.onCreate(savedInstanceState); // or super.onCreate(null) with react-native-screens
  }

  @Override
  protected String getMainComponentName() {
    return "incoming_call";
  }
}

Still getting the blank screen; any suggestions?

itstaranarora commented 1 year ago

@pierguinzani Thanks for this code snippet. Now I can open custom activity when the device is locked! But I'm not able to figure out how to get notification data in IncomingCall component and how I can close this activity when user rejects the call. Can you help?

anirudh-antino commented 1 year ago

For some of you the activity might not appear on the lock screen and that’s because of your phone, not all phones allow full screen intents by default. I have a Xiaomi and it’s not enabled by default.

To enable it you have to go to the app configuration -> Other permissions -> Show On Lock screen.

anirudh-antino commented 1 year ago

@pierguinzani Thanks for this code snippet. Now I can open custom activity when the device is locked! But I'm not able to figure out how to get notification data in IncomingCall component and how I can close this activity when user rejects the call. Can you help?

notifee.onBackgroundEvent(async ({ type, detail }) => { console.log(detail) });

mikehardy commented 1 year ago

@anirudh-antino interesting, unfortunately the behavior of Xioami is pretty shameful here, there is no evidence I can find that documents this stuff at all: https://stackoverflow.com/search?q=miui+show+on+lock+screen+permission

emuter commented 1 year ago

@shawarmaz

package com.myapp;

import com.facebook.react.ReactActivity;

public class CustomActivity extends ReactActivity {
  @Override
  protected String getMainComponentName() {
    return "custom";
  }
}

which folder did you place this activity in

im not able to launch this with an expo managed project with dev client. do you have any clues to how i could prevail with expo.

github-actions[bot] commented 1 year ago

Hello πŸ‘‹, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

wardbeyens commented 1 year ago

will get to writing an article on Incoming Calls with notifee based on @pierguinzani's suggestion

Please do, I am working on an alarm where the user has to execute something immediately and through this thread, it will probably work!

Thank you all!

PS: I love Notifee and will use it in future projects, but sometimes on advanced concepts the docs are indeed not super clear. And then it does indeed take days to figure it out.

github-actions[bot] commented 1 year ago

Hello πŸ‘‹, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

wiltonmaddams commented 11 months ago

that the passcode lockscreen gets presented in between?

Thanks so much for your code examples and help here, @pierguinzani ! I too am very curious how to switch activities automatically as my goal is to show the user an incoming call screen in the custom activity opened by the full screen notification and in that component show buttons like "accept" or "decline". When the user taps "decline", BackHandler.exitApp() does fine to close the activity, but when the user taps "accept", I'm not sure how to close the current (custom) activity, present the keyguard, and then open the main (default) activity afterwards? From your response it seems that it's matter of setting the properties on the different activities in the Manifest but I don't see how that alone would do it? I've tried but nothing happens. Pseudo-coding here, it almost seems like I would need something in my component like:

<Button onPress={() => {
   CustomModule.presentKeyguard().then(() => 
     BackHandler.exitApp();
     CustomModule.startMainActivity(); ??
   );
})>Accept</Button>

Sorry I'm sure there's plenty of reasons why that pseudocode would never work, my native Android is almost non-existent so it's more an expression of my goals.