Определить обновление приложения Android и установить логический класс приложения для отображения / скрытия лицензионного соглашения

Я пытаюсь определить, когда мое приложение было обновлено с помощью BroadcastReceiver, и установить логическое значение в моем классе приложений. Это логическое значение будет использоваться вместе с несколькими другими логическими значениями, чтобы определить, показывать ли пользователю диалоговое окно EULA или нет.

Я верю, что у меня все настроено правильно, но EULA все еще появляется, когда не должно. В частности, когда пользователь уже принял лицензионное соглашение в предыдущей версии, лицензионное соглашение не изменилось в версии, которая обновляется до (установленной мной вручную), и приложение обновляется.

Я считаю, что причина этого не в том, что мое приложение не запущено, и поэтому метод isAppUpgrade () не вызывается и не устанавливает правильный логический флаг. Может кто-нибудь подтвердить, что это так, или что-то не так в моем коде?

К вашему сведению - в моей основной деятельности в первую очередь вызывается статический метод EULA.show (Activity, boolean, boolean).

Вот код

Класс приложения

public class MFCApplication extends Application {

    private boolean isUpgrade = false;

    /**
     * Returns a manually set value of whether the EULA has changed in this version of the App
     * @return true/false
     */
    public boolean hasEULAChanged() {
        return false;
    }

    /**
     * Returns whether or not the application has been upgraded.  Set by the UpgradeBroadcastReceiver
     * @return true/false
     */
    public boolean isAppUpgrade() {
        return isUpgrade;
    }

    /**
     * Method called by UpgradeBroadcastReceiver if the App has been upgraded
     */
    public void setAppIsUpgrade() {
        this.isUpgrade = true;
    }
}

BroadcastReceiver

public class UpgradeBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent == null)
            return;
        if (context == null)
            return;

        String action = intent.getAction();
        if (action == null)
            return;

        if (action.equals(Intent.ACTION_PACKAGE_REPLACED)) {
            MFCApplication myApp = ((MFCApplication)((Activity)context).getApplication());

            myApp.setAppIsUpgrade();
        }
    }
}

EULA Class

public class EULA {

    private static final String EULA_ASSET = "EULA";
    private static final String EULA_PREFERENCES = "eula";
    private static Activity mActivity;

    private static PackageInfo getPackageInfo() {
        PackageInfo pi = null;
        try {
            pi = mActivity.getPackageManager().getPackageInfo(mActivity.getPackageName(), PackageManager.GET_ACTIVITIES);
        } catch (PackageManager.NameNotFoundException ex) {
            ex.printStackTrace();
        }
        return pi;
    }

    public static boolean show(Activity activity, boolean hasEULAChanged, boolean isAppUpgrade) {
        mActivity = activity;
        final SharedPreferences preferences = activity.getSharedPreferences(EULA_PREFERENCES, Activity.MODE_PRIVATE);
        final PackageInfo packageInfo = getPackageInfo();
        String eulaPref = preferences.getString(EULA_PREFERENCES, "0");
        boolean eulaVersionAccepted = packageInfo.versionName.equals(eulaPref);
        if (!eulaVersionAccepted && (hasEULAChanged || !isAppUpgrade)) {
            //The EULA should be shown here, but it isn't
            return false;
        }
        return true;
    }
}

Манифест приложения

<receiver android:name=".helpers.UpgradeBroadcastReceiver">
    <intent-filter>
        <action android:name="android.intent.action.PACKAGE_REPLACED" />
        <data android:scheme="package" android:path="com.hookedroid.fishingcompanion" />
    </intent-filter>
</receiver>

5 ответов

Решение

Гораздо проще просто проверить текущую версию приложения.

PackageInfo packageInfo = activity.getPackageManager()
    .getPackageInfo(activity.getPackageName(), 0);
int versionCode = packageInfo.versionCode;

Когда ваше приложение запускается, вы проверяете ваши SharedPreferences для целочисленного значения с кодом версии. Если их нет или они не совпадают, отобразите лицензионное соглашение. После того, как пользователь примет лицензионное соглашение, запишите значение versionCode в SharedPreferences.

versionCode будет соответствовать номеру версии, которую вы храните в манифесте.

Согласно первоначальному подходу, мне удалось определить, обновлено ли приложение с помощью BroadcastReceiver.

public YourUpgradeReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {
        Uri packageName = intent.getData();
        if(packageName.toString().equals("package:" + context.getPackageName()){
            //Application was upgraded
        }
    } 
}

И в вашем Манифесте

 <receiver android:name=".YourUpgradeReceiver">
            <intent-filter>
                <action android:name="android.intent.action.PACKAGE_REPLACED"/>
                <data android:scheme="package"/>
            </intent-filter>
 </receiver>

Определить, обновлено ли приложение

SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
int versionCode = sharedPreferences.getInt("VERSION_CODE", BuildConfig.VERSION_CODE);

if(versionCode != BuildConfig.VERSION_CODE) {
    onAppUpdated();
}

sharedPreferences.edit().putInt("VERSION_CODE", BuildConfig.VERSION_CODE).apply();

Если вы нацеливаетесь на API > 11, тогда решение из ответа @Marian Klühspies может быть упрощено. Регистрация получателя:

<receiver
    android:name=".your.receivers.package.AppUpdateReceiver">
    <intent-filter>
        <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
    </intent-filter>
</receiver>

И сам приемник:

class AppUpdateReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (intent.action == Intent.ACTION_MY_PACKAGE_REPLACED) {
            onAppUpdated()
        }
    }
}

Вот простой способ, который может решить вашу проблему. В своем коде вы легко можете получить приложение versionCode и versionName. При первой установке после регистрации GCM сохраните versionName в sharedPreferences. В своей домашней деятельности вы проверяете isAppUpdated(). если текущее приложение VERSION_NAME не соответствует сохраненному VERSION_NAME, повторно зарегистрируйте идентификатор GCM.

Вот пример кода:

Сохранить VersionName в настройках:

public static void saveVersionNameAndCode(Context context){
        try{
            PackageInfo packageInfo = context.getPackageManager()
                    .getPackageInfo(context.getPackageName(), 0);
            int versionCode = packageInfo.versionCode;
            String versionName=packageInfo.versionName;

            CommonTasks.showLog("Saving APP VersionCode and Version Name");

            // SAVE YOUR DATA

        }catch(Exception e){
        }
    }

Проверьте приложение обновлено:

public static boolean isAppUpdated(Context context){
        boolean result=false;
        try{
            PackageInfo packageInfo = context.getPackageManager()
                    .getPackageInfo(context.getPackageName(), 0);
            int versionCode = packageInfo.versionCode;
            String versionName=packageInfo.versionName;

            String prevVersionName= GET STORED VERSION_NAME;
            if(prevVersionName!=null && !prevVersionName.equals("") &&
                    !prevVersionName.equals(versionName)){
                showLog("App Updated");
                result=true;
            }else{
                showLog("App Not updated");
            }

        }catch(Exception e){
        }
        return result;
    }

здесь, если isAppUpdated () возвращает true, значит, вам нужно перерегистрировать GCM ID.

Не используйте саму версию приложения, так как приложение может быть обновлено без изменения лицензионного соглашения. Предоставьте ресурс, имеющий определенную версию для самого лицензионного соглашения. Может быть строковым ресурсом "eula_version". С каждым изменением в EULA вы обновляете эту строку для обновления вашего приложения. При создании своей деятельности вы проверяете строку в ресурсах по отношению к строке в SharedPreferences. Простой подход состоит только в проверке на ноль или не равно. (Единственный недостаток, который вы могли бы отобразить EULA снова после понижения приложения или деинсталляции / переустановки).

public static boolean show(Activity activity, boolean hasEULAChanged, boolean isAppUpgrade) {
    mActivity = activity;
    final SharedPreferences preferences = activity.getSharedPreferences(EULA_PREFERENCES, Activity.MODE_PRIVATE);
    final PackageInfo packageInfo = getPackageInfo();
    String eulaPref = preferences.getString(EULA_PREFERENCES, "0"); //save on accept EULA Dialog click
    String eulaActive = getString(R.string.eula_version)
    return eulaPref==null || !eulaPref.equals(eulaActive);
}
Другие вопросы по тегам