Search code examples
c#androidxmlmobilemaui

How to run a service in the Background when the screen is blank, NET MAUI app?


Thanks to the help of the community I managed to solve the problem I had here: How to continue scanning WiFi networks in the background on Android text; As I already explained in the previous question, I have to create a background service that scans WiFi networks and if it finds a network with a specific SSID, it has to do some operations. In the previous question I was unable to scan networks in the background, this problem has now been resolved. My current problem is that when the app is closed and you continue to use the device, the service works perfectly, when the device is put in stambay (screen off), the service stops working, as soon as I unlock the device the service restarts . Can someone help me ?

Android\Resource\DemoServices.cs

[Service(Name = "com.BackgroudAppTest.DemoServices")]
public class DemoServices : Service, IServicesTest
{   
    public int numeroUscite;
    public List<string> wifiResults = new List<string>();
    public string ssid;
    public override void OnCreate()
    {
        base.OnCreate(); 
    }
    public override IBinder OnBind(Intent intent)
    {
        throw new NotImplementedException();
    }
    [return: GeneratedEnum]
    public override StartCommandResult OnStartCommand(Intent intent, [GeneratedEnum] StartCommandFlags flags, int startId)
    {
        //service start
        if (intent.Action == "START_SERVICE")
        {
            System.Diagnostics.Debug.WriteLine("il servizio è iniziato");

            Task.Delay(2000);                
            //I receive the number from the user
            int intValue = intent.GetIntExtra("MyIntValue", -1) -1;
            string userString = intent.Extras.GetString("MySsid");
                // Run the WiFi scan
             Task.Run(async () =>
             {
                  while (true)
                  {
                     List<string> wifiResults = new List<string>();

                     var database = new Database();

                     wifiResults.Clear(); // Cleans up previous results

                     
                     var wifiManager = (WifiManager)Android.App.Application.Context.GetSystemService(Context.WifiService);
                     var wifiList = wifiManager.ScanResults;

                        // Check if the specific SSID "myssid" exists in the list
                     bool mySsidExists = wifiList.Any(scanResult => scanResult.Ssid.Equals(userString));

                     if (mySsidExists)
                     {
                         intValue++;
                         MessItem nuovoGeoItem = new MessItem
                         {
                             Data = DateTime.Now,
                             Descrizione = "Entrato " + intValue
                         };
                         int esito = await database.AggiungiGeoItem(nuovoGeoItem);
                     }
                     else
                     {
                         numeroUscite++;
                         MessItem nuovoGeoItem = new MessItem
                         {
                             Data = DateTime.Now,
                             Descrizione = "Uscito " + numeroUscite
                         };
                         int esito = await database.AggiungiGeoItem(nuovoGeoItem);
                     }
                        //Please wait before running a new scan 
                        await Task.Delay(TimeSpan.FromMinutes(1));
                  }             
             });
            RegisterNotification();  
        }
        //stop servizio
        else if (intent.Action == "STOP_SERVICE")
        {
            System.Diagnostics.Debug.WriteLine("il servizio è fermato");
            StopForeground(true);
            StopSelfResult(startId);
        }
        return StartCommandResult.NotSticky;
    }
   
    public void Start()
    {
        Intent startService = new Intent(MainActivity.ActivityCurrent, typeof(DemoServices));
        startService.SetAction("START_SERVICE");
        MainActivity.ActivityCurrent.StartService(startService);
    }
    public void Stop()
    {          
        Intent stopIntent = new Intent(MainActivity.ActivityCurrent, this.Class);
        stopIntent.SetAction("STOP_SERVICE");
        MainActivity.ActivityCurrent.StartService(stopIntent);
    }
    public override void OnDestroy()
    {
        base.OnDestroy();
    }
    private void RegisterNotification()
    {
        NotificationChannel channel = new NotificationChannel("ServicioChannel", "Servizio Scan", NotificationImportance.Max);
        NotificationManager manager = (NotificationManager)MainActivity.ActivityCurrent.GetSystemService(Context.NotificationService);
        manager.CreateNotificationChannel(channel);
        Notification notification = new Notification.Builder(this, "ServicioChannel")
            .SetContentTitle("Servizo Attivo")
            .SetSmallIcon(Resource.Drawable.abc_switch_thumb_material)
            .SetOngoing(true)
            .Build();

        StartForeground(100, notification);
    }
}

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true">
        <service
            android:name=".Services.DemoServices"
            android:exported="false"
            android:stopWithTask="false" />     
    </application>
    
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.NETWORK_SETUP_WIZARD" />
    <uses-permission android:name="android.permission.NETWORK_SETTINGS" />
    <uses-permission android:name="android.permission.PROCESS_STATE_BACKGROUND" />
    <uses-permission android:name="android.permission.PROCESS_STATE_CACHED" />
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />    
    
</manifest>


Solution

  • You can check the wakelock to control the application awake when the sereen was locked.

    First, you need to create a foreground service inherited from Android.App.Service. Then, you need to create a broadcasereceiver to get the recieves SCREEN_OFF events.

    Here is the code and build steps about how to make the app awake after locking the screen you can refer to.