Facebook Twitter LinkedIn E-mail
magnify
Home 2012 六月

Android 自动获取时间的方法

对于手机,如果有SIM卡支持的话,在设置时间时可以通过选择自动从网络获取时间来取得当地的时间和时区:

但如果手机没有SIM卡,此时如果有Wifi链接,手机依然可以通过网络自动获取时间(时区此时需要手动设置)。 查看Android源码,在android.net 中有 SntpClient类,可以通过访问NTP服务器来取得当前的GMT时间。pool.ntp.org为最常用的一个NTF服务器。修改SntpClient代码,你也可以在自己的应用(包括非Android应用)中通过NTP服务器来取得当前GMT时间,代码如下:


import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Date;

public class GetTime {

	public static void main(String[] args) {
		SntpClient client = new SntpClient();
		if (client.requestTime("pool.ntp.org", 30000)) {
			long now = client.getNtpTime() + System.nanoTime() / 1000
					- client.getNtpTimeReference();
			Date current = new Date(now);
			System.out.println(current.toString());
		}

	}
}

class SntpClient {

	private static final int ORIGINATE_TIME_OFFSET = 24;
	private static final int RECEIVE_TIME_OFFSET = 32;
	private static final int TRANSMIT_TIME_OFFSET = 40;
	private static final int NTP_PACKET_SIZE = 48;

	private static final int NTP_PORT = 123;
	private static final int NTP_MODE_CLIENT = 3;
	private static final int NTP_VERSION = 3;

	// Number of seconds between Jan 1, 1900 and Jan 1, 1970
	// 70 years plus 17 leap days
	private static final long OFFSET_1900_TO_1970 = ((365L * 70L) + 17L) * 24L * 60L * 60L;

	// system time computed from NTP server response
	private long mNtpTime;

	// value of SystemClock.elapsedRealtime() corresponding to mNtpTime
	private long mNtpTimeReference;

	// round trip time in milliseconds
	private long mRoundTripTime;

	/**
	 * Sends an SNTP request to the given host and processes the response.
	 *
	 * @param host
	 *            host name of the server.
	 * @param timeout
	 *            network timeout in milliseconds.
	 * @return true if the transaction was successful.
	 */
	public boolean requestTime(String host, int timeout) {
		try {
			DatagramSocket socket = new DatagramSocket();
			socket.setSoTimeout(timeout);
			InetAddress address = InetAddress.getByName(host);
			byte[] buffer = new byte[NTP_PACKET_SIZE];
			DatagramPacket request = new DatagramPacket(buffer, buffer.length,
					address, NTP_PORT);

			// set mode = 3 (client) and version = 3
			// mode is in low 3 bits of first byte
			// version is in bits 3-5 of first byte
			buffer[0] = NTP_MODE_CLIENT | (NTP_VERSION << 3);

			// get current time and write it to the request packet
			long requestTime = System.currentTimeMillis();
			long requestTicks = System.nanoTime() / 1000;
			writeTimeStamp(buffer, TRANSMIT_TIME_OFFSET, requestTime);

			socket.send(request);

			// read the response
			DatagramPacket response = new DatagramPacket(buffer, buffer.length);
			socket.receive(response);
			long responseTicks = System.nanoTime() / 1000;
			long responseTime = requestTime + (responseTicks - requestTicks);
			socket.close();

			// extract the results
			long originateTime = readTimeStamp(buffer, ORIGINATE_TIME_OFFSET);
			long receiveTime = readTimeStamp(buffer, RECEIVE_TIME_OFFSET);
			long transmitTime = readTimeStamp(buffer, TRANSMIT_TIME_OFFSET);
			long roundTripTime = responseTicks - requestTicks
					- (transmitTime - receiveTime);
			// receiveTime = originateTime + transit + skew
			// responseTime = transmitTime + transit - skew
			// clockOffset = ((receiveTime - originateTime) + (transmitTime -
			// responseTime))/2
			// = ((originateTime + transit + skew - originateTime) +
			// (transmitTime - (transmitTime + transit - skew)))/2
			// = ((transit + skew) + (transmitTime - transmitTime - transit +
			// skew))/2
			// = (transit + skew - transit + skew)/2
			// = (2 * skew)/2 = skew
			long clockOffset = ((receiveTime - originateTime) + (transmitTime - responseTime)) / 2;
			// if (Config.LOGD) Log.d(TAG, "round trip: " + roundTripTime +
			// " ms");
			// if (Config.LOGD) Log.d(TAG, "clock offset: " + clockOffset +
			// " ms");

			// save our results - use the times on this side of the network
			// latency
			// (response rather than request time)
			mNtpTime = responseTime + clockOffset;
			mNtpTimeReference = responseTicks;
			mRoundTripTime = roundTripTime;
		} catch (Exception e) {

			return false;
		}

		return true;
	}

	/**
	 * Returns the time computed from the NTP transaction.
	 *
	 * @return time value computed from NTP server response.
	 */
	public long getNtpTime() {
		return mNtpTime;
	}

	/**
	 * Returns the reference clock value (value of
	 * SystemClock.elapsedRealtime()) corresponding to the NTP time.
	 *
	 * @return reference clock corresponding to the NTP time.
	 */
	public long getNtpTimeReference() {
		return mNtpTimeReference;
	}

	/**
	 * Returns the round trip time of the NTP transaction
	 *
	 * @return round trip time in milliseconds.
	 */
	public long getRoundTripTime() {
		return mRoundTripTime;
	}

	/**
	 * Reads an unsigned 32 bit big endian number from the given offset in the
	 * buffer.
	 */
	private long read32(byte[] buffer, int offset) {
		byte b0 = buffer[offset];
		byte b1 = buffer[offset + 1];
		byte b2 = buffer[offset + 2];
		byte b3 = buffer[offset + 3];

		// convert signed bytes to unsigned values
		int i0 = ((b0 & 0x80) == 0x80 ? (b0 & 0x7F) + 0x80 : b0);
		int i1 = ((b1 & 0x80) == 0x80 ? (b1 & 0x7F) + 0x80 : b1);
		int i2 = ((b2 & 0x80) == 0x80 ? (b2 & 0x7F) + 0x80 : b2);
		int i3 = ((b3 & 0x80) == 0x80 ? (b3 & 0x7F) + 0x80 : b3);

		return ((long) i0 << 24) + ((long) i1 << 16) + ((long) i2 << 8)
				+ (long) i3;
	}

	/**
	 * Reads the NTP time stamp at the given offset in the buffer and returns it
	 * as a system time (milliseconds since January 1, 1970).
	 */
	private long readTimeStamp(byte[] buffer, int offset) {
		long seconds = read32(buffer, offset);
		long fraction = read32(buffer, offset + 4);
		return ((seconds - OFFSET_1900_TO_1970) * 1000)
				+ ((fraction * 1000L) / 0x100000000L);
	}

	/**
	 * Writes system time (milliseconds since January 1, 1970) as an NTP time
	 * stamp at the given offset in the buffer.
	 */
	private void writeTimeStamp(byte[] buffer, int offset, long time) {
		long seconds = time / 1000L;
		long milliseconds = time - seconds * 1000L;
		seconds += OFFSET_1900_TO_1970;

		// write seconds in big endian format
		buffer[offset++] = (byte) (seconds >> 24);
		buffer[offset++] = (byte) (seconds >> 16);
		buffer[offset++] = (byte) (seconds >> 8);
		buffer[offset++] = (byte) (seconds >> 0);

		long fraction = milliseconds * 0x100000000L / 1000L;
		// write fraction in big endian format
		buffer[offset++] = (byte) (fraction >> 24);
		buffer[offset++] = (byte) (fraction >> 16);
		buffer[offset++] = (byte) (fraction >> 8);
		// low order bits should be random data
		buffer[offset++] = (byte) (Math.random() * 255.0);
	}
}

运行这个Java应用,可以得到当前GMT时间,如:Sat Jun 16 10:52:19 BST 2012

 

在Windows上编写Object C程序

随着iphone的流行,越来越多的程序员开始学习Object C编程,但一般来说编写Object C需要iMac计算机。这对于刚开始学习Object C编程的程序员是个问题。

本文给出了一个在 windows 平台上学习Object C编程的方法。

1.下载GNUStep

http://ftpmain.gnustep.org/pub/gnustep/binaries/windows/

下载

gnustep-msys-system-x.x.x-setup.exe

gnustep-core-x.x.x-setup.exe

gnustep-cairo-x.x.x-setup.exe

gnustep-devel-x.x.x-setup.exe

将下载的GNUStep安装,比如C:\GNUStep

2. 下载JEdit

http://www.jedit.org/index.php?page=download

JEdit 是Freeware,可以用来编辑 .m 文件 .m 是Object C缺省后缀。 .m 相当于 .c 文件

3. 一个Object C教材

http://www.otierney.net/objective-c.html

———————————————

4. 安装后,执行msys.bat 启动 GNUStep 环境 (类Linux环境)

5. 编写示例程序

fraction.h

#import <Foundation/NSObject.h>

@interface Fraction: NSObject {
     int numerator;
     int denominator;
 }

-(void) print;
 -(void) setNumerator: (int) n;
 -(void) setDenominator: (int) d;
 -(int) numerator;
 -(int) denominator;
 @end

fraction.m

#import "fraction.h"
 #import 

@implementation Fraction
 -(void) print {
     printf( "%i/%i", numerator, denominator );
 }

-(void) setNumerator: (int) n {
     numerator = n;
 }

-(void) setDenominator: (int) d {
     denominator = d;
 }

-(int) denominator {
     return denominator;
 }

-(int) numerator {
     return numerator;
 }
 @end

main.m

#import 
#import "fraction.h"

int main( int argc, const char *argv[] ) {
     // create a new instance
     Fraction *frac = [[Fraction alloc] init];

    // set the values
     [frac setNumerator: 1];
     [frac setDenominator: 3];

    // print it
     printf( "The fraction is: " );
     [frac print];
     printf( "\n" );

    // free memory
     [frac release];

    return 0;
 }

6. 编写Makefile

在当前目录下创建GNUmakefile

include $(GNUSTEP_MAKEFILES)/common.make

TOOL_NAME = Hello
 Hello_OBJC_FILES = main.m fraction.m

include $(GNUSTEP_MAKEFILES)/tool.make

6. 编译程序

$ make

将创建 obj目录 运行  hello.exe

The fraction is: 1/3

这样环境就搭好了,你就可以继续学习 Object C了

最终写iphone程序一般还是要Mac OS.