Android4.4.2 获取NTP时间,并设置系统时间
16lz
2021-01-23
http://www.oschina.net/question/54100_31740
感谢博主的第一种方法,第二种方法没有尝试,
工作流程如下记录:
1. 有wifi的情况下获取ntp时间
2. 用获取NTP时间Android已经有现成的类D:\work_java\Android\sdk-meng\sources\android-19\android\net\SntpClient.java, 但是 是隐形的类.
源码中可见{@hide} 表示隐形类不能直接调用.所以要想其他的办法调用
3. 隐形的api在window的编译环境下不能直接调用包括以下几个办法:
- 直接复制SntpClient.java整个类到自己的工程下
- 源码编译工程
- java反射调用
4. 本次用java反射方法调用SntpClient类, 新编写类SntpTime
5. 在适当地方调用此类 之后执行SystemClock.setCurrentTimeMillis(sntpTime);
6. 修改AndroidManifest.xml 在manifest添加 android:sharedUserId="android.uid.system"
在win编译不通过提示错误
"http://schemas.android.com/apk/res/android" package="com.csctek.android.iserver.services" android:versionCode="1" android:versionName="1.0" android:sharedUserId="android.uid.system">
- 确保Linux下的app编译路径下的Android.mk 文件 下 LOCAL_CERTIFICATE := platform
- 源码下编译 mm
- 自测可修改系统时间
- 测试NTP服务器 123.124.209.75 默认端口123
- 没有执行权限的调用函数
SystemClock.setCurrentTimeMillis(sntpTime);
无论怎么调用这个函数都是没用的,无论模拟器还是真机,在logcat中总会得到”Unable to open alarm driver: Permission denied “
package com.android.myapp.sntptime;import android.os.Handler;import android.os.Message;import android.os.SystemClock;import android.util.Log;import java.lang.reflect.Method;import java.util.Date;/** * Created by user on 2016/11/28. */public class SntpTime { private String TAG = "SntpTime"; private String mIp; private int mTimeOut; private Handler mOtherHandler; private int mHandlerWhatNumber; // 时间获取ip地址 // socket超时时间 // 消息句柄// 消息标号自定义What数字 public SntpTime (String ip, int timeOut, Handler handler, int handlerWhatNumber) { this.mIp = ip; this.mTimeOut = timeOut; this.mOtherHandler = handler; this.mHandlerWhatNumber = handlerWhatNumber; Log.i(TAG, "SntpTime: " + mIp + " " + mTimeOut + " " + mHandlerWhatNumber); } public void getTime() { new Thread() { public void run() { //使用隐形类 try { Class C; //通过名字查找类 class C = Class.forName("android.net.SntpClient"); Log.i(TAG, "class is " + C); Object obj = C.newInstance(); try { //函数参数 2个 requestTime //根据名字和参数个数查找函数 Method m = C.getMethod("requestTime", new Class[]{String.class, int.class}); //参数值以数组的形式传入,格式与Class一样 //调用函数 Object o = m.invoke(obj, new Object[]{mIp, mTimeOut}); //返回值转换 boolean b = (Boolean)o; Log.i(TAG, "return is " + b); if (b) { //SntpClient.getNtpTime() //return time value computed from NTP server response Method mGetNtpTime = C.getMethod("getNtpTime", new Class[]{}); Object oGetNtpTime = mGetNtpTime.invoke(obj, new Object[]{}); Long ntpTime = (Long)oGetNtpTime; Log.i(TAG, "ntpTime is " + ntpTime); //SntpClient.getNtpTimeReference() == SystemClock.elapsedRealtime() //reference clock corresponding to the NTP time Method mGetNtpTimeReference = C.getMethod("getNtpTimeReference", new Class[]{}); Object oGetNtpTimeReference = mGetNtpTimeReference.invoke(obj, new Object[]{}); Long ntpTimeReference = (Long)oGetNtpTimeReference; Log.i(TAG, "ntpTimeReference is " + ntpTimeReference); //////////////////////////////// Log.i(TAG, "SystemClock.elapsedRealtime() is "+ SystemClock.elapsedRealtime()); Log.i(TAG, "System.currentTimeMillis() is "+ System.currentTimeMillis()); Date test0 = new Date(ntpTime); Log.i(TAG, "ntpTime is Date.toString()" + test0.toString()); Date test1 = new Date(System.currentTimeMillis()); Log.i(TAG, "System.currentTimeMillis() is Date.toString()" + test1.toString()); //很多网上的公式我这里测试返回的结果是错误的如: long now = client.getNtpTime() + System.nanoTime() / 1000 - client.getNtpTimeReference(); //本人这个计算公式是源码SntpClient.java源码注释中提供的,可自己查看 long nowTime = ntpTime + SystemClock.elapsedRealtime() - ntpTimeReference; updateTimeAndDate(nowTime); Date currentTime = new Date(nowTime); Message toOtherHandler = new Message(); toOtherHandler.what = mHandlerWhatNumber; toOtherHandler.obj = nowTime; Log.i(TAG, "mHandlerWhatNumber is "+ mHandlerWhatNumber + "time : " + currentTime.toString()); mOtherHandler.sendMessage(toOtherHandler); } } catch (Exception e) { e.printStackTrace(); Log.e(TAG, "GetClass SntpClient is error! two "); } } catch (Exception e) { e.printStackTrace(); Log.e(TAG, "GetClass SntpClient is error! one "); } } }.start(); }private void updateTimeAndDate(Long sntpTime) { long systemTime = System.currentTimeMillis(); Log.i(ISSERVICE, "Time////System.currentTimeMillis() is " + System.currentTimeMillis()); Log.i(ISSERVICE, "Time////sntpTime is " + sntpTime); Log.i(ISSERVICE, "Time////(systemTime - sntpTime) = " + (systemTime - sntpTime)); //if((systemTime - sntpTime >= 1000*60 ) || (systemTime - sntpTime <= -1000*60) ) { //时间格式修改 SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd.HHmmss");//yyyy-MM-dd HH:mm:ss String format = df.format(new Date(sntpTime)); Log.i(TAG, "Time////format is " + format); boolean b = SystemClock.setCurrentTimeMillis(sntpTime); Log.i(TAG, "Time////System.currentTimeMillis() is " + System.currentTimeMillis() + "return currentTimeMillis bool = " + b);// } }}
SntpTime类中有构造函数传入一个Handler, 所以我们通过Handler得到msg也就是NTP上的时间, 传递给主调函数,给系统设置时间
private void startSntpTime() {//参数1 表示Ip//参数2 超时时间//参数3 Handler//参数4 传入的Handler.What值 SntpTime currentTime = new SntpTime(ISGlobleBaseData.SNTP_TIME_IP, 30000, mHandler, ISServiceHandleMessage.SNTP_TIME_HANDLER); currentTime.getTime(); }/////////////////////////////////Handler消息分类 //Long这里一定要用 Long 代替long 否则linux源码mm编译的时候会报错case ISServiceHandleMessage.SNTP_TIME_HANDLER: Long time = (Long)msg.obj; Log.i(ISSERVICE, "time//// = " + String.valueOf(time)); break;///////////////////////////////////////////////
更多相关文章
- Android中调用C++函数的一个简单Demo
- Android的参数大致分成两块:系统服务参数和平台系统信息。
- 使用android中drawline函数无法绘制水平线的解决办法
- WebView与Javascript交互(相互调用参数、传值)
- Android中的时间自动更新
- Android 设置合理的定时器隔一段时间执行某段程序
- Android如何在三年时间里征服移动世界的
- Android 获取View的位置参数:x,y和相对父容器的偏移量以及中心点