Android4.4.2 获取NTP时间,并设置系统时间

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">
  1. 确保Linux下的app编译路径下的Android.mk 文件 下 LOCAL_CERTIFICATE := platform
  2. 源码下编译 mm
  3. 自测可修改系统时间
  4. 测试NTP服务器 123.124.209.75 默认端口123
  5. 没有执行权限的调用函数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)