package com.gh.gamecenter; import android.Manifest; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.os.Parcelable; 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.text.TextUtils; 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.constant.Config; import com.gh.common.util.DialogUtils; import com.gh.common.util.NotificationUtils; import com.gh.common.util.PackageUtils; import com.gh.common.util.UserIconUtils; import com.gh.common.util.Utils; import com.gh.download.DownloadDao; import com.gh.download.DownloadEntity; import com.gh.download.DownloadStatus; import com.gh.gamecenter.adapter.FileReceiverAdapter; import com.gh.gamecenter.eventbus.EBDownloadChanged; import com.gh.gamecenter.eventbus.EBDownloadStatus; import com.gh.gamecenter.eventbus.EBPackage; import com.gh.gamecenter.kuaichuan.BaseTransfer; import com.gh.gamecenter.kuaichuan.Constant; import com.gh.gamecenter.kuaichuan.FileInfo; import com.gh.gamecenter.kuaichuan.FileReceiver; import com.gh.gamecenter.kuaichuan.HotspotManager; import com.gh.gamecenter.kuaichuan.IpPortInfo; import com.gh.gamecenter.kuaichuan.WifiMgr; import com.gh.gamecenter.manager.DataCollectionManager; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.ServerSocket; import java.net.Socket; 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; import de.greenrobot.event.EventBus; /** * Created by khy on 2017/1/20. */ public class FileReceiverActivity extends BaseActivity implements FileReceiverAdapter.OnReceiverCancelListener{ @BindView(R.id.sender_rv) RecyclerView mReceiverRv; @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_bottom) LinearLayout mReceiverBottom; @BindView(R.id.sender_keep_send) RelativeLayout mKeepReceiver; @BindView(R.id.sender_keep_send_tv) TextView mKeepReceiverTv; @BindView(R.id.sender_bottom_hint) TextView mReceiverBottomHint; @BindView(R.id.sender_bottom_control) LinearLayout mReceiverControl; private FileReceiverAdapter mFileReceiverAdapter; private FileInfo mCurFileInfo; private List mFileInfos; private List> sendData; // 传送成绩单数据 private IpPortInfo mIpPortInfo; private ServerRunnable mReceiverServer; private FileReceiver mFileReceiver; private DatagramSocket mDatagramSocket; private SharedPreferences sp; private boolean isReceivesOver; private boolean isOpenWifi; //记录开热点前的WiFi状态 private boolean isDestroy; Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (mFileInfos == null) { Utils.log("接收器出现异常"); return; } int index = getCurrentFileInfoIndex(); if (index == -100) { Utils.toast(FileReceiverActivity.this, "接收失败"); colsePage(); return; } if (index == -1) { // Utils.toast(FileReceiverActivity.this, " 获取刷新位置异常"); return; } FileInfo fileInfo = mFileInfos.get(index); if (msg.what == FileInfo.FLAG_DEFAULT) { // 传输中更新界面 long progress = (long) msg.obj; fileInfo.setProgress(progress); fileInfo.setResult(FileInfo.FLAG_DEFAULT); } else if (msg.what == FileInfo.FLAG_SUCCESS) { // 传输成功更新界面 fileInfo.setResult(FileInfo.FLAG_SUCCESS); if (index == mFileInfos.size() -1) initSenderHint(false); } else if (msg.what == FileInfo.FLAG_FAILURE) { // 传输失败更新界面 fileInfo.setResult(FileInfo.FLAG_FAILURE); if (index == mFileInfos.size() -1) initSenderHint(false); } else if (msg.what == FileInfo.FLAG_CANCEL) { // 传输取消更新界面 fileInfo.setResult(FileInfo.FLAG_CANCEL); if (index == mFileInfos.size() -1) initSenderHint(false); } else if (msg.what == FileInfo.FLAG_NO_MEMORY) { Utils.toast(FileReceiverActivity.this, "手机空间不足"); fileInfo.setResult(FileInfo.FLAG_NO_MEMORY); // 接收方内存不足 if (index == mFileInfos.size() -1) initSenderHint(true); } Utils.log("FileReceiverActivity:: 刷新位置::" + index + "刷新状态::" + msg.what); mFileReceiverAdapter.notifyItemChanged(index); } }; private int getCurrentFileInfoIndex() { for (int i = 0; i < mFileInfos.size(); i++) { FileInfo fileInfo = mFileInfos.get(i); if (mCurFileInfo == null) { return -100; } if (fileInfo.getFileTag().equals(mCurFileInfo.getFileTag())) { return i; } } Utils.log("FileReceiverActivity:: 获取刷新位置异常" + mFileInfos.size()); mFileInfos.add(mCurFileInfo); return mFileInfos.size() - 1; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); View contentView = View.inflate(this, R.layout.activity_file_sender, null); init(contentView, "接收游戏"); isDestroy = false; // mFileInfos = (List) AppController.get("FileInfo", false); sendData = new ArrayList<>(); mIpPortInfo = (IpPortInfo) getIntent().getSerializableExtra(Constant.KEY_IP_PORT_INFO); isOpenWifi = getIntent().getBooleanExtra("isOpenWifi", false); ArrayList list = getIntent().getParcelableArrayListExtra(Constant.KEY_IP_FILE_INFO); mFileInfos = (List) list.get(0); mFileReceiverAdapter = new FileReceiverAdapter(this, mFileInfos); mReceiverRv.setLayoutManager(new LinearLayoutManager(this)); mReceiverRv.setAdapter(mFileReceiverAdapter); mKeepReceiverTv.setText("继续接收"); sp = getSharedPreferences(Config.PREFERENCE, Context.MODE_PRIVATE); initUserData(); if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 200); } else { initServer(); //启动接收服务 } findViewById(R.id.actionbar_rl_back).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { backHint(); } }); } private void initUserData() { isReceivesOver = 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("来自 " + mIpPortInfo.getSenderName()); mSenderUserIcon.setImageURI(UserIconUtils.getUserIcon(mIpPortInfo.getSenderIcon())); mReceiverBottom.setVisibility(View.GONE); mSenderHint.setText("已连接"); } /** * 开启文件接收端服务 */ private void initServer() { mReceiverServer = new ServerRunnable(Constant.DEFAULT_SERVER_PORT); new Thread(mReceiverServer).start(); new Thread(new Runnable() { @Override public void run() { try { receiverData(); } catch (Exception e) { Utils.log("FileReceiverActivity:: UDP请求异常" + e.toString() ); e.printStackTrace(); } } }).start(); } private void receiverData() throws Exception { if (mDatagramSocket == null) { mDatagramSocket = new DatagramSocket(Constant.DEFAULT_SERVER_SENDING_PORT); mDatagramSocket.setBroadcast(true); } byte[] receiveData = new byte[1024]; Utils.log("FileReceiverActivity:: 开始接收UDP请求::" + Constant.DEFAULT_SERVER_SENDING_PORT + "::" +mDatagramSocket.getInetAddress()); while (!isDestroy) { Utils.log("FileReceiverActivity:: 开始接收UDP请求" ); DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); mDatagramSocket.receive(receivePacket); String response = new String(receivePacket.getData(), 0, receivePacket.getLength()).trim(); Utils.log("FileReceiverActivity:: 接收UDP请求" + response); if (response != null && response.equals(Constant.MSG_ADD_DATA_OVER)) { handler.post(new Runnable() { @Override public void run() { mFileReceiverAdapter.update(); initUserData(); } }); sendMessageToSender(Constant.MSG_ADD_DATA_OVER); Utils.log("FileReceiverActivity:: 回复信息" + Constant.MSG_ADD_DATA_OVER); } else if (response != null) { parseFileInfo(response); } } } /** * 解析FileInfo * @param msg */ private void parseFileInfo(String msg) { // mFileInfos = (List) AppController.get("FileInfo", false); // mFileInfos 数据异常 需要重新获取 FileInfo fileInfo = FileInfo.toObject(msg); if(fileInfo != null && fileInfo.getFilePath() != null){ mFileInfos.add(fileInfo); Utils.log("FileReceiverActivity 添加一条数据::" + msg); // AppController.put("FileInfo", mFileInfos); } } @Override public void OnCancelPosition(final int position) { // if (position == getCurrentFileInfoIndex()) { // mFileReceiver.cancel(); // } else { // Utils.toast(this, "在传送中的游戏才可以取消"); // } Utils.log("接收方发送取消消息 让发送方取消"); try { // 接收方更改界面 FileInfo fileInfo = mFileInfos.get(position); fileInfo.setResult(FileInfo.FLAG_CANCEL); mFileReceiverAdapter.notifyItemChanged(position); // 发消息让发送方取消 JSONObject jsonObject = new JSONObject(); jsonObject.put("controlStatus", Constant.MSG_RECEIVER_CANCEL); jsonObject.put("controlTag", position); sendMessageToSender(jsonObject.toString()); } catch (Exception e) { e.printStackTrace(); } } //安装事件 public void onEventMainThread(EBPackage busFour) { if ("安装".equals(busFour.getType())) { for (int i = 0; i < mFileInfos.size(); i++) { FileInfo fileInfo = mFileInfos.get(i); if (fileInfo.getResult() == FileInfo.FLAG_SUCCESS && fileInfo.getPackageName().equals(busFour.getPackageName())) { fileInfo.setResult(FileInfo.FLAG_INSTALLED); mFileReceiverAdapter.notifyItemChanged(i); } } } } private void sendMessageToSender(final String sendData) throws Exception { new Thread(new Runnable() { @Override public void run() { try { byte[] bytes = sendData.getBytes(BaseTransfer.UTF_8); DatagramPacket sendPacket = new DatagramPacket(bytes, bytes.length, mIpPortInfo.getInetAddress(), Constant.DEFAULT_SERVER_SENDING_PORT); mDatagramSocket.send(sendPacket); Utils.log("接收方消息已发送至接收方:" + sendData + "==" + mIpPortInfo.getInetAddress() + "==" + Constant.DEFAULT_SERVER_SENDING_PORT); } catch (Exception e) { Utils.log("接收方发送消息异常。。" + e.toString()); e.printStackTrace(); } } }).start(); } /** * ServerSocket启动线程 */ class ServerRunnable implements Runnable { ServerSocket serverSocket; private int port; public ServerRunnable(int port) { this.port = port; } @Override public void run() { Utils.log("接收线程:Socket已经开启"); try { serverSocket = new ServerSocket(Constant.DEFAULT_SERVER_PORT); while (!Thread.currentThread().isInterrupted()){ Socket socket = serverSocket.accept(); mFileReceiver = new FileReceiver(socket, FileReceiverActivity.this); mFileReceiver.setOnReceiveListener(new FileReceiver.OnReceiveListener() { private long mStartTime; private long mNormalStartTime; @Override public void onStart() { Utils.log("快传文件接收::onStart"); mStartTime = Utils.getTime(FileReceiverActivity.this); mNormalStartTime = System.currentTimeMillis(); } @Override public void onGetFileInfo(FileInfo fileInfo) { // 获取FileInfo mCurFileInfo = fileInfo; for (int i = 0; i < mFileInfos.size(); i++) { FileInfo info = mFileInfos.get(i); if (info.getName(). //NullPointerException equals(mCurFileInfo.getName())) { info.setBitmap(fileInfo.getBitmap()); } } } @Override public void onProgress(long progress, long total) { // 获取传输进度 // Utils.log("快传文件接收中..." + progress + "==" + total); Message message = new Message(); message.what = FileInfo.FLAG_DEFAULT; message.obj = progress; handler.sendMessage(message); } @Override public void onSuccess() { // 获取传输成功 handler.sendEmptyMessage(FileInfo.FLAG_SUCCESS); String ghVersion = (String) PackageUtils.getMetaData(FileReceiverActivity.this , mCurFileInfo.getPackageName(), "gh_version"); if (TextUtils.isEmpty(ghVersion)) { ghVersion = ""; } long sendTime = Utils.getTime(FileReceiverActivity.this) - mStartTime; Map hashMap = new HashMap<>(); hashMap.put("send_time", mStartTime); hashMap.put("receive_time", Utils.getTime(FileReceiverActivity.this)); hashMap.put("game_name", mCurFileInfo.getName()); hashMap.put("package_name", mCurFileInfo.getPackageName()); hashMap.put("package_size", mCurFileInfo.getSize()); hashMap.put("expend_time", sendTime); hashMap.put("send_nickname", mIpPortInfo.getSenderName()); hashMap.put("receive_nickname", mIpPortInfo.getReceiverName()); hashMap.put("receive_token", sp.getString("token", null)); hashMap.put("package_gh_version", ghVersion); DataCollectionManager.onEvent(FileReceiverActivity.this, "transfer", hashMap, false); Utils.log("快传文件接收成功::onSuccess:: 发送事件::" + sendTime); long sendNormalTime = System.currentTimeMillis() - mNormalStartTime; Map map = new HashMap<>(); map.put("sendTime", String.valueOf(sendNormalTime)); map.put("apkPath",Environment.getExternalStorageDirectory() + "/GH-KC/" + mCurFileInfo.getName() + ".apk"); map.put("apkSize", String.valueOf(mCurFileInfo.getSize())); sendData.add(map); NotificationUtils.showKuaiChuanDoneNotification(FileReceiverActivity.this, Environment.getExternalStorageDirectory() + "/GH-KC/" + mCurFileInfo.getName() + ".apk", mCurFileInfo.getName(), mCurFileInfo.getPackageName()); } @Override public void onFailure(Throwable t) { // 获取传输失败 Utils.log("快传文件接收失败::onFailure"); handler.sendEmptyMessage(FileInfo.FLAG_FAILURE); } @Override public void onCancel() { // 获取传输取消 Utils.log("快传文件接收取消::onCancel"); handler.sendEmptyMessage(FileInfo.FLAG_CANCEL); } @Override public void onNoMemory() { handler.sendEmptyMessage(FileInfo.FLAG_NO_MEMORY); } }); AppController.MAIN_EXECUTOR.execute(mFileReceiver); } } catch (IOException e) { e.printStackTrace(); } } /** * 关闭Socket 通信 */ public void close(){ if(serverSocket != null){ try { serverSocket.close(); serverSocket = null; } catch (IOException e) { } } } } private void initSenderHint(boolean isNoMemory) { for (FileInfo mFileInfo : mFileInfos) { if (mFileInfo.getResult() == 0 || mFileInfo.getResult() == 1) { // 还有没完成的任务 return; } } mReceiverBottom.setVisibility(View.VISIBLE); mReceiverControl.setVisibility(View.VISIBLE); isReceivesOver = true; int sendSuccess = 0; for (FileInfo mFileInfo : mFileInfos) { if (mFileInfo.getResult() == FileInfo.FLAG_SUCCESS) { sendSuccess ++; } } if (isNoMemory) { mKeepReceiverTv.setText("手机空间清理"); } 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 onBackPressed() { backHint(); } @Override protected void onDestroy() { super.onDestroy(); isDestroy = true; handler.removeCallbacksAndMessages(null); } @OnClick({R.id.actionbar_rl_back, R.id.sender_keep_send, R.id.sender_back}) public void back(View view) { switch (view.getId()) { case R.id.actionbar_rl_back: backHint(); break; case R.id.sender_back: backHint(); break; case R.id.sender_keep_send: if ("继续接收".equals(mKeepReceiverTv.getText())) { // mReceiverControl.setVisibility(View.GONE); mKeepReceiverTv.setBackgroundResource(R.drawable.game_item_btn_pause_style); Utils.toast(FileReceiverActivity.this, "无需操作,请让对方继续发送即可"); } else { // 跳转安装包清理 Intent intent = new Intent(this, CleanApkActivity.class); startActivity(intent); } break; } } private void colsePage() { if(mDatagramSocket != null) { // mDatagramSocket.disconnect(); mDatagramSocket.close(); mDatagramSocket = null; } //关闭热点 HotspotManager.initUserAp(getApplicationContext()); if (isOpenWifi) { WifiMgr.getInstance(this).openWifi(); } for (FileInfo fileInfo : mFileInfos) { if (fileInfo.getResult() == FileInfo.FLAG_SUCCESS) { DownloadEntity entry = new DownloadEntity(); entry.setName(fileInfo.getName()); entry.setSize(fileInfo.getSize()); entry.setPackageName(fileInfo.getPackageName()); entry.setPath(Environment.getExternalStorageDirectory() + "/GH-KC/" + fileInfo.getName() + ".apk"); entry.setPercent(100.0); entry.setUrl(fileInfo.getFilePath()); //url拿 路径替代 entry.setStatus(DownloadStatus.done); JSONObject jsonObject = new JSONObject(); try { jsonObject.put("KuaiChuanIcon", Environment.getExternalStorageDirectory() + "/GH-KC/" + fileInfo.getName() + ".apk"); } catch (JSONException e) { e.printStackTrace(); } entry.setIcon(jsonObject.toString()); DownloadDao.getInstance(this).newOrUpdate(entry); } } List all = DownloadDao.getInstance(this).getAll(); EventBus.getDefault().post(new EBDownloadChanged("download", View.VISIBLE, all.size())); EventBus.getDefault().post(new EBDownloadStatus("download")); mReceiverServer.close(); // AppController.remove("FileInfo"); mFileInfos.clear(); AppController.put("sendData", sendData); finish(); } private void backHint() { if (isReceivesOver) { colsePage(); } else { DialogUtils.showWarningDialog(FileReceiverActivity.this, "退出提示", "退出会中断接收,确定要退出吗?" , "取消", "确定" , new DialogUtils.ConfiremListener() { @Override public void onConfirem() { colsePage(); } }, null); } } }