【问题标题】:Setting system time of ROOTED phone设置ROOTED手机的系统时间
【发布时间】:2018-08-04 15:44:06
【问题描述】:

我目前正在尝试在软件中设置 Android 系统时间。是的,我知道很多人都尝试过——但像我现在一样失败了。 :-)

但我也知道可以在 ROOTED 手机上设置 Android 系统时间。我测试了一个名为 ClockSync 的应用程序,它确实可以做到这一点。

所以我想要了解如何在 ROOTED 设备上设置系统时间。请不要说不可能。 :-)

到目前为止,我尝试的是设置以下权限:

<uses-permission android:name="android.permission.SET_TIME_ZONE"/>
<uses-permission android:name="android.permission.SET_TIME"/>

然后在我的代码中:

AlarmManager a = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
long current_time_millies = System.currentTimeMillis();
try {
    a.setTime((long)current_time_millies+10000);
} catch (Exception e) {
// Why is this exception thrown?
}

但我总是遇到以下异常:

java.lang.SecurityException: setTime: 用户 10054 和当前进程都没有 android.permission.SET_TIME。

我正在使用 ClockSync 完美运行的同一台设备上对其进行测试。那么 - 我做错了什么?或者更好:你能提供经过测试的有效代码吗?

【问题讨论】:

    标签: android


    【解决方案1】:

    更新:此方法不再适用于最新的 Android 版本。我知道的唯一其他方法是使用date 命令设置时间。请注意,命令格式可能因 Android 版本和安装的第三方工具而异(date 的 BusyBox 版本不支持时区)。

      // Android 6 and later default date format is "MMDDhhmm[[CC]YY][.ss]", that's (2 digits each)
      // month, day, hour (0-23), and minute. Optionally century, year, and second.
    private static final SimpleDateFormat setDateFormat = new SimpleDateFormat("MMddHHmmyyyy.ss", Locale.US);
    
      // Standard Android date format: yyyymmdd.[[[hh]mm]ss]
      // http://stackoverflow.com/questions/5300999/set-the-date-from-a-shell-on-android
    private static final SimpleDateFormat setDateFormat = new SimpleDateFormat("yyyyMMdd.HHmmss", Locale.US);
    
      // BusyBox date format:
      // [[[[[YY]YY]MM]DD]hh]mm[.ss]
      // but recent versions also accept MMDDhhmm[[YY]YY][.ss]
    private static final SimpleDateFormat bbSetDateFormat = new SimpleDateFormat("yyyyMMddHHmm.ss", Locale.US);
    

    首先,我是ClockSync的开发者,我对在Android上设置时间有所了解。

    恐怕Violet Giraffe 提供的答案不正确。问题是普通用户应用程序无法访问 SET_TIME 权限。此权限只能由作为 ROM 的一部分安装或使用与 ROM 本身相同的密钥签名的系统应用程序使用(取决于供应商)。使用这种方法的应用程序之一是NTPc。它使用 AOSP 密钥签名,可以安装在基于 AOSP 的 Android ROM 上,例如 CyanogenMod。请注意,Google 最近已从 Market 禁止 AOSP 密钥,并且作者将永远无法更新他的应用程序。 NTPc 无法安装在大多数手机使用的常规 ROM 上。

    如果您需要详细信息,请务必阅读著名的 issue 4581 的 cmets:Allow user apps to set the system time。请注意,该问题已被 Google 拒绝,并附有以下评论:

    您好,应用程序无法更改时间是设计使然。那里 安全的许多微妙方面可以依赖于当前时间, 如证书到期、许可证管理等。我们不 希望允许第三方应用程序在全球范围内破坏系统 以这种方式。


    如何在 root 设备上设置时间:

    ClockSync 设置时间的作用是更改/dev/alarm 设备的权限。本质上,它在根 shell 中运行 chmod 666 /dev/alarm。一旦此设备对所有用户都有写权限,SystemClock.setCurrentTimeMillis(...) 调用将成功。一些应用程序使用另一种方法,它们在带有适当参数的根 shell 中运行 date 命令,但是它容易出错并且不太准确,因为超级用户 shell 和命令执行可能需要几秒钟。此类应用程序的一个示例是Sytrant

    默认情况下,ClockSync 仅在 /dev/alarm 尚未可写时设置 666 权限。这节省了 CPU/电池,因为 su/Superuser.apk 执行相对昂贵。如果你担心安全问题,有Restore Permission选项,设置时间后报警器权限为664。

    为了更轻松地从应用程序访问 root shell,我使用了自己的帮助程序类:ShellInterface。另一种选择是使用RootTools 库。

    这里是基于ShellInterface类的示例代码:

      public void setTime(long time) {
        if (ShellInterface.isSuAvailable()) {
          ShellInterface.runCommand("chmod 666 /dev/alarm");
          SystemClock.setCurrentTimeMillis(time);
          ShellInterface.runCommand("chmod 664 /dev/alarm");
        }
      }
    

    请随时查看与设置时间相关的其他 Android 问题:


    如果您需要应用程序中的精确时间而不使用 root 和更改系统时间,您可以拥有自己的计时器,例如基于 Joda Time。您可以使用 Apache commons-net 库中的 NTP 客户端从 NTP 服务器获取时间。

    【讨论】:

    • 我已将 /dev/alarm 设置为 666,并正在调用 setCurrentTimeMillis,但它总是返回 false
    • @TimothyP 它可能发生在启用了 KNOX (SELinux) 的最新三星固件上。克服它的唯一方法是使用@Karan 建议的date 命令行调用。 date 命令不支持毫秒,所以我建议您使用基于原子时间的计时器将命令调用与第二次启动对齐。
    • 仅供参考,在新的 Lollipop 权限模型之前,这种方法对我有效。我无法再以这种方式设置日期/时间了。
    • 在棒棒糖和棉花糖上,我不得不切换到对“日期”进行根调用,只有包含的用法不/不支持 -s 选项。所以我切换到“日期 mmddHHmmYYYY.ss”。请注意,使用情况与其他人报告的不同。
    • @TomásRodrigues 是的,它在 5.0 或 6.0 中发生了变化,现在设置时间的唯一方法是使用 date 命令。
    【解决方案2】:

    你可以像这样在root设备上设置系统日期和时间

    public void setDate()
        {
            try {
                Process process = Runtime.getRuntime().exec("su");
            DataOutputStream os = new DataOutputStream(process.getOutputStream());
                os.writeBytes("date -s 20120419.024012; \n");
            } catch (Exception e) {
                Log.d(TAG,"error=="+e.toString());
                e.printStackTrace();
            }
        } 
    

    【讨论】:

    • 这是一个糟糕的选择,因为它会在您每次需要设置时钟时调用 shell,日期命令将需要一些时间来执行,因此精度较低,某些设备上的日期命令也使用不同的格式并且不会工作。
    • 它适用于有根设备。有人可以帮我为系统应用程序制作这个功能吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多