0

我有一个 IntentService 执行以下操作:

protected void onHandleIntent(Intent intent) {
    // TODO Auto-generated method stub
    while (true) {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("Hello, World!");
    }
}

以上是我正在使用的代码示例。我打算将 println() 替换为发送到服务器的 HTTP 请求,但现在我将其用作测试。我这样调用 startService() :

@Override
public void onPause() {
    ConnectionUtility.getInstance().startService(this);
    super.onPause();
}

@Override
public void onDestroy() {
    ConnectionUtility.getInstance().startService(this);
    super.onDestroy();
}

@Override
public void onStop() {
    ConnectionUtility.getInstance().startService(this);
    super.onStop();
}

我的自定义 startService 方法在哪里执行此操作:

public void startService(Activity activity) {
    if (!isMyServiceRunning(activity)) {
        Intent intent = new Intent(activity, BackgroundUpdateService.class);
        activity.startService(intent);
    }
}

注意: isMyServiceRunning() 方法是我在其他地方找到的用于确定服务是否正在运行的自定义方法。据我所知,该方法有效。

现在,此服务的目的是在特定 Activity 退出时(通过 onPause()、onDestroy() 或 onStop())触发 println(),并且当 onCreate() 或 onResume() 运行时,该服务将像这样停止:

@Override
public void onResume() {
    ConnectionUtility.getInstance().stopServiceIfRunning(this);
    super.onResume();
}

更深入地了解 stopServiceIfRunning():

public void stopServiceIfRunning(Activity activity) {
    if (isMyServiceRunning(activity)) {
        Intent intent = new Intent(activity, BackgroundUpdateService.class);
        activity.stopService(intent);
    }
}

现在问题来了:我可以正常启动服务,当我通过 Home/Back 按钮退出 Activity 或切换到不同的 Activity 时,startService() 方法启动并完美运行;也就是说,“你好,世界!” 根据需要每 5 秒打印一次。但是当我导航回 Activity 时,我可以确定我的自定义 stopServiceIfRunning() 方法运行并且代码正常进入 IF 块(已确认),但是服务没有停止并且“Hello,World!”只是保持未来。我究竟做错了什么?

---编辑---回应塞拉芬的评论:

private boolean isMyServiceRunning(Activity activity) {
    ActivityManager manager = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
    for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (BackgroundUpdateService.class.getName().equals(service.service.getClassName())) {
            return true;
        }
    }
    return false;
}

但同样,到目前为止,这种方法可以准确地返回真假值,所以我认为这不是问题所在。

4

2 回答 2

2

终于想出了一个办法,真的很感谢塞拉芬帮了我这么多。

我最终覆盖了我的自定义 IntentService 类的 onDestroy() 方法。这就是我想出的:

public class BackgroundUpdateService extends IntentService {

    private boolean status;

    public BackgroundUpdateService() {
        super("BackgroundUpdateService");
        // TODO Auto-generated constructor stub
    }   

    @Override
    protected void onHandleIntent(Intent intent) {
        status = true;
        // TODO Auto-generated method stub
        while (status) {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("Hello, World!");
        }
    }

    @Override
    public void onDestroy() {
        status = false;
        super.onDestroy();
    }
}

显然,每当调用 .stopService(intent) 时都会调用 onDestroy() 方法,所以我利用这个事实来停止 while 循环。这规避了可靠性问题,因为每个服务都有自己的布尔变量,并且不依赖于静态变量,并且不需要通过 Intent 传递任何其他变量。

再次感谢 Seraphim 抽出宝贵时间帮助我。

于 2013-07-01T08:35:41.217 回答
0

停止服务不是同步操作。如果您对服务终止的检查接近于之前的“服务停止”调用,您可能会发现您的服务仍在运行。

在我的应用程序中,当我需要停止服务时(退出应用程序时),我进入一个循环周期(使用 AsyncTask)并等待服务终止。

我看到你打电话

@Override
public void onDestroy() {
    ConnectionUtility.getInstance().startService(this);
    super.onDestroy();
}

我建议Application Context用于启动和停止您的服务,而不是Activity作为context. 因为当活动即将被销毁时,您正在启动服务!

还有部分

protected void onHandleIntent(Intent intent) {
    // TODO Auto-generated method stub
    while (true) {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("Hello, World!");
    }
}

处理意图时的无限循环?对我来说听起来不太好。

于 2013-07-01T07:29:30.560 回答