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
并在处理程序线程中完成您的工作。这样的话你的服务会继续运行。
我有一个 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
并在处理程序线程中完成您的工作。这样的话你的服务会继续运行。