我有AlarmManager问题。

简而言之,我计划一个alarmManager:

Intent intent = new Intent(context, MyActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + delayInMs, pendingIntent);

Activity MyActivity将在指定的时间出现。仅在插入设备时。当它放在我的口袋中或延迟几分钟后,它也可以使用。
但是,当我在晚上之前设置alarmManager时,它在早晨将无法工作。但是,只要我拿起电话或解锁屏幕,它便会起作用。

所以,我想这是由于设备的 sleep 模式引起的,但是如何解决呢?

1)我在myActivity的每个方法中添加了一个日志,并且在手动唤醒设备之前,我确定没有人被调用。
2)我尝试了PowerManagement的唤醒锁(在 list 中具有WAKE_LOCK权限),但没有任何变化:
alarmManager.setExact(.........);
wakeLock = ((PowerManager)contexte.getSystemService(Context.POWER_SERVICE)).newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, "MyActivity");
wakeLock.acquire();

请帮忙 !我敢肯定我很亲近...

编辑2016年12月4日:
多亏了尼克·弗里斯凯尔(Nick Friskel)和维克拉姆·拉奥(Vikram Rao),我更改了初始代码以调用broadcastReceiver并在onReceive中获取了我的wakeLock。不幸的是,它似乎不起作用。当插入电话或计划在35分钟后发出警报时,它可以完美地工作,但是整整一个晚上,甚至都不会调用onReceive。
我那天晚上尝试过,计划在9:00 AM发出警报,但是onReceive仅在9:46 AM执行,这就是我解锁设备的那一刻。
这是我的新代码:
Intent intent = new Intent("com.blah.something.ALARM_RECEIVED");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + delayInMs, pendingIntent);

就是说,由于某种原因,我写的日志“onReceive的开始”实际上并不是在监听器的开始。我只是设法将其放在真正的开始,所以我将看看是否调用了监听器。

编辑16年5月5日:
因此,我更改了onReceive顶部的日志写入,并且发生了相同的问题:手动唤醒设备后,就会调用onReceive的启动。
我可以实现ukeefulBroadcastReceiver,但是我担心它无法解决任何问题。如果我理解正确,wakefulBroadcastReceiver有助于防止设备在onReceive与 Activity 或服务启动之间进入休眠状态。但是,如果甚至没有调用onReceive怎么办?
我有点绝望...也许我应该直接问索尼。
此外,我的手机具有耐力模式,但未激活。

编辑16年11月11日:
因此,通过更多的测试,现在我确定自己什么都不懂。...我设置了一个广播接收器,该接收器每5分钟激活一次(onReceive在5分钟后将AlarmManager重置一次),并且我可以看到它运行得很好...有时。它可以持续几个小时,然后 sleep 两个小时,然后正常运行30分钟,然后重新进入休眠状态。 (当我的手机打开,拔下电源并处于闲置状态时)。
我将删除所有代码,但让我们感兴趣的是。这将更容易理解,并且我将能够在这里编写所有 Activity 代码。

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.par.hasard.mysimpleapplication">
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver android:name="com.par.hasard.mysimpleapplication.MySimpleReceiver">
            <intent-filter android:priority="1">
                <action android:name="com.par.hasard.mysimpleapplication.REGULAR_ALARM" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

MainActivity.java
package com.par.hasard.mysimpleapplication;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = (Button)findViewById(R.id.myExportButton);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                MyLogManager.copyLogToClipboard(view.getContext());
                MyLogManager.emptyLogFile(view.getContext());
            }
        });
        try {
            MyLogManager.createLogFile(this);
            MyLogManager.write(this, "Application launched\n");
            MyAlarmPlanner.planAlarm(this);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

MySimpleReceiver.java
package com.par.hasard.mysimpleapplication;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class MySimpleReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        try {
            MyLogManager.write(context, "Beginning of onReceive\n");
            MyAlarmPlanner.planAlarm(context);
            MyLogManager.write(context, "End of onReceive\n");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

MyAlarmPlanner.java
package com.par.hasard.mysimpleapplication;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
import java.io.IOException;

public class MyAlarmPlanner {
    public static void planAlarm(Context context) throws IOException {
        MyLogManager.write(context, "Beginning of alarm planning\n");
        AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent("com.par.hasard.mysimpleapplication.REGULAR_ALARM");
        PendingIntent pendingIntent =  PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
        alarmManager.cancel(pendingIntent);
        alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 300000, pendingIntent);
        MyLogManager.write(context, "End of alarm planning\n");
    }
}

我认为MyLogManager.java没有用,只是无聊的文件管理方法。

长时间闲置后的日志文件内容:
12/12 15h33m23s380 => Beginning of onReceive
12/12 15h33m23s381 => Beginning of alarm planning
12/12 15h33m23s383 => End of alarm planning
12/12 15h33m23s384 => End of onReceive
12/12 15h38m24s337 => Beginning of onReceive
12/12 15h38m24s339 => Beginning of alarm planning
12/12 15h38m24s375 => End of alarm planning
12/12 15h38m24s376 => End of onReceive
12/12 15h43m24s375 => Beginning of onReceive
12/12 15h43m24s376 => Beginning of alarm planning
12/12 15h43m24s380 => End of alarm planning
12/12 15h43m24s381 => End of onReceive
12/12 15h48m25s301 => Beginning of onReceive
12/12 15h48m25s304 => Beginning of alarm planning
12/12 15h48m25s307 => End of alarm planning
12/12 15h48m25s308 => End of onReceive
12/12 15h53m25s316 => Beginning of onReceive
12/12 15h53m25s318 => Beginning of alarm planning
12/12 15h53m25s328 => End of alarm planning
12/12 15h53m25s329 => End of onReceive
12/12 15h58m25s328 => Beginning of onReceive
12/12 15h58m25s329 => Beginning of alarm planning
12/12 15h58m25s331 => End of alarm planning
12/12 15h58m25s333 => End of onReceive
12/12 16h3m26s336 => Beginning of onReceive
12/12 16h3m26s351 => Beginning of alarm planning
12/12 16h3m26s379 => End of alarm planning
12/12 16h3m26s380 => End of onReceive
12/12 16h8m26s397 => Beginning of onReceive
12/12 16h8m26s401 => Beginning of alarm planning
12/12 16h8m26s404 => End of alarm planning
12/12 16h8m26s405 => End of onReceive
12/12 16h13m26s406 => Beginning of onReceive
12/12 16h13m26s407 => Beginning of alarm planning
12/12 16h13m26s410 => End of alarm planning
12/12 16h13m26s411 => End of onReceive
12/12 16h18m27s328 => Beginning of onReceive
12/12 16h18m27s329 => Beginning of alarm planning
12/12 16h18m27s346 => End of alarm planning
12/12 16h18m27s348 => End of onReceive
12/12 16h23m28s298 => Beginning of onReceive
12/12 16h23m28s299 => Beginning of alarm planning
12/12 16h23m28s303 => End of alarm planning
12/12 16h23m28s304 => End of onReceive
12/12 16h28m29s308 => Beginning of onReceive
12/12 16h28m29s310 => Beginning of alarm planning
12/12 16h28m29s323 => End of alarm planning
12/12 16h28m29s324 => End of onReceive
12/12 16h33m29s339 => Beginning of onReceive
12/12 16h33m29s340 => Beginning of alarm planning
12/12 16h33m29s355 => End of alarm planning
12/12 16h33m29s361 => End of onReceive
12/12 16h38m29s356 => Beginning of onReceive
12/12 16h38m29s357 => Beginning of alarm planning
12/12 16h38m29s360 => End of alarm planning
12/12 16h38m29s361 => End of onReceive
12/12 16h43m29s364 => Beginning of onReceive
12/12 16h43m29s365 => Beginning of alarm planning
12/12 16h43m29s367 => End of alarm planning
12/12 16h43m29s369 => End of onReceive
12/12 16h48m29s376 => Beginning of onReceive
12/12 16h48m29s380 => Beginning of alarm planning
12/12 16h48m29s390 => End of alarm planning
12/12 16h48m29s394 => End of onReceive
12/12 16h53m29s392 => Beginning of onReceive
12/12 16h53m29s394 => Beginning of alarm planning
12/12 16h53m29s402 => End of alarm planning
12/12 16h53m29s403 => End of onReceive
12/12 17h43m33s986 => Beginning of onReceive      //problem, the 16'58 onReceive wasn't called
12/12 17h43m33s988 => Beginning of alarm planning
12/12 17h43m33s996 => End of alarm planning
12/12 17h43m34s4 => End of onReceive
12/12 17h48m34s535 => Beginning of onReceive
12/12 17h48m34s536 => Beginning of alarm planning
12/12 17h48m34s539 => End of alarm planning
12/12 17h48m34s540 => End of onReceive
12/12 18h29m49s635 => Beginning of onReceive     //the moment I turned on my device
12/12 18h29m49s648 => Beginning of alarm planning
12/12 18h29m49s667 => End of alarm planning
12/12 18h29m49s668 => End of onReceive

有人可以告诉我我的错误在哪里吗?

最佳答案

多亏了CommonsWare,问题得以解决!失败是由于打ze模式(https://developer.android.com/training/monitoring-device-state/doze-standby.html)
简而言之,从Android 6.0开始,如果设备处于此打do模式,AlarmManager会受到影响并且无法触发。但是您可以将setExact替换为setExactAndAllowWhileIdle。有局限性,但我们必须处理。有指向CommonsWare回答的帖子的链接:
sendWakefulWork not always called with cwac-wakeful-1.1.0

关于手机进入休眠状态时,Android AlarmManager无法正常工作,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40897112/

10-10 23:14