是否可以在不使用服务的应用程序的情况下使用 AlarmManager 来运行警报。AlarmManager 必须让设备退出睡眠模式并在 onReceive 中执行我的代码。实际上,我在这里看到的每个代码示例都显示了正在使用的服务。然而,Android 文档并没有提到需要服务。
问问题
1522 次
3 回答
1
这是一个工作示例,
activity_alarm_manager.xml 文件的代码
<linearlayout android:layout_height="match_parent"
android:layout_width="match_parent" android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<button android:id="@+id/btStart" android:layout_height="wrap_content"
android:layout_width="match_parent" android:onclick="startRepeatingTimer"
android:padding="@dimen/padding_medium" android:text="@string/btStart"
tools:context=".WidgetAlarmManagerActivity"/>
<button android:id="@+id/btCancel" android:layout_height="wrap_content"
android:layout_width="match_parent" android:onclick="cancelRepeatingTimer"
android:padding="@dimen/padding_medium" android:text="@string/btCancel"
tools:context=".WidgetAlarmManagerActivity"/>
<button android:id="@+id/btOneTime" android:layout_height="wrap_content"
android:layout_width="match_parent" android:onclick="onetimeTimer"
android:padding="@dimen/padding_medium" android:text="@string/btOneTime"
tools:context=".WidgetAlarmManagerActivity"/>
</linearlayout>
BroadcastReceiver的代码,
public class AlarmManagerBroadcastReceiver extends BroadcastReceiver {
final public static String ONE_TIME = "onetime";
@Override
public void onReceive(Context context, Intent intent) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "YOUR TAG");
//Acquire the lock
wl.acquire();
//You can do the processing here.
Bundle extras = intent.getExtras();
StringBuilder msgStr = new StringBuilder();
if(extras != null && extras.getBoolean(ONE_TIME, Boolean.FALSE)){
//Make sure this intent has been sent by the one-time timer button.
msgStr.append("One time Timer : ");
}
Format formatter = new SimpleDateFormat("hh:mm:ss a");
msgStr.append(formatter.format(new Date()));
Toast.makeText(context, msgStr, Toast.LENGTH_LONG).show();
//Release the lock
wl.release();
}
public void SetAlarm(Context context)
{
AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
intent.putExtra(ONE_TIME, Boolean.FALSE);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
//After after 5 seconds
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 5 , pi);
}
public void CancelAlarm(Context context)
{
Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(sender);
}
public void setOnetimeTimer(Context context){
AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
intent.putExtra(ONE_TIME, Boolean.TRUE);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), pi);
}
}
AndroidManifest.xml 的代码
<manifest android:versioncode="1" android:versionname="1.0"
package="com.rakesh.alarmmanagerexample"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-sdk android:minsdkversion="10" android:targetsdkversion="15"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application android:icon="@drawable/ic_launcher"
android:label="@string/app_name" android:theme="@style/AppTheme">
<activity android:label="@string/title_activity_alarm_manager"
android:name="com.rakesh.alarmmanagerexample.AlarmManagerActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="com.rakesh.alarmmanagerexample.AlarmManagerBroadcastReceiver">
</receiver>
</application>
</manifest>
AlarmManagerActivity.java 文件的代码
public class AlarmManagerActivity extends Activity {
private AlarmManagerBroadcastReceiver alarm;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_alarm_manager);
alarm = new AlarmManagerBroadcastReceiver();
}
@Override
protected void onStart() {
super.onStart();
}
public void startRepeatingTimer(View view) {
Context context = this.getApplicationContext();
if(alarm != null){
alarm.SetAlarm(context);
}else{
Toast.makeText(context, "Alarm is null", Toast.LENGTH_SHORT).show();
}
}
public void cancelRepeatingTimer(View view){
Context context = this.getApplicationContext();
if(alarm != null){
alarm.CancelAlarm(context);
}else{
Toast.makeText(context, "Alarm is null", Toast.LENGTH_SHORT).show();
}
}
public void onetimeTimer(View view){
Context context = this.getApplicationContext();
if(alarm != null){
alarm.setOnetimeTimer(context);
}else{
Toast.makeText(context, "Alarm is null", Toast.LENGTH_SHORT).show();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_widget_alarm_manager, menu);
return true;
}
}
于 2013-04-20T10:45:52.107 回答
0
我认为Activity
通过传递它来设置周期性事件Context
并不重要,并且传递哪个上下文似乎并不重要。
passcontext
仅用于获取PendingIntent
fromPendingIntent.getBroadcast
和 from 查看4.2.2 的源:
/**
* Retrieve a PendingIntent that will perform a broadcast, like calling
* {@link Context#sendBroadcast(Intent) Context.sendBroadcast()}.
*
* @param context The Context in which this PendingIntent should perform
* the broadcast.
* @param requestCode Private request code for the sender (currently
* not used).
* @param intent The Intent to be broadcast.
* @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE},
* {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT},
* or any of the flags as supported by
* {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
* of the intent that can be supplied when the actual send happens.
*
* @return Returns an existing or new PendingIntent matching the given
* parameters. May return null only if {@link #FLAG_NO_CREATE} has been
* supplied.
*/
public static PendingIntent getBroadcast(Context context, int requestCode,
Intent intent, int flags) {
return getBroadcastAsUser(context, requestCode, intent, flags,
new UserHandle(UserHandle.myUserId()));
}
/**
* @hide
* Note that UserHandle.CURRENT will be interpreted at the time the
* broadcast is sent, not when the pending intent is created.
*/
public static PendingIntent getBroadcastAsUser(Context context, int requestCode,
Intent intent, int flags, UserHandle userHandle) {
String packageName = context.getPackageName();
String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
context.getContentResolver()) : null;
try {
intent.setAllowFds(false);
IIntentSender target =
ActivityManagerNative.getDefault().getIntentSender(
ActivityManager.INTENT_SENDER_BROADCAST, packageName,
null, null, requestCode, new Intent[] { intent },
resolvedType != null ? new String[] { resolvedType } : null,
flags, null, userHandle.getIdentifier());
return target != null ? new PendingIntent(target) : null;
} catch (RemoteException e) {
}
return null;
}
你可以看到,passedcontext
仅用于获取包名和解析类型,并没有存储在PendingIntent
或任何可能导致一些问题和泄漏的东西中。
于 2013-04-20T11:16:08.427 回答
0
你可以:
给出
AlarmManager
一个PendingIntent
带有 Intent 的特定过滤器BroadCastReciever
。在应用程序的清单中声明此接收器以及意图过滤器。
该接收器
onRecieve()
将被调用AlarmManager
。
不涉及任何服务。
于 2013-04-20T08:24:20.510 回答