我想在我的项目中实现一个时间表功能。所以我在谷歌上搜索了一个警报管理程序,但我找不到任何例子。
谁能帮我一个基本的警报管理程序?
我想在我的项目中实现一个时间表功能。所以我在谷歌上搜索了一个警报管理程序,但我找不到任何例子。
谁能帮我一个基本的警报管理程序?
当前回答
我在Android上也遇到了警报问题。问题是关于打盹模式(https://developer.android.com/training/monitoring-device-state/doze-standby)。例如,当我把闹钟调到一个小时后,它就正常了,但如果我把它调到凌晨4点,它就不工作了。我刚刚发现这是非常简单的,我只是应该使用AlarmManager.setAlarmClock()而不是AlarmManager.set()。
所以我决定在github上创建一个示例应用程序。 https://github.com/carlosabreu/androidalarm
其他回答
•AlarmManager与IntentService结合使用
我认为使用AlarmManager的最佳模式是它与IntentService的协作。IntentService由AlarmManager触发,它通过接收意图处理所需的操作。这种结构不像使用BroadcastReceiver那样对性能有影响。我在kotlin中为这个想法开发了一个示例代码,可以在这里获得:
MyAlarmManager.kt
import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
object MyAlarmManager {
private var pendingIntent: PendingIntent? = null
fun setAlarm(context: Context, alarmTime: Long, message: String) {
val alarmManager: AlarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(context, MyIntentService::class.java)
intent.action = MyIntentService.ACTION_SEND_TEST_MESSAGE
intent.putExtra(MyIntentService.EXTRA_MESSAGE, message)
pendingIntent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
alarmManager.set(AlarmManager.RTC_WAKEUP, alarmTime, pendingIntent)
}
fun cancelAlarm(context: Context) {
pendingIntent?.let {
val alarmManager: AlarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmManager.cancel(it)
}
}
}
MyIntentService.kt
import android.app.IntentService
import android.content.Intent
class MyIntentService : IntentService("MyIntentService") {
override fun onHandleIntent(intent: Intent?) {
intent?.apply {
when (intent.action) {
ACTION_SEND_TEST_MESSAGE -> {
val message = getStringExtra(EXTRA_MESSAGE)
println(message)
}
}
}
}
companion object {
const val ACTION_SEND_TEST_MESSAGE = "ACTION_SEND_TEST_MESSAGE"
const val EXTRA_MESSAGE = "EXTRA_MESSAGE"
}
}
manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.aminography.alarm">
<application
... >
<service
android:name="path.to.MyIntentService"
android:enabled="true"
android:stopWithTask="false" />
</application>
</manifest>
用法:
val calendar = Calendar.getInstance()
calendar.add(Calendar.SECOND, 10)
MyAlarmManager.setAlarm(applicationContext, calendar.timeInMillis, "Test Message!")
如果你想取消预定的闹钟,试试这个:
MyAlarmManager.cancelAlarm(applicationContext)
这段代码将帮助您制作重复警报。重复时间可由您设置。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#000000"
android:paddingTop="100dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center" >
<EditText
android:id="@+id/ethr"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:ems="10"
android:hint="Hr"
android:singleLine="true" >
<requestFocus />
</EditText>
<EditText
android:id="@+id/etmin"
android:layout_width="55dp"
android:layout_height="wrap_content"
android:ems="10"
android:hint="Min"
android:singleLine="true" />
<EditText
android:id="@+id/etsec"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:ems="10"
android:hint="Sec"
android:singleLine="true" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingTop="10dp">
<Button
android:id="@+id/setAlarm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onClickSetAlarm"
android:text="Set Alarm" />
</LinearLayout>
</LinearLayout>
MainActivity.java
public class MainActivity extends Activity {
int hr = 0;
int min = 0;
int sec = 0;
int result = 1;
AlarmManager alarmManager;
PendingIntent pendingIntent;
BroadcastReceiver mReceiver;
EditText ethr;
EditText etmin;
EditText etsec;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ethr = (EditText) findViewById(R.id.ethr);
etmin = (EditText) findViewById(R.id.etmin);
etsec = (EditText) findViewById(R.id.etsec);
RegisterAlarmBroadcast();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
protected void onDestroy() {
unregisterReceiver(mReceiver);
super.onDestroy();
}
public void onClickSetAlarm(View v) {
String shr = ethr.getText().toString();
String smin = etmin.getText().toString();
String ssec = etsec.getText().toString();
if(shr.equals(""))
hr = 0;
else {
hr = Integer.parseInt(ethr.getText().toString());
hr=hr*60*60*1000;
}
if(smin.equals(""))
min = 0;
else {
min = Integer.parseInt(etmin.getText().toString());
min = min*60*1000;
}
if(ssec.equals(""))
sec = 0;
else {
sec = Integer.parseInt(etsec.getText().toString());
sec = sec * 1000;
}
result = hr+min+sec;
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), result , pendingIntent);
}
private void RegisterAlarmBroadcast() {
mReceiver = new BroadcastReceiver() {
// private static final String TAG = "Alarm Example Receiver";
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Alarm time has been reached", Toast.LENGTH_LONG).show();
}
};
registerReceiver(mReceiver, new IntentFilter("sample"));
pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent("sample"), 0);
alarmManager = (AlarmManager)(this.getSystemService(Context.ALARM_SERVICE));
}
private void UnregisterAlarmBroadcast() {
alarmManager.cancel(pendingIntent);
getBaseContext().unregisterReceiver(mReceiver);
}
}
如果你只需要报警一次,那么更换
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), result , pendingIntent);
with
alarmManager.set( AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + result , pendingIntent );
下面是一个使用Kotlin的Alarm Manager的例子:
class MainActivity : AppCompatActivity() {
val editText: EditText by bindView(R.id.edit_text)
val timePicker: TimePicker by bindView(R.id.time_picker)
val buttonSet: Button by bindView(R.id.button_set)
val buttonCancel: Button by bindView(R.id.button_cancel)
val relativeLayout: RelativeLayout by bindView(R.id.activity_main)
var notificationId = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
timePicker.setIs24HourView(true)
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
buttonSet.setOnClickListener {
if (editText.text.isBlank()) {
Toast.makeText(applicationContext, "Title is Required!!", Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
alarmManager.set(
AlarmManager.RTC_WAKEUP,
Calendar.getInstance().apply {
set(Calendar.HOUR_OF_DAY, timePicker.hour)
set(Calendar.MINUTE, timePicker.minute)
set(Calendar.SECOND, 0)
}.timeInMillis,
PendingIntent.getBroadcast(
applicationContext,
0,
Intent(applicationContext, AlarmBroadcastReceiver::class.java).apply {
putExtra("notificationId", ++notificationId)
putExtra("reminder", editText.text)
},
PendingIntent.FLAG_CANCEL_CURRENT
)
)
Toast.makeText(applicationContext, "SET!! ${editText.text}", Toast.LENGTH_SHORT).show()
reset()
}
buttonCancel.setOnClickListener {
alarmManager.cancel(
PendingIntent.getBroadcast(
applicationContext, 0, Intent(applicationContext, AlarmBroadcastReceiver::class.java), 0))
Toast.makeText(applicationContext, "CANCEL!!", Toast.LENGTH_SHORT).show()
}
}
override fun onTouchEvent(event: MotionEvent?): Boolean {
(getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager)
.hideSoftInputFromWindow(relativeLayout.windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
relativeLayout.requestFocus()
return super.onTouchEvent(event)
}
override fun onResume() {
super.onResume()
reset()
}
private fun reset() {
timePicker.apply {
val now = Calendar.getInstance()
hour = now.get(Calendar.HOUR_OF_DAY)
minute = now.get(Calendar.MINUTE)
}
editText.setText("")
}
}
MainActivity.java
package com.example.alarmexample;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
Button b1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startAlert();
} public void startAlert() {
int timeInSec = 2;
Intent intent = new Intent(this, MyBroadcastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
this.getApplicationContext(), 234, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (timeInSec * 1000), pendingIntent);
Toast.makeText(this, "Alarm set to after " + i + " seconds",Toast.LENGTH_LONG).show();
}
}
MyBroadcastReceiver.java
package com.example.alarmexample;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.widget.Toast;
public class MyBroadcastReceiver extends BroadcastReceiver {
MediaPlayer mp;
@Override
public void onReceive(Context context, Intent intent) {
mp=MediaPlayer.create(context, R.raw.alarm);
mp.start();
Toast.makeText(context, "Alarm", Toast.LENGTH_LONG).show();
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.alarmexample" >
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.alarmexample.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="MyBroadcastReceiver" >
</receiver>
</application>
</manifest>
我尝试了XXX的解决方案,虽然它最初确实有效,但在某种程度上它停止了工作。onReceive再也没有被调用。我花了好几个小时想知道那是什么。我开始意识到,出于某种神秘的原因,意图不再被召唤。为了解决这个问题,我发现确实需要在清单中为接收者指定一个操作。例子:
<receiver android:name=".Alarm" android:exported="true">
<intent-filter>
<action android:name="mypackage.START_ALARM" >
</action>
</intent-filter>
</receiver>
请注意,名称是“。“Alarm”和周期。在XXX的setAlarm方法中,创建Intent,如下所示:
Intent i = new Intent("mypackage.START_ALARM");
START_ALARM消息可以是您想要的任何消息。我这样命名只是为了演示。
I have not seen receivers defined in the manifest without an intent filter that specifies the action. Creating them the way XXX has specified it seems kind of bogus. By specifying the action name, Android will be forced to create an instance of the BroadcastReceiver using the class that corresponds to the action. If you rely upon context, be aware that Android has several different objects that are ALL called context and may not result in getting your BroadcastReceiver created. Forcing Android to create an instance of your class using only the action message is far better than relying upon some iffy context that may never work.