package com.gh.gamecenter; import android.Manifest; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import com.facebook.drawee.view.SimpleDraweeView; import com.gh.base.AppController; import com.gh.base.BaseActivity; import com.gh.common.util.DialogUtils; import com.gh.common.util.UserIconUtils; import com.gh.common.util.Utils; import com.gh.gamecenter.adapter.FileSenderAdapter; import com.gh.gamecenter.kuaichuan.Constant; import com.gh.gamecenter.kuaichuan.FileInfo; import com.gh.gamecenter.kuaichuan.FileSender; import com.gh.gamecenter.kuaichuan.WifiMgr; import org.json.JSONObject; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import butterknife.BindView; import butterknife.OnClick; /** * Created by khy on 2017/1/20. */ public class FileSenderActivity extends BaseActivity implements FileSenderAdapter.OnCancelListener { @BindView(R.id.sender_rv) RecyclerView mSenderRv; @BindView(R.id.sender_user_icon) SimpleDraweeView mSenderUserIcon; @BindView(R.id.sender_user_name) TextView mSenderUserName; @BindView(R.id.sender_user_send_des) TextView mSenderUserDes; @BindView(R.id.sender_hint) TextView mSenderHint; @BindView(R.id.sender_keep_send) RelativeLayout mKeepSend; @BindView(R.id.sender_bottom) LinearLayout mSenderBottom; private FileSenderAdapter mSenderAdapter; private DatagramSocket mDatagramSocket; private List mFileInfos; private List> sendData; // 传送成绩单数据 private List mFileSenderList; private boolean isSendOver; private boolean isDestroy; private long mStartTime; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what == FileInfo.FLAG_DEFAULT) { int position = (int) msg.obj; mFileInfos.get(position).setResult(FileInfo.FLAG_DEFAULT); mSenderAdapter.notifyItemChanged(position); } else if (msg.what == FileInfo.FLAG_SUCCESS) { int position = (int) msg.obj; mFileInfos.get(position).setResult(FileInfo.FLAG_SUCCESS); mSenderAdapter.notifyItemChanged(position); if (position == mFileInfos.size() -1) initSenderHint(); } else if (msg.what == FileInfo.FLAG_FAILURE) { int position = (int) msg.obj; mFileInfos.get(position).setResult(FileInfo.FLAG_FAILURE); mSenderAdapter.notifyItemChanged(position); if (position == mFileInfos.size() -1) initSenderHint(); } else if (msg.what == FileInfo.FLAG_CANCEL) { int position = (int) msg.obj; mFileInfos.get(position).setResult(FileInfo.FLAG_CANCEL); mSenderAdapter.notifyItemChanged(position); if (position == mFileInfos.size() -1) initSenderHint(); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); View contentView = View.inflate(this, R.layout.activity_file_sender, null); init(contentView, "发送游戏"); mFileInfos = (List) AppController.get("FileInfo", false); isDestroy = false; sendData = new ArrayList<>(); mFileSenderList = new ArrayList<>(); mSenderAdapter = new FileSenderAdapter(this, mFileInfos); mSenderRv.setLayoutManager(new LinearLayoutManager(this)); mSenderRv.setAdapter(mSenderAdapter); init(); findViewById(R.id.actionbar_rl_back).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { backHint(); } }); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == 0x130 && requestCode == 0x178) { mSenderAdapter.notifyDataSetChanged(); initUserData(); new Thread(new Runnable() { @Override public void run() { try { sendFileInfo(); } catch (Exception e) { e.printStackTrace(); } } }).start(); } } private void sendFileInfo() throws Exception { if (mDatagramSocket == null) { mDatagramSocket = new DatagramSocket(null); mDatagramSocket.setReuseAddress(true); mDatagramSocket.bind(new InetSocketAddress(Constant.DEFAULT_SERVER_SENDING_PORT)); } String ipAddress = WifiMgr.getInstance(this).getIpAddressFromHotspot(); InetAddress ipAddressName = InetAddress.getByName(ipAddress); // 转译 //发送apk列表 for (FileInfo fileInfo : mFileInfos) { if (fileInfo.getResult() == 0) { // 过滤已发送过的列表 String fileInfoJson = FileInfo.toJsonStr(fileInfo); Utils.log("FileSenderActivity:: 发送的文件列表::" + fileInfoJson ); DatagramPacket sendFileInfoListPacket = new DatagramPacket(fileInfoJson.getBytes() , fileInfoJson.getBytes().length, ipAddressName, Constant.DEFAULT_SERVER_SENDING_PORT); mDatagramSocket.send(sendFileInfoListPacket); Utils.log("FileSenderActivity:: 发送的文件列表完成::" + ipAddressName + "==" + Constant.DEFAULT_SERVER_SENDING_PORT); } } DatagramPacket sendFileInfoListPacket = new DatagramPacket(Constant.MSG_ADD_DATA_OVER.getBytes() , Constant.MSG_ADD_DATA_OVER.getBytes().length, ipAddressName, Constant.DEFAULT_SERVER_SENDING_PORT); mDatagramSocket.send(sendFileInfoListPacket); Utils.log("FileSenderActivity:: 发送结束请求完成"); } private void init() { Utils.log("FileSenderActivity == init()"); initUserData(); if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, Constant.REQUEST_CODE_WRITE_FILE); } else{ Utils.log("FileSenderActivity == initSendServer()" + mFileInfos.size()); try { initSendServer();//开启传送文件 startReceiver(); } catch (Exception e) { e.printStackTrace(); } } } private void startReceiver() { new Thread(new Runnable() { @Override public void run() { try { initTestReceiverData(); } catch (Exception e) { e.printStackTrace(); } } }).start(); } private void initTestReceiverData() throws Exception { if (mDatagramSocket == null) { mDatagramSocket = new DatagramSocket(null); mDatagramSocket.setReuseAddress(true); mDatagramSocket.bind(new InetSocketAddress(Constant.DEFAULT_SERVER_SENDING_PORT)); } Utils.log("接收方取消Socket端口" + Constant.DEFAULT_SERVER_SENDING_PORT); byte[] receiveData = new byte[1024]; // 主要接收 接收方取消操作 while (!isDestroy) { DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); mDatagramSocket.receive(receivePacket); String response = new String( receivePacket.getData(),0 , receivePacket.getLength()).trim(); Utils.log("====接收取消消息中。。。" + response); if(response != null && response.contains(Constant.MSG_RECEIVER_CANCEL)){ Utils.log("====接收取消消息完毕。。。" + response); // 进入文件发送列表界面 (并且通知文件接收方进入文件接收列表界面) JSONObject jsonObject = new JSONObject(response); int cancelPosition = (int) jsonObject.get("controlTag"); FileSender fileSender = mFileSenderList.get(cancelPosition); Message message = new Message(); message.what = FileInfo.FLAG_CANCEL; message.obj = cancelPosition; handler.sendMessage(message); if (fileSender != null && fileSender.isRunning()) { Utils.log("接收方取消发送"); fileSender.cancel(); } } else if (response != null && response.contains(Constant.MSG_ADD_DATA_OVER)) { try { Utils.log("====收到UDP结束请求 开始传送文件"); initSendServer();//开启传送文件 } catch (Exception e) { e.printStackTrace(); } } } } //初始化用户数据 private void initUserData() { isSendOver = false; Map map = (Map) AppController.get("userMap", false); long allGameSize = 0; for (FileInfo mFileInfo : mFileInfos) { allGameSize = allGameSize + mFileInfo.getSize(); } double size = (((float)allGameSize/1024)/1024); DecimalFormat df = new DecimalFormat("#.00"); String sizeName = df.format(size) + "MB"; mSenderUserDes.setText(mFileInfos.size() + "个游戏,共" + sizeName); mSenderUserName.setText("发给 " + map.get("receiverName")); mSenderUserIcon.setImageURI(UserIconUtils.getUserIcon(Integer.parseInt(map.get("usericon")))); mSenderBottom.setVisibility(View.GONE); mSenderHint.setText("已连接"); } private void initSendServer() throws Exception { String serverIp = WifiMgr.getInstance(this).getIpAddressFromHotspot(); Utils.log("====FileSenderActivity传送个数::" + mFileInfos.size()); // TODO: 发送的首个游戏 socket被拒绝的概率较大 延迟0.5秒发送试试 Thread.sleep(500); //test for (final FileInfo fileInfo : mFileInfos) { Utils.log("FileSenderActivity == initSendServer()===" + fileInfo.getName() + "==" + fileInfo.getResult()); if (fileInfo.getResult() != 0) continue; // result != 0 是已经传送过的apk FileSender fileSender = new FileSender(this, fileInfo, serverIp, Constant.DEFAULT_SERVER_PORT); fileSender.setOnSendListener(new FileSender.OnSendListener() { @Override public void onStart() { mStartTime = System.currentTimeMillis(); Utils.log("快传文件发送::onStart" + "==" + fileInfo.getName()); } @Override public void onProgress(long progress, long total) { // Utils.log("快传文件发送中..." + progress + "==" + total + "==" + fileInfo.getName()); fileInfo.setProgress(progress); Message message = new Message(); message.what = FileInfo.FLAG_DEFAULT; message.obj = getCurrentFileInfoIndex(fileInfo); handler.sendMessage(message); } @Override public void onSuccess(FileInfo fileInfo) { Utils.log("快传文件发送成功::onSuccess" + "==" + fileInfo.getName()); Message message = new Message(); message.what = FileInfo.FLAG_SUCCESS; message.obj = getCurrentFileInfoIndex(fileInfo); handler.sendMessage(message); long sendTime = System.currentTimeMillis() - mStartTime; Map map = new HashMap<>(); map.put("sendTime", String.valueOf(sendTime)); map.put("apkPath", fileInfo.getFilePath()); map.put("apkSize", String.valueOf(fileInfo.getSize())); sendData.add(map); } @Override public void onFailure(Throwable t, FileInfo fileInfo) { Utils.log("快传文件发送失败::onFailure" + "==" + fileInfo.getName()); Message message = new Message(); message.what = FileInfo.FLAG_FAILURE; message.obj = getCurrentFileInfoIndex(fileInfo); handler.sendMessage(message); } @Override public void onCancel(FileInfo fileInfo) { Utils.log("快传文件用户主动取消::onCancel" + "==" + fileInfo.getName()); Message message = new Message(); message.what = FileInfo.FLAG_CANCEL; message.obj = getCurrentFileInfoIndex(fileInfo); handler.sendMessage(message); } }); mFileSenderList.add(fileSender); AppController.FILE_SENDER_EXECUTOR.execute(fileSender); } } private int getCurrentFileInfoIndex(FileInfo curFileInfo) { for (int i = 0; i < mFileInfos.size(); i++) { FileInfo fileInfo = mFileInfos.get(i); if (curFileInfo == null) { return -100; } if (fileInfo.getFileTag().equals(curFileInfo.getFileTag())) { Utils.log("FileSenderActivity === index::" + i); return i; } } Utils.log("FileReceiverActivity:: 获取刷新位置异常"); return -1; } private void initSenderHint(){ for (FileInfo mFileInfo : mFileInfos) { if (mFileInfo.getResult() == 0 || mFileInfo.getResult() == 1) { // 还有没完成的任务 return; } } mSenderBottom.setVisibility(View.VISIBLE); int sendSuccess = 0; isSendOver = true; for (FileInfo mFileInfo : mFileInfos) { if (mFileInfo.getResult() == FileInfo.FLAG_SUCCESS) { sendSuccess ++; } } if (sendSuccess > 0) { mSenderHint.setVisibility(View.VISIBLE); mSenderHint.setText("传输结束,成功分享" + sendSuccess + "个游戏"); } else { if (mFileInfos.get(mFileInfos.size() - 1).getResult() == FileInfo.FLAG_CANCEL) { mSenderHint.setVisibility(View.VISIBLE); mSenderHint.setText("传输已取消"); } else if (mFileInfos.get(mFileInfos.size() - 1).getResult() == FileInfo.FLAG_FAILURE) { mSenderHint.setVisibility(View.VISIBLE); mSenderHint.setText("传输失败"); } } } @Override public void OnCancelPosition(int position) { FileSender fileSender = mFileSenderList.get(position); Utils.log("发送方准备取消发送" + position); if (fileSender != null && fileSender.isRunning()) { Utils.log("发送方取消发送"); fileSender.cancel(); } } @Override public void onBackPressed() { backHint(); } @Override protected void onDestroy() { super.onDestroy(); isDestroy = true; } @OnClick({R.id.actionbar_rl_back, R.id.sender_keep_send, R.id.sender_back}) public void onClick(View view) { if (view.getId() == R.id.actionbar_rl_back || view.getId() == R.id.sender_back) { backHint(); } else if (view.getId() == R.id.sender_keep_send) { Intent intent = new Intent(this, KcSelectGameActivity.class); intent.putExtra("isConn", true); startActivityForResult(intent, 0x178); } } /** * 停止所有的文件发送任务 */ private void stopAllFileSendingTask(){ for(FileSender fileSender : mFileSenderList){ if(fileSender != null){ fileSender.cancel(); fileSender.finish(); } } } public void colsePage() { if(mDatagramSocket != null) { // mDatagramSocket.disconnect(); mDatagramSocket.close(); mDatagramSocket = null; } stopAllFileSendingTask(); AppController.remove("FileInfo"); AppController.put("sendData", sendData); FileSenderActivity.this.finish(); } private void backHint() { if(!isSendOver){ DialogUtils.showWarningDialog(FileSenderActivity.this, "退出传送", "退出会中断所有游戏的传送,确定要退出吗?" , "取消", "确定" , new DialogUtils.ConfiremListener() { @Override public void onConfirem() { colsePage(); } }, null); } else { colsePage(); } } }