2019年3月5日更新
进入下一步条件改为,时间大于>1970且网络已连接
之间校时存在的问题
1.无网出现几率太大
断电重启进入Launcher后,网路需要等待一会才会连接上传WiFi,这是页面大部分将会显示无网页面,之后校时成功后,整个Activity会把主要的页面重新提交,用户体验不好;
2.时区错误
经常重启几次后变成GMT+00:00时区,导致无论怎么做都会差8个小时;
日志分析
正常情况下的日志
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 01-02 08:00:07.300 579-579/com.onespax.launcher D/SyncTimeService: 启动了校时服务Fri Jan 02 08:00:07 GMT+08:00 1970 01-02 08:00:07.340 579-862/com.onespax.launcher D/SyncTimeService: 校时之前的时区:中国标准时间 01-02 08:00:07.400 579-862/com.onespax.launcher W/System.err: at com.spax.launcher.module.service.SyncTimeService$3.run(SyncTimeService.java:165) 01-02 08:00:07.400 579-862/com.onespax.launcher D/SyncTimeService: 网络校时失败 01-02 08:00:12.370 579-862/com.onespax.launcher D/SyncTimeService: 校时之前的时区:中国标准时间 01-02 08:00:12.380 579-862/com.onespax.launcher W/System.err: at com.spax.launcher.module.service.SyncTimeService$3.run(SyncTimeService.java:165) 01-02 08:00:12.380 579-862/com.onespax.launcher D/SyncTimeService: 网络校时失败 01-02 08:00:17.330 579-862/com.onespax.launcher D/SyncTimeService: 校时之前的时区:中国标准时间 01-02 08:00:17.380 579-862/com.onespax.launcher D/SyncTimeService: 没处理的网络时间:Mon Jan 14 14:33:33 GMT+08:00 2019 01-02 08:00:17.380 579-862/com.onespax.launcher D/SyncTimeService: 得到的网络时间:Mon Jan 14 14:33:33 GMT+08:00 2019 01-14 14:33:33.000 579-862/com.onespax.launcher D/SyncTimeService: 网络校时成功 01-14 14:33:33.000 579-862/com.onespax.launcher D/SyncTimeService: 执行的shell命令:date -s 20190114.143333 01-14 14:33:33.000 579-862/com.onespax.launcher D/SyncTimeService: 校时过后的时区:中国标准时间 01-14 14:33:33.030 579-579/com.onespax.launcher D/SyncTimeService: m_timeChangedReceiver onReceive() 01-14 14:33:33.060 579-862/com.onespax.launcher D/SyncTimeService: 校时之前的时区:中国标准时间 01-14 14:33:33.140 579-862/com.onespax.launcher D/SyncTimeService: 没处理的网络时间:Mon Jan 14 14:33:33 GMT+08:00 2019 01-14 14:33:33.140 579-862/com.onespax.launcher D/SyncTimeService: 得到的网络时间:Mon Jan 14 14:33:33 GMT+08:00 2019 01-14 14:33:33.150 579-862/com.onespax.launcher D/SyncTimeService: 系统的网络校时成功或者已经校对过时间
|
异常情况下的日志
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 01-02 08:00:07.250 579-853/com.onespax.launcher D/SyncTimeService: 校时之前的时区:GMT+00:00 01-02 08:00:07.260 579-853/com.onespax.launcher D/SyncTimeService: 网络校时失败 01-02 08:00:12.280 579-853/com.onespax.launcher D/SyncTimeService: 校时之前的时区:GMT+00:00 01-02 08:00:12.290 579-853/com.onespax.launcher D/SyncTimeService: 网络校时失败 01-02 08:00:17.240 579-853/com.onespax.launcher D/SyncTimeService: 校时之前的时区:GMT+00:00 01-02 08:00:17.290 579-853/com.onespax.launcher D/SyncTimeService: 没处理的网络时间:Mon Jan 14 07:35:30 GMT+00:00 2019 01-02 08:00:17.290 579-853/com.onespax.launcher D/SyncTimeService: 得到的网络时间:Mon Jan 14 07:35:30 GMT+00:00 2019 01-02 08:00:17.300 579-853/com.onespax.launcher D/SyncTimeService: 得到的系统时间:Fri Jan 02 00:00:17 GMT+00:00 1970 01-02 08:00:17.300 579-853/com.onespax.launcher D/SyncTimeService: 开始执行shell命令 01-14 07:35:30.000 579-853/com.onespax.launcher D/SyncTimeService: 网络校时成功 01-14 07:35:30.010 579-853/com.onespax.launcher D/SyncTimeService: 执行的shell命令:date -s 20190114.073530 01-14 07:35:30.010 579-853/com.onespax.launcher D/SyncTimeService: 校时过后的时区:GMT+00:00 01-14 07:35:30.060 579-853/com.onespax.launcher D/SyncTimeService: 校时之前的时区:GMT+00:00 01-14 07:35:30.070 579-579/com.onespax.launcher D/SyncTimeService: m_timeChangedReceiver onReceive() 01-14 07:35:30.100 579-853/com.onespax.launcher D/SyncTimeService: 没处理的网络时间:Mon Jan 14 07:35:30 GMT+00:00 2019 01-14 07:35:30.100 579-853/com.onespax.launcher D/SyncTimeService: 得到的网络时间:Mon Jan 14 07:35:30 GMT+00:00 2019 01-14 07:35:30.110 579-853/com.onespax.launcher D/SyncTimeService: 得到的系统时间:Sun Jan 13 23:35:30 GMT+00:00 2019 01-14 07:35:30.110 579-853/com.onespax.launcher D/SyncTimeService: 系统的网络校时成功或者已经校对过时间了
|
发现问题
之前老是断电重启系统时间差八小时,是此时系统的时区变成GMT+00:00,所以才有上篇文章提到的使用每次都用shell命令设置时区,这种做法加大了GMT+00:00出现的可能性。
1
| setprop persist.sys.timezone Asia/Shanghai
|
尝试怀疑是我写的有问题,重新写一个显示时间的程序,install到板子上发现程序时间是正确的,但是我们的launcher的时间仍是差8小时,故将我们的launcher kill掉重新启动,时间正常,故应该是当系统启动后马上启动我们的launcher,时区没有设置好,默认的是GMT+00:00,而此时我们的launcher已把之前的系统时区加载到进程中了,不会再次加载,故需要kill掉进程后,重新加载一遍
改进中心思想
之前5秒一次校时的Service逻辑不变,不手动设置时区,用shell设置时间
在InitActivity中每秒检查当前时间年份是否大于1970,再做下一步
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| private void next() { /** * 检查时间是否正确 */ DebugLogger.d(TAG, "开始检查时间是否正确"); CountDownLatch countDownLatch = new CountDownLatch(1); TimeHandler timeHandler = new TimeHandler(countDownLatch); timeHandler.start(); try { countDownLatch.await(30, TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } finally { DebugLogger.d(TAG, "时间检查结束"); jumpToNextActivity(); } }
private void jumpToNextActivity() { /** * 时区不正确但是时间是正确的需要重启一下app */ if (TimeZone.getDefault().getDisplayName().equals("GMT+00:00") && Calendar.getInstance().get(Calendar.YEAR) > 1970){ DebugLogger.d(TAG, "时区获取的不正确,需要退出重启APP"); Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage(getApplication().getPackageName()); LaunchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(LaunchIntent); System.exit(0); return; } /** * 跳转到其他页面 */ final boolean checkRet = SharedPrefsUtil.getConfig(App.getInstance(), Constants.Config.IS_NEED_UPDATE, false); Logger.t(TAG).d("checkRet:" + checkRet); Class<? extends Context> clazz = checkRet ? UpgradeActivity.class : SplashActivity.class; if (!checkRet) { InstallFilePolicy installFilePolicy = new InstallFilePolicy(null); SpaxInstallConfig restore = installFilePolicy.restore(); if (restore != null) { RootCmd.execRootCmd("rm -rf " + restore.getApkPath()); } } Intent intent = new Intent(InitConfigActivity.this, clazz); startActivity(intent); finish(); } private static final class TimeHandler extends Thread { private CountDownLatch countDownLatch; private int count; private boolean flag = true;
private TimeHandler(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; }
@Override public void run() { while (flag){ try { if (count == 30){ countDownLatch.countDown(); flag = false; return; } Thread.sleep(1000); // 在android5.1.1上表现为校时成功后但是没有连上网,所以要加一个条件限制 if (Calendar.getInstance().get(Calendar.YEAR) > 1970 && CommonUtil.isNetworkAvailable(App.getInstance())){ countDownLatch.countDown(); flag = false; } } catch (InterruptedException e) { e.printStackTrace(); countDownLatch.countDown(); flag = false; } count ++; } } }
|
开一个线程每秒轮询,符合条件下次结束,同时countDownLatch.countDown();唤醒主线程
同时主线有超时等待,最后在finally中进入下一步