Xamarin Forms - 如何检查 Android 上的 RequestIgnoreBatteryOptimizations 权限设置

use*_*634 3 android xamarin.forms xamarin.essentials

(请参阅下面的更新)

我在 Android 上有一个 Xamarin Forms 应用程序,它使用 Xamarin.Essentials 库。

该应用程序需要在后台运行以获取位置数据(与当前的问题不是特别相关,但包含在上下文中),因此不得通过操作系统可能尝试的任何电池优化来使其进入睡眠状态。

我知道用户可以手动从电池优化中选择退出特定应用程序,但由于它对于应用程序的成功运行至关重要,我希望该应用程序能够:

  1. 检查电池优化选择退出权限状态以确保其设置正确,

和/或

  1. 强制 Android 选择任何电池优化的应用程序。

我已在 AndroidManifest.xml 中添加了一个条目,但它似乎没有帮助,新安装的应用程序默认为电池优化。

AndroidManifest.xml

该清单包含以下条目:

<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
Run Code Online (Sandbox Code Playgroud)

Xamarin.Essentials

该库允许访问设备上的许多与权限相关的信息,但电池优化似乎不是其中之一。

正在使用的设备

我不知道这是否相关,但我正在三星 Galaxy S20 Ultra 上进行测试。

有人可以提供任何建议吗?

2021 年 8 月 28 日更新

遵循贡献者的建议并参考https://learn.microsoft.com/en-us/xamarin/essentials/permissions?tabs=android#extending-permissions上的文档...

在我的共享代码中

public interface IRequestIgnoreBatteryOptimizationPermission
{
    Task<PermissionStatus> CheckStatusAsync();
    Task<PermissionStatus> RequestAsync();
}
Run Code Online (Sandbox Code Playgroud)

在我的 Android 项目中

[assembly: Xamarin.Forms.Dependency(typeof(RequestIgnoreBatteryOptimizationPermission))]

namespace MyAndroidProject
{
    public class RequestIgnoreBatteryOptimizationPermission : Permissions.BasePlatformPermission, IRequestIgnoreBatteryOptimizationPermission
    {
        public override (string androidPermission, bool isRuntime)[] RequiredPermissions => new List<(string androidPermission, bool isRuntime)>
        {
            (Android.Manifest.Permission.RequestIgnoreBatteryOptimizations, true)
        }.ToArray();
    }
}
Run Code Online (Sandbox Code Playgroud)

关于共享应用程序初始化

// Ensure Required Permissions have been granted
var requestIgnoreBatteryOptimizationPermission = DependencyService.Get<IRequestIgnoreBatteryOptimizationPermission>();
            
var status = requestIgnoreBatteryOptimizationPermission.CheckStatusAsync().Result;

if (status != PermissionStatus.Granted)
{
    status = requestIgnoreBatteryOptimizationPermission.RequestAsync().Result;
}
Run Code Online (Sandbox Code Playgroud)

结果...

调用时CheckStatusAsync,结果返回为Granted

但应用程序设置仍然另有说明......

在此输入图像描述

在此输入图像描述

我已经在物理设备(Samsung Galaxy S20 Ultra)和 Android 模拟器(Pixel 2 API 28)上进行了尝试,两者的结果相同。

Che*_*SFT 5

本文档来看,有两种方法可以设置电池优化

应用程序可以激发ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS意图,将用户直接带到Battery Optimization,在那里他们可以添加应用程序。

持有该REQUEST_IGNORE_BATTERY_OPTIMIZATIONS权限的应用程序可以触发系统对话框,让用户直接将应用程序添加到豁免列表中,而无需进入设置。应用程序触发一个ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONSIntent 来触发对话框。

我使用PowserManager.isIgnoringBatteryOptimizations来检查电池优化。

首先,RequestIgnoreBatteryOptimizations在AndroidManifest.xml中添加

<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
Run Code Online (Sandbox Code Playgroud)

然后在共享代码中创建接口。

public interface IBattery
{
     void getbattery();     
}
Run Code Online (Sandbox Code Playgroud)

在Android平台上实现该接口。

[assembly: Dependency(typeof(ImplementBattery))]
namespace FormsSample.Droid
{
public class ImplementBattery : IBattery
{
    public void getbattery()
    {
        Intent intent = new Intent();
        String packageName = MainActivity.mac.PackageName;
        PowerManager pm = (PowerManager)MainActivity.mac.GetSystemService(Context.PowerService);
        if (pm.IsIgnoringBatteryOptimizations(packageName))
            intent.SetAction(Android.Provider.Settings.ActionIgnoreBatteryOptimizationSettings);
        else
        {
            intent.SetAction(Android.Provider.Settings.ActionRequestIgnoreBatteryOptimizations);
            intent.SetData(Android.Net.Uri.Parse("package:" + packageName));
        }
        MainActivity.mac.StartActivity(intent);
    }
}
}
Run Code Online (Sandbox Code Playgroud)

在 Mainactivity.cs 中创建静态 Mainactivity 字段。

  public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
    public static MainActivity mac;
    protected override void OnCreate(Bundle savedInstanceState)
    {
        initFontScale();
        TabLayoutResource = Resource.Layout.Tabbar;
        ToolbarResource = Resource.Layout.Toolbar;
        
        base.OnCreate(savedInstanceState);
       
        mac = this;
Run Code Online (Sandbox Code Playgroud)

现在,使用 DependencyService 来触发。

   private void Button_Clicked(object sender, EventArgs e)
    {
        DependencyService.Get<IBattery>().getbattery();
    }
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述