如何在安卓手机上设置系统时间和日期?

47
当您想要在应用程序中更改移动系统的日期或时间时,该怎么做?
6个回答

70

你无法在普通的现成手机上进行此操作,因为无法获得SET_TIME权限。该权限的保护级别signatureOrSystem,因此市场应用程序无法更改全局系统时间(但也许可以使用我还不知道的黑魔法)。

您不能使用其他方法,因为这在Linux层面上受到阻止(请参见下面的详细答案),这就是为什么所有使用终端和SysExec的尝试都会失败。

如果您能够获得该权限,可能是因为您已经root了手机或构建并签署了自己的平台映像,请继续阅读。

简短回答

这是可能的,并已经实现过。您需要获得android.permission.SET_TIME权限。之后通过Context.getSystemService(Context.ALARM_SERVICE)和它的方法setTime()使用AlarmManager

从Activity或Service设置时间为2010/1/1 12:00:00的代码片段:

Calendar c = Calendar.getInstance();
c.set(2010, 1, 1, 12, 00, 00);
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
am.setTime(c.getTimeInMillis());

如果你想更改时区,方法应该非常相似(请参见android.permission.SET_TIME_ZONEsetTimeZone)。

长回答

正如在几个主题中指出的那样,只有system用户可以更改系统时间。这只是故事的一半。 SystemClock.setCurrentTimeMillis() 直接写入由 system 拥有且缺少全局可写权限的设备文件 /dev/alarm。因此,换句话说,只有以system身份运行的进程才能使用SystemClock方法。对于这种方式,Android权限并不重要,不存在检查适当权限的实体。

这就是内部预安装的设置应用程序的工作方式。它只在system用户帐户下运行。

对于城镇中的所有其他用户,都有闹钟管理器。它是在system_server进程下以system用户身份运行的系统服务。它公开了上述的setTime方法,但强制执行SET_TIME权限,并在内部调用SystemClock.setCurrentTimeMillis(由于闹钟管理器正在运行的用户,因此成功)。

干杯


好的,我已经root了我的手机,但我不确定如何说服我的应用程序以适当的权限运行am.setTime()。你知道是否有办法吗? - Rich
但我想从服务器MDT获取时区,然后将时区更改为GMT,这是否可能? - Hardik Parmar
1
在最新的 Nexus 6 上,am.setTime(c.getTimeInMillis()); 对我来说失败了。 - zeeshan

23

根据这个讨论串,无论我们给予应用程序的权限如何,用户应用程序均无法设置时间。相反,最好的方法是要求用户手动设置时间。我们将使用:

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

很遗憾,没有直接将它们链接到时间设置的方法(这会为他们节省一次点击)。通过利用elapsedRealtime,我们可以确保用户正确设置时间。


16

对于已取得 root 权限的设备,可以执行以下命令:

  • su
  • date -s YYYYMMDD.HHMMSS

Change date on cmd

您可以通过以下方法使用代码来实现此操作:

private void changeSystemTime(String year,String month,String day,String hour,String minute,String second){
    try {
        Process process = Runtime.getRuntime().exec("su");
        DataOutputStream os = new DataOutputStream(process.getOutputStream());
        String command = "date -s "+year+month+day+"."+hour+minute+second+"\n";
        Log.e("command",command);
        os.writeBytes(command);
        os.flush();
        os.writeBytes("exit\n");
        os.flush();
        process.waitFor();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

只需像这样调用先前的方法:

changeSystemTime("2015","04","06","13","09","30");

我在安卓6上进行了测试,发现默认格式为“MMDDhhmm[[CC]YY][.ss]”,-s选项应该跟随格式而不是你想设置的实际时间。不确定这是否是安卓版本差异导致的。 - York Yang
2
如何设置时区? - Jaya
针对较新版本的安卓系统,此命令需要更改为 date 2015-04-06T13:09:30Z - Alann Maulana

3

我在列表中没有看到这个,但是它对我有用。我的设备已经root并且安装了超级用户,但如果超级用户可以在非root设备上使用,那么它可能会起作用。我使用了AsyncTask并调用了以下代码:

protected String doInBackground(String... params){
Runtime.getRuntime().exec("su && date -s " + params[0]);}

2
在我们的应用案例中,不太正规的解决方案是:
当用户连接到互联网时,我们获取互联网时间(NTP服务器)并比较内部设备时间与其之间的差异(registederOffsetFromInternetTime)。然后将其保存在用户的配置记录文件中。
我们使用设备时间 + registederOffsetFromInternetTime 来考虑我们应用程序的正确更新时间。
所有 GETHOUR 进程都检查实际时间与上次比较(与互联网时间)之间的差异。如果时间超过 10 分钟,则进行新的比较以更新 registederOffsetFromInternetTime 并保持准确性。
如果用户在没有互联网的情况下使用该应用程序,我们只能使用存储为参考的 registederOffsetFromInternetTime,并使用它。仅当用户在离线状态下更改本地设备的小时数并使用应用程序时,应用程序才会考虑不正确的时间。但是当用户恢复互联网访问时,我们会提醒他时钟已更改,并要求重新同步所有或忽略在不正确的小时数下离线执行的更新。

-2

谢谢Penguin。在QuickShortcutMaker中,我准确地捕获了日期/时间设置活动的名称。因此,要启动系统时间设置:

Intent intent=new Intent();
intent.setComponent(new ComponentName("com.android.settings",
         "com.android.settings.DateTimeSettingsSetupWizard"));      
startActivity(intent);

`


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接