In a xamarin forms project, I have added Firebase plugin to my project to do push notification.
The plugin works well in my IOS project. I can see the data in the output and when the app is in background the notification pops up.
My problem:
In my Android project the notification never pop up. I can see in output console the data send on Firebase platform, but when the app is in background the pop up does not appear and I have this error when I put the value com.AppName.urgent in my Strings.xml file
[FirebaseMessaging] Notification Channel set in AndroidManifest.xml has not been created by the app. Default value will be used.
I have not error when I put the value default but the notification still not appear
How can I make the notification appear on Android ?
Here is my code :
the strings.xml file in my android project :
<?xml version="1.0" encoding="UTF-8" ?>
<resources>
<string name="notification_channel_id">default</string>
</resources>
My Android Files : MainActivity
namespace AppName.Droid
{
[Activity(Label = "AppName", Icon = "@mipmap/icon", Theme = "@style/MainTheme", ConfigurationChanges = ConfigChanges.ScreenSize
| ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize
| ConfigChanges.Orientation, ScreenOrientation = ScreenOrientation.Portrait
)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
internal static MainActivity Instance { get; private set; }
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
FirebasePushNotificationManager.ProcessIntent(this, Intent);
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
Stormlion.ImageCropper.Droid.Platform.OnActivityResult(requestCode, resultCode, data);
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode)
{
case AndroidMicrophoneService.RecordAudioPermissionCode:
if (grantResults[0] == Permission.Granted)
{
micService.OnRequestPermissionResult(true);
}
else
{
micService.OnRequestPermissionResult(false);
}
break;
}
}
}
}
My Firebase file : MainApplication
[Application]
public class MainApplication : Application
{
public MainApplication(IntPtr handle, JniHandleOwnership transer) : base(handle, transer)
{
}
public override void OnCreate()
{
base.OnCreate();
//Set the default notification channel for your app when running Android Oreo
if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
{
//Change for your default notification channel id here
FirebasePushNotificationManager.DefaultNotificationChannelId = "FirebasePushNotificationChannel";
//Change for your default notification channel name here
FirebasePushNotificationManager.DefaultNotificationChannelName = "General";
}
//If debug you should reset the token each time.
#if DEBUG
FirebasePushNotificationManager.Initialize(this, true);
#else
FirebasePushNotificationManager.Initialize(this,false);
#endif
//Handle notification when app is closed here
CrossFirebasePushNotification.Current.OnNotificationReceived += (s, p) =>
{
};
}
}
In my app.xaml.cs :
public App()
{
InitializeComponent();
MainPage = new LInPage();
}
// Firebase Notifcation
CrossFirebasePushNotification.Current.OnTokenRefresh += (s, p) =>
{
System.Diagnostics.Debug.WriteLine($"MyTOKEN : {p.Token}");
};
CrossFirebasePushNotification.Current.OnNotificationReceived += (s, p) =>
{
System.Diagnostics.Debug.WriteLine("Received");
foreach (var data in p.Data)
{
System.Diagnostics.Debug.WriteLine($"Mydata {data.Key} : {data.Value}");
}
};
CrossFirebasePushNotification.Current.OnNotificationOpened += (s, p) =>
{
System.Diagnostics.Debug.WriteLine("Opened");
foreach (var data in p.Data)
{
System.Diagnostics.Debug.WriteLine($"Opended {data.Key} : {data.Value}");
}
};
}
SplashActivity.cs (Opening Screen Image) :
namespace AppName.Droid
{
[Activity(Theme = "@style/MyTheme.Splash", MainLauncher = true, NoHistory = true)]
public class SplashActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your application here
}
protected override async void OnResume()
{
base.OnResume();
await SimulateStartup();
}
async Task SimulateStartup()
{
await Task.Delay(1000); // Simulate a bit of startup work.
StartActivity(new Intent(Application.Context, typeof(MainActivity)));
}
}
}
My AndroidManifest.xml :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="98.0" package="com.AppName" android:versionCode="98">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="31" />
<application android:label="AppName" android:theme="@style/MainTheme" android:icon="@mipmap/icon_round">
<activity android:name="com.theartofdev.edmodo.cropper.CropImageActivity" android:theme="@style/Base.Theme.AppCompat" />
<meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="@string/notification_channel_id" />
<!-- optional (needed if default theme has no action bar) -->
<service android:name="crc6494e14b9856016c30.PNFirebaseMessagingService" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-feature android:name="android.hardware.location" android:required="false" />
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
<uses-feature android:name="android.hardware.location.network" android:required="false" />
<queries>
<intent>
<action android:name="android.intent.action.SENDTO" />
<data android:scheme="mailto" />
</intent>
</queries>
</manifest>
I have followed these links but without success :
2
Answers
You should avoid to mix up declarative attributes and manually writing the AndroidManifest.xml.
[Activity (Label = "MyApp", MainLauncher = true, Icon = "@mipmap/ic_launcher")]
is generating a piece of code in the actual used (generated)AndroidManifest.xml
that looks like:and your code will be somewhere else. You can find the generated
AndroidManifest.xml
in the output folder.objDebugandroid
.So,try to remove the manual edits from your manifest file.
For more information, you can check document: Working with the Android Manifest.
Besides, you can also refer to the sample of FirebasePushNotificationPlugin here, which can guide us on how to implement this function concretely.
The error message is trying to say you are specifying different notification channel ids in your manifest (you supplied "default") and your programming (you supplied "General"). You should use the same values in both places.
Try this: