android-获取网络时间、获取特定时区时间、时间同步的方法
最近整理出android-获取网络时间、获取特定时区时间、时间同步的方法。具体如下:
方法一:
SimpleDateFormat dff = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); dff.setTimeZone(TimeZone.getTimeZone("GMT+08")); String ee = dff.format(new Date());
这个方法获取的结果是24小时制的,月份也正确。
这个方法不随手机时间的变动而变动。也就是说,即使手机设置成别的时区,不是东八区,这个方法返回的也照样是北京时间!!!这正是我在做项目的时候用到的方法!!彻底解决项目需求!
方法二:
Calendar calendar = Calendar.getInstance(); SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss"); sdf.setTimeZone(TimeZone.getTimeZone("GMT+8")); String rt = sdf.format(calendar.getTime());
这个方法获取的结果是不是24小时制的,月份也正确。
方法三:
public static String getLocalDatetimeString(String local) { Calendar cal = new GregorianCalendar(TimeZone.getTimeZone(local)); cal.setTimeInMillis(Calendar.getInstance().getTimeInMillis()); String date = cal.get(Calendar.YEAR) + "-" + (cal.get(Calendar.MONTH) + 1) + "-" + cal.get(Calendar.DAY_OF_MONTH); String time = cal.get(Calendar.HOUR_OF_DAY) + ":" + cal.get(Calendar.MINUTE) + ":" + cal.get(Calendar.SECOND); return date + " " + time; }
方法调用:
String tt = getLocalDatetimeString("GMT+8");
代码里也看出来了,这个在月份上加了一个1, 24小时制
以上三种方法验证如下:
import java.sql.Time; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; public class TimeTest { /** * @param args */ public static void main(String[] args) { method1(); method2(); method3(); } static void method1(){ SimpleDateFormat dff = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); dff.setTimeZone(TimeZone.getTimeZone("GMT+08")); String ee = dff.format(new Date()); System.out.println("ee="+ee); } static void method2(){ Calendar calendar = Calendar.getInstance(); SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss"); sdf.setTimeZone(TimeZone.getTimeZone("GMT+8")); String rt = sdf.format(calendar.getTime()); System.out.println("TimeTest.method2() rt="+rt); } static void method3(){ String local = "GMT+8"; Calendar cal = new GregorianCalendar(TimeZone.getTimeZone(local)); cal.setTimeInMillis(Calendar.getInstance().getTimeInMillis()); String date = cal.get(Calendar.YEAR) + "-" + (cal.get(Calendar.MONTH) + 1) + "-" + cal.get(Calendar.DAY_OF_MONTH); String time = cal.get(Calendar.HOUR_OF_DAY) + ":" + cal.get(Calendar.MINUTE) + ":" + cal.get(Calendar.SECOND); System.out.println("TimeTest.method3() date="+date+",time="+time); } }
结果如下:
本人采用的是第一种方法,因为第一种方法的时间是不随手机时间的设置而改变。
第二种方法也是可以的,不过时间小时是12进制。
第四种方法:
网上还有这种方法获取时间:
URL url=new URL("http://www.bjtime.cn");//取得资源对象 URLConnection uc=url.openConnection();//生成连接对象 uc.connect(); //发出连接 long ld=uc.getDate(); //取得网站日期时间 Date date=new Date(ld); //转换为标准时间对象 //分别取得时间中的小时,分钟和秒,并输出 System.out.print(date.getHours()+"时"+date.getMinutes()+"分"+date.getSeconds()+"秒");
这种方式需要开启一个线程获取时间,同时也存在着一种风险就是由于网络问题,获取不到响应的问题。还有一个重要的问题件就是这个时间的获取会随着手机时区的改变而改变。
方法五:
通过网络或者GPS的方式。
代码:
LocationManager locMan = (LocationManager) this.getSystemService(MainActivity.LOCATION_SERVICE); //获取最近一次知道的时间 long networkTS = locMan.getLastKnownLocation(LocationManager.NETWORK_PROVIDER).getTime();
或者实时的获取时间:
locMan.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this); //获取当前时间
当我们使用requestLocationUpdates时,我们需要实现LocationListener接口。
在LocationListen的回调onLocationChanged当中获取时间
@Override public void onLocationChanged(Location location) { // TODO Auto-generated method stub long time = location.getTime(); Date date = new Date(time); System.out.println(time + " NETWORK_PROVIDER " + date); // System.out.println(STANDARD_TIME + " "); }
这种方式是利用手机定位系统进行时间的获取,但是这种方式会随着手机的设置的时区的变动而改变。
第四种方式和第五种方式,我都在手机端进行了验证,可以正常获取时间。方式是没有问题的。
既然有这么多方法,大家看着那种方式适合自己的需求,选择相应的方法。
我还是推荐第一种方法!简单实用!!!!^_^
今天再在本文基础上补充一些内容。现在我的项目中有这样一种需求:就是播放视频的时候,特别是监控视频,我想要有时间限制,在一定时间内可以观看,超出设置的时间,不能观看。
Android端对于这样的需求,上面的几种方法都不行了,因为上面的方法都跟手机系统有关系了,当我改变手机系统的时间,时区等都会造成获取的时间不对应,跟服务器时间不对。怎么办呢?有办法!!!
我是这样做的,当获取到信息的时候,比如视频节点信息的时候,服务器顺带着把服务器当前的时间返回来,有了服务器的时间,剩下的我就利用用户操作的时间间隔,加上服务器的时间不就是手机所在地当前的时间吗?
那么时间间隔怎么算呢?请看下面的SystemClock类几个方法:
1、System.currentTimeMillis()是一个标准的“墙”时钟(时间和日期),表示从纪元到现在的毫秒数。该墙时钟能够被用户或电话网络(见setCurrentTimeMillis(long))设置,所以该时间可能会向前或向后不可预知地跳越。该时钟应该仅仅被使用在当现实世界的对应的日期和时间是重要的情况,例如一个日历或闹钟应用程序。而间隔时间和经过时间应该使用不同的时钟。如果你使用System.currentTimeMillis(),可以考虑监听ACTION为ACTION_TIME_TICK、 ACTION_TIME_CHANGED、ACTION_TIMEZONE_CHANGED 的广播去监听时间变化。
2、uptimeMillis()表示自系统启动时开始计数,以毫秒为单位。返回的是从系统启动到现在这个过程中的处于非休眠期的时间。当系统进入深度睡眠时(CPU关闭,设备变黑,等待外部输入装置)该时钟会停止。但是该时钟不会被时钟调整,闲置或其他节能机所影响。这是大多数间隔时间的基本点,例如Thread.sleep(millls)、Object.wait(millis)和System.nanoTime()。该时钟被保证是单调的,适用于检测不包含休眠的间隔时间的情况。大多数的方法接受一个时间戳的值除了uptimeMillis()时钟。
3、elapsedRealtime() and elapsedRealtimeNanos() 返回系统启动到现在的时间,包含设备深度休眠的时间。该时钟被保证是单调的,即使CPU在省电模式下,该时间也会继续计时。该时钟可以被使用在当测量时间间隔可能跨越系统睡眠的时间段。
有几种机制控制事件发生的时间:
1、标准的方法像Thread.sleep(millis) 和 Object.wait(millis)总是可用的,这些方法使用的是uptimeMillis()时钟,如果设备进入深度休眠,剩余的时间将被推迟直到系统唤醒。这些同步方法可能被Thread.interrupt()中断,并且你必须处理InterruptedException异常。
2、SystemClock.sleep(millis)是一个类似于Thread.sleep(millis)的实用方法,但是它忽略InterruptedException异常。使用该函数产生的延迟如果你不使用Thread.interrupt(),因为它会保存线程的中断状态。
3、Handler可以在一个相对或者绝对的时间设置异步回调,Handler类对象也使用uptimeMillis()时钟,而且需要一个loop(经常出现在GUI程序中)。
4、AlarmManager可以触发一次或重复事件,即使设备深度休眠或者应用程序没有运行。事件可以选择用 currentTimeMillis或者elapsedRealtime()(ELAPSED_REALTIME)来设置时间,当事件发生会触发一个广播。
方法:
1、public static long currentThreadTimeMillis () 返在当前线程运行的毫秒数。
2、public static long elapsedRealtime () 返回系统启动到现在的毫秒数,包含休眠时间。
3、public static long elapsedRealtimeNanos () 返回系统启动到现在的纳秒数,包含休眠时间。
4、public static boolean setCurrentTimeMillis (long millis) 设置当前的”墙”时间,要求调用进程有许可权限。返回是否成功。
5、public static void sleep (long ms) 等待给定的时间。和Thread.sleep(millis)类似,但是它不会抛出InterruptedException异常。事件被推迟到下一个中断操作。该方法直到指定的时间过去才返回。
6、public static long uptimeMillis () 返回系统启动到现在的毫秒数,不包含休眠时间。就是说统计系统启动到现在的非休眠期时间。
这些方法大家看看就知道啦。
剩下的就是计算事件间隔了:
public static long elapsedRealtime () 返回系统启动到现在的毫秒数,包含休眠时间
这个方法就可以计算从服务器返回时间到用户操作,播放视频这一段时间的时间间隔。有个这个不就可以做到时间不受手机系统的限制了吗?
/** * * @param ts 形如yyyy-MM-dd hh:mm:ss * @param intervalTime long类型 * @return String HH:mm:ss */ @SuppressLint("SimpleDateFormat") public static String getTime(String ts,long intervalTime){ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); Timestamp t=null; String tt=""; try { t = new Timestamp(format.parse(ts).getTime()); long ss = t.getTime(); long st = ss+intervalTime; tt= getTime(st); } catch (java.text.ParseException e) { e.printStackTrace(); } return tt; } /** * @param mis * @return HH:mm:ss */ @SuppressLint("SimpleDateFormat") public static String getTime(long mis){ SimpleDateFormat dff = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String ee = dff.format(new Date(mis)); return ee.substring(11); }
上面的方法中, ts参数就是服务器返回的当前时间,形如yyyy-MM-dd hh:mm:ss的字符串intervalTime参数,是获取到服务器响应到用户进行操作的时间间隔,就是使用上面的elapsedRealtime ()方法获取两次时间计算得到。
方法的返回值String,形如 HH:mm:ss,这样返回字符串方便比较时间字符。由于视频事件限制,就是时分秒,不可能涉及到年月日,所以这里就是直接返回时分秒。
有了这个方法,完美解决了android APP与服务器时间保持基本一致的需求。但是还是存在一定的问题的,因为服务器返回时间不定,可能长可能短,所以时间并不会和服务器的当前时间分秒不差,总会有延时,但是这个延时可以接受,大概最多在10秒左右。可以在时间间隔上稍微加一点就可以了。基本就满足需求了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。