问题
I am having issues saving and displaying push notification in my apps UI when the app is swiped from memory or closed. I still receive the notifications in this state, but upon opening the app or tapping the notification to open the app, the message does not display. Everything works fine when the app is running or in the background. I've followed the documentation here https://docs.microsoft.com/en-us/xamarin/xamarin-forms/data-cloud/azure-services/azure-notification-hub with a few modification to save the notification in a SQLite file. I finally got this to work for iOS but no such luck on Android. Here is my code.
FireBaseService class
[Service]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class FirebaseService : FirebaseMessagingService
{
public override void OnMessageReceived(RemoteMessage message)
{
base.OnMessageReceived(message);
string messageBody = string.Empty;
if (message.GetNotification() != null)
{
messageBody = message.GetNotification().Body;
}
// NOTE: test messages sent via the Azure portal will be received here
else
{
messageBody = message.Data.Values.First();
}
// convert the incoming message to a local notification
SendLocalNotification(messageBody);
// send the incoming message directly to the MainPage
SendMessageToMainPage(messageBody);
}
//public override void HandleIntent(Intent intent)
//{
// base.HandleIntent(intent);
// //Create your notification
//}
public override void OnNewToken(string token)
{
// TODO: save token instance locally, or log if desired
SendRegistrationToServer(token);
}
void SendLocalNotification(string body)
{
var intent = new Intent(this, typeof(MainActivity));
intent.AddFlags(ActivityFlags.ClearTop);
intent.PutExtra("message", body);
var pendingIntent = PendingIntent.GetActivity(this, 0, intent,
PendingIntentFlags.OneShot);
var notificationBuilder = new NotificationCompat.Builder(this,
AppConstants.NotificationChannelName)
.SetContentTitle("MyMessage")
.SetSmallIcon(Resource.Drawable.pushimageicon)
.SetContentText(body)
.SetAutoCancel(true)
.SetWhen(JavaSystem.CurrentTimeMillis())
.SetShowWhen(true)
.SetStyle(new NotificationCompat.BigTextStyle())
.SetContentIntent(pendingIntent);
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
notificationBuilder.SetChannelId(AppConstants.NotificationChannelName);
}
int m = (int)((new Date().Time / 1000L) % Integer.MaxValue);
var notificationManager = NotificationManager.FromContext(this);
notificationManager.Notify(m, notificationBuilder.Build());
}
void SendMessageToMainPage(string body)
{
//send to AppShell to save in SQLite
(Xamarin.Forms.Application.Current.MainPage as AppShell)?.AddMessage(body);
}
void SendRegistrationToServer(string token)
{
try
{
NotificationHub hub = new NotificationHub(AppConstants.NotificationHubName,
AppConstants.ListenConnectionString, this);
// register device with Azure Notification Hub using the token from FCM
Registration registration = hub.Register(token, AppConstants.SubscriptionTags);
// subscribe to the SubscriptionTags list with a simple template.
string pnsHandle = registration.PNSHandle;
TemplateRegistration templateReg = hub.RegisterTemplate(pnsHandle, "defaultTemplate",
AppConstants.FCMTemplateBody, AppConstants.SubscriptionTags);
}
catch (System.Exception e)
{
Log.Error(AppConstants.DebugTag, $"Error registering device: {e.Message}");
}
}
}
MainActivity.cs
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
Rg.Plugins.Popup.Popup.Init(this, savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
//SQLite Code
string fileName = "sample.db";
string folderPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
string completePath = Path.Combine(folderPath, fileName);
if (!File.Exists(completePath))
{
using (var binaryReader = new BinaryReader(Android.App.Application.Context.Assets.Open(fileName)))
{
using (var binaryWriter = new BinaryWriter(new FileStream(completePath, FileMode.Create)))
{
byte[] buffer = new byte[2048];
int length = 0;
while ((length = binaryReader.Read(buffer, 0, buffer.Length)) > 0)
{
binaryWriter.Write(buffer, 0, length);
}
}
}
}
//End SQLite Code
LoadApplication(new App(completePath));
//For azure push notification
if (!IsPlayServiceAvailable())
{
throw new Exception("This device does not have Google Play Services and cannot receive push notifications.");
}
CreateNotificationChannel();
//END azure push notification
}
//For azure push notification
protected override void OnNewIntent(Intent intent)
{
if (intent.Extras != null)
{
var message = intent.GetStringExtra("message");
// save message in SQLite on AppShell
(Xamarin.Forms.Application.Current.MainPage as AppShell)?.AddMessage(message);
}
base.OnNewIntent(intent);
}
bool IsPlayServiceAvailable()
{
int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.Success)
{
if (GoogleApiAvailability.Instance.IsUserResolvableError(resultCode))
Log.Debug(AppConstants.DebugTag, GoogleApiAvailability.Instance.GetErrorString(resultCode));
else
{
Log.Debug(AppConstants.DebugTag, "This device is not supported");
}
return false;
}
return true;
}
void CreateNotificationChannel()
{
// Notification channels are new as of "Oreo".
// There is no need to create a notification channel on older versions of Android.
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
var channelName = AppConstants.NotificationChannelName;
var channelDescription = String.Empty;
var channel = new NotificationChannel(channelName, channelName, NotificationImportance.Default)
{
Description = channelDescription
};
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(channel);
}
}
//END azure push notification
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);
}
}
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1" android:versionName="1.0"
package="YOUR_PACKAGE_NAME"
android:installLocation="auto">
<uses-sdk android:minSdkVersion="21" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission
android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<application android:label="Notification Hub Sample">
<receiver
android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver"
android:exported="false" />
<receiver
android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION"
/>
<category android:name="${applicationId}" />
</intent-filter>
</receiver>
</application>
</manifest>
Any help would be appreciated. So far everything I find says to use onHandleIntent method but my application says there is no override for this method.
来源:https://stackoverflow.com/questions/61639866/unable-to-save-push-notification-in-sqlite-when-xamarin-android-app-is-swiped-or