标签: android-doze

Android打盹模式 - 蓝牙

我的问题很简单.我想知道我的应用程序的最佳做法是什么,以便它可以"防止打瞌睡".随着Android N将在更多情况下应用Doze,这变得更加相关.

在阅读Doze文档时,有一部分提到了网络访问:

在打盹模式下,系统会通过限制应用程序访问网络和CPU密集型服务来尝试节省电池电量.它还可以防止应用程序访问网络并延迟其作业,同步和标准警报.

我相信Buetooth属于网络访问,这是正确的吗?

由于我没有使用Marshmallow(或Android N)设备,并且因为Emulator不允许蓝牙交互,所以我无法在打盹模式下测试我的应用行为.

Doze模式会杀死任何正在进行的蓝牙连接吗?这同样适用于Bluetooth Classic和LE吗?带蓝牙A2DP的耳机怎么样?

我的应用必须保持此连接,否则核心功能将被破坏.

当然,对于这样的情况,存在某种例外情况,即用户需要将设备连接到蓝牙远程设备.

我知道存在一个打盹白名单,但在某些情况下,似乎可能不会让应用程序在API 23以下的设备上运行.

谢谢您的帮助!

android bluetooth android-6.0-marshmallow android-doze android-7.0-nougat

5
推荐指数
1
解决办法
2216
查看次数

地理围栏有效,但过了一段时间才停止触发

我的地理围栏正在开始工作,但是在一两天停止触发之后突然间,谷歌这边或我的代码有问题吗?

在启动并启动应用程序后,我使用IntentService然后注册Geofence:

public class RegisterGeoIntentService extends IntentService implements 
GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener, ResultCallback<Status> {

private static final String TAG = "RegisterGeoIS";

private static final long TIME_OUT = 100;
protected GoogleApiClient mGoogleApiClient;
protected ArrayList<Geofence> mGeofenceList;
private PendingIntent mGeofencePendingIntent;

public RegisterGeoIntentService() {
    super(TAG);
}

@Override
public void onCreate() {
    super.onCreate();
    Log.i(TAG, "Creating Register Geo Intent service");
    mGeofenceList = new ArrayList<Geofence>();
    mGeofencePendingIntent = null;
}

@Override
protected void onHandleIntent(Intent intent) {
    buildGoogleApiClient();
    populateGeofenceList();
    mGoogleApiClient.blockingConnect(TIME_OUT, TimeUnit.MILLISECONDS);
    String connected = mGoogleApiClient.isConnected() ? "connected" : "disconnected";
    Log.i(TAG, "Restoring …
Run Code Online (Sandbox Code Playgroud)

performance android android-geofence android-intentservice android-doze

5
推荐指数
1
解决办法
629
查看次数

未触发Android Nougat PhoneStateListener

在Android(目标25)中,我有一个后台服务,在onCreate函数中,我初始化了一个手机状态监听器.它适用于Nougat之前的Android版本,但在Nougat中它不起作用,即使权限被授予.

public class Service extends IntentService
{
    class PhoneListener extends PhoneStateListener
    {
       String TAG = getClass().getName();
       @Override
       public void onCallStateChanged(int state, String incomingNumber) 
       {
           super.onCallStateChanged(state, incomingNumber);
           switch (state)
           {
               case TelephonyManager.CALL_STATE_IDLE:
                Log.d(TAG,"IDLE" );
               break;
               case TelephonyManager.CALL_STATE_OFFHOOK:
                Log.d(TAG,"OFFHOOK");
               break;
               case TelephonyManager.CALL_STATE_RINGING:
                Log.d(TAG,"RINGING");
               break;
           }
       }
   }

   public Service ()
   {
       super("ChatService");
   }
   public Service(String name)
   {
       super(name);
   }

   @Override
   public void onCreate()
   {
       super.onCreate();
       TelephonyManager tm = (TelephonyManager)getApplicationContext().getSystemService(TELEPHONY_SERVICE);
       PhoneListener listener = new PhoneListener();
       tm.listen(listener,PhoneStateListener.LISTEN_CALL_STATE);
   }
}
Run Code Online (Sandbox Code Playgroud)

我不知道是什么问题,看起来电话管理器没有注册,因此没有触发onCallStateChanged.我的猜测之一是在Android M上引入的Doze功能,但仍然......即使手机未找到"工作中",此代码在Android 6上运行正常

android telephonymanager android-doze android-7.0-nougat android-7.1-nougat

5
推荐指数
2
解决办法
2126
查看次数

最新的Android更新会禁用电池优化白名单吗?

TL; DR

Android 7.1.2的“ 2017年6月5日”安全更新是否导致Android开始忽略电池优化白名单(即让应用程序禁用“打ze”模式的功能)?

如果是这样,如果应用程序需要持续保持CPU和wifi的使用情况,那么现在该如何通过编程方式禁用“打ze”模式?

语境

我有一个Android应用程序,它支持将本地音频文件投射到联网的Chromecast接收器(使用嵌入式HTTP服务器将文件内容流式传输到接收器)。

为了在Android M上实现此功能(就在设备投射音频时没有使Chromecast会话掉落,否则处于空闲状态),我不得不在此答案中使用该方法来禁用打ze模式。

具体来说,AndroidManifest.xml我有:

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

...,只要建立Chromecast会话,就会执行以下代码:

if (Build.VERSION.SDK_INT >= 23) {
    String packageName = context.getPackageName();
    PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    if (! pm.isIgnoringBatteryOptimizations(packageName)) {
        //reguest that Doze mode be disabled
        Intent intent = new Intent();
        intent.setAction(
            Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
        intent.setData(Uri.parse("package:" + packageName));

        context.startActivity(intent);
    }

}
Run Code Online (Sandbox Code Playgroud)

...并且在Chromecast播放处于活动状态时,我还以标准方式获取唤醒/ wifi锁定:

PowerManager powerManager = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "myapp-cast-server-cpu");
wakeLock.acquire();

WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "myapp-cast-server-net");
wifiLock.acquire(); 
Run Code Online (Sandbox Code Playgroud)

该应用程序出现在电池白名单中,而就在几周前,这一切都运行良好。但是,该应用程序现在被打ze睡模式捕获。

测试设备没有改变;这是运行Android …

java android media-player chromecast android-doze

5
推荐指数
0
解决办法
1273
查看次数

在打ze模式下获取位置更新

我在打ze睡模式下尝试在我的android应用中获取位置更新,该更新以前可以在android 5.x上使用。随着android 6和doze的出现,无论我做什么,更新都会在某个时候停止。在阅读了有关该主题的几篇文章和stackoverflow答案之后,我进行了以下更改:

  • 使我的服务成为前台服务
  • 使服务持有部分唤醒锁
  • 我已为我的应用授予WAKE_LOCK权限
  • 使服务在单独的进程中运行(针对某些Android错误的解决方法)
  • 我已为我的应用禁用电池优化

但是,无论何时打do睡,我都没有得到位置更新。我已经验证了打do睡开始时(通过定期记录消息)我的服务线程保持运行,但是位置管理器以某种方式停止发送更新。在这方面,关于Manager睡和LocationManager的文档非常少,所以我想知道是否有人知道一种使位置管理器在do睡中存活的方法?LocationManager上是否有某种方法,如果定期调用该方法,可以使LocationManager保持活动状态?请注意,我只对GPS更新感兴趣,更新频率很高,每秒更新一次。

android locationmanager android-gps android-doze

5
推荐指数
1
解决办法
2914
查看次数

在 Doze 模式下在前台服务中重复任务

我正在开发一个应用程序,在该应用程序中我必须以固定时间间隔(假设 2 分钟后)执行一些重复任务,即使在打盹模式下也应该完成。我的观察如下-

  1. 使用警报(使用 RTC 标志)执行重复任务不准确。安卓系统批量报警。如果我们使用 RTC_WAKEUP 那么它比 RTC 更好,但是它在 Android Vitals 中显示 WAKEUP 计数并不好。
  2. Jobschedulers 很有用,但在 2 分钟之类的较短时间间隔内不起作用。我曾尝试过 Firebase Jobdispatcher 但这也不是很准确,我以 2 分钟的触发时间开始工作,但它从 10-20 分钟不等。
  3. 使用处理程序和计时器在前台服务中重复任务。在这种情况下,前台服务继续在打盹模式下运行,但处理程序和计时器停止重复任务。我阅读了 Handlers.postDelayed() 并发现这也受打盹模式的影响。

我不想为这个重复的任务获得 WAKELOCK。

有人可以建议我一些更好/更干净的方法,我们可以通过它在打瞌睡模式下执行短间隔重复任务吗?

以供参考 -

Android:让重复的后台任务 Android Oreo 准备就绪的最佳方法是什么?

打瞌睡模式如何影响后台/前台服务,有/没有部分/完全唤醒锁?

android alarmmanager android-jobscheduler android-doze firebase-job-dispatcher

5
推荐指数
1
解决办法
884
查看次数

广播接收器在 Android 8 的前台服务中不起作用

我正在尝试创建一个应用程序,允许用户在设置的时间间隔内或手动使设备静音。我还希望用户能够输入更复杂的规则,例如仅在连接到某个 WiFi 网络、蓝牙设备或进入地理围栏时才将手机静音。但是,在静音模式下,我希望允许用户创建电话仍应响铃的联系人列表。

为此,我创建了一个前台服务,在其中注册了一个广播接收器。但是,在活动离开前台仅几分钟后,接收器就会停止按时工作并不时更新。

此问题出现在搭载 Android 8 的设备(华为/荣耀 7x)上。

注意:我尝试将应用程序添加到Doze 白名单并禁用供应商特定的电池优化,但没有任何改变。

下面是我的代码的 MCVE。每当服务中的接收器被触发时,一些 int 值就会增加,然后它们会显示在通知中。在我的设备上,由于活动离开前台,值在几分钟后停止增加:

清单权限

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

清单声明的服务

<service android:name=".PhoneService"/>
Run Code Online (Sandbox Code Playgroud)

在 Activity 中启动 Service

//for the sake of simplicity, I omit the code where runtime permissions are requested
Intent foregroundIntent = new Intent(this, PhoneService.class);
foregroundIntent.putExtra(PhoneService.EXTRA_ACTION, PhoneService.ACTION_START);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    startForegroundService(foregroundIntent);
} else {
    startService(foregroundIntent);
}
Run Code Online (Sandbox Code Playgroud)

服务类

public class PhoneService extends Service {

private static final String NOTIFICATION_CATEGORY = "notification_category";
private static …
Run Code Online (Sandbox Code Playgroud)

android android-service android-broadcastreceiver android-doze

5
推荐指数
1
解决办法
3349
查看次数

ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS 什么都不做

我的意思不是什么都没有发生。弹出对话框:

“让应用始终在后台运行?允许/拒绝

但是,如果我进入设置、应用、电池优化,我的应用仍设置为“优化电池使用”。然后我可以手动将其切换为“不优化”,但根据此处的文档和所有其他问题,使用 ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS 意图并单击“允许”应该会更改此设置。

我正在使用:

此外,这个应用程序是用于研究的,不会在商店上架,所以我不担心 Play 商店的政策。

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        Intent intent = new Intent();
        String packageName = getPackageName();
        PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
        if (!pm.isIgnoringBatteryOptimizations(packageName)) {
            intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
            intent.setData(Uri.parse("package:" + packageName));
            startActivity(intent);
        }
    }
Run Code Online (Sandbox Code Playgroud)

我正在使用上面的代码。它启动,弹出一个对话框“让应用程序始终在后台运行?” 我按允许。

我的问题是按下“允许”实际上是做什么的,因为如果您随后进入应用程序设置并查看电池优化,设置会显示该应用程序仍在“优化电池使用”。

所以看起来上面的意图,按下允许,实际上并没有做任何事情。

android android-doze

5
推荐指数
1
解决办法
5173
查看次数

应用程序处于打ze模式时,警报管理器触发的Android通知未触发

我有以下要求。用户需要能够在我的应用中安排定期提醒,该提醒将在每天的确切时间触发推送通知。

这是我希望最终不要提交的那些问题之一,因为在编写它时建议您提出类似的问题。但是,几个团队成员花了很多时间来查看Android Developer Docs和Stackoverflow,我们似乎离答案还很近,所以我们到了。

如果我创建了一个提醒并将其设置为在未来5分钟触发通知,则该通知会正常触发。

我怀疑这可能是由于Android P中引入的节电,唤醒锁等更改引起的问题,因为在将目标SDK更新到28之前我们没有这个问题。唯一的问题,但我可以在运行Android P的Pixel和Pixel 3 XL上一贯重现该问题。

例如,当用户将提醒设置为半夜的某个时间(大概是在用户处于睡眠状态,因此将有几个小时没有使用电话)时,便会发生通知未触发的示例。这些提醒从未触发过。

我目前正在尝试使用“警报管理器”来完成此操作。

该问题似乎类似于另一个问题,该问题使用了警报管理器的setRepeating方法,但我们发现该方法不起作用。相反,我们使用警报管理器的setExactAndAllowWhileIdle方法。我们还使用Alarm Managers setAlarmClock方法尝试了相同的实现,根据Android文档,该方法“即使系统处于低功率空闲(也称为打ze)模式,也将被允许触发”,但这也没有成功。

我怀疑这不起作用的原因是因为在电话处于打ze模式时setExactAndAllowWhileIdle不会触发,类似于此问题中表达的问题。此问题建议使用Firebase JobDispatcher,但由于这是内部通知,因此无论是否具有网络连接,我都需要触发该通知,这似乎消除了Firebase JobDispatcher的选择。这个问题还表明,一旦手机退出打ze模式,用户会收到通知,但我们从未收到通知,他们似乎因为缺少更好的条件而迷路了。

我已将唤醒锁定权限添加到我的AndroidManifest.xml中:

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

这是我的接收者在AndroidManifest.xml中的注册方式

<receiver android:name="com.myapp.receiver.AlarmReceiver">
    </receiver>
Run Code Online (Sandbox Code Playgroud)

这是我当前的实现:

待处理通知的意图

Intent i = new Intent(context, ScheduleAllReceiver.class);
    PendingIntent scheduleAllPendingIntent = PendingIntent.getBroadcast(context, SCHEDULER_DAILY_ALL, i, PendingIntent.FLAG_UPDATE_CURRENT);
Run Code Online (Sandbox Code Playgroud)

我随后将方法称为“ createAlarm”,如下所示

createAlarm(context, scheduleAllPendingIntent, calendar.getTimeInMillis());
Run Code Online (Sandbox Code Playgroud)

创建警报

public static void createAlarm(Context context, PendingIntent pendingIntent, long timeinMilli) {
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

    if(alarmManager != null) {

        if (Build.VERSION.SDK_INT >= 23) {
            alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, timeinMilli, …
Run Code Online (Sandbox Code Playgroud)

notifications android alarmmanager android-doze android-9.0-pie

5
推荐指数
1
解决办法
1830
查看次数

打盹模式处理

我正在开发一个应用程序,它使用AlarmManager在后台生成一些服务.时序对我们的应用程序非常重要,功能不能等待下一个维护窗口发生.要求用户将应用程序列入白名单不是问题,但不能解决暂停警报的问题.电池消耗也不是一个大问题.

我想到的第一个可能的解决方案是生成一个始终运行的前台服务来处理服务的重新安排而不是AlarmManager,但这样做会改变我们应用程序的大部分基础结构,对我们来说是不可行的.

我刚刚实现的当前修复是发送高优先级推送通知,并在接收消息时,完全唤醒锁定并打开屏幕以打破打盹模式.

我想知道是否有另一种打破打盹模式的方法?也可以不用唤醒锁?实施上述解决方案会产生一些可能的后果吗?

PS我正在使用UrbanAirship进行推送通知.

android android-6.0-marshmallow android-doze-and-standby android-doze

4
推荐指数
1
解决办法
2704
查看次数