package com.sunvote.xpadcomm; import android.os.Environment; import android.util.Log; import com.sunvote.util.LogUtil; import com.sunvote.xpadapp.utils.FileUtil; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.Socket; public class FileRecver { private String TAG = "FileRecver"; private String ip; private int port; private Socket socket = null; DataOutputStream out = null; DataInputStream getMessageStream = null; private String filePath = Environment.getExternalStorageDirectory().getPath() + "/sunvote"; private String fileName; private String keypadID; private FileReciverInterface listener; public interface FileReciverInterface { void onConnectServerError(); void onDownloadDataError(); void onDownload(long percent); void onDownloadUserStop(); void onDownloadSuccess(); void onUnzipError(); } public FileRecver(FileReciverInterface recvInterface, String ip, int port) { this.ip = ip; this.port = port; this.listener = recvInterface; File file = new File(filePath); if (!file.exists()) { file.mkdir(); if (file.exists()) { LogUtil.d(TAG, "create dir ok!"); } } } private InetAddress servInetAddress; private DatagramSocket udpSocket ; private Thread mReceiveThread; private DatagramSocket udpSocketServ ; private final int BLOCK_SIZE = 1024 * 48; private byte[] udpRecvBuf = new byte[BLOCK_SIZE + 8]; private boolean hasFileInfo; private int blockIndex; private long blockCount; private byte cmdType; private byte fileFlag; private String savePath; private long askTime; private long startTime; CheckUdpReceveThread checkUdpReceveThread; public void tryGetMeetingFileInfo(int keyId){ try { servInetAddress = InetAddress.getByName(this.ip); if(udpSocket == null) { udpSocket = new DatagramSocket(); } if(udpSocketServ == null){ udpSocketServ = new DatagramSocket(15155); // 定义接收数据包 DatagramPacket packet = new DatagramPacket(udpRecvBuf, udpRecvBuf.length); } if(mReceiveThread == null){ mReceiveThread = new Thread(udpRecvThread); mReceiveThread.start(); } hasFileInfo = false; startTime = System.currentTimeMillis(); byte[] buffer = new byte[10]; buffer[0]= (byte)0xFE; buffer[1] = (byte)0xAA; buffer[2] = 0; buffer[3] = 1;//1 文件信息 buffer[4] =(byte) (keyId >> 8 & 0xff); buffer[5] =(byte) (keyId & 0xff); DatagramPacket packet = new DatagramPacket(buffer,buffer.length,servInetAddress,this.port); while(!hasFileInfo){ udpSocket.send(packet); Log.i(TAG, "tryGetMeetingFileInfo -----"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } catch (Exception e) { e.printStackTrace(); } } private void getFilePackage(int index){ if(udpSocket==null){ return; } byte[] buffer = new byte[10]; buffer[0]= (byte)0xFE; buffer[1] = (byte)0xAA; buffer[2] = fileFlag; buffer[3] = 2;// buffer[4] = (byte)(index & 0xff); buffer[5] = (byte)((index >> 8) & 0xff); DatagramPacket packet = new DatagramPacket(buffer,buffer.length,servInetAddress,this.port); askTime = System.currentTimeMillis(); for( int i= 0; i <3 ;i++){ try { udpSocket.send(packet); Log.i(TAG, "getFilePackage:"+index); Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } } } /* TDataPackeg = packed record HeadWord: array[0..1] of Byte; Flag: Byte; //下载批次编号,自动累加,主控控制 CmdType: TCmdType; //类型 1文件信息 2文件数据 3下载完成 BlockID: Word; //数据块序号 BufferLen: Word; //数据长度 Buffer: array of Byte; //数据区 依照DataType定义 end; */ // 线程类,该类使用匿名内部类的方式进行声明 Runnable udpRecvThread = new Runnable() { public void run() { Log.i(TAG,"执行 udpRecvThread"); try { DatagramPacket packet = new DatagramPacket(udpRecvBuf, udpRecvBuf.length); while (true) { // 接收数据 if(udpSocketServ==null){ return; } Log.d(TAG, "udpRecvThread: try receive"); udpSocketServ.receive(packet); if (packet.getLength() > 0) { LogUtil.i(TAG, "udpRecvThread recv udp "+ String.format("%x %x",udpRecvBuf[0] & 0xff,udpRecvBuf[1] & 0xff)); if((udpRecvBuf[0] & 0xff) == 0xFE && (udpRecvBuf[1] & 0xff) == 0xAA ){ fileFlag = (byte) (udpRecvBuf[2] & 0xff); //Log.d(TAG, "run: fileFlag:" + fileFlag); cmdType = udpRecvBuf[3]; if(cmdType == 1){ //文件信息 hasFileInfo = true; fileLen = ((udpRecvBuf[8] & 0xff) << 3*8) | ((udpRecvBuf[9] & 0xff) << 2*8) | ((udpRecvBuf[10] & 0xff) << 1*8) | (udpRecvBuf[11] & 0xff ) ; byte fileNameLen = udpRecvBuf[12]; byte[] namebuf = new byte[fileNameLen]; System.arraycopy(udpRecvBuf,13,namebuf,0,fileNameLen); fileName = new String(namebuf,"unicode"); LogUtil.d(TAG, "recvFileInfo len:"+ fileLen + " fileName:"+ fileName); savePath = filePath + "/" + fileName; File saveFile = new File(savePath); if (saveFile.exists()) { saveFile.delete(); } fileOut = new DataOutputStream( new BufferedOutputStream(new BufferedOutputStream(new FileOutputStream(savePath)))); blockCount = fileLen / BLOCK_SIZE ; if(fileLen % BLOCK_SIZE > 0) { blockCount ++; } LogUtil.i(TAG, "run: blockCount:"+ blockCount); blockIndex=0; getFilePackage(blockIndex); }else if(cmdType == 2){ //文件数据 LogUtil.e(TAG, "======: Time:" + (System.currentTimeMillis() - askTime )); int blockId = ((udpRecvBuf[4]&0xff) << 8 ) | (udpRecvBuf[5]&0xff); int dataLen = ((udpRecvBuf[6]&0xff) << 8 ) | (udpRecvBuf[7]&0xff); Log.i(TAG, "run: recv block:"+ blockId + " datalen:"+ dataLen); if(blockId == blockIndex){ blockIndex++; if(dataLen>0) { fileOut.write(udpRecvBuf,8,dataLen); passedlen = BLOCK_SIZE* (blockIndex-1) + dataLen ; long per = (passedlen * 100 /fileLen); listener.onDownload(per); LogUtil.i(TAG, "run: file recv "+ per + "%"); } if(blockIndex <= blockCount) {//多发一包确认包 getFilePackage(blockIndex); } } }else if(cmdType == 3) {//下载完成 LogUtil.i(TAG, "run: file recv done!"); LogUtil.e(TAG, "Total Time:" + (System.currentTimeMillis() - startTime )); fileOut.close(); String outDirName; try { if (fileName.endsWith(".zip")) { outDirName = fileName.substring(0, fileName.length() - 4); String uzipDirPath = filePath + "/" + outDirName; File unzipDir = new File(uzipDirPath); if (unzipDir.exists()) { try { LogUtil.d(TAG, "clear dir"); FileUtil.deleteFileInDir(unzipDir); }catch (Exception e){ LogUtil.e(TAG,e); } }else{ boolean ret=false; try { ret = unzipDir.mkdir(); } catch (Exception e){ LogUtil.e(TAG,e); } if(ret) { LogUtil.d(TAG, "createFile Ok, unzip!"); }else{ LogUtil.d(TAG,"createFile fail !"+ uzipDirPath); } } LogUtil.d(TAG, "unzip"); AntZipUtil.unZip(filePath + "/" + fileName, uzipDirPath); LogUtil.d(TAG, "unzip ok"); } listener.onDownloadSuccess(); } catch (Exception e) { LogUtil.d(TAG, "onUnzipError"); listener.onUnzipError(); LogUtil.e(TAG,e); }finally { closeUdpSocket(); LogUtil.i(TAG, "run: udpRecvThread over"); break; } } } } } } catch ( Exception e) { LogUtil.e(TAG,e); } } }; public void closeUdpSocket(){ try { udpSocket.close(); udpSocketServ.close(); udpSocket = null; udpSocketServ = null; }catch (Exception e){ LogUtil.e(TAG,e); } } public void tryGetMeetingFiles(int keyId) { keypadID = String.valueOf(keyId); if (createConnection()) { sendMessage(keyId + "\n"); lastReceveLength = 0; CheckReceveThread checkReceveThread = new CheckReceveThread(); checkReceveThread.start(); getMeetingFiles(); } } private class CheckUdpReceveThread extends Thread{ public void run() { while (true) { try { Thread.sleep(2000); if(lastReceveLength != passedlen ){ lastReceveLength = passedlen; //sendMessage(keypadID + ":recv"+lastReceveLength+"\n"); LogUtil.d(TAG,"CheckUdpReceveThread:check ok!"); compareCount = 0; }else{ compareCount ++; Log.i(TAG, "CheckUdpReceveThread: retry block:"+blockIndex); getFilePackage(blockIndex); if(compareCount == 600){ compareCount = 0; LogUtil.d(TAG,"CheckUdpReceveThread:60s no response ,fail!"); try { if(fileOut!=null) { fileOut.close(); } } catch (IOException e) { e.printStackTrace(); } closeUdpSocket(); //Thread.sleep(1000); listener.onDownloadDataError(); break; } } if (passedlen > 0 && passedlen == fileLen) { LogUtil.d(TAG,"CheckUdpReceveThread:success!"); break; } } catch (InterruptedException e) { e.printStackTrace(); } } } }; public long lastReceveLength; private int compareCount; private class CheckReceveThread extends Thread{ public void run() { while (true) { try { Thread.sleep(1000); if(lastReceveLength != passedlen ){ lastReceveLength = passedlen; //sendMessage(keypadID + ":recv"+lastReceveLength+"\n"); LogUtil.d(TAG,"CheckReceveThread:check ok!"); compareCount = 0; }else{ compareCount ++; if(compareCount == 60){ compareCount = 0; LogUtil.d(TAG,"CheckReceveThread:60s no response ,fail!"); shutDownConnection(); Thread.sleep(1000); listener.onDownloadDataError(); break; } } if (passedlen > 0 && passedlen == fileLen) { LogUtil.d(TAG,"CheckReceveThread:success!"); break; } } catch (InterruptedException e) { e.printStackTrace(); } } } }; public boolean createConnection() { for(int i=0;i<3 ;i++) { LogUtil.d(TAG, "try create socket"); try { socket = new Socket(ip, port); LogUtil.d(TAG, "create socket ok"); return true; } catch (Exception e) { listener.onConnectServerError(); e.printStackTrace(); if (socket != null) { try { socket.close(); } catch (Exception e1) { e1.printStackTrace(); } } } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } return false; } public void sendMessage(String sendMessage) { try { out = new DataOutputStream(socket.getOutputStream()); byte[] midbytes = sendMessage.getBytes("UTF8"); out.write(midbytes); // out.writeUTF(sendMessage); out.flush(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); if (out != null) { try { out.close(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } } public long passedlen = 0; public long fileLen = 0; private boolean userStop; DataInputStream inputStream = null; DataOutputStream fileOut; public void getMeetingFiles() { userStop = false; inputStream = getDataInStream(); try { String savePath = null; int bufferSize = 512000;// 8192 byte[] buf = new byte[bufferSize]; long tmpTime = System.currentTimeMillis(); String strln = null; while (strln == null) { strln = inputStream.readLine(); if (strln != null) { Log.d(TAG, strln); String[] ary = strln.split(","); if (ary.length == 2) { fileLen = Long.parseLong(ary[0]); fileName = ary[1]; savePath = filePath + "/" + fileName; break; } } if (System.currentTimeMillis() - tmpTime > 20 * 1000) { Log.e(TAG, "get file name and fileLen time out!"); break; } // strln = inputStream.readLine(); } if (savePath == null) { Log.e(TAG, "savePath==null"); listener.onConnectServerError(); return; } File saveFile = new File(savePath); if (saveFile.exists()) { saveFile.delete(); } // savePath += inputStream.readUTF(); // log.d("AndroidClient","@@@savePath"+savePath); fileOut = new DataOutputStream( new BufferedOutputStream(new BufferedOutputStream(new FileOutputStream(savePath)))); // len = inputStream.readLong(); // Log.d(TAG,"文件的长度为:"+len); if(checkUdpReceveThread==null) { checkUdpReceveThread = new CheckUdpReceveThread(); checkUdpReceveThread.start(); } Log.d(TAG, "start recv"); while (true) { if(userStop ){ Log.i(TAG, "getMeetingFiles: UserStop ,clear "); fileOut.close(); inputStream.close(); fileOut = null; inputStream = null; shutDownConnection(); listener.onDownloadUserStop(); return; } int read = 0; if (inputStream != null) { LogUtil.d(TAG, "inputStream.read"); read = inputStream.read(buf); LogUtil.d(TAG, "inputStream.read len:"+ read); } passedlen += read; if (read == -1) { break; } long per = passedlen * 100 / fileLen; Log.d(TAG, "file recv" + per + "%/n"); LogUtil.d(TAG, "file recv" + per + "%/n"); if (per < 0) { Log.d(TAG, "error"); } listener.onDownload(per); if(read>0) { fileOut.write(buf, 0, read); } if (passedlen == fileLen) { break; } } // Log.d("AndroidClient", "@@@文件接收完成" + savePath); Log.d(TAG, "recv file 100%"); fileOut.close(); String outDirName; try { if (fileName.endsWith(".zip")) { outDirName = fileName.substring(0, fileName.length() - 4); String uzipDirPath = filePath + "/" + outDirName; File unzipDir = new File(uzipDirPath); if (unzipDir.exists()) { try { LogUtil.d(TAG, "clear dir"); FileUtil.deleteFileInDir(unzipDir); }catch (Exception e){ e.printStackTrace(); } }else{ boolean ret=false; try { ret = unzipDir.mkdir(); } catch (Exception e){ e.printStackTrace(); } if(ret) { LogUtil.d(TAG, "createFile Ok, unzip!"); }else{ LogUtil.d(TAG,"createFile fail !"+ uzipDirPath); } } Log.d(TAG, "unzip"); AntZipUtil.unZip(filePath + "/" + fileName, uzipDirPath); Log.d(TAG, "unzip ok"); } } catch (Exception e) { e.printStackTrace(); } sendMessage(keypadID + ":success\n"); Log.d(TAG, "send success"); int answerTimes = 0; while (answerTimes < 30) { Log.d(TAG, "send success"); sendMessage(keypadID + ":success\n"); strln = inputStream.readLine(); if (strln != null) { Log.d(TAG, "=======recv:" + strln); if (strln.equals("success")) { Log.d(TAG, "recv server seccuss"); break; } } answerTimes++; try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (answerTimes == 30) { Log.d(TAG, "wait answer timeout"); } shutDownConnection();// 关掉socket连接 listener.onDownloadSuccess(); // UnZip.unzipFile(filePath+"/"+fileName , filePath+"/metting/"); } catch (IOException e) { e.printStackTrace(); } } public void cleanDownloadFiles(){ Log.i(TAG, "cleanDownloadFiles: "); userStop = true; } public DataInputStream getDataInStream() { try { getMessageStream = new DataInputStream(new BufferedInputStream(socket.getInputStream())); // return getMessageStream; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); if (getMessageStream != null) { try { getMessageStream.close(); } catch (IOException e1) { e1.printStackTrace(); } } } return getMessageStream; } public void shutDownConnection() { try { if (out != null) { out.close(); } if (getMessageStream != null) { getMessageStream.close(); } if (socket != null) { socket.close(); } } catch (IOException e) { e.printStackTrace(); } } }