当用户销毁应用时,从onPause或onStop呼叫结束

时间:2015-09-30 08:41:22

标签: android

Coclusion:onDestroy() is not always being invoked.

情况如下:

启动应用后,会创建MainActivity,启动后台跟踪服务。另一方面,用户可以使用主活动中的复选框列表来选择他感兴趣的路线,其中复选框列表的项目表示路线。

单击提交按钮后,alarmManager每30秒开始向IntentService类发送数据。随后,建立与服务器的连接,并在用户自动重定向到MapActivity后开始向MapActivity检索数据。

用户可以使用两个活动菜单中的图标来停止和启动后台服务。在下面描述的案例中,我面临着破坏应用程序的问题。

使用当前代码:

  • 启动应用程序后,我可以在mainActivity中停止服务并破坏应用程序。
  • 在我从主活动更改为地图活动后启动应用程序后,我可以停止并启动服务以及通过打开Mapactivity销毁应用程序。
  • 当我按照以下(mainActivity-> mapActivity-> MainAtivity-> 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);
           }
        }

    }

}

1 个答案:

答案 0 :(得分:0)

一个经典的解决方案是在每个活动中增加一个静态计数器" onStart"并且在" onPause"上减少。

当计数器为0时,app真的关闭

唯一困难的部分是如果您的第一个活动有方向更改,因为活动被系统完全销毁并重新创建,您可能会认为应用程序真的已关闭(因为在这种情况下,计数器为0)

对于这个特殊情况我没有神奇的解决方案