当使用START_STICKY启动服务时,服务进程被杀死后的onStartCommand方法。

15

我一直在阅读Android文档,想知道使用START_STICKY启动的服务实例在其进程被杀死时会发生什么。我假设本地状态数据(实例变量)也会丢失。当Android重新创建服务时,它是否会对重新填充本地状态数据有所帮助?

我有一些数据通过intent发送到服务中。在onStateCommand()中,我将根据intent中的内容填充服务实例数据。从我在Android文档中读到的内容来看,当服务被杀死并重新启动(使用START_STICKY)时,传递给onStartCommand()的intent参数将为null。这是否意味着在服务重新创建时,我会失去intent和服务成员数据?

4个回答

17

当一个进程被杀死并重新创建时,它会再次经历整个生命周期(从onCreate开始)。这取决于它是如何被杀死以及你如何保存数据,它可能会或者不会对你可用。

至于获取意图,有一个标志可以使用START_REDELIVER_INTENT,它将重新传送Intent。


谢谢您确认我的怀疑。我不知道START_REDLIVER_INTENT(可能是文档的那一部分被忽略了)。 - adstro
谢谢,伙计。这个 bug 让我几乎一个月都被困扰了... 最终发现是 Android 操作系统杀死了服务... - macio.Jun
不错。我从来不知道START_REDELIVER_INTENT,这对@Falmarri确实很有用。 - Phil
如果 START_REDELIVER_INTENT 传递了旧意图,那么如果我们创建一个处理程序在10分钟后停止服务呢?那个处理程序将不会执行吗? - Mohd Qasim

2

我最近遇到了同样的问题。服务没有内置的保存状态的方法,而且最后一个意图可能不足以使服务恢复到其先前的状态。我的解决方案是让活动保持状态,并通过startService()将该状态传递给服务。然后,服务只需向活动发送事件,例如:

  • 这里有一个更新
  • 某些东西挂了,这是异常
  • 我已经被杀死,请使用任何必要的状态重新启动我

这种方法大大简化了我的设计,服务和活动都能够抵御被杀死的情况。


2
你能分享一些相应的代码吗?这个概念看起来很理想,但是我无法实现它。 - rolling.stones

1
使用内部存储单独保存对象或其字段。
public void writeToInternalStorage(String fileName,String userName)
    {
        try{
            String endOfLine = System.getProperty("line.separator");
            StringBuffer buffer = new StringBuffer();

            FileOutputStream fos = openFileOutput(fileName, Context.MODE_PRIVATE); //// MODE_PRIVATE will create the file (or replace a file of the same name) and make it private to your application. Other modes available are: MODE_APPEND, MODE_WORLD_READABLE, and MODE_WORLD_WRITEABLE.

            buffer.append(userName.toString() + endOfLine);
            fos.write(buffer.toString().getBytes());


            Log.v(TAG, "writeFileToInternalStorage complete..  " + buffer.toString());
            //      writer.write(userName);

            fos.close();
        }
        catch(Exception e)
        {
            Log.v(TAG, "Error: " + e.getMessage());
            ExceptionNotificationMessage("writeToInternalStorage() Error: " + e.getMessage());
        }
    }

    public String readFromInternalStorage(String fileName)
    {
        try{
            File file = this.getFileStreamPath(fileName);
            if(file.exists() == true)
            {
                Log.v(TAG, "readFileFromInternalStorage File found...");    

                FileInputStream fis = openFileInput(fileName);  
                StringBuilder buffer = new StringBuilder();             
                int ch;
                while( (ch = fis.read()) != -1){
                    buffer.append((char)ch);
                }

                Log.v(TAG, "readFileFromInternalStorage complete.. " + buffer.toString());
                fis.close();

                return buffer.toString();
            }
        }
        catch(Exception e)
        {
            Log.v(TAG, "Error: " + e.getMessage());
            ExceptionNotificationMessage("readFromInternalStorage() Error: " + e.getMessage());
        }
        return "";
    }

1
Android在重新启动服务时不会再次填充“丢失”的数据值,因此您的代码需要考虑这种情况。
我的方法是使用所有非原始状态变量并将它们留空。这样我就可以测试null并在适当时初始化它们。
我已经开始将我想要在应用程序重新启动时保持的轻量级数据存储在应用程序的首选项中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接