2013-04-20 73 views
2

是否有可能使用AlarmManager在沒有應用程序使用服務的情況下運行鬧鐘。 AlarmManager必須使設備退出睡眠模式並在onReceive中執行我的代碼。事實上,我在這裏發佈的每個代碼示例都顯示了正在使用的服務。然而,Android文檔沒有提到需要提供服務。使用AlarmManager沒有服務

+0

把你的鏈接放在一個解決方案,我會檢查它。 – AndroidDev 2013-04-20 10:40:43

回答

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> 

廣播接收器的代碼,

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; 
    } 
} 

引用鏈從Github

0

您可以:

  1. AlarmManager一個PendingIntent與特定BroadCastReciever的意圖過濾器。

  2. 聲明此接收器的應用程序的清單連同意圖 篩選器。

  3. 接收者的onRecieve()將被AlarmManager調用。

否涉及服務。

0

,我不認爲它很重要我通過傳遞這是一個Context設置從Activity週期性事件,它似乎並沒有問題哪個上下文被傳遞。

傳遞的context僅在正從PendingIntent.getBroadcastPendingIntent和看source of 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; 
} 

你可以看到,通過context僅用於獲取包名和解決的類型和不存儲在PendingIntent或任何可能導致一些問題和泄漏的東西。

+0

這似乎不是真的。我在Pending意圖中使用了一個動作,而不是使用上下文,然後onReceive被解僱了。使用上下文最初在我的應用程序中工作,但最終未能觸發。使用動作保證AlarmManager將創建你的類的一個實例。上下文並不完全相同,並且有很多人在接受解僱時遇到問題。 – AndroidDev 2013-04-20 12:20:35

+0

@AndroidDev你是如何得到一個廣播'PendingIntent'而不通過'context'傳遞的?你沒有使用這個函數:http://developer.android.com/reference/android/app/PendingIntent.html#getBroadcast (android.content.Context,%20int,%20android.content.Intent,%20int) – 2013-04-20 12:30:55

+0

I指的是Intent,而不是getBroadcast的上下文參數。您不需要意向的上下文。我使用動作信息。 – AndroidDev 2013-04-20 15:15:54