检测新安装或更新版本(Android应用程序)

时间:2014-10-14 04:54:47

标签: android

我在Play商店有一款应用。我想要求如果用户想要使用应用程序的某个部分,他们必须先邀请朋友才能这样做。但我只想对应用程序的新安装施加此限制(对于在限制之前安装了应用程序的用户公平)。 很抱歉这个长篇介绍,我的问题是如何确定当前设备是否已更新应用程序或是否是新安装?

9 个答案:

答案 0 :(得分:74)

public static boolean isFirstInstall() {
    try {
        long firstInstallTime =   App.getContext().getPackageManager().getPackageInfo(getPackageName(), 0).firstInstallTime;
        long lastUpdateTime = App.getContext().getPackageManager().getPackageInfo(getPackageName(), 0).lastUpdateTime;
        return firstInstallTime == lastUpdateTime;
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
        return true;
    }
}



public static boolean isInstallFromUpdate() {
    try {
        long firstInstallTime =   App.getContext().getPackageManager().getPackageInfo(getPackageName(), 0).firstInstallTime;
        long lastUpdateTime = App.getContext().getPackageManager().getPackageInfo(getPackageName(), 0).lastUpdateTime;
        return firstInstallTime != lastUpdateTime;
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
        return false;
    }
}

答案 1 :(得分:19)

我能看到的唯一不涉及设备外部实体的解决方案是获取应用的PackageInfo并检查

的值

首次安装时,firstInstallTimelastUpdateTime将具有相同的值(至少在我的设备上它们是相同的);更新后,值将不同,因为lastUpdateTime将更改。此外,您大致知道创建引入此新行为的版本的日期和时间,并且您还知道它将具有哪个版本代码。

我会扩展Application并在onCreate()中实施此检查,并将结果存储在SharedPreferences中:

public class MyApplication extends Application {

    // take the date and convert it to a timestamp. this is just an example.
    private static final long MIN_FIRST_INSTALL_TIME = 1413267061000L;
    // shared preferences key
    private static final String PREF_SHARE_REQUIRED = "pref_share_required";

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

    private void checkAndSaveInstallInfo() {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        if (prefs.contains(PREF_SHARE_REQUIRED)) {
            // already have this info, so do nothing
            return;
        }

        PackageInfo info = null;
        try {
            info = getPackageManager().getPackageInfo(getPackageName(), 0);
        } catch (NameNotFoundException e) {
            // bad times
            Log.e("MyApplication", "couldn't get package info!");
        }

        if (packageInfo == null) {
            // can't do anything
            return;
        }

        boolean shareRequired = true;
        if (MIN_FIRST_INSTALL_TIME > info.firstInstallTime
                && info.firstInstallTime != info.lastUpdateTime) {
            /*
             * install occurred before a version with this behavior was released
             * and there was an update, so assume it's a legacy user
             */
            shareRequired = false;
        }
        prefs.edit().putBoolean(PREF_SHARE_REQUIRED, shareRequired).apply();
    }
}

这不是万无一失的,如果用户真的想要,有办法绕过这个,但我认为这和它一样好。如果您想更好地跟踪这些内容并避免被用户篡改,您应该开始在服务器上存储用户信息(假设您有任何类型的后端)。

答案 2 :(得分:6)

检查旧版本的应用是否在磁盘或首选项上保存了一些数据。这些数据必须是安全的,即用户不能删除(我不确定是否可能)。

新安装新版本时,此数据将不存在。如果新版本是旧版本的升级版本,则此数据将存在。

最糟糕的情况是,旧用户将被标记为新用户并且使用受限。

答案 3 :(得分:3)

更新

(感谢下面的评论,我的答案是为了更具体/完整的回复)。

由于您无法追溯更改应用程序以前版本的代码,因此我认为最简单的方法是允许所有 当前 安装完成英寸

因此,要记住这一点,一种方法是找到指向特定应用版本的信息。从应用的最后一个版本开始,您要允许用户不受此限制,这是一个带时间戳的文件,或SharedPreferences,甚至是versionCode(由@DaudArfin在他的回答中建议)。然后你需要改变它。然后,该更改将成为所有先前安装的参考点。对于这些用户,将其"has_shared"标记标记为true。他们成为 grandfathered 。然后,继续,您可以将"has_shared"默认设置为true

(原文,部分答案如下)

使用 SharedPrefence (或类似)

使用SharedPreferences之类的内容。 通过这种方式,您可以将has_shared = trueSharedPreferences这样的简单值保留在应用更新中。

当他们签署某人/分享您的应用时,会发生类似这样的事情

SharedPreferences prefs = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("has_shared", true)
editor.commit();

然后你只能在pref返回true

时给人们发错
SharedPreferences prefs = getActivity().getPreferences(Context.MODE_PRIVATE);
boolean defaultValue = false;
boolean hasShared= prefs.gettBoolean("has_shared", defaultValue);
if (!hasShared) {
    askUserToShare();
}

SharedPreference的文档:
http://developer.android.com/training/basics/data-storage/shared-preferences.html

答案 4 :(得分:2)

我的解决方案是使用SahredPreference

private int getFirstTimeRun() {
    SharedPreferences sp = getSharedPreferences("MYAPP", 0);
    int result, currentVersionCode = BuildConfig.VERSION_CODE;
    int lastVersionCode = sp.getInt("FIRSTTIMERUN", -1);
    if (lastVersionCode == -1) result = 0; else
        result = (lastVersionCode == currentVersionCode) ? 1 : 2;
    sp.edit().putInt("FIRSTTIMERUN", currentVersionCode).apply();
    return result;
}

返回3个posibles值:

  • 0:APP是首次安装
  • 1:APP运行一次
  • 2:APP已更新

答案 5 :(得分:0)

您可以使用以下代码段

获取版本代码和版本名称
String versionName = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;

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

现在您可以检查最新版本并根据您的要求进行限制。

答案 6 :(得分:0)

我们可以使用广播接收器收听应用程序更新。

接收器

class AppUpgradeReceiver : BroadcastReceiver() {

  @SuppressLint("UnsafeProtectedBroadcastReceiver")
  override fun onReceive(context: Context?, intent: Intent?) {
    if (context == null) {
        return
    }
    Toast.makeText(context, "Updated to version #${BuildConfig.VERSION_CODE}!", Toast.LENGTH_LONG).show()
  }

}

清单

<receiver android:name=".AppUpgradeReceiver">
<intent-filter>
    <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>

在调试时不起作用。因此,您必须手动安装。

  1. 在应用程序级别的build.gradle中增加versionCode(因此将其视为更新)。
  2. 单击“构建”->“构建捆绑包” /“ APK”->“构建APK”,然后选择一个调试APK。
  3. 在Android Studio底部的“终端”标签中输入以下命令:

    adb install -r C:\Repositories\updatelistener\app\build\outputs\apk\debug\app-debug.apk
    

答案 7 :(得分:0)

如果您每次更新只执行一次操作,请遵循以下代码片段

private void performOperationIfInstallFromUpdate(){ 
try {
        SharedPreferences prefs = getActivity().getPreferences(Context.MODE_PRIVATE);
        String versionName = prefs.getString(versionName, "1.0");
        String currVersionName = getApplicationContext().getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
        if(!versionName.equals(currVersionName)){
            //Perform Operation which want execute only once per update
            //Modify pref 
            SharedPreferences.Editor editor = prefs.edit();
            editor.putString(versionName, currVersionName);
            editor.commit();
        }
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
        return BASE_VERSION;
    }

}

答案 8 :(得分:0)

简洁的 Kotlin 解决方案,基于仍然出色的 wudizhuo 答案:

 val isFreshInstall = with(packageManager.getPackageInfo(packageName, 0)) {
     firstInstallTime == lastUpdateTime
 }

这可以直接从 Activity 中调用,因为 Activity 是一个上下文(因此可以访问 packageManager 等)

如果你想在多个地方/上下文中使用它,它可以很容易地变成一个扩展属性:

val Context.isFreshInstall get() = with(packageManager.getPackageInfo(packageName, 0)) {
    firstInstallTime == lastUpdateTime
}

这样,您可以简单地在任何 Activity 中编写 if (isFreshInstall),或在任何 Fragment 中编写 if (requireContext().isFreshInstall)