-
DOWNLOAD
+
光环助手
+
乐于分享的人是最帅的^_^
仅限安卓系统
+
diff --git a/app/src/main/java/com/gh/common/util/ShareUtils.java b/app/src/main/java/com/gh/common/util/ShareUtils.java
index ed29c92211..9959a0cd6f 100644
--- a/app/src/main/java/com/gh/common/util/ShareUtils.java
+++ b/app/src/main/java/com/gh/common/util/ShareUtils.java
@@ -230,7 +230,7 @@ public class ShareUtils {
Intent data=new Intent(Intent.ACTION_SENDTO);
data.setData(Uri.parse("mailto:"));
data.putExtra(Intent.EXTRA_SUBJECT, "快来试试光环助手");
- data.putExtra(Intent.EXTRA_TEXT, "我用光环助手一段时间了,在里面可以下载各种热门卡牌手游的加速版,绿色安全,超级省心,做日常效率提高3-5倍!\n" +
+ data.putExtra(Intent.EXTRA_TEXT, "我用光环助手一段时间了,在里面可以下载各种热门卡牌手游的加速版,绿色安全,超级省心,日常效率提高3-5倍!\n" +
"\n" +
"不用肝的感觉真好,快来试试。\n" +
"\n" +
@@ -292,7 +292,7 @@ public class ShareUtils {
}
}
} else {
- title = "不用肝的感觉真好";
+ title = "玩手游不用肝的感觉真好";
summary = "绿色安全的手游加速助手";
}
params.putString(QQShare.SHARE_TO_QQ_TITLE, title);
@@ -333,7 +333,7 @@ public class ShareUtils {
}
}
} else {
- title = "不用肝的感觉真好";
+ title = "玩手游不用肝的感觉真好";
summary = "绿色安全的手游加速助手";
}
@@ -371,7 +371,7 @@ public class ShareUtils {
}
}
} else {
- title = "不用肝的感觉真好";
+ title = "玩手游不用肝的感觉真好";
summary = "绿色安全的手游加速助手";
}
@@ -465,7 +465,7 @@ public class ShareUtils {
}
}
} else {
- smsBody = "这个App可以下载各种热门卡牌手游的加速版,绿色安全,超级省心,做日常效率提高3-5倍!光环助手官网:" + shareUrl;
+ smsBody = "这个App可以下载各种热门卡牌手游的加速版,绿色安全,超级省心,日常效率提高3-5倍!光环助手官网地址:" + shareUrl;
}
Intent sendIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("smsto:"));
diff --git a/app/src/main/java/com/gh/common/util/UserIconUtils.java b/app/src/main/java/com/gh/common/util/UserIconUtils.java
index 4b627032fb..4c902fbb30 100644
--- a/app/src/main/java/com/gh/common/util/UserIconUtils.java
+++ b/app/src/main/java/com/gh/common/util/UserIconUtils.java
@@ -34,4 +34,27 @@ public class UserIconUtils {
return "res:///" + R.drawable.user_default_icon1;
}
}
+
+ public static String getUserIconUrl(int i) {
+ switch (i) {
+ case 1:
+ return "http://image.ghzhushou.com/pic/default_icon_1.png";
+ case 2:
+ return "http://image.ghzhushou.com/pic/default_icon_2.png";
+ case 3:
+ return "http://image.ghzhushou.com/pic/default_icon_3.png";
+ case 4:
+ return "http://image.ghzhushou.com/pic/default_icon_4.png";
+ case 5:
+ return "http://image.ghzhushou.com/pic/default_icon_5.png";
+ case 6:
+ return "http://image.ghzhushou.com/pic/default_icon_6.png";
+ case 7:
+ return "http://image.ghzhushou.com/pic/default_icon_7.png";
+ case 8:
+ return "http://image.ghzhushou.com/pic/default_icon_8.png";
+ default:
+ return "http://image.ghzhushou.com/pic/default_icon_1.png";
+ }
+ }
}
diff --git a/app/src/main/java/com/gh/common/view/RadarLayout.java b/app/src/main/java/com/gh/common/view/RadarLayout.java
new file mode 100644
index 0000000000..6472e3e30d
--- /dev/null
+++ b/app/src/main/java/com/gh/common/view/RadarLayout.java
@@ -0,0 +1,255 @@
+package com.gh.common.view;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.animation.LinearInterpolator;
+import android.widget.FrameLayout;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by khy on 2017/2/16.
+ * 快传接收方 的雷达动画
+ */
+public class RadarLayout extends FrameLayout {
+
+ public static final int INFINITE = 0;
+
+ private static final int DEFAULT_COUNT = 4;
+ private static final int DEFAULT_COLOR = Color.rgb(0, 116, 193);
+ private static final int DEFAULT_DURATION = 7000;
+ private static final int DEFAULT_REPEAT = INFINITE;
+ private static final int DEFAULT_STROKE_WIDTH = 2;
+
+ private int mCount;
+ private int mDuration;
+ private int mRepeat;
+
+ private AnimatorSet mAnimatorSet;
+
+ private Paint mPaint;
+ private int mColor;
+ private float mRadius;
+ private float mCenterX;
+ private float mCenterY;
+ private int mStrokeWidth;
+ private boolean mIsStarted;
+ private boolean mUseRing;
+
+ public RadarLayout(Context context) {
+ super(context);
+ initGlobalparams();
+ }
+
+ public RadarLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ initGlobalparams();
+ }
+
+ public RadarLayout(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ initGlobalparams();
+ }
+
+ private void initGlobalparams() {
+ mColor = DEFAULT_COLOR;
+ mCount = DEFAULT_COUNT;
+ mDuration = DEFAULT_DURATION;
+ mRepeat = DEFAULT_REPEAT;
+ mUseRing = false;
+ mStrokeWidth = dip2px(DEFAULT_STROKE_WIDTH);
+
+ build();
+ }
+
+ public synchronized void start() {
+ if (mAnimatorSet == null || mIsStarted) {
+ return;
+ }
+
+ mAnimatorSet.start();
+ }
+
+ public synchronized void stop() {
+ if (mAnimatorSet == null || !mIsStarted) {
+ return;
+ }
+ mAnimatorSet.end();
+ }
+
+ public synchronized boolean isStarted() {
+ return (mAnimatorSet != null && mIsStarted);
+ }
+
+ public int getCount() {
+ return mCount;
+ }
+
+ public int getDuration() {
+ return mDuration;
+ }
+
+ public void setCount(int count) {
+ if (count < 0) {
+ throw new IllegalArgumentException("Count cannot be negative");
+ }
+
+ if (count != mCount) {
+ mCount = count;
+ reset();
+ invalidate();
+ }
+ }
+
+ public void setDuration(int millis) {
+ if (millis < 0) {
+ throw new IllegalArgumentException("Duration cannot be negative");
+ }
+
+ if (millis != mDuration) {
+ mDuration = millis;
+ reset();
+ invalidate();
+ }
+ }
+
+ public void setColor(int color) {
+ if (mColor != color) {
+ mColor = color;
+ reset();
+ invalidate();
+ }
+ }
+
+ public void setUseRing(boolean useRing) {
+ if (mUseRing != useRing) {
+ mUseRing = useRing;
+ reset();
+ invalidate();
+ }
+ }
+
+ @Override
+ public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ int width = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
+ int height = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
+
+ // 确定圆的圆点坐标及半径
+ mCenterX = width * 0.5f;
+ mCenterY = height * 0.5f;
+ mRadius = Math.min(width, height) * 0.5f;
+ }
+
+ private void clear() {
+ stop();
+ removeAllViews();
+ }
+
+ private void build() {
+
+ LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+
+ int repeatCount = (mRepeat == INFINITE) ? ObjectAnimator.INFINITE : mRepeat;
+
+ List animators = new ArrayList();
+ for (int index = 0; index < mCount; index++) {
+ RadarView radarView = new RadarView(getContext());
+ radarView.setScaleX(0);
+ radarView.setScaleY(0);
+ radarView.setAlpha(1);
+
+ addView(radarView, index, params);
+
+ // 计算时间间隔
+ long delay = index * mDuration / mCount;
+
+ // 属性动画
+ animators.add(create(radarView, "scaleX", repeatCount, delay, 0, 1));
+ animators.add(create(radarView, "scaleY", repeatCount, delay, 0, 1));
+ animators.add(create(radarView, "alpha", repeatCount, delay, 1, 0));
+ }
+
+ mAnimatorSet = new AnimatorSet();
+ mAnimatorSet.playTogether(animators);
+ mAnimatorSet.setInterpolator(new LinearInterpolator());
+ mAnimatorSet.setDuration(mDuration);
+ mAnimatorSet.addListener(mAnimatorListener);
+ }
+
+ private ObjectAnimator create(View target, String propertyName, int repeatCount, long delay, float from, float to) {
+ ObjectAnimator animator = ObjectAnimator.ofFloat(target, propertyName, from, to);
+ animator.setRepeatCount(repeatCount);
+ animator.setRepeatMode(ObjectAnimator.RESTART);
+ animator.setStartDelay(delay);
+ return animator;
+ }
+
+ private void reset() {
+ boolean isStarted = isStarted();
+
+ clear();
+ build();
+
+ if (isStarted) {
+ start();
+ }
+ }
+
+ private class RadarView extends View {
+
+ public RadarView(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (null == mPaint) {
+ mPaint = new Paint();
+ mPaint.setColor(mColor);
+ mPaint.setAntiAlias(true);
+ // 注意Style的用法,【STROKE:画环】【FILL:画圆】
+ mPaint.setStyle(mUseRing ? Paint.Style.STROKE : Paint.Style.FILL);
+ mPaint.setStrokeWidth(mUseRing ? mStrokeWidth : 0);
+ }
+ // 画圆或环
+ canvas.drawCircle(mCenterX, mCenterY, mUseRing ? mRadius - mStrokeWidth : mRadius, mPaint);
+ }
+ }
+
+ private int dip2px(float dpValue) {
+ final float scale = getResources().getDisplayMetrics().density;
+ return (int) (dpValue * scale + 0.5f);
+ }
+
+ private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
+
+ @Override
+ public void onAnimationStart(Animator animator) {
+ mIsStarted = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ mIsStarted = false;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animator) {
+ mIsStarted = false;
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animator) {
+ }
+ };
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/gh/common/view/SwipeLayout.java b/app/src/main/java/com/gh/common/view/SwipeLayout.java
index 0fbb5d9a24..3c49709c97 100644
--- a/app/src/main/java/com/gh/common/view/SwipeLayout.java
+++ b/app/src/main/java/com/gh/common/view/SwipeLayout.java
@@ -524,7 +524,6 @@ public class SwipeLayout extends FrameLayout {
private int mEventCounter = 0;
protected void dispatchSwipeEvent(int surfaceLeft, int surfaceTop, int dx, int dy) {
- Utils.log("=======dispatchSwipeEvent");
DragEdge edge = getDragEdge();
boolean open = true;
if (edge == DragEdge.Left) {
diff --git a/app/src/main/java/com/gh/gamecenter/ChooseReceiverActivity.java b/app/src/main/java/com/gh/gamecenter/ChooseReceiverActivity.java
index 1b445416a0..ecb4626fd4 100644
--- a/app/src/main/java/com/gh/gamecenter/ChooseReceiverActivity.java
+++ b/app/src/main/java/com/gh/gamecenter/ChooseReceiverActivity.java
@@ -1,14 +1,24 @@
package com.gh.gamecenter;
+import android.animation.Animator;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.graphics.Color;
import android.net.wifi.ScanResult;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.Html;
+import android.view.Gravity;
import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+import android.view.animation.ScaleAnimation;
+import android.view.animation.TranslateAnimation;
+import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
@@ -20,6 +30,7 @@ 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.DisplayUtils;
import com.gh.common.util.UserIconUtils;
import com.gh.common.util.Utils;
import com.gh.gamecenter.kuaichuan.BaseTransfer;
@@ -65,6 +76,12 @@ public class ChooseReceiverActivity extends BaseActivity implements View.OnClick
@BindView(R.id.scan_user_des) TextView mScanUserDes;
@BindView(R.id.reuse_actionbar) RelativeLayout mActionbar;
@BindView(R.id.scan_hint) TextView mScanHint;
+ @BindView(R.id.choosereceiver_roket_anim) RelativeLayout mRoketAnimRl;
+ @BindView(R.id.choosereceiver_ready_rl) RelativeLayout mRoketRl;
+ @BindView(R.id.choosereceiver_roket_anim_bottom) LinearLayout mRoketAnimBottom;
+ @BindView(R.id.choosereceiver_roket_anim_top) ImageView mRoketTop;
+ @BindView(R.id.choosereceiver_roket_left) ImageView mRoketAnimLeft;
+ @BindView(R.id.choosereceiver_roket_right) ImageView mRoketAnimRight;
private List
mScanResultList;
@@ -78,6 +95,10 @@ public class ChooseReceiverActivity extends BaseActivity implements View.OnClick
private SharedPreferences sp;
+ private ScaleAnimation mScaleAnimation; // 火箭喷火动画
+
+ private TranslateAnimation mTranslateAnimation; // 整个火箭移动页面
+
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -95,6 +116,20 @@ public class ChooseReceiverActivity extends BaseActivity implements View.OnClick
View contentView = View.inflate(this, R.layout.activity_choosereceiver, null);
init(contentView, "发送游戏");
+
+ // 添加分享图标
+ TextView hintTv = new TextView(this);
+ hintTv.setText("操作说明");
+ hintTv.setTextColor(Color.WHITE);
+ hintTv.setGravity(Gravity.CENTER);
+ hintTv.setPadding(DisplayUtils.dip2px(this, 13),0 ,DisplayUtils.dip2px(this, 13),0);
+ RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
+ params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT );
+ RelativeLayout reuse_actionbar = (RelativeLayout) contentView.findViewById(
+ R.id.reuse_actionbar);
+ reuse_actionbar.addView(hintTv, params);
+
//修改沉浸栏以及ActionBar 颜色
mActionbar.setBackgroundColor(getResources().getColor(R.color.scan_bg));
SystemBarTintManager tintManager = getTintManager();
@@ -103,13 +138,39 @@ public class ChooseReceiverActivity extends BaseActivity implements View.OnClick
}
init();
+
+ hintTv.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showConnHintDialog();
+ }
+ });
+
+ boolean showConnHintDialog = sp.getBoolean("showConnHintDialog", true);
+ if (showConnHintDialog || (getIntent() != null && getIntent().getExtras() != null
+ && getIntent().getExtras().getBoolean("showConnHintDialog"))) {
+ if (showConnHintDialog) {
+ sp.edit().putBoolean("showConnHintDialog", false).apply();
+ }
+ showConnHintDialog();
+ }
+ }
+
+ private void showConnHintDialog() {
+ DialogUtils.showHintDialog(ChooseReceiverActivity.this, "请告诉你的好友这样操作:", "1.拿出手机,打开光环助手 " +
+ "\n2.点击左上角“↓”按钮 \n3.点击“我要接收”", "确定");
}
@OnClick(R.id.scan_hint)
public void onScanHintListener() {
- DialogUtils.showHintDialog(this, "请告诉你的好友这样操作:", "1.拿出手机,打开光环助手 " +
- "\n2.点击首页左上角,进入下载管理 \n3.点击“零流量传送”,再点击“我要接收”",
- "确定");
+// DialogUtils.showHintDialog(this, "请告诉你的好友这样操作:", "1.拿出手机,打开光环助手 " +
+// "\n2.点击首页左上角,进入下载管理 \n3.点击“零流量传送”,再点击“我要接收”",
+// "确定");
+
+ // TODO 关闭扫描??
+
+ Intent intent = new Intent(this, ShareGhActivity.class);
+ startActivity(intent);
}
private void init() {
@@ -122,7 +183,7 @@ public class ChooseReceiverActivity extends BaseActivity implements View.OnClick
.build();
mScanGif.setController(controller);
- mScanHint.setText(Html.fromHtml(""+"搜不到对方?"+""));
+ mScanHint.setText(Html.fromHtml(""+"好友还没安装光环助手?请点这里"+""));
isStopScan = false;
isDestroy = false;
@@ -225,6 +286,9 @@ public class ChooseReceiverActivity extends BaseActivity implements View.OnClick
//1.连接网络
private void connReceiverWifi(int connPosition) {
+ // 进入动画页面
+ readyAnimView();
+
if (isStopScan) {
return;
}
@@ -271,6 +335,7 @@ public class ChooseReceiverActivity extends BaseActivity implements View.OnClick
startFileSenderServer(ipAddress);
} catch (Exception e) {
isStopScan = false;
+ handler.sendEmptyMessage(0);
Utils.log("UDP通信异常--startFileSenderServer" + e.toString());
e.printStackTrace();
}
@@ -305,6 +370,18 @@ public class ChooseReceiverActivity extends BaseActivity implements View.OnClick
// mDatagramSocket = new DatagramSocket(serverPort);
byte[] receiveData = new byte[1024];
byte[] sendData;
+ Utils.log("=====ip::" + ipAddress);
+ if (!ipAddress.equals("192.168.43.1")) {
+ // 连接失败,可能是连接的热点已经关闭, 关闭动画,开启扫描
+ isStopScan = false;
+ handler.sendEmptyMessage(0);
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ connFailedAnimView();
+ }
+ });
+ }
InetAddress ipAddressName = InetAddress.getByName(ipAddress); // 转译
//发送 即将发送的文件列表 到文件接收方
@@ -336,13 +413,13 @@ public class ChooseReceiverActivity extends BaseActivity implements View.OnClick
userMap.put("usericon", String.valueOf(conUserIconTag));
AppController.put("userMap", userMap);
- // 进入文件发送列表界面 (并且通知文件接收方进入文件接收列表界面)
- Intent intent = new Intent(ChooseReceiverActivity.this, FileSenderActivity.class);
- startActivity(intent);
- closeSocket();
- Intent resultIntent= new Intent();
- setResult(0x123, resultIntent);
- finish();
+
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ connSuccessAnimView();
+ }
+ });
break;
}
}
@@ -366,21 +443,143 @@ public class ChooseReceiverActivity extends BaseActivity implements View.OnClick
}
}
+ // 连接中-动画
+ private void readyAnimView() {
+
+ mRoketRl.setVisibility(View.VISIBLE);
+ mRoketRl.animate()
+ .alpha(1f)
+ .setDuration(1000)
+ .setListener(null);
+
+ mScaleAnimation = new ScaleAnimation(0.5f, 0.8f, 0.5f, 0.8f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
+ mScaleAnimation.setDuration(250);
+ mScaleAnimation.setRepeatCount(Animation.INFINITE);
+ mScaleAnimation.setRepeatMode(Animation.REVERSE);
+
+ mRoketAnimLeft.startAnimation(mScaleAnimation);
+ mRoketAnimRight.startAnimation(mScaleAnimation);
+ }
+
+ // 连接成功-动画
+ private void connSuccessAnimView() {
+ if (mScaleAnimation != null) {
+ mScaleAnimation.cancel();
+ }
+ AlphaAnimation alphaAnimation = new AlphaAnimation(1f, 0.6f);
+ alphaAnimation.setDuration(250);
+ alphaAnimation.setRepeatCount(Animation.INFINITE);
+ alphaAnimation.setRepeatMode(Animation.REVERSE);
+ mRoketAnimLeft.startAnimation(alphaAnimation);
+ mRoketAnimRight.startAnimation(alphaAnimation);
+
+ mScaleAnimation = new ScaleAnimation(0.5f, 0.8f, 0.5f, 0.8f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
+ mScaleAnimation.setDuration(250);
+ mScaleAnimation.setRepeatCount(Animation.INFINITE);
+ mScaleAnimation.setRepeatMode(Animation.REVERSE);
+
+ mRoketAnimLeft.setImageResource(R.drawable.kuaichuan_rocket_fire);
+ mRoketAnimRight.setImageResource(R.drawable.kuaichuan_rocket_fire);
+
+ LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) mRoketAnimRight.getLayoutParams();
+ layoutParams.height = LinearLayout.LayoutParams.MATCH_PARENT;
+ layoutParams.width = DisplayUtils.dip2px(this, 25);
+
+ mRoketAnimRight.setLayoutParams(layoutParams);
+ LinearLayout.LayoutParams layoutParams2 = (LinearLayout.LayoutParams) mRoketAnimLeft.getLayoutParams();
+ layoutParams2.height = LinearLayout.LayoutParams.MATCH_PARENT;
+ layoutParams2.width = DisplayUtils.dip2px(this, 25);
+
+ layoutParams2.setMargins(0, 0, DisplayUtils.dip2px(ChooseReceiverActivity.this, 14), 0);
+ mRoketAnimLeft.setLayoutParams(layoutParams2);
+
+
+ if (mScaleAnimation == null) {
+ mScaleAnimation.cancel();
+ }
+
+ mTranslateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, -1000);
+ mTranslateAnimation.setDuration(1000);
+ mTranslateAnimation.setInterpolator(new AccelerateInterpolator(2.0f));
+// mTranslateAnimation.setFillAfter(true);
+
+ mRoketAnimRl.startAnimation(mTranslateAnimation);
+
+ mTranslateAnimation.setAnimationListener(new Animation.AnimationListener() {
+ @Override
+ public void onAnimationStart(Animation animation) {
+
+ }
+
+ @Override
+ public void onAnimationEnd(Animation animation) {
+ mRoketAnimRl.setVisibility(View.GONE);
+ Intent intent = new Intent(ChooseReceiverActivity.this, FileSenderActivity.class);
+ startActivity(intent);
+ closeSocket();
+ Intent resultIntent= new Intent();
+ setResult(0x123, resultIntent);
+ finish();
+ }
+
+ @Override
+ public void onAnimationRepeat(Animation animation) {
+
+ }
+ });
+ }
+
+ // 连接失败-动画
+ private void connFailedAnimView() {
+ Utils.toast(ChooseReceiverActivity.this, "连接失败");
+ if (mScaleAnimation == null) {
+ mScaleAnimation.cancel();
+ }
+ mRoketRl.animate()
+ .alpha(0f)
+ .setDuration(1000)
+ .setListener(new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mRoketRl.setVisibility(View.GONE);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+
+ }
+
+ });
+ }
+
@Override
public void onBackPressed() {
super.onBackPressed();
closeSocket();
+ AppController.remove("FileInfo");
}
@OnClick(R.id.actionbar_rl_back)
public void onBackListener() {
closeSocket();
+ AppController.remove("FileInfo");
}
@Override
protected void onDestroy() {
super.onDestroy();
isDestroy = true;
+ isStopScan = true;
}
/**
@@ -389,7 +588,7 @@ public class ChooseReceiverActivity extends BaseActivity implements View.OnClick
private void closeSocket(){
isStopScan = true;
if(mDatagramSocket != null) {
- mDatagramSocket.disconnect();
+// 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
index e079dee5fb..32ae73fb75 100644
--- a/app/src/main/java/com/gh/gamecenter/CleanApkActivity.java
+++ b/app/src/main/java/com/gh/gamecenter/CleanApkActivity.java
@@ -51,7 +51,7 @@ public class CleanApkActivity extends BaseActivity implements CleanApkAdapter.On
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View contentView = View.inflate(this, R.layout.activity_clean_apk, null);
- init(contentView, "选择游戏");
+ init(contentView, "安装包清理");
mNodataSkipLl.setVisibility(View.GONE);
@@ -92,7 +92,7 @@ public class CleanApkActivity extends BaseActivity implements CleanApkAdapter.On
if ("停止扫描".equals(s)) {
mAdapter.isStopScan();
} else {
- if (s.equals("一键删除")) {
+ if (s.equals("立即删除")) {
Utils.toast(CleanApkActivity.this, "请选择需要删除的安装包");
return;
}
@@ -103,7 +103,7 @@ public class CleanApkActivity extends BaseActivity implements CleanApkAdapter.On
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() {
@@ -169,7 +169,7 @@ public class CleanApkActivity extends BaseActivity implements CleanApkAdapter.On
@Override
public void onScanOver() {
- mApkDeleteBtn.setText("一键删除");
+ mApkDeleteBtn.setText("立即删除");
mApkDeleteBtn.setBackgroundResource(R.drawable.game_item_btn_red_style);
long allSize = 0;
diff --git a/app/src/main/java/com/gh/gamecenter/DownloadManagerActivity.java b/app/src/main/java/com/gh/gamecenter/DownloadManagerActivity.java
index 0885d5a55d..7820d80345 100644
--- a/app/src/main/java/com/gh/gamecenter/DownloadManagerActivity.java
+++ b/app/src/main/java/com/gh/gamecenter/DownloadManagerActivity.java
@@ -99,11 +99,12 @@ public class DownloadManagerActivity extends BaseFragmentActivity implements
}
}
if (currentItem == -1) {
- if (updateSize != 0 && downloadSize == 0) {
- currentItem = 1;
- } else {
- currentItem = 0;
- }
+ currentItem = 0;
+// if (updateSize != 0 && downloadSize == 0) {
+// currentItem = 1;
+// } else {
+// currentItem = 0;
+// }
}
DisplayMetrics outMetrics = new DisplayMetrics();
@@ -115,9 +116,9 @@ public class DownloadManagerActivity extends BaseFragmentActivity implements
downloadmanager_slide_line.setLayoutParams(lparams);
List list = new ArrayList<>();
+ list.add(new FileSendFragment());
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);
@@ -125,13 +126,13 @@ public class DownloadManagerActivity extends BaseFragmentActivity implements
@Override
public void onPageSelected(int position) {
- if (position == 0) {
- EventBus.getDefault().post(new EBUISwitch("DownloadManagerActivity", 0));
+ if (position == 1) {
+ EventBus.getDefault().post(new EBUISwitch("DownloadManagerActivity", 1));
downloadmanager_tv_download.setTextColor(getResources().getColor(R.color.theme));
downloadmanager_tv_update.setTextColor(getResources().getColor(R.color.title));
downloadmanager_tv_send.setTextColor(getResources().getColor(R.color.title));
- } else if (position == 1){
- EventBus.getDefault().post(new EBUISwitch("DownloadManagerActivity", 1));
+ } else if (position == 2){
+ EventBus.getDefault().post(new EBUISwitch("DownloadManagerActivity", 2));
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));
@@ -161,11 +162,11 @@ public class DownloadManagerActivity extends BaseFragmentActivity implements
if (id == R.id.actionbar_rl_back) {
finish();
} else if (id == R.id.downloadmanager_ll_download) {
- downloadmanager_viewPager.setCurrentItem(0);
- } else if (id == R.id.downloadmanager_ll_update) {
downloadmanager_viewPager.setCurrentItem(1);
- } else if (id == R.id.downloadmanager_ll_send) {
+ } else if (id == R.id.downloadmanager_ll_update) {
downloadmanager_viewPager.setCurrentItem(2);
+ } else if (id == R.id.downloadmanager_ll_send) {
+ downloadmanager_viewPager.setCurrentItem(0);
}
}
diff --git a/app/src/main/java/com/gh/gamecenter/FileReceiverActivity.java b/app/src/main/java/com/gh/gamecenter/FileReceiverActivity.java
index 1ea0e858b5..d6d8353159 100644
--- a/app/src/main/java/com/gh/gamecenter/FileReceiverActivity.java
+++ b/app/src/main/java/com/gh/gamecenter/FileReceiverActivity.java
@@ -1,6 +1,9 @@
package com.gh.gamecenter;
import android.Manifest;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Environment;
@@ -11,11 +14,14 @@ import android.support.v4.content.ContextCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
import android.widget.TextView;
import com.facebook.drawee.view.SimpleDraweeView;
import com.gh.base.AppController;
import com.gh.base.BaseActivity;
+import com.gh.common.constant.Config;
import com.gh.common.util.DialogUtils;
import com.gh.common.util.UserIconUtils;
import com.gh.common.util.Utils;
@@ -31,6 +37,7 @@ import com.gh.gamecenter.kuaichuan.FileReceiver;
import com.gh.gamecenter.kuaichuan.HotspotManager;
import com.gh.gamecenter.kuaichuan.IpPortInfo;
import com.gh.gamecenter.kuaichuan.WifiMgr;
+import com.gh.gamecenter.manager.DataCollectionManager;
import org.json.JSONException;
import org.json.JSONObject;
@@ -41,7 +48,9 @@ import java.net.DatagramSocket;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.DecimalFormat;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import butterknife.BindView;
import butterknife.OnClick;
@@ -56,6 +65,11 @@ public class FileReceiverActivity extends BaseActivity implements FileReceiverAd
@BindView(R.id.sender_user_name) TextView mSenderUserName;
@BindView(R.id.sender_user_send_des) TextView mSenderUserDes;
@BindView(R.id.sender_hint) TextView mSenderHint;
+ @BindView(R.id.sender_bottom) LinearLayout mReceiverBottom;
+ @BindView(R.id.sender_keep_send) RelativeLayout mKeepReceiver;
+ @BindView(R.id.sender_keep_send_tv) TextView mKeepReceiverTv;
+ @BindView(R.id.sender_bottom_hint) TextView mReceiverBottomHint;
+ @BindView(R.id.sender_bottom_control) LinearLayout mReceiverControl;
private FileReceiverAdapter mFileReceiverAdapter;
@@ -71,10 +85,14 @@ public class FileReceiverActivity extends BaseActivity implements FileReceiverAd
private DatagramSocket mDatagramSocket;
+ private SharedPreferences sp;
+
private boolean isReceivesOver;
private boolean isOpenWifi; //记录开热点前的WiFi状态
private boolean isDestroy;
+ private long mStartTime;
+
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -100,16 +118,19 @@ public class FileReceiverActivity extends BaseActivity implements FileReceiverAd
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();
+ if (index == mFileInfos.size() -1) initSenderHint(false);
} else if (msg.what == FileInfo.FLAG_FAILURE) { // 传输失败更新界面
fileInfo.setResult(FileInfo.FLAG_FAILURE);
- if (index == mFileInfos.size() -1) initSenderHint();
+ if (index == mFileInfos.size() -1) initSenderHint(false);
} else if (msg.what == FileInfo.FLAG_CANCEL) { // 传输取消更新界面
fileInfo.setResult(FileInfo.FLAG_CANCEL);
- if (index == mFileInfos.size() -1) initSenderHint();
+ if (index == mFileInfos.size() -1) initSenderHint(false);
+ } else if (msg.what == FileInfo.FLAG_NO_MEMORY) {
+ Utils.toast(FileReceiverActivity.this, "手机空间不足");
+ fileInfo.setResult(FileInfo.FLAG_NO_MEMORY); // 接收方内存不足
+ if (index == mFileInfos.size() -1) initSenderHint(true);
}
Utils.log("FileReceiverActivity:: 刷新位置::" + index + "刷新状态::" + msg.what);
@@ -128,10 +149,6 @@ public class FileReceiverActivity extends BaseActivity implements FileReceiverAd
}
}
Utils.log("FileReceiverActivity:: 获取刷新位置异常" + mFileInfos.size());
- for (FileInfo mFileInfo : mFileInfos) {
- Utils.log("FileReceiverActivity:: 位置异常mFileInfos====" + mFileInfo.getFileTag() + "==" + mFileInfo.getName());
- Utils.log("FileReceiverActivity:: 位置异常mCurFileInfo====" + mCurFileInfo.getFileTag() + "==" + mCurFileInfo.getName());
- }
return -1;
}
@@ -141,7 +158,6 @@ public class FileReceiverActivity extends BaseActivity implements FileReceiverAd
View contentView = View.inflate(this, R.layout.activity_file_sender, null);
init(contentView, "接收游戏");
- isReceivesOver = false;
isDestroy = false;
mFileReceiverAdapter = new FileReceiverAdapter(this);
@@ -153,6 +169,10 @@ public class FileReceiverActivity extends BaseActivity implements FileReceiverAd
mIpPortInfo = (IpPortInfo) getIntent().getSerializableExtra(Constant.KEY_IP_PORT_INFO);
isOpenWifi = getIntent().getBooleanExtra("isOpenWifi", false);
+ mKeepReceiverTv.setText("继续接收");
+
+ sp = getSharedPreferences(Config.PREFERENCE, Context.MODE_PRIVATE);
+
initUserData();
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
@@ -164,6 +184,8 @@ public class FileReceiverActivity extends BaseActivity implements FileReceiverAd
}
private void initUserData() {
+ isReceivesOver = false;
+
long allGameSize = 0;
for (FileInfo mFileInfo : mFileInfos) {
allGameSize = allGameSize + mFileInfo.getSize();
@@ -174,8 +196,12 @@ public class FileReceiverActivity extends BaseActivity implements FileReceiverAd
String sizeName = df.format(size) + "MB";
mSenderUserDes.setText(mFileInfos.size() + "个游戏,共" + sizeName);
- mSenderUserName.setText("来自-" + mIpPortInfo.getSenderName());
+ mSenderUserName.setText("来自 " + mIpPortInfo.getSenderName());
mSenderUserIcon.setImageURI(UserIconUtils.getUserIcon(mIpPortInfo.getSenderIcon()));
+
+ mReceiverBottom.setVisibility(View.GONE);
+
+ mSenderHint.setText("已连接");
}
/**
@@ -238,7 +264,7 @@ public class FileReceiverActivity extends BaseActivity implements FileReceiverAd
* @param msg
*/
private void parseFileInfo(String msg) {
- mFileInfos = (List) AppController.get("FileInfo", false); //TODO mFileInfos 数据异常 需要重新获取
+ mFileInfos = (List) AppController.get("FileInfo", false); // mFileInfos 数据异常 需要重新获取
FileInfo fileInfo = FileInfo.toObject(msg);
if(fileInfo != null && fileInfo.getFilePath() != null){
mFileInfos.add(fileInfo);
@@ -256,9 +282,16 @@ public class FileReceiverActivity extends BaseActivity implements FileReceiverAd
// }
- //TODO 接收方发送取消消息 会导致接收列表时无法回复信息 == 将消息整合在一起
Utils.log("接收方发送取消消息 让发送方取消");
+
+
try {
+ // 接收方更改界面
+ FileInfo fileInfo = mFileInfos.get(position);
+ fileInfo.setResult(FileInfo.FLAG_CANCEL);
+ mFileReceiverAdapter.notifyItemChanged(position);
+
+ // 发消息让发送方取消
JSONObject jsonObject = new JSONObject();
jsonObject.put("controlStatus", Constant.MSG_RECEIVER_CANCEL);
jsonObject.put("controlTag", position);
@@ -325,11 +358,12 @@ public class FileReceiverActivity extends BaseActivity implements FileReceiverAd
while (!Thread.currentThread().isInterrupted()){
Socket socket = serverSocket.accept();
- mFileReceiver = new FileReceiver(socket);
+ mFileReceiver = new FileReceiver(socket, FileReceiverActivity.this);
mFileReceiver.setOnReceiveListener(new FileReceiver.OnReceiveListener() {
@Override
public void onStart() {
Utils.log("快传文件接收::onStart");
+ mStartTime = Utils.getTime(FileReceiverActivity.this);
}
@Override
@@ -354,22 +388,42 @@ public class FileReceiverActivity extends BaseActivity implements FileReceiverAd
}
@Override
- public void onSuccess(FileInfo fileInfo) { // 获取传输成功
+ public void onSuccess() { // 获取传输成功
handler.sendEmptyMessage(FileInfo.FLAG_SUCCESS);
- Utils.log("快传文件接收成功::onSuccess");
+
+ // TODO 数据收集
+ long sendTime = Utils.getTime(FileReceiverActivity.this) - mStartTime;
+
+ Map hashMap = new HashMap<>();
+ hashMap.put("send_time", mStartTime);
+ hashMap.put("receive_time", Utils.getTime(FileReceiverActivity.this));
+ hashMap.put("game_name", mCurFileInfo.getName());
+ hashMap.put("package_name", mCurFileInfo.getPackageName());
+ hashMap.put("package_size", mCurFileInfo.getSize());
+ hashMap.put("expend_time", sendTime);
+ hashMap.put("send_nickname", mIpPortInfo.getSenderName());
+ hashMap.put("receive_nickname", mIpPortInfo.getReceiverName());
+ hashMap.put("receive_token", sp.getString("token", null));
+ DataCollectionManager.onEvent(FileReceiverActivity.this, "transfer", hashMap, false);
+ Utils.log("快传文件接收成功::onSuccess:: 发送事件::" + sendTime);
}
@Override
- public void onFailure(Throwable t, FileInfo fileInfo) { // 获取传输失败
+ public void onFailure(Throwable t) { // 获取传输失败
Utils.log("快传文件接收失败::onFailure");
handler.sendEmptyMessage(FileInfo.FLAG_FAILURE);
}
@Override
- public void onCancel(FileInfo fileInfo) { // 获取传输取消
+ public void onCancel() { // 获取传输取消
Utils.log("快传文件接收取消::onCancel");
handler.sendEmptyMessage(FileInfo.FLAG_CANCEL);
}
+
+ @Override
+ public void onNoMemory() {
+ handler.sendEmptyMessage(FileInfo.FLAG_NO_MEMORY);
+ }
});
AppController.MAIN_EXECUTOR.execute(mFileReceiver);
@@ -394,7 +448,12 @@ public class FileReceiverActivity extends BaseActivity implements FileReceiverAd
}
}
- private void initSenderHint(){
+ private void initSenderHint(boolean isNoMemory) {
+
+ mReceiverBottom.setVisibility(View.VISIBLE);
+ mReceiverControl.setVisibility(View.VISIBLE);
+
+
isReceivesOver = true;
int sendSuccess = 0;
for (FileInfo mFileInfo : mFileInfos) {
@@ -403,6 +462,10 @@ public class FileReceiverActivity extends BaseActivity implements FileReceiverAd
}
}
+ if (isNoMemory) {
+ mKeepReceiverTv.setText("手机空间清理");
+ }
+
if (sendSuccess > 0) {
mSenderHint.setVisibility(View.VISIBLE);
mSenderHint.setText("传输结束,成功接收" + sendSuccess + "个游戏");
@@ -429,15 +492,31 @@ public class FileReceiverActivity extends BaseActivity implements FileReceiverAd
isDestroy = true;
}
- @OnClick(R.id.actionbar_rl_back)
- public void back() {
- backHint();
+ @OnClick({R.id.actionbar_rl_back, R.id.sender_keep_send, R.id.sender_back})
+ public void back(View view) {
+ switch (view.getId()) {
+ case R.id.actionbar_rl_back:
+ backHint();
+ break;
+ case R.id.sender_back:
+ backHint();
+ break;
+ case R.id.sender_keep_send:
+ if ("继续接收".equals(mKeepReceiverTv.getText())) {
+ mReceiverControl.setVisibility(View.GONE);
+ } else { // 跳转安装包清理
+ Intent intent = new Intent(this, CleanApkActivity.class);
+ startActivity(intent);
+ }
+ break;
+
+ }
}
private void colsePage() {
if(mDatagramSocket != null) {
- mDatagramSocket.disconnect();
+// mDatagramSocket.disconnect();
mDatagramSocket.close();
mDatagramSocket = null;
}
diff --git a/app/src/main/java/com/gh/gamecenter/FileSenderActivity.java b/app/src/main/java/com/gh/gamecenter/FileSenderActivity.java
index 0a958d139d..2a85fe0bf9 100644
--- a/app/src/main/java/com/gh/gamecenter/FileSenderActivity.java
+++ b/app/src/main/java/com/gh/gamecenter/FileSenderActivity.java
@@ -101,7 +101,6 @@ public class FileSenderActivity extends BaseActivity implements FileSenderAdapte
mFileInfos = (List) AppController.get("FileInfo", false);
- isSendOver = false;
isDestroy = false;
mFileSenderList = new ArrayList<>();
@@ -115,11 +114,9 @@ public class FileSenderActivity extends BaseActivity implements FileSenderAdapte
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
- if (requestCode == 0x178) {
- mFileInfos = (List) AppController.get("FileInfo", false);
+ if (resultCode == 0x130 && requestCode == 0x178) {
mSenderAdapter.notifyDataSetChanged();
initUserData();
- Utils.log("FileSenderActivity:: onActivityResult::" + mFileInfos.size());
new Thread(new Runnable() {
@Override
public void run() {
@@ -214,6 +211,10 @@ public class FileSenderActivity extends BaseActivity implements FileSenderAdapte
JSONObject jsonObject = new JSONObject(response);
int cancelPosition = (int) jsonObject.get("controlTag");
FileSender fileSender = mFileSenderList.get(cancelPosition);
+ Message message = new Message();
+ message.what = FileInfo.FLAG_CANCEL;
+ message.obj = cancelPosition;
+ handler.sendMessage(message);
if (fileSender != null && fileSender.isRunning()) {
Utils.log("接收方取消发送");
fileSender.cancel();
@@ -231,6 +232,8 @@ public class FileSenderActivity extends BaseActivity implements FileSenderAdapte
//初始化用户数据
private void initUserData() {
+ isSendOver = false;
+
Map map = (Map) AppController.get("userMap", false);
long allGameSize = 0;
@@ -243,10 +246,12 @@ public class FileSenderActivity extends BaseActivity implements FileSenderAdapte
String sizeName = df.format(size) + "MB";
mSenderUserDes.setText(mFileInfos.size() + "个游戏,共" + sizeName);
- mSenderUserName.setText("发给-" + map.get("receiverName"));
+ mSenderUserName.setText("发给 " + map.get("receiverName"));
mSenderUserIcon.setImageURI(UserIconUtils.getUserIcon(Integer.parseInt(map.get("usericon"))));
mSenderBottom.setVisibility(View.GONE);
+
+ mSenderHint.setText("已连接");
}
private void initSendServer() throws Exception {
@@ -330,6 +335,12 @@ public class FileSenderActivity extends BaseActivity implements FileSenderAdapte
}
private void initSenderHint(){
+ for (FileInfo mFileInfo : mFileInfos) {
+ if (mFileInfo.getResult() == 0 || mFileInfo.getResult() == 1) { // 还有没完成的任务
+ return;
+ }
+ }
+
mSenderBottom.setVisibility(View.VISIBLE);
int sendSuccess = 0;
@@ -376,9 +387,9 @@ public class FileSenderActivity extends BaseActivity implements FileSenderAdapte
isDestroy = true;
}
- @OnClick({R.id.actionbar_rl_back, R.id.sender_keep_send})
+ @OnClick({R.id.actionbar_rl_back, R.id.sender_keep_send, R.id.sender_back})
public void onClick(View view) {
- if (view.getId() == R.id.actionbar_rl_back) {
+ if (view.getId() == R.id.actionbar_rl_back || view.getId() == R.id.sender_back) {
backHint();
} else if (view.getId() == R.id.sender_keep_send) {
Intent intent = new Intent(this, KcSelectGameActivity.class);
@@ -402,13 +413,16 @@ public class FileSenderActivity extends BaseActivity implements FileSenderAdapte
public void colsePage() {
if(mDatagramSocket != null) {
- mDatagramSocket.disconnect();
+// mDatagramSocket.disconnect();
mDatagramSocket.close();
mDatagramSocket = null;
}
stopAllFileSendingTask();
AppController.remove("FileInfo");
+
+ setResult(0x171);
+ Utils.log("======zz" + 0x171);
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
index c7e31b3120..5ca8a61433 100644
--- a/app/src/main/java/com/gh/gamecenter/KcSelectGameActivity.java
+++ b/app/src/main/java/com/gh/gamecenter/KcSelectGameActivity.java
@@ -55,7 +55,7 @@ public class KcSelectGameActivity extends BaseActivity {
mIsConn = false;
}
-
+ selectAll.setVisibility(View.GONE);
mAdapter = new KcSelectGameAdapter(this, mSelectSend);
mSelectRv.setLayoutManager(new LinearLayoutManager(this));
@@ -75,9 +75,7 @@ public class KcSelectGameActivity extends BaseActivity {
for (FileInfo fileInfo : selectData) {
oldInfo.add(fileInfo);
}
-
- AppController.put("FileInfo", oldInfo);
- setResult(0x178);
+ setResult(0x130);
finish();
} else {
AppController.put("FileInfo", selectData);
@@ -108,6 +106,6 @@ public class KcSelectGameActivity extends BaseActivity {
}
});
- installCount.setText("已安装(" + mAdapter.getItemCount() + ")");
+ 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
index 10404ca6fb..8afda8689c 100644
--- a/app/src/main/java/com/gh/gamecenter/ReceiverWaitingActivity.java
+++ b/app/src/main/java/com/gh/gamecenter/ReceiverWaitingActivity.java
@@ -4,6 +4,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -12,8 +13,6 @@ 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;
@@ -21,6 +20,7 @@ import com.gh.common.constant.Config;
import com.gh.common.util.RandomUtils;
import com.gh.common.util.UserIconUtils;
import com.gh.common.util.Utils;
+import com.gh.common.view.RadarLayout;
import com.gh.gamecenter.kuaichuan.BaseTransfer;
import com.gh.gamecenter.kuaichuan.Constant;
import com.gh.gamecenter.kuaichuan.FileInfo;
@@ -40,7 +40,6 @@ import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
-import butterknife.OnClick;
/**
* Created by khy on 2017/1/20.
@@ -51,9 +50,10 @@ public class ReceiverWaitingActivity extends BaseActivity {
@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_radar_layout) RadarLayout mRadarLayout;
@BindView(R.id.waiting_hint) TextView mWaitingHint;
@BindView(R.id.reuse_actionbar) RelativeLayout mActionbar;
+ @BindView(R.id.waiting_gprs_hint) TextView mGPRSHint;
private WifiAPBroadcastReceiver mWifiAPBroadcastReceiver;
@@ -117,15 +117,16 @@ public class ReceiverWaitingActivity extends BaseActivity {
}
mUserStatus.setText("正在初始化...");
- DraweeController controller = Fresco.newDraweeControllerBuilder()
- .setUri("res:///" + R.drawable.kuaichuan_receiver_waiting)
- .setAutoPlayAnimations(true)
- .build();
- mWaitingGif.setController(controller);
+ mRadarLayout.setUseRing(true);
+ mRadarLayout.setColor(Color.WHITE);
+ mRadarLayout.setCount(4);
+ mRadarLayout.start();
mFileInfos = new ArrayList<>();
+ HotspotManager.initApData(this); // 记录原始热点信息
+
//初始化热点
if(HotspotManager.isApOn(this)){
HotspotManager.disableAp(this);
@@ -134,7 +135,7 @@ public class ReceiverWaitingActivity extends BaseActivity {
mWifiAPBroadcastReceiver = new WifiAPBroadcastReceiver() {
@Override
public void onWifiApEnabled() {
- if(!mIsInitialized){
+ if(!mIsInitialized) {
mUdpServerRuannable = createSendMsgToFileSenderRunnable();
AppController.MAIN_EXECUTOR.execute(mUdpServerRuannable);
mIsInitialized = true;
@@ -142,6 +143,8 @@ public class ReceiverWaitingActivity extends BaseActivity {
mWaitingConn.setVisibility(View.VISIBLE);
mUserStatus.setText(Html.fromHtml("成功创建热点:" + "" + mySsid + ""));
mWaitingHint.setVisibility(View.GONE);
+ mUserName.setVisibility(View.GONE);
+ mGPRSHint.setVisibility(View.VISIBLE);
}
}
@@ -159,6 +162,20 @@ public class ReceiverWaitingActivity extends BaseActivity {
}
mySsid = mySsid + sp.getInt("default_user_icon", 1);
HotspotManager.configApState(this, mySsid); // change Ap state :boolean
+
+ findViewById(R.id.actionbar_rl_back).setOnClickListener(
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ colsePage();
+ //关闭热点
+ HotspotManager.disableAp(ReceiverWaitingActivity.this);
+
+ if (isOpenWifi) {
+ WifiMgr.getInstance(ReceiverWaitingActivity.this).openWifi();
+ }
+ }
+ });
}
/**
@@ -232,7 +249,8 @@ public class ReceiverWaitingActivity extends BaseActivity {
Message message = new Message();
message.what = 0;
JSONObject jsonObject = new JSONObject(msg);
- message.obj = new IpPortInfo(inetAddress, port, jsonObject.getString(Constant.MSG_FILE_RECEIVER_INIT), jsonObject.getInt("UserIcon"));
+ message.obj = new IpPortInfo(inetAddress, port, jsonObject.getString(Constant.MSG_FILE_RECEIVER_INIT),
+ sp.getString("user_name", "光环用户"),jsonObject.getInt("UserIcon"));
mHandler.sendMessage(message);
} else {
@@ -260,23 +278,23 @@ public class ReceiverWaitingActivity extends BaseActivity {
*/
private void closeSocket(){
if(mDatagramSocket != null){
- mDatagramSocket.disconnect();
+// 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();
- }
- }
+// @OnClick(R.id.actionbar_rl_back)
+// public void onBackListener() {
+// Utils.log("=========back");
+// colsePage();
+// //关闭热点
+// HotspotManager.disableAp(this);
+//
+// if (isOpenWifi) {
+// WifiMgr.getInstance(this).openWifi();
+// }
+// }
@Override
public void onBackPressed() {
@@ -284,7 +302,7 @@ public class ReceiverWaitingActivity extends BaseActivity {
colsePage();
//关闭热点
- HotspotManager.disableAp(this);
+ HotspotManager.initUserAp(ReceiverWaitingActivity.this);
if (isOpenWifi) {
WifiMgr.getInstance(this).openWifi();
@@ -295,6 +313,8 @@ public class ReceiverWaitingActivity extends BaseActivity {
* 关闭广播并关闭Socket流
*/
private void colsePage() {
+ mRadarLayout.stop();
+
try {
if(mWifiAPBroadcastReceiver != null){
unregisterReceiver(mWifiAPBroadcastReceiver);
diff --git a/app/src/main/java/com/gh/gamecenter/SelectUserIconActivity.java b/app/src/main/java/com/gh/gamecenter/SelectUserIconActivity.java
index 14a6abd41c..4db2e16072 100644
--- a/app/src/main/java/com/gh/gamecenter/SelectUserIconActivity.java
+++ b/app/src/main/java/com/gh/gamecenter/SelectUserIconActivity.java
@@ -9,14 +9,30 @@ import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.TextView;
+import android.widget.Toast;
import com.gh.base.BaseActivity;
import com.gh.common.constant.Config;
-import com.gh.common.util.UserIconUtils;
+import com.gh.common.util.TokenUtils;
import com.gh.common.util.Utils;
+import com.gh.gamecenter.retrofit.JSONObjectResponse;
+import com.gh.gamecenter.retrofit.RetrofitManager;
+
+import org.json.JSONObject;
+
+import java.util.HashMap;
+import java.util.Map;
import butterknife.BindView;
import butterknife.OnClick;
+import okhttp3.MediaType;
+import okhttp3.RequestBody;
+import okhttp3.ResponseBody;
+import retrofit2.adapter.rxjava.HttpException;
+import rx.Observable;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.functions.Func1;
+import rx.schedulers.Schedulers;
/**
* Created by khy on 2017/2/10.
@@ -108,11 +124,65 @@ public class SelectUserIconActivity extends BaseActivity {
}
public void postUserIocn(int i) {
- sp.edit().putInt("default_user_icon", i).apply();
- Intent intent = new Intent();
- intent.putExtra("url", UserIconUtils.getUserIcon(i));
- setResult(0x125, intent);
- finish();
+ postDefaultIcon(true, i);
+ }
+
+ public void postDefaultIcon(boolean isCheck, final int i) {
+ TokenUtils.getToken(this, isCheck)
+ .flatMap(new Func1>() {
+ @Override
+ public Observable call(String token) {
+ Map params = new HashMap<>();
+ params.put("icon_key" , "icon" + i);
+ RequestBody body = RequestBody.create(MediaType.parse("application/json"),
+ new JSONObject(params).toString());
+ return RetrofitManager.getUser().postDefaultIcon(token, body);
+ }
+ })
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new JSONObjectResponse(){
+ @Override
+ public void onResponse(JSONObject response) {
+ super.onResponse(response);
+ try {
+ String icon = response.getString("icon");
+
+ sp.edit().putInt("default_user_icon", i).apply();
+ Intent intent = new Intent();
+ intent.putExtra("url", icon);
+ setResult(0x125, intent);
+ finish();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ @Override
+ public void onFailure(HttpException e) {
+ super.onFailure(e);
+ if (e != null) {
+ if (e.code() == 401) {
+ postDefaultIcon(true, i);
+ return;
+ }
+
+ if (e.code() == 403) {
+ try {
+ JSONObject response = new JSONObject(new String(e.response().errorBody().bytes()));
+ if ("too frequent".equals(response.getString("detail"))) {
+ Toast.makeText(SelectUserIconActivity.this, "修改太频繁", Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(SelectUserIconActivity.this, "修改失败", Toast.LENGTH_SHORT).show();
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ Toast.makeText(SelectUserIconActivity.this, "修改失败", Toast.LENGTH_SHORT).show();
+ }
+ }
+ }
+ }
+ }
+ );
}
}
diff --git a/app/src/main/java/com/gh/gamecenter/ShareGhActivity.java b/app/src/main/java/com/gh/gamecenter/ShareGhActivity.java
index 6a06bad6ad..6335cc6b79 100644
--- a/app/src/main/java/com/gh/gamecenter/ShareGhActivity.java
+++ b/app/src/main/java/com/gh/gamecenter/ShareGhActivity.java
@@ -57,7 +57,7 @@ public class ShareGhActivity extends BaseActivity {
ClipboardManager cmb = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
cmb.setText("http://www.ghzhushou.com?source=appshare100");
- Utils.toast(this, "网址复制成功");
+ Utils.toast(this, "网址复制成功,请到微信/QQ粘贴分享");
}
diff --git a/app/src/main/java/com/gh/gamecenter/ShareGhWfifActivity.java b/app/src/main/java/com/gh/gamecenter/ShareGhWfifActivity.java
index e5e5d166ba..7bbb055646 100644
--- a/app/src/main/java/com/gh/gamecenter/ShareGhWfifActivity.java
+++ b/app/src/main/java/com/gh/gamecenter/ShareGhWfifActivity.java
@@ -3,8 +3,13 @@ package com.gh.gamecenter;
import android.content.Context;
import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.graphics.Color;
import android.os.Bundle;
+import android.text.Html;
import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
import android.widget.TextView;
import com.gh.base.AppController;
@@ -21,7 +26,6 @@ import com.gh.gamecenter.kuaichuan.HtmlUriHandler;
import com.gh.gamecenter.kuaichuan.ImageUriHandler;
import com.gh.gamecenter.kuaichuan.KcUriHandler;
import com.gh.gamecenter.kuaichuan.WifiMgr;
-import com.gh.gamecenter.kuaichuan.WifiUtils;
import com.gh.gamecenter.receiver.WifiAPBroadcastReceiver;
import java.io.IOException;
@@ -41,7 +45,12 @@ import butterknife.OnClick;
*/
public class ShareGhWfifActivity extends BaseActivity {
- @BindView(R.id.hotspot_name) TextView mHotSpotName;
+// @BindView(R.id.hotspot_name) TextView mHotSpotName;
+ @BindView(R.id.init_hotpost_pb) ProgressBar mInitHotspostPb;
+ @BindView(R.id.init_status_icon) ImageView mInitStatusIcon;
+ @BindView(R.id.init_status_tv) TextView mInitStatusTv;
+ @BindView(R.id.init_hotpost_hint) TextView mInitHotpostHint;
+ @BindView(R.id.init_success_ll) LinearLayout mInitSuccessLl;
private ServerSocket mServerSocket;
@@ -57,13 +66,15 @@ public class ShareGhWfifActivity extends BaseActivity {
private boolean isOpenWifi; //记录开热点前的WiFi状态
+ private boolean initSuccess;
+
private String mySsid;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View contentView = View.inflate(this, R.layout.activity_share_gh_wifi, null);
- init(contentView, "分享光环");
+ init(contentView, "免流量分享");
ButterKnife.bind(this);
mUriHandlers = new ArrayList<>();
@@ -73,13 +84,16 @@ public class ShareGhWfifActivity extends BaseActivity {
sp = getSharedPreferences(Config.PREFERENCE, Context.MODE_PRIVATE);
isColseActivity = false;
+ initSuccess = false;
if (WifiMgr.getInstance(this).isWifiEnable()) {
isOpenWifi = true;
WifiMgr.getInstance(this).closeWifi();
}
+ HotspotManager.initApData(this); // 记录原始热点信息
+ initHotSpotView(0);
initHotSpot();
}
@@ -93,7 +107,7 @@ public class ShareGhWfifActivity extends BaseActivity {
Utils.log("===初始化热点成功");
AppController.MAIN_EXECUTOR.execute(checkHotSpot());
mIsInitialized = true;
- mHotSpotName.setText(mySsid);
+// mHotSpotName.setText(mySsid);
}
}
@@ -114,6 +128,42 @@ public class ShareGhWfifActivity extends BaseActivity {
HotspotManager.configApState(this, mySsid); // change Ap state :boolean
}
+ /**
+ * 初始化创建热点View
+ * @param i i=0 初始化中, i=1 初始化成功, i=2 初始化失败
+ */
+
+ public void initHotSpotView(int i) {
+ switch (i) {
+ case 0:
+ mInitHotspostPb.setVisibility(View.VISIBLE);
+ mInitStatusIcon.setVisibility(View.GONE);
+ mInitStatusTv.setText("正在创建热点...");
+ mInitStatusTv.setTextColor(getResources().getColor(R.color.title));
+ mInitHotpostHint.setVisibility(View.VISIBLE);
+ mInitHotpostHint.setText("如果出现获取权限的提示,请点击允许");
+ break;
+ case 1:
+ mInitStatusIcon.setVisibility(View.VISIBLE);
+ mInitStatusIcon.setImageResource(R.drawable.kc_checkbox_select);
+ mInitStatusTv.setText(Html.fromHtml("热点创建成功:" + "" + mySsid + ""));
+ mInitHotpostHint.setVisibility(View.VISIBLE);
+ mInitHotpostHint.setText("为了避免消耗流量,请关闭你手机的移动网络");
+ mInitHotspostPb.setVisibility(View.GONE);
+ mInitSuccessLl.setVisibility(View.VISIBLE);
+ initSuccess = true;
+ break;
+ case 2:
+ mInitStatusIcon.setVisibility(View.VISIBLE);
+ mInitStatusIcon.setImageResource(R.drawable.hotspot_failed_icon);
+ mInitStatusTv.setText("初始化失败, 请退出重试");
+ mInitStatusTv.setTextColor(Color.parseColor("#ff4147"));
+ mInitHotpostHint.setVisibility(View.VISIBLE);
+ mInitHotspostPb.setVisibility(View.GONE);
+ break;
+ }
+ }
+
private Runnable checkHotSpot() {
return new Runnable() {
@Override
@@ -129,11 +179,11 @@ public class ShareGhWfifActivity extends BaseActivity {
}
// 即使热点wifi的IP地址也是无法连接网络 所以采取此策略
- count = 0;
- while(!WifiUtils.pingIpAddress(hotspotIpAddr) && count < Constant.DEFAULT_TRY_TIME){
- Thread.sleep(500);
- count ++;
- }
+// count = 0;
+// while(!WifiUtils.pingIpAddress(hotspotIpAddr) && count < Constant.DEFAULT_TRY_TIME){
+// Thread.sleep(500);
+// count ++;
+// }
} catch(Exception e) {
Utils.log("==热点启动异常::" + e.toString());
}
@@ -158,6 +208,15 @@ public class ShareGhWfifActivity extends BaseActivity {
}
while (!isColseActivity) {
+ if (!initSuccess) {
+ mInitStatusTv.post(new Runnable() {
+ @Override
+ public void run() {
+ initHotSpotView(1);
+ }
+ });
+ }
+
Utils.log("===循环等待客户端请求");
Socket socket = mServerSocket.accept();
KcWebRequestEntity requestEntity = hanlderSocket(socket);
@@ -175,6 +234,15 @@ public class ShareGhWfifActivity extends BaseActivity {
} catch (IOException e) {
Utils.log("===网页传下载出现异常" + e.toString());
e.printStackTrace();
+
+ if (!e.toString().contains("Socket closed")) {
+ mInitStatusTv.post(new Runnable() {
+ @Override
+ public void run() {
+ initHotSpotView(2);
+ }
+ });
+ }
}
}
}).start();
@@ -251,7 +319,7 @@ public class ShareGhWfifActivity extends BaseActivity {
}
}
- HotspotManager.disableAp(ShareGhWfifActivity.this);
+ HotspotManager.initUserAp(ShareGhWfifActivity.this);
if (isOpenWifi) {
WifiMgr.getInstance(ShareGhWfifActivity.this).openWifi();
}
diff --git a/app/src/main/java/com/gh/gamecenter/adapter/CleanApkAdapter.java b/app/src/main/java/com/gh/gamecenter/adapter/CleanApkAdapter.java
index fce956c141..65166342e0 100644
--- a/app/src/main/java/com/gh/gamecenter/adapter/CleanApkAdapter.java
+++ b/app/src/main/java/com/gh/gamecenter/adapter/CleanApkAdapter.java
@@ -4,10 +4,12 @@ import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.database.Cursor;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
-import android.os.Environment;
+import android.net.Uri;
import android.os.Handler;
+import android.provider.MediaStore;
import android.support.v4.util.ArrayMap;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
@@ -76,7 +78,7 @@ public class CleanApkAdapter extends RecyclerView.Adapter 0) {
- for (File file_str : files) {
- FindAllAPKFile(file_str);
- }
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ notifyItemInserted((mApkList.size() - 1));
+ }
+ });
+ } while (cursor.moveToNext());
}
}
+ cursor.close();
}
private int doType(PackageManager pm, String packageName) {
diff --git a/app/src/main/java/com/gh/gamecenter/adapter/FileReceiverAdapter.java b/app/src/main/java/com/gh/gamecenter/adapter/FileReceiverAdapter.java
index 61d80d0562..2eb97a98c8 100644
--- a/app/src/main/java/com/gh/gamecenter/adapter/FileReceiverAdapter.java
+++ b/app/src/main/java/com/gh/gamecenter/adapter/FileReceiverAdapter.java
@@ -72,9 +72,22 @@ public class FileReceiverAdapter extends RecyclerView.Adapter gameList;
+ private List sendOverList; //发送过的游戏
+
private int cardMargin;
public KcSelectGameAdapter(KcSelectGameActivity activity, TextView selectCount) {
@@ -54,6 +57,8 @@ public class KcSelectGameAdapter extends RecyclerView.Adapter();
selectPosition = new HashMap<>();
+ sendOverList = (List) AppController.get("FileInfo", false);
+
cardMargin = (int) context.getResources().getDimension(R.dimen.cardview_margin);
@@ -170,11 +175,20 @@ public class KcSelectGameAdapter extends RecyclerView.Adapter" + sizeName + "");
holder.gameSize.setText(spanned);
- holder.gameNameAndSize.setText(gameEntity.getGameName());
holder.gameDes.setText("版本:V" + gameEntity.getGameVersion());
holder.gameThumb.setImageBitmap(gameEntity.getGameBm());
+ holder.gameNameAndSize.setText(gameEntity.getGameName());
+ holder.gameNameAndSize.setTextColor(context.getResources().getColor(R.color.title));
+ if (sendOverList != null && sendOverList.size() > 0) {
+ for (FileInfo fileInfo : sendOverList) {
+ if (fileInfo.getFilePath().equals(gameEntity.getGamePath())) {
+ holder.gameNameAndSize.setTextColor(context.getResources().getColor(R.color.hint));
+ break;
+ }
+ }
+ }
holder.selectCB.setVisibility(View.VISIBLE);
if (selectPosition.get(i)) {
@@ -185,27 +199,47 @@ public class KcSelectGameAdapter extends RecyclerView.Adapter getSelectData() {
diff --git a/app/src/main/java/com/gh/gamecenter/adapter/viewholder/GameNormalSwipeViewHolder.java b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/GameNormalSwipeViewHolder.java
index 8804e55d49..5ac1f9e6c9 100644
--- a/app/src/main/java/com/gh/gamecenter/adapter/viewholder/GameNormalSwipeViewHolder.java
+++ b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/GameNormalSwipeViewHolder.java
@@ -31,6 +31,7 @@ public class GameNormalSwipeViewHolder extends RecyclerView.ViewHolder {
public CardLinearLayout cardView;
public SwipeLayout swipeLayout;
public TextView swipeText;
+ public TextView swipeShareText;
public GameNormalSwipeViewHolder(View itemView) {
super(itemView);
@@ -49,6 +50,7 @@ public class GameNormalSwipeViewHolder extends RecyclerView.ViewHolder {
cardView = (CardLinearLayout) itemView.findViewById(R.id.home1_game_card);
swipeLayout = (SwipeLayout) itemView.findViewById(R.id.swipeLayout);
swipeText = (TextView) itemView.findViewById(R.id.swipe_text);
+ swipeShareText = (TextView) itemView.findViewById(R.id.swipe_share_text);
}
}
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
index beaaa1efe6..a3b7582278 100644
--- a/app/src/main/java/com/gh/gamecenter/adapter/viewholder/KcSelectGameViewHolder.java
+++ b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/KcSelectGameViewHolder.java
@@ -9,7 +9,6 @@ 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;
@@ -21,7 +20,7 @@ import butterknife.ButterKnife;
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_thumb) public ImageView 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;
@@ -33,6 +32,7 @@ public class KcSelectGameViewHolder extends RecyclerView.ViewHolder{
@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;
+ @BindView(R.id.select_game_cb_rl) public RelativeLayout checkBoxRl;
public KcSelectGameViewHolder(View itemView) {
super(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
index 160ccc72df..22c4651a00 100644
--- a/app/src/main/java/com/gh/gamecenter/download/FileSendFragment.java
+++ b/app/src/main/java/com/gh/gamecenter/download/FileSendFragment.java
@@ -10,6 +10,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
+import com.gh.common.util.Utils;
import com.gh.gamecenter.CleanApkActivity;
import com.gh.gamecenter.KcSelectGameActivity;
import com.gh.gamecenter.R;
@@ -39,7 +40,7 @@ public class FileSendFragment extends Fragment {
@Override
public void onClick(View v) {
Intent intent = new Intent(getActivity(), KcSelectGameActivity.class);
- getActivity().startActivity(intent);
+ startActivityForResult(intent, 0x170);
}
});
@@ -76,4 +77,12 @@ public class FileSendFragment extends Fragment {
return view;
}
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ Utils.log("======zzzz" + 0x170 + "===" + 0x171 + "==" + requestCode + "==" + resultCode);
+ if (requestCode == 0x170 && resultCode == 0x171) {
+ Utils.toast(getContext(), "显示弹窗啦");
+ }
+ }
}
diff --git a/app/src/main/java/com/gh/gamecenter/kuaichuan/FileInfo.java b/app/src/main/java/com/gh/gamecenter/kuaichuan/FileInfo.java
index 66c98d5c06..e46e1cab9b 100644
--- a/app/src/main/java/com/gh/gamecenter/kuaichuan/FileInfo.java
+++ b/app/src/main/java/com/gh/gamecenter/kuaichuan/FileInfo.java
@@ -16,6 +16,7 @@ public class FileInfo implements Serializable {
* 文件传输的标识
*/
// -1 失败 0 发送中 1 成功 2发送取消 3已安装
+ public static final int FLAG_NO_MEMORY =5;
public static final int FLAG_INSTALLED = 4;
public static final int FLAG_CANCEL = 3;
public static final int FLAG_SUCCESS = 2;
diff --git a/app/src/main/java/com/gh/gamecenter/kuaichuan/FileReceiver.java b/app/src/main/java/com/gh/gamecenter/kuaichuan/FileReceiver.java
index 7babad729b..7f762670c8 100644
--- a/app/src/main/java/com/gh/gamecenter/kuaichuan/FileReceiver.java
+++ b/app/src/main/java/com/gh/gamecenter/kuaichuan/FileReceiver.java
@@ -1,10 +1,14 @@
package com.gh.gamecenter.kuaichuan;
+import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
+import android.text.TextUtils;
+import com.gh.common.util.FileUtils;
import com.gh.common.util.Utils;
+import com.gh.gamecenter.FileReceiverActivity;
import java.io.File;
import java.io.FileOutputStream;
@@ -12,6 +16,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
+import java.text.DecimalFormat;
/**
@@ -19,6 +24,8 @@ import java.net.Socket;
*/
public class FileReceiver extends BaseTransfer implements Runnable {
+ Context mContext;
+
/**
* Socket的输入输出流
*/
@@ -44,8 +51,9 @@ public class FileReceiver extends BaseTransfer implements Runnable {
OnReceiveListener mOnReceiveListener;
- public FileReceiver(Socket mSocket) {
+ public FileReceiver(Socket mSocket, FileReceiverActivity activity) {
this.mSocket = mSocket;
+ this.mContext = activity;
}
public void setOnReceiveListener(OnReceiveListener mOnReceiveListener) {
@@ -61,7 +69,7 @@ public class FileReceiver extends BaseTransfer implements Runnable {
} catch (Exception e) {
e.printStackTrace();
Utils.log("FileReceiver init() --->>> occur expection" + e.toString());
- if(mOnReceiveListener != null) mOnReceiveListener.onFailure(e, mFileInfo);
+ if(mOnReceiveListener != null) mOnReceiveListener.onFailure(e);
}
//解析头部
@@ -70,7 +78,7 @@ public class FileReceiver extends BaseTransfer implements Runnable {
} catch (Exception e) {
e.printStackTrace();
Utils.log("FileReceiver parseHeader() --->>> occur expection" + e.toString());
- if(mOnReceiveListener != null) mOnReceiveListener.onFailure(e, mFileInfo);
+ if(mOnReceiveListener != null) mOnReceiveListener.onFailure(e);
}
@@ -80,7 +88,7 @@ public class FileReceiver extends BaseTransfer implements Runnable {
} catch (Exception e) {
e.printStackTrace();
Utils.log("FileReceiver parseBody() --->>> occur expection" + e.toString());
- if(mOnReceiveListener != null) mOnReceiveListener.onFailure(e, mFileInfo);
+ if(mOnReceiveListener != null) mOnReceiveListener.onFailure(e);
}
//结束
@@ -89,7 +97,7 @@ public class FileReceiver extends BaseTransfer implements Runnable {
} catch (Exception e) {
e.printStackTrace();
Utils.log("FileReceiver finish() --->>> occur expection"+ e.toString());
- if(mOnReceiveListener != null) mOnReceiveListener.onFailure(e, mFileInfo);
+ if(mOnReceiveListener != null) mOnReceiveListener.onFailure(e);
}
@@ -186,6 +194,12 @@ public class FileReceiver extends BaseTransfer implements Runnable {
long sTime = System.currentTimeMillis();
long eTime = 0;
+
+ double size = (((float)mFileInfo.getSize()/1024)/1024);
+ DecimalFormat df = new DecimalFormat("#.00");
+ String sizeName = df.format(size) + "MB";
+
+ String canDownload = FileUtils.isCanDownload(mContext, sizeName);
while((len=mInputStream.read(bytes)) != -1){
synchronized(LOCK) {
if (mIsPaused) {
@@ -196,6 +210,8 @@ public class FileReceiver extends BaseTransfer implements Runnable {
}
}
+ if (!TextUtils.isEmpty(canDownload)) break; // 内存不足 拒绝接受
+
bos.write(bytes, 0, len);
total = total + len;
eTime = System.currentTimeMillis();
@@ -217,10 +233,16 @@ public class FileReceiver extends BaseTransfer implements Runnable {
long endTime = System.currentTimeMillis();
Utils.log("接收完成对比 游戏总大小:" + fileSize + "游戏接收大小:" + total);
+
+ if (!TextUtils.isEmpty(canDownload)) { // 内存不足回调
+ if(mOnReceiveListener != null) mOnReceiveListener.onNoMemory();
+ return;
+ }
+
if (total == fileSize) {
- if(mOnReceiveListener != null) mOnReceiveListener.onSuccess(mFileInfo);
+ if(mOnReceiveListener != null) mOnReceiveListener.onSuccess();
} else {
- if(mOnReceiveListener != null) mOnReceiveListener.onCancel(mFileInfo);
+ if(mOnReceiveListener != null) mOnReceiveListener.onCancel();
}
}
@@ -280,9 +302,10 @@ public class FileReceiver extends BaseTransfer implements Runnable {
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);
+ void onSuccess();
+ void onFailure(Throwable t);
+ void onCancel();
+ void onNoMemory();
}
}
diff --git a/app/src/main/java/com/gh/gamecenter/kuaichuan/HotspotManager.java b/app/src/main/java/com/gh/gamecenter/kuaichuan/HotspotManager.java
index 04f4b261a1..f1638f2b7d 100644
--- a/app/src/main/java/com/gh/gamecenter/kuaichuan/HotspotManager.java
+++ b/app/src/main/java/com/gh/gamecenter/kuaichuan/HotspotManager.java
@@ -2,7 +2,12 @@ package com.gh.gamecenter.kuaichuan;
import android.content.Context;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+import android.text.TextUtils;
+import com.gh.common.util.Utils;
+
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
@@ -10,6 +15,62 @@ import java.lang.reflect.Method;
*/
public class HotspotManager {
+ private static String apSSID;
+ private static String apKey;
+ private static String apKeyMgmt;
+
+
+ public static void initApData(Context context) {
+ try {
+ WifiManager manager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ //拿到getWifiApConfiguration()方法
+ Method method = manager.getClass().getDeclaredMethod("getWifiApConfiguration");
+ //调用getWifiApConfiguration()方法,获取到 热点的WifiConfiguration
+ WifiConfiguration configuration = (WifiConfiguration) method.invoke(manager);
+ apSSID = configuration.SSID;
+ apKey = configuration.preSharedKey;
+ apKeyMgmt = configuration.allowedKeyManagement.toString();
+ Utils.log("=====名称:" + apSSID);
+ Utils.log("=====密码:" + apKey);
+ Utils.log("=====安全:" + apKeyMgmt);
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ // 初始化用户热点 回退到原始状态并关闭热点
+ public static void initUserAp(Context context) {
+ android.net.wifi.WifiManager wifimanager = (android.net.wifi.WifiManager) context.getSystemService(context.WIFI_SERVICE);
+ WifiConfiguration wificonfiguration = null;
+ try {
+ wificonfiguration = new WifiConfiguration();
+ wificonfiguration.SSID = apSSID;
+ if (!TextUtils.isEmpty(apKey)) {
+ wificonfiguration.preSharedKey = apKey;
+ wificonfiguration.allowedKeyManagement.set(4); //WPA2_PSK
+ }
+ // if WiFi is on, turn it off
+ if(isApOn(context)) {
+ wifimanager.setWifiEnabled(false);
+ // if ap is on and then disable ap
+ disableAp(context);
+ }
+ Method method = wifimanager.getClass().getMethod("setWifiApConfiguration", WifiConfiguration.class);
+ method.invoke(wifimanager, wificonfiguration);
+ }
+ catch (Exception e) {
+ Utils.log("======" + e.toString());
+ e.printStackTrace();
+ }
+ }
+
+
+
+
//检查热点开关
public static boolean isApOn(Context context) {
android.net.wifi.WifiManager wifimanager = (android.net.wifi.WifiManager) context.getSystemService(context.WIFI_SERVICE);
diff --git a/app/src/main/java/com/gh/gamecenter/kuaichuan/IpPortInfo.java b/app/src/main/java/com/gh/gamecenter/kuaichuan/IpPortInfo.java
index 1bad096a1b..a829c74cb3 100644
--- a/app/src/main/java/com/gh/gamecenter/kuaichuan/IpPortInfo.java
+++ b/app/src/main/java/com/gh/gamecenter/kuaichuan/IpPortInfo.java
@@ -12,11 +12,13 @@ public class IpPortInfo implements Serializable {
private int port;
private String senderName;
private int senderIcon;
+ private String receiverName;
- public IpPortInfo(InetAddress inetAddress, int port, String senderName, int senderIcon) {
+ public IpPortInfo(InetAddress inetAddress, int port, String senderName, String receiverName, int senderIcon) {
this.inetAddress = inetAddress;
this.port = port;
this.senderName = senderName;
+ this.receiverName = receiverName;
this.senderIcon = senderIcon;
}
@@ -51,4 +53,12 @@ public class IpPortInfo implements Serializable {
public void setSenderIcon(int senderIcon) {
this.senderIcon = senderIcon;
}
+
+ public String getReceiverName() {
+ return receiverName;
+ }
+
+ public void setReceiverName(String receiverName) {
+ this.receiverName = receiverName;
+ }
}
diff --git a/app/src/main/java/com/gh/gamecenter/personal/InstallFragmentAdapter.java b/app/src/main/java/com/gh/gamecenter/personal/InstallFragmentAdapter.java
index 623dacaa56..533e29ac8e 100644
--- a/app/src/main/java/com/gh/gamecenter/personal/InstallFragmentAdapter.java
+++ b/app/src/main/java/com/gh/gamecenter/personal/InstallFragmentAdapter.java
@@ -26,6 +26,7 @@ import com.gh.common.util.GameViewUtils;
import com.gh.common.util.PackageUtils;
import com.gh.common.util.PlatformUtils;
import com.gh.common.util.TrafficUtils;
+import com.gh.common.util.Utils;
import com.gh.common.view.SwipeLayout;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.ChooseReceiverActivity;
@@ -63,22 +64,29 @@ class InstallFragmentAdapter extends RecyclerView.Adapter gameList;
private ArrayList sortedList;
- private int cardMargin;
-
//下载用到的map
private ArrayMap> locationMap;
+ private LibaoDao libaoDao;
+
private boolean isRemove;
private boolean isSwipe;
- private LibaoDao libaoDao;
-
private boolean showUserNameHint;
+ private boolean showKcHint;
+
+ private int cardMargin;
+
+ private int maxWidth;
+
+
InstallFragmentAdapter(InstallFragment fragment) {
this.context = fragment.getActivity();
@@ -94,8 +102,11 @@ class InstallFragmentAdapter extends RecyclerView.Adapter runnableGame = cManager.getInstalledGame();
@@ -346,9 +357,18 @@ class InstallFragmentAdapter extends RecyclerView.Adapter 480) {
- holder.swipeText.setPadding(0, 0, DisplayUtils.dip2px(context, 30), 0);
- holder.swipeText.setText("释放分享");
+ Utils.log("==================zzz" + leftOffset + "==" + maxWidth/2);
+ if (leftOffset > maxWidth/2) {
+// holder.swipeText.setPadding(0, 0, DisplayUtils.dip2px(context, 30), 0);
+ holder.swipeText.setVisibility(View.GONE);
+ holder.swipeShareText.setVisibility(View.VISIBLE);
} else {
- holder.swipeText.setPadding(0, 0, DisplayUtils.dip2px(context, 15), 0);
- holder.swipeText.setText("右划分享");
+// holder.swipeText.setPadding(0, 0, DisplayUtils.dip2px(context, 15), 0);
+ holder.swipeText.setVisibility(View.VISIBLE);
+ holder.swipeShareText.setVisibility(View.GONE);
}
}
@@ -520,14 +543,17 @@ class InstallFragmentAdapter extends RecyclerView.Adapter postGhzs(@Header("TOKEN") String token, @Body RequestBody body);
+ @Headers({"Content-Type: application/json", "Accept: application/json"})
+ @POST("icon-default") // 上传用户所使用的助手信息
+ Observable postDefaultIcon(@Header("TOKEN") String token, @Body RequestBody body);
+
}
diff --git a/app/src/main/res/anim/huojian_test_anim.xml b/app/src/main/res/anim/huojian_test_anim.xml
new file mode 100644
index 0000000000..8938d9f075
--- /dev/null
+++ b/app/src/main/res/anim/huojian_test_anim.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable-hdpi/anyshare_scan_anim_rocket_fire.png b/app/src/main/res/drawable-hdpi/anyshare_scan_anim_rocket_fire.png
new file mode 100644
index 0000000000000000000000000000000000000000..cfe3f27191c5f4ffc8579bef0ddf6d1de073f0fe
GIT binary patch
literal 1426
zcmZuxdpy)x6dxfa)-o#NZ9MZDAL|u^5gMa0BV&6^gdNWvnY0Qu%xFy>OCFU(LzG8(
ztWZ0vyqfVSM7u?KtYtN&`5^ja(D>b*!R|l1_jB$!-}^o1d+zz%KW>IE0jnslE)Rpj
z6mec2e&XmV-p)Iu#ohwv#)rYAynXThp5h}k=J)^B>kU=7KvgbKEe0xaf^MOq5#N6+
z0o4RV7=aLd@U0FwtOaG;Zl(as8n`2X%U-Bx|5h;%w*{`)1FSkA>wzd^sPTZ91hJ-2
zD|Sm5hy*^GAZFjz(M=67P+P){2|=70H0T4uj3h#T9bl&lj_XOVSmmt&qD_DY0tD$x
zc*or!-W-G&Y_$?I!3Izt9#9M=^>(UIKVCAS7$4JvZaYhu%_}y5q{BZ3b$9`ymLyy1
z1pQ8c9(rt6{@3U4w?&FyGbYZDK!SAx0b=KBx)a!3OG>9V0l8cfYe&J9XoD~Vz?vjR
zo{0e9i!hG?SnC^WnlXF<`nlX94q*Q#Q@I4F%ofQQ$>w`nT|69?7d=PP-=+k|JK+-*_i4HG;=Z@@`P*P|k{aDIv$#{a
zca9dU$=#$IWQwQ=9fMTfw4#k_l`}U}O20S9o00XxEfoF2*S*o%K*;^)L?rS!+)A%$j??{7ugAuu6c)n@n4rTqjFT=-aWfmw4W;liy
z)2}?X?w-9EYllQ_D~xGRI9`~m_`FJk7yMko&9wNn%zG7je)Q~EY7dSr#ZpT$w?b3k
zo=mN$>nB>;4kg^|_D{|^#y_;2~tRY8566}pmn_XC^{X2YKes%9eBYu(iJGrCfu-EQx-x2=
zq@Bz%yL%oHiIX*W@7-TwZ_`QmOdA^bsPW^qNs9Wx+RIPk*UJ^GQo{Uw
zcxvZq7{Tp65OOW+hwX05oHGNAbu_19P<2_+ac@IJ<$zWoREKC%zT)>FbY$uxg*`oIj&p^6Xmxi=PrNG}ge#$4;3tQJ1?
zoTBnD)po=oD_y`$qU>tpynDnuYXrAbD#m`)f=B&<;ER6)wdeCG
literal 0
HcmV?d00001
diff --git a/app/src/main/res/drawable-hdpi/hotspot_failed_icon.png b/app/src/main/res/drawable-hdpi/hotspot_failed_icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..558758d19956cdb2ac42f778ed2e136fa73b2bf2
GIT binary patch
literal 949
zcmV;m14{gfP)7*Cv;8hSfVfu7DWoISSVB|hEU+bK8l3MRuo7YQqZ`ip>c}PAVpAGA}&IT
zBtlUvVi`JP}m@EO6hnb8Romy@_kgezwjj@`PDB-6b24$f7hiNJEK39{nHvI91M*Tol
zfob6Un3n#*
za6k3X|Eii)b`Df%n;$b}*QvY)uvL@t$*`2^tHMkww@&R;%J{=rt4Repowafqm{-a#
zp6$xKpVg$@0i4|hOs1+(nfLvgv{ivmb_uf^sLcCrP1-lD;uvB8_%V!O1FK{_qbL9CJ%KjV&pXyp3j3}$G&VD
zKTFHN342@Ichey}l2X@<<>n$gYwAU56E`C53hMg^Q`g#g+{s|_K%^S?snpHi?h{lU
z--X9ht-87^(5CcU*YFvBle%`VbSPq82#=}A^o2n10;jZk>XGgPy{x7pR@O78!fS_$
zvi%FZuQjHc_(kzL)l1{iwkaDkDRu`;FCfz6yMP(3C1C}BN!ywabWg~GacwT{UD2A_
zGZC|}80_c3Y7xKNd0=(C?fSY@T#-tM;avMt2Uh)_pl#!ucy&9{%OJL->Y@K5y`267
XYWNC)VO{JB00000NkvXXu0mjf)tb(!
literal 0
HcmV?d00001
diff --git a/app/src/main/res/drawable-hdpi/installfragment_footerview_icon.png b/app/src/main/res/drawable-hdpi/installfragment_footerview_icon.png
index 58b6cf8cc5f93791b4c1e750d8917a0ef35d456c..fdbfe64a1a04dc4a8be69fe0eef8f235b4e63c3a 100644
GIT binary patch
literal 30000
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
literal 28914
zcmXtgcRbep_rD~!C@VXAls&R#?;W!D-kI4eBzv#y>||w=ki9}OLu7BVviY6s^Lu>%
zxR;wN*X#W{=RDWB!c~-I9-@<=BOxI@l#`WILqfWv1pgj|h6;Z_HlN3|;
z%-m`5@>M@+xxLNw8#I5Cw$p4*b)S+*RFpB&-c~F(^1^khUU#Q%kmY*9hhlzmcivXd
zv2Jp9zCN!-^Ht<{gshlK6-yqaohYTreOmJz`StRZ2Px0_18YReI?d6!Pk`f&!4O#xEsJlCl
zOe}ffmoMo}uIq;bOqD+-Cc1}s7Zkeiqq(<1KoXRx;+Bl=ub57JSEFePZC4o`JZ5{v)P54o`Gbh&7GZ<
z{8(W%Qi0d9CePB6ZVxDKb48r~yeX=$pHwk0c(t{&qyAQ$N>^9c`qit#(o&4Jg%`BA
zV!0~V;gV=5$ZtDMkdox-G)t4ee^;!osgaYHr^ZH$OHU_B=XsUhY0Q3B{33_k_v)ax
zMLM5DUt60fP1w(S1>R0UYiqX1)gl(N_UAWVM{89MzXhVCX>u;-);*V_dEfKAB4PXb
z7kR8mX}J?iWF=mPJh!ecIV$QwtuD)m;L!u4+lwiF&%cxkDaF9i(lH->8@^$71yz_uoU(5NC$T={@9&sdU;taaxJ%g;F%rsp#!35E2rC+fI*%j)yMQW(L0sDdvB_fBz;G_I)o(DauZS@&}$V_W&lSPs5M^Ujd{8VR5
zem~T&U9PF2r`ER#pYs=Qp)wO2v->f6AcZ*@NZut{#?&PH<)3xtu63WV$78VxM
z_B?P(o12^F78da4e{8<~sLqIo-i@U8s9^Kx+({sdFH8ALbMxlj9_okU;?S8HU0prB
z
0IF}D=Rg^_0suN3=Er5+vmQ*aKEN&tgxQD@2Kp~)G=+sGgtIJnb5i;?z;Bf`FlF|
z;MlKUn>-}Z74W0q&fg0>jT1#Si;PU?qKQXiU|>LxmNvT@%egT(Y}gx0dNo^5Ol9kq
zl9c4MnymHAV^1G(I5sv6jLD39{ww>)hntO8K0Dq^K76Dp%xa5w@fX|#$nM>{hlhvf
z1h)^_>Flpb{j1rY6c#=8X7}A{;gj)~nr{jfQvY#ran%+V6r6pxtkFADc_d327)e1$
zX7jGoea&Sb&mh(-tUWuh=`<^7|itqI)#~3Hlw|b
zjSW6F)qNCPS>u&Pdf6HelHvIlpTum>rSR`8diC#pyuHYOO#
z9%EQ*b#=nPfIM7g2DxeW2aZT8A
zD=8`UV+o%b|7+fFwL3ibjY#9Ps`fp1vHbo%P_y(N<rl3=Img($<5784omRw8-rYx
z*LTCuy^-(hqcl<$l&CY_M-Bc|UtfQ`@4Nn7$GzDgIW@IctL;LgqV2{T8k~WF0nr0g
zc?AWIjG^nirPMqX!AZ9dnlfyD^mx#;k=QK;@Zda+s!Y4l$$fS>y7e4eEUsZ#Bv5#7
z*eqLHRwkZ(CWT#O_Vk*zI(i}
zv(vSFprWeUUTcGxY`azlJ<9!TmQ0T})*Yk$#MI3`sgKf`VQbG4M2!3ToqaVS2J9#2hon~UWexC>FMxxl9G~CR8-#RmiMe5$t92xeT=-a
zdUNHwqQ(H#!^X4WUh!;AQ~7P%qY_=T~~XpK^yn2Fv?Xr
zJ?O#Dv9a@QYcW&?9!^et93aPBC?f+5GGBHKMc!JJL%U_k~r02N^&R^WX{JcDB|C^(nmpVHAFJB0CAB~9QsA*^vvaztd(ylg_d-0X|BjPR2
z{mD#YfYBz}1k?CfhQhDby7S$`C;6j&TCIop;3zze!)sG)Po`B;L
zJo^(o=e=Ei<|_=t6`nMVro5?bxbb(x)C{Y4bF%PE-LhRg-iqgb+dqAT9zxH^Xu8-D
zf)Xrt^RJ<;gvWk5u58pA#?U7w+;HP6?SjzZb95p)=HDp73PeZE@+Ind6V~cjB3Dj(
zl>yh=wN8BBC$x-)K53NFv$FO$G%O!@(lav`G&T~|=_=9VT_|ENr(y43b>kTns^MUU
z9$a3ptgRg;=3KoE3PRQ_*DX97jrC8On3%vnzd3DNxEfhGQi2A7V`tyImVpskmy5%X3
z0hhDTB@pGtc#F70gK&e7$6oM8rsv#;TQhB@SiH`YF?4)=8=$cWO)CMZ`)8rTc|*V@
zZ
z^`rRYGbj(CS=icon0ye+$Ni`qNd>~bs@2I
zczLHuSL0;)5W`{x@2jfbLyx^V8x(CQnT4x0-cj2+04{J2nxz`limI=94c{puA5gU^
z=S`{7;!@$E=Z;z6g42BP2+J&u|$CJrx>d?!vd_9Ev-
zPRz}%?vC-+cuARV9eS2>=-4Jo-eG=10&YS=!i9zip)B@VAEo}|jt≥DX}fqkM|%
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