当前位置: 首页 > 知识库问答 >
问题:

使用Google Play服务位置在Android中唤醒过多警报管理器

舒嘉德
2023-03-14

我在Google Play控制台上收到了一份来自Android Vval的关于过度警报管理器唤醒的性能报告:

https://developer.android.com/topic/performance/vitals/wakeup.html

我使用Google Play Services的位置API在后台请求位置更新。报告显示,过度唤醒是由com引起的。谷歌。Android地方ALARM_WAKEUP_定位器来自LocationListener。

下面是导致报警的代码片段:

private synchronized void buildGoogleApiClient() {
    mGoogleApiClient = new GoogleApiClient.Builder(context)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
    mGoogleApiClient.connect();
}

/**
 * Runs when a GoogleApiClient object successfully connects.
 */
@Override
public void onConnected(Bundle connectionHint) {
    try {
        // Set location request
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(5 * 60000);
        mLocationRequest.setFastestInterval(60000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
        mLocationRequest.setMaxWaitTime(30 * 60000);

        // Create a pending intent to listening on location service when the update become available
        Intent mIntent = new Intent(context, LocationReceiver.class);
        mIntent.setAction(LocationReceiver.LOCATION_EXTRA);
        mPendingIntent = PendingIntent.getBroadcast(context, 42, mIntent, PendingIntent.FLAG_CANCEL_CURRENT);
        // Permission check before launching location services
        if (ContextCompat.checkSelfPermission(context,
                Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, mPendingIntent);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

此警报唤醒是否链接到google play services的位置API?

有人知道如何解决这个问题吗?

共有1个答案

左丘烨烁
2023-03-14

这是com的一个问题。谷歌。Android地方ALARM_WAKEUP_定位器每60秒唤醒一次设备,并使其保持15秒以上的清醒状态,从而导致严重的电池耗电问题。

已经有了通过外部应用程序使用手机的修复程序,并教会用户如何实际撤销应用程序的权限。

以下提供了减少应用程序电池使用的工具。

不可能为应用程序提供定制的解决方案,因为该解决方案取决于应用程序的用例和业务逻辑,以及您希望通过位置更新实现的成本效益分析

电池性能问题也就不足为奇了。通过以下设置:

mLocationRequest.setInterval(5 * 60000);
mLocationRequest.setFastestInterval(60000);
mLocationRequest.setMaxWaitTime(30 * 60000);

您的时间间隔设置为每5分钟(5*60000毫秒)更新一次。那是一天24小时。如果每5分钟更新一次:12次/小时==288次/天。

最快的间隔时间设定为1分钟(60000)。虽然这是可用的,因为位置可以在设备上的其他地方访问,但它仍然会在应用程序中使用电源)。

最大等待时间只有30分钟。这意味着设备最多每天被唤醒和轮询至少48次。

增加这些时间。

setMaxWaitTime。。。这可以消耗更少的电池,并根据设备的硬件功能提供更准确的位置。如果您不需要立即送货,您应该将该值设置为尽可能大,以满足您的需求。。。

在Android8系统中,谷歌将请求数量限制在每小时几次。考虑将此作为设置请求间隔的指南。

特定时间范围内的更新数量可能会受到限制。通过在使用更新次数后主动取消位置请求,或在请求上设置过期时间。通过这种方式,应用程序可以通过在应用程序内的某个触发器上创建一个请求来进行管理,并小心地进行管理,以使其不会无休止地继续。创建流很困难,因为我不知道该应用的用例。

setNumUpdates(整数numUpdates)

默认情况下,位置会持续更新,直到请求被明确删除,但是您可以选择请求一组更新。例如,如果您的应用程序只需要一个新的位置,那么在将请求传递给位置客户端之前,请使用值1调用此方法。

另一个选项是在不需要时管理站点位置更新。这些链接给出了在活动失去焦点时调用此功能的示例,但它可以在应用程序中实现,在满足某些要求(在您的业务逻辑中)时,甚至可以通过让用户在应用程序本身中打开和关闭来实现。

确保你的应用程序没有忽略电池优化。

此外,根据业务逻辑,管理setSmallestDisplace(浮点小位移计)将有助于微调应用程序。

以下是在更新问题之前写的。

开发人员和用户可以设置应用程序更新的频率。间隔和优先级。

您可以在发出位置请求时设置这些选项,例如:

protected void createLocationRequest() {
    LocationRequest mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(10000);
    mLocationRequest.setFastestInterval(5000);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
}

此外,还有一个“优先权”的设置,这意味着应用程序只有在用户要求时才会获得更新。

您需要提示用户更改位置设置

task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
    @Override
    public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
        // All location settings are satisfied. The client can initialize
        // location requests here.
        // ...
    }
});

task.addOnFailureListener(this, new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception e) {
        int statusCode = ((ApiException) e).getStatusCode();
        switch (statusCode) {
            case CommonStatusCodes.RESOLUTION_REQUIRED:
                // Location settings are not satisfied, but this can be fixed
                // by showing the user a dialog.
                try {
                    // Show the dialog by calling startResolutionForResult(),
                    // and check the result in onActivityResult().
                    ResolvableApiException resolvable = (ResolvableApiException) e;
                    resolvable.startResolutionForResult(MainActivity.this,
                            REQUEST_CHECK_SETTINGS);
                } catch (IntentSender.SendIntentException sendEx) {
                    // Ignore the error.
                }
                break;
            case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                // Location settings are not satisfied. However, we have no way
                // to fix the settings so we won't show the dialog.
                break;
        }
    }
});

要管理用户设置的更改,请使用位置回拨。

... 除了位置更新之外,您还可以使用新的LocationCallback类代替现有的LocationListener来接收LocationAvailability更新,从而在设置发生更改时提供一个简单的回调,这将影响当前的LocationRequests集。

为了降低功耗,Android 8.0(API级别26)限制了后台应用程序检索用户当前位置的频率。应用程序每小时只能接收几次位置更新。

注意:这些限制适用于运行Android 8.0(API级别26)或更高版本的设备上使用的所有应用,无论应用的目标SDK版本如何。

这可能与警报管理器有关。

这不是一个简单的修复,最终您需要重写如何安排更新。

>

  • 为了至少减缓问题,您需要调试代码并找到警报管理器调用或创建计划并减少间隔的任何实例。

    之后,您将需要重写应用程序的整个位置更新调度部分。

    解决问题

    在你的应用程序中确定你安排唤醒警报的位置,并降低触发这些警报的频率。以下是一些提示:

    • 查找对警报管理器中包含RTC_WAKEUP或ELAPSED_REALTIME_WAKEUP标志的各种set()方法的调用。
    • 我们建议在警报的标记名称中包含您的包、类或方法名称,以便您可以轻松识别源中设置警报的位置。以下是一些额外的提示:
      • 在名称中省略任何个人识别信息(PII),例如电子邮件地址。否则,设备会记录_UNKNOWN而不是警报名称。
      • 不要以编程方式获取类或方法名称,例如通过调用getName(),因为它可能会被ProGuard混淆。相反,使用硬编码字符串。
      • 不要向警报标签添加计数器或唯一标识符。系统将无法聚合以这种方式设置的警报,因为它们都有唯一标识符。

      解决问题后,通过运行以下ADB命令验证唤醒警报是否正常工作:

      adb外壳转储系统警报

      此命令提供有关设备上警报系统服务的状态的信息。有关详细信息,请参阅Dumasps。

      如果你对上述任何一个有特殊的问题,你需要用mcve发布另一个问题。

      为了改进应用程序,需要按照最佳实践中所述重写代码。不要使用闹钟管理器来安排后台任务,如果手机处于睡眠状态,则定位将被视为后台任务。而且你说这是一项背景任务。使用JobScheduler或Firebase JobDispatcher。

      如果报警管理器是更好的选择(这里没有),那么很重要的一点是阅读这里的内容,安排重复报警,但您需要了解折衷

      设计不当的警报可能会导致电池耗尽,并给服务器带来巨大的负载。

  •  类似资料:
    • 目前,我正在开发一个新的android项目,它使用后台服务。因为android版本 我的通知服务如下 我使用以下代码启动AlarmHandler 我还注册了以下广播接收器 我的问题是有时它会跳过我的通知。时间安排为晚上10:00和早上7:00。收到晚上10点的通知(请注意,我在晚上10:00使用电话或在晚上10:00前几分钟使用)。但并非所有时间都收到上午7:00的通知。还要注意的是,我每天都需要

    • Future 一次polled 就能完成的,并不常见。而多数情况下,Future 需要确保一旦准备好前进,就再次进行轮询(poll) 。而这是通过Waker类型,辅助完成的。 每次 Future poll 时,都会将其作为“任务(task)”的一部分。任务是已提交给 executor 的顶级 Future 。 Waker提供一个wake()方法,它可以用来告诉 executor,应该唤醒的相关任务

    • 我已经按照在Android应用程序中实现GCM的示例,该应用程序正在使用以下代码接收消息: 问题是GCMinentService(公共类GCMinentService扩展了IntentService)从未运行过?我是否遗漏了什么,或者它通常应该触发onHandleIntent方法? 如果以任何方式与清单文件相关,请提前感谢:

    • 我想在我的LibGDX Android游戏中使用Google Play Game Services API的成就和排行榜。我所做的唯一一件事就是从游戏服务开发者网站上获取运行的示例。我已经尝试在我的项目中使用这段代码很多天了,但仍然一无所获。我也尝试过学习本教程http://helios.hud.ac.uk/u1070589/blog/?p=202但我没有“主游戏类(从ApplicationLis