diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 446797f758..8d4dace2a8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -170,6 +170,24 @@ + + + + + + diff --git a/app/src/main/assets/Home.html b/app/src/main/assets/Home.html index b8d3890cf8..16b49ea0f1 100644 --- a/app/src/main/assets/Home.html +++ b/app/src/main/assets/Home.html @@ -59,7 +59,7 @@ article {

光环助手

乐于分享的人
是最帅(美)的^_^

diff --git a/app/src/main/java/com/gh/common/util/BitmapUtils.java b/app/src/main/java/com/gh/common/util/BitmapUtils.java index 3c16288b34..7c0ebb795b 100644 --- a/app/src/main/java/com/gh/common/util/BitmapUtils.java +++ b/app/src/main/java/com/gh/common/util/BitmapUtils.java @@ -2,7 +2,10 @@ package com.gh.common.util; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.Canvas; import android.graphics.Matrix; +import android.graphics.PixelFormat; +import android.graphics.drawable.Drawable; import android.media.ExifInterface; import java.io.IOException; @@ -84,4 +87,30 @@ public class BitmapUtils { } } + /** + * Drawable转Bitmap + * + */ + public static Bitmap drawableToBitmap(Drawable drawable){ + if(drawable == null){ + return null; + } + + // 取 drawable 的长宽 + int w = drawable.getIntrinsicWidth(); + int h = drawable.getIntrinsicHeight(); + // 取 drawable 的颜色格式 + Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 + : Bitmap.Config.RGB_565; + //建立对应的Bitmap + Bitmap bitmap = Bitmap.createBitmap(w, h, config); + // 建立对应 bitmap 的画布 + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, w, h); + // 把 drawable 内容画到画布中 + drawable.draw(canvas); + + return bitmap; + } + } diff --git a/app/src/main/java/com/gh/download/DownloadManager.java b/app/src/main/java/com/gh/download/DownloadManager.java index 09a49426c3..6ed8d08a51 100644 --- a/app/src/main/java/com/gh/download/DownloadManager.java +++ b/app/src/main/java/com/gh/download/DownloadManager.java @@ -220,6 +220,7 @@ public class DownloadManager { String entrance, String location) { + Utils.log("========www==" + android.os.Build.MANUFACTURER); // 安装指引 if (android.os.Build.MANUFACTURER.equalsIgnoreCase("Huawei") || "Oppo".equalsIgnoreCase(android.os.Build.MANUFACTURER)) { SharedPreferences sp = context.getSharedPreferences(Config.PREFERENCE, Context.MODE_PRIVATE); diff --git a/app/src/main/java/com/gh/gamecenter/ChooseReceiverActivity.java b/app/src/main/java/com/gh/gamecenter/ChooseReceiverActivity.java new file mode 100644 index 0000000000..a5c512ba9e --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/ChooseReceiverActivity.java @@ -0,0 +1,363 @@ +package com.gh.gamecenter; + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.net.wifi.ScanResult; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.text.Html; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.facebook.drawee.backends.pipeline.Fresco; +import com.facebook.drawee.interfaces.DraweeController; +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.Utils; +import com.gh.gamecenter.kuaichuan.BaseTransfer; +import com.gh.gamecenter.kuaichuan.Constant; +import com.gh.gamecenter.kuaichuan.FileInfo; +import com.gh.gamecenter.kuaichuan.HotspotManager; +import com.gh.gamecenter.kuaichuan.WifiMgr; +import com.gh.gamecenter.kuaichuan.WifiUtils; +import com.gh.gamecenter.manager.SystemBarTintManager; + +import org.json.JSONObject; + +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.util.List; + +import butterknife.BindView; +import butterknife.OnClick; + +/** + * Created by khy on 2017/1/20. + */ +public class ChooseReceiverActivity extends BaseActivity implements View.OnClickListener{ + + @BindView(R.id.choosereceiver_user1_name) TextView choosereceiver_user1_name; + @BindView(R.id.choosereceiver_user2_name) TextView choosereceiver_user2_name; + @BindView(R.id.choosereceiver_user3_name) TextView choosereceiver_user3_name; + @BindView(R.id.choosereceiver_user4_name) TextView choosereceiver_user4_name; + @BindView(R.id.choosereceiver_user1) LinearLayout choosereceiver_user1; + @BindView(R.id.choosereceiver_user2) LinearLayout choosereceiver_user2; + @BindView(R.id.choosereceiver_user3) LinearLayout choosereceiver_user3; + @BindView(R.id.choosereceiver_user4) LinearLayout choosereceiver_user4; + @BindView(R.id.scan_gif) SimpleDraweeView mScanGif; + @BindView(R.id.scan_user) TextView mScanUser; + @BindView(R.id.scan_user_des) TextView mScanUserDes; + @BindView(R.id.reuse_actionbar) RelativeLayout mActionbar; + @BindView(R.id.scan_hint) TextView mScanHint; + + private List mScanResultList; + + private DatagramSocket mDatagramSocket; + + private boolean isStopScan; + + private boolean isConnSuccess; + + private SharedPreferences sp; + + Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + if (msg.what == 0 && !isStopScan) { + updateWifiScanResult(); + handler.sendEmptyMessageDelayed(0, 2000); + } + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View contentView = View.inflate(this, R.layout.activity_choosereceiver, null); + init(contentView, "发送游戏"); + + //修改沉浸栏以及ActionBar 颜色 + mActionbar.setBackgroundColor(getResources().getColor(R.color.scan_bg)); + SystemBarTintManager tintManager = getTintManager(); + if (tintManager != null) { + tintManager.setStatusBarTintResource(R.color.scan_bg); + } + + init(); + } + + @OnClick(R.id.scan_hint) + public void onScanHintListener() { + DialogUtils.showHintDialog(this, "对方操作步骤", "1.掏出手机,打开光环助手 " + + "\n2.在首页点击左上角,进去下载管理 \n3.点击“零流量传送”,在点击“我要接收”", + "确定"); + } + + private void init() { + sp = getSharedPreferences(Config.PREFERENCE, Context.MODE_PRIVATE); + + DraweeController controller = Fresco.newDraweeControllerBuilder() + .setUri("res:///" + R.drawable.scan_receiver) + .setAutoPlayAnimations(true) + .build(); + mScanGif.setController(controller); + + mScanHint.setText(Html.fromHtml(""+"搜不到对方?"+"")); + + isStopScan = false; + isConnSuccess = false; + + if (HotspotManager.isApOn(this)) { + HotspotManager.disableAp(this); + } + + if(!WifiMgr.getInstance(this).isWifiEnable()) { //wifi未打开的情况 + WifiMgr.getInstance(this).openWifi(); + } + + updateWifiScanResult(); + handler.sendEmptyMessageDelayed(0, 2000); + } + + private void updateWifiScanResult () { + + if (mScanResultList != null && mScanResultList.size() > 0) { + mScanUser.setText("点击头像开始发送"); + mScanUserDes.setVisibility(View.GONE); + } else { + mScanUserDes.setVisibility(View.VISIBLE); + mScanUser.setText("正在寻找周围的小伙伴..."); + } + + if (mScanResultList != null) { + mScanResultList.clear(); + } + + choosereceiver_user1.setVisibility(View.GONE); + choosereceiver_user2.setVisibility(View.GONE); + choosereceiver_user3.setVisibility(View.GONE); + choosereceiver_user4.setVisibility(View.GONE); + choosereceiver_user1.setEnabled(true); + choosereceiver_user2.setEnabled(true); + choosereceiver_user3.setEnabled(true); + choosereceiver_user4.setEnabled(true); + + WifiMgr.getInstance(this).startScan(); + mScanResultList = WifiMgr.getInstance(this).getScanResultList(); + Utils.log("======WifiCount::" + mScanResultList.size()); + mScanResultList = WifiUtils.filterWithNoPassword(mScanResultList); + if(mScanResultList != null){ + for (int i = 0; i < mScanResultList.size(); i++) { + ScanResult scanResult = mScanResultList.get(i); + Utils.log(i + "=====" + scanResult.SSID ); + switch (i) { + case 0: + choosereceiver_user1.setVisibility(View.VISIBLE); + choosereceiver_user1_name.setText(scanResult.SSID); + choosereceiver_user1.setOnClickListener(this); + break; + case 1: + choosereceiver_user2.setVisibility(View.VISIBLE); + choosereceiver_user2_name.setText(scanResult.SSID); + choosereceiver_user2.setOnClickListener(this); + break; + case 2: + choosereceiver_user3.setVisibility(View.VISIBLE); + choosereceiver_user3_name.setText(scanResult.SSID); + choosereceiver_user3.setOnClickListener(this); + break; + case 3: + choosereceiver_user4.setVisibility(View.VISIBLE); + choosereceiver_user4_name.setText(scanResult.SSID); + choosereceiver_user4.setOnClickListener(this); + break; + } + } + + } + + } + + @Override + public void onClick(View v) { + if (v == choosereceiver_user1) { + connReceiverWifi(0); + } else if (v == choosereceiver_user2) { + connReceiverWifi(1); + } else if (v == choosereceiver_user3) { + connReceiverWifi(2); + } else if (v == choosereceiver_user4) { + connReceiverWifi(3); + } + } + + //1.连接网络 + private void connReceiverWifi(int connPosition) { + if (isStopScan) { + return; + } + + Utils.log("======开始连接热点"); + mScanUser.setText("开始连接对方设备..."); + isStopScan = true; +// choosereceiver_user1.setEnabled(false); +// choosereceiver_user2.setEnabled(false); +// choosereceiver_user3.setEnabled(false); +// choosereceiver_user4.setEnabled(false); + +// handler.postAtTime(new Runnable() { // 5s后还收不到接收者的回馈消息 重新回到扫描页面 +// @Override +// public void run() { +// Utils.log("==========aa" + isConnSuccess); +// if (!isConnSuccess) { +// isStopScan = false; +// updateWifiScanResult(); +// } +// } +// }, 5000); + + String ssid = "ghzs"; + ssid = mScanResultList.get(connPosition).SSID; + WifiMgr.getInstance(this).openWifi(); + WifiMgr.getInstance(this).addNetwork(WifiMgr.createWifiCfg(ssid, null, WifiMgr.WIFICIPHER_NOPASS)); + + + createSendMsgToServerRunnable(WifiMgr.getInstance(this).getIpAddressFromHotspot()); + } + + //发送UDP通知信息到 文件接收方 开启ServerSocketRunnable + private void createSendMsgToServerRunnable(final String ipAddress) { + new Thread(new Runnable() { + @Override + public void run() { + try { + startFileSenderServer(ipAddress); + } catch (Exception e) { + isStopScan = false; + Utils.log("UDP通信异常--startFileSenderServer" + e.toString()); + e.printStackTrace(); + } + + } + }).start(); + } + + private void startFileSenderServer(String ipAddress) throws Exception { + int serverPort = Constant.DEFAULT_SERVER_COM_PORT; + + // 确保Wifi连接上之后获取得到IP地址 + int count = 0; + while(ipAddress.equals(Constant.DEFAULT_UNKOWN_IP) && count < Constant.DEFAULT_TRY_TIME) { + Thread.sleep(1000); + ipAddress = WifiMgr.getInstance(ChooseReceiverActivity.this).getIpAddressFromHotspot(); + count ++; + } + + // 即使获取到连接的热点wifi的IP地址也是无法连接网络 所以采取此策略 + count = 0; + while(!WifiUtils.pingIpAddress(ipAddress) && count < Constant.DEFAULT_TRY_TIME) { + Thread.sleep(500); + count ++; + } + + if (mDatagramSocket == null) { + mDatagramSocket = new DatagramSocket(null); + mDatagramSocket.setReuseAddress(true); + mDatagramSocket.bind(new InetSocketAddress(serverPort)); + } +// mDatagramSocket = new DatagramSocket(serverPort); + byte[] receiveData = new byte[1024]; + byte[] sendData; + InetAddress ipAddressName = InetAddress.getByName(ipAddress); // 转译 + + //发送 即将发送的文件列表 到文件接收方 + sendFileInfoListToFileReceiverWithUdp(serverPort, ipAddressName); + + //发送 文件接收方 初始化 + + JSONObject senderData = new JSONObject(); + senderData.put(Constant.MSG_FILE_RECEIVER_INIT, sp.getString("user_name", "光环用户")); + + sendData = senderData.toString().getBytes(BaseTransfer.UTF_8); + DatagramPacket sendPacket = + new DatagramPacket(sendData, sendData.length, ipAddressName, serverPort); + mDatagramSocket.send(sendPacket); + + while(true) { + DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); + mDatagramSocket.receive(receivePacket); + String response = new String(receivePacket.getData(), 0, receivePacket.getLength()).trim(); + Utils.log("ChooseReceiverActivity:: 接收UDP请求" + response); + + if(response != null && response.contains(Constant.MSG_FILE_RECEIVER_INIT_SUCCESS)) { + JSONObject jsonObject = new JSONObject(response); + Utils.log("ChooseReceiverActivity:: 收到UDP请求::SUCCESS=" + jsonObject.getString(Constant.MSG_FILE_RECEIVER_INIT_SUCCESS)); + isConnSuccess = true; + + // 进入文件发送列表界面 (并且通知文件接收方进入文件接收列表界面) + Intent intent = new Intent(ChooseReceiverActivity.this, FileSenderActivity.class); + intent.putExtra("receiverName", jsonObject.getString(Constant.MSG_FILE_RECEIVER_INIT_SUCCESS)); + startActivity(intent); + closeSocket(); + Utils.log("==========发送销毁消息"); + Intent resultIntent= new Intent(); + setResult(0*123, resultIntent); + finish(); + break; + } + } + + } + + private void sendFileInfoListToFileReceiverWithUdp(int serverPort, InetAddress ipAddress) { + List fileInfos = (List) AppController.get("FileInfo", false); + + for (FileInfo fileInfo : fileInfos) { + String fileInfoJson = FileInfo.toJsonStr(fileInfo); + Utils.log("ChooseReceiverActivity:: 发送的文件列表::" + fileInfoJson); + DatagramPacket sendFileInfoListPacket = + new DatagramPacket(fileInfoJson.getBytes(), fileInfoJson.getBytes().length, ipAddress, serverPort); + try{ + mDatagramSocket.send(sendFileInfoListPacket); + Utils.log("ChooseReceiverActivity:: UDP通知 Success::" + ipAddress + "==" + serverPort); + } catch (Exception e) { + Utils.log("ChooseReceiverActivity:: UDP通知 Failure!"); + } + } + } + + @Override + public void onBackPressed() { + super.onBackPressed(); + closeSocket(); + } + + @OnClick(R.id.actionbar_rl_back) + public void onBackListener() { + closeSocket(); + } + + + + /** + * 关闭UDP Socket 流 + */ + private void closeSocket(){ + isStopScan = true; + if(mDatagramSocket != null) { + mDatagramSocket.disconnect(); + mDatagramSocket.close(); + mDatagramSocket = null; + } + } +} diff --git a/app/src/main/java/com/gh/gamecenter/CleanApkActivity.java b/app/src/main/java/com/gh/gamecenter/CleanApkActivity.java new file mode 100644 index 0000000000..087ad54659 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/CleanApkActivity.java @@ -0,0 +1,200 @@ +package com.gh.gamecenter; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.util.ArrayMap; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.Html; +import android.view.View; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.gh.base.BaseActivity; +import com.gh.common.util.DialogUtils; +import com.gh.common.util.Utils; +import com.gh.gamecenter.adapter.CleanApkAdapter; +import com.gh.gamecenter.entity.InstallGameEntity; +import com.gh.gamecenter.eventbus.EBSkip; + +import java.io.File; +import java.text.DecimalFormat; +import java.util.List; + +import butterknife.BindView; +import butterknife.OnClick; +import de.greenrobot.event.EventBus; + +/** + * Created by khy on 2017/1/24. + */ +public class CleanApkActivity extends BaseActivity implements CleanApkAdapter.OnScanListener { + + @BindView(R.id.apk_count) TextView mApkCount; + @BindView(R.id.apk_rv) RecyclerView mApkRv; + @BindView(R.id.delete_btn) TextView mApkDeleteBtn; + @BindView(R.id.select_game_all) CheckBox mApkSelectAll; + @BindView(R.id.scan_pb) ProgressBar mScanPb; + @BindView(R.id.reuse_nodata_skip_tv_hint) TextView mNodataSkipTv; + @BindView(R.id.reuse_nodata_skip_tv_btn) TextView mNodataSkipBtn; + @BindView(R.id.reuse_nodata_skip) LinearLayout mNodataSkipLl; + @BindView(R.id.delete_bottom) LinearLayout mDeleteBottom; + @BindView(R.id.select_game_installed_ll) RelativeLayout mInstallAllData; + + private CleanApkAdapter mAdapter; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View contentView = View.inflate(this, R.layout.activity_clean_apk, null); + init(contentView, "选择游戏"); + + mNodataSkipLl.setVisibility(View.GONE); + + mAdapter = new CleanApkAdapter(this, mApkDeleteBtn); + mApkRv.setLayoutManager(new LinearLayoutManager(this)); + mApkRv.setAdapter(mAdapter); + + mApkSelectAll.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + ArrayMap selectPosition = new ArrayMap<>(); + int itemCount = mAdapter.getItemCount(); + if (isChecked) { + for (int i = 0; i < itemCount; i++) { + selectPosition.put(i, true); + } + } else { + for (int i = 0; i < itemCount; i++) { + selectPosition.put(i, false); + } + } + + mAdapter.setSelectPosition(selectPosition); + mAdapter.notifyItemRangeChanged(0, itemCount); + } + }); + + mNodataSkipBtn.setText("去首页看看"); + mNodataSkipTv.setText("安装包已清理干净\n快去发现更多好玩的游戏吧!"); + + } + + @OnClick({R.id.delete_btn, R.id.reuse_nodata_skip_tv_btn}) + public void onClick(View view) { + switch (view.getId()) { + case R.id.delete_btn: { + String s = mApkDeleteBtn.getText().toString(); + if ("停止扫描".equals(s)) { + mAdapter.isStopScan(); + } else { + if (s.equals("一键删除")) { + Utils.toast(CleanApkActivity.this, "请选择需要删除的安装包"); + return; + } + + final List apkList = mAdapter.getApkList(); + final ArrayMap selectPosition = mAdapter.getSelectPosition(); + + for (int i = 0; i < apkList.size(); i++) { + if (selectPosition.get(i) && apkList.get(i).getInstallStatus() == 1) { + DialogUtils.showWarningDialog(CleanApkActivity.this, "删除安装包" + , "已选的安装包中可能包含未安装的应用,确定删除吗?", "取消 ", "确定" + , new DialogUtils.ConfiremListener() { + @Override + public void onConfirem() { + deleteApk(apkList, selectPosition); + } + }, null); + return; + } + } + + deleteApk(apkList, selectPosition); + } + break; + } + case R.id.reuse_nodata_skip_tv_btn: { + Intent intent = new Intent(CleanApkActivity.this, MainActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(intent); + new Thread(){ + @Override + public void run() { + try { + sleep(300); + } catch (InterruptedException e) { + e.printStackTrace(); + } + EventBus.getDefault().post(new EBSkip("GameFragment", 0)); + } + }.start(); + break; + } + } + } + + private void deleteApk(List apkList, ArrayMap selectPosition) { + long size = 0; + for (int i = 0; i < apkList.size(); i++) { + if (selectPosition.get(i)) { + InstallGameEntity installGameEntity = apkList.get(i); + size = size + installGameEntity.getGameSize(); + File file = new File(installGameEntity.getGamePath()); + if (file.isFile() && file.exists()) { + file.delete(); + mAdapter.deleteApk(i); + i--; + } + } + } + + double allSize = (((float)size/1024)/1024); + DecimalFormat df = new DecimalFormat("#.00"); + String sizeName = df.format(allSize) + "MB"; + Utils.toast(CleanApkActivity.this, "删除成功,已为您节省" + sizeName + "空间"); + + mAdapter.notifyDataSetChanged(); // 刷新Adapter position + + if (apkList.size() == 0) { // 全部删除 + mNodataSkipLl.setVisibility(View.VISIBLE); + mInstallAllData.setVisibility(View.GONE); + mDeleteBottom.setVisibility(View.GONE); + } + } + + @Override + public void onScanOver() { + mApkDeleteBtn.setText("一键删除"); + mApkDeleteBtn.setBackgroundResource(R.drawable.game_item_btn_red_style); + + long allSize = 0; + + List apkList = mAdapter.getApkList(); + for (InstallGameEntity installGameEntity : apkList) { + allSize = allSize + installGameEntity.getGameSize(); + } + + double size = (((float)allSize/1024)/1024); + DecimalFormat df = new DecimalFormat("#.00"); + String sizeName = df.format(size) + "MB"; + + mApkCount.setText(Html.fromHtml("找到" + apkList.size() + "个安装包,占用" + + "" + sizeName + ""+ "空间")); + mScanPb.setVisibility(View.GONE); + mApkSelectAll.setVisibility(View.VISIBLE); + } + + @Override + public void noData() { + mNodataSkipBtn.setText("去首页看看"); + mNodataSkipTv.setText("暂无游戏"); + mNodataSkipLl.setVisibility(View.VISIBLE); + mInstallAllData.setVisibility(View.GONE); + mDeleteBottom.setVisibility(View.GONE); + } +} diff --git a/app/src/main/java/com/gh/gamecenter/DownloadManagerActivity.java b/app/src/main/java/com/gh/gamecenter/DownloadManagerActivity.java index 412e93bb22..0885d5a55d 100644 --- a/app/src/main/java/com/gh/gamecenter/DownloadManagerActivity.java +++ b/app/src/main/java/com/gh/gamecenter/DownloadManagerActivity.java @@ -15,6 +15,7 @@ import com.gh.base.BaseFragmentActivity; import com.gh.common.util.DisplayUtils; import com.gh.download.DownloadManager; import com.gh.gamecenter.adapter.FragmentAdapter; +import com.gh.gamecenter.download.FileSendFragment; import com.gh.gamecenter.download.GameDownLoadFragment; import com.gh.gamecenter.download.GameUpdateFragment; import com.gh.gamecenter.eventbus.EBDownloadChanged; @@ -42,8 +43,10 @@ public class DownloadManagerActivity extends BaseFragmentActivity implements @BindView(R.id.downloadmanager_tv_download) TextView downloadmanager_tv_download; @BindView(R.id.downloadmanager_tv_update) TextView downloadmanager_tv_update; @BindView(R.id.downloadmanager_download_number) TextView downloadmanager_download_number; + @BindView(R.id.downloadmanager_tv_send) TextView downloadmanager_tv_send; @BindView(R.id.downloadmanager_update_number) TextView downloadmanager_update_number; @BindView(R.id.downloadmanager_ll_download) LinearLayout downloadmanager_ll_download; + @BindView(R.id.downloadmanager_ll_send) LinearLayout downloadmanager_ll_send; @BindView(R.id.downloadmanager_ll_update) LinearLayout downloadmanager_ll_update; @BindView(R.id.downloadmanager_slide_line) View downloadmanager_slide_line; @@ -68,6 +71,7 @@ public class DownloadManagerActivity extends BaseFragmentActivity implements downloadmanager_ll_download.setOnClickListener(this); downloadmanager_ll_update.setOnClickListener(this); + downloadmanager_ll_send.setOnClickListener(this); int updateSize = PackageManager.getUpdateList().size(); if (updateSize != 0) { @@ -104,14 +108,16 @@ public class DownloadManagerActivity extends BaseFragmentActivity implements DisplayMetrics outMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(outMetrics); - width = outMetrics.widthPixels / 2; - lparams = new LinearLayout.LayoutParams(width / 2, DisplayUtils.dip2px(getApplicationContext(), 2)); + width = outMetrics.widthPixels / 3; + lparams = new LinearLayout.LayoutParams(width / 2, + DisplayUtils.dip2px(getApplicationContext(), 2)); lparams.leftMargin = (int) (width * (currentItem + 0.25f)); downloadmanager_slide_line.setLayoutParams(lparams); List list = new ArrayList<>(); list.add(new GameDownLoadFragment()); list.add(new GameUpdateFragment()); + list.add(new FileSendFragment()); downloadmanager_viewPager.setAdapter(new FragmentAdapter(getSupportFragmentManager(), list)); downloadmanager_viewPager.addOnPageChangeListener(this); downloadmanager_viewPager.setCurrentItem(currentItem); @@ -123,17 +129,23 @@ public class DownloadManagerActivity extends BaseFragmentActivity implements EventBus.getDefault().post(new EBUISwitch("DownloadManagerActivity", 0)); downloadmanager_tv_download.setTextColor(getResources().getColor(R.color.theme)); downloadmanager_tv_update.setTextColor(getResources().getColor(R.color.title)); - } else { + downloadmanager_tv_send.setTextColor(getResources().getColor(R.color.title)); + } else if (position == 1){ EventBus.getDefault().post(new EBUISwitch("DownloadManagerActivity", 1)); downloadmanager_tv_download.setTextColor(getResources().getColor(R.color.title)); downloadmanager_tv_update.setTextColor(getResources().getColor(R.color.theme)); + downloadmanager_tv_send.setTextColor(getResources().getColor(R.color.title)); + } else { + downloadmanager_tv_download.setTextColor(getResources().getColor(R.color.title)); + downloadmanager_tv_update.setTextColor(getResources().getColor(R.color.title)); + downloadmanager_tv_send.setTextColor(getResources().getColor(R.color.theme)); } } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { if (positionOffset != 0) { - lparams.leftMargin = (int) (width * (positionOffset + 0.25f)); + lparams.leftMargin = (int) (width * (position + positionOffset + 0.25f)); downloadmanager_slide_line.setLayoutParams(lparams); } } @@ -152,6 +164,8 @@ public class DownloadManagerActivity extends BaseFragmentActivity implements downloadmanager_viewPager.setCurrentItem(0); } else if (id == R.id.downloadmanager_ll_update) { downloadmanager_viewPager.setCurrentItem(1); + } else if (id == R.id.downloadmanager_ll_send) { + downloadmanager_viewPager.setCurrentItem(2); } } diff --git a/app/src/main/java/com/gh/gamecenter/FileReceiverActivity.java b/app/src/main/java/com/gh/gamecenter/FileReceiverActivity.java new file mode 100644 index 0000000000..8dfe60cc78 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/FileReceiverActivity.java @@ -0,0 +1,395 @@ +package com.gh.gamecenter; + +import android.Manifest; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.os.Environment; +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.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.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.EBPackage; +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 java.io.IOException; +import java.net.DatagramSocket; +import java.net.ServerSocket; +import java.net.Socket; +import java.text.DecimalFormat; +import java.util.List; + +import butterknife.BindView; +import butterknife.OnClick; + +/** + * 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; + + private FileReceiverAdapter mFileReceiverAdapter; + + private FileInfo mCurFileInfo; + + private List mFileInfos; + + private IpPortInfo mIpPortInfo; + + private ServerRunnable mReceiverServer; + + private FileReceiver mFileReceiver; + + private boolean isReceivesOver; + private boolean isOpenWifi; //记录开热点前的WiFi状态 + + 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; + } + 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(); + } else if (msg.what == FileInfo.FLAG_FAILURE) { // 传输失败更新界面 + fileInfo.setResult(FileInfo.FLAG_FAILURE); + if (index == mFileInfos.size() -1) initSenderHint(); + } else if (msg.what == FileInfo.FLAG_CANCEL) { // 传输取消更新界面 + fileInfo.setResult(FileInfo.FLAG_CANCEL); + if (index == mFileInfos.size() -1) initSenderHint(); + } + + 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.getFilePath().equals(mCurFileInfo.getFilePath())) { + return i; + } + } + Utils.log("FileReceiverActivity:: 获取刷新位置异常"); + return -1; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View contentView = View.inflate(this, R.layout.activity_file_sender, null); + init(contentView, "接收游戏"); + + isReceivesOver = false; + + mFileReceiverAdapter = new FileReceiverAdapter(this); + mReceiverRv.setLayoutManager(new LinearLayoutManager(this)); + mReceiverRv.setAdapter(mFileReceiverAdapter); + + mFileInfos = (List) AppController.get("FileInfo", false); + + mIpPortInfo = (IpPortInfo) getIntent().getSerializableExtra(Constant.KEY_IP_PORT_INFO); + isOpenWifi = getIntent().getBooleanExtra("isOpenWifi", false); + + 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(); //启动接收服务 + } + } + + private void initUserData() { + 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("res:///" + R.drawable.logo); + } + + /** + * 开启文件接收端服务 + */ + private void initServer() { + mReceiverServer = new ServerRunnable(Constant.DEFAULT_SERVER_PORT); + new Thread(mReceiverServer).start(); + } + + DatagramSocket mDatagramSocket; + @Override + public void OnCancelPosition(final int position) { + if (position == getCurrentFileInfoIndex()) { + mFileReceiver.cancel(); + } else { + Utils.toast(this, "在传送中的游戏才可以取消"); + } + + +// Utils.log("接收方发送取消消息"); +// new Thread(new Runnable() { +// @Override +// public void run() { +// try { +// sendCancelControlToSender(position); +// } catch (Exception e) { +// Utils.log("接收方发送取消消息异常。。" + e.toString()); +// e.printStackTrace(); +// } +// } +// }).start(); + } + + //安装事件 + 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 sendCancelControlToSender(int position) throws Exception { +// if (mDatagramSocket == null) { +// mDatagramSocket = new DatagramSocket(Constant.DEFAULT_SERVER_CANCEL_PORT); +// } +// +// byte[] sendData = null; +// +// JSONObject jsonObject = new JSONObject(); +// jsonObject.put("controlStatus", Constant.MSG_RECEIVER_CANCEL); +// jsonObject.put("controlTag", position); +// sendData = jsonObject.toString().getBytes(BaseTransfer.UTF_8); +// DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, mIpPortInfo.getInetAddress(), Constant.DEFAULT_SERVER_CANCEL_PORT); +// mDatagramSocket.send(sendPacket); +// +// Utils.log("接收方取消接收操作已发送至接收方:" + jsonObject + "==" + mIpPortInfo.getInetAddress() + "==" + Constant.DEFAULT_SERVER_CANCEL_PORT); +// } + + /** + * 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); + mFileReceiver.setOnReceiveListener(new FileReceiver.OnReceiveListener() { + @Override + public void onStart() { + Utils.log("快传文件接收::onStart"); + } + + @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(FileInfo fileInfo) { // 获取传输成功 + handler.sendEmptyMessage(FileInfo.FLAG_SUCCESS); + Utils.log("快传文件接收成功::onSuccess"); + } + + @Override + public void onFailure(Throwable t, FileInfo fileInfo) { // 获取传输失败 + Utils.log("快传文件接收失败::onFailure"); + handler.sendEmptyMessage(FileInfo.FLAG_FAILURE); + } + + @Override + public void onCancel(FileInfo fileInfo) { // 获取传输取消 + Utils.log("快传文件接收取消::onCancel"); + handler.sendEmptyMessage(FileInfo.FLAG_CANCEL); + } + }); + + 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(){ + isReceivesOver = true; + int sendSuccess = 0; + 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 onBackPressed() { + backHint(); + } + + @OnClick(R.id.actionbar_rl_back) + public void back() { + backHint(); + } + + private void colsePage() { + //关闭热点 + HotspotManager.disableAp(this); + + mReceiverServer.close(); + AppController.get("FileInfo", true); + HotspotManager.disableAp(FileReceiverActivity.this); + + if (isOpenWifi) { + WifiMgr.getInstance(this).openWifi(); + } + + for (FileInfo fileInfo : mFileInfos) { + // TODO 接收完成未安装的游戏,添加到下载管理-游戏下载 + 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); + DownloadDao.getInstance(this).newOrUpdate(entry); + } + } + + FileReceiverActivity.this.finish(); + + } + + private void backHint() { + if (isReceivesOver) { + colsePage(); + } else { + DialogUtils.showWarningDialog(FileReceiverActivity.this, "退出提示", "退出会中断接收,确定要退出吗?" + , "取消", "确定" + , new DialogUtils.ConfiremListener() { + @Override + public void onConfirem() { + colsePage(); + } + }, null); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/FileSenderActivity.java b/app/src/main/java/com/gh/gamecenter/FileSenderActivity.java new file mode 100644 index 0000000000..e1d1c1c69b --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/FileSenderActivity.java @@ -0,0 +1,293 @@ +package com.gh.gamecenter; + +import android.Manifest; +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.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.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 java.net.DatagramSocket; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; + +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; + + private FileSenderAdapter mSenderAdapter; + + private List mFileInfos; + + private List mFileSenderList = new ArrayList<>(); + + private boolean isSendOver; + + 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, "发送游戏"); + + isSendOver = false; + + mFileSenderList = new ArrayList<>();; + mSenderAdapter = new FileSenderAdapter(this); + mSenderRv.setLayoutManager(new LinearLayoutManager(this)); + mSenderRv.setAdapter(mSenderAdapter); + + init(); + } + + private void init() { + + Utils.log("FileSenderActivity == init()"); + mFileInfos = (List) AppController.get("FileInfo", false); + + 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();//开启传送文件 + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + //初始化用户数据 + private void initUserData() { + String receiverName = getIntent().getExtras().getString("receiverName"); + + 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("发给-" + receiverName); + mSenderUserIcon.setImageURI("res:///" + R.drawable.logo); + } + + DatagramSocket mDatagramSocket; + private void initSendServer() throws Exception { + String serverIp = WifiMgr.getInstance(this).getIpAddressFromHotspot(); + for (int i = 0; i < mFileInfos.size(); i++) { + final FileInfo mFileInfo = mFileInfos.get(i); + Utils.log("FileSenderActivity == initSendServer()===" + mFileInfo.getName()); + FileSender fileSender = new FileSender(this, mFileInfo, serverIp, Constant.DEFAULT_SERVER_PORT); + final int finalI = i; + fileSender.setOnSendListener(new FileSender.OnSendListener() { + @Override + public void onStart() { + Utils.log("快传文件发送::onStart" + "==" + mFileInfo.getName()); + + } + + @Override + public void onProgress(long progress, long total) { + Utils.log("快传文件发送中..." + progress + "==" + total + "==" + mFileInfo.getName()); + mFileInfo.setProgress(progress); + Message message = new Message(); + message.what = FileInfo.FLAG_DEFAULT; + message.obj = finalI; + handler.sendMessage(message); + } + + @Override + public void onSuccess(FileInfo fileInfo) { + Utils.log("快传文件发送成功::onSuccess" + "==" + mFileInfo.getName()); + Message message = new Message(); + message.what = FileInfo.FLAG_SUCCESS; + message.obj = finalI; + handler.sendMessage(message); + } + + @Override + public void onFailure(Throwable t, FileInfo fileInfo) { + Utils.log("快传文件发送失败::onFailure" + "==" + mFileInfo.getName()); + Message message = new Message(); + message.what = FileInfo.FLAG_FAILURE; + message.obj = finalI; + handler.sendMessage(message); + } + + @Override + public void onCancel(FileInfo fileInfo) { + Utils.log("快传文件用户主动取消::onCancel" + "==" + mFileInfo.getName()); + Message message = new Message(); + message.what = FileInfo.FLAG_CANCEL; + message.obj = finalI; + handler.sendMessage(message); + } + + }); + mFileSenderList.add(fileSender); + AppController.FILE_SENDER_EXECUTOR.execute(fileSender); + } + +// mDatagramSocket = new DatagramSocket(Constant.DEFAULT_SERVER_CANCEL_PORT); +// Utils.log("接收方取消Socket端口" + Constant.DEFAULT_SERVER_CANCEL_PORT); +// byte[] receiveData = new byte[1024]; +// byte[] sendData = null; +// // 主要接收 接收方取消操作 +// while (true) { +// DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); +// mDatagramSocket.receive(receivePacket); +// String response = new String( receivePacket.getData(), BaseTransfer.UTF_8).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); +// if (fileSender != null && fileSender.isRunning()) { +// Utils.log("接收方取消发送"); +// fileSender.cancel(); +// } +// } +// } + } + + private void initSenderHint(){ + 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(); + } + + @OnClick(R.id.actionbar_rl_back) + public void back() { + backHint(); + } + + + /** + * 停止所有的文件发送任务 + */ + private void stopAllFileSendingTask(){ + for(FileSender fileSender : mFileSenderList){ + if(fileSender != null){ + fileSender.cancel(); + } + } + } + + private void backHint() { + if(!isSendOver){ + DialogUtils.showWarningDialog(FileSenderActivity.this, "退出传送", "退出会中断所有游戏的传送,确定要退出吗?" + , "取消", "确定" + , new DialogUtils.ConfiremListener() { + @Override + public void onConfirem() { + stopAllFileSendingTask(); + AppController.get("FileInfo", true); + FileSenderActivity.this.finish(); + } + }, null); + } else { + stopAllFileSendingTask(); + AppController.get("FileInfo", true); + FileSenderActivity.this.finish(); + } + + + } +} diff --git a/app/src/main/java/com/gh/gamecenter/KcSelectGameActivity.java b/app/src/main/java/com/gh/gamecenter/KcSelectGameActivity.java new file mode 100644 index 0000000000..a22d1d7387 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/KcSelectGameActivity.java @@ -0,0 +1,91 @@ +package com.gh.gamecenter; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.TextView; + +import com.gh.base.AppController; +import com.gh.base.BaseActivity; +import com.gh.common.util.Utils; +import com.gh.gamecenter.adapter.KcSelectGameAdapter; +import com.gh.gamecenter.kuaichuan.FileInfo; + +import java.util.HashMap; +import java.util.List; + +import butterknife.BindView; + +/** + * Created by khy on 2017/1/20. + * 快传-选择游戏 + */ +public class KcSelectGameActivity extends BaseActivity { + + @BindView(R.id.select_game_rv) RecyclerView mSelectRv; + @BindView(R.id.select_game_send) TextView mSelectSend; + @BindView(R.id.select_game_all) CheckBox selectAll; + @BindView(R.id.install_count) TextView installCount; + + private KcSelectGameAdapter mAdapter; + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == 0*123) { + finish(); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View contentView = View.inflate(this, R.layout.activity_kc_select_game, null); + init(contentView, "选择游戏"); + + + mAdapter = new KcSelectGameAdapter(this, mSelectSend); + mSelectRv.setLayoutManager(new LinearLayoutManager(this)); + mSelectRv.setAdapter(mAdapter); + + mSelectSend.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + List selectData = mAdapter.getSelectData(); + if (selectData.size() == 0) { + Utils.toast(KcSelectGameActivity.this, "请选择游戏"); + return; + } + AppController.put("FileInfo", selectData); + Intent intent = new Intent(KcSelectGameActivity.this, ChooseReceiverActivity.class); + startActivityForResult(intent, 0*123); + } + }); + + selectAll.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + HashMap selectPosition = new HashMap<>(); + int itemCount = mAdapter.getItemCount(); + if (isChecked) { + for (int i = 0; i < itemCount; i++) { + selectPosition.put(i, true); + } + } else { + for (int i = 0; i < itemCount; i++) { + selectPosition.put(i, false); + } + } + + mAdapter.setSelectPosition(selectPosition); + mAdapter.notifyItemRangeChanged(0, itemCount); + } + }); + + installCount.setText("已安装(" + mAdapter.getItemCount() + ")"); + } +} diff --git a/app/src/main/java/com/gh/gamecenter/ReceiverWaitingActivity.java b/app/src/main/java/com/gh/gamecenter/ReceiverWaitingActivity.java new file mode 100644 index 0000000000..b9990c43f9 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/ReceiverWaitingActivity.java @@ -0,0 +1,308 @@ +package com.gh.gamecenter; + +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.text.Html; +import android.view.View; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.facebook.drawee.backends.pipeline.Fresco; +import com.facebook.drawee.interfaces.DraweeController; +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.RandomUtils; +import com.gh.common.util.Utils; +import com.gh.gamecenter.kuaichuan.BaseTransfer; +import com.gh.gamecenter.kuaichuan.Constant; +import com.gh.gamecenter.kuaichuan.FileInfo; +import com.gh.gamecenter.kuaichuan.HotspotManager; +import com.gh.gamecenter.kuaichuan.IpPortInfo; +import com.gh.gamecenter.kuaichuan.WifiMgr; +import com.gh.gamecenter.manager.SystemBarTintManager; +import com.gh.gamecenter.receiver.WifiAPBroadcastReceiver; + +import org.json.JSONObject; + +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.List; + +import butterknife.BindView; +import butterknife.OnClick; + +/** + * Created by khy on 2017/1/20. + */ +public class ReceiverWaitingActivity extends BaseActivity { + + @BindView(R.id.waiting_user_icon) SimpleDraweeView mUserIcon; + @BindView(R.id.waiting_user_name) TextView mUserName; + @BindView(R.id.waiting_user_status) TextView mUserStatus; + @BindView(R.id.waiting_conn) TextView mWaitingConn; + @BindView(R.id.waiting_gif) SimpleDraweeView mWaitingGif; + @BindView(R.id.waiting_hint) TextView mWaitingHint; + @BindView(R.id.reuse_actionbar) RelativeLayout mActionbar; + + + private WifiAPBroadcastReceiver mWifiAPBroadcastReceiver; + + private List mFileInfos; // 接收到的文件列表 + + private SharedPreferences sp; + + private boolean mIsInitialized; + private boolean isOpenWifi; //记录开热点前的WiFi状态 + + private String mySsid; + + /** + * 与 文件发送方 通信的 线程 + */ + Runnable mUdpServerRuannable; + + Handler mHandler = new Handler(){ + @Override + public void handleMessage(Message msg) { + if(msg.what == 0){ + IpPortInfo ipPortInfo = (IpPortInfo) msg.obj; + Bundle bundle = new Bundle(); + bundle.putSerializable(Constant.KEY_IP_PORT_INFO, ipPortInfo); + bundle.putBoolean("isOpenWifi", isOpenWifi); + + Intent intent = new Intent(ReceiverWaitingActivity.this, FileReceiverActivity.class); + intent.putExtras(bundle); + startActivity(intent); + + colsePage(); + } + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View contentView = View.inflate(this, R.layout.activity_receiver_waiting, null); + init(contentView, "接收游戏"); + + //修改沉浸栏以及ActionBar 颜色 + mActionbar.setBackgroundColor(getResources().getColor(R.color.scan_bg)); + SystemBarTintManager tintManager = getTintManager(); + if (tintManager != null) { + tintManager.setStatusBarTintResource(R.color.scan_bg); + } + + sp = getSharedPreferences(Config.PREFERENCE, Context.MODE_PRIVATE); + mIsInitialized = false; + isOpenWifi = WifiMgr.getInstance(this).isWifiEnable(); + + mUserName.setText(sp.getString("user_name", "光环用户")); + + if (isOpenWifi) { + WifiMgr.getInstance(this).closeWifi(); + } + + mUserStatus.setText("正在初始化..."); + DraweeController controller = Fresco.newDraweeControllerBuilder() + .setUri("res:///" + R.drawable.kuaichuan_receiver_waiting) + .setAutoPlayAnimations(true) + .build(); + mWaitingGif.setController(controller); + + + mFileInfos = new ArrayList<>(); + + //初始化热点 + if(HotspotManager.isApOn(this)){ + HotspotManager.disableAp(this); + } + + mWifiAPBroadcastReceiver = new WifiAPBroadcastReceiver() { + @Override + public void onWifiApEnabled() { + if(!mIsInitialized){ + mUdpServerRuannable = createSendMsgToFileSenderRunnable(); + AppController.MAIN_EXECUTOR.execute(mUdpServerRuannable); + mIsInitialized = true; + + mWaitingConn.setVisibility(View.VISIBLE); + mUserStatus.setText(Html.fromHtml("成功创建热点:" + "" + mySsid + "")); + mWaitingHint.setVisibility(View.GONE); + } + + } + }; + + IntentFilter filter = new IntentFilter(WifiAPBroadcastReceiver.ACTION_WIFI_AP_STATE_CHANGED); + registerReceiver(mWifiAPBroadcastReceiver, filter); + + HotspotManager.isApOn(this); + String chars = "abcdefghijklmnopqrstuvwxyz"; + int[] randomArray = RandomUtils.getRandomArray(2, 25); + mySsid = "ghZS-"; + for (int i : randomArray) { + mySsid = mySsid + chars.charAt(i); + } + mySsid = mySsid + 1; + HotspotManager.configApState(this, mySsid); // change Ap state :boolean + } + + /** + * 创建发送UDP消息到 文件发送方 的服务线程 + */ + private Runnable createSendMsgToFileSenderRunnable(){ + return new Runnable() { + @Override + public void run() { + try { + startFileReceiverServer(Constant.DEFAULT_SERVER_COM_PORT); + } catch (Exception e) { + e.printStackTrace(); + } + } + }; + } + + /** + * 开启 文件接收方 通信服务 (必须在子线程执行) + * @param serverPort + * @throws Exception + */ + DatagramSocket mDatagramSocket; + private void startFileReceiverServer(int serverPort) throws Exception{ + //网络连接上,无法获取IP的问题 + int count = 0; + String localAddress = WifiMgr.getInstance(ReceiverWaitingActivity.this).getHotspotLocalIpAddress(); + Utils.log("开启 文件接收方 通信服务 " + localAddress); + + //ip地址无效 重新获取 + while(localAddress.equals(Constant.DEFAULT_UNKOWN_IP) && count < Constant.DEFAULT_TRY_TIME){ + Thread.sleep(1000); + localAddress = WifiMgr.getInstance(ReceiverWaitingActivity.this).getHotspotLocalIpAddress(); + count ++; + } + + mDatagramSocket = new DatagramSocket(serverPort); + + byte[] receiveData = new byte[1024]; + byte[] sendData; + Utils.log("接收接受信息 "); + while (true) { + //接收 文件发送方的消息 + DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); + mDatagramSocket.receive(receivePacket); + String msg = new String( receivePacket.getData(), 0, receivePacket.getLength()).trim(); + InetAddress inetAddress = receivePacket.getAddress(); + + int port = receivePacket.getPort(); + Utils.log("接收信息中。。。" + msg ); + if(msg != null && msg.contains(Constant.MSG_FILE_RECEIVER_INIT)){ + Utils.log("接收方初始化完毕准备进去传输页面 并回馈消息给发送者" + inetAddress); + + AppController.put("FileInfo", mFileInfos); //保存数据列表 + + for (FileInfo mFileInfo : mFileInfos) { + Utils.log("=======zz===" + mFileInfo.getSize() + "==" + mFileInfo.getName() + "==" + mFileInfo.getFilePath()); + } + + // 反馈 文件发送方的消息 +// sendData = Constant.MSG_FILE_RECEIVER_INIT_SUCCESS.getBytes(BaseTransfer.UTF_8); + JSONObject receiverData = new JSONObject(); + receiverData.put(Constant.MSG_FILE_RECEIVER_INIT_SUCCESS, sp.getString("user_name", "光环用户")); + sendData = receiverData.toString().getBytes(BaseTransfer.UTF_8); + + DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, inetAddress, port); + mDatagramSocket.send(sendPacket); + + Message message = new Message(); + message.what = 0; + message.obj = new IpPortInfo(inetAddress, port, new JSONObject(msg).getString(Constant.MSG_FILE_RECEIVER_INIT)); + mHandler.sendMessage(message); + + } else { + if(msg != null){ + Utils.log("保存文件列表数据" + msg); + parseFileInfo(msg); + } + } + } + } + + /** + * 解析FileInfo + * @param msg + */ + private void parseFileInfo(String msg) { + FileInfo fileInfo = FileInfo.toObject(msg); + Utils.log("parseFileInfo" + fileInfo.getFilePath() + "==" + fileInfo.getName() + "==" + fileInfo.getSize()); + if(fileInfo != null && fileInfo.getFilePath() != null){ + mFileInfos.add(fileInfo); + } + } + + /** + * 关闭UDP Socket 流 + */ + private void closeSocket(){ + if(mDatagramSocket != null){ + mDatagramSocket.disconnect(); + mDatagramSocket.close(); + mDatagramSocket = null; + } + } + + @OnClick(R.id.actionbar_rl_back) + public void back() { + colsePage(); + + //关闭热点 + HotspotManager.disableAp(this); + + if (isOpenWifi) { + WifiMgr.getInstance(this).openWifi(); + } + } + + @Override + public void onBackPressed() { + super.onBackPressed(); + colsePage(); + + //关闭热点 + HotspotManager.disableAp(this); + + if (isOpenWifi) { + WifiMgr.getInstance(this).openWifi(); + } + } + + /** + * 关闭广播并关闭Socket流 + */ + private void colsePage() { + try { + if(mWifiAPBroadcastReceiver != null){ + unregisterReceiver(mWifiAPBroadcastReceiver); + mWifiAPBroadcastReceiver = null; + } + } catch (Exception e) { + Utils.log("接收方d等待连接异常-关闭广播"); + e.printStackTrace(); + } + + closeSocket(); + + this.finish(); + } + + +} diff --git a/app/src/main/java/com/gh/gamecenter/adapter/CleanApkAdapter.java b/app/src/main/java/com/gh/gamecenter/adapter/CleanApkAdapter.java new file mode 100644 index 0000000000..a367dab9da --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/adapter/CleanApkAdapter.java @@ -0,0 +1,330 @@ +package com.gh.gamecenter.adapter; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.os.Environment; +import android.os.Handler; +import android.support.v4.util.ArrayMap; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CompoundButton; +import android.widget.TextView; + +import com.gh.common.util.BitmapUtils; +import com.gh.common.util.PackageUtils; +import com.gh.common.view.CardLinearLayout; +import com.gh.gamecenter.CleanApkActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.adapter.viewholder.KcSelectGameViewHolder; +import com.gh.gamecenter.entity.InstallGameEntity; + +import java.io.File; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * Created by khy on 2017/1/24. + */ +public class CleanApkAdapter extends RecyclerView.Adapter { + + private Context mContext; + + private List mApkList; + + private OnScanListener scanListener; + + private ArrayMap mSelectPosition; + + private static int INSTALLED = 0; // 表示已经安装 + private static int UNINSTALLED = 1; // 表示未安装 + + private int cardMargin; + + private boolean isStopScan; + + private TextView mApkDeleteBtn; + + private boolean isScanOver; + + + Handler handler = new Handler(); + + public CleanApkAdapter(CleanApkActivity activity, TextView apkDeleteBtn) { + this.mContext = activity; + this.mApkDeleteBtn = apkDeleteBtn; + scanListener = activity; + + mApkList = new ArrayList<>(); + mSelectPosition = new ArrayMap<>(); + isStopScan = false; + isScanOver = false; + + cardMargin = (int) mContext.getResources().getDimension(R.dimen.cardview_margin); + init(); + } + + private void init() { + new Thread(new Runnable() { + @Override + public void run() { + FindAllAPKFile(Environment.getExternalStorageDirectory()); + handler.post(new Runnable() { + @Override + public void run() { + isScanOver = true; + scanListener.onScanOver(); + if (mApkList.size() == 0) { + scanListener.noData(); + } + notifyItemRangeChanged(0, getItemCount()); + } + }); + } + }).start(); + + } + + public void FindAllAPKFile(File file) { + + if (isStopScan) { + return; + } + + // 手机上的文件,目前只判断SD卡上的APK文件 + // file = Environment.getDataDirectory(); + // SD卡上的文件目录 + if (file.isFile()) { +// Utils.log("===== 是文件" + file.getAbsolutePath().toString()); + String name_s = file.getName(); + InstallGameEntity apkEntity = new InstallGameEntity(); + String apk_path = null; + // MimeTypeMap.getSingleton() + if (name_s.toLowerCase().endsWith(".apk")) { + apk_path = file.getAbsolutePath();// apk文件的绝对路劲 + PackageManager pm = mContext.getPackageManager(); + PackageInfo packageInfo = pm.getPackageArchiveInfo(apk_path, PackageManager.GET_ACTIVITIES); + if (packageInfo == null) return; + + ApplicationInfo appInfo = packageInfo.applicationInfo; + + + /**获取apk的图标 */ + appInfo.sourceDir = apk_path; + appInfo.publicSourceDir = apk_path; + Drawable apk_icon = appInfo.loadIcon(pm); + apkEntity.setGameBm(BitmapUtils.drawableToBitmap(apk_icon)); + /** apk的绝对路劲 */ + apkEntity.setGamePath(file.getAbsolutePath()); + /** apk的版本名称 String */ + String versionName = packageInfo.versionName; + apkEntity.setGameVersion(versionName); + + String apkName = packageInfo.applicationInfo.loadLabel(pm).toString(); + apkEntity.setGameName(apkName); + + apkEntity.setGameSize(file.length()); + + /**安装处理类型*/ + /** 得到包名 */ + String packageName = packageInfo.packageName; + int type = doType(pm, packageName); + apkEntity.setInstallStatus(type); + + mApkList.add(apkEntity); + mSelectPosition.put((mApkList.size() - 1), false); + + handler.post(new Runnable() { + @Override + public void run() { + notifyItemInserted((mApkList.size() - 1)); + } + }); + } + } else { +// Utils.log("===== 是文件夹" + file.getAbsolutePath().toString()); + File[] files = file.listFiles(); + if (files != null && files.length > 0) { + for (File file_str : files) { + FindAllAPKFile(file_str); + } + } + } + } + + private int doType(PackageManager pm, String packageName) { + List pakageinfos = pm.getInstalledPackages(0); + for (PackageInfo pi : pakageinfos) { + if ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { + String pi_packageName = pi.packageName; + //如果这个包名在系统已经安装过的应用中存在 + if(packageName.endsWith(pi_packageName)){ + return INSTALLED; + } + } + } + return UNINSTALLED; + } + + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()).inflate( + R.layout.kc_game_select_item, parent, false); + return new KcSelectGameViewHolder(view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, final int position) { + final InstallGameEntity gameEntity = mApkList.get(position); + if (viewHolder instanceof KcSelectGameViewHolder) { + KcSelectGameViewHolder holder = (KcSelectGameViewHolder) viewHolder; + // 第一个 + if (position == 0) { + ((CardLinearLayout) holder.itemView).setmTop(cardMargin); + } else { + ((CardLinearLayout) holder.itemView).setmTop(0); + } + + // 最后一个 + if (position == mApkList.size() - 1) { + ((CardLinearLayout) holder.itemView).setBottom(true); + } else { + ((CardLinearLayout) holder.itemView).setBottom(false); + } + + double size = (((float)gameEntity.getGameSize()/1024)/1024); + DecimalFormat df = new DecimalFormat("#.00"); + String sizeName = df.format(size) + "MB"; + +// Spanned spanned = Html.fromHtml("大小:" + "" + sizeName + ""); +// holder.gameSize.setText(spanned); + holder.selectCB.setVisibility(View.VISIBLE); + if (mSelectPosition.get(position)) { + holder.selectCB.setChecked(true); + } else { + holder.selectCB.setChecked(false); + } + + holder.gameNameAndSize.setText(gameEntity.getGameName()); + holder.gameDes.setText("版本:V" + gameEntity.getGameVersion() + " | " + sizeName); + + holder.gameThumb.setImageBitmap(gameEntity.getGameBm()); + + if (gameEntity.getInstallStatus() == INSTALLED) { + holder.gameSize.setText("已安装"); + holder.gameSize.setTextColor(mContext.getResources().getColor(R.color.theme)); + } else { + holder.gameSize.setText("未安装"); + holder.gameSize.setTextColor(Color.RED); + } + + if (isScanOver) { + holder.selectCB.setEnabled(true); + } else { + holder.selectCB.setEnabled(false); + } + + holder.selectCB.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (isChecked) { + mSelectPosition.put(position, true); + } else { + mSelectPosition.put(position, false); + } + + long gameSize = 0; + for (Integer integer : mSelectPosition.keySet()) { + if (mSelectPosition.get(integer)) { + gameSize = gameSize + mApkList.get(integer).getGameSize(); + } + } + + if (gameSize == 0) { + mApkDeleteBtn.setText("一键删除"); + } else { + double size = (((float)gameSize/1024)/1024); + DecimalFormat df = new DecimalFormat("#.00"); + String sizeName = df.format(size) + "MB"; + mApkDeleteBtn.setText("一键删除("+ sizeName +")"); + } + } + }); + + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (isScanOver) { + PackageUtils.launchSetup(mContext, gameEntity.getGamePath()); + } + } + }); + + } + + } + + @Override + public int getItemCount() { + return mApkList.size(); + } + + public List getApkList() { + return mApkList; + } + + public ArrayMap getSelectPosition() { + return mSelectPosition; + } + + public void setSelectPosition(ArrayMap selectPosition) { + this.mSelectPosition = selectPosition; + } + + public void isStopScan () { + this.isStopScan = true; + } + + public void deleteApk(int position) { + mApkList.remove(position); + + Iterator> iterator = mSelectPosition.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + Integer key = entry.getKey(); + + if (key == position) { + iterator.remove(); + } + } + + ArrayMap newMap = new ArrayMap<>(mSelectPosition); + for (Integer integer : newMap.keySet()) { + if (integer > position) { + int newPosition = integer - 1; + mSelectPosition.put(newPosition, mSelectPosition.get(integer)); + } + } + + if (mSelectPosition.size() > mApkList.size()) { + mSelectPosition.removeAt(mSelectPosition.size() - 1); + } + + notifyItemRemoved(position); + } + + public interface OnScanListener { + void onScanOver(); + void noData(); + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/adapter/FileReceiverAdapter.java b/app/src/main/java/com/gh/gamecenter/adapter/FileReceiverAdapter.java new file mode 100644 index 0000000000..4ef2f96772 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/adapter/FileReceiverAdapter.java @@ -0,0 +1,159 @@ +package com.gh.gamecenter.adapter; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.os.Environment; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.gh.base.AppController; +import com.gh.common.util.DisplayUtils; +import com.gh.common.util.PackageUtils; +import com.gh.common.util.SpeedUtils; +import com.gh.common.util.Utils; +import com.gh.gamecenter.FileReceiverActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.adapter.viewholder.KcSelectGameViewHolder; +import com.gh.gamecenter.kuaichuan.FileInfo; + +import java.text.DecimalFormat; +import java.util.List; + +/** + * Created by khy on 2017/1/22. + */ +public class FileReceiverAdapter extends RecyclerView.Adapter { + + private Context mContext; + private List mFileInfos; + + private long lastProgress; + + private OnReceiverCancelListener cancelListener; + + + public FileReceiverAdapter(FileReceiverActivity activity) { + this.mContext = activity; + this.cancelListener = activity; + + mFileInfos = (List) AppController.get("FileInfo", false); + } + + /** + * 更新数据 + */ + public void update(){ + mFileInfos = (List) AppController.get("FileInfo", false); + notifyItemRangeChanged(0, getItemCount()); + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(mContext).inflate(R.layout.kc_game_select_item, parent, false); + return new KcSelectGameViewHolder(view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { + final FileInfo fileInfo = mFileInfos.get(position); + + if (holder instanceof KcSelectGameViewHolder) { + final KcSelectGameViewHolder viewHolder = (KcSelectGameViewHolder) holder; + viewHolder.gameNameAndSize.setText(fileInfo.getName()); + viewHolder.downloadStatus.setVisibility(View.VISIBLE); + viewHolder.gameProgressbar.setMax(100); + viewHolder.gameProgressbar.setVisibility(View.VISIBLE); + viewHolder.gameLlInfo.setVisibility(View.VISIBLE); + viewHolder.gameSize.setVisibility(View.GONE); + viewHolder.gameNameAndSize.setPadding(0, 0, 0, DisplayUtils.dip2px(mContext, 5)); + if (fileInfo.getBitmap() != null) { + viewHolder.gameThumb.setImageBitmap(fileInfo.getBitmap()); + } + Utils.log("=====传送状态::" + fileInfo.getResult()); + + if (fileInfo.getResult() == FileInfo.FLAG_SUCCESS || fileInfo.getResult() == FileInfo.FLAG_INSTALLED) { // 传输完成... + viewHolder.gameProgressbar.setProgress(100); + viewHolder.downloadPercentage.setText("100%"); + + if (fileInfo.getResult() == FileInfo.FLAG_SUCCESS) { + viewHolder.downloadStatus.setText("安装"); + viewHolder.downloadStatus.setTextColor(Color.WHITE); + viewHolder.downloadStatus.setBackgroundResource(R.drawable.game_item_btn_download_style); + } else { + viewHolder.downloadStatus.setText("已安装"); + viewHolder.downloadStatus.setTextColor(mContext.getResources().getColor(R.color.theme)); + viewHolder.downloadStatus.setBackgroundDrawable(new ColorDrawable(0)); + } + + double size = (((float)fileInfo.getSize()/1024)/1024); + DecimalFormat df = new DecimalFormat("#.00"); + String sizeName = df.format(size) + "MB"; + viewHolder.downloadSpeed.setTextColor(mContext.getResources().getColor(R.color.content)); + viewHolder.downloadSpeed.setText(sizeName + "/" + sizeName); + } else if (fileInfo.getResult() == FileInfo.FLAG_FAILURE) { // 传输失败... + double sizeMb = (((float)fileInfo.getSize()/1024)/1024); + double curSizeMb = (((float)fileInfo.getProgress()/1024)/1024); + DecimalFormat df = new DecimalFormat("#.00"); + String sizeName = df.format(sizeMb) + "MB"; + String curSizeName = df.format(curSizeMb) + "MB"; + viewHolder.downloadSpeed.setTextColor(mContext.getResources().getColor(R.color.content)); + viewHolder.downloadSpeed.setText(curSizeName + "/" + sizeName); + viewHolder.downloadStatus.setText("传输失败"); + viewHolder.downloadStatus.setTextColor(mContext.getResources().getColor(R.color.type_huodong)); + viewHolder.downloadStatus.setBackgroundDrawable(new ColorDrawable(0)); + } else if (fileInfo.getResult() == FileInfo.FLAG_CANCEL) { // 取消传输 + double sizeMb = (((float)fileInfo.getSize()/1024)/1024); + double curSizeMb = (((float)fileInfo.getProgress()/1024)/1024); + DecimalFormat df = new DecimalFormat("#.00"); + String sizeName = df.format(sizeMb) + "MB"; + String curSizeName = df.format(curSizeMb) + "MB"; + viewHolder.downloadSpeed.setTextColor(mContext.getResources().getColor(R.color.content)); + viewHolder.downloadSpeed.setText(curSizeName + "/" + sizeName); + viewHolder.downloadStatus.setText("已取消"); + viewHolder.downloadStatus.setBackgroundDrawable(new ColorDrawable(0)); + } else if (fileInfo.getResult() == FileInfo.FLAG_DEFAULT){ // 传输中... + int percent = (int)(fileInfo.getProgress() * 100 / fileInfo.getSize()); + viewHolder.gameProgressbar.setProgress(percent); + viewHolder.downloadStatus.setText("取消"); + viewHolder.downloadStatus.setTextColor(mContext.getResources().getColor(R.color.content)); + viewHolder.downloadStatus.setBackgroundResource(R.drawable.kuaichuan_cancel_bg); + + long speed = (fileInfo.getProgress() - lastProgress) / 1024; + + viewHolder.downloadPercentage.setText(percent + "%"); + viewHolder.downloadSpeed.setTextColor(mContext.getResources().getColor(R.color.theme)); + viewHolder.downloadSpeed.setText(String.format("%s(剩%s)", + SpeedUtils.getSpeed(speed), + SpeedUtils.getRemainTime(fileInfo.getSize(), fileInfo.getProgress(), speed * 1024))); + lastProgress = fileInfo.getProgress(); + } + + viewHolder.downloadStatus.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + String s = viewHolder.downloadStatus.getText().toString(); + if ("取消".equals(s)) { + cancelListener.OnCancelPosition(position); + } else if ("安装".equals(s)) { + PackageUtils.launchSetup(mContext, Environment.getExternalStorageDirectory() + "/GH-KC/" + fileInfo.getName() + ".apk"); + } + } + }); + } + } + + @Override + public int getItemCount() { + if (mFileInfos == null) { + return 0; + } + return mFileInfos.size(); + } + + public interface OnReceiverCancelListener { + void OnCancelPosition(int position); + } +} diff --git a/app/src/main/java/com/gh/gamecenter/adapter/FileSenderAdapter.java b/app/src/main/java/com/gh/gamecenter/adapter/FileSenderAdapter.java new file mode 100644 index 0000000000..6065206604 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/adapter/FileSenderAdapter.java @@ -0,0 +1,136 @@ +package com.gh.gamecenter.adapter; + +import android.content.Context; +import android.graphics.drawable.ColorDrawable; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.gh.base.AppController; +import com.gh.common.util.DisplayUtils; +import com.gh.common.util.SpeedUtils; +import com.gh.gamecenter.FileSenderActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.adapter.viewholder.KcSelectGameViewHolder; +import com.gh.gamecenter.kuaichuan.FileInfo; + +import java.text.DecimalFormat; +import java.util.List; + +/** + * Created by khy on 2017/1/20. + */ +public class FileSenderAdapter extends RecyclerView.Adapter { + private Context mContext; + private List mFileInfos; + + private long lastProgress; + + private OnCancelListener cancelListener; + + public FileSenderAdapter(FileSenderActivity activity) { + this.mContext = activity; + this.cancelListener = activity; + mFileInfos = (List) AppController.get("FileInfo", false); + lastProgress = 0; + + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(mContext).inflate(R.layout.kc_game_select_item, parent, false); + return new KcSelectGameViewHolder(view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { + FileInfo fileInfo = mFileInfos.get(position); + + if (holder instanceof KcSelectGameViewHolder) { + KcSelectGameViewHolder viewHolder = (KcSelectGameViewHolder) holder; + viewHolder.gameNameAndSize.setText(fileInfo.getName()); + viewHolder.downloadStatus.setVisibility(View.VISIBLE); + viewHolder.gameProgressbar.setMax(100); + viewHolder.gameProgressbar.setVisibility(View.VISIBLE); + viewHolder.gameLlInfo.setVisibility(View.VISIBLE); + viewHolder.gameSize.setVisibility(View.GONE); + viewHolder.gameNameAndSize.setPadding(0, 0, 0, DisplayUtils.dip2px(mContext, 5)); + if (fileInfo.getBitmap() != null) { + viewHolder.gameThumb.setImageBitmap(fileInfo.getBitmap()); + } + + if (fileInfo.getResult() == FileInfo.FLAG_SUCCESS) { // 传输完成... + viewHolder.gameProgressbar.setProgress(100); + viewHolder.downloadPercentage.setText("100%"); +// viewHolder.downloadStatus.setText("传输成功"); + viewHolder.downloadStatus.setVisibility(View.GONE); + viewHolder.sendOverIcon.setVisibility(View.VISIBLE); + double size = (((float)fileInfo.getSize()/1024)/1024); + DecimalFormat df = new DecimalFormat("#.00"); + String sizeName = df.format(size) + "MB"; + viewHolder.downloadSpeed.setTextColor(mContext.getResources().getColor(R.color.content)); + viewHolder.downloadSpeed.setText(sizeName + "/" + sizeName); + } else if (fileInfo.getResult() == FileInfo.FLAG_FAILURE) { // 传输失败... + double sizeMb = (((float)fileInfo.getSize()/1024)/1024); + double curSizeMb = (((float)fileInfo.getProgress()/1024)/1024); + DecimalFormat df = new DecimalFormat("#.00"); + String sizeName = df.format(sizeMb) + "MB"; + String curSizeName; + if (curSizeMb == 0) { + curSizeName= "0.00MB"; + } else { + curSizeName= df.format(curSizeMb) + "MB"; + } + viewHolder.downloadSpeed.setTextColor(mContext.getResources().getColor(R.color.content)); + viewHolder.downloadSpeed.setText(curSizeName + "/" + sizeName); + viewHolder.downloadStatus.setText("传输失败"); + viewHolder.downloadStatus.setTextColor(mContext.getResources().getColor(R.color.type_huodong)); + viewHolder.downloadStatus.setBackgroundDrawable(new ColorDrawable(0)); + } else if (fileInfo.getResult() == FileInfo.FLAG_CANCEL) { // 取消传输 + double sizeMb = (((float)fileInfo.getSize()/1024)/1024); + double curSizeMb = (((float)fileInfo.getProgress()/1024)/1024); + DecimalFormat df = new DecimalFormat("#.00"); + String sizeName = df.format(sizeMb) + "MB"; + String curSizeName = df.format(curSizeMb) + "MB"; + viewHolder.downloadSpeed.setTextColor(mContext.getResources().getColor(R.color.content)); + viewHolder.downloadSpeed.setText(curSizeName + "/" + sizeName); + viewHolder.downloadStatus.setText("已取消"); + viewHolder.downloadStatus.setBackgroundDrawable(new ColorDrawable(0)); + } else if (fileInfo.getResult() == FileInfo.FLAG_DEFAULT){ // 传输中... + int percent = (int)(fileInfo.getProgress() * 100 / fileInfo.getSize()); + viewHolder.gameProgressbar.setProgress(percent); + viewHolder.downloadStatus.setText("取消"); + viewHolder.downloadStatus.setTextColor(mContext.getResources().getColor(R.color.content)); + viewHolder.downloadStatus.setBackgroundResource(R.drawable.kuaichuan_cancel_bg); + + long speed = (fileInfo.getProgress() - lastProgress) / 1024; + + viewHolder.downloadPercentage.setText(percent + "%"); + viewHolder.downloadSpeed.setTextColor(mContext.getResources().getColor(R.color.theme)); + viewHolder.downloadSpeed.setText(String.format("%s(剩%s)", + SpeedUtils.getSpeed(speed), + SpeedUtils.getRemainTime(fileInfo.getSize(), fileInfo.getProgress(), speed * 1024))); + lastProgress = fileInfo.getProgress(); + + viewHolder.downloadStatus.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + cancelListener.OnCancelPosition(position); + } + }); + } + } + + } + + @Override + public int getItemCount() { + return mFileInfos.size(); + } + + public interface OnCancelListener { + void OnCancelPosition(int position); + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/adapter/KcSelectGameAdapter.java b/app/src/main/java/com/gh/gamecenter/adapter/KcSelectGameAdapter.java new file mode 100644 index 0000000000..8bfea210e5 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/adapter/KcSelectGameAdapter.java @@ -0,0 +1,237 @@ +package com.gh.gamecenter.adapter; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.graphics.drawable.Drawable; +import android.support.v7.widget.RecyclerView; +import android.text.Html; +import android.text.Spanned; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CompoundButton; +import android.widget.TextView; + +import com.gh.common.constant.ItemViewType; +import com.gh.common.util.BitmapUtils; +import com.gh.common.view.CardLinearLayout; +import com.gh.gamecenter.KcSelectGameActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.adapter.viewholder.FooterViewHolder; +import com.gh.gamecenter.adapter.viewholder.KcSelectGameViewHolder; +import com.gh.gamecenter.db.info.ConcernInfo; +import com.gh.gamecenter.entity.InstallGameEntity; +import com.gh.gamecenter.kuaichuan.FileInfo; +import com.gh.gamecenter.manager.ConcernManager; + +import java.io.File; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * Created by khy on 2017/1/20. + */ +public class KcSelectGameAdapter extends RecyclerView.Adapter { + + private Context context; + + private TextView mSelectCount; + + private HashMap selectPosition; // 记录选择游戏的位置 + + private List gameList; + + private int cardMargin; + + public KcSelectGameAdapter(KcSelectGameActivity activity, TextView selectCount) { + this.context = activity; + this.mSelectCount = selectCount; + + gameList = new ArrayList<>(); + selectPosition = new HashMap<>(); + + + cardMargin = (int) context.getResources().getDimension(R.dimen.cardview_margin); + + ConcernManager cManager = new ConcernManager(context); + List runnableGame = cManager.getInstalledGame(); + if (runnableGame.isEmpty()) { + activity.loadEmpty(); + } else { + init(runnableGame); + } + } + + //初始化 + private void init(List runnableGame) { + PackageManager pm = context.getPackageManager(); + List installedPackages = pm.getInstalledPackages(0); + + List arrInstallPackage = new ArrayList<>(); + + for (ConcernInfo concernInfo : runnableGame) { + for (String s : concernInfo.getPackageNames().keySet()) { + if (concernInfo.getPackageNames().get(s)) { + arrInstallPackage.add(s); + } + } + } + + for (int i = 0; i < arrInstallPackage.size(); i++) { + for (PackageInfo installedPackage : installedPackages) { + if ((installedPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0 + && installedPackage.packageName.equals(arrInstallPackage.get(i))) { + selectPosition.put(i, false); + + InstallGameEntity installGameEntity = new InstallGameEntity(); + installGameEntity.setGamePath(installedPackage.applicationInfo.sourceDir); + try{ + Drawable drawable = installedPackage.applicationInfo.loadIcon(pm); + installGameEntity.setGameBm(BitmapUtils.drawableToBitmap(drawable)); + + installGameEntity.setGameVersion(installedPackage.versionName); + installGameEntity.setGameName(installedPackage.applicationInfo.loadLabel(pm).toString()); + installGameEntity.setPackageName(installedPackage.packageName); + + File file = new File(installedPackage.applicationInfo.sourceDir); + installGameEntity.setGameSize(file.length()); + gameList.add(installGameEntity); + }catch(Exception e){ + + } + } + } + } + + notifyDataSetChanged(); + + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + if (viewType == ItemViewType.GAME_NORMAL) { + View view = LayoutInflater.from(parent.getContext()).inflate( + R.layout.kc_game_select_item, parent, false); + return new KcSelectGameViewHolder(view); + } else if (viewType == ItemViewType.LOADING) { + View view = LayoutInflater.from(parent.getContext()).inflate( + R.layout.refresh_footerview, parent, false); + return new FooterViewHolder(view); + } + return null; + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + if (holder instanceof KcSelectGameViewHolder) { + initGameNormal((KcSelectGameViewHolder) holder, gameList.get(position), position); + } + } + + @Override + public int getItemCount() { + if (gameList.isEmpty()) { + return 1; + } + return gameList.size(); + } + + @Override + public int getItemViewType(int position) { + if (gameList.size() != 0 && position >= 0 && position < gameList.size()) { + return ItemViewType.GAME_NORMAL; + } + return ItemViewType.LOADING; + } + + private void initGameNormal(final KcSelectGameViewHolder holder, final InstallGameEntity gameEntity, final int i) { + + // 第一个 + if (i == 0) { + ((CardLinearLayout) holder.itemView).setmTop(cardMargin); + } else { + ((CardLinearLayout) holder.itemView).setmTop(0); + } + + // 最后一个 + if (i == gameList.size() - 1) { + ((CardLinearLayout) holder.itemView).setBottom(true); + } else { + ((CardLinearLayout) holder.itemView).setBottom(false); + } + + double size = (((float)gameEntity.getGameSize()/1024)/1024); + DecimalFormat df = new DecimalFormat("#.00"); + String sizeName = df.format(size) + "MB"; + + Spanned spanned = Html.fromHtml("大小:" + "" + sizeName + ""); + holder.gameSize.setText(spanned); + holder.gameNameAndSize.setText(gameEntity.getGameName()); + holder.gameDes.setText("版本:V" + gameEntity.getGameVersion()); + + holder.gameThumb.setImageBitmap(gameEntity.getGameBm()); + + + holder.selectCB.setVisibility(View.VISIBLE); + if (selectPosition.get(i)) { + holder.selectCB.setChecked(true); + } else { + holder.selectCB.setChecked(false); + } + holder.selectCB.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (isChecked) { + selectPosition.put(i, true); + } else { + selectPosition.put(i, false); + } + + int count = 0; + for (Integer integer : selectPosition.keySet()) { + if (selectPosition.get(integer)) { + count ++; + } + } + + if (count == 0) { + mSelectCount.setText("发送"); + } else { + mSelectCount.setText("发送("+ count +")"); + } + } + }); + + } + + public List getSelectData() { + List fileInfos = new ArrayList<>(); + + for (int i = 0; i < selectPosition.keySet().size(); i++) { + if (selectPosition.get(i)) { + InstallGameEntity installGameEntity = gameList.get(i); + + FileInfo fileInfo = new FileInfo(); + fileInfo.setName(installGameEntity.getGameName()); + fileInfo.setFilePath(installGameEntity.getGamePath()); + fileInfo.setSize(installGameEntity.getGameSize()); + fileInfo.setBitmap(installGameEntity.getGameBm()); + fileInfo.setPackageName(installGameEntity.getPackageName()); + + fileInfos.add(fileInfo); + } + } + + + return fileInfos; + } + + public void setSelectPosition(HashMap selectPosition) { + this.selectPosition = selectPosition; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/adapter/viewholder/KcSelectGameViewHolder.java b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/KcSelectGameViewHolder.java new file mode 100644 index 0000000000..beaaa1efe6 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/KcSelectGameViewHolder.java @@ -0,0 +1,41 @@ +package com.gh.gamecenter.adapter.viewholder; + +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.CheckBox; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.facebook.drawee.view.SimpleDraweeView; +import com.gh.gamecenter.R; + +import butterknife.BindView; +import butterknife.ButterKnife; + +/** + * Created by khy on 2017/1/20. + */ +public class KcSelectGameViewHolder extends RecyclerView.ViewHolder{ + + @BindView(R.id.select_game_order) public TextView gameOrder; + @BindView(R.id.select_game_thumb) public SimpleDraweeView gameThumb; + @BindView(R.id.select_game_nameAndsize) public TextView gameNameAndSize; + @BindView(R.id.select_game_btn) public CheckBox selectCB; + @BindView(R.id.select_game_des) public TextView gameDes; + @BindView(R.id.select_game_size) public TextView gameSize; + @BindView(R.id.select_game_progressbar) public ProgressBar gameProgressbar; + @BindView(R.id.select_game_ll_info) public LinearLayout gameLlInfo; + @BindView(R.id.select_status_btn) public TextView downloadStatus; + @BindView(R.id.download_percentage) public TextView downloadPercentage; + @BindView(R.id.select_download_speed) public TextView downloadSpeed; + @BindView(R.id.send_over_icon) public ImageView sendOverIcon; + @BindView(R.id.select_game_rl) public RelativeLayout selectGameRl; + + public KcSelectGameViewHolder(View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + } +} diff --git a/app/src/main/java/com/gh/gamecenter/download/FileSendFragment.java b/app/src/main/java/com/gh/gamecenter/download/FileSendFragment.java new file mode 100644 index 0000000000..2c230d7317 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/download/FileSendFragment.java @@ -0,0 +1,79 @@ +package com.gh.gamecenter.download; + +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.text.Html; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.gh.gamecenter.CleanApkActivity; +import com.gh.gamecenter.KcSelectGameActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.ReceiverWaitingActivity; +import com.gh.gamecenter.ShareGhActivity; + +/** + * Created by khy on 2017/1/20. + */ +public class FileSendFragment extends Fragment { + + View view; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + } + + @Nullable + @Override + public View onCreateView(final LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + if (view == null) { + view = inflater.inflate(R.layout.fragment_file_send, container, false); + + view.findViewById(R.id.file_send_btn).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getActivity(), KcSelectGameActivity.class); + getActivity().startActivity(intent); + } + }); + + view.findViewById(R.id.file_receiver_btn).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getActivity(), ReceiverWaitingActivity.class); + getActivity().startActivity(intent); + } + }); + + TextView shareGh = (TextView) view.findViewById(R.id.share_gh); + shareGh.setText(Html.fromHtml(""+"好友还没安装光环助手?点这里"+"")); + shareGh.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getActivity(), ShareGhActivity.class); + getActivity().startActivity(intent); + } + }); + + TextView cleanApk = (TextView) view.findViewById(R.id.clean_apk_tv); + cleanApk.setText(Html.fromHtml("手机空间不足?试试" +""+"安装包清理"+"")); + + cleanApk.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(getActivity(), CleanApkActivity.class); + getActivity().startActivity(intent); + } + }); + + } + + return view; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/entity/InstallGameEntity.java b/app/src/main/java/com/gh/gamecenter/entity/InstallGameEntity.java new file mode 100644 index 0000000000..368d9b1611 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/entity/InstallGameEntity.java @@ -0,0 +1,82 @@ +package com.gh.gamecenter.entity; + +import android.graphics.Bitmap; + +/** + * Created by khy on 2017/1/23. + */ +public class InstallGameEntity { + + private String gameName; + + private String gameVersion; + + private long gameSize; + + private Bitmap gameBm; + + private String gamePath; + + /** + * 安装状态 用于清理安装包 + */ + private int installStatus; + + private String packageName; + + public String getGameName() { + return gameName; + } + + public void setGameName(String gameName) { + this.gameName = gameName; + } + + public String getGameVersion() { + return gameVersion; + } + + public void setGameVersion(String gameVersion) { + this.gameVersion = gameVersion; + } + + public long getGameSize() { + return gameSize; + } + + public void setGameSize(long gameSize) { + this.gameSize = gameSize; + } + + public Bitmap getGameBm() { + return gameBm; + } + + public void setGameBm(Bitmap gameBm) { + this.gameBm = gameBm; + } + + public String getGamePath() { + return gamePath; + } + + public void setGamePath(String gamePath) { + this.gamePath = gamePath; + } + + public int getInstallStatus() { + return installStatus; + } + + public void setInstallStatus(int installStatus) { + this.installStatus = installStatus; + } + + public String getPackageName() { + return packageName; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/kuaichuan/BaseTransfer.java b/app/src/main/java/com/gh/gamecenter/kuaichuan/BaseTransfer.java new file mode 100644 index 0000000000..ea4a9346a7 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/kuaichuan/BaseTransfer.java @@ -0,0 +1,30 @@ +package com.gh.gamecenter.kuaichuan; + +/** + * Created by khy on 2017/1/20. + */ +public abstract class BaseTransfer implements Transferable{ + + /** + * 头部分割字符 + */ + public static final String SPERATOR = "::"; + + /** + * 字节数组长度 + */ + public static final int BYTE_SIZE_HEADER = 1024 * 10; + public static final int BYTE_SIZE_SCREENSHOT = 1024 * 40; + public static final int BYTE_SIZE_DATA = 1024 * 4; + + /** + * 传输文件类型 + */ + public static final int TYPE_FILE = 1; //文件类型 + public static final int TYPE_MSG = 2; //消息类型 + + /** + * 传输字节类型 + */ + public static final String UTF_8 = "UTF-8"; +} diff --git a/app/src/main/java/com/gh/gamecenter/kuaichuan/FileInfo.java b/app/src/main/java/com/gh/gamecenter/kuaichuan/FileInfo.java new file mode 100644 index 0000000000..9318d33cbd --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/kuaichuan/FileInfo.java @@ -0,0 +1,181 @@ +package com.gh.gamecenter.kuaichuan; + +import android.graphics.Bitmap; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.Serializable; +import java.util.List; + +/** + * Created by khy on 2017/1/20. + */ +public class FileInfo implements Serializable { + + /** + * 文件传输的标识 + */ + // -1 失败 0 发送中 1 成功 2发送取消 3已安装 + public static final int FLAG_INSTALLED = 4; + public static final int FLAG_CANCEL = 3; + public static final int FLAG_SUCCESS = 2; + public static final int FLAG_DEFAULT = 1; + public static final int FLAG_FAILURE = -1; + + //必要属性 + /** + * 文件路径 + */ + private String filePath; + + /** + * 文件大小 + */ + private long size; + + //非必要属性 + /** + * 文件显示名称 + */ + private String name; + + /** + * 文件缩略图 + */ + private Bitmap bitmap; + + /** + * 文件额外信息 + */ + private String extra; + + /** + * 文件传送的结果 + */ + private int result; + + /** + * 下载进度 + */ + private long progress; + + private String packageName; + + + public FileInfo(){ + + } + + public FileInfo(String filePath, long size) { + this.filePath = filePath; + this.size = size; + } + + public long getProgress() { + return progress; + } + + public void setProgress(long progress) { + this.progress = progress; + } + + public long getSize() { + return size; + } + + public void setSize(long size) { + this.size = size; + } + + public String getFilePath() { + return filePath; + } + + public void setFilePath(String filePath) { + this.filePath = filePath; + } + + public Bitmap getBitmap() { + return bitmap; + } + + public void setBitmap(Bitmap bitmap) { + this.bitmap = bitmap; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + + public int getResult() { + return result; + } + + public void setResult(int result) { + this.result = result; + } + + public String getPackageName() { + return packageName; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + public static String toJsonStr(FileInfo fileInfo){ + String jsonStr = ""; + JSONObject jsonObject = new JSONObject(); + try { + jsonObject.put("filePath", fileInfo.getFilePath()); + jsonObject.put("size", fileInfo.getSize()); + jsonObject.put("name", fileInfo.getName()); + jsonObject.put("packageName", fileInfo.getPackageName()); + } catch (JSONException e) { + e.printStackTrace(); + } + return jsonObject.toString(); + } + + public static FileInfo toObject(String jsonStr){ + FileInfo fileInfo = new FileInfo(); + try { + JSONObject jsonObject = new JSONObject(jsonStr); + String filePath = (String) jsonObject.get("filePath"); + long size = jsonObject.getLong("size"); + String name = jsonObject.getString("name"); + String packageName = jsonObject.getString("packageName"); + fileInfo.setFilePath(filePath); + fileInfo.setSize(size); + fileInfo.setName(name); + fileInfo.setPackageName(packageName); + } catch (JSONException e) { + e.printStackTrace(); + } + return fileInfo; + } + + public static String toJsonArrayStr(List fileInfoList){ + JSONArray jsonArray = new JSONArray(); + if(fileInfoList != null){ + for(FileInfo fileInfo : fileInfoList ){ + if(fileInfo != null){ + try { + jsonArray.put(new JSONObject(toJsonStr(fileInfo))); + } catch (JSONException e) { + e.printStackTrace(); + } + } + } + } + return jsonArray.toString(); + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/kuaichuan/FileReceiver.java b/app/src/main/java/com/gh/gamecenter/kuaichuan/FileReceiver.java new file mode 100644 index 0000000000..06c5cb1ced --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/kuaichuan/FileReceiver.java @@ -0,0 +1,286 @@ +package com.gh.gamecenter.kuaichuan; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.Environment; + +import com.gh.common.util.Utils; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; + + +/** + * 快传传输核心类 + */ +public class FileReceiver extends BaseTransfer implements Runnable { + + /** + * Socket的输入输出流 + */ + private Socket mSocket; + private InputStream mInputStream; + + /** + * 传送文件的信息 + */ + private FileInfo mFileInfo; + + /** + * 控制线程暂停 恢复 + */ + private final Object LOCK = new Object(); + boolean mIsPaused = false; + + boolean isCancel = false; + + /** + * 文件接收的监听 + */ + OnReceiveListener mOnReceiveListener; + + + public FileReceiver(Socket mSocket) { + this.mSocket = mSocket; + } + + public void setOnReceiveListener(OnReceiveListener mOnReceiveListener) { + this.mOnReceiveListener = mOnReceiveListener; + } + + @Override + public void run() { + //初始化 + try { + if(mOnReceiveListener != null) mOnReceiveListener.onStart(); + init(); + } catch (Exception e) { + e.printStackTrace(); + Utils.log("FileReceiver init() --->>> occur expection" + e.toString()); + if(mOnReceiveListener != null) mOnReceiveListener.onFailure(e, mFileInfo); + } + + //解析头部 + try { + parseHeader(); + } catch (Exception e) { + e.printStackTrace(); + Utils.log("FileReceiver parseHeader() --->>> occur expection" + e.toString()); + if(mOnReceiveListener != null) mOnReceiveListener.onFailure(e, mFileInfo); + } + + + //解析主体 + try { + parseBody(); + } catch (Exception e) { + e.printStackTrace(); + Utils.log("FileReceiver parseBody() --->>> occur expection" + e.toString()); + if(mOnReceiveListener != null) mOnReceiveListener.onFailure(e, mFileInfo); + } + + //结束 + try { + finish(); + } catch (Exception e) { + e.printStackTrace(); + Utils.log("FileReceiver finish() --->>> occur expection"+ e.toString()); + if(mOnReceiveListener != null) mOnReceiveListener.onFailure(e, mFileInfo); + } + + + } + + @Override + public void init() throws Exception { + if(this.mSocket != null){ + this.mInputStream = mSocket.getInputStream(); + } + } + + @Override + public void parseHeader() throws IOException { + Utils.log("parseHeader######>>>start"); + isCancel = false; + //Are you sure can read the 1024 byte accurately? + //读取header部分 + byte[] headerBytes = new byte[BYTE_SIZE_HEADER]; + int headTotal = 0; + int readByte = -1; + //开始读取header + while((readByte = mInputStream.read()) != -1){ + headerBytes[headTotal] = (byte) readByte; + + headTotal ++; + if(headTotal == headerBytes.length){ + break; + } + } + Utils.log("FileReceiver receive header size------>>>" + headTotal); + Utils.log("FileReceiver receive header------>>>" + new String(headerBytes, UTF_8)); + + + //读取缩略图部分 + byte[] screenshotBytes = new byte[BYTE_SIZE_SCREENSHOT]; + int screenshotTotal = 0; + int sreadByte = -1; + //开始读取缩略图 + while((sreadByte = mInputStream.read()) != -1){ + screenshotBytes[screenshotTotal] = (byte) sreadByte; + + screenshotTotal ++; + if(screenshotTotal == screenshotBytes.length){ + break; + } + } + + Bitmap bitmap = BitmapFactory.decodeByteArray(screenshotBytes, 0, screenshotBytes.length); +// Utils.log("FileReceiver receive screenshot size------>>>" + screenshotTotal); +// MLog.i(TAG, "FileReceiver receive screenshot------>>>" + new String(headerBytes, UTF_8)); + + + //解析header + String jsonStr = new String(headerBytes, UTF_8); + String[] strArray = jsonStr.split(SPERATOR); + jsonStr = strArray[1].trim(); + mFileInfo = FileInfo.toObject(jsonStr); + mFileInfo.setBitmap(bitmap); + if(mOnReceiveListener != null) mOnReceiveListener.onGetFileInfo(mFileInfo); +// String fileName = getFileName(fileInfo.getFilePath()); +// int fileSize = fileInfo.getSize(); + Utils.log("parseHeader######>>>end"); + } + + @Override + public void parseBody() throws Exception { + Utils.log("parseBody######>>>start"); + + //写入文件 + long fileSize = mFileInfo.getSize(); + + //TODO 快传存储路径 + String path = Environment.getExternalStorageDirectory() + "/GH-KC"; + + File dirFile = new File(path); + if (!dirFile.exists()) { + dirFile.mkdirs(); + } + + File file = new File(dirFile, mFileInfo.getName()+ ".apk"); + + Utils.log("FileReceiver" + file.getAbsolutePath()); + OutputStream bos = new FileOutputStream(file); + + //记录文件开始写入时间 + long startTime = System.currentTimeMillis(); + + byte[] bytes = new byte[BYTE_SIZE_DATA]; + long total = 0; + int len = 0; + + long sTime = System.currentTimeMillis(); + long eTime = 0; + while((len=mInputStream.read(bytes)) != -1){ + synchronized(LOCK) { + if (mIsPaused) { + try { + LOCK.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + bos.write(bytes, 0, len); + total = total + len; + eTime = System.currentTimeMillis(); + if(eTime - sTime > 500) { //大于500ms 才进行一次监听 + sTime = eTime; + if(mOnReceiveListener != null) mOnReceiveListener.onProgress(total, fileSize); + } + + if (isCancel) { + break; + } + } + +// bos.write(bytes, 0, len); +// total = total + len; +// if(mOnReceiveListener != null) mOnReceiveListener.onProgress(total, fileSize); + } + //记录文件结束写入时间 + long endTime = System.currentTimeMillis(); + + Utils.log("接收完成对比 游戏总大小:" + fileSize + "游戏接收大小:" + total); + if (total == fileSize) { + if(mOnReceiveListener != null) mOnReceiveListener.onSuccess(mFileInfo); + } else { + if(mOnReceiveListener != null) mOnReceiveListener.onCancel(mFileInfo); + } + + } + + @Override + public void finish() { + //TODO 实现一些资源的关闭 + + if(mInputStream != null){ + try { + mInputStream.close(); + } catch (IOException e) { + + } + } + + if(mSocket != null && mSocket.isConnected()){ + try { + mSocket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + Utils.log("FileReceiver close socket######>>>"); + } + + /** + * 停止线程下载 + */ + public void pause() { + synchronized(LOCK) { + mIsPaused = true; + LOCK.notifyAll(); + } + } + + /** + * 重新开始线程下载 + */ + public void resume() { + synchronized(LOCK) { + mIsPaused = false; + LOCK.notifyAll(); + } + } + + public void cancel() { + isCancel = true; + } + + /** + * 文件接收的监听 + */ + public interface OnReceiveListener{ + void onStart(); + void onGetFileInfo(FileInfo fileInfo); + void onProgress(long progress, long total); + void onSuccess(FileInfo fileInfo); + void onFailure(Throwable t, FileInfo fileInfo); + void onCancel(FileInfo fileInfo); + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/kuaichuan/FileSender.java b/app/src/main/java/com/gh/gamecenter/kuaichuan/FileSender.java new file mode 100644 index 0000000000..7ed96d8047 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/kuaichuan/FileSender.java @@ -0,0 +1,317 @@ +package com.gh.gamecenter.kuaichuan; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; +import android.media.ThumbnailUtils; + +import com.gh.common.util.Utils; + +import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; + + +/** + * 快传发送核心类 + */ +public class FileSender extends BaseTransfer implements Runnable { + + Context mContext; + + /** + * 传送文件目标的地址以及端口 + */ + private String mServerIpAddress; + private int mPort; + + /** + * 传送文件的信息 + */ + private FileInfo mFileInfo; + + /** + * Socket的输入输出流 + */ + private Socket mSocket; + private OutputStream mOutputStream; + + /** + * 控制线程暂停 恢复 + */ + private final Object LOCK = new Object(); + boolean mIsPaused = false; + + /** + * 判断此线程是否完毕 + */ + boolean mIsFinished = false; + + /** + * 取消操作 + */ + boolean mIsCancel = false; + + /** + * 文件传送的监听 + */ + OnSendListener mOnSendListener; + + public FileSender(Context context, FileInfo mFileInfo, String mServerIpAddress, int mPort) { + this.mContext = context; + this.mFileInfo = mFileInfo; + this.mServerIpAddress = mServerIpAddress; + this.mPort = mPort; + } + + public void setOnSendListener(OnSendListener mOnSendListener) { + this.mOnSendListener = mOnSendListener; + } + + @Override + public void run() { + + //初始化 + try { + if(mOnSendListener != null) mOnSendListener.onStart(); + init(); + }catch(Exception e){ + e.printStackTrace(); + Utils.log("nit() --->>> occur expection" + e.toString()); + if(mOnSendListener != null) mOnSendListener.onFailure(e, mFileInfo); + } + + //解析头部 + try { + parseHeader(); + } catch (Exception e) { + e.printStackTrace(); + Utils.log("parseHeader() --->>> occur expection" + e.toString()); + if(mOnSendListener != null) mOnSendListener.onFailure(e, mFileInfo); + } + + //解析主体 + try { + parseBody(); + } catch (Exception e) { + e.printStackTrace(); + Utils.log("parseBody() --->>> occur expection" + e.toString()); + if(mOnSendListener != null) mOnSendListener.onFailure(e, mFileInfo); + } + + //结束 + try { + finish(); + } catch (Exception e) { + e.printStackTrace(); + Utils.log("finish() --->>> occur expection"+ e.toString()); + if(mOnSendListener != null) mOnSendListener.onFailure(e, mFileInfo); + } + + + } + + @Override + public void init() throws Exception { + this.mSocket = new Socket(mServerIpAddress, mPort); + OutputStream os = this.mSocket.getOutputStream(); + mOutputStream = new BufferedOutputStream(os); + } + + @Override + public void parseHeader() throws Exception { + Utils.log("parseHeader######>>>start"); + + //拼接header + StringBuilder headerSb = new StringBuilder(); + String jsonStr = FileInfo.toJsonStr(mFileInfo); + jsonStr = TYPE_FILE + SPERATOR + jsonStr; + headerSb.append(jsonStr); + int leftLen = BYTE_SIZE_HEADER - jsonStr.getBytes(UTF_8).length; //对于英文是一个字母对应一个字节,中文的情况下对应两个字节。剩余字节数不应该是字节数 + for(int i=0; i < leftLen; i++){ + headerSb.append(" "); + } + byte[] headbytes = headerSb.toString().getBytes(UTF_8); + + Utils.log("parseHeader======" + headerSb + "==" + headbytes.toString()); + //写入header + mOutputStream.write(headbytes); + + + //拼接缩略图 + StringBuilder screenshotSb = new StringBuilder(); + + int ssByteArraySize = 0; + + //缩略图的分类处理 + if(mFileInfo != null){ + Bitmap screenshot; + byte[] bytes; + + Drawable apkThumbnail = WifiUtils.getApkThumbnail(mContext, mFileInfo.getFilePath()); + Bitmap bitmap = WifiUtils.drawableToBitmap(apkThumbnail); + screenshot = ThumbnailUtils.extractThumbnail(bitmap, 96, 96); + if(screenshot != null) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + screenshot.compress(Bitmap.CompressFormat.PNG, 100, baos); + bytes = baos.toByteArray(); + ssByteArraySize = bytes.length; + mOutputStream.write(bytes); + } + } + + int ssLeftLen = BYTE_SIZE_SCREENSHOT - ssByteArraySize; //缩略图剩余的字节数 + for(int i=0; i < ssLeftLen; i++){ + screenshotSb.append(" "); + } + byte[] screenshotBytes = screenshotSb.toString().getBytes(UTF_8); + + //写入缩略图 + mOutputStream.write(screenshotBytes); + + Utils.log("FileSender screenshot write------>>>" + (ssByteArraySize + ssLeftLen)); + + Utils.log("FileSender header write------>>>" + new String(headbytes, UTF_8)); + + Utils.log("parseHeader######>>>end"); + } + + @Override + public void parseBody() throws Exception { + Utils.log("parseBody######>>>start"); + + //写入文件 + long fileSize = mFileInfo.getSize(); + InputStream fis = new FileInputStream(new File(mFileInfo.getFilePath())); + + //记录文件开始写入时间 + long startTime = System.currentTimeMillis(); + + byte[] bytes = new byte[BYTE_SIZE_DATA]; + long total = 0; + int len = 0; + + long sTime = System.currentTimeMillis(); + long eTime = 0; + while((len=fis.read(bytes)) != -1){ + synchronized(LOCK) { + if (mIsPaused) { + try { + LOCK.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + if (mIsCancel) { + if(mOnSendListener != null) mOnSendListener.onCancel(mFileInfo); + break; + } + + mOutputStream.write(bytes, 0, len); + total = total + len; + eTime = System.currentTimeMillis(); + if(eTime - sTime > 500) { //大于500ms 才进行一次监听 + sTime = eTime; + if(mOnSendListener != null) mOnSendListener.onProgress(total, fileSize); + } + } + + +// mOutputStream.write(bytes, 0, len); +// total = total + len; +// if(mOnSendListener != null) mOnSendListener.onProgress(total, fileSize); + } + + //记录文件结束写入时间 + long endTime = System.currentTimeMillis(); + Utils.log("FileSender body write######>>>" + total); + + mOutputStream.flush(); + //每一次socket连接就是一个通信,如果当前OutputStream不关闭的话。FileReceiver端会阻塞在那里 + mOutputStream.close(); + Utils.log("parseBody######>>>end"); + + if (!mIsCancel) { + if(mOnSendListener != null) mOnSendListener.onSuccess(mFileInfo); + } + + mIsFinished = true; + } + + @Override + public void finish() { + + if(mOutputStream != null){ + try { + mOutputStream.close(); + } catch (IOException e) { + + } + } + + if(mSocket != null && mSocket.isConnected()){ + try { + mSocket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + Utils.log("FileSender close socket######>>>"); + } + + /** + * 停止线程下载 + */ + public void pause() { + synchronized(LOCK) { + mIsPaused = true; + LOCK.notifyAll(); + } + } + + /** + * 重新开始线程下载 + */ + public void resume() { + synchronized(LOCK) { + mIsPaused = false; + LOCK.notifyAll(); + } + } + + /** + * 取消操作 + */ + public void cancel(){ + mIsCancel = true; + } + + + /** + * 文件是否在传送中 + * @return + */ + public boolean isRunning(){ + return !mIsFinished; + } + + + /** + * 文件传送的监听 + */ + public interface OnSendListener{ + void onStart(); + void onProgress(long progress, long total); + void onSuccess(FileInfo fileInfo); + void onFailure(Throwable t, FileInfo fileInfo); + void onCancel(FileInfo fileInfo); + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/kuaichuan/IpPortInfo.java b/app/src/main/java/com/gh/gamecenter/kuaichuan/IpPortInfo.java new file mode 100644 index 0000000000..f038ec4b38 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/kuaichuan/IpPortInfo.java @@ -0,0 +1,44 @@ +package com.gh.gamecenter.kuaichuan; + +import java.io.Serializable; +import java.net.InetAddress; + +/** + * Ip Port 实体 + */ +public class IpPortInfo implements Serializable { + + private InetAddress inetAddress; + private int port; + private String senderName; + + public IpPortInfo(InetAddress inetAddress, int port, String senderName) { + this.inetAddress = inetAddress; + this.port = port; + this.senderName = senderName; + } + + public InetAddress getInetAddress() { + return inetAddress; + } + + public void setInetAddress(InetAddress inetAddress) { + this.inetAddress = inetAddress; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public String getSenderName() { + return senderName; + } + + public void setSenderName(String senderName) { + this.senderName = senderName; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/kuaichuan/Transferable.java b/app/src/main/java/com/gh/gamecenter/kuaichuan/Transferable.java new file mode 100644 index 0000000000..45e091e6e8 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/kuaichuan/Transferable.java @@ -0,0 +1,34 @@ +package com.gh.gamecenter.kuaichuan; + +/** + * Created by khy on 2017/1/20. + */ +public interface Transferable { + + /** + * + * @throws Exception + */ + void init() throws Exception; + + + /** + * + * @throws Exception + */ + void parseHeader() throws Exception; + + + /** + * + * @throws Exception + */ + void parseBody() throws Exception; + + + /** + * + * @throws Exception + */ + void finish() throws Exception; +} diff --git a/app/src/main/java/com/gh/gamecenter/kuaichuan/WifiUtils.java b/app/src/main/java/com/gh/gamecenter/kuaichuan/WifiUtils.java index ed4ddc474d..ea6ae0d310 100644 --- a/app/src/main/java/com/gh/gamecenter/kuaichuan/WifiUtils.java +++ b/app/src/main/java/com/gh/gamecenter/kuaichuan/WifiUtils.java @@ -24,7 +24,7 @@ public class WifiUtils { public static final String NO_PASSWORD_WPS = "[WPS][ESS]"; /** - * 过滤有密码的Wifi扫描结果集合 和WIFI名称为空 不包含GHZS + * 过滤有密码的Wifi扫描结果集合 和WIFI名称为空 不包含ghZS * @param scanResultList * @return */ @@ -38,7 +38,7 @@ public class WifiUtils { if(!TextUtils.isEmpty(scanResult.SSID) && scanResult.capabilities != null && scanResult.capabilities.equals(NO_PASSWORD) || scanResult.capabilities != null && scanResult.capabilities.equals(NO_PASSWORD_WPS)){ - if (scanResult.SSID.contains("GHZS")) { + if (scanResult.SSID.contains("ghZS")) { resultList.add(scanResult); } } diff --git a/app/src/main/res/drawable-hdpi/clean_apk_icon.png b/app/src/main/res/drawable-hdpi/clean_apk_icon.png new file mode 100644 index 0000000000..683f76a8ef Binary files /dev/null and b/app/src/main/res/drawable-hdpi/clean_apk_icon.png differ diff --git a/app/src/main/res/drawable-hdpi/kc_checkbox_select.png b/app/src/main/res/drawable-hdpi/kc_checkbox_select.png new file mode 100644 index 0000000000..9798c1c171 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/kc_checkbox_select.png differ diff --git a/app/src/main/res/drawable-hdpi/kc_checkbox_unselect.png b/app/src/main/res/drawable-hdpi/kc_checkbox_unselect.png new file mode 100644 index 0000000000..32e3809ed2 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/kc_checkbox_unselect.png differ diff --git a/app/src/main/res/drawable-hdpi/kc_send_over_icon.png b/app/src/main/res/drawable-hdpi/kc_send_over_icon.png new file mode 100644 index 0000000000..e7318bef40 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/kc_send_over_icon.png differ diff --git a/app/src/main/res/drawable-nodpi/kuaichuan_receiver_waiting.gif b/app/src/main/res/drawable-nodpi/kuaichuan_receiver_waiting.gif new file mode 100644 index 0000000000..76ac4e6444 Binary files /dev/null and b/app/src/main/res/drawable-nodpi/kuaichuan_receiver_waiting.gif differ diff --git a/app/src/main/res/drawable-nodpi/scan_receiver.gif b/app/src/main/res/drawable-nodpi/scan_receiver.gif new file mode 100644 index 0000000000..cc837cbfa8 Binary files /dev/null and b/app/src/main/res/drawable-nodpi/scan_receiver.gif differ diff --git a/app/src/main/res/drawable/game_item_btn_red_dn.xml b/app/src/main/res/drawable/game_item_btn_red_dn.xml new file mode 100644 index 0000000000..30a5ab8040 --- /dev/null +++ b/app/src/main/res/drawable/game_item_btn_red_dn.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/game_item_btn_red_style.xml b/app/src/main/res/drawable/game_item_btn_red_style.xml new file mode 100644 index 0000000000..9d98a8439a --- /dev/null +++ b/app/src/main/res/drawable/game_item_btn_red_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/game_item_btn_red_up.xml b/app/src/main/res/drawable/game_item_btn_red_up.xml new file mode 100644 index 0000000000..58766df7b4 --- /dev/null +++ b/app/src/main/res/drawable/game_item_btn_red_up.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/kc_checkbox_style.xml b/app/src/main/res/drawable/kc_checkbox_style.xml new file mode 100644 index 0000000000..27a140d615 --- /dev/null +++ b/app/src/main/res/drawable/kc_checkbox_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/kuaichuan_cancel_bg.xml b/app/src/main/res/drawable/kuaichuan_cancel_bg.xml new file mode 100644 index 0000000000..ccd6248b90 --- /dev/null +++ b/app/src/main/res/drawable/kuaichuan_cancel_bg.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/sender_hint_bg.xml b/app/src/main/res/drawable/sender_hint_bg.xml new file mode 100644 index 0000000000..016e9a9268 --- /dev/null +++ b/app/src/main/res/drawable/sender_hint_bg.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_choosereceiver.xml b/app/src/main/res/layout/activity_choosereceiver.xml new file mode 100644 index 0000000000..30cbfdd8d5 --- /dev/null +++ b/app/src/main/res/layout/activity_choosereceiver.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_clean_apk.xml b/app/src/main/res/layout/activity_clean_apk.xml new file mode 100644 index 0000000000..3ff6bc1fe1 --- /dev/null +++ b/app/src/main/res/layout/activity_clean_apk.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_downloadmanager.xml b/app/src/main/res/layout/activity_downloadmanager.xml index c6801264bc..b56054bfc1 100644 --- a/app/src/main/res/layout/activity_downloadmanager.xml +++ b/app/src/main/res/layout/activity_downloadmanager.xml @@ -69,6 +69,22 @@ android:textColor="@android:color/white" android:textSize="10sp" /> + + + + + - - - - - - - - + android:layout_height="match_parent" + android:overScrollMode="never" > + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_file_sender.xml b/app/src/main/res/layout/activity_file_sender.xml new file mode 100644 index 0000000000..3a5c3213ae --- /dev/null +++ b/app/src/main/res/layout/activity_file_sender.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_kc_select_game.xml b/app/src/main/res/layout/activity_kc_select_game.xml new file mode 100644 index 0000000000..7620c8e020 --- /dev/null +++ b/app/src/main/res/layout/activity_kc_select_game.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_receiver_waiting.xml b/app/src/main/res/layout/activity_receiver_waiting.xml new file mode 100644 index 0000000000..98a2e50f97 --- /dev/null +++ b/app/src/main/res/layout/activity_receiver_waiting.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_file_send.xml b/app/src/main/res/layout/fragment_file_send.xml new file mode 100644 index 0000000000..40108cc608 --- /dev/null +++ b/app/src/main/res/layout/fragment_file_send.xml @@ -0,0 +1,58 @@ + + + +