2

アプリがサービスを使用せずに AlarmManager を使用してアラームを実行することは可能ですか? AlarmManager は、デバイスをスリープ モードから復帰させ、onReceive でコードを実行する必要があります。私がここに投稿したほとんどすべてのコード サンプルは、サービスが使用されていることを示しています。しかし、Android のドキュメントには、サービスの必要性については言及されていません。

4

3 に答える 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;
    }
}

Githubからの参照リンク

于 2013-04-20T10:45:52.107 に答える
0

Activity渡すことで定期的なイベントを設定することは問題ではないと思いますが、Contextどのコンテキストが渡されるかは問題ではないようです。

渡された は、 4.2.2 のソースを参照してfromおよび from をcontext取得する場合にのみ使用されます。PendingIntentPendingIntent.getBroadcast

/**
 * 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問題やリークを引き起こす可能性のある に格納されていないことがわかります。

于 2013-04-20T11:16:08.427 に答える