package com.gh.gamecenter.changeskin; import android.content.Context; import android.os.Handler; import android.os.Message; import android.view.View; import android.widget.ProgressBar; import android.widget.TextView; import com.gh.base.AppController; import com.gh.common.util.Utils; import com.gh.gamecenter.R; import com.gh.gamecenter.adapter.viewholder.GameDetailSkinViewHolder; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import java.io.File; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Timer; import java.util.TimerTask; /** * Created by khy on 2016/11/16. */ public class ChangeSkinUtils { public static boolean isChecking = false; private static List patchDatas = new ArrayList(); private static List updatePatchList; private static Timer timer; private static Timer poiTimer; private static int pageNum = 1; private static int curProgress = 0; private static int pg = 0; private static int maxPoogress = 0; private static int curMD5Num; //当前检查过的本地MD5文件数量 private static int localMD5Num;//文件总数量 private static ProgressBar pgPatch; private static String checkPoint = "."; private static String speed = " 0KB/s"; private static String filePath = "/mnt/sdcard/Android/data/" + SkinConfig.patchVersion + "/files"; private static TextView tvPatch; private static TextView tvPer; private static int downPosition = -1; private static int downState = 0; // 0:无操作 1:暂停 2:正在下载 3:下载完成 private static int patchSize; private static Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { //下载完成 case SkinConfig.MSG_DOWNLOAD_OVER: String jsonRuslt = (String) msg.obj; if ("".equals(jsonRuslt)) { startCheckMD5Thread(); } else { List patchData = parseDesPatchJson(jsonRuslt); patchDatas.addAll(patchData); if (patchData.size() < SkinConfig.perPage) { startCheckMD5Thread(); } else { pageNum++; String urlPath = SkinConfig.JSON_PATCHURL + pageNum; DownloadUtils.downloadJson(urlPath, handler); } } break; //进度条更新 case SkinConfig.MSG_PROGRESS_UPDATE: tvPatch.setVisibility(View.GONE); pgPatch.setVisibility(View.VISIBLE); tvPer.setVisibility(View.VISIBLE); curProgress++; pg = curProgress * 100 / maxPoogress; pgPatch.setProgress(pg); Utils.log("当前下载:" + pg + "% (" + speed + ")" + "::" + curProgress); if (pg >= 100) { tvPatch.setText("更新完成"); tvPatch.setVisibility(View.VISIBLE); pgPatch.setVisibility(View.GONE); tvPer.setVisibility(View.GONE); tvPatch.setEnabled(false); pgPatch.setEnabled(false); tvPer.setEnabled(false); downState = 3; timer.cancel(); } else { if (downState == 1) { tvPer.setText("继续"); } else { tvPer.setText(pg + "% (" + speed + ")"); } } break; //更新下载速度 case SkinConfig.MSG_NETWORK_SPEED: speed = (String) msg.obj; break; //更新检测当前文件MD5值数量 case SkinConfig.MSG_MD5_PROGRSS: curMD5Num++; String showTxt = "检测中(" + curMD5Num + "/" + localMD5Num + ")" + checkPoint; changeViewState(showTxt, "blue", SkinConfig.TYPE_DESUPDATE, false); break; //文件MD5值检查完 case SkinConfig.MSG_MD5_OVER: poiTimer.cancel(); Map map = (Map) msg.obj; relMD5File(map); break; //网络error case SkinConfig.MSG_NETWORK_ERROR: changeViewState("网络异常,请保持网络通畅", "gray", SkinConfig.TYPE_DESUPDATE, true); break; } } }; public static void changeSkinControl(GameDetailSkinViewHolder holder, final Context context) { tvPatch = holder.skinDownloadTv; pgPatch = holder.skinDownloadPb; tvPer = holder.skinDownloadPerTv; pgPatch.setMax(100); if (SkinConfig.PG_STATE == SkinConfig.TYPE_UPDATE) { String showTxt = "点击开始更新(" + patchSize + "MB)"; changeViewState(showTxt, "blue", SkinConfig.TYPE_UPDATE, true); } else { switch (downState) { case 0: tvPatch.setText("检测更新"); tvPatch.setVisibility(View.VISIBLE); pgPatch.setVisibility(View.GONE); tvPer.setVisibility(View.GONE); break; case 1: tvPatch.setVisibility(View.GONE); pgPatch.setVisibility(View.VISIBLE); tvPer.setVisibility(View.VISIBLE); pgPatch.setProgress(pg); tvPer.setText("继续"); break; case 2: tvPatch.setVisibility(View.GONE); pgPatch.setVisibility(View.VISIBLE); tvPer.setVisibility(View.VISIBLE); tvPer.setText(pg + "% (" + speed + ")"); break; case 3: tvPatch.setText("更新完成"); tvPatch.setVisibility(View.VISIBLE); pgPatch.setVisibility(View.GONE); tvPer.setVisibility(View.GONE); break; } } holder.skinDownloadTv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if ("更新完成".equals(tvPatch.getText().toString())) return; switch (SkinConfig.PG_STATE) { case SkinConfig.TYPE_DESUPDATE: if (!"检测更新".equals(tvPatch.getText().toString())) return; // /data/data目录下包名文件 File pgFile = new File("/data/data/" + SkinConfig.patchVersion); // 内部sdcard中版本文件 String pgFilePath = "/mnt/sdcard/Android/data/" + SkinConfig.patchVersion + "/files"; File verFile = new File(pgFilePath); if (!pgFile.exists() || !verFile.exists()) { String showTxt = "请先安装游戏,并更新好所有补丁"; tvPatch.setBackgroundResource(R.drawable.textview_cancel_style); changeViewState(showTxt, "gray", SkinConfig.TYPE_DESUPDATE, true); } else { isChecking = true; String showTxt = "检测中" + checkPoint; changeViewState(showTxt, "blue", SkinConfig.TYPE_DESUPDATE, false); startSetPoint(); String urlPath = SkinConfig.JSON_PATCHURL + pageNum; //下载数据json DownloadUtils.downloadJson(urlPath, handler); } break; case SkinConfig.TYPE_UPDATE: String showTxt = "开始更新..."; changeViewState(showTxt, "blue", SkinConfig.TYPE_DESUPDATE, false); maxPoogress = updatePatchList.size(); startTimer(context); updateProgress(); break; } } }); tvPer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if ("继续".equals(tvPer.getText().toString())) { downState = 2; tvPer.setText(pg + "% (" + speed + ")"); updateProgress(); } else { tvPer.setText("继续"); downState = 1; } } }); } //按钮状态改变 private static void changeViewState(String txt, String color, int type, boolean isEnabled) { tvPatch.setText(txt); SkinConfig.PG_STATE = type; pgPatch.setEnabled(isEnabled); } //正在下载 ... 点用计时器控制 private static void startSetPoint() { final int[] curPoint = {0}; final TimerTask task = new TimerTask() { @Override public void run() { curPoint[0] += 1; if (curPoint[0] == 1) { checkPoint = "."; } else if (curPoint[0] == 2) { checkPoint = ".."; } else if (curPoint[0] == 3) { curPoint[0] = 0; checkPoint = "..."; } } }; poiTimer = new Timer(true); poiTimer.schedule(task, 1000, 1000); } //开启计时器,计算下载速度 private static void startTimer(final Context context) { final TimerTask task = new TimerTask() { @Override public void run() { NetSpeed.showNetSpeed(context, handler); } }; timer = new Timer(true); timer.schedule(task, 1000, 1000); } //指定目录,下载替换文件 private static void updateProgress() { Thread downThread = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < updatePatchList.size(); i++) { if (downState == 1) { break; } if (i < downPosition) { // 重复下载暂停前的一张图片,防止断网下载失败 漏掉下载的图片 continue; } downPosition = i; PatchEntity patchData = updatePatchList.get(i); String filePath = patchData.path; Utils.log("updateProgress---" + updatePatchList.size() + "::" + i); DownloadUtils.saveUrlToFile(filePath, patchData.url, handler); } } }); downThread.start(); } //比较文件的MD5值,返回MD5值不同的文件个数 private static void relMD5File(Map dirMD5Map) { updatePatchList = new ArrayList(); patchSize = 0; curMD5Num = 0; //获取目录下所有文件的 MD5 值 for (int i = 0; i < patchDatas.size(); i++) { PatchEntity data = patchDatas.get(i); String path = data.path; String updateMD5 = data.md5; String updateSize = data.size; //替换地址中标识符& String replacePath = path.replace("&", SkinConfig.patchVersion); patchDatas.get(i).path = replacePath; String localMD5 = dirMD5Map.get("/" + replacePath); if (localMD5 != null) { if (!updateMD5.equals(localMD5)) { updatePatchList.add(data); patchSize += Integer.parseInt(updateSize); } } } isChecking = false; if (patchSize == 0) { String showTxt = "暂无更新"; tvPatch.setBackgroundResource(R.drawable.textview_cancel_style); changeViewState(showTxt, "gray", SkinConfig.TYPE_DESUPDATE, true); } else { patchSize = patchSize / 1024 / 1024; String showTxt = "点击开始更新(" + patchSize + "MB)"; changeViewState(showTxt, "blue", SkinConfig.TYPE_UPDATE, true); } } private static void startCheckMD5Thread() { AppController.MAIN_EXECUTOR.execute(new Runnable() { @Override public void run() { localMD5Num = FileMD5Utils.getDirNum(new File(filePath)); Map dirMD5Map = FileMD5Utils.getDirMD5(new File(filePath), handler); Message msg = Message.obtain(); msg.obj = dirMD5Map; msg.what = SkinConfig.MSG_MD5_OVER; handler.sendMessage(msg); } }); } //解析json数据 private static List parseDesPatchJson(String jsonString) { Type listType = new TypeToken>() { }.getType(); Gson gson = new Gson(); return gson.fromJson(jsonString, listType); } //断网或者写入文件失败的操作 public static void NetWorkErrorControl() { downState = 1; handler.post(new Runnable() { @Override public void run() { tvPer.setText("继续"); } }); } }