The push notification clears when the user taps on the notification to open app. However if the user goes and opens the app, the push notification is still there. How can I get rid of the notification? I can't seem to find anywhere in the documentation that addresses this.
Thanks a lot in advance
I did some digging as I too had this problem, and it looks like a bug in the Push Plugin. Basically they added the removal code to the pause event instead of the resume event.
You just have to change the code in src/android/com/plugin/gcm/PushPlugin.java
from:
#Override
public void onPause(boolean multitasking) {
super.onPause(multitasking);
gForeground = false;
final NotificationManager notificationManager = (NotificationManager) cordova.getActivity().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancelAll();
}
#Override
public void onResume(boolean multitasking) {
super.onResume(multitasking);
gForeground = true;
}
to:
#Override
public void onPause(boolean multitasking) {
super.onPause(multitasking);
gForeground = false;
}
#Override
public void onResume(boolean multitasking) {
super.onResume(multitasking);
gForeground = true;
final NotificationManager notificationManager = (NotificationManager) cordova.getActivity().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancelAll();
}
This will create a more standard behaviour, where the notifications will be removed on app resume (instead of on pause). Note though, I haven't fully tested the effects on the internal app messages yet, which may require more changes.
Related
I am using Xamarin with C#.
FirebasePushNotificationManager.Initialize(options, true);
^ this code works fine in my Android Application.cs file, I can receive notifications in Android. However, when I add this code to AppDelegate.cs in iOS, it freezes my app, meaning there's no response when I click on button or input field. But if I remove this line of code, my iOS app works.
I've Googled a lot but didn't get any luck, can someone please help me?
Following is my AppDelegate.cs code:
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
ServicePointManager
.ServerCertificateValidationCallback +=
(sender, cert, chain, sslPolicyErrors) => true;
global::Xamarin.Forms.Forms.Init();
var iosClientHandler = new NSUrlSessionHandler();
Services.HttpClientService.HttpClientHandler = iosClientHandler;
LoadApplication(new App());
//This line is causing the issue
FirebasePushNotificationManager.Initialize(options, true);
return base.FinishedLaunching(app, options);
}
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
FirebasePushNotificationManager.DidRegisterRemoteNotifications(deviceToken);
}
public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
{
FirebasePushNotificationManager.RemoteNotificationRegistrationFailed(error);
}
// To receive notifications in foreground on iOS 9 and below
// To receive notifications in background in any iOS version
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired 'till the user taps on the notification launching the application.
// If you disable method swizzling, you'll need to call this method.
// This lets FCM track message delivery and analytics, which is performed
// automatically with method swizzling enabled
FirebasePushNotificationManager.DidReceiveMessage(userInfo);
// Do your magic to handle the notification data
System.Console.WriteLine(userInfo);
completionHandler(UIBackgroundFetchResult.NewData);
}
}
Having android sdk which intercept the push notification, and has been using notification trampoline to further open the end activity. In the case of deeplink the app who uses this sdk will open the configured deeplink handler activity.
Snippet for the trampoline:
public class NotificationTrampolineReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
final PendingResult asyncResult = goAsync();
ExecutorService executor = Executors.newSingleThreadExecutor();
asycTask(executor, new Runnable() {
#Override
public void run() {
String urlStr = getStringExtra(intent, PUSH_URL);
if (urlStr != null) {
var intent2: Intent = Intent(Intent.ACTION_VIEW, Uri.parse(urlStr));
if (intent2 != null) {
intent2.addFlags(FLAG_ACTIVITY_NEW_TASK);
intent2.addFlags(FLAG_ACTIVITY_BROUGHT_TO_FRONT);
context.startActivity(intent2);
logAnalytics(intent, Message.MessageAction.OPEN);
}
}
asyncResult.finish();
}
});
}
void asycTask(ExecutorService executor, final Runnable task) {
try {
executor.execute(task);
} catch (Throwable ex) {}
}
}
The notification trampolines is not working in Android 12 anymore.
The notification trampolines is needed in the sdk to intercept the click and do something like to log analytics event; closing the notification drawer when clicking at the Action button on the notification, etc. And this sdk does not know what activities the app may configure to handle the deeplinks.
Using a dummy activity to replace the trampoline would work, but not feel right, i.e. open the activity and inside to open another one then finish this one.
When android 12 puts restriction on the notification tramoline, does it suggest a replacement for the use case like the one here? Haven't find one.
What is the suggested new solution for intercepting the push notification tap first and then open the activity?
You are better off launching an Activity directly from the Notification. The Activity could then do the analytics and figure out what Activity needs to be launched and then delegate to that. As an alternative, the launched Activity could send the broadcast Intent to your BroadcastReceiver which could do the work.
NOTE: If you launch an Activity directly from a Notification, that is not a trampoline. The trampoline occurs when you launch a Service or a BroadcastReceiver directly from the Notification and that component then launches an Activity. The idea is that the user needs to be in control of what pops onto his screen. If he taps a notification, he expects that something will appear on his screen, if your Service launches an Activity, that can happen at any time and could possibly interrupt him.
How can i use broadcast receiver/intent to open flutter android app when receive firebase message.
Implment FirebaseMessagingService and start Main activity from onMessageReceived:
public class FirebaseMsgService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
//...
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
and also in MainActivity you may want to unlock device:
public class MainActivity extends FlutterActivity {
#Override
public void configureFlutterEngine(#NonNull FlutterEngine flutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
Window window = this.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}
}
The answer provided by #Develocode777 will work until android 9. From android 10, this behavior is not allowed anymore. You can learn more about it in this page, Restrictions on starting activities from the background.
If you are planning to show a notification, and upon clicking the notification you want to open the app, then it it will work normally, but opening the app without no user interaction, not allowed in Android 10 and above.
How to Get both Notification and data when app is background in android.
When app is foreground than get both Notification and data.
But when app in background than get only data.
I want Get both Notification and data when app is background.
As i searched it's not possible.
you can pass Notification parameters to data and get them in
#Override
public void onMessageReceived(RemoteMessage remoteMessage){
createNotification(remoteMessage.getData());
}
private void createNotification(Map<String, String> data) {
....
NotificationCompat.Builder mNotificationBuilder = new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.mipmap.ic_icon)
.setContentTitle(data.get("title"))
.setContentText(data.get("body"))
}
When using Firebase Google user authentication the user is immediately logged in if they have already authorized the application and only logged in to one Google account.
Is there a way to force the "Choose an account" dialog to appear so that the user has the opportunity to login to a different Google account or create a new one?
Currency as far as I know the user has to manually logout of the current Google account (or login to > 1) from Google.com to make the dialog appear.
You can force to choose an account with 'prompt' provider parameter.
var googleAuthProvider = new firebase.auth.GoogleAuthProvider();
googleAuthProvider.setCustomParameters({
prompt: 'select_account'
});
firebase.auth().signInWithRedirect(googleAuthProvider)
Tested with Firebase JavaScript SDK v4.1.2
You should sign out from Google explicitly:
Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(status -> {
mFirebaseAuth.signOut();
});
Found the solution here
I'm trying to figure out the same thing. According to some Google documentation, it appears that you can force the account chooser with a "prompt" command (of "none", "select_account" or "consent"):
Force google account chooser
...however there appears to be no way to set the "prompt" value in any of Firebase's authentication methods (specifically authWithOAuthRedirect and authWithOAuthPopup).
Were you ever able to figure it out?
In my following code, the gooogle sign-in button every time prompts for choosing account...
public class MainActivity extends AppCompatActivity {
Button btn_signOut;
private GoogleSignInClient mGoogleSignInClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_signOut = findViewById(R.id.btnSignOut);
btn_signOut.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
signOut();
}
});
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build();
mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
}
private void signOut() {
mGoogleSignInClient.signOut()
.addOnCompleteListener(this, new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
finish();
}
});
}
}
Use this way to signout.
Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(new
ResultCallback<Status>()
{
#Override
public void onResult(#NonNull Status status)
{
mAuth.signOut();
}
});
In flutter, use: GoogleSignIn().signOut();
(assumming you used the google_sign_in package)