C# 如何在Android上自动从电源按钮启动应用程序页面
我正在用Xamarin Android在VS2017为我侄女制作一个小应用程序。我想让它在应用程序上打开一个页面,每次她打开手机时都会问她一个简单的乘法问题。我希望它作为前台服务运行,这样当应用程序最小化时,它仍然会这样做。我有一个广播接收器,在应用程序有焦点时检测到按钮事件,我已将其移动到服务运行 目前我按下了切换按钮,5-10秒后它会抛出一个错误。无法在VS中看到错误,因为它是外部的。我想那就是Genymotion了吧 有什么想法吗 更新:我想如果这对将来的其他人有用的话,我会来更新的。在Oreo更新通知之后,compat.Builder现在需要提供通道ID。我已经在代码中反映了这一点,现在它正确地启动了服务 我仍然需要让广播接收器在服务中工作,但我已经做到了 更新2:工作完成C# 如何在Android上自动从电源按钮启动应用程序页面,c#,android,xamarin,broadcastreceiver,foreground-service,C#,Android,Xamarin,Broadcastreceiver,Foreground Service,我正在用Xamarin Android在VS2017为我侄女制作一个小应用程序。我想让它在应用程序上打开一个页面,每次她打开手机时都会问她一个简单的乘法问题。我希望它作为前台服务运行,这样当应用程序最小化时,它仍然会这样做。我有一个广播接收器,在应用程序有焦点时检测到按钮事件,我已将其移动到服务运行 目前我按下了切换按钮,5-10秒后它会抛出一个错误。无法在VS中看到错误,因为它是外部的。我想那就是Genymotion了吧 有什么想法吗 更新:我想如果这对将来的其他人有用的话,我会来更新的。在O
[Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
Intent startServiceIntent;
Intent stopServiceIntent;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_main);
// Difficulty Radio Buttons
RadioButton radioEasy = FindViewById<RadioButton>(Resource.Id.radioEasy);
radioEasy.Click += RadioButton_Click;
RadioButton radioMedium = FindViewById<RadioButton>(Resource.Id.radioMedium);
radioMedium.Click += RadioButton_Click;
RadioButton radioHard = FindViewById<RadioButton>(Resource.Id.radioHard);
radioHard.Click += RadioButton_Click;
// Set/Remove Lock
Button ToggleLock = FindViewById<Button>(Resource.Id.ToggleLock);
ToggleLock.Click += ToggleLock_Click;
startServiceIntent = new Intent(this, typeof(LockService));
stopServiceIntent = new Intent(this, typeof(LockService));
}
private void RadioButton_Click(object sender, EventArgs e)
{
var radiobtn = sender as RadioButton;
Toast.MakeText(this, radiobtn.Text, ToastLength.Long).Show();
}
private void ToggleLock_Click(object sender, EventArgs e)
{
var togglebtn = sender as ToggleButton;
if (togglebtn.Checked)
{
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
StartForegroundService(startServiceIntent);
else
StartService(startServiceIntent);
Toast.MakeText(this, "On", ToastLength.Long).Show();
}
else
{
Toast.MakeText(this, "Off", ToastLength.Long).Show();
}
}
}
/// <summary>
/// ////////////////////////////////////////////////////////////////////////////
/// </summary>
[Service]
public class LockService : Service
{
private PowerBroadcastReceiver receiver;
public override void OnCreate()
{
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
NotificationManager mngr = (NotificationManager)GetSystemService(NotificationService);
NotificationChannel chnl = new NotificationChannel("Channel", "Name", NotificationImportance.Default);
mngr.CreateNotificationChannel(chnl);
NotificationCompat.Builder foregroundNotification = new NotificationCompat.Builder(this);
foregroundNotification.SetOngoing(true);
foregroundNotification.SetContentTitle("My Foreground Notification")
.SetChannelId("Channel")
.SetContentText("This is the first foreground notification Peace");
StartForeground(101, foregroundNotification.Notification);
// Broadcast Receiver
receiver = new PowerBroadcastReceiver();
RegisterReceiver(receiver, new IntentFilter(Intent.ActionScreenOn));
return StartCommandResult.Sticky;
}
public override IBinder OnBind(Intent intent)
{
// Return null because this is a pure started service. A hybrid service would return a binder that would
// allow access to the GetFormattedStamp() method.
return null;
}
}
/// <summary>
/// ////////////////////////////////////////////////////////////////////////////////
/// </summary>
[BroadcastReceiver]
[IntentFilter(new[] { Intent.ActionScreenOn, Intent.ActionScreenOff })]
public class PowerBroadcastReceiver : BroadcastReceiver
{
public PowerBroadcastReceiver()
{
}
public override void OnReceive(Context context, Intent intent)
{
if (intent.Action.Equals(Intent.ActionScreenOn))
{
// TODO: Launch Question Page
Toast.MakeText(context, "On", ToastLength.Long).Show();
}
else if (intent.Action.Equals(Intent.ActionScreenOff))
Toast.MakeText(context, "Off", ToastLength.Long).Show();
}
}
[活动(标签=“@string/app_name”,Theme=“@style/AppTheme”,MainLauncher=true)]
公共类MainActivity:AppCompativeActivity
{
意向启动服务意向;
意图;服务意图;
创建时受保护的覆盖无效(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_main);
//难度单选按钮
RadioButton radioEasy=FindViewById(Resource.Id.radioEasy);
radioEasy.Click+=RadioButton\u Click;
RadioButton RadioMedia=FindViewById(Resource.Id.RadioMedia);
无线媒体。单击+=无线按钮\u单击;
RadioButton radioHard=FindViewById(Resource.Id.radioHard);
radioHard.Click+=RadioButton\u Click;
//设置/解除锁定
按钮ToggleLock=findviewbyd(Resource.Id.ToggleLock);
ToggleLock.Click+=ToggleLock\u Click;
startServiceIntent=新意图(此,类型为(锁服务));
stopServiceIntent=新意图(此,类型为(锁定服务));
}
私有void单选按钮\u单击(对象发送方,事件参数e)
{
var radiobtn=发送方为RadioButton;
Toast.MakeText(this,radiobtn.Text,ToastLength.Long).Show();
}
私有无效切换锁定\单击(对象发送方,事件参数e)
{
var togglebtn=发送方作为切换按钮;
如果(已选中切换按钮)
{
if(Build.VERSION.SdkInt>=BuildVersionCodes.O)
StartForegroundService(startServiceIntent);
其他的
StartService(StartService意向);
Toast.MakeText(这个“On”,ToastLength.Long).Show();
}
其他的
{
Toast.MakeText(这个“Off”,ToastLength.Long).Show();
}
}
}
///
/// ////////////////////////////////////////////////////////////////////////////
///
[服务]
公共类锁服务:服务
{
专用功率广播接收机;
public override void OnCreate()
{
}
公共覆盖StartCommandResult OnStartCommand(意图、StartCommandFlags标志、int-startId)
{
NotificationManager mngr=(NotificationManager)GetSystemService(NotificationService);
NotificationChannel chnl=新的NotificationChannel(“频道”、“名称”、NotificationImportance.Default);
mngr.CreateNotificationChannel(chnl);
NotificationCompat.Builder foregroundNotification=新建NotificationCompat.Builder(此);
foregroundNotification.setContinuous(true);
SetContentTitle(“我的前台通知”)
.SetChannelId(“通道”)
.SetContentText(“这是第一个前台通知”);
StartForeground(101,foregroundNotification.Notification);
//广播接收机
receiver=新的PowerBroadcastReceiver();
RegisterReceiver(接收者,新意向过滤器(Intent.ActionScreenOn));
返回StartCommandResult.Sticky;
}
公共覆盖iBind OnBind(意图)
{
//返回null,因为这是纯启动服务。混合服务将返回
//允许访问GetFormattedStamp()方法。
返回null;
}
}
///
/// ////////////////////////////////////////////////////////////////////////////////
///
[广播接收机]
[IntentFilter(新[]{Intent.ActionScreenOn,Intent.ActionScreenOff}]
公共类PowerBroadcastReceiver:BroadcastReceiver
{
公共广播接收器()
{
}
公共覆盖void OnReceive(上下文、意图)
{
if(intent.Action.Equals(intent.ActionScreenOn))
{
//TODO:启动问题页面
Toast.MakeText(上下文“On”,ToastLength.Long).Show();
}
else if(intent.Action.Equals(intent.ActionScreenOff))
Toast.MakeText(上下文“Off”,ToastLength.Long).Show();
}
}
谢谢。您可以创建一个侦听器类来侦听android锁屏和解锁事件,使用广播接收屏幕状态。由于是系统广播,我认为没有必要使用服务
您可以参考以下内容:您可以创建一个侦听器类来侦听android锁屏和解锁事件,使用广播接收屏幕状态。由于是系统广播,我认为没有必要使用服务
您可以参考以下内容:尝试使用读取设备日志?我想我们正在取得进展。谢谢@DenseCrab!android.app.RemoteServiceException:Context.startForegroundService()当时没有调用服务。startForeground()是否尝试实现屏幕解锁之类的功能,每次进入应用程序都会看到一个问题页面?您好。是的,当你解锁手机时,我想要一个问题页面。是的,上面的代码是这样的。试过使用读取设备日志吗?我想我们有进展了。谢谢@Dens