如何在android中设置移动系统时间和日期?

Posted

技术标签:

【中文标题】如何在android中设置移动系统时间和日期?【英文标题】:How to set mobile system time and date in android? 【发布时间】:2010-11-22 20:49:40 【问题描述】:

当您想在您的应用程序中更改移动系统日期或时间时,您会怎么做?

【问题讨论】:

【参考方案1】:

您不能使用普通的现成手机,因为无法获得SET_TIME permission。此权限具有signatureOrSystem 的protectionLevel,因此市场应用程序无法更改全球系统时间(但也许使用我还不知道的黑巫术魔法)。

您不能使用其他方法,因为这在 Linux 级别上是被阻止的,(请参阅下面的长答案) - 这就是所有使用终端和 SysExecs 的试验都会失败的原因。

如果您获得许可是因为您将手机植根或构建并签署了自己的平台映像,请继续阅读。

简答

这是可能的,并且已经完成。你需要android.permission.SET_TIME。之后通过Context.getSystemService(Context.ALARM_SERVICE) 使用AlarmManager 及其方法setTime()

从 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() 直接写入/dev/alarm,这是system 拥有的设备文件,缺少世界可写权限。所以换句话说,只有以system 运行的进程才能使用SystemClock 方法。对于这种方式,android 权限无关紧要,不涉及检查适当权限的实体。

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

对于镇上的所有其他孩子来说,还有警报管理器。它是运行在system_server 进程下的系统服务——猜猜看——system 用户帐户。它公开了提到的setTime 方法,但强制执行SET_TIME 权限,然后只在内部调用SystemClock.setCurrentTimeMillis(由于运行警报管理器的用户而成功)。

干杯

【讨论】:

好吧,我已经植根了我的手机,但我不确定如何说服我的应用程序以适当的权限运行 am.setTime()。不知道有没有办法?? 但我想从服务器 MDT 中获取时区,并且我想更改像 GMT 这样的时区,所以它是如何可能的 am.setTime(c.getTimeInMillis());对我来说失败了,在带有最新更新的 Nexus 6 上。【参考方案2】:

根据this thread,用户应用程序无法设置时间,无论我们赋予它什么权限。相反,最好的方法是make the user set the time manually。我们将使用:

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

不幸的是,无法将它们直接链接到时间设置(这样可以节省更多点击时间)。通过使用ellapsedRealtime,我们可以确保用户正确设置时间。

【讨论】:

【参考方案3】:

root 设备的解决方案是执行命令

苏 日期-s YYYYMMDD.HHMMSS

您可以通过以下方法通过代码来做到这一点:

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");

【讨论】:

我在 android 6 上测试过,默认格式是 "MMDDhhmm[[CC]YY][.ss]" -s 选项后面应该跟格式而不是你想设置的实际时间。不确定这是否是android版本的差异。 如何设置时区? 对于较新的android版本,此命令需要更改为date 2015-04-06T13:09:30Z【参考方案4】:

我没有在任何地方看到这个列表,但它对我有用。我的设备是 root 并且我安装了超级用户,但是如果超级用户在非 root 设备上工作,这可能会起作用。我使用了 AsyncTask 并调用了以下内容:

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

【讨论】:

【参考方案5】:

在我们的应用案例中,肮脏的解决方法是:

当用户连接到 Internet 时,我们获取 Internet 时间(NTP 服务器)并比较内部设备时间(registerederOffsetFromInternetTime)的差异(-)。我们保存在用户的配置记录文件中。

我们使用 devide + registererOffsetFromInternetTime 的时间来考虑我们的应用程序的正确更新时间。

所有 GETHOUR 进程都会检查实际时间与上次比较时间(与 Internet 时间)之间的差异。如果时间超过 10 分钟,请进行新的比较以更新 registererOffsetFromInternetTime 并保持准确性。

如果用户在没有互联网的情况下使用App,我们只能使用存储的registerederOffsetFromInternetTime作为参考,并使用它。只要用户在离线时更改本地设备的小时并使用应用程序,应用程序就会考虑错误的时间。但是当用户重新访问互联网时,我们会警告他时钟已更改,要求重新同步所有更新,或者考虑在不正确的时间下线的更新。

【讨论】:

【参考方案6】:

感谢 Penquin。在 quickshortcutmaker 中,我准确地捕捉到日期/时间设置活动的名称。所以开始系统时间设置:

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

`

【讨论】:

以上是关于如何在android中设置移动系统时间和日期?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Android DatePicker 中设置最小和最大日期?

如何在 API 28 中设置 android 日期和时间选择器的样式

如何在本机反应中设置不可移动的地图标记

如何在android的日期选择器中设置特定日期

我如何在android中设置自定义日期

如何使用 AlarmClock 在 android 中设置闹钟的日期