我有一个带闹钟的旧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警报并不能完成我的用户想要做的事情。警报先前根据应用程序中的某些数据设置为建议。用户必须运行它们,并且可以根据自己的需要进行高度自定义。
答案 0 :(得分:2)
您实际上在OnReceive方法中使用了错误的Context。而不是这样做:
Forms.Context.StartActivity(myIntent);
试试这个:
context.StartActivity(myIntent);
当您强制关闭应用程序时,不会有任何要使用的Forms.Context。
更新:如果要在锁定屏幕上显示“活动”,则需要将showForAllUsers设置为true。以下是Android文档中的说明:
指定即使当前/前台用户与活动用户不同,也应显示活动。 这也会强制为此活动的所有窗口设置android.view.LayoutParams.FLAG_SHOW_WHEN_LOCKED标志。
之前您会使用更具描述性的showOnLockScreen标记,但在API级别23中已弃用。
答案 1 :(得分:2)
只需设置正确的窗口标志即可。这适用于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();
}
}
调用此例程,警报管理器将在一分钟内启动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);
}