判断Android应用是否为设备启动后首次运行

转载请注明出处:https://blog.csdn.net/qq_40358211/article/details/80289674

这是我的第一篇技术博客,若有纰漏或不足之处还请多多指正哈~


这几天开发项目时遇到了一个需求——判断应用是否为设备启动后首次运行。在网上搜索一番后,发现了一个获取系统开机时间方法:

//返回开机时间,单位毫秒
long bootTime() { 
    return long bootTime = System.currentTimeMillis() - SystemClock.elapsedRealtime();
}

于是使用这个方法写了一个判断应用是否为设备启动后首次运行的方法

public static void initBootPref() {
    //本次开机时刻,单位毫秒
    long time = System.currentTimeMillis() - SystemClock.elapsedRealtime();
    //取出上次保存的启动时间
    SharedPreferences pref = getSharedPreferences("BootTime", MODE_PRIVATE);
    //获取上次的开机时刻
    long old_time = pref.getLong("boot_time", time);
    //如果两次时间不等则改变两个按钮的键值为未使用,也就是认为手机重启过且应用是启动后第一次运行。
    if (old_time != time) {
        SharedPreferences.Editor editor = getSharedPreferences("Flags", MODE_PRIVATE).edit();
        editor.putBoolean("isPower", false);
        editor.putBoolean("isBalan", false);
        editor.apply();
    }

    //保存本次启动时间
    SharedPreferences.Editor editor = getSharedPreferences("BootTime", MODE_PRIVATE).edit();
    editor.putLong("boot_time", time);
    editor.apply();
}

看到这里可能有会同学发现其中的问题,没错,使用这样的方法会发现即使手机未重启,这里的键值还是被更改,也就是说time与old_time相等了。

要解决这个问题,我们先来看相关函数(API链接):

  1. System.currentTimeMillis()是含设备深度休眠的一个标准的“墙”时钟(时间和日期),表示从纪元(1970年1月1号0时0分0秒)到现在的毫秒数。该墙时钟能够被用户或电话网络(见setCurrentTimeMillis(long))设置,所以该时间可能会向前或向后不可预知地跳越。该时钟应该仅仅被使用在当现实世界对应的日期和时间非常重要的情况下,比如日历或闹钟应用程序。而间隔时间和经历时间的测算应该使用不同的时钟。如果你使用System.currentTimeMillis(),当时间变化时时可以考虑监听ACTION为ACTION_TIME_TICK、ACTION_TIME_CHANGED和ACTION_TIMEZONE_CHANGED的广播。
  2. elapsedRealtime() 和elapsedRealtimeNanos() 返回系统启动到现在的时间,包含设备深度休眠的时间。该时钟被确保单调,即使CPU在省电模式下,该时间也会继续计时。该时钟可以被使用在测量时间间隔时系统可能睡眠的时间段。

注意这里的System.currentTimeMillis(),该墙时钟能够被用户或电话网络(见setCurrentTimeMillis(long))设置,所以该时间可能会向前或向后不可预知地跳越。所以这里出现old_time与time不等的情况很可能是因为网络时间更改了手机时间。所以使用System.currentTimeMillis()获取当前时间需要注意该时间出现跳越的情况。

了解了原因,我们更改下代码

public static void initBootPref() {
    //本次开机时刻,单位毫秒
    long time = System.currentTimeMillis() - SystemClock.elapsedRealtime();
    //取出上次保存的启动时间
    SharedPreferences pref = getSharedPreferences("BootTime", MODE_PRIVATE);
    //获取上次的开机时刻
    long old_time = pref.getLong("boot_time", time);
    //如果两次时间之差大于30秒,则改变两个按钮的键值为未使用。也就是认为手机重启过且应用是启动后第一次运行
    if (Math.abs(time - old_time) > 30000) {
        SharedPreferences.Editor editor = getSharedPreferences("Flags", MODE_PRIVATE).edit();
        editor.putBoolean("isPower", false);
        editor.putBoolean("isBalan", false);
        editor.apply();
    }

    //保存本次启动时间
    SharedPreferences.Editor editor = getSharedPreferences("BootTime", MODE_PRIVATE).edit();
    editor.putLong("boot_time", time);
    editor.apply();
}

这里改变了判断方法为 

Math.abs(time - old_time) > 30000

加入了这容许30秒的误差之后,就不再收到关于显示问题的反馈了。

但这样的解决方案同时也带来了一个问题——若应用两次启动时间之差小于30秒,且手机中间重启过,这个方法会认为手机并没有重启过。不过现在的手机应该还没有这么快的启动速度吧~~

最后,如果有更好的判断Android应用是否为设备启动后首次运行的方法,欢迎留言

展开阅读全文

没有更多推荐了,返回首页