I've got a serious problem with power saving mode on Android. My application crashes when power saving mode is enabled. The problem manifests itself on Samsung Galaxy phones (or on any phone/emulator with AOSP or LineageOS), but it never happened on Meizu or Xiaomi (due to their own battery optimizations, I guess; the code below always returns false, doesn't matter if I turned on power saving mode on these phones).
1st test: power saving mode disabled, app works great.
2nd test: power saving mode enabled, app not whitelisted, app crashes on launch.
3rd test: power saving mode disabled, app started and minimized; when I enable power saving mode, app asks me to add itself to white list; even if I add app to the white list, app still may crash.
4th test: power saving mode enabled, app whitelisted; app works partly, crashes or freezes randomly.
I know about Doze mode and enabled REQUEST_IGNORE_BATTERY_OPTIMIZATIONS permission in AndroidManifest.xml. Here's my code that checks if power saving mode is enabled and if app is in the white list. But my app crashes before this code being reached (except one issue that I've described).
PowerWorker.cs
[assembly: Dependency(typeof(BSWApp.Droid.PowerWorker))]
namespace MyApp.Droid
{
class PowerWorker : IPowerWorker
{
public bool IsInPowerSavingMode()
{
PowerManager powerManager = (PowerManager)Application.Context.GetSystemService(Context.PowerService);
bool isPowerSaveMode = powerManager.IsPowerSaveMode;
return isPowerSaveMode;
}
public bool IsInWhiteList(string packageName)
{
PowerManager powerManager = (PowerManager)Application.Context.GetSystemService(Context.PowerService);
bool isInWhiteList = powerManager.IsIgnoringBatteryOptimizations(packageName);
return isInWhiteList;
}
public void RequestWhiteList(string packageName)
{
Application.Context.StartActivity(new Intent(Provider.Settings.ActionRequestIgnoreBatteryOptimizations, Net.Uri.Parse("package:"+packageName)));
}
}
}
Logcat from crash moment:
01-31 02:31:58.015 1511 1511 E AndroidRuntime: FATAL EXCEPTION: main
01-31 02:31:58.015 1511 1511 E AndroidRuntime: Process: [hidden], PID: 1511
01-31 02:31:58.015 1511 1511 E AndroidRuntime: android.runtime.JavaProxyThrowable: System.NullReferenceException: Object reference not set to an instance of an object
01-31 02:31:58.015 1511 1511 E AndroidRuntime: at MyApp.Handlers.MessageHandler+<DisplayConfirmation>d__3.MoveNext () [0x00014] in <bf9ac05a02a44989a618d26fad48d12d>:0
01-31 02:31:58.015 1511 1511 E AndroidRuntime: --- End of stack trace from previous location where exception was thrown ---
01-31 02:31:58.015 1511 1511 E AndroidRuntime: at MyApp.ViewModels.PowerWorkerViewModel+<LaunchPowerSettings>d__1.MoveNext () [0x0006e] in <bf9ac05a02a44989a618d26fad48d12d>:0
01-31 02:31:58.015 1511 1511 E AndroidRuntime: --- End of stack trace from previous location where exception was thrown ---
01-31 02:31:58.015 1511 1511 E AndroidRuntime: at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__6_0 (System.Object state) [0x00000] in <fe08c003e91342eb83df1ca48302ddbb>:0
01-31 02:31:58.015 1511 1511 E AndroidRuntime: at Android.App.SyncContext+<>c__DisplayClass2_0.<Post>b__0 () [0x00000] in <ad2f15102b3a4d36b40e9b0cbc11c376>:0
01-31 02:31:58.015 1511 1511 E AndroidRuntime: at Java.Lang.Thread+RunnableImplementor.Run () [0x00008] in <ad2f15102b3a4d36b40e9b0cbc11c376>:0
01-31 02:31:58.015 1511 1511 E AndroidRuntime: at Java.Lang.IRunnableInvoker.n_Run (System.IntPtr jnienv, System.IntPtr native__this) [0x00009] in <ad2f15102b3a4d36b40e9b0cbc11c376>:0
01-31 02:31:58.015 1511 1511 E AndroidRuntime: at (wrapper dynamic-method) System.Object.17(intptr,intptr)
01-31 02:31:58.015 1511 1511 E AndroidRuntime: at mono.java.lang.RunnableImplementor.n_run(Native Method)
01-31 02:31:58.015 1511 1511 E AndroidRuntime: at mono.java.lang.RunnableImplementor.run(RunnableImplementor.java:30)
01-31 02:31:58.015 1511 1511 E AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:751)
01-31 02:31:58.015 1511 1511 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:95)
01-31 02:31:58.015 1511 1511 E AndroidRuntime: at android.os.Looper.loop(Looper.java:154)
01-31 02:31:58.015 1511 1511 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6077)
01-31 02:31:58.015 1511 1511 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
01-31 02:31:58.015 1511 1511 E AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
01-31 02:31:58.015 1511 1511 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
01-31 02:31:58.016 534 546 W ActivityManager: Force finishing activity [hidden]/md5be088b8fe6dd8127a24806968ac5b197.MainActivity
No matter where I try to run it from (I tried from App.cs (shared code) and from MainActivity.cs (Android local code)), I still getting same result. I expected that app will ask user to add application to the whitelist, but in fact even if user did it, it doesn't matter, 'cause app still may crash even if whitelisted. So I'm completely confused what to do.