23

我正在开发一个 android 应用程序,并遇到了确定系统首次启动时间的问题。我的意思是我需要测量从设备首次启动到现在已经过去了多少时间。

我知道侦听 ACTION_BOOT_COMPLETED 并将任何内容保存在 SharedPreferences 中的解决方案,但我需要另一种解决方案,因为这个解决方案在某些情况下不起作用。也许有任何系统属性?

用例(摘自讨论

  1. 我从服务器收到的每个文件的文件名都包含一个时间戳,取自System.currentMillis()
  2. 我比较这些时间戳以确定哪个文件是最新的。
  3. 现在,用户提前几个月更改系统时间。
  4. 在用户更改系统时间后,我仍然能够确定下载的最新文件。
  5. 现在,用户将时间更改回原始设置。
  6. 在比较时间戳时,第 4 步下载的文件总是获胜。

解决这个问题的灵丹妙药是一个时间戳,它计算自首次启动(出厂重置后)以来的秒数。就像SystemClock.elapsedRealtime()但每次启动后都没有重置。不幸的是,到目前为止的答案告诉我们,这个灵丹妙药并不存在。

但是,许多答案显示了如何解决该问题的多种选择。OneWorld123 评论了每个答案,这是否适合他的需求。

4

5 回答 5

13

也许有任何系统属性?

不确定系统属性,但有一个SystemClock类提供 API 来获取系统正常运行时间:

SystemClock.uptimeMillis()哪一个

返回自启动以来的毫秒数,不包括在深度睡眠中花费的时间

您也可以使用SystemClock.elapsedRealtime()which

返回自启动以来的毫秒数,包括在 sleep 中花费的时间

希望这可以帮助。

于 2014-04-25T01:30:47.420 回答
9

如果需要知道第一次启动 Android 设备是什么时候,

最简单的方法是申请

  • 安装在出厂映像中
  • 配置为在引导期间运行
  • sharedPreference在第一次运行时将当前日期和时间记录到 a

随后,任何其他需要确定 Android 设备首次启动时间的应用程序都可以sharedPreference在设备的生命周期内查找适当的。(或直到设备恢复出厂设置;此时预安装的应用程序将在重新启动后将新的日期和时间写入共享首选项。)


但是,如果无法在 Android 设备上预安装应用程序,那么可能的解决方法是:

1. 作为 root/超级用户

可以查找在首次启动期间在 Android 设备上创建的目录/文件的时间戳。

2.作为一个普通的应用程序,

使用标准 Android API 的一种简单解决方法是检查已知在首次启动期间安装的适当系统包的安装时间。

/* This returns the last time a package was installed */
PackageManager pm = context.getPackageManager();
PackageInfo pInfo = pm.getPackageInfo(<app-package-name>, 0);
return pInfo.firstInstallTime;

3. 或者作为常规应用程序,

如果我们可以依赖一个特定的包在第一次启动期间被更新一次(并且永远不会再次),我们可以检查它的更新时间如下:

/* This returns the last time a package was updated */
PackageManager pm = context.getPackageManager();
ApplicationInfo appInfo = pm.getApplicationInfo(<app-package-name>, 0);
String appFile = appInfo.sourceDir;
long installed = new File(appFile).lastModified();
于 2016-01-30T13:59:30.483 回答
1

ANDROID SDK 中有 3 种方法:-

public static long  elapsedRealtime ()

在 API 级别 1 中添加

返回自启动以来的毫秒数,包括睡眠时间。退货

自启动以来经过的毫秒数。

public static long elapsedRealtimeNanos ()

在 API 级别 17 中添加

返回自启动以来的纳秒数,包括睡眠时间。退货

自启动以来经过的纳秒。

对于@oneWorld 案例:

您可以使用两种方法:-

1)在写入时检查某些数据的日期是否高于当前日期,然后将先前数据的日期更改为小于当前数据和时间的日期,因此它将返回正确的最新数据。

2)您可以将时间存储在服务器上并从那里检索时间并进行设置。

于 2016-02-02T05:18:14.577 回答
1

如果我们坚持使用 SDK,我不知道直接提供此信息的方法;但可能有一种方法可以从其他资源中获取这些信息。同样,如果我们坚持使用 SDK,一个“相当可靠”的选项是使用Android 操作系统在设备生命周期内保存的应用程序使用统计信息。那就是 - 保存的第一个“使用统计信息”的时间戳。

但是,这显然没有提供确切的“首次启动时间”时间戳,因此这取决于您的情况是否可以使用某种近似值。一般来说,使用统计的问题在于,Andriod 会在很远的时间段内聚合它——因此,越旧的设备——日期越不准确。例如,对于我目前在 2014 年 12 月 3 日首次启动的手机,汇总的使用统计数据目前首次记录在 2014 年 12 月 21 日(记录在案 - 撰写本文时是 2016 年 2 月)。(我不得不承认,虽然我不知道 Android OS 是如何安排聚合的,以及它是否只是安排在每年的 12 月 21 日,或者它是否确实有点接近第一次设备使用 - 我想这很容易与任何其他设备检查。)

以下是一些示例代码,显示了UsageStatsManager 的使用情况,但它肯定需要更多的调整才能解决最近时期具有更高精确度的事实:

UsageStatsManager usageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
Calendar year2013 = Calendar.getInstance(); year2013.set(2013, 0, 1);
List<UsageStats> stats = usageStatsManager.queryUsageStats(
    UsageStatsManager.INTERVAL_YEARLY, // or adjust for "younger" devices to get more precision - so, you'll probably need several queries
    year2013.getTimeMillis(),
    Calendar.getInstance().getTimeInMillis());
// now, first element in stats (if it is present at all) will point to the "earliest" statistics saved *for this interval* (yearly in this case)
// use UsageStats.getFirstTimeStamp() to get first known/saved usage

另请注意,如 SDK 中所述,UsageStatsManager需要PACKAGE_USAGE_STATS系统级权限,因此您需要先让用户在设置中接受它:

Intent settingsIntent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
startActivity(settingsIntent);

希望能帮助到你!

于 2016-02-02T23:17:08.077 回答
1

根据您对https://chat.stackoverflow.com/rooms/102325/discussion-between-ankitagrawal-and-oneworld的讨论,您需要一个单调计数器来唯一标识数据集。

为此,您可以轻松设置 SharedPreference 并在每次需要新标识符时增加此值。当您需要知道哪个是最新文件时,只需比较标识符即可。如果卸载应用后此计数器被重置是一个问题,请参阅:In android is there any way to preserve SharedPreferences after an uninstall

可以使用的另一种方法是从外部服务器请求时间戳。

希望能帮助到你 ;-)

于 2016-02-03T00:16:17.167 回答