我目前正在尝试在软件中设置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完美运行的同一设备上进行测试。那么 - 我做错了什么?或者更好:你能提供有效的测试代码吗?
答案 0 :(得分:53)
更新:此方法不再适用于最近的Android版本。我所知道的另一种方法是使用date
命令来设置时间。请注意,根据Android版本和安装的第三方工具,命令格式可能会有所不同(BusyBox版本的date
不支持时区)。
// 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。请注意,谷歌最近已禁止市场上出现AOSP密钥,而作者将永远无法更新其申请。 NTPc不能安装在大多数手机上使用的普通ROM上。
如果您需要详细信息,请务必阅读着名的问题4581 :Allow user apps to set the system time的评论。请注意,Google的问题是拒绝,并带有以下注释:
嗨,应用程序无法改变时间。那里 安全的许多微妙方面可以依赖于当前时间, 例如证书到期,许可证管理等。我们没有 希望允许第三方应用程序在全球范围内破坏系统 就这样。
如何在有根设备上设置时间:
ClockSync设置时间的做法是更改/dev/alarm
设备的权限。实质上,它在根shell中运行chmod 666 /dev/alarm
。一旦此设备对所有用户具有写入权限,SystemClock.
setCurrentTimeMillis(...)呼叫将成功。一些应用程序使用另一种方法,它们在root shell中使用适当的参数运行date
命令,但是它容易出错且不太准确,因为超级用户shell和命令执行可能需要几秒钟。这种应用的一个例子是Sytrant。
默认情况下,只有/dev/alarm
尚未写入时,ClockSync才会设置666权限。这节省了CPU /电池,因为su / Superuser.apk执行相对昂贵。如果您担心安全性,则会有恢复权限选项,该选项会在设置时间后使警报设备获得权限。
为了更容易从应用程序访问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服务器获取时间。
答案 1 :(得分:9)
您可以在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();
}
}