invertase / react-native-firebase

🔥 A well-tested feature-rich modular Firebase implementation for React Native. Supports both iOS & Android platforms for all Firebase services.
https://rnfirebase.io
Other
11.5k stars 2.18k forks source link

React-Native POST_NOTIFICATIONS permission/ Firebase Clound Messaging dont work in release mode Android #7746

Closed HerickRaposo closed 2 months ago

HerickRaposo commented 2 months ago

i created one React-Native Android aplication that using react-native-push-notification plugin whith firebase clound messaging. When i ue debug mode the application request permission to use notification, but when generate apk or aab in release mode the aplication dont request permission then, i tryed many solutions anything dont resolve my problem.

  1. In First moment i did think the problem relationed with firebase configuration than i tryed sand sha-1 and sha-256 keys that i use signify my app on google play console, after i downloaded google-services.json,this didnt alter anything.
  2. I tryed disable proguard
  3. I tryed create notificationchannel configure manualy in AndroidManifest

After some test using npx react-native log-android i verifyed that somethings: First the permission camera is openned normaly in debug and release mode but POST_NOTIFICATIONS is required only in debug mode and cant print permission in console, after this i thyed some solutions thinking the problem is request POST_NOTIFICATION permission:

  1. I tryed follow pureact-native-push-notification plugin documentation that sayd to alter node_modules/react-native/libraries/PermissionsAndroid/PermissionsAndroid.js adding WRITE_EXTERNAL_STORAGE: string and POST_NOTIFICATION'android.permission.POST_NOTIFICATIONS';
  2. I tryed alter POST_NOTIFICATION to NOTIFICATION_MANAGER, but permissionsAndroid dont have NOTIFICATION_MANAGER
  3. I tryed add many permissions notifications in AndroidManifest

That is my code that i was implement: AndroidManifest:

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

  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.CAMERA" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.VIBRATE" />
  <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
  <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
  <uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
  <uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" />
  <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
  <uses-permission android:name="android.permission.NOTIFICATION_MANAGER" />

  <application
    android:name=".MainApplication"
    android:label="@string/app_name"
    android:icon="@mipmap/ic_launcher"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:allowBackup="true"
    android:usesCleartextTraffic="true"
    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:screenOrientation="portrait"
      android:exported="true">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
    <service
      android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationListenerService"
      android:exported="false">
      <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
      </intent-filter>
    </service>
    <meta-data
      android:name="com.google.firebase.messaging.default_notification_icon"
      android:resource="@drawable/notification_icon" />
  </application>
</manifest>

Build.gradle:

buildscript {
    ext {
        buildToolsVersion = "31.0.0"
        minSdkVersion = 21
        compileSdkVersion = 33
        targetSdkVersion = 33
        googlePlayServicesVersion = "+" 
        firebaseMessagingVersion = "+" // default: "21.1.0"
        ndkVersion = "21.4.7075529"
    }
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath("com.android.tools.build:gradle:7.2.2")
        classpath("com.facebook.react:react-native-gradle-plugin")
        classpath("de.undercouch:gradle-download-task:4.1.2")
        classpath 'com.google.gms:google-services:4.3.14'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

AndroidPermissions:


const PERMISSIONS = Object.freeze({
  READ_CALENDAR: 'android.permission.READ_CALENDAR',
  WRITE_CALENDAR: 'android.permission.WRITE_CALENDAR',
  CAMERA: 'android.permission.CAMERA',
  READ_CONTACTS: 'android.permission.READ_CONTACTS',
  WRITE_CONTACTS: 'android.permission.WRITE_CONTACTS',
  GET_ACCOUNTS: 'android.permission.GET_ACCOUNTS',
  ACCESS_FINE_LOCATION: 'android.permission.ACCESS_FINE_LOCATION',
  ACCESS_COARSE_LOCATION: 'android.permission.ACCESS_COARSE_LOCATION',
  ACCESS_BACKGROUND_LOCATION: 'android.permission.ACCESS_BACKGROUND_LOCATION',
  RECORD_AUDIO: 'android.permission.RECORD_AUDIO',
  READ_PHONE_STATE: 'android.permission.READ_PHONE_STATE',
  CALL_PHONE: 'android.permission.CALL_PHONE',
  READ_CALL_LOG: 'android.permission.READ_CALL_LOG',
  WRITE_CALL_LOG: 'android.permission.WRITE_CALL_LOG',
  ADD_VOICEMAIL: 'com.android.voicemail.permission.ADD_VOICEMAIL',
  USE_SIP: 'android.permission.USE_SIP',
  PROCESS_OUTGOING_CALLS: 'android.permission.PROCESS_OUTGOING_CALLS',
  BODY_SENSORS: 'android.permission.BODY_SENSORS',
  SEND_SMS: 'android.permission.SEND_SMS',
  RECEIVE_SMS: 'android.permission.RECEIVE_SMS',
  READ_SMS: 'android.permission.READ_SMS',
  RECEIVE_WAP_PUSH: 'android.permission.RECEIVE_WAP_PUSH',
  RECEIVE_MMS: 'android.permission.RECEIVE_MMS',
  READ_EXTERNAL_STORAGE: 'android.permission.READ_EXTERNAL_STORAGE',
  WRITE_EXTERNAL_STORAGE: 'android.permission.WRITE_EXTERNAL_STORAGE',
  BLUETOOTH_CONNECT: 'android.permission.BLUETOOTH_CONNECT',
  BLUETOOTH_SCAN: 'android.permission.BLUETOOTH_SCAN',
  BLUETOOTH_ADVERTISE: 'android.permission.BLUETOOTH_ADVERTISE',
  ACCESS_MEDIA_LOCATION: 'android.permission.ACCESS_MEDIA_LOCATION',
  ACCEPT_HANDOVER: 'android.permission.ACCEPT_HANDOVER',
  ACTIVITY_RECOGNITION: 'android.permission.ACTIVITY_RECOGNITION',
  ANSWER_PHONE_CALLS: 'android.permission.ANSWER_PHONE_CALLS',
  READ_PHONE_NUMBERS: 'android.permission.READ_PHONE_NUMBERS',
  UWB_RANGING: 'android.permission.UWB_RANGING',
  POST_NOTIFICATIONS: 'android.permission.POST_NOTIFICATIONS',
});

/**
 * `PermissionsAndroid` provides access to Android M's new permissions model.
 *
 * See https://reactnative.dev/docs/permissionsandroid
 */

class PermissionsAndroid {
  PERMISSIONS: {|
    ACCEPT_HANDOVER: string,
    ACCESS_BACKGROUND_LOCATION: string,
    ACCESS_COARSE_LOCATION: string,
    ACCESS_FINE_LOCATION: string,
    ACCESS_MEDIA_LOCATION: string,
    ACTIVITY_RECOGNITION: string,
    ADD_VOICEMAIL: string,
    ANSWER_PHONE_CALLS: string,
    BLUETOOTH_ADVERTISE: string,
    BLUETOOTH_CONNECT: string,
    BLUETOOTH_SCAN: string,
    BODY_SENSORS: string,
    CALL_PHONE: string,
    CAMERA: string,
    GET_ACCOUNTS: string,
    PROCESS_OUTGOING_CALLS: string,
    READ_CALENDAR: string,
    READ_CALL_LOG: string,
    READ_CONTACTS: string,
    READ_EXTERNAL_STORAGE: string,
    READ_PHONE_NUMBERS: string,
    READ_PHONE_STATE: string,
    READ_SMS: string,
    RECEIVE_MMS: string,
    RECEIVE_SMS: string,
    RECEIVE_WAP_PUSH: string,
    RECORD_AUDIO: string,
    SEND_SMS: string,
    USE_SIP: string,
    UWB_RANGING: string,
    WRITE_CALENDAR: string,
    WRITE_CALL_LOG: string,
    WRITE_CONTACTS: string,
    WRITE_EXTERNAL_STORAGE: string,
    POST_NOTIFICATIONS: string,
  |} = PERMISSIONS;
  RESULTS: {|
    DENIED: $TEMPORARY$string<'denied'>,
    GRANTED: $TEMPORARY$string<'granted'>,
    NEVER_ASK_AGAIN: $TEMPORARY$string<'never_ask_again'>,
  |} = PERMISSION_REQUEST_RESULT;

App.js:


const requestPermissionsIOS = async () => {
  const authStatus = await messaging().requestPermission();
  const enabled =
      authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
      authStatus === messaging.AuthorizationStatus.PROVISIONAL;
    if (enabled) {
      messaging().getAPNSToken().then(async (apnsToken) => {
        console.log("APN TOKEN: " + apnsToken)
        messaging().setAPNSToken(apnsToken);
        const token = await messaging().getToken();
        console.log("TOKEN IOS:" +  token)
      })
    }
  }

const requestPermissionsAndroid = async () => {
  const granted = await PermissionsAndroid.request(
    PermissionsAndroid.PERMISSIONS.CAMERA,

  );
  await PermissionsAndroid.request(
    PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS,
  );
};

export default function App() {
  useEffect(() => {
    checkVersion();
    createTable();
    enviarRota();
    verificarMotorista();
    verificaLogin();
    verificaUltimoIndex();
    if(isIOS){
      requestPermissionsIOS();
    } else {
      requestPermissionsAndroid();
    }
    SplashScreen.hide();
  });

    useEffect(() => {
      if (isIOS) {
        requestPermissionsIOS();
        const unsubscribe = messaging().onMessage(async remoteMessage => {
          console.log('A new FCM message arrived!', JSON.stringify(remoteMessage));
          PushNotificationIOS.addNotificationRequest({
            id:remoteMessage.messageId,
            tile:remoteMessage.notification.title,
            subtitle:remoteMessage.notification.subtitle,
            body:remoteMessage.notification.body,
          })
        });
        return unsubscribe;
      }
    }, []);

  return (
    <Routes />
  )

Index.js

import { AppRegistry, Platform, Alert } from 'react-native';
import App from './App';
import { name as appName } from './app.json';
import PushNotification, { Importance } from 'react-native-push-notification';
import messaging from '@react-native-firebase/messaging';
import PushNotificationIOS from '@react-native-community/push-notification-ios';

PushNotification.configure({
  // (required) Called when a remote is received or opened, or local notification is opened
  onNotification: function (notification) {
    PushNotification.localNotification({
      title: notification.title,
      message: notification.message,
      channelId: 'CanalNotificacao2000',
      date: new Date(Date.now()), // in 60 secs
      smallIcon: 'ic_launcher_round',
      bigText: notification.message,
      priority: 'max',
      visibility: "public",
      importance: Importance.HIGH,
    });
    console.log("NOTIFICATION:", notification);
  },

  permissions: {
    alert: true,
    sound: true,
  },
  popInitialNotification: true,
  requestPermissions: Platform.OS === 'ios', // Solicita permissões tanto para Android quanto para iOS
});
PushNotification.createChannel(

  {

    channelId: 'CanalNotificacao2000', // (required)
    channelName: "Meu canal 2000", // (required)
    channelDescription: "Canal de comunicação de mensagens", // (optional) default: undefined.
    playSound: true, // (optional) default: true
    soundName: "default", // (optional) See `soundName` parameter of `localNotification` function
    importance: Importance.HIGH, // (optional) default: Importance.HIGH. Int value of the Android notification importance
    vibrate: true, // (optional) default: true. Creates the default vibration pattern if true.
  },
  (created) => console.log(`createChannel returned '${created}'`) // (optional) callback returns whether the channel was created, false means it already existed.

  );

const isBackgroundHandlerInitialized = messaging().isBackgroundRestricted;

if (!isBackgroundHandlerInitialized) {
  messaging().setBackgroundMessageHandler(async remoteMessage => {
    console.log('Message handled in the background!', remoteMessage);

  });
}

AppRegistry.registerComponent(appName, () => App);

Enviroment settings:

System:
    OS: Windows 11 10.0.22631
    CPU: (12) x64 12th Gen Intel(R) Core(TM) i5-12500
    Memory: 3.69 GB / 15.70 GB
  Binaries:
    Node: 20.11.1 - C:\Program Files\nodejs\node.EXE
    Yarn: Not Found
    npm: 10.4.0 - C:\Program Files\nodejs\npm.CMD
    Watchman: Not Found
  SDKs:
    Android SDK: Not Found
    Windows SDK: Not Found
  IDEs:
    Android Studio: AI-223.8836.35.2231.10406996
    Visual Studio: Not Found
  Languages:
    Java: 21.0.2
  npmPackages:
    @react-native-community/cli: Not Found
    react: ^17.0.2 => 17.0.2
    react-native: ^0.68.7 => 0.68.7
    react-native-windows: Not Found
  npmGlobalPackages:
    *react-native*: Not Found

Version android tested:10.0.0
mikehardy commented 2 months ago

Requesting permissions and permission support is a bit out of scope for this repository

I recommend using react-native-permissions to manage your permissions

HerickRaposo commented 1 month ago

The problem is that even requesting permission I cannot extract the token. After much debugging I found that the application can even display the token but cannot capture the information internally, it is as if the code lost the information and does not recover it when I call the gettoken method