MaikuB / flutter_local_notifications

A Flutter plugin for displaying local notifications on Android, iOS, macOS and Linux
2.45k stars 1.4k forks source link

Android not displaying foreground and background notifications #1004

Closed RemeJuan closed 3 years ago

RemeJuan commented 3 years ago

Describe the bug Neither foreground nor background notifications are displaying in release mode.

I can get them to work perfectly in debug mode, but the release build refuses to work. I have made the required updates to the proguard as well as the K8 keep instructions. Registered the plugin correctly with android native. There is an icon (png) in android/app/src/main/res/drawable

All notifications work working as expected in iOS.

I saw no other required steps in the readme and saw nothing that I missed when looking through the example in the native android code, as far as I can tell it should be working and am assuming it's likely something simple that I have somehow missed somewhere.

Tested on Android 9/10/11 on a real device (9) and emulators (10/11).

Thanks.

To Reproduce

  1. Send notification to the device.
  2. Notification arrives (there are other indicators in my app), no notification pops up.

Expected behavior A notification should show in the foreground or the background.

Sample code to reproduce the problem

app/android/proguard-rules.pro

## Flutter wrapper
-keep class io.flutter.app.** { *; }
-keep class io.flutter.plugin.**  { *; }
-keep class io.flutter.plugins.**  { *; }
-keep class io.flutter.util.**  { *; }
-keep class io.flutter.view.**  { *; }
-keep class io.flutter.**  { *; }
-keep class io.flutter.plugins.**  { *; }
-dontwarn io.flutter.embedding.**

## Firebase
-keep class com.firebase.** { *; }
-keep class org.apache.** { *; }
-keepnames class com.fasterxml.jackson.** { *; }
-keepnames class javax.servlet.** { *; }
-keepnames class org.ietf.jgss.** { *; }
-dontwarn org.w3c.dom.**
-dontwarn org.joda.time.**
-dontwarn org.shaded.apache.**
-dontwarn org.ietf.jgss.**

## Google
-keep public class com.google.android.gms.* { public *; }
-dontwarn com.google.android.gms.**

## Gson rules
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature

# For using GSON @Expose annotation
-keepattributes *Annotation*

# Gson specific classes
-dontwarn sun.misc.**
#-keep class com.google.gson.stream.** { *; }

# Prevent proguard from stripping interface information from TypeAdapter, TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
-keep class * extends com.google.gson.TypeAdapter
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer

# Prevent R8 from leaving Data object members always null
-keepclassmembers,allowobfuscation class * {
  @com.google.gson.annotations.SerializedName <fields>;
}

android/app/src/main/AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.member_ui_flutter">
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.USE_BIOMETRIC"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.CAMERA"/>
    <application
            android:name=".Application"
            android:extractNativeLibs="false"
            android:label="App Name"
            android:icon="@mipmap/icon"
    >
        <activity
                android:name=".MainActivity"
                android:launchMode="singleTop"
                android:theme="@style/LaunchTheme"
                android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
                android:hardwareAccelerated="true"
                android:windowSoftInputMode="adjustResize">

            <meta-data
                    android:name="io.flutter.embedding.android.SplashScreenDrawable"
                    android:resource="@drawable/launch_background"/>
            <meta-data
                    android:name="io.flutter.embedding.android.NormalTheme"
                    android:resource="@style/LaunchTheme"
            />

            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
            <intent-filter>
                <action android:name="FLUTTER_NOTIFICATION_CLICK"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

        <meta-data
                android:name="flutterEmbedding"
                android:value="2"/>
    </application>
</manifest>

android/app/src/main/res/raw/keep.xml

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
           tools:keep="@drawable/*,@raw/slow_spring_board"/>

Application.java

package com.example.member_ui_flutter;

import android.os.Bundle;
import io.flutter.app.FlutterApplication;
import io.flutter.app.FlutterActivity;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.GeneratedPluginRegistrant;

//Firebase and notifications
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService;
import io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin;
import com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin;

public class Application extends FlutterApplication implements PluginRegistrantCallback {
    @Override
    public void onCreate() {
        super.onCreate();
        FlutterFirebaseMessagingService.setPluginRegistrant(this);
    }

    @Override
    public void registerWith(PluginRegistry pluginRegistry) {
        FirebaseMessagingPlugin.registerWith(pluginRegistry.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
        FlutterLocalNotificationsPlugin.registerWith(pluginRegistry.registrarFor("com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin"));
    }
}

android/app/build.gradle (partial)

    buildTypes {
        release {
            signingConfig signingConfigs.release

            minifyEnabled true

            shrinkResources true

            proguardFiles getDefaultProguardFile(
                    'proguard-android-optimize.txt'),
                    'proguard-rules.pro'

            dependencies {
                implementation 'com.android.support:support-fragment:28.0.0'
            }
        }
    }

notification display function

    final androidPlatformChannelSpecifics = const AndroidNotificationDetails(
      'all_notifications',
      'General Notifications',
      'General Notifications',
      playSound: true,
      enableVibration: true,
      importance: Importance.max,
      priority: Priority.high,
    );
    final iOSPlatformChannelSpecifics = const IOSNotificationDetails();
    final platformChannelSpecifics = NotificationDetails(
      android: androidPlatformChannelSpecifics,
      iOS: iOSPlatformChannelSpecifics,
    );
    final payload = setupNotificationPayload(
      notification: jsonDecode(jsonEncode(notification)),
    );

    final String title = payload['title'];
    final String body = payload['body'];

    await flutterLocalNotificationsPlugin.show(
      0,
      title,
      body,
      platformChannelSpecifics,
      payload: jsonEncode(payload),
    );
MaikuB commented 3 years ago

Note that in the bug report template that I specified that a link to a repo containing a minimal app to reproduce the problem is needed. These code snippets don't help with tracking issues like this, particularly when the snippets also indicate that your application is using FCM. The minimal app would need to reference only this plugin or at least not reference FCM as I've seen issues opened where developers have confused push notifications with local notifications. May not be the case here since you say iOS is working but this helps isolate the issue further. There is already an example app in the repository as well that could've been used to do a release build of to check as well. If you haven't done so already, I'd suggest creating a release build off that to see if you've been having the same issue.

RemeJuan commented 3 years ago

It would be impossible to replicate the issue by taking FCM out, that's where the data comes from, the data object from the FCM push it's handed over to local_notifications for displaying and interaction.

Without FCM there is no data and without data there is nothing to hand over to the notification, therefor no notification.

It worked for months and has been broken since upgrading to embedded v2, but that also broke the firebase integration which I only got around to fixing last week.

I can spend some time putting together a minimal project, but it's functionally impossible to do so without FCM.

MaikuB commented 3 years ago

First I should clarify that I'm not asking to get a link to a repository to your actual application. The point of removing FCM is make sure that the issue is actually to do with this plugin. If all FCM does is provide data then to call the APIs from this plugin then the minimal app to reproduce this problem could call the same method from this plugin with the same data it would've received from FCM without a referencing to FCM

RemeJuan commented 3 years ago

Thanks that was a valid point, I actually just popped a button into the app to call the "showNotification" function and in dev it's working, release nothing.

I'll setup a new flutter project with just notifications and my android folder.

Thanks.

MaikuB commented 3 years ago

Also note that the plugin use to require that there are Proguard rules specific to this plugin. Your Proguard rules file doesn't contain and that should only be done if you were using versions 3.0.1+4 or newer. Mentioning this in case you decided keep using an older version of the plugin but went through the setup steps again but those were for recent versions

RemeJuan commented 3 years ago

Morning,

Yes, I do prefer to stick with the newer versions, try to avoid staying in the past as much as possible.

Finished setting this up this morning, hope it has everything you need, but I am able to replicate the issue with it.

https://github.com/RemeJuan/android_pn_test

MaikuB commented 3 years ago

I created a fork and branch at https://github.com/MaikuB/android_pn_test/tree/fix_gradle_to_build. This was done so I can use the debug signing key (this shouldn't affect the result for this issue) and references to some other dependencies as I wasn't able to build as it would say that google-services.json is missing. Created a release apk, installed it and ran it on my Pixel 4 XL phone. The notification appeared after tapping on the button. Not sure what's going on in your case. Perhaps you'll need to check logcat. In case it helps, the output I get from flutter doctor -v is

[✓] Flutter (Channel stable, 1.22.5, on macOS 11.1 20C69 darwin-x64, locale en-AU)
    • Flutter version 1.22.5 at /Users/michaelbui/flutter
    • Framework revision 7891006299 (7 weeks ago), 2020-12-10 11:54:40 -0800
    • Engine revision ae90085a84
    • Dart version 2.10.4

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
    • Android SDK at /Users/michaelbui/Library/Android/sdk
    • Platform android-30, build-tools 30.0.2
    • Java binary at: /Applications/Android
      Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build
      1.8.0_242-release-1644-b3-6915495)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 12.3)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 12.3, Build version 12C33
    • CocoaPods version 1.10.1

[!] Android Studio (version 4.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
    • Java version OpenJDK Runtime Environment (build
      1.8.0_242-release-1644-b3-6915495)

[✓] VS Code (version 1.52.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.18.1

[!] Connected device
    ! No devices available
RemeJuan commented 3 years ago

Well that is just annoying, even building off your fork it is still not working and my doctor output is very much the same as yours. Running on a Nokia 6 with android 9.

Updated the base repo with your changes, well just commenting all the code out, I was hoping it would work and I could easily just use the comments to find the fubar line.

RemeJuan commented 3 years ago

Ok... I owe you like a 6 pack or something, turns out the entire time I have had DND enabled on my test phone.

This is a prime case of ID10T error, there was a serious PBKaC.