如何在更新Andoid应用程序时更新在单独进程中运行的服务?

时间:2017-08-14 12:35:32

标签: java android service

当我将应用更新到新版本时,与之前的应用版本一起安装的服务仍在运行。当我第二次更新应用程序时,更新的服务正在正常运行。

但是,在第一次更新后,每当我关闭应用程序或重新启动手机时,都会运行先前版本的服务。

如何在应用更新后立即强制新服务运行。

这是我的代码

的AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.djuro.updateservicewithappupdate">

    <application
        android:name=".App"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>


        <service
            android:name=".MyService"
            android:process=":myService" />

        <receiver android:name=".PackageReplacedReceiver">
            <intent-filter>
                <action android:name="android.intent.action.PACKAGE_REMOVED" />
                <data android:scheme="package" android:path="com.djuro.updateservicewithappupdate"/>
            </intent-filter>
        </receiver>
    </application>

</manifest>

App.java

public class App extends Application {
    private static final String TAG = App.class.getName();

    private static App mInstance;

    private Messenger myServiceMessenger;
    private boolean isBound;

    private Messenger replyMessenger = new Messenger(new IncomingHandler());



    @Override
    public void onCreate() {
        super.onCreate();

        if (mInstance == null) {
            mInstance = this;
            startMyService();
        }

        isBound = false;

        // start the chore service (if it is not running) and bind to it

    }


    public void startMyService() {
        startService(new Intent(mInstance, MyService.class));
        doBindService();
    }

    public void stopMyService() {
        doUnBindService(true);
        stopService(new Intent(mInstance, MyService.class));
    }



    public static App getInstance() {
        return mInstance;
    }

    public static Context getContext() {
        return mInstance.getApplicationContext();
    }

    public static Messenger getChoreMessenger() {return mInstance.myServiceMessenger;}


    @Override
    public void onTerminate() {
        doUnBindService(false);
        super.onTerminate();
    }

    private void doBindService() {
        if (!isBound) {
            Log.d(TAG, "Binding ChoreService.");
            bindService(new Intent(this, MyService.class), myServiceConnection, Context.BIND_AUTO_CREATE);
            isBound = true;
        }
    }


    private void doUnBindService(boolean restartService) {
        if (isBound) {
            Log.d(TAG, "Unbinding ChoreService.");
            if (myServiceMessenger != null) {
                try {
                    Message msg = Message.obtain(null, MyService.UNREGISTER_CLIENT);
                    msg.replyTo = replyMessenger;
                    replyMessenger.send(msg);
                }
                catch (RemoteException e) {
                    // There is nothing special we need to do if the service has crashed.
                }
            }
            if (restartService) {
                try {
                    Message msg = Message.obtain(null, MyService.STOP_SERVICE_ON_UNBIND);
                    msg.replyTo = replyMessenger;
                    replyMessenger.send(msg);
                }
                catch (RemoteException e) {
                    // There is nothing special we need to do if the service has crashed.
                }
            }
            unbindService(myServiceConnection);
            isBound = false;
        } else if (restartService) {
            stopService(new Intent(mInstance, MyService.class));
        }
    }




    private ServiceConnection myServiceConnection = new ServiceConnection() {

        public void onServiceConnected(ComponentName className, IBinder service) {
            myServiceMessenger = new Messenger(service);
            Log.d(TAG, "connected to service");
            try {
                Message msg = Message.obtain(null, MyService.REGISTER_CLIENT);
                msg.replyTo = replyMessenger;
                myServiceMessenger.send(msg);
            }
            catch (RemoteException e) {
                // In this case the service has crashed before we could even do anything with it
            }
        }

        public void onServiceDisconnected(ComponentName className) {
            myServiceMessenger = null;
            Log.d(TAG, "disconnected from ChoreService");
        }
    };

    class IncomingHandler extends Handler {

        @Override
        public void handleMessage(Message msg) {
        }
    }
}

MyService.java

public class MyService extends Service {

    private static final String TAG = MyService.class.getName();

    public static final int UNREGISTER_CLIENT = 1;
    public static final int REGISTER_CLIENT = 2;
    public static final int STOP_SERVICE_ON_UNBIND = 3;

    final Messenger messenger = new Messenger(new IncomingHandler());

    private String appVersion;
    private boolean stopOnUnbind;
    private int boundCount = 0;


    // called when the intent starts the Service
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //return super.onStartCommand(intent, flags, startId);
        Log.d(TAG, "onStartCommand()");
        getVersion();
        return START_STICKY;
    }


    // called once at creation (before onStartCommand)
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate");
    }

    // used to bind intent to service
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        //doStopForeground();
        boundCount ++;
        Log.d(TAG, "bound count: " + boundCount);
        return messenger.getBinder();
    }


    @Override
    public boolean onUnbind(Intent intent) {
        boundCount --;
        Log.d(TAG, "bound count: " + boundCount);
        boolean result = super.onUnbind(intent);
        if (stopOnUnbind) {
            Log.d(TAG, "stopSelf()");
            stopSelf();
        }
        return result;
    }

    // called when the service is destroyed
    @Override
    public void onDestroy() {
        Log.d(TAG, "onDestroy()");
        super.onDestroy();
    }



    public void getVersion() {
        try {
            PackageInfo pInfo = this.getPackageManager().getPackageInfo(getPackageName(), 0);
            appVersion = pInfo.versionName;
            Log.d(TAG, "appVersion: " + appVersion);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
    }


    private class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            Log.d(TAG, "IncomingHandler handling message. msg.what= " + msg.what);
            switch (msg.what) {
                case STOP_SERVICE_ON_UNBIND:
                    stopOnUnbind = true;
                    break;
                default:
                    super.handleMessage(msg);
                    break;
            }
        }
    }
}

PackageReplacedReceiver.java

public class PackageReplacedReceiver extends BroadcastReceiver {

    private static final String TAG = PackageReplacedReceiver.class.getName();

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "package updated");
        App.getInstance().stopMyService();
    }

}

1 个答案:

答案 0 :(得分:0)

在意图文件管理器中使用android.intent.action.MY_PACKAGE_REPLACED操作,并从广播接收器停止服务。

<receiver android:name=".PackageReplacedReceiver" android:enabled="@bool/is_at_least_api_12" > <intent-filter> 
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
 </intent-filter> 
</receiver>