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

Posted

技术标签:

【中文标题】Xamarin Forms - 如何检查 Android 上 RequestIgnoreBatteryOptimizations 权限的设置【英文标题】:Xamarin Forms - How to check setting of RequestIgnoreBatteryOptimizations permission on Android 【发布时间】:2021-10-23 21:40:51 【问题描述】:

(见下面的更新)

我在 android 上有一个使用 Xamarin.Essentials 库的 Xamarin Forms 应用程序。

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

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

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

和/或

    强制 Android 选择任何电池优化的应用。

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

AndroidManifest.xml

清单包含以下条目:

<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />

Xamarin.Essentials

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

正在使用的设备

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

谁能给点建议?

2021 年 8 月 28 日更新

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

在我的共享代码中

public interface IRequestIgnoreBatteryOptimizationPermission

    Task<PermissionStatus> CheckStatusAsync();
    Task<PermissionStatus> RequestAsync();

在我的 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();
    

关于共享应用初始化

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

if (status != PermissionStatus.Granted)

    status = requestIgnoreBatteryOptimizationPermission.RequestAsync().Result;

结果...

调用CheckStatusAsync 时,结果返回为Granted

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

我在物理设备(Samsung Galaxy S20 Ultra)和 Android 模拟器(Pixel 2 API 28)上都试过了,结果都一样。

【问题讨论】:

你不应该得到这样的结果 status = requestIgnoreBatteryOptimizationPermission.RequestAsync().Result; 等待结果,否则按照我在回答中的建议进行操作 【参考方案1】:

来自this document,有两种设置电池优化的方法

应用可以触发ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS Intent,将用户直接带到Battery Optimization,在那里他们可以添加应用。

拥有REQUEST_IGNORE_BATTERY_OPTIMIZATIONS 权限的应用可以触发系统对话框,让用户直接将应用添加到豁免列表,而无需进入设置。该应用会触发 ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS Intent 以触发对话框。

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

首先,在AndroidManifest.xml中添加RequestIgnoreBatteryOptimizations

<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />

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

public interface IBattery

     void getbattery();     

在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);
    


在 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;

现在,使用 DependencyService 来触发。

   private void Button_Clicked(object sender, EventArgs e)
    
        DependencyService.Get<IBattery>().getbattery();
    

【讨论】:

太棒了。这是一种享受。感谢您分享您的智慧......! :)【参考方案2】:

在您的MainActivity 中添加两个属性:

private const int RequestPermissionsId = 0

private readonly string[] ManifestPermissions =

    Manifest.Permission.RequestIgnoreBatteryOptimizations
    // Add here other permissions you want to check

然后重写 OnStart 方法并在那里强制进行权限检查:

public override void OnStart()

    base.OnStart();
    
    if ((int)Build.VERSION.SdkInt >= 23)
    
        if (CheckSelfPermission(Manifest.Permission.RequestIgnoreBatteryOptimizations != Permission.Granted)
            RequestPermissions(ManifestPermissions, RequestPermissionsId);
    

当然,请记住,您必须实现 OnRequestPermissionsResult 方法:

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)

    Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

    base.OnRequestPermissionsResult(requestCode, permissions, grantResults);

【讨论】:

感谢您的建议。它把我带到了我忽略的文档的一部分。我仍然有这个应用程序默认设置为电池优化的问题。我已经用最新的详细信息更新了我的问题。【参考方案3】:

嗯,我猜你正在尝试通过共享代码直接检查它

最简单的方法是使用 Essentials 在本机中扩展所需的权限。

通过接口查看状态和请求权限:

 public interface IRequestIgnoreBatteryOptimizations
 
    Task<PermissionStatus> CheckStatusAsync();
    Task<PermissionStatus> RequestAsync();
 

实现相同的原生部分:

 public class IgnoreBatteryOptimizationsPlatformPermission : Xamarin.Essentials.Permissions.BasePlatformPermission, IRequestIgnoreBatteryOptimizations
 
    public override (string androidPermission, bool isRuntime)[] RequiredPermissions =>
             new (string, bool)[]  (Manifest.Permission.RequestIgnoreBatteryOptimizations, true) ;
 

然后在你的 Native XF 调用者类中注册它(MainActivity,Appdelegate(获取其他权限))

 DependencyService.Register<IRequestIgnoreBatteryOptimizations, IgnoreBatteryOptimizationsPlatformPermission>();

然后在你的 XF 类中使用这个方法:

 public static async Task<PermissionStatus> CheckAndRequestBatteryOptimizations()
    
        var batteryOptimizationsPermission = DependencyService.Get<IRequestIgnoreBatteryOptimizations>();
        var status = await batteryOptimizationsPermission.CheckStatusAsync();
        if (status != PermissionStatus.Granted)
        
            status = await batteryOptimizationsPermission.RequestAsync();
        
        return status;
    

然后随时请求:

var status= await CheckAndRequestBatteryOptimizations();

更多信息在这里:https://docs.microsoft.com/en-us/xamarin/essentials/permissions?tabs=android#extending-permissions

【讨论】:

感谢您的建议。我试了一下,但结果是一样的,应用程序仍然设置为优化电池。虽然没有错误/异常。然后,我在 Xamarin Essentials 文档中采取了不同的方法来扩展权限,但同样的结果不正确。请参阅我的问题中的更新。

以上是关于Xamarin Forms - 如何检查 Android 上 RequestIgnoreBatteryOptimizations 权限的设置的主要内容,如果未能解决你的问题,请参考以下文章

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

Xamarin Forms:如何在 Xamarin ios 应用程序中检查 GPS 是打开还是关闭?

Xamarin.Forms Android 保留汉堡包/菜单图标而不是后退按钮

Xamarin.Forms(2.5.0.122203)使用Zxing.Net.Mobile.Forms(2.3.3)时,Android端莫名崩溃

如何正确使用 Xamarin.Forms 的 Image Source 属性?

我怎么看我的代码如何执行xamarin.forms