Android 服务在发布结果之前被销毁

Android Service gets destroyed before publishing the result

我有一个 Activity(MainActivity),它启动一个服务 (FirstService),而 FirstService 启动另一个服务 (SsecondService)。场景是 MainActivity 应该等待来自 FirstService 的结果,但这只会在它从 SecondService 收到某些东西时发送结果。 问题是在 MainActivity 得到最终结果之前调用了 FirstService 的 "onDestroy()" 方法并注销了 SecondService。

>> I/FirstService: On create...
>> I/FirstService: Handling intent...
>> I/SecondService: On create...
>> I/SecondService: On handling intent..
>> I/FirstService: OnDestroy receiver...
>> I/SecondService: Handling result ...
>> I/SecondService: Publishing result ...

在我的 Activity:

    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        if (id == R.id.nav_home) {
            // Handle the camera action
        } else if (id == R.id.nav_camera) {

        } else if (id == R.id.nav_pictures) {
            startAction();   
        }
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

    public void startAction {
        Log.i("MainActivity", "Starting FirstService");
        Intent intent = new Intent(this, FirstService.class);
        intent.setAction(FirstService.ACTION_FETCH_PICTURES);
        intent.putExtra(FirstService.EXTRA_ACCOUNT, account);
        this.startService(intent);
    }

    private BroadcastReceiver receiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            Log.i("MainActivity", "Waiting for onReceive");
            Bundle bundle = intent.getExtras();
            if (bundle != null) {
                resultCode = bundle.getInt(FirstService.RESULT);
                switch (resultCode) {
                    case FirstService.RESULT_CODE_OK: [...]
                    }
                    [...]
                    }
                }
            }
        }
    };

    @Override
    protected void onResume() {
        super.onResume();
        Log.i("MainActivity", "on resume");
        registerReceiver(receiver, new IntentFilter(FirstService.NOTIFICATION));
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.i("MainActivity", "Unregister receiver...");
        unregisterReceiver(receiver);
    }

我的第一个服务:

 @Override
    public void onCreate() {
        super.onCreate();
        Log.i("FirstService", "On create...");           
        registerReceiver(secondReceiver, new IntentFilter(SecondService.NOTIFICATION_SECOND));
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.i("SecondService", "Handling intent...");
        if (intent != null) {
            final String action = intent.getAction();
            // .... some more code
            Intent intent = new Intent(this, SecondService.class);
            intent.setAction(SecondService.ACTION_FETCH_VALIDITY);
            intent.putExtra(SecondService.EXTRA_ACCOUNT, accNumber);
            this.startService(intent);
        }
    }

    private void publishResults(int result) {
        Log.i("FirstService", "Publishing result...");
        Intent intent = new Intent(NOTIFICATION);
        intent.putExtra(RESULT, result);
        sendBroadcast(intent);
    }

    public BroadcastReceiver secondReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            Log.i("SecondService", "On receiving result...");
            Bundle bundle = intent.getExtras();
            if (bundle != null) {
                result = bundle.getInt(SecondService.RESULT);
                switch (result) {
                    //[....]
                }
                publishResults(result);
            }
        }
    };


    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("SecondService", "OnDestroy receiver...");
        unregisterReceiver(secondReceiver);
    }

我已经为此苦苦挣扎了几个小时,但找不到解决方案。我做错了什么,我应该怎么做才能让它发挥作用?任何想法都受到欢迎。 干杯!

基本上,您有两个选择:

使用静态 BroadcastReceiver

您可以使用独立的 BroadcastReceiver。它必须在应用程序 Manifest 中注册。每当您的 SecondService 想要发布内容时,它就会像以前一样广播结果。然后接收方可以启动另一个 Service 来处理结果。 另见 documentation

如果您阅读 link,您会发现使用静态 BroadcastReceiver 有一些缺点。那么,为什么不直接跳过接收器并直接从 SecondService 开始一些(第三个?)Service 呢?

这将我们带到第二个选项:

将第一个服务实现为 "normal" 服务

现在,FirstService 正在扩展 IntentService。 如果 FirstService 作为启动的 Service 实现,那么您可以通过从 Service.onStartCommand() 返回 START_STICKY 来确保它在需要时保持活动状态。您将继续使用动态 BroadcastReceiver,甚至直接通过 onStartcommand() 访问 Service。一旦完成,您的 Service 将注销接收器并调用 stopSelf().

IntentService 的优点是它不在 UI 线程上工作。但是一个启动的Service可以使用AsyncTask,所以它也可以避免冻结UI。

你不应该使用 IntentService。如果您查看 IntentService 的文档,服务会在 onHandleIntent 中启动并完成其工作,然后结束。它不等待任何事情。这就是 FirstService 被销毁的原因,因为它已经完成了它的工作。相反,使用 Simple Service 并在处理程序线程中完成您的工作。这样的话你的服务会继续运行。