首页 > 解决方案 > BroadcastReciever.onReceive startActivity 不显示活动

问题描述

下面的评论都不适合我。

但是,我找到了解决方法。我需要更改我的 AlarmActivity,看来 keyguardManager.requestDismissKeyguard 非常重要。

代码:

public class AlarmActivity extends BaseActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        this.setTurnScreenOn(true);
        this.setShowWhenLocked(true);
        KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Activity.KEYGUARD_SERVICE);
        keyguardManager.requestDismissKeyguard(this, null);
    }
}

最初的问题是..

我正在尝试从 BroadcastReciever.onReceive 方法显示一个活动 (startActivity),但它不能始终如一地工作。如果设备处于活动状态但在设备锁定时出现问题,我的代码似乎运行良好。以下代码应符合 minSdkVersion 28。

现有代码使用 AlarmManager.setExactAndAllowWhileIdle 来触发 BroadcastReciever。根据 intent.getExtras 中的某些值,代码应显示:AssessmentAlarmActivity 或 MATActivity。即使设备正在打盹并且在锁定屏幕上,AssessmentAlarmActivity 也需要始终显示。MATActivity 应仅在设备处于活动状态时显示(不必唤醒设备或在锁定屏幕上显示)。

以下代码似乎适用于很多设备。查看 logcat 数据,我看到 BroadcaseReceiver.onReceive 被触发,但有时活动可能需要一分钟才能显示。在某些设备上,活动根本不会显示。我假设以下代码在 intent.addFlags 代码中有不正确的值,但我不确定。

AlarmManager.setExactAndAllowWhileIdle 代码:

private static void setAlarm(Context context, ResponseInfo responseInfo, int requestCode) {
    // Create a new PendingIntent and add it to the AlarmManager
    Intent intent = new Intent(context, ResponseAlarmReceiver.class);
    responseInfo.setRequestCode(requestCode);
    intent.putExtras(responseInfo.createBundle());

    // Create a new PendingIntent and add it to the AlarmManager
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    AlarmManager am = (AlarmManager) context.getSystemService(Activity.ALARM_SERVICE);

    am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, responseInfo.getAlarmTime(), pendingIntent);

    pendingIntents.put(requestCode, pendingIntent);
}

BroadcastReceiver.onRecieve 代码:

public class ResponseAlarmReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) { 
        // read the ResponseInfo from the extras
        ResponseInfo responseInfo = new ResponseInfo();
        responseInfo.readBundle(intent.getExtras());

        // log requestInfo data
        Log.i("ALARM", String.format("Now: %d, responseInfo: %s",
                System.currentTimeMillis(), responseInfo.toString()) );

        if (responseInfo.getAlarmType() == AlarmType.CANCEL) {
            cancelAlarm(context);
        }
        else {
            showAssessmentAlarm(context);
        }
    }

    private static void showAssessmentAlarm(Context context) {
        Log.i("ALARM", "showAssessmentAlarm top");

        Intent nextIntent = new Intent(context, AssessmentAlarmActivity.class);
        nextIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(nextIntent);

        Log.i("ALARM", "showAssessmentAlarm bottom");
    }
    
    private void cancelAlarm(Context context) {
        Log.i("ALARM", "cancelAlarm top");

        Intent intent = new Intent(context, MATActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }

AndroidManifest.xml 定义的活动:

    <activity
        android:name=".MATActivity"
        android:label="@string/app_name"
        android:screenOrientation="portrait" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity> 

    <activity android:name=".AssessmentAlarmActivity" android:theme="@android:style/Theme.Dialog" android:screenOrientation="portrait" ></activity>     
    

MATActivity 是一个非常标准的活动,所以我将跳过该代码。AssessmentAlarmActivity 确实有一个特殊的设置并扩展了 AlarmActivity:

public class AlarmActivity extends BaseActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
    // not minSdkVersion 28 complient, but this is what I have tested most
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
                WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
    }
}       
        
        
public class AssessmentAlarmActivity extends AlarmActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.assessment_alarm);      
        
        ..
    }
    ...
}   

标签: androidbroadcastreceiverstart-activity

解决方案


我认为这是因为后台进程限制。尝试在插入电话(充电)的情况下再次对其进行测试。如果问题解决了,那是因为后台进程限制。

  1. 如果您正在制作闹钟或非常重要的事情,您可以使用alarmManager.setAlarmClock()。它将绕过限制。

  2. 不要忘记wakeLock立即获取 in onReceive。否则安卓系统可能很快就会进入空闲模式。

注意:您可能只需要第二部分(获取 WakeLock)。但同时实施两者是一种更强大的方式。


推荐阅读