问题
I am trying to implement an alarm based application in Android Q using a broadcast receiver. I am running a foreground service using notification for triggering the alarm broadcast receiver. The service is working fine and it is also triggering the broadcast receiver. If we close the application or lock the screen after setting an alarm, the service will be running in the foreground with a notification.
When the alarm broadcast is called I am trying to open a new activity when the screen is locked to provide the functionality to stop the alarm and service. I tried disabling the keyguard, turn on the screen and then opening the activity from the broadcast receiver, but I couldn't succeed.
I tried using WindowManager flags but they are deprecated and do not make any difference in the code.
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
Since I am trying to start an activity from a BroadcastReceiver I won't be having any Activity to use KeyguardManager.requestDismissKeyguard(Activity activity, KeyguardDismissCallback callback)
Is there any way to start an activity when the screen is locked to turn off the alarm. My implementation is given as follows,
I also added permissions in the manifest file.
AndroidManifest.xml
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
AlarmBroadcastReceiver.class
public class AlarmBroadcastReceiver extends BroadcastReceiver {
public static MediaPlayer mp;
public static Vibrator vibrator;
private boolean isVibrationEnabled = false;
@Override
public void onReceive(Context context, Intent intent) {
long[] mVibratePattern = new long[]{0, 400, 400, 400, 400, 400, 400, 400};
final int[] mAmplitudes = new int[]{0, 128, 0, 128, 0, 128, 0, 128};
isVibrationEnabled = intent.getExtras().getBoolean(LocationAlertService.IS_VIBRATE);
mp=MediaPlayer.create(context, R.raw.ring1);
mp.setLooping(true);
mp.start();
if(isVibrationEnabled) {
vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
vibrator.vibrate(VibrationEffect.createWaveform(mVibratePattern, mAmplitudes, 0));
} else {
//deprecated in API 26
vibrator.vibrate(mVibratePattern, 3);
}
}
Intent wakeIntent = new Intent(context, WakeUpActivity.class);
wakeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(wakeIntent);
}
}
I know that I am missing something. I would be happy if there are any suggestions to overcome the issue which I am facing. Thanks in advance for helping me out.
回答1:
With Android Q, it is impossible to start an activity from background automatically if your app is not includes those exceptions listed in the link below. You can choose just show a service notification, and start pending intent with click.
https://developer.android.com/guide/components/activities/background-starts
To make the system work. The most possible solution in my view is adding "SYSTEM_ALERT_WINDOW" to manifest file. And ask for user permission once when the app opened first time.(The user can give this permission manually - (Settings-Apps-Your App-Advanced- Draw over other apps)) Example code to request permission :
In Manifest:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
Somewhere in app:
private void RequestPermission() {
// Check if Android M or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Show alert dialog to the user saying a separate permission is needed
// Launch the settings activity if the user prefers
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getActivity().getPackageName()));
startActivityForResult(intent, ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(getContext())) {
PermissionDenied();
}
else
{
//Permission Granted-System will work
}
}
}
来源:https://stackoverflow.com/questions/59416738/how-to-start-a-activity-from-a-broadcast-receiver-when-the-screen-is-locked-in-a