以编程方式设置系统时间

Programmatically set System Time

我意识到这个问题出现在 SO 的其他地方,但是我已经尝试了我可以在网站上找到的所有解决方案,但仍然遇到困难。这些问题(及其答案)也有好几年了,与其评论旧问题,我想我应该在这里为其他人整合信息,并调查从那时到现在对 Android 的潜在相关更改。尽管如此,如果您认为此问题符合重复条件,请将其标记为重复。

编辑:正如我所说,关于 SO 的其他答案并没有解决问题。 我看不出如何用 "Doesn't work for me" 评论每一个潜在的修复有利于帮助自己和他人解决问题,但既然如此,那就这样吧。作为参考,3 人已将问题标记为 this question 的潜在重复项,因此我将这些无效答案添加到下面的列表中。

我的应用程序有一些非常具体的需求,但为了简洁起见,我们假设我需要手动将系统时间和日期设置为固定值。下面我详细介绍了一些关于我在尝试使这项工作取得进展的笔记。

该应用的最低 SDK 版本为 24,目标是 24。其他人发现他们需要将版本提高到这个级别。

设备已 root,正在将应用程序安装到 /system/app,以便我可以更改 date/time。

有人评论说,应用程序完全不可能设置时间,但是看看 ClockSync 等应用程序,情况似乎并非如此。我知道我的应用程序将无法在 Play 商店中使用。

应用程序必须在没有用户输入的情况下自动设置 date/time,因此使用以下代码让用户设置它无济于事;

startActivity(new Intent(android.provider.Settings.ACTION_DATE_SETTINGS));

我通过两种方式将设置时间权限添加到清单中,一种是单独添加,另一种是一起添加。我还尝试添加有关删除 maxSDKversion 的部分。

<uses-permission android:name="android.permission.SET_TIME" tools:remove="android:maxSdkVersion" />

<permission android:name="android.permission.SET_TIME"
    android:protectionLevel="signature|system"/>

我读到某些权限不仅需要清单条目,还需要用户接受并允许它们。但是,SET_TIME 不在其中。无论如何我确实尝试过这样做,但是我的许可请求被自动拒绝而没有显示确认框,可能是因为它实际上并没有首先需要许可。

我用来尝试设置时间的代码如下:

try {
        Calendar c = Calendar.getInstance();
        c.set(2017, 11, 21, 12, 32, 30);
        AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        am.setTime(c.getTimeInMillis());
    } catch (Exception e) {
        Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
    }

失败时我在 toast 中收到的错误是:

java.lang.securityexception: setTime: neither user 10051 nor current process has android.permission.SET_TIME

我已经尝试了上述编辑中引用的问题中的两种解决方案,这两种解决方案都涉及 运行 用于设置日期的代码:

Runtime.getRuntime().exec("su && date -s 20171122.153720");}

这两个答案什么都不做——时间没有改变,也没有抛出异常。另一个答案需要互联网访问,这超出了我的问题范围。

考虑到以上所有情况,我在完成这项工作时是否遗漏了任何关键步骤,或者代码中是否有任何表明存在问题的地方?

事实证明,答案 确实 就在所引用的问题 found here 中。但是,对于 Android 7 个(可能还有 6 个,我还没有测试过)设备,命令是不同的。我没有资格在那里发表评论,所以如果有人希望 paste/reference 这个问题的答案,请继续。

我使用的日期代码格式是 MMddhhmmyy,而不是 yyyyMMdd.hhmmss;这适用于 Android 7。我还删除了附加的“-s”。我用来设置系统时间的完整工作代码如下。再次需要注意的是,这需要对设备进行 root,因此仅在像我这样的某些情况下有用。

     try {

        Process process = Runtime.getRuntime().exec("su");
        DataOutputStream os = new DataOutputStream(process.getOutputStream());
        String command = "date 1123104017\n";
        // Log.e("command",command);
        os.writeBytes(command);
        os.flush();
        os.writeBytes("exit\n");
        os.flush();
        process.waitFor();

    } catch (InterruptedException e) {
        Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
    } catch (IOException e) {
        Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
    }

为清楚起见,我输入的日期是 2017 年 11 月 23 日 10:40 上午。

如果您也需要设置第二个,请使用此格式:MMddhhmmyy.ss

如果你有很长的时间价值,使用这个:

SimpleDateFormat dateFormat = new SimpleDateFormat("MMddhhmmyy.ss");
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timeValue);
Date date = calendar.getTime();

Process process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());

String command = "date " + dateFormat.format(date)  + "\n";

os.writeBytes(command);
os.flush();
os.writeBytes("exit\n");
os.flush();
process.waitFor();