2

我正在编写我的第一个使用服务的应用程序,遵循这里的教程/指南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);

    }
}

我的清单文件如下所示:

    <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>
4

2 回答 2

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() 方法在活动“死亡”时被调用?或者您的活动启动它或绑定到它,但是当进程被杀死时它会消失并且永远不会回来?

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

Service 和 Activity 生命周期是完全不同且不相关的,并且进程生命周期与其中任何一个都有很大不同。如果你想从你的活动中与你的服务交互,你可能想绑定到它,以及从一个计时器启动它。两者都做完全没问题!(尽管拥有两个服务通常更好——一个后台或基于计时器的服务,以及一个后台服务和活动都绑定到的控制/配置服务)。

只是为了确保将每个绑定与取消绑定匹配,并且每次以 Service.stopSelfResult(int) (如果服务每次启动时都执行一个工作单元)或 Context.stopService(Intent) (如果服务根据调用者的需要是连续的),因此系统知道您何时完成服务。

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

于 2012-12-29T09:44:25.750 回答
0

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

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

于 2012-06-25T19:34:45.890 回答