'How can I open app when screen is off from foreground service?

Android: 11

NETStandard.Library: 2.0.3

Xamarin.Forms: 5.0.0.2012

Permissions(i tried):

"android.permission.FOREGROUND_SERVICE"
"android.permission.INSTANT_APP_FOREGROUND_SERVICE"
"android.permission.SYSTEM_ALERT_WINDOW"
"android.permission.DISABLE_KEYGUARD"
"android.permission.WAKE_LOCK"
"android.permission.MODIFY_PHONE_STATE"
"android.permission.RESTART_PACKAGES"

I have a security application that my clients want to know something all the time via SMS and firebase, so I have to keep the application open at all time, And I have to open Activity even when my app is closed and the screen is off,

To do that,I wrote BroadcastReceiver which is:

[BroadcastReceiver]
[IntentFilter(new[] { "android.provider.Telephony.SMS_RECEIVED" }, Priority = (int)IntentFilterPriority.HighPriority)]
public class SmsListener : BroadcastReceiver

SmsListener class always works fine.

and I have ForegroundService that work only on update notifications, play sound, Vibrate phone but I cannot open activity without error!

here is how i wrote this service:

public class AndroidServiceHelper : IAndroidService
{
    private static Context context = global::Android.App.Application.Context;
    public void StartService()
    {
        var intent = new Intent(context, typeof(AntiTheft));
        if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
        {
            context.StartForegroundService(intent);
        }
        else
        {
            context.StartService(intent);
        }
    }

    public void StopService()
    {
        var intent = new Intent(context, typeof(AntiTheft));
        context.StopService(intent);
    }
}

and here is my AntiTheft Class which is my service:

[Service(Enabled = true, Label = "xxxx")]
public class AntiTheft : Service
{ 
    public override IBinder OnBind(Intent intent)
    {
        return null;
    }
    public override void OnCreate()
    {
        base.OnCreate(); 
    }
    public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
    {
        Notification notif = DependencyService.Get<INotification>().ReturnNotif();

        StartForeground(Constants.SERVICE_RUNNING_NOTIFICATION_ID, notif);
        return StartCommandResult.Sticky;
    }
    public override void OnDestroy()
    {
        base.OnDestroy();
    }
    public override bool StopService(Intent name)
    {
        return base.StopService(name);
    }
}

and this is how I show AlarmActivity (I put everything I have tried so this isn't clean at all!):

 public void ShowAlert(string address, string message)
    {
        Toast.MakeText(context, message, ToastLength.Short).Show();
        Intent mainIntent = new Intent(context, typeof(AlertActivity));
        mainIntent.AddFlags(ActivityFlags.NewTask | ActivityFlags.ClearTop | ActivityFlags.SingleTop);
        mainIntent.PutExtra(address, message);
        context.StartActivity(mainIntent);

        //Intent launchIntent = Application.Context.PackageManager.GetLaunchIntentForPackage(Application.Context.PackageName);
        //Intent mainIntent = Intent.MakeRestartActivityTask(launchIntent.Component);
        //mainIntent.AddFlags(ActivityFlags.NewTask | ActivityFlags.ClearTop | ActivityFlags.SingleTop);
        //mainIntent.PutExtra(address, message);
        //context.StartActivity(mainIntent);

        Toast.MakeText(context, message, ToastLength.Short).Show();
        var f96v = (Vibrator)context.GetSystemService(Context.VibratorService);
        long[] vbf = { 100, 200, 200, 500, 500, 400, 400, 100 };
        f96v.Cancel();
        f96v.Vibrate(VibrationEffect.CreateWaveform(vbf, 1));

        var alarmAttributes = new AudioAttributes.Builder()
                   .SetContentType(AudioContentType.Music)
                   .SetUsage(AudioUsageKind.Alarm)
                   .Build();

        Android.Net.Uri alarmUri = Android.Net.Uri.Parse($"{ContentResolver.SchemeAndroidResource}://{Application.Context.PackageName}/{Resource.Raw.car_alarm}");
        var mNotificationManager = context.GetSystemService(Context.NotificationService) as NotificationManager;
        NotificationChannel notificationChannel = new NotificationChannel(Constants.FOREGROUND_CHANNEL_ID, "xxxx", NotificationImportance.Default);
        notificationChannel.Importance = NotificationImportance.High;
        notificationChannel.EnableLights(true);
        notificationChannel.EnableVibration(true);
        notificationChannel.SetSound(alarmUri, alarmAttributes);
        notificationChannel.SetShowBadge(true);
        notificationChannel.SetVibrationPattern(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 });
        notificationChannel.SetBypassDnd(true);
        notificationChannel.LockscreenVisibility = NotificationVisibility.Public;

        var pendingIntent = PendingIntent.GetActivity(context, 0, mainIntent, PendingIntentFlags.UpdateCurrent);
        var notification = new Notification.Builder(context, Constants.FOREGROUND_CHANNEL_ID)
                                                    .SetColor(Android.Resource.Color.DarkerGray)
                                                    .SetContentTitle(address)
                                                    .SetOngoing(true)
                                                    .SetContentText(message)
                                                    .SetSmallIcon(Resource.Mipmap.icon)
                                                    .SetContentIntent(pendingIntent);

        if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
        {
            notification.SetChannelId(Constants.FOREGROUND_CHANNEL_ID);
            mNotificationManager.CreateNotificationChannel(notificationChannel);
            mNotificationManager.Notify(Constants.SERVICE_RUNNING_NOTIFICATION_ID, notification.Build());
        }
    }

Edit 1: in my AlertActivity i have

  [Activity(Label = "AlertActivity", Name = "com.xxxx.xxxx.AlertActivity", AlwaysRetainTaskState = true, TurnScreenOn = true, NoHistory = true,
ShowForAllUsers = true, ShowWhenLocked = true,
LaunchMode = Android.Content.PM.LaunchMode.SingleInstance)]
internal class AlertActivity : Activity
{
    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        KeyguardManager keyguardManager = (KeyguardManager)GetSystemService(Context.KeyguardService);
        PowerManager pm = (PowerManager)GetSystemService(Context.PowerService);
        if (keyguardManager != null)
        {
            keyguardManager.RequestDismissKeyguard(this, null);
            PowerManager.WakeLock wl = pm.NewWakeLock(WakeLockFlags.Full | WakeLockFlags.AcquireCausesWakeup, "");
            wl.Acquire();
        }

        Window.AddFlags(WindowManagerFlags.ShowWhenLocked |
                        WindowManagerFlags.KeepScreenOn |
                        WindowManagerFlags.DismissKeyguard |
                        WindowManagerFlags.TurnScreenOn | WindowManagerFlags.AllowLockWhileScreenOn | WindowManagerFlags.TouchableWhenWaking);
         
        // Create your application here
        SetContentView(Resource.Layout.activity_alert);
        income = FindViewById<TextView>(Resource.Id.alert_text);
        start();
    }

every single help is life saving :)



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source