【问题标题】:How wake up device and show an activity on top of lock screen for alarm?如何唤醒设备并在锁定屏幕顶部显示活动以进行警报?
【发布时间】:2017-08-23 15:22:25
【问题描述】:

我有一个带有闹钟的旧 Android 应用,用户可以在其中设置时间和闹钟行为,例如铃声和铃声持续时间、音量、是否仅振动或静音。它可以工作,但由于新的 android 规则很久以前就停止工作了,刚才我有时间更新它,但我找不到这些问题的最新答案。

一旦闹钟到期,我需要在任何东西之上打开一个活动,包括另一个应用程序或锁定屏幕,就像默认的 Android 闹钟或来电一样。此活动将有一条消息和一个关闭按钮。一旦被解雇,我需要将电话状态恢复到以前的状态。

我可以设置警报并且它可以工作,如果应用程序处于前台或后台,BroadcastReceiver 会打开活动,但如果应用程序被强制关闭则不会。它会弹出我的应用程序停止的默认崩溃消息。另外,我不知道如何让它在任何锁定屏幕上打开。

我猜这是因为缺少权限或标志。

我正在使用 Xamarin,所以如果您不知道,您只需要知道活动元数据是在类上设置的,然后编译到清单中。

这是我想在闹钟结束时显示的活动(不是主要活动):

[Activity(Label = "@string/app_name", Theme = "@style/MainTheme.StopAlarm", LaunchMode = Android.Content.PM.LaunchMode.SingleTask)]
public class StopAlarmActivity : Activity
{

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        SetContentView(Resource.Layout.StopAlarmLayout);

        Bundle bundle = Intent.Extras;
        string msg = bundle.GetString("message");

        TextView nameTV = FindViewById<TextView>(Resource.Id.alarmTextView);
        nameTV.Text = msg;

        Button okButton = FindViewById<Button>(Resource.Id.okButton);
        okButton.Text = AppResources.OK;
        okButton.Click += (object sender, EventArgs args) =>
        {
            Finish();
        };
    }
}

我的接收器:

[BroadcastReceiver]
    public class AlarmReceiver : BroadcastReceiver
    {

        public override void OnReceive(Context context, Intent intent)
        {
            Toast.MakeText(context, "Alarm worked.", ToastLength.Long).Show();

            string msg = intent.Extras.GetString("message");

            var myIntent = new Intent(context, typeof(StopAlarmActivity));
            Bundle bundle = new Bundle();
            bundle.PutString("message", msg);
            myIntent.PutExtras(bundle);
            myIntent.SetFlags(ActivityFlags.FromBackground);
            myIntent.SetFlags(ActivityFlags.NewTask);
            myIntent.AddCategory(Intent.CategoryLauncher);
            Forms.Context.StartActivity(myIntent);
        }
    }

请不要浪费时间告诉我应该避免这种行为。这是一个闹钟,如果是他自己设置的,它是用来叫醒他的。另外,默认的 android 闹钟不会做我的用户想要做的事情。警报之前是根据应用程序中的一些数据作为建议设置的。用户必须运行它们,并且它可以根据他的需要进行高度定制。

【问题讨论】:

  • 顺便说一句,我更新了我的答案,还包括了锁屏部分。

标签: android xamarin xamarin.android


【解决方案1】:

只需设置正确的窗口标志。这适用于 API 14(?) 到 Oreo Beta:

活动:

[Activity(Label = "AlarmActivity")]
public class AlarmActivity : Activity, View.IOnClickListener
{
    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.Alarm);
        FindViewById<Button>(Resource.Id.myButton).SetOnClickListener(this);
    }

    public override void OnAttachedToWindow()
    {
        Window.AddFlags(WindowManagerFlags.ShowWhenLocked | 
                        WindowManagerFlags.KeepScreenOn | 
                        WindowManagerFlags.DismissKeyguard | 
                        WindowManagerFlags.TurnScreenOn);
    }

    public void OnClick(View v)
    {
        Finish();
    }
}

AlarmManager 测试:

调用此例程,警报管理器将在一分钟内启动AlarmActivity,因此在按钮单击/侦听器中应用此例程并锁定您的屏幕:

using (var manager = (Android.App.AlarmManager)GetSystemService(AlarmService))
using (var calendar = Calendar.Instance)
{
    calendar.Add(CalendarField.Minute, 1);
    Log.Debug("SO", $"Current date is   : {Calendar.Instance.Time.ToString()}");
    Log.Debug("SO", $"Alarm will fire at {calendar.Time.ToString()}");
    var alarmIntent = new Intent(ApplicationContext, typeof(AlarmActivity));
    var pendingIntent = PendingIntent.GetActivity(this, 0, alarmIntent, PendingIntentFlags.OneShot);
    manager.SetExact(AlarmType.RtcWakeup, calendar.TimeInMillis, pendingIntent);
}

【讨论】:

  • 实际上@SushiHangover 它正在工作,但不像我预期的那样。如果我删除 DismissKeyguard 它不起作用。我希望设备保持锁定状态。难道没有别的办法了吗?我必须在 Finish() 上再次锁定屏幕吗?
  • @Dpedrinha 已解锁?如果用户启用了锁定屏幕,这不会禁用它(它不能)。
  • 嗯,我只使用滑动锁进行测试。我会用销锁测试
  • 这就是问题所在。更好的安全锁不会解锁。谢谢
  • @Dpedrinha 没问题,一些滑动锁无法使用此解锁设备....锁没有解锁......我猜它是 API 版本(?)或 OEM 用他们自己的“更好”版本替换它;-)
【解决方案2】:

您实际上在 OnReceive 方法中使用了错误的上下文。而不是这样做:

Forms.Context.StartActivity(myIntent);

试试这个:

context.StartActivity(myIntent);

当您强制关闭应用程序时,将没有任何 Forms.Context 可供使用。

更新:如果你想在锁屏上显示Activity,你需要将showForAllUsers设置为true。以下是 Android 文档中的描述:

指定即使当前/前台用户与 Activity 的用户不同,也应显示 Activity。 这也将强制为该活动的所有窗口设置 android.view.LayoutParams.FLAG_SHOW_WHEN_LOCKED 标志

之前您会使用更具描述性的 showOnLockScreen 标志,但它在 API 级别 23 中已被弃用。

【讨论】:

  • 感谢您指出上下文问题,它让我失望了。但我仍然不知道如何在 Xamarin 中使用 showForAllUsers 标志。你知道怎么用吗?
  • 好的,如果有人知道答案,这里的问题是:stackoverflow.com/questions/45827701/…
  • 好的,上面的问题已经回答并且解决方案有效。但是,我的活动仍然没有显示在我的锁定屏幕上。
猜你喜欢
  • 1970-01-01
  • 2021-01-28
  • 1970-01-01
  • 2012-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多