【问题标题】:Service with Timer calling another Service带有计时器的服务调用另一个服务
【发布时间】:2016-01-09 10:28:30
【问题描述】:

我正在使用Service 管理从服务器到客户端客户端到服务器的数据。因为我在登录后打电话给Service

context.startService(new Intent(LoginActivity.this, CheckAutoSyncReceivingOrder.class));
context.startService(new Intent(LoginActivity.this, CheckAutoSyncSendingOrder.class));

我在Service上面都调用了一个计时器

CheckAutoSyncReceivingOrder 服务:

它在 Every 1 上调用另一个名为 ReceivingOrderService 的服务 分钟从服务器获取更新数据。

public class CheckAutoSyncReceivingOrder extends Service {

    Timer timer;

    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        Log.i(TAG, "CheckAutoSyncReceivingOrder Binding Service...");
        return null;
    }

    @Override
    public void onStart(Intent intent, int startId) {
        // TODO Auto-generated method stub

        if (timer != null) {
            timer.cancel();
            Log.i(TAG, "RECEIVING OLD TIMER CANCELLED>>>");
        }

        timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                Log.i(TAG, "<<<<<<<<< RECEIVING AUTO SYNC SERVICE <<<<<<<<");
                if (InternetConnection.checkConnection(getApplicationContext())) {
                    if (getDatabasePath(DatabaseHelper.DATABASE_NAME).exists())
                        startService(new Intent(
                                CheckAutoSyncReceivingOrder.this,
                                ReceivingOrderService.class));
                } else {
                    Log.d(TAG, "Connection not available");
                }
            }
        }, 0, 60000); // 1000*60 = 60000 = 1 minutes
    }

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub

        if (timer != null)
            timer.cancel();

        Log.d(TAG, "Stopping Receiving...");

        super.onDestroy();
    }
}

CheckAutoSyncSendingOrder 服务:

它每 2.5 调用另一个名为 SendingOrderService 的服务 分钟将更新的数据发送到服务器。

public class CheckAutoSyncSendingOrder extends Service {

    Timer timer;

    @Override
    public void onStart(Intent intent, int startId) {
        // TODO Auto-generated method stub

        if (timer != null) {
            timer.cancel();
            Log.i(TAG, "OLD TIMER CANCELLED>>>");
        }

        timer = new Timer();

        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                Log.i(TAG, ">>>>>>>> SENDING AUTO SYNC SERVICE >>>>>>>>");
                if (InternetConnection.checkConnection(getApplicationContext())) {
                    if (getDatabasePath(DatabaseHelper.DATABASE_NAME).exists())
                        startService(new Intent(CheckAutoSyncSendingOrder.this,
                                SendingOrderService.class));
                } else {
                    Log.d(TAG, "connection not available");
                }
            }
        }, 0, 150000); // 1000*60 = 60000 = 1 minutes * 2.5 = 2.5 =>Minutes
    }

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub

        if (timer != null)
            timer.cancel();

        Log.d(TAG, "Stopping Sending...");

        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }

这两个 Activity 将一直运行到 Internet 关闭。当 Internet 连接可用时,它会自动再次调用。

主要是我遇到了问题在自动销毁活动服务调用时

是否有任何解决方案或方法可以改变同一事物的流程?

提前谢谢你。

【问题讨论】:

  • 它是IntentService I have posted this question 的子类,但我认为我的问题在于流量,所以我再次发布。
  • 我已经在我的last question中解释过了
  • 我刚刚解决了错误日志的问题,其中我收到了token null 的错误,但我仍然遇到调用破坏活动的服务问题。
  • 我没有覆盖除onCreate()之外的任何其他方法
  • @PratikButani 您是否使用过 IntentService 而不是 Service?如果您查看stackoverflow.com/questions/15524280/service-vs-intentservice,您会发现 Service 在后台运行,但它在应用程序的主线程上运行,因此如果主线程被破坏,服务将重新启动,因此您需要使用 IntentService 并覆盖 onStartCommand(Intent, int, int) ,将所有实现代码移至此方法并在该方法中返回 START_NOT_STICKY

标签: android android-activity android-service android-lifecycle android-timer


【解决方案1】:

您必须使用IntentService 而不是Service

  • Service 在后台运行,但在应用程序的主线程上运行。
  • IntentService 在单独的工作线程上运行。

如果运行你的服务的进程被杀死,Android系统会自动重启,这是默认行为。

因此,如果 Activity 的主线程被破坏,服务将重新启动,但如果您使用 IntentService 并使用 START_NOT_STICKY,那么它不会重新启动您的服务。

此行为由您的服务实现中onStartCommand() 的返回值定义。常量START_NOT_STICKY 告诉Android 如果服务正在运行而进程被“杀死”,则不要重新启动服务。

您需要在您的服务类中重写方法onStartCommand(),并将您的所有代码从onStart() 方法移动到onStartCommand() 方法。

根据 Android 文档:

对于已启动的服务,还有两种额外的主要模式 他们可以决定运行的操作,具体取决于他们的价值 从onStartCommand() 返回:START_STICKY 用于服务 根据需要显式启动和停止,而START_NOT_STICKYSTART_REDELIVER_INTENT 用于仅应 在处理发送给他们的任何命令时保持运行

每次重启服务时都会调用onStart()方法,但如果返回START_NON_STICKY则不会调用onStartCommand()方法。

有关IntentServiceService 之间区别的更多详细信息。你可以查看this

希望对你有帮助。

【讨论】:

  • 我想到了一个问题,当IntentService 被销毁时,onDestroy() 将调用并且myTimer 将停止。那么它将如何重新开始。它将如何运作?
  • 当Activity被销毁时,你希望服务继续还是停止服务?
  • 因为 Timer,我想继续运行服务。我不想在活动被破坏时停止。当我不需要时,我已经以编程方式停止了该服务。
【解决方案2】:

来自documentation

服务启动时,它的生命周期独立于启动它的组件,并且该服务可以无限期地在后台运行,即使启动它的组件被销毁也是如此。因此,服务应该在其工作完成时通过调用 stopSelf() 自行停止,或者其他组件可以通过调用 stopService() 来停止它。

由于您在相关Activity“没有覆盖除 onCreate() 之外的任何其他方法”,您可能会遇到以下情况:

  1. ServiceonDestroy()不会被调用,除非另一个应用组件调用stopService()
  2. 说结果Timer 继续执行其工作。

根据文档停止服务。

编辑(关于您的评论):

“当我销毁活动时它开始新工作” 表示系统终止了服务,并且由于您没有覆盖默认返回值为START_STICKYonStartCommand(),因此该服务已被重新创建并调用了它的onStart() 方法。

无法更改此类系统行为。但是您可以在foreground 中运行该服务。

【讨论】:

  • 但是为什么当我破坏活动时它开始新工作。我不想停止服务,因为我的应用程序的后台同步过程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-01
  • 1970-01-01
  • 2018-04-25
  • 1970-01-01
  • 2011-01-31
  • 2015-11-10
相关资源
最近更新 更多