【问题标题】:Setting up Alarm Manager is creating 2 Instances of my Main Activity设置警报管理器正在创建我的主要活动的 2 个实例
【发布时间】:2025-12-14 02:20:03
【问题描述】:

我有 2 个活动,一个主要活动和 SetAlarm 活动。我从 Main 调用 SetAlarm Activity。当我设置警报时,我创建了一个我的 main 实例。如何在不创建 Main 的另一个实例的情况下设置警报,或者在设置警报之前杀死 main?对此很陌生。我已经阅读了几个警报管理器示例,但它们似乎都建立了一个新的意图,我认为这就是创建我的 2 个实例的原因。这就是你设置闹钟的方式。它确实熄灭了。

这是我从 Main 调用 SetAlarm 的方式:

public void setAlarm(View view) {
    Intent intent = new Intent(this, SetAlarmActivity.class);
    startActivityForResult(intent, 2);  
} 

这是我设置闹钟的方法:

public void setUpAlarm() {
    if (VERBOSE) Log.v(TAG, "+++ IN setUpAlarm +++");                   
        PLAY_MUSIC = "Y";
        Intent intentAlarm = new Intent(this, MainActivity.class);
        intentAlarm.putExtra("playMusic",PLAY_MUSIC);
        intentAlarm.putExtra("mPos", mPos);
        intentAlarm.putExtra("result",ALARM_SET);
        setResult(RESULT_OK,intentAlarm);
        pIntent = PendingIntent.getActivity(this, 12345, 
                intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager am = (AlarmManager)(this.getSystemService( Context.ALARM_SERVICE ));
        am.set(AlarmManager.RTC_WAKEUP, calSet.getTimeInMillis(), pIntent );
    } // setAlarmPlaySong

我主要切断了警报:

@Override
public void onResume() {
    if (VERBOSE) Log.v(TAG, "+++ IN onResume +++");
    super.onResume();  
    Intent intent = getIntent()
    if (intent.hasExtra("playMusic")  && intent.hasExtra("mPos")) {
   playMusicFlag = intent.getStringExtra("playMusic"); 
   mPos = intent.getIntExtra("mPos", 0);   
   if (playMusicFlag.equalsIgnoreCase("Y")) {
       if (VERBOSE) Log.v(TAG, "+++ playMusicFlag is SET+++");
           playSongs();
               showStopAlarmButton();
       } // if    
   }
}

【问题讨论】:

  • 当你设置警报时你是什么意思,你创建了一个 main 实例?你的意思是 Main Activity 已经创建了吗?
  • 是的,main 已经创建,然后我在设置警报时设置了另一个 Main 实例。

标签: android alarmmanager start-activity


【解决方案1】:

如果您希望您的 startActivity 不应该启动多个 alam 活动实例 你应该去你的清单,并且必须为你的警报活动添加一个名为 launchMode 的属性并将其设置为 SingleTop ,这将确保只有一个实例保留在 taskk 后台堆栈中(每个活动都以 LIFO 方式驻留的地方)

【讨论】:

  • 感谢您的回复。我使用 StartActivityForResults 通过以下语句 setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP) 调用 SetAlarm。这似乎实现了我期望的结果。我阅读了 Tasks 和 Back Stack ,但仍然有些混乱。带有 StartActivity 的标志是否完成与“android:launchmode="singleTask" 或 "singleTop" 相同的行为?
  • 是的,它们的工作方式相同。 startActivity 在您动态设置模式时很有帮助,但当您想通过清单永久设置它时。
【解决方案2】:

默认情况下,Activity 可以在多个任务上多次实例化。如果您想保持单一,请在 AnroidManifest.xml 中的 Activity 声明中指定 android:launchMode="singleTask" 并在主 Activity 上覆盖 Activity#onNewIntent() 以接收来自 AlarmManager 的新意图(如果主 Activity 已实例化)。

请参阅Tasks and Back Stack 了解更多信息。您面临的情况与 图 3 中显示的情况几乎相同。

【讨论】:

  • 感谢您的回复。是的,图 3 正是我所面临的情况。
【解决方案3】:

我不知道为什么你有 SetAlarm Activity,你不需要一个活动来设置警报。无论如何,AlarmManager 工作起来很痛苦。我花了一段时间才启动并运行它。这就是我现在在我的代码中运行的内容。

        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.SECOND, 5);
        AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
        Intent notifyintent = new Intent(this, OnAlarmReceiver.class);
        notifyintent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        notifyintent.setAction("android.intent.action.NOTIFY");
        PendingIntent notifysender = PendingIntent.getBroadcast(this, 0, notifyintent,
                PendingIntent.FLAG_UPDATE_CURRENT);
        am.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 20 * 1000,
                notifysender);

OnAlarmReceiver

public class OnAlarmReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // PullPendingRequests.acquireStaticLock(context)
        try {
            lock = getLock(context);
            lock.acquire();
            context.startService(new Intent(context, UpdateCustomerRequests.class));
        } finally {
            if (lock.isHeld()) {
                lock.release();
            }
        }
    }

    private static final String NAME = "com.commonsware.cwac.wakeful.WakefulIntentService";
    private static volatile PowerManager.WakeLock lockStatic = null;
    private static PowerManager.WakeLock lock;

    synchronized private static PowerManager.WakeLock getLock(Context context) {
        if (lockStatic == null) {
            PowerManager mgr = (PowerManager) context.getSystemService(Context.POWER_SERVICE);

            lockStatic = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NAME);
            lockStatic.setReferenceCounted(true);
        }

        return (lockStatic);
    }
}

OnAlarmReceiver调用的IntentService

public class UpdateCustomerRequests extends IntentService {
@Override
    final protected void onHandleIntent(Intent intent) {
        //
        //Your stuff here
        //
    }

    public class LocalBinder extends Binder {
        public UpdateCustomerRequests getService() {
            return UpdateCustomerRequests.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return bindToHomeScreen;
    }
}

Android 清单

  • 清单标签内

<uses-permission android:name="android.permission.WAKE_LOCK" />

  • 内部应用标签

        <receiver
            android:name="com.taxeeta.support.OnAlarmReceiver"
            android:exported="true" >
            <intent-filter>
                <action android:name="android.intent.action.NOTIFY" />
            </intent-filter>
        </receiver>
    

【讨论】:

  • 感谢代码 sn-ps。我有一个 setAlarm 活动,因为它允许用户执行其他操作,例如在闹钟响起时选择要开始的歌曲并使用按钮打开闹钟。看起来我们正在设置类似的警报,但我不使用广泛的接收器。再次感谢您的帮助!
  • 我推荐一个 BroadcastReceiver,因为它符合 Android 的基本原理。我已经尝试了所有其他方法,但在运行 3-4 小时后失败了。 :) 这种组合现在在生产应用程序上运行良好。也为你的问题投票,格式正确。
最近更新 更多