启动服务计划而不重启?

时间:2012-06-25 19:14:16

标签: android service broadcastreceiver

我正在编写我的第一个使用服务的应用,遵循此处的教程/指南http://www.vogella.com/articles/AndroidServices/article.html 我的服务工作正常,它描述了为BOOT_COMPLETED制作广播接收器,它可以让我每隔几分钟运行一次服务。

我遇到的问题是,在用户重新启动手机之前它无效。该服务从活动开始,但似乎也会因为活动而死亡,除非设备已重新启动。

有没有办法在第一次运行时从活动启动调度程序而不重新启动?

我的调度程序代码如下:

public class ScheduleReceiver extends BroadcastReceiver {

    // Restart service every 30 seconds
    private static final long REPEAT_TIME = 1000 * 60; // check every minute.  

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("schedulereceiver", "starting schedule");
        AlarmManager service = (AlarmManager) context
                .getSystemService(Context.ALARM_SERVICE);
        Intent i = new Intent(context, StartServiceReceiver.class);
        PendingIntent pending = PendingIntent.getBroadcast(context, 0, i,
                PendingIntent.FLAG_CANCEL_CURRENT);
        Calendar cal = Calendar.getInstance();
        // Start 30 seconds after boot completed
        cal.add(Calendar.SECOND, 30);
        //
        // Fetch every 30 seconds
        // InexactRepeating allows Android to optimize the energy consumption
        service.setInexactRepeating(AlarmManager.RTC_WAKEUP,
                cal.getTimeInMillis(), REPEAT_TIME, pending);

        // service.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
        // REPEAT_TIME, pending);

    }
}

My Manifest文件如下所示:          

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

    <uses-sdk android:minSdkVersion="8" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >

        <activity
            android:name=".ProximityActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".ProximityService"
            android:enabled="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/service_name" >
        </service>

        <receiver android:name="ScheduleReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
        <receiver android:name="StartServiceReceiver" >
        </receiver>
    </application>

</manifest>

2 个答案:

答案 0 :(得分:2)

这里的基本问题是你想在两种不同的情况下设置计时器。

您希望在启动时进行设置 - 并且您希望在用户首次启动应用程序时进行设置。 (我担心你不能安装它。)

我发现这样做的最好方法是在第一次设置时,在文件系统中记录你设置的计时器。

在ScheduleReceiver中,创建两个公共静态方法:

public static void startupActions(Context ctx) {
    setupTimer();
    try {
        ctx.openFileOutput(".inited", Context.MODE_PRIVATE).close();
    } catch (IOException e) {
        throw new Error(e);
    }
}

从onReceive()方法调用上面的方法。我们马上就会重复使用它。

public static boolean hasStartupRun(Context ctx) {
    try {
        ctx.openFileInput(".inited").close();
        return true;
    } catch (IOException e) {
        return false;
    }
}

在主活动的onCreate()方法中使用这些来判断是否需要启动计时器:

    if (! ScheduleReceiver.hasStartupRun(this)) {
        ScheduleReceiver.startupActions(this);
    }

似乎重新安装不会清除计时器,因此您需要担心的唯一其他故障是您是否需要以某种方式修改计时器(或其他一组启动操作)。要处理这个问题,您可以修改意图,以便不处理旧的意图,并重命名该文件,以便安排新文件。

您可以使用任何其他持久性标志,例如数据库创建,首选项文件等,但以这种方式创建文件是我从BroadcastReceiver可以想到的最简单的方法。

我发现你的问题有点令人费解的一件事是你的服务“开始”并且“死”了活动。

我意识到这个问题已经有几个月了,但是为了其他可能穿着类似鞋子的读者......这听起来有点困惑。你的意思是,当活动开始时调用服务的onCreate()方法,当活动“死”时调用onDestroy()方法?或者你的活动开始它或绑定它,但它消失了,并且当过程被杀死时它永远不会回来?

我提出这个问题的原因是,根据您的服务的不同,您可能希望删除正在启动服务的其他任何代码,并且只依赖于计时器。

服务和活动生命周期完全不同且不相关,并且流程生命周期与任何一个都完全不同。如果您想要从您的活动中与您的服务进行交互,您可能希望绑定它,以及从计时器启动它。这两个都完全可以! (虽然通常最好有两个服务 - 基于后台或基于计时器的服务,以及后台服务和活动绑定到的控制/配置服务。)

只是为了确保将每个绑定与unbind匹配,并且每次以Service.stopSelfResult(int)开始(如果服务在每次启动时执行一个工作单元)或者Context.stopService(Intent)(如果服务是根据呼叫者的需要连续进行的,那么系统就知道你何时完成了服务。

如果您正在使用startService,请务必仔细选择要从onStartCommand(...)返回的标志。

答案 1 :(得分:0)

Service的问题是它作为单个实例运行。每次启动相同的服务时,只调用onStartCommand()方法。因此,在alarmManager中使用它并期望Service重新运行可能不会发生。

检查以下内容以获取更多详细信息: http://developer.android.com/guide/components/services.html#StartingAService