【问题标题】:How do you start an Activity with AlarmManager in Android?如何在 Android 中使用 AlarmManager 启动 Activity?
【发布时间】:2011-08-13 10:55:45
【问题描述】:

我已经浏览了十几个关于这个问题的教程和论坛答案,但仍然无法将一些工作代码放在一起。我会尽量让问题直截了当:

如何使用 AlarmManager(在 Android API 中)在给定时间启动 Activity?这个问题的任何解决方案都可以。

我最近的尝试如下。

(省略了导入。我希望 MyActivity 在程序打开 3 秒后启动,但事实并非如此。没有错误消息可言。)

public class AndroidTest2Activity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Context context = this;//.getApplicationContext();

        AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); // CORRECT
        Intent intent = new Intent(context, myReceiver.class); // CORRECT
        PendingIntent pending = PendingIntent.getBroadcast( context, 0, intent, 0 ); // CORRECT
        manager.set( AlarmManager.RTC, System.currentTimeMillis() + 3000, pending ); // CORRECT

        setContentView(R.layout.main);
    }
}

public class myReceiver extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
        Intent i=new Intent(context, myActivity.class);
        i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(i);
    }
}

public class myActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("", "Elusive success");
        setContentView(R.layout.main);
    }
}

任何建议将不胜感激。

请注意:我已经在清单中找到了 myReceiver

【问题讨论】:

  • 你在你的 AndroidManifest 中注册了接收器吗?
  • 对不起,应该提到这一点。使用 行,是的,我做到了。让我知道这是否是错误的行。
  • 对于启动活动而不是创建广播的警报,请确保您使用的是PendingIntent.getActivity(...) 而不是PendingIntent.getBroadcast(...)

标签: android alarmmanager


【解决方案1】:

万一其他人偶然发现 - 这里有一些工作代码(在 2.3.3 模拟器上测试):

public final void setAlarm(int seconds) {
    // create the pending intent
    Intent intent = new Intent(MainActivity.this, AlarmReceiver.class);
    // intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0,
            intent, 0);
    // get the alarm manager, and scedule an alarm that calls the receiver
    ((AlarmManager) getSystemService(ALARM_SERVICE)).set(
            AlarmManager.RTC, System.currentTimeMillis() + seconds
                    * 1000, pendingIntent);
    Toast.makeText(MainActivity.this, "Timer set to " + seconds + " seconds.",
            Toast.LENGTH_SHORT).show();
}

public static class AlarmReceiver extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
        Log.d("-", "Receiver3");
    }
}

AndroidManifest.xml:

    <receiver android:name="com.example.test.MainActivity$AlarmReceiver" >
    </receiver>

BenLambell 的代码问题:

  • 要么:
    • 将接收器移动到它自己的 .java 文件或
    • 将内部类设为静态 - 这样就可以从外部访问它
  • 接收方未在清单中正确声明:
    • 如果它是 MainActivity 中的内部类,请使用: &lt;receiver android:name="package.name.MainActivity$AlarmReceiver" &gt;&lt;/receiver&gt;
    • 如果它位于单独的文件中: &lt;receiver android:name="package.name.AlarmReceiver" &gt;&lt;/receiver&gt;

如果您的意图是在接收者的 onReceive 中显示一个对话框(像我一样):这是不允许的 - 只有活动才能启动对话框。这可以通过dialog activity 来实现。

您可以直接使用 AlarmManager 调用活动:

Intent intent = new Intent(MainActivity.this, TriggeredActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
((AlarmManager) getSystemService(ALARM_SERVICE)).set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + seconds * 1000, pendingIntent);

【讨论】:

  • 如果应用在后台或关闭,是否可以直接使用AlarmManager调用活动启动活动或将其置于最前面?我正在尝试没有成功。
【解决方案2】:

如何使用 AlarmManager(在 Android API 中)在给定时间启动 Activity?

set() 调用提供PendingIntent,以标识要启动的活动。或者,做你正在做的事情,这应该可以正常工作。

This sample project 有点复杂,因为我的一本书中有 19 个教程,但是如果您查看 EditPreferencesOnBootReceiverOnAlarmReceiver 之类的课程,您会看到相同的基本配方你在上面使用。在这种情况下,我可以只使用getActivity()PendingIntent,但在此之后的教程让用户可以选择启动活动或显示Notification,因此BroadcastReceiver 更有意义。

在 LogCat 中查找除错误之外的警告。很可能,您的接收器或活动不在您的清单中。

请注意,突然弹出一个活动通常不是一个好主意。从有问题的书中引用我自己的话:

通过全屏活动显示午餐时间警报当然有效, 如果用户正在看屏幕,它会引起他们的注意。然而, 如果他们碰巧使用了正确的电话,那也会造成很大的破坏 立即的。例如,如果他们在开车时输入短信,您的 突然出现的警报活动可能会分散他们的注意力 造成事故。所以,为了公共安全,我们应该给用户一个选项 有一个更微妙的方式来提醒他们吃午饭。

【讨论】:

  • 感谢您的快速响应 - 实际上我已经看过您的教程了。我尝试替换 Intent intent = new Intent(context, MyActivity.class); // 正确的 PendingIntent pending = PendingIntent.getActivity( context, 0, intent, 0 ); //正确
  • 感谢您的快速响应 - 实际上我已经看过您的教程(并将接收器放在清单中)。我尝试替换 Intent intent = new Intent(context, MyActivity.class); PendingIntent 未决 = PendingIntent.getActivity(context, 0, intent, 0);但仍然没有得到 MyActivity 运行的任何证据。但是,我确实收到以下日志消息: (ActivityManager) Starting: Intent { flg=0x4 cmp=com.ben/.MyActivity (has extras) } from pid -1
  • 然后出现“ID 0 没有键盘”警告和“请求时间失败:Java.net.SocketException:协议不支持地址系列”调试消息。

    这是否意味着 MyActivity 正在启动?如果是这样,为什么它的 onCreate() 不运行?
  • @BenLambell:打败我。如果活动在清单中,它应该正在启动。也许它在 onCreate() 的某个地方崩溃了——不过,你应该看到一个堆栈跟踪。
  • @user1681572:“这是误导吗?” -- 如果您使用_WAKEUP 警报,您对设备处于唤醒状态的唯一保证是它在调用onReceive() 期间将处于唤醒状态。除了这种情况之外,与任何其他类型的 PendingIntent 相比,我不知道使用 getBroadcast() PendingIntentAlarmManager 有什么特别神奇的地方。
【解决方案3】:

将此添加到您的 android mainifest 文件中,它有望工作

<activity android:name=".MyReceiver" />
        <receiver android:name=".MyReceiver"> </receiver>

【讨论】:

    【解决方案4】:

    根据我的经验,您可以在没有广播接收器的情况下实现此目的,只需使用PendingIntent.getActivity() 而不是getbroadcast()

    private void setReminder(){
    
    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
                Calendar startTime = Calendar.getInstance();
                startTime.add(Calendar.MINUTE, 1);
                Intent intent = new Intent(ReminderActivity.this, ReminderActivity.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                PendingIntent pendingIntent = PendingIntent.getActivity(ReminderActivity.this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
                alarmManager.set(AlarmManager.RTC, startTime.getTimeInMillis(), pendingIntent);   
    }
    

    我已在 android O 上测试过此代码,但我不确定其他 android 版本是否适用于任何其他 android 版本,请告知我。

    【讨论】:

      【解决方案5】:

      我很久以前就遇到过这个问题,不知道哪个答案是正确的,但是感谢大家的回答。我是自我回答的,所以问题还没有解决。

      【讨论】:

        【解决方案6】:

        根据Java约定类名以大写字母开头。所以改变你的

        "myReceiver" to "MyReceiver" and  "myActivity" to "MyActivity".
        

        然后在清单文件中添加您的接收器,如下所示。

        <application 
        ------------
        <receiver android:name="MyReceiver"></receiver>
        ---------------------
        </application>
        

        【讨论】:

        • 我采用了适当的 Java 约定,以防万一。虽然清单中已经有正确的行(我尝试使用 .MyReceiver 和 MyReceiver 作为 android:name - 我见过的来源似乎也可以)。无论如何,这并不能解决问题,但感谢您的建议。
        【解决方案7】:

        您没有为接收器发送任何广播到接收器,而且它看起来像您想要一个启动屏幕或类似的东西为此您可以启动一个新线程等待几秒钟然后开始您的活动那个时间段你可以在 UI 线程上做任何你想做的事......

        【讨论】:

          【解决方案8】:

          主要问题:如果您完全关闭您的应用程序并期望在 3 秒后开始您的活动,那您就错了。因为当您关闭您的应用时,您的应用无法接收广播,为了解决此问题,请使用服务而不是广播。

          要点:当你的服务会运行时,你不能开始你的活动如果你的应用程序不会在前台。

          解决方案:我认为当您的服务启动时,您可以再次将 Alarmmanager 设置为使用 PendingIntent 开始您的活动 刚刚

          记住

          1. 创建意图以将其传递给pendingIntent 时,将FLAG_ACTIVITY_NEW_TASK 添加到其中。
          2. 对于这个 PendingIntent 使用 PendingIntent.getActivity() 方法,对于第一个 PendingIntent 使用 PendingIntent.getService() 方法。

          希望对你有所帮助。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-06-19
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多