【发布时间】:2010-11-22 20:49:40
【问题描述】:
当您想在您的应用程序中更改移动系统日期或时间时,您会怎么做?
【问题讨论】:
当您想在您的应用程序中更改移动系统日期或时间时,您会怎么做?
【问题讨论】:
您不能使用普通的现成手机,因为无法获得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_ZONE 和setTimeZone)
正如在几个线程中指出的那样,只有system 用户可以更改系统时间。这只是故事的一半。 SystemClock.setCurrentTimeMillis() 直接写入/dev/alarm,这是system 拥有的设备文件,缺少世界可写权限。所以换句话说,只有以system 运行的进程才能使用SystemClock 方法。对于这种方式,android 权限无关紧要,不涉及检查适当权限的实体。
这是内部预装设置应用程序的工作方式。它只是在system 用户帐户下运行。
对于镇上的所有其他孩子来说,还有警报管理器。它是运行在system_server 进程下的系统服务——猜猜看——system 用户帐户。它公开了提到的setTime 方法,但强制执行SET_TIME 权限,然后只在内部调用SystemClock.setCurrentTimeMillis(由于运行警报管理器的用户而成功)。
干杯
【讨论】:
根据this thread,用户应用程序无法设置时间,无论我们赋予它什么权限。相反,最好的方法是make the user set the time manually。我们将使用:
startActivity(new Intent(android.provider.Settings.ACTION_DATE_SETTINGS));
不幸的是,无法将它们直接链接到时间设置(这样可以节省更多点击时间)。通过使用ellapsedRealtime,我们可以确保用户正确设置时间。
【讨论】:
root 设备的解决方案是执行命令
您可以通过以下方法通过代码来做到这一点:
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");
【讨论】:
date 2015-04-06T13:09:30Z
我没有在任何地方看到这个列表,但它对我有用。我的设备是 root 并且我安装了超级用户,但是如果超级用户在非 root 设备上工作,这可能会起作用。我使用了 AsyncTask 并调用了以下内容:
protected String doInBackground(String... params){
Runtime.getRuntime().exec("su && date -s " + params[0]);}
【讨论】:
在我们的应用案例中,肮脏的解决方法是:
当用户连接到 Internet 时,我们获取 Internet 时间(NTP 服务器)并比较内部设备时间(registerederOffsetFromInternetTime)的差异(-)。我们保存在用户的配置记录文件中。
我们使用 devide + registererOffsetFromInternetTime 的时间来考虑我们的应用程序的正确更新时间。
所有 GETHOUR 进程都会检查实际时间与上次比较时间(与 Internet 时间)之间的差异。如果时间超过 10 分钟,请进行新的比较以更新 registererOffsetFromInternetTime 并保持准确性。
如果用户在没有互联网的情况下使用App,我们只能使用存储的registerederOffsetFromInternetTime作为参考,并使用它。只要用户在离线时更改本地设备的小时并使用应用程序,应用程序就会考虑错误的时间。但是当用户重新访问互联网时,我们会警告他时钟已更改,要求重新同步所有更新,或者考虑在不正确的时间下线的更新。
【讨论】:
感谢 Penquin。在 quickshortcutmaker 中,我准确地捕捉到日期/时间设置活动的名称。所以开始系统时间设置:
Intent intent=new Intent();
intent.setComponent(new ComponentName("com.android.settings",
"com.android.settings.DateTimeSettingsSetupWizard"));
startActivity(intent);
`
【讨论】: