How to keep CPU active during a foreground service, NET MAUI?

202 views Asked by At

As explained in this question:How to continue scanning WiFi networks in the background on Android I'm creating an app with NET MAUI which has a service in the foreground, which scans nearby wifi networks, saves the results in a list, and if it finds a certain SSID it has to carry out some operations. As explained in this other question: How to run a service in the Background when the screen is blank, NET MAUI app? my app when closed and the device is active, the app works perfectly. When I turn off the screen the service starts working. Now, thanks to the advice I received in the forget question, my app also works with the screen off, BUT only if connected to the charger. Can you tell me why??

 [Service(Name = "com.BackgroudAppTest.DemoServices")]
 public class DemoServices : Service, IServicesTest
 {
     private PowerManager.WakeLock wakeLock;  
     public int numeroUscite;
     private WifiManager wifiManager;
     private ObservableCollection<string> wifiNetworks = new ObservableCollection<string>();

     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)
           
         if (intent.Action == "START_SERVICE")
         {
             wifiManager = (WifiManager)Android.App.Application.Context.GetSystemService(Android.Content.Context.WifiService);

             //Mantiene la CPU attiva quando lo schermo viene spento 
             WakeLockFlags wakeFlags = WakeLockFlags.Partial;
             var powerManager = (PowerManager)GetSystemService(PowerService);
             wakeLock = powerManager.NewWakeLock(wakeFlags, typeof(DemoServices).FullName);
             wakeLock.Acquire();

             System.Diagnostics.Debug.WriteLine("il servizio è iniziato");
             Task.Delay(2000);                
             //ricevo il numero dall utente
              int intValue = intent.GetIntExtra("MyIntValue", -1) -1;
             //ricevo SSID dall utente
             string userString = intent.Extras.GetString("MySsid");

              Task.Run(async () =>
              {
                   while (true)
                   {
                      bool foud = false;
                      var database = new Database();

                      wifiNetworks.Clear();
                      wifiManager.StartScan();
                      await Task.Delay(5000);
                      IList<ScanResult> scanResults = wifiManager.ScanResults;
                      foreach (ScanResult scanResult in scanResults)
                      {
                          wifiNetworks.Add(scanResult.Ssid);
                          if (scanResult.Ssid.Equals(userString, StringComparison.OrdinalIgnoreCase))
                          {
                              foud = true;
                              break;                                
                          }                       
                      }

                      if (foud)
                      {
                          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);
                      }


                      // Attendi prima di eseguire una nuova scansione
                      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.Sticky;
     }
     
     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()
     {
         if (wakeLock != null && wakeLock.IsHeld)
         {
             wakeLock.Release();
             wakeLock = null;
         }
         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_textfield_search_default_mtrl_alpha)
             .SetOngoing(true)
             .Build();

         StartForeground(100, notification);
     }
 }

AndroidManifest.xaml

<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" />
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> 
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    
</manifest>

1

There are 1 answers

0
Liyun Zhang - MSFT On BEST ANSWER

The different phone manufacturers have different battery optimization policies. According to the OEM battery optimization IssueTracker:

Samsung continues to run these shady practices by disabling wake-locks and broadcast messages without user or developer consent

So you can try to test the foreground service with the wake-lock on the android emulator not the Samsung device.

In addition, you can refer to this blog about battery optimization on Samsung and the part of how to prevent certain apps from going to sleep or deep sleep, follow the instructions below in the official document about Samsung Galaxy Battery optimization.