简体   繁体   English

用户销毁应用程序时从onPause或onStop调用完成

[英]Call finish from onPause or onStop when the user destroys the app

Coclusion: onDestroy() is not always being invoked. 结论: onDestroy() is not always being invoked.

Here is the case: 就是这种情况:

After Launching the app, the MainActivity is created which starts background tracking service. 启动应用程序后,将创建MainActivity ,它将启动后台跟踪服务。 On the other hand, the user can use a checkbox list in the main activity to select his interested routes where the items of the checkbox list represents the routes. 另一方面,用户可以在主要活动中使用复选框列表来选择他感兴趣的路线,其中复选框列表中的各项代表路线。

After clicking the submit button, the alarmManager starts firing the data to the IntentService class every 30 seconds. 单击提交按钮后,alarmManager开始每30秒将数据触发到IntentService类。 Subsequently, connection with the server is established and retrieving data to the MapActivity is started after the user was redirected automatically to the MapActivity . 随后,在自动将用户重定向到MapActivity之后,建立与服务器的连接并开始向MapActivity检索数据。

The user is able to stop and start the background service by using an icon in the menu of the both activities. 用户可以使用两个活动菜单中的图标来停止和启动后台服务。 I am facing problem to destroy the app in the case describes below. 在下面所述的情况下,我面临销毁应用程序的问题。

With the current code: 使用当前代码:

  • After launching the app I can stop the service in the mainActivity and destory the app. 启动应用程序后,我可以在mainActivity中停止该服务,并销毁该应用程序。
  • after launching the app when I change from the main activity to the map activity , I can stop and start the service as well as destroy the app with opening Mapactivity. 从主活动更改为地图活动后启动应用程序后,我可以停止并启动该服务以及通过打开Mapactivity销毁该应用程序。
  • When I go as the following (mainActivity->mapActivity->MainAtivity->MapActivity) and closed the app with opening map view the app is not being destroyed and the service is not being stoped. 当我按照以下说明进行操作(mainActivity-> mapActivity-> MainAtivity-> MapActivity)并通过打开地图视图关闭该应用程序时,该应用程序未被破坏,该服务也未停止。 Also the onDestroy() in MapActivity is not being invoked. 同样,MapActivity中的onDestroy()也不会被调用。 Here the app opens gain with the map view. 在这里,应用程序通过地图视图打开增益。

But when I do the following: adding startService(i)(as the code snippet four lines below) to the onStart() in the MapActivity after bindService I can destroy the app as well stoping and starting the service but the problem here is I dont want to start the service every time I am going from the MainActivity to the MapActivity since if the user stops the service in the MainActivity it must stay off when he goes from the main to the map. 但是,当我执行以下操作时: bindService之后,在MapActivity bindService startService(i)(作为下面的四行代码段)添加到onStart()中,我可以销毁该应用程序以及停止和启动该服务,但是这里的问题是我没有我想每次从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);
}

I know that there's no guarantee of when onDestroy() will be called in an Activity and maybe I should call finish() inside onPause() or onStop() but my question is how to know when to call finish() inside onPause() or onStop() since the tracking service should run in the background until the app is being destroyed by the user or the user decides to stop it with the icon in the menu. 我知道无法保证何时在活动中调用onDestroy(),也许我应该在onPause()或onStop()内调用finish() (),但我的问题是如何知道何时在onPause()内调用finish()或onStop(),因为跟踪服务应在后台运行,直到该应用被用户破坏或用户决定使用菜单中的图标将其停止为止。 I dont want to stop the tracking service when the user goes in the background or everytime onPause() is being called (In my case onPause() in the MapActivity is being called several time in one minute). 我不想在用户进入后台或每次调用onPause()时停止跟踪服务(以我为例,在一分钟内多次调用MapActivity中的onPause())。

How can I call finish() from onPause() or onStop() only when the user destroys the app? 仅当用户销毁应用程序时,如何才能从onPause()onStop()调用finish() How to manage it in this case? 在这种情况下如何管理?

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 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 class: 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);
           }
        }

    }

}

a classic solution is to have a static counter that is increased at each activity "onStart" and decreased on "onPause". 一个经典的解决方案是拥有一个静态计数器,该计数器在每个活动“ onStart”上增加,而在“ onPause”上减少。

when counter is at 0, app is really closed 当计数器为0时,应用程序实际上已关闭

the only hard part is if you have orientation change on your first activity, as activity is completely destroyed and recreated by system, you may think that app is really closed (as counter is at 0 in this situation) 唯一困难的部分是,如果您对第一个活动的方向有所更改,因为活动已完全被系统破坏并重新创建,您可能会认为该应用程序确实已关闭(在这种情况下,计数器为0)

i have no magic solution for this particular case 对于这种特殊情况,我没有神奇的解决方案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM