Xamarin - BroadcastReceiver Unable to receive after Distribution APK - c#

Hi I am new to xamarin and I hit a weird issue.
I currently developing an app for Zebra MC93, and I use broadcast receiver to received the barcode information. I hardcorded the intent to be "com.symbol.ccn.RECVR". when I zebra developer mode to install the app via visual studio to zebra with usb debugging, the app can run smoothly with all the broadcast receiver working. But when I archive and distribute the file, and install the app with the apk, the broadcast receiver doesnt work at all. I didnt declare the intent filter in AndroidManifest, i only declared it in a class below. Anyone had any idea?
[BroadcastReceiver(Enabled = true, Exported = true)]
[IntentFilter(new[] { "com.symbol.ccn.RECVR" })]
public class Receiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
if (intent.Action.Equals(GeneralString.IntentPASSTOAPP))
{
string x = intent.GetStringExtra(GeneralString.BcReaderData);
// Toast.MakeText(context, "Received !" + x, ToastLength.Short).Show();
MessagingCenter.Send<ProductIdentificationScanPage, string>(new ProductIdentificationScanPage(), "BarcodeInfo", x);
}
else if (intent.Action.Equals("com.symbol.ccn.RECVR"))
{
string x = intent.GetStringExtra("com.symbol.datawedge.data_string");
MessagingCenter.Send<ProductIdentificationScanPage, string>(new ProductIdentificationScanPage(), "BarcodeInfo", x);
}
}
}
Anyone had any idea or meet this type of issues before?

Related

Android Foreground Location Service stops after some time

Im using this code to get location updates for my Xamarin Android app. I have 2 questions.
How to make this foreground service to run forever? I've tried to change return StartCommandResult.NotSticky; to return StartCommandResult.Sticky; and remove anything from OnDestroy() method, but OS seems to be unable to recreate service after it was killed or crashed. So, it runs about a half day only, even i've added app to my battery optimization exclude list. How to make it run forever?
How to properly start service from boot?
Here is what i've tried. Added following to MainActivity.cs
[IntentFilter(new[] { Android.Content.Intent.ActionBootCompleted })]
public class BootReceiver : BroadcastReceiver
{
public Context Context { get; set; }
public override void OnReceive(Context context, Intent intent)
{
var stepServiceIntent = new Intent(context, typeof(LocationUpdatesService));
stepServiceIntent.PutExtra("StartedFromBoot", true);
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
{
context.StartForegroundService(stepServiceIntent);
}
else
{
context.StartService(stepServiceIntent);
}
}
}
Edited LocationUpdatesService.cs
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
Log.Info(Tag, "Service started");
var startedFromNotification = intent.GetBooleanExtra(ExtraStartedFromNotification, false);
var startedFromBoot = intent.GetBooleanExtra("StartedFromBoot", false);
if (startedFromBoot)
{
//Preferences.Set("LocationUpdates", true);
StartForeground(NotificationId, StartNotification("",""));
Preferences.Set("foreground", true);
try
{
FusedLocationClient.RequestLocationUpdates(LocationRequest, LocationCallback, Looper.MyLooper());
}
catch (SecurityException unlikely)
{
Preferences.Set("LocationUpdates", false);
Log.Error(Tag, "Lost location permission. Could not request updates. " + unlikely);
}
}
if (startedFromNotification)
{
RemoveLocationUpdates();
StopSelf();
}
return StartCommandResult.Sticky;
}
I got only single location update that way right from boot. After that single update Im geting "Unknown Location" so service doesnt run continuously. So, how to properly start that service from boot to make it run continuously?
Maybe there will be a single solution for both questions, so if there is a way to start fully functional service from boot, then system could recreate it with Sticky flag and run forever.
Actually, the foreground service will keep running when the phone is on. But you can also use the PowerManager.WakeLock to make sure your app always keep alive even the device is sleep.
You can check this case:Xamarin wakelock
In addition, it seems that you want to get the user's location cyclically. So you can run a timed task in the foreground service. There are many ways to do that. Such as:
JobScheduler
AlarmManager
WorkManager
ScheduledThreadPoolExecutor
You can check this case:Xamarin Android - Periodic task execution

Xamarin Forms Push Notifications using Azure Messaging Hub not working in release mode

I added a functionality to my Xamarin Forms App allowing it to receive Notifications from Azure.
Everything works fine in debug mode, but in release mode, the App crashes when I receive a notification.
I got a logger working with Adb to see the exception. The code I am using is the following:
public void OnPushNotificationReceived(Context context, INotificationMessage message)
{
try
{
var msgData = message.Data;
if (msgData.ContainsKey("EventType"))
{
try
{
if (AllowStoreNotification(msgData["VirtualStoreId"], msgData["EventType"]))
{
SendNotification(message.Title, message.Body);
}
}
catch (KeyNotFoundException ex)
{
new TrackEvent("Could not deliver notification. Parameter error.")
.AddParameter("exception", ex.Message.ToString())
.Send();
}
}
}
catch (Exception ex)
{
Log.Error("Notification", ex.Message);
}
void SendNotification(string title, string body)
{
var notification = new NotificationCompat.Builder(context, "PushNotifications")
.SetContentTitle(title)
.SetContentText(body)
.SetSmallIcon(Resource.Drawable.logo_pink_circle)
.SetAutoCancel(true)
.SetDefaults((int)NotificationDefaults.All)
.SetPriority((int)NotificationPriority.High)
.Build();
if (_notificationManager is null)
{
NotificationManagerCompat.From(context).Notify(0, notification);
}
else
{
_notificationManager.Notify(0, notification);
}
}
}
The _notificationManager is null for version Build.VERSION.SdkInt >= BuildVersionCodes.O.
The exception from de ADB log adb logcat Notification:E *:S:
Notification: no non-static method "Lcom/microsoft/windowsazure/messaging/notificationhubs/BasicNotificationMessage;.getData()Ljava/util/Map;"
Anyone knows how to fix this?
I figured out how to make it work using the skip linking assembly.
The issue is the certificate you uploaded to azure, it's just for development, not for production
You have a few options:
Change the certificate once you move to production
2 clouds, one for development and another for production.
Or just compile your app as production every time you want to test notifications

Chang Phone to Silent Mode on BroadCast Recieving in Xamarin Android

MainActivity.cs
private void StartAlarm()
{
Intent myIntent;
PendingIntent pendingIntent; myIntent = new Intent(this, typeof(AlarmToastReceiver));
pendingIntent = PendingIntent.GetBroadcast(this, 0, myIntent, 0);
alarm_manager.Set(AlarmType.RtcWakeup, calndr.TimeInMillis, pendingIntent);
}
AlarmToastReceiver.cs
[BroadcastReceiver(Enabled =true)]
public class AlarmToastReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
Toast.MakeText(context, "BroadCast Received.", ToastLength.Long).Show();
}
}
I want to Change my Phone mode to Silent at Specific Time automatically on Broadcast receiving, So here i pick the Time from Time-picker, and then set the Ala ram Manager Instance. When the Pending Intent completed , then Broadcast Receiver is active, and a Message is Shown to me,i.e "Broadcast Received.", but here i want to change my Mobile Mode to silent Mode,So how can i do it,can any one help me ? thanks in advance.
You can use the AudioManager to set Silent/Vibrate/Normal.
var audioMgr = (AudioManager)GetSystemService(AudioService);
audioMgr.RingerMode = RingerMode.Silent; // In Oreo(+) this will enable DnD mode
From N onward, ringer mode adjustments that would toggle Do Not Disturb are not allowed unless the app has been granted Do Not Disturb Access.
Re: AudioManager

Xamarin Form(PCL) IOS Firebase Push Message not working

I created a xamarin form project and I integrated firebase push notification in both Android & IOS projects. Its working fine on Android but not working with iOS.
I downloaded and added GoogleService-info.plist in iOS project, Set its Build Action to BundleResource.
AppDelegates.cs
namespace PushNotification.iOS
{
// The UIApplicationDelegate for the application. This class is responsible for launching the
// User Interface of the application, as well as listening (and optionally responding) to
// application events from iOS.
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate, IUNUserNotificationCenterDelegate
{
//
// This method is invoked when the application has loaded and is ready to run. In this
// method you should instantiate the window, load the UI into it and then make the window
// visible.
//
// You have 17 seconds to return from this method, or iOS will terminate your application.
//
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App());
RegisterForNotificationFCM();
return base.FinishedLaunching(app, options);
}
private void RegisterForNotificationFCM()
{
//Firebase Cloud Messaging Configuration
//Get permission for notification
if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
{
// iOS 10
var authOptions = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound;
UNUserNotificationCenter.Current.RequestAuthorization(authOptions, (granted, error) =>
{
Console.WriteLine(granted);
});
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.Current.Delegate = this;
Messaging.SharedInstance.RemoteMessageDelegate = this as IMessagingDelegate;
}
else
{
// iOS 9 <=
var allNotificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound;
var settings = UIUserNotificationSettings.GetSettingsForTypes(allNotificationTypes, null);
UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
}
UIApplication.SharedApplication.RegisterForRemoteNotifications();
Firebase.Analytics.App.Configure();
Firebase.InstanceID.InstanceId.Notifications.ObserveTokenRefresh((sender, e) =>
{
var newToken = Firebase.InstanceID.InstanceId.SharedInstance.Token;
System.Diagnostics.Debug.WriteLine(newToken);
connectFCM();
});
}
public override void DidEnterBackground(UIApplication uiApplication)
{
Messaging.SharedInstance.Disconnect();
}
public override void OnActivated(UIApplication uiApplication)
{
connectFCM();
base.OnActivated(uiApplication);
}
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
Firebase.InstanceID.InstanceId.SharedInstance.SetApnsToken(deviceToken, Firebase.InstanceID.ApnsTokenType.Prod);
}
//Fire when background received notification is clicked
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
//Messaging.SharedInstance.AppDidReceiveMessage(userInfo);
System.Diagnostics.Debug.WriteLine(userInfo);
// Generate custom event
NSString[] keys = { new NSString("Event_type") };
NSObject[] values = { new NSString("Recieve_Notification") };
var parameters = NSDictionary<NSString, NSObject>.FromObjectsAndKeys(keys, values, keys.Length);
// Send custom event
Firebase.Analytics.Analytics.LogEvent("CustomEvent", parameters);
if (application.ApplicationState == UIApplicationState.Active)
{
System.Diagnostics.Debug.WriteLine(userInfo);
var aps_d = userInfo["aps"] as NSDictionary;
var alert_d = aps_d["alert"] as NSDictionary;
var body = alert_d["body"] as NSString;
var title = alert_d["title"] as NSString;
debugAlert(title, body);
}
}
private void connectFCM()
{
Messaging.SharedInstance.Connect((error) =>
{
if (error == null)
{
Messaging.SharedInstance.Subscribe("/topics/topicName");
}
System.Diagnostics.Debug.WriteLine(error != null ? "error occured" : "connect success");
});
}
private void debugAlert(string title, string message)
{
var alert = new UIAlertView(title ?? "Title", message ?? "Message", null, "Cancel", "OK");
alert.Show();
}
}
}
Added all required Firebase libraries in IOS project & its building fine. But notification is not receiving on IOS simulator. Tell me what I am missing.
SOLVED
I had this same problem and was dealing with it for a day or two. The problem came down to the selected provisioning profile that was being used. When I changed my app id in the apple development portal to use push notification and downloaded my provisioning profile it created a second profile with the same name downloaded. This caused an error when it tried to select the correct one. Deleted the old provisioning profile and all is well now.
You cannot test push notification in the simulator
Please take a look on the Prerequisites.
For Cloud Messaging:
- A physical iOS device
- APNs certificate with Push Notifications enabled
- In Xcode, enable Push Notifications in App > Capabilities

sending email in xamarin forms

I'm trying to send an email in my xamarin forms project, I have tried both in the iPhone simulator and on an iPhone device. When I push the send email button on the iPhone, nothing happens, not even a debug error. I have also made sure i am logged in with my email on the device.
I have used serviceDependency and followed the setup at this link:
https://developer.xamarin.com/recipes/ios/shared_resources/email/send_an_email/
my interface:
public interface InterfaceEmail
{
void sendEmail();
}
iOS implementation:
[assembly: Xamarin.Forms.Dependency(typeof(SendEmail))]
namespace myProject.iOS
{
public partial class SendEmail : InterfaceEmail
{
MFMailComposeViewController mailController;
public SendEmail() {}
public void sendEmail()
{
if (MFMailComposeViewController.CanSendMail)
{
mailController = new MFMailComposeViewController();
mailController.SetToRecipients (new string[] {"my#email.com"});
mailController.SetSubject ("test mail");
mailController.SetMessageBody ("This is a test", false);
mailController.Finished += (object sender, MFComposeResultEventArgs e) =>
{
Console.WriteLine(e.Result.ToString());
e.Controller.DismissViewController(true, null);
};
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(mailController, true, null);
}}}}
Implementation in my shared code:
async void Handle_ToolbarButton(object sender, System.EventArgs e)
{
var action = await DisplayActionSheet("What do you want to do?", "Abort", null, "Send email");
if(action == "Send email")
{
DependencyService.Get<InterfaceEmail>().sendEmail();
}
}
Does anyone have an idea on what could be wrong here?
For a better way to send email without even writing platform specific code install this nuget into your solution
xam.plugin.Messaging(https://www.nuget.org/packages/Xam.Plugins.Messaging/)
Then write the code below in PCL
var email = new EmailMessageBuilder()
.To("to.plugins#xamarin.com")
.Subject("Xamarin Messaging Plugin")
.Body("Well hello there from Xam.Messaging.Plugin")
.Build();
You can also add attachments. For more details please go through https://github.com/cjlotz/Xamarin.Plugins/blob/master/Messaging/Details.md
Probably it is related to this bug:
https://bugzilla.xamarin.com/show_bug.cgi?id=58933
Just remove DisplayActionSheet.
Or if you want to use it, then there is a temporary solution in this Xamarin forum topic
Add
await Task.Delay(100);
after DisplayActionSheet
The iPhone simulator will always return false to CanSendMail as it can not send mail. On a physical device, you will need to configure at least on e mail account.
Also:
Typo in:
[assembly: Xamarin.Forms.Dependency(typeof(sendEmail))]
Should be:
[assembly: Xamarin.Forms.Dependency(typeof(SendEmail))]
Typo in:
mailController.Finnished += ~~~~~
Should be:
mailController.Finished += ~~~~~

Categories