我在Play商店有一款应用。我想要求如果用户想要使用应用程序的某个部分,他们必须先邀请朋友才能这样做。但我只想对应用程序的新安装施加此限制(对于在限制之前安装了应用程序的用户公平)。 很抱歉这个长篇介绍,我的问题是如何确定当前设备是否已更新应用程序或是否是新安装?
答案 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
并检查
首次安装时,firstInstallTime
和lastUpdateTime
将具有相同的值(至少在我的设备上它们是相同的);更新后,值将不同,因为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
(原文,部分答案如下)
使用SharedPreferences
之类的内容。
通过这种方式,您可以将has_shared = true
和SharedPreferences
这样的简单值保留在应用更新中。
当他们签署某人/分享您的应用时,会发生类似这样的事情
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值:
答案 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>
在调试时不起作用。因此,您必须手动安装。
在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)
。