Coclusion:onDestroy() is not always being invoked.
情况如下:
启动应用后,会创建MainActivity
,启动后台跟踪服务。另一方面,用户可以使用主活动中的复选框列表来选择他感兴趣的路线,其中复选框列表的项目表示路线。
单击提交按钮后,alarmManager每30秒开始向IntentService
类发送数据。随后,建立与服务器的连接,并在用户自动重定向到MapActivity
后开始向MapActivity
检索数据。
用户可以使用两个活动菜单中的图标来停止和启动后台服务。在下面描述的案例中,我面临着破坏应用程序的问题。
使用当前代码:
onDestroy()
。这里的应用程序使用地图视图打开增益。但是当我做以下事情时:
在onStart()
之后将startService(i)(作为下面的四行代码片段)添加到MapActivity中的bindService
我可以销毁应用程序以及停止和启动服务但这里的问题是我不想要的每次从MainActivity转到MapActivity时启动服务,因为如果用户在MainActivity中停止服务,它必须在从主要地图到地图时保持关闭状态。
@Override
protected void onStart() {
super.onStart();
// Bind to TrackingService.
Intent intent = new Intent(this, TrackingService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
Intent i = new Intent(this, TrackingService.class);
startService(i);
}
我知道在活动中调用onDestroy()时不能保证,也许我应该在onPause()或onStop()中调用finish()
但我的问题是如何知道何时在onPause()或onStop()中调用finish(),因为跟踪服务应该在后台运行,直到用户销毁应用程序或用户决定使用菜单中的图标停止它。我不希望在用户进入后台或每次调用onPause()
时停止跟踪服务(在我的情况下,MapActivity中的onPause()在一分钟内被调用几次)。
仅当用户销毁应用时,如何才能从finish()
或onPause()
拨打onStop()
?在这种情况下如何管理?
MainActivity:
public class MainActivity extends ActionBarActivity implements
AsyncTaskCallback {
boolean serviceStatus = true;
TrackingService mService;
boolean mBound = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.route_available);
// Start the TrackingService class.
Intent i = new Intent(this, TrackingService.class);
startService(i);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
System.out.println("ABC MainActivity onOptionsItemSelected was invoked.");
switch (item.getItemId()) {
case R.id.menu_toggle:
if (serviceStatus) {
item.setIcon(R.drawable.off);
item.setTitle("OFF");
serviceStatus = false;
mService.stopTrackingService();
} else {
item.setIcon(R.drawable.on);
item.setTitle("ON");
serviceStatus = true;
Intent i = new Intent(this, TrackingService.class);
startService(i);
System.out.println("ABC MainActivity onOptionsitemSelected ON");
}
return super.onOptionsItemSelected(item);
}
}
@Override
protected void onStart() {
super.onStart();
// Bind to TrackingService.
Intent intent = new Intent(this, TrackingService.class);
//To start the onPrepareOptionsMenue() after returning from the map activity to change the icon of the toggle button.
invalidateOptionsMenu();
}
@Override
protected void onStop() {
super.onStop();
//13.08.15
// Unbind from the service
if (mBound) {
unbindService(mConnection);
System.out.println("ABC MainActivity onStop() - unbindService(mConnection) was invoked. " + mBound);
mBound = false;
}else{
System.out.println("ABC MainActivity onStop() - unbindService(mConnection) was invoked. " + mBound);
}
}
@Override
protected void onDestroy() {
Intent i = new Intent(this, TrackingService.class);
stopService(i);
mService.stopTrackingService();
}
private ServiceConnection mConnection = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
mBound = false;
}
};
}
MapActivity
public class MapActivity extends ActionBarActivity implements OnMapReadyCallback,
ConnectionCallbacks, OnConnectionFailedListener {
boolean serviceStatus;
TrackingService mService;
boolean mBound = false;
@Override
protected void onStart() {
super.onStart();
serviceStatus = getIntent().getExtras().getBoolean("ServiceStatusExtras");
if (serviceStatus) {
Intent i = new Intent(this, TrackingService.class);
bindService(i, mConnection, Context.BIND_AUTO_CREATE);
startService(i);
System.out.println("ABC MapActivity onStart serviceStatus = " + serviceStatus);
}
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
//System.out.println("ABC Map onServiceConnected() - " + mBound);
}
@Override
public void onServiceDisconnected(ComponentName name) {
mBound = false;
//System.out.println("ABC Map onServiceDisconnected() - mBound");
}
};
@Override
protected void onStop() {
super.onStop();
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
markerMap.clear();
stopAlarm();
if(!serviceStatus){
Intent i = new Intent(this, TrackingService.class);
stopService(i);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_toggle:
if (serviceStatus) {
item.setIcon(R.drawable.off);
item.setTitle("OFF");
serviceStatus = false;
if(mService!=null){
mService.stopTrackingService();
}
} else {
item.setIcon(R.drawable.on);
item.setTitle("ON");
serviceStatus = true;
Intent i = new Intent(this, TrackingService.class);
startService(i);
}
}
return super.onOptionsItemSelected(item);
}
}
TrackingService类:
public class TrackingService extends Service implements AsyncTaskCallback,
LocationListener {
LocationManager lm;
private final IBinder mBinder = new LocalBinder();
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
detectLocation();
return START_NOT_STICKY;
}
private void detectLocation() {
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 12 * 1000, 0,
this);
}
public class LocalBinder extends Binder {
TrackingService getService() {
return TrackingService.this;
}
}
public void stopTrackingService(){
if(lm != null){
lm.removeUpdates(this);
}
}
}
}
答案 0 :(得分:0)
一个经典的解决方案是在每个活动中增加一个静态计数器" onStart"并且在" onPause"上减少。
当计数器为0时,app真的关闭
唯一困难的部分是如果您的第一个活动有方向更改,因为活动被系统完全销毁并重新创建,您可能会认为应用程序真的已关闭(因为在这种情况下,计数器为0)
对于这个特殊情况我没有神奇的解决方案