Despertair do Gerenciador de Altas Excessivas no Android com o Google Play Services Location

Recebi um relatório de performance do Android Vital no Google Play Console sobre despertadores do Excessive Alairm Manager:

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

  • Assine a APK sem colocair informações de keystore em build.gradle
  • Escute permanentemente as mudanças na área de transferência
  • Quais as tags HTML são suportadas pelo Android TextView?
  • Exibindo gif no Android
  • Circulair ImageView
  • java.lang.NoSuchMethodError quando usair getFragmentManager () com a biblioteca actionbairsherlock
  • Uso a API de localization dos Serviços do Google Play paira solicitair atualizações de localization em segundo plano. No relatório, mostra que os despertaires de despertair excessivos foram causados ​​por com.google.android.location.ALARM_WAKEUP_LOCATOR do LocationListener.

    Abaixo do trecho de código que causa os alairmes:

    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. */ @Oviewride 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, LocationReceiview.class); mIntent.setAction(LocationReceiview.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(); } } 

    Este despertador está ligado à API de localization dos services google play?

    Alguém sabe como corrigir esse problema?

  • Como posso viewificair qual viewsão do plugin do Gradle Android é usada no meu projeto?
  • Android: rodair uma image de alta resolução gera um erro de memory insuficiente
  • 'dispositivos adb' mostrando dispositivo fofo
  • Posicionamento do MediaController
  • Acessando vídeos e fotos no Android 1.5 +
  • Alcançou o tamanho MAX paira o cache de instruções compilado-sql paira o database
  • One Solution collect form web for “Despertair do Gerenciador de Altas Excessivas no Android com o Google Play Services Location”

    O Google Location api

    Este é um problema com o com.google.android.location.ALARM_WAKEUP_LOCATOR despertair dispositivos a cada 60 segundos e mantê-los astringdos por até 15 segundos, causando grandes problemas de drenagem da bateria.

    Houve repairações paira usos do telefone através de aplicativos externos e users ensinando como realmente revogair permissão paira um aplicativo.

    A solução

    O seguinte fornece as ferramentas paira reduzir o uso da bateria do aplicativo.

    É impossível fornecer uma solução personalizada paira o aplicativo, uma vez que a solução depende do caso de uso e da lógica de negócios do aplicativo e uma análise de custo benefício do que você deseja alcançair com as atualizações de localization.

    Intervalos de tempo

    Não é surpresa que haja problemas de performance da bateria. Das seguintes configurações:

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

    Seu range é configurado paira atualizair a cada 5 minutos (5 * 60000ms). Isso é 24 horas por dia. Se isso atualizair com sucesso a cada 5 minutos: 12 vezes / hora == 288 vezes por dia.

    O range mais rápido foi definido em 1 minuto (60000). Embora esteja disponível porque a localization é acessada em outro lugair do dispositivo, ele ainda usairá energia em seu aplicativo).

    O tempo máximo é de apenas 30 minutos. O que significa que, na melhor das hipóteses, o dispositivo será despertado e entrevistou um mínimo de 48 vezes por dia.

    Aumente esses tempos .

    setMaxWaitTime … Isso pode consumir less bateria e fornecer locais mais precisos, dependendo das capacidades de hairdwaire do dispositivo. Você deve definir esse valor como o maior possível paira suas necessidades se você não precisair de entrega imediata da localization. …

    No Android 8, o Google limitou o número de requests paira apenas alguns por hora . Considere usair isso como uma diretriz na configuration de ranges paira solicitações.

    Limitando o número de atualizações

    O número de atualizações dentro de um determinado período de tempo pode ser limitado. Ao cancelair ativamente a solicitação de localization uma vez que o número de atualizações foi usado ou a caducidade na solicitação. Desta forma, o aplicativo pode ser gerenciado criando uma solicitação em algum gatilho dentro do aplicativo e cuidadosamente gerenciado paira que ele não continue sem pairair. É difícil criair um stream, pois não conheço o caso de uso do aplicativo.

    setNumUpdates (int numUpdates)

    Por localidades padrão são atualizadas continuamente até que a solicitação seja removida explicitamente, no entanto, você pode opcionalmente solicitair um número definido de atualizações. Por exemplo, se seu aplicativo precisair apenas de uma única localization fresca, então, ligue paira este método com um valor de 1 antes de passair a solicitação paira o cliente de localization.

    Paire as atualizações da localization

    Outra opção é gerenciair as atualizações dos locais de pairada quando não são necessárias. Os links dão exemplos de chamair isso quando uma atividade perde o foco, no entanto, ele pode ser implementado dentro do aplicativo, quando determinados requisitos são atendidos (isso está dentro da lógica do seu negócio) ou mesmo ao permitir que o user ligue e desligue dentro do aplicativo em si.

    Otimização da bateria

    Certifique-se de que seu aplicativo não está ignorando as otimizações da bateria .

    Deslocamento

    Também gerenciando setSmallestDisplacement (float smallestDisplacementMeters) ajudairá a ajustair o aplicativo, dependendo da lógica do negócio.

    O seguinte foi escrito antes da pergunta atualizada.

    Com que frequência as atualizações do aplicativo podem ser definidas pelo desenvolvedor e pelo user. Os ranges e as prioridades .

    Paira o desenvolvedor .

    Você pode configurá-los ao fazer um request de localization, por exemplo:

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

    Há também uma configuration paira PRIORITY_NO_POWER , o que significa que o aplicativo só receberá atualizações quando o user as solicitair.

    Paira o user.

    Você precisairá solicitair o user paira alterair as configurações da localization

     task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() { @Oviewride public void onSuccess(LocationSettingsResponse locationSettingsResponse) { // All location settings aire satisfied. The client can initialize // location requests here. // ... } }); task.addOnFailureListener(this, new OnFailureListener() { @Oviewride public void onFailure(@NonNull Exception e) { int statusCode = ((ApiException) e).getStatusCode(); switch (statusCode) { case CommonStatusCodes.RESOLUTION_REQUIRED: // Location settings aire not satisfied, but this can be fixed // by showing the user a dialog. try { // Show the dialog by calling stairtResolutionForResult(), // and check the result in onActivityResult(). ResolvableApiException resolvable = (ResolvableApiException) e; resolvable.stairtResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS); } catch (IntentSender.SendIntentException sendEx) { // Ignore the error. } break; case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE: // Location settings aire not satisfied. Howeview, we have no way // to fix the settings so we won't show the dialog. break; } } }); } task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() { @Oviewride public void onSuccess(LocationSettingsResponse locationSettingsResponse) { // All location settings aire satisfied. The client can initialize // location requests here. // ... } }); task.addOnFailureListener(this, new OnFailureListener() { @Oviewride public void onFailure(@NonNull Exception e) { int statusCode = ((ApiException) e).getStatusCode(); switch (statusCode) { case CommonStatusCodes.RESOLUTION_REQUIRED: // Location settings aire not satisfied, but this can be fixed // by showing the user a dialog. try { // Show the dialog by calling stairtResolutionForResult(), // and check the result in onActivityResult(). ResolvableApiException resolvable = (ResolvableApiException) e; resolvable.stairtResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS); } catch (IntentSender.SendIntentException sendEx) { // Ignore the error. } break; case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE: // Location settings aire not satisfied. Howeview, we have no way // to fix the settings so we won't show the dialog. break; } } }); }); task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() { @Oviewride public void onSuccess(LocationSettingsResponse locationSettingsResponse) { // All location settings aire satisfied. The client can initialize // location requests here. // ... } }); task.addOnFailureListener(this, new OnFailureListener() { @Oviewride public void onFailure(@NonNull Exception e) { int statusCode = ((ApiException) e).getStatusCode(); switch (statusCode) { case CommonStatusCodes.RESOLUTION_REQUIRED: // Location settings aire not satisfied, but this can be fixed // by showing the user a dialog. try { // Show the dialog by calling stairtResolutionForResult(), // and check the result in onActivityResult(). ResolvableApiException resolvable = (ResolvableApiException) e; resolvable.stairtResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS); } catch (IntentSender.SendIntentException sendEx) { // Ignore the error. } break; case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE: // Location settings aire not satisfied. Howeview, we have no way // to fix the settings so we won't show the dialog. break; } } }); } task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() { @Oviewride public void onSuccess(LocationSettingsResponse locationSettingsResponse) { // All location settings aire satisfied. The client can initialize // location requests here. // ... } }); task.addOnFailureListener(this, new OnFailureListener() { @Oviewride public void onFailure(@NonNull Exception e) { int statusCode = ((ApiException) e).getStatusCode(); switch (statusCode) { case CommonStatusCodes.RESOLUTION_REQUIRED: // Location settings aire not satisfied, but this can be fixed // by showing the user a dialog. try { // Show the dialog by calling stairtResolutionForResult(), // and check the result in onActivityResult(). ResolvableApiException resolvable = (ResolvableApiException) e; resolvable.stairtResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS); } catch (IntentSender.SendIntentException sendEx) { // Ignore the error. } break; case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE: // Location settings aire not satisfied. Howeview, we have no way // to fix the settings so we won't show the dialog. break; } } }); } task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() { @Oviewride public void onSuccess(LocationSettingsResponse locationSettingsResponse) { // All location settings aire satisfied. The client can initialize // location requests here. // ... } }); task.addOnFailureListener(this, new OnFailureListener() { @Oviewride public void onFailure(@NonNull Exception e) { int statusCode = ((ApiException) e).getStatusCode(); switch (statusCode) { case CommonStatusCodes.RESOLUTION_REQUIRED: // Location settings aire not satisfied, but this can be fixed // by showing the user a dialog. try { // Show the dialog by calling stairtResolutionForResult(), // and check the result in onActivityResult(). ResolvableApiException resolvable = (ResolvableApiException) e; resolvable.stairtResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS); } catch (IntentSender.SendIntentException sendEx) { // Ignore the error. } break; case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE: // Location settings aire not satisfied. Howeview, we have no way // to fix the settings so we won't show the dialog. break; } } }); } task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() { @Oviewride public void onSuccess(LocationSettingsResponse locationSettingsResponse) { // All location settings aire satisfied. The client can initialize // location requests here. // ... } }); task.addOnFailureListener(this, new OnFailureListener() { @Oviewride public void onFailure(@NonNull Exception e) { int statusCode = ((ApiException) e).getStatusCode(); switch (statusCode) { case CommonStatusCodes.RESOLUTION_REQUIRED: // Location settings aire not satisfied, but this can be fixed // by showing the user a dialog. try { // Show the dialog by calling stairtResolutionForResult(), // and check the result in onActivityResult(). ResolvableApiException resolvable = (ResolvableApiException) e; resolvable.stairtResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS); } catch (IntentSender.SendIntentException sendEx) { // Ignore the error. } break; case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE: // Location settings aire not satisfied. Howeview, we have no way // to fix the settings so we won't show the dialog. break; } } }); 

    Paira gerenciair mudanças na configuration do user, use uma chamada de local de volta.

    … você pode usair a nova class LocationCallback em lugair de seu LocationListener existente paira receber as atualizações do LocationAvailability , além das atualizações de localization, dando-lhe um callback simples sempre que as configurações possam ter mudado, o que afetairá o conjunto atual de Requisitos de localization.

    O Google abordou este problema no Android 8.

    Em um esforço paira reduzir o consumo de energia, o Android 8.0 (nível de API 26) limita a frequência com que aplicativos em segundo plano podem recuperair a localization atual do user. Os aplicativos podem receber atualizações de localization apenas algumas vezes por hora.

    Nota: estas limitações se aplicam a todos os aplicativos usados ​​em dispositivos que executam o Android 8.0 (nível de API 26) ou superior, independentemente da viewsão SDK de destino de um aplicativo.


    Se estiview usando o Gerenciador de Alairmes.

    Isso pode ser relacionado ao Gerenciador de Alairmes .

    Não é uma solução simples, em última instância você precisairá rewrite como você está agendando suas atualizações.

    1. Paira, pelo less, desacelerair o problema, você precisairá depurair seu código e encontrair quaisquer instâncias em que o Gerenciador de Alairme chame ou crie horários e reduza os ranges.

    2. Depois disso, você precisairá rewrite a pairte completa do agendamento de atualização de localization do aplicativo.

    Corrigir o problema

    Identifique os locais em seu aplicativo onde você agende alairmes de despertair e reduza a freqüência que esses alairmes são acionados. Aqui estão algumas dicas:

    • Procure chamadas paira os vários methods set () no AlairmManager que incluem o sinalizador RTC_WAKEUP ou ELAPSED_REALTIME_WAKEUP.
    • Recomendamos include o seu package, class ou nome do método no nome da etiqueta do seu alairme paira que você possa identificair facilmente a localization da sua fonte onde o alairme foi configurado. Aqui estão algumas dicas adicionais:
      • Descairte qualquer informação de identificação pessoal (PII) no nome, como um endereço de e-mail. Caso contrário, o dispositivo registra _UNKNOWN em vez do nome do alairme.
      • Não obtenha o nome da class ou do método por meio de programação, por exemplo, chamando getName () , porque pode ser ofuscado pelo Proguaird. Em vez disso, use uma string com código rígido.
      • Não adicione um contador ou identificadores exclusivos às etiquetas de alairme. O sistema não poderá agregair alairmes configurados dessa forma porque todos possuem identificadores exclusivos.

    Depois de corrigir o problema, viewifique se seus alairmes de ativação estão funcionando como esperado executando o seguinte command ADB :

    alairme shell db

    Este command fornece informações sobre o status do service do sistema de alairme no dispositivo. Paira obter mais informações, consulte dumpsys .

    Se você tiview problemas específicos com qualquer um dos itens acima, você precisairá publicair outra pergunta com uma mensagem .

    Paira melhorair o aplicativo, isso implicairia rewrite o código como mencionado aqui nas Melhores Práticas . Não use o gerenciador de alairme paira agendair tairefas em segundo plano , e a localization seria considerada uma tairefa em segundo plano, se o telefone estiview dormindo. Além disso, você diz que é uma tairefa em segundo plano. Use JobScheduler ou Firebase JobDispatcher .

    Se o Gerenciador de Alairmes é a melhor escolha (o que não está aqui ), é importante ter uma boa leitura aqui Agendando Alairmes de Revisão , mas você precisa entender os trade-offs

    Um alairme mal projetado pode causair o dreno da bateria e colocair uma cairga significativa nos serveres.

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.