【问题标题】:StartForeground for IntentServiceIntentService 的 StartForeground
【发布时间】:2012-03-29 17:53:20
【问题描述】:

我有一个IntentService,我想通过持续的通知使其具有粘性。问题是通知出现然后立即消失。该服务继续运行。我应该如何在IntentService 中使用startForeground()

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    super.onStartCommand(intent, flags, startId);
    Notification notification = new Notification(R.drawable.marker, "Notification service is running",
            System.currentTimeMillis());
    Intent notificationIntent = new Intent(this, DashboardActivity.class);
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
        Intent.FLAG_ACTIVITY_SINGLE_TOP);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
    notification.setLatestEventInfo(this, "App",
            "Notification service is running", pendingIntent);
    notification.flags|=Notification.FLAG_NO_CLEAR;
    startForeground(1337, notification);
    return START_STICKY;
}

@Override
protected void onHandleIntent(Intent intent) {

    String id = intent.getStringExtra(ID);
    WebSocketConnectConfig config = new WebSocketConnectConfig();
    try {
        config.setUrl(new URI("ws://" + App.NET_ADDRESS
                + "/App/socket?id="+id));
    } catch (URISyntaxException e) {
        e.printStackTrace();
    }
    ws = SimpleSocketFactory.create(config, this);
    ws.open();
}

谢谢

【问题讨论】:

    标签: android intentservice foreground-service


    【解决方案1】:

    这不应该是IntentService。如所写,您的IntentService 将存活一毫秒左右。一旦onHandleIntent() 返回,服务就会被销毁。这应该是一个常规的Service,您可以在其中创建自己的线程并管理线程和服务的生命周期。

    您的Notification 立即消失的原因是服务将立即消失。

    【讨论】:

    • 投反对票,因为:这可能是一个不正确的答案。摘自 IntentService 文档:“所有请求都在单个工作线程上处理 - 它们可能需要尽可能长的时间(并且不会阻塞应用程序的主循环),但只有一个请求将在一次。”没有说毫秒左右。 developer.android.com/reference/android/app/IntentService.html
    • 正如所写,这个IntentService 将存活一毫秒左右,原因很简单,onHandleIntent() 中的代码只需一毫秒左右即可运行。
    • @GregoryK 其实答案是正确的,因为onHandleIntent 方法不包含任何线程阻塞代码来防止IntentService 破坏。
    • 这个答案不正确,根据文档:This method may take several seconds to complete, so it should only be called from a worker thread.
    【解决方案2】:

    正如documentation for IntentService 所说:

    ...服务根据需要启动,依次使用 工作线程,并在工作结束时自行停止。

    所以,我想问题在于,onHandleIntent() 完成后您的服务无法正常工作。因此,服务会自行停止并且通知被忽略。因此,IntentService 的概念可能不是您任务的最佳案例。


    由于问题的标题是“IntentService 的 StartForeground”,我想澄清一些事情:

    让您的 IntentService 在前台运行非常简单(参见下面的代码),但您确实需要考虑几件事:

    • 如果只需要几秒钟就不要在前台运行服务 - 这可能会困扰您的用户。想象一下,您定期运行短任务 - 这将导致通知出现和消失 - uhhhh*

    • 您可能需要使您的服务能够保持设备唤醒(但这是另一回事,stackoverflow 对此进行了很好的介绍)*

    • 如果您将多个 Intent 排队到您的 IntentService,下面的代码将最终显示/隐藏通知。 (因此对于您的情况可能有更好的解决方案 - 正如@CommonsWare 建议扩展 Service 并自己做所有事情,但是想提一下 - javadoc 中没有任何 IntentService 说它只工作几秒钟 - 只要它工作它必须做点什么。)


    public class ForegroundService extends IntentService {
    
        private static final String TAG = "FrgrndSrv";
    
        public ForegroundService() {
            super(TAG);
        }
    
        @Override
        protected void onHandleIntent(Intent intent) {
    
            Notification.Builder builder = new Notification.Builder(getBaseContext())
                    .setSmallIcon(R.drawable.ic_foreground_service)
                    .setTicker("Your Ticker") // use something from something from R.string
                    .setContentTitle("Your content title") // use something from something from
                    .setContentText("Your content text") // use something from something from
                    .setProgress(0, 0, true); // display indeterminate progress
    
            startForeground(1, builder.build());
            try {
                doIntesiveWork();
            } finally {
                stopForeground(true);
            }
        }
    
        protected void doIntesiveWork() {
            // Below should be your logic that takes lots of time
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    

    【讨论】:

    • 计算机编程的一般规则是:永远不要对其他人代表您获得的资源做出假设。你没有创建IntentService使用的后台线程;因此,您不应该对可以安全使用它的时间做出任何假设。我们在AsyncTask 中遇到了这个问题,Google 更改了execute() 的规则,将您限制在所有任务的单个线程中。如果您想保持一个线程的时间超过一个短暂的时间,请创建您自己的线程。因推荐令人尴尬的编程实践而投反对票。
    • @CommonsWare 我明白你的意思并理解它。这就说得通了。实际上,我有点不同意“正如所写的那样,您的 IntentService 将存活一毫秒左右”的说法。我不想做任何假设,API java 说:“IntentService 是按需处理异步请求(表示为 Intent)的服务的基类。客户端通过 startService(Intent) 调用发送请求;服务根据需要启动,使用工作线程依次处理每个 Intent,并在工作结束时自行停止。”
    猜你喜欢
    • 2019-04-14
    • 1970-01-01
    • 2012-09-22
    • 1970-01-01
    • 1970-01-01
    • 2014-08-23
    • 1970-01-01
    • 2012-02-02
    • 1970-01-01
    相关资源
    最近更新 更多