commit 3f29f7b39a93ee9326f56df83f0ec522ca6ff0d5 Author: huangzhuanghua <401742778@qq.com> Date: Mon Apr 25 11:18:59 2016 +0800 提交项目 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..c6cbe562a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000000..de71a895f6 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +GH-ASSISTv1.45 \ No newline at end of file diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml new file mode 100644 index 0000000000..b6c1cd7c79 --- /dev/null +++ b/.idea/codeStyleSettings.xml @@ -0,0 +1,229 @@ + + + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000000..96cc43efa6 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000000..e7bedf3377 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000000..97626ba454 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000000..25de04808a --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,24 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000000..45bb483c5e --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000000..fe0d0ade49 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000000..7f68460d8b --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000000..94a25f7f4c --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000000..796b96d1c4 --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000000..69271c631e --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,26 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 19 + buildToolsVersion "23.0.3" + + defaultConfig { + applicationId "com.gh.gamecenter" + minSdkVersion 14 + targetSdkVersion 19 + versionCode 10 + versionName "1.45" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) + testCompile 'junit:junit:4.12' +} diff --git a/app/libs/EventBus-2.4.0.jar b/app/libs/EventBus-2.4.0.jar new file mode 100644 index 0000000000..106ed5b53d Binary files /dev/null and b/app/libs/EventBus-2.4.0.jar differ diff --git a/app/libs/MiPush_SDK_Client_2_2_18.jar b/app/libs/MiPush_SDK_Client_2_2_18.jar new file mode 100644 index 0000000000..837bfff2dd Binary files /dev/null and b/app/libs/MiPush_SDK_Client_2_2_18.jar differ diff --git a/app/libs/MobTools.jar b/app/libs/MobTools.jar new file mode 100644 index 0000000000..c27145ed4c Binary files /dev/null and b/app/libs/MobTools.jar differ diff --git a/app/libs/ShareSDK-Core-2.6.0.jar b/app/libs/ShareSDK-Core-2.6.0.jar new file mode 100644 index 0000000000..e809c414f9 Binary files /dev/null and b/app/libs/ShareSDK-Core-2.6.0.jar differ diff --git a/app/libs/ShareSDK-QQ-2.6.0.jar b/app/libs/ShareSDK-QQ-2.6.0.jar new file mode 100644 index 0000000000..a2a092b25d Binary files /dev/null and b/app/libs/ShareSDK-QQ-2.6.0.jar differ diff --git a/app/libs/ShareSDK-QZone-2.6.0.jar b/app/libs/ShareSDK-QZone-2.6.0.jar new file mode 100644 index 0000000000..9c3a501049 Binary files /dev/null and b/app/libs/ShareSDK-QZone-2.6.0.jar differ diff --git a/app/libs/ShareSDK-SinaWeibo-2.6.0.jar b/app/libs/ShareSDK-SinaWeibo-2.6.0.jar new file mode 100644 index 0000000000..6afdd00fe1 Binary files /dev/null and b/app/libs/ShareSDK-SinaWeibo-2.6.0.jar differ diff --git a/app/libs/TalkingDataAnalytics_V1.2.79.jar b/app/libs/TalkingDataAnalytics_V1.2.79.jar new file mode 100644 index 0000000000..a0adfd9247 Binary files /dev/null and b/app/libs/TalkingDataAnalytics_V1.2.79.jar differ diff --git a/app/libs/android-support-v4.jar b/app/libs/android-support-v4.jar new file mode 100644 index 0000000000..7b78bb8ee8 Binary files /dev/null and b/app/libs/android-support-v4.jar differ diff --git a/app/libs/android-support-v7-appcompat.jar b/app/libs/android-support-v7-appcompat.jar new file mode 100644 index 0000000000..830a4936a6 Binary files /dev/null and b/app/libs/android-support-v7-appcompat.jar differ diff --git a/app/libs/gson-2.3.1.jar b/app/libs/gson-2.3.1.jar new file mode 100644 index 0000000000..250132c197 Binary files /dev/null and b/app/libs/gson-2.3.1.jar differ diff --git a/app/libs/ormlite-android-4.49-SNAPSHOT.jar b/app/libs/ormlite-android-4.49-SNAPSHOT.jar new file mode 100644 index 0000000000..6241326e78 Binary files /dev/null and b/app/libs/ormlite-android-4.49-SNAPSHOT.jar differ diff --git a/app/libs/ormlite-core-4.49-SNAPSHOT.jar b/app/libs/ormlite-core-4.49-SNAPSHOT.jar new file mode 100644 index 0000000000..c467a055ba Binary files /dev/null and b/app/libs/ormlite-core-4.49-SNAPSHOT.jar differ diff --git a/app/libs/recycler-v7-21.jar b/app/libs/recycler-v7-21.jar new file mode 100644 index 0000000000..9c48d7a9e3 Binary files /dev/null and b/app/libs/recycler-v7-21.jar differ diff --git a/app/libs/universal-image-loader-1.9.4.jar b/app/libs/universal-image-loader-1.9.4.jar new file mode 100644 index 0000000000..871d0e8f9c Binary files /dev/null and b/app/libs/universal-image-loader-1.9.4.jar differ diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000000..8a2f402f9c --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in C:\Android\sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/app/src/androidTest/java/com/gh/gamecenter/ApplicationTest.java b/app/src/androidTest/java/com/gh/gamecenter/ApplicationTest.java new file mode 100644 index 0000000000..8b27fad01c --- /dev/null +++ b/app/src/androidTest/java/com/gh/gamecenter/ApplicationTest.java @@ -0,0 +1,13 @@ +package com.gh.gamecenter; + +import android.app.Application; +import android.test.ApplicationTestCase; + +/** + * Testing Fundamentals + */ +public class ApplicationTest extends ApplicationTestCase { + public ApplicationTest() { + super(Application.class); + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..10ae9cce30 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,258 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/cn/sharesdk/onekeyshare/CustomerLogo.java b/app/src/main/java/cn/sharesdk/onekeyshare/CustomerLogo.java new file mode 100644 index 0000000000..027653c8b4 --- /dev/null +++ b/app/src/main/java/cn/sharesdk/onekeyshare/CustomerLogo.java @@ -0,0 +1,20 @@ +/* + * 官网地站:http://www.mob.com + * 技术支持QQ: 4006852216 + * 官方微信:ShareSDK (如果发布新版本的话,我们将会第一时间通过微信将版本更新内容推送给您。如果使用过程中有任何问题,也可以通过微信与我们取得联系,我们将会在24小时内给予回复) + * + * Copyright (c) 2013年 mob.com. All rights reserved. + */ + +package cn.sharesdk.onekeyshare; + +import android.graphics.Bitmap; +import android.view.View.OnClickListener; + +/** 九宫格自定义的图标对象 */ +public class CustomerLogo { + public String label; + public Bitmap enableLogo; + public Bitmap disableLogo; + public OnClickListener listener; +} diff --git a/app/src/main/java/cn/sharesdk/onekeyshare/EditPageFakeActivity.java b/app/src/main/java/cn/sharesdk/onekeyshare/EditPageFakeActivity.java new file mode 100644 index 0000000000..946097c5d8 --- /dev/null +++ b/app/src/main/java/cn/sharesdk/onekeyshare/EditPageFakeActivity.java @@ -0,0 +1,263 @@ +/* + * 官网地站:http://www.mob.com + * 技术支持QQ: 4006852216 + * 官方微信:ShareSDK (如果发布新版本的话,我们将会第一时间通过微信将版本更新内容推送给您。如果使用过程中有任何问题,也可以通过微信与我们取得联系,我们将会在24小时内给予回复) + * + * Copyright (c) 2013年 mob.com. All rights reserved. + */ + +package cn.sharesdk.onekeyshare; + + +import static com.mob.tools.utils.R.getStringRes; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import android.graphics.Bitmap; +import android.os.AsyncTask; +import android.text.TextUtils; +import android.view.View; +import android.widget.Toast; +import cn.sharesdk.framework.Platform; +import cn.sharesdk.framework.ShareSDK; + +import com.mob.tools.FakeActivity; +import com.mob.tools.utils.BitmapHelper; + +public class EditPageFakeActivity extends FakeActivity { + + protected List platforms; + + protected HashMap shareParamMap; + // 设置显示模式为Dialog模式 + protected boolean dialogMode; + protected View backgroundView; + protected ArrayList toFriendList; + private ArrayList shareImageList; + + public static class ImageInfo { + public String paramName; + public String srcValue; + public Bitmap bitmap; + } + + protected static interface ImageListResultsCallback { + void onFinish(ArrayList results); + } + + public void setShareData(HashMap data) { + shareParamMap = data; + } + + /** 设置显示模式为Dialog模式 */ + public void setDialogMode() { + dialogMode = true; + } + + /** + * @param bgView + */ + public void setBackgroundView(View bgView) { + this.backgroundView = bgView; + } + + public void setPlatforms(List supportEditPagePlatforms) { + this.platforms = supportEditPagePlatforms; + } + + public String getLogoName(String platform) { + if (platform == null) { + return ""; + } + + int resId = getStringRes(getContext(), platform); + return getContext().getString(resId); + } + + protected boolean isShowAtUserLayout(String platformName) { + return "SinaWeibo".equals(platformName) || "TencentWeibo".equals(platformName) + || "Facebook".equals(platformName) || "Twitter".equals(platformName) + || "FacebookMessenger".equals(platformName); + } + + protected String getAtUserButtonText(String platform) { + return "FacebookMessenger".equals(platform) ? "To" : "@"; + } + + protected String getJoinSelectedUser(HashMap data) { + if (data != null && data.containsKey("selected")) { + @SuppressWarnings("unchecked") + ArrayList selected = (ArrayList) data.get("selected"); + String platform = ((Platform)data.get("platform")).getName(); + if("FacebookMessenger".equals(platform)) { + toFriendList = selected; + return null; + } + StringBuilder sb = new StringBuilder(); + for (String sel : selected) { + sb.append('@').append(sel).append(' '); + } + return sb.toString(); + } + return null; + } + + public boolean haveImage(){ + String imageUrl = (String) shareParamMap.get("imageUrl"); + String imagePath = (String) shareParamMap.get("imagePath"); + Bitmap viewToShare = (Bitmap) shareParamMap.get("viewToShare"); + String[] imageArray = (String[]) shareParamMap.get("imageArray"); + + if(!TextUtils.isEmpty(imagePath) && new File(imagePath).exists()) { + return true; + } else if(viewToShare != null && !viewToShare.isRecycled()){ + return true; + } else if (!TextUtils.isEmpty(imageUrl)) { + return true; + } else if(imageArray != null && imageArray.length > 0) { + return true; + } + + return false; + } + + protected boolean initImageList(ImageListResultsCallback callback) { + String imageUrl = (String) shareParamMap.get("imageUrl"); + String imagePath = (String) shareParamMap.get("imagePath"); + Bitmap viewToShare = (Bitmap) shareParamMap.get("viewToShare"); + String[] imageArray = (String[]) shareParamMap.get("imageArray"); + + shareImageList = new ArrayList(); + if(!TextUtils.isEmpty(imagePath) && new File(imagePath).exists()) { + ImageInfo imageInfo = new ImageInfo(); + imageInfo.paramName = "imagePath"; + imageInfo.srcValue = imagePath; + shareImageList.add(imageInfo); + shareParamMap.remove("imagePath"); + } else if(viewToShare != null && !viewToShare.isRecycled()){ + ImageInfo imageInfo = new ImageInfo(); + imageInfo.paramName = "viewToShare"; + imageInfo.bitmap = viewToShare; + shareImageList.add(imageInfo); + shareParamMap.remove("viewToShare"); + } else if (!TextUtils.isEmpty(imageUrl)) { + ImageInfo imageInfo = new ImageInfo(); + imageInfo.paramName = "imageUrl"; + imageInfo.srcValue = imageUrl; + shareImageList.add(imageInfo); + shareParamMap.remove("imageUrl"); + } else if(imageArray != null && imageArray.length > 0) { + for(String imageUri : imageArray) { + if(TextUtils.isEmpty(imageUri)) + continue; + ImageInfo imageInfo = new ImageInfo(); + imageInfo.paramName = "imageArray"; + imageInfo.srcValue = imageUri; + shareImageList.add(imageInfo); + } + shareParamMap.remove("imageArray"); + } + + if(shareImageList.size() == 0) { + return false; + } + + new AsyncTask() { + @Override + protected ImageListResultsCallback doInBackground(Object... objects) { + for(ImageInfo imageInfo : shareImageList) { + if(imageInfo.bitmap == null) { + try{ + Bitmap bitmap; + String uri = imageInfo.srcValue; + if(uri.startsWith("http://") || uri.startsWith("https://")) { + uri = BitmapHelper.downloadBitmap(activity, uri); + } + bitmap = BitmapHelper.getBitmap(uri); + if(bitmap == null) + continue; + + imageInfo.bitmap = bitmap; + } catch (Throwable e) { + e.printStackTrace(); + } + } + } + return (ImageListResultsCallback) objects[0]; + } + + @Override + protected void onPostExecute(ImageListResultsCallback callback1) { + callback1.onFinish(shareImageList); + } + }.execute(callback); + return true; + } + + protected void removeImage(ImageInfo imageInfo) { + if(shareImageList == null || imageInfo == null) + return; + shareImageList.remove(imageInfo); + } + + protected void setResultAndFinish() { + ArrayList imageArray = new ArrayList(); + if(shareImageList != null) { + for(ImageInfo imageInfo : shareImageList) { + if("imagePath".equals(imageInfo.paramName) || "imageUrl".equals(imageInfo.paramName)) { + shareParamMap.put(imageInfo.paramName, imageInfo.srcValue); + } else if("viewToShare".equals(imageInfo.paramName)) { + shareParamMap.put(imageInfo.paramName, imageInfo.bitmap); + } else if("imageArray".equals(imageInfo.paramName)) { + imageArray.add(imageInfo.srcValue); + } + } + shareImageList.clear(); + if(imageArray.size() == 0) { + shareParamMap.put("imageArray", null); + } else { + shareParamMap.put("imageArray", imageArray.toArray(new String[imageArray.size()])); + } + } + + HashMap> editRes = new HashMap>(); + + for(Platform platform : platforms) { + + if("FacebookMessenger".equals(platform.getName())) { + HashMap param = new HashMap(shareParamMap); + if(toFriendList != null && toFriendList.size() > 0) { + param.put("address", toFriendList.get(toFriendList.size() - 1)); + } + if(param.get("address") == null) { + int resId = getStringRes(activity, "select_a_friend"); + if (resId > 0) { + Toast.makeText(getContext(), activity.getString(resId) + " - " + platform.getName(), Toast.LENGTH_SHORT).show(); + } + return; + } + editRes.put(platform, param); + // a statistics of Sharing + ShareSDK.logDemoEvent(3, platform); + continue; + } + // a statistics of Sharing + ShareSDK.logDemoEvent(3, platform); + editRes.put(platform, shareParamMap); + } + + HashMap res = new HashMap(); + res.put("editRes", editRes); + setResult(res); + finish(); + } + + @Override + public boolean onFinish() { + shareImageList = null; + return super.onFinish(); + } +} diff --git a/app/src/main/java/cn/sharesdk/onekeyshare/FollowerListFakeActivity.java b/app/src/main/java/cn/sharesdk/onekeyshare/FollowerListFakeActivity.java new file mode 100644 index 0000000000..93481bc26f --- /dev/null +++ b/app/src/main/java/cn/sharesdk/onekeyshare/FollowerListFakeActivity.java @@ -0,0 +1,168 @@ +package cn.sharesdk.onekeyshare; + +import java.util.ArrayList; +import java.util.HashMap; + +import cn.sharesdk.framework.Platform; + +import com.mob.tools.FakeActivity; + +public class FollowerListFakeActivity extends FakeActivity { + protected Platform platform; + + public void setPlatform(Platform platform) { + this.platform = platform; + } + + public Platform getPlatform() { + return platform; + } + + public boolean isRadioMode(String platformName) { + return "FacebookMessenger".equals(platformName); + } + + public void setResultForChecked(ArrayList checked) { + HashMap res = new HashMap(); + res.put("selected", checked); + res.put("platform", platform); + setResult(res); + } + + public static class Following { + public boolean checked; + public String screenName; + public String description; + public String uid; + public String icon; + //@Name 用于微博等提示或关联某个人 + public String atName; + } + + public static class FollowersResult { + public ArrayList list; + public boolean hasNextPage = false; + } + + public static FollowersResult parseFollowers(String platformName, HashMap res, HashMap uidMap) { + if (res == null || res.size() <= 0) { + return null; + } + + boolean hasNext = false; + ArrayList data = new ArrayList(); + if ("SinaWeibo".equals(platformName)) { + // users[id, name, description] + @SuppressWarnings("unchecked") + ArrayList> users + = (ArrayList>) res.get("users"); + for (HashMap user : users) { + String uid = String.valueOf(user.get("id")); + if (!uidMap.containsKey(uid)) { + Following following = new Following(); + following.uid = uid; + following.screenName = String.valueOf(user.get("name")); + following.description = String.valueOf(user.get("description")); + following.icon = String.valueOf(user.get("profile_image_url")); + following.atName = following.screenName; + uidMap.put(following.uid, true); + data.add(following); + } + } + hasNext = (Integer) res.get("total_number") > uidMap.size(); + } + else if ("TencentWeibo".equals(platformName)) { + hasNext = ((Integer)res.get("hasnext") == 0); + // info[nick, name, tweet[text]] + @SuppressWarnings("unchecked") + ArrayList> infos + = (ArrayList>) res.get("info"); + for (HashMap info : infos) { + String uid = String.valueOf(info.get("name")); + if (!uidMap.containsKey(uid)) { + Following following = new Following(); + following.screenName = String.valueOf(info.get("nick")); + following.uid = uid; + following.atName = uid; + @SuppressWarnings("unchecked") + ArrayList> tweets = (ArrayList>) info.get("tweet"); + for (HashMap tweet : tweets) { + following.description = String.valueOf(tweet.get("text")); + break; + } + following.icon = String.valueOf(info.get("head")) + "/100"; + uidMap.put(following.uid, true); + data.add(following); + } + } + } + else if ("Facebook".equals(platformName)) { + // data[id, name] + @SuppressWarnings("unchecked") + ArrayList> datas + = (ArrayList>) res.get("data"); + for (HashMap d : datas) { + String uid = String.valueOf(d.get("id")); + if (!uidMap.containsKey(uid)) { + Following following = new Following(); + following.uid = uid; + following.atName = "["+uid+"]"; + following.screenName = String.valueOf(d.get("name")); + @SuppressWarnings("unchecked") + HashMap picture = (HashMap) d.get("picture"); + if (picture != null) { + @SuppressWarnings("unchecked") + HashMap pData = (HashMap) picture.get("data"); + following.icon = String.valueOf(pData.get("url")); + } + uidMap.put(following.uid, true); + data.add(following); + } + } + @SuppressWarnings("unchecked") + HashMap paging = (HashMap) res.get("paging"); + hasNext = paging.containsKey("next"); + } + else if ("Twitter".equals(platformName)) { + // users[screen_name, name, description] + @SuppressWarnings("unchecked") + ArrayList> users + = (ArrayList>) res.get("users"); + for (HashMap user : users) { + String uid = String.valueOf(user.get("screen_name")); + if (!uidMap.containsKey(uid)) { + Following following = new Following(); + following.uid = uid; + following.atName = uid; + following.screenName = String.valueOf(user.get("name")); + following.description = String.valueOf(user.get("description")); + following.icon = String.valueOf(user.get("profile_image_url")); + uidMap.put(following.uid, true); + data.add(following); + } + } + } + else if ("FacebookMessenger".equals(platformName)) { + @SuppressWarnings("unchecked") + ArrayList> users + = (ArrayList>) res.get("users"); + for (HashMap user : users) { + String userAddr = String.valueOf(user.get("jid")); + if (!uidMap.containsKey(userAddr)) { + Following following = new Following(); + following.uid = userAddr; + following.atName = userAddr; + following.screenName = String.valueOf(user.get("name")); + uidMap.put(following.uid, true); + data.add(following); + } + } + hasNext = false; + } + + FollowersResult ret = new FollowersResult(); + ret.list = data; + ret.hasNextPage = hasNext; + return ret; + } +} diff --git a/app/src/main/java/cn/sharesdk/onekeyshare/OnekeyShare.java b/app/src/main/java/cn/sharesdk/onekeyshare/OnekeyShare.java new file mode 100644 index 0000000000..0da9c9c596 --- /dev/null +++ b/app/src/main/java/cn/sharesdk/onekeyshare/OnekeyShare.java @@ -0,0 +1,601 @@ +/* + * 官网地站:http://www.mob.com + * 技术支持QQ: 4006852216 + * 官方微信:ShareSDK (如果发布新版本的话,我们将会第一时间通过微信将版本更新内容推送给您。如果使用过程中有任何问题,也可以通过微信与我们取得联系,我们将会在24小时内给予回复) + * + * Copyright (c) 2013年 mob.com. All rights reserved. + */ + +package cn.sharesdk.onekeyshare; + +import static com.mob.tools.utils.BitmapHelper.captureView; +import static com.mob.tools.utils.R.getStringRes; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map.Entry; + +import android.app.NotificationManager; +import android.content.Context; +import android.graphics.Bitmap; +import android.os.Handler.Callback; +import android.os.Message; +import android.text.TextUtils; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Toast; +import cn.sharesdk.framework.CustomPlatform; +import cn.sharesdk.framework.Platform; +import cn.sharesdk.framework.PlatformActionListener; +import cn.sharesdk.framework.ShareSDK; + +import com.mob.tools.utils.UIHandler; + +/** + * 快捷分享的入口 + *

+ * 通过不同的setter设置参数,然后调用{@link #show(Context)}方法启动快捷分享 + */ +public class OnekeyShare implements PlatformActionListener, Callback { + private static final int MSG_TOAST = 1; + private static final int MSG_ACTION_CCALLBACK = 2; + private static final int MSG_CANCEL_NOTIFY = 3; + + private HashMap shareParamsMap; + private ArrayList customers; + private boolean silent; + private PlatformActionListener callback; + private ShareContentCustomizeCallback customizeCallback; + private boolean dialogMode = false; + private boolean disableSSO; + private HashMap hiddenPlatforms; + private View bgView; + private OnekeyShareTheme theme; + + private Context context; + private PlatformListFakeActivity.OnShareButtonClickListener onShareButtonClickListener; + + public OnekeyShare() { + shareParamsMap = new HashMap(); + customers = new ArrayList(); + callback = this; + hiddenPlatforms = new HashMap(); + } + + public void show(Context context) { + ShareSDK.initSDK(context); + this.context = context; + + // 打开分享菜单的统计 + ShareSDK.logDemoEvent(1, null); + + // 显示方式是由platform和silent两个字段控制的 + // 如果platform设置了,则无须显示九宫格,否则都会显示; + // 如果silent为true,表示不进入编辑页面,否则会进入。 + // 本类只判断platform,因为九宫格显示以后,事件交给PlatformGridView控制 + // 当platform和silent都为true,则直接进入分享; + // 当platform设置了,但是silent为false,则判断是否是“使用客户端分享”的平台, + // 若为“使用客户端分享”的平台,则直接分享,否则进入编辑页面 + if (shareParamsMap.containsKey("platform")) { + String name = String.valueOf(shareParamsMap.get("platform")); + Platform platform = ShareSDK.getPlatform(name); + + if (silent + || ShareCore.isUseClientToShare(name) + || platform instanceof CustomPlatform + ) { + HashMap> shareData + = new HashMap>(); + shareData.put(ShareSDK.getPlatform(name), shareParamsMap); + share(shareData); + return; + } + } + + PlatformListFakeActivity platformListFakeActivity; + try { + if(OnekeyShareTheme.SKYBLUE == theme){ + platformListFakeActivity = (PlatformListFakeActivity) Class.forName("cn.sharesdk.onekeyshare.theme.skyblue.PlatformListPage").newInstance(); + }else{ + platformListFakeActivity = (PlatformListFakeActivity) Class.forName("cn.sharesdk.onekeyshare.theme.classic.PlatformListPage").newInstance(); + } + } catch (Exception e) { + e.printStackTrace(); + return; + } + + platformListFakeActivity.setDialogMode(dialogMode); + platformListFakeActivity.setShareParamsMap(shareParamsMap); + platformListFakeActivity.setSilent(silent); + platformListFakeActivity.setCustomerLogos(customers); + platformListFakeActivity.setBackgroundView(bgView); + platformListFakeActivity.setHiddenPlatforms(hiddenPlatforms); + platformListFakeActivity.setOnShareButtonClickListener(onShareButtonClickListener); + platformListFakeActivity.setThemeShareCallback(new ThemeShareCallback() { + + @Override + public void doShare(HashMap> shareData) { + share(shareData); + } + }); + if (shareParamsMap.containsKey("platform")) { + String name = String.valueOf(shareParamsMap.get("platform")); + Platform platform = ShareSDK.getPlatform(name); + platformListFakeActivity.showEditPage(context, platform); + return; + } + platformListFakeActivity.show(context, null); + } + + public void setTheme(OnekeyShareTheme theme) { + this.theme = theme; + } + + /** address是接收人地址,仅在信息和邮件使用,否则可以不提供 */ + public void setAddress(String address) { + shareParamsMap.put("address", address); + } + + /** + * title标题,在印象笔记、邮箱、信息、微信(包括好友、朋友圈和收藏)、 + * 易信(包括好友、朋友圈)、人人网和QQ空间使用,否则可以不提供 + */ + public void setTitle(String title) { + shareParamsMap.put("title", title); + } + + /** titleUrl是标题的网络链接,仅在人人网和QQ空间使用,否则可以不提供 */ + public void setTitleUrl(String titleUrl) { + shareParamsMap.put("titleUrl", titleUrl); + } + + /** text是分享文本,所有平台都需要这个字段 */ + public void setText(String text) { + shareParamsMap.put("text", text); + } + + /** 获取text字段的值 */ + public String getText() { + return shareParamsMap.containsKey("text") ? String.valueOf(shareParamsMap.get("text")) : null; + } + + /** imagePath是本地的图片路径,除Linked-In外的所有平台都支持这个字段 */ + public void setImagePath(String imagePath) { + if(!TextUtils.isEmpty(imagePath)) + shareParamsMap.put("imagePath", imagePath); + } + + /** imageUrl是图片的网络路径,新浪微博、人人网、QQ空间和Linked-In支持此字段 */ + public void setImageUrl(String imageUrl) { + if (!TextUtils.isEmpty(imageUrl)) + shareParamsMap.put("imageUrl", imageUrl); + } + + /** url在微信(包括好友、朋友圈收藏)和易信(包括好友和朋友圈)中使用,否则可以不提供 */ + public void setUrl(String url) { + shareParamsMap.put("url", url); + } + + /** filePath是待分享应用程序的本地路劲,仅在微信(易信)好友和Dropbox中使用,否则可以不提供 */ + public void setFilePath(String filePath) { + shareParamsMap.put("filePath", filePath); + } + + /** comment是我对这条分享的评论,仅在人人网和QQ空间使用,否则可以不提供 */ + public void setComment(String comment) { + shareParamsMap.put("comment", comment); + } + + /** site是分享此内容的网站名称,仅在QQ空间使用,否则可以不提供 */ + public void setSite(String site) { + shareParamsMap.put("site", site); + } + + /** siteUrl是分享此内容的网站地址,仅在QQ空间使用,否则可以不提供 */ + public void setSiteUrl(String siteUrl) { + shareParamsMap.put("siteUrl", siteUrl); + } + + /** foursquare分享时的地方名 */ + public void setVenueName(String venueName) { + shareParamsMap.put("venueName", venueName); + } + + /** foursquare分享时的地方描述 */ + public void setVenueDescription(String venueDescription) { + shareParamsMap.put("venueDescription", venueDescription); + } + + /** 分享地纬度,新浪微博、腾讯微博和foursquare支持此字段 */ + public void setLatitude(float latitude) { + shareParamsMap.put("latitude", latitude); + } + + /** 分享地经度,新浪微博、腾讯微博和foursquare支持此字段 */ + public void setLongitude(float longitude) { + shareParamsMap.put("longitude", longitude); + } + + /** 是否直接分享 */ + public void setSilent(boolean silent) { + this.silent = silent; + } + + /** 设置编辑页的初始化选中平台 */ + public void setPlatform(String platform) { + shareParamsMap.put("platform", platform); + } + + /** 设置KakaoTalk的应用下载地址 */ + public void setInstallUrl(String installurl) { + shareParamsMap.put("installurl", installurl); + } + + /** 设置KakaoTalk的应用打开地址 */ + public void setExecuteUrl(String executeurl) { + shareParamsMap.put("executeurl", executeurl); + } + + /** 设置微信分享的音乐的地址 */ + public void setMusicUrl(String musicUrl) { + shareParamsMap.put("musicUrl", musicUrl); + } + + /** 设置自定义的外部回调 */ + public void setCallback(PlatformActionListener callback) { + this.callback = callback; + } + + /** 返回操作回调 */ + public PlatformActionListener getCallback() { + return callback; + } + + /** 设置用于分享过程中,根据不同平台自定义分享内容的回调 */ + public void setShareContentCustomizeCallback(ShareContentCustomizeCallback callback) { + customizeCallback = callback; + } + + /** 返回自定义分享内容的回调 */ + public ShareContentCustomizeCallback getShareContentCustomizeCallback() { + return customizeCallback; + } + + /** 设置自己图标和点击事件,可以重复调用添加多次 */ + public void setCustomerLogo(Bitmap enableLogo,Bitmap disableLogo, String label, OnClickListener ocListener) { + CustomerLogo cl = new CustomerLogo(); + cl.label = label; + cl.enableLogo = enableLogo; + cl.disableLogo = disableLogo; + cl.listener = ocListener; + customers.add(cl); + } + + /** 设置一个总开关,用于在分享前若需要授权,则禁用sso功能 */ + public void disableSSOWhenAuthorize() { + disableSSO = true; + } + + /** 设置编辑页面的显示模式为Dialog模式 */ + public void setDialogMode() { + dialogMode = true; + shareParamsMap.put("dialogMode", dialogMode); + } + + /** 添加一个隐藏的platform */ + public void addHiddenPlatform(String platform) { + hiddenPlatforms.put(platform, platform); + } + + /** 设置一个将被截图分享的View , surfaceView是截不了图片的*/ + public void setViewToShare(View viewToShare) { + try { + Bitmap bm = captureView(viewToShare, viewToShare.getWidth(), viewToShare.getHeight()); + shareParamsMap.put("viewToShare", bm); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + /** 腾讯微博分享多张图片 */ + public void setImageArray(String[] imageArray) { + shareParamsMap.put("imageArray", imageArray); + } + + public void setEditPageBackground(View bgView) { + this.bgView = bgView; + } + + public void setOnShareButtonClickListener(PlatformListFakeActivity.OnShareButtonClickListener onShareButtonClickListener) { + this.onShareButtonClickListener = onShareButtonClickListener; + } + + /** 循环执行分享 */ + public void share(HashMap> shareData) { + boolean started = false; + for (Entry> ent : shareData.entrySet()) { + Platform plat = ent.getKey(); + plat.SSOSetting(disableSSO); + String name = plat.getName(); + +// boolean isGooglePlus = "GooglePlus".equals(name); +// if (isGooglePlus && !plat.isValid()) { +// Message msg = new Message(); +// msg.what = MSG_TOAST; +// int resId = getStringRes(context, "google_plus_client_inavailable"); +// msg.obj = context.getString(resId); +// UIHandler.sendMessage(msg, this); +// continue; +// } + + boolean isKakaoTalk = "KakaoTalk".equals(name); + if (isKakaoTalk && !plat.isClientValid()) { + Message msg = new Message(); + msg.what = MSG_TOAST; + int resId = getStringRes(context, "kakaotalk_client_inavailable"); + msg.obj = context.getString(resId); + UIHandler.sendMessage(msg, this); + continue; + } + + boolean isKakaoStory = "KakaoStory".equals(name); + if (isKakaoStory && !plat.isClientValid()) { + Message msg = new Message(); + msg.what = MSG_TOAST; + int resId = getStringRes(context, "kakaostory_client_inavailable"); + msg.obj = context.getString(resId); + UIHandler.sendMessage(msg, this); + continue; + } + + boolean isLine = "Line".equals(name); + if (isLine && !plat.isClientValid()) { + Message msg = new Message(); + msg.what = MSG_TOAST; + int resId = getStringRes(context, "line_client_inavailable"); + msg.obj = context.getString(resId); + UIHandler.sendMessage(msg, this); + continue; + } + + boolean isWhatsApp = "WhatsApp".equals(name); + if (isWhatsApp && !plat.isClientValid()) { + Message msg = new Message(); + msg.what = MSG_TOAST; + int resId = getStringRes(context, "whatsapp_client_inavailable"); + msg.obj = context.getString(resId); + UIHandler.sendMessage(msg, this); + continue; + } + + boolean isPinterest = "Pinterest".equals(name); + if (isPinterest && !plat.isClientValid()) { + Message msg = new Message(); + msg.what = MSG_TOAST; + int resId = getStringRes(context, "pinterest_client_inavailable"); + msg.obj = context.getString(resId); + UIHandler.sendMessage(msg, this); + continue; + } + + if ("Instagram".equals(name) && !plat.isClientValid()) { + Message msg = new Message(); + msg.what = MSG_TOAST; + int resId = getStringRes(context, "instagram_client_inavailable"); + msg.obj = context.getString(resId); + UIHandler.sendMessage(msg, this); + continue; + } + + boolean isLaiwang = "Laiwang".equals(name); + boolean isLaiwangMoments = "LaiwangMoments".equals(name); + if(isLaiwang || isLaiwangMoments){ + if (!plat.isClientValid()) { + Message msg = new Message(); + msg.what = MSG_TOAST; + int resId = getStringRes(context, "laiwang_client_inavailable"); + msg.obj = context.getString(resId); + UIHandler.sendMessage(msg, this); + continue; + } + } + + boolean isYixin = "YixinMoments".equals(name) || "Yixin".equals(name); + if (isYixin && !plat.isClientValid()) { + Message msg = new Message(); + msg.what = MSG_TOAST; + int resId = getStringRes(context, "yixin_client_inavailable"); + msg.obj = context.getString(resId); + UIHandler.sendMessage(msg, this); + continue; + } + + HashMap data = ent.getValue(); + int shareType = Platform.SHARE_TEXT; + String imagePath = String.valueOf(data.get("imagePath")); + if (imagePath != null && (new File(imagePath)).exists()) { + shareType = Platform.SHARE_IMAGE; + if (imagePath.endsWith(".gif")) { + shareType = Platform.SHARE_EMOJI; + } else if (data.containsKey("url") && !TextUtils.isEmpty(data.get("url").toString())) { + shareType = Platform.SHARE_WEBPAGE; + if (data.containsKey("musicUrl") && !TextUtils.isEmpty(data.get("musicUrl").toString())) { + shareType = Platform.SHARE_MUSIC; + } + } + } else { + Bitmap viewToShare = (Bitmap) data.get("viewToShare"); + if (viewToShare != null && !viewToShare.isRecycled()) { + shareType = Platform.SHARE_IMAGE; + if (data.containsKey("url") && !TextUtils.isEmpty(data.get("url").toString())) { + shareType = Platform.SHARE_WEBPAGE; + if (data.containsKey("musicUrl") && !TextUtils.isEmpty(data.get("musicUrl").toString())) { + shareType = Platform.SHARE_MUSIC; + } + } + } else { + Object imageUrl = data.get("imageUrl"); + if (imageUrl != null && !TextUtils.isEmpty(String.valueOf(imageUrl))) { + shareType = Platform.SHARE_IMAGE; + if (String.valueOf(imageUrl).endsWith(".gif")) { + shareType = Platform.SHARE_EMOJI; + } else if (data.containsKey("url") && !TextUtils.isEmpty(data.get("url").toString())) { + shareType = Platform.SHARE_WEBPAGE; + if (data.containsKey("musicUrl") && !TextUtils.isEmpty(data.get("musicUrl").toString())) { + shareType = Platform.SHARE_MUSIC; + } + } + } + } + } + data.put("shareType", shareType); + + if (!started) { + started = true; +// if (this == callback) { + int resId = getStringRes(context, "sharing"); + if (resId > 0) { + showNotification(context.getString(resId)); + } +// } + } + plat.setPlatformActionListener(callback); + ShareCore shareCore = new ShareCore(); + shareCore.setShareContentCustomizeCallback(customizeCallback); + shareCore.share(plat, data); + } + } + + public void onComplete(Platform platform, int action, + HashMap res) { + Message msg = new Message(); + msg.what = MSG_ACTION_CCALLBACK; + msg.arg1 = 1; + msg.arg2 = action; + msg.obj = platform; + UIHandler.sendMessage(msg, this); + } + + public void onError(Platform platform, int action, Throwable t) { + t.printStackTrace(); + + Message msg = new Message(); + msg.what = MSG_ACTION_CCALLBACK; + msg.arg1 = 2; + msg.arg2 = action; + msg.obj = t; + UIHandler.sendMessage(msg, this); + + // 分享失败的统计 + ShareSDK.logDemoEvent(4, platform); + } + + public void onCancel(Platform platform, int action) { + Message msg = new Message(); + msg.what = MSG_ACTION_CCALLBACK; + msg.arg1 = 3; + msg.arg2 = action; + msg.obj = platform; + UIHandler.sendMessage(msg, this); + } + + public boolean handleMessage(Message msg) { + switch(msg.what) { + case MSG_TOAST: { + String text = String.valueOf(msg.obj); + Toast.makeText(context, text, Toast.LENGTH_SHORT).show(); + } + break; + case MSG_ACTION_CCALLBACK: { + switch (msg.arg1) { + case 1: { + // 成功 + int resId = getStringRes(context, "share_completed"); + if (resId > 0) { + showNotification(context.getString(resId)); + } + } + break; + case 2: { + // 失败 + String expName = msg.obj.getClass().getSimpleName(); + if ("WechatClientNotExistException".equals(expName) + || "WechatTimelineNotSupportedException".equals(expName) + || "WechatFavoriteNotSupportedException".equals(expName)) { + int resId = getStringRes(context, "wechat_client_inavailable"); + if (resId > 0) { + showNotification(context.getString(resId)); + } + } else if ("GooglePlusClientNotExistException".equals(expName)) { + int resId = getStringRes(context, "google_plus_client_inavailable"); + if (resId > 0) { + showNotification(context.getString(resId)); + } + } else if ("QQClientNotExistException".equals(expName)) { + int resId = getStringRes(context, "qq_client_inavailable"); + if (resId > 0) { + showNotification(context.getString(resId)); + } + } else if ("YixinClientNotExistException".equals(expName) + || "YixinTimelineNotSupportedException".equals(expName)) { + int resId = getStringRes(context, "yixin_client_inavailable"); + if (resId > 0) { + showNotification(context.getString(resId)); + } + } else if ("KakaoTalkClientNotExistException".equals(expName)) { + int resId = getStringRes(context, "kakaotalk_client_inavailable"); + if (resId > 0) { + showNotification(context.getString(resId)); + } + }else if ("KakaoStoryClientNotExistException".equals(expName)) { + int resId = getStringRes(context, "kakaostory_client_inavailable"); + if (resId > 0) { + showNotification(context.getString(resId)); + } + }else if("WhatsAppClientNotExistException".equals(expName)){ + int resId = getStringRes(context, "whatsapp_client_inavailable"); + if (resId > 0) { + showNotification(context.getString(resId)); + } + }else { + int resId = getStringRes(context, "share_failed"); + if (resId > 0) { + showNotification(context.getString(resId)); + } + } + } + break; + case 3: { + // 取消 + int resId = getStringRes(context, "share_canceled"); + if (resId > 0) { + showNotification(context.getString(resId)); + } + } + break; + } + } + break; + case MSG_CANCEL_NOTIFY: { + NotificationManager nm = (NotificationManager) msg.obj; + if (nm != null) { + nm.cancel(msg.arg1); + } + } + break; + } + return false; + } + + // 在状态栏提示分享操作 + private void showNotification(String text) { + Toast.makeText(context, text, Toast.LENGTH_SHORT).show(); + } + + /** 是否支持QQ,QZone授权登录后发微博 */ + public void setShareFromQQAuthSupport(boolean shareFromQQLogin) + { + shareParamsMap.put("isShareTencentWeibo", shareFromQQLogin); + } +} diff --git a/app/src/main/java/cn/sharesdk/onekeyshare/OnekeyShareTheme.java b/app/src/main/java/cn/sharesdk/onekeyshare/OnekeyShareTheme.java new file mode 100644 index 0000000000..248ada51a9 --- /dev/null +++ b/app/src/main/java/cn/sharesdk/onekeyshare/OnekeyShareTheme.java @@ -0,0 +1,3 @@ +package cn.sharesdk.onekeyshare; + +public enum OnekeyShareTheme {CLASSIC, SKYBLUE} diff --git a/app/src/main/java/cn/sharesdk/onekeyshare/PicViewer.java b/app/src/main/java/cn/sharesdk/onekeyshare/PicViewer.java new file mode 100644 index 0000000000..3d974eb94c --- /dev/null +++ b/app/src/main/java/cn/sharesdk/onekeyshare/PicViewer.java @@ -0,0 +1,221 @@ +/* + * 官网地站:http://www.mob.com + * 技术支持QQ: 4006852216 + * 官方微信:ShareSDK (如果发布新版本的话,我们将会第一时间通过微信将版本更新内容推送给您。如果使用过程中有任何问题,也可以通过微信与我们取得联系,我们将会在24小时内给予回复) + * + * Copyright (c) 2013年 mob.com. All rights reserved. + */ + + +package cn.sharesdk.onekeyshare; + +import android.annotation.SuppressLint; +import android.graphics.Bitmap; +import android.graphics.Matrix; +import android.graphics.PointF; +import android.graphics.RectF; +import android.util.DisplayMetrics; +import android.util.FloatMath; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.OnTouchListener; +import android.widget.ImageView; +import android.widget.ImageView.ScaleType; + +import com.mob.tools.FakeActivity; + +/** 查看编辑页面中图片的例子 */ +public class PicViewer extends FakeActivity implements OnTouchListener { + private ImageView ivViewer; + private Bitmap pic; + + Matrix matrix = new Matrix(); + Matrix savedMatrix = new Matrix(); + DisplayMetrics dm; + + /** 最小缩放比例*/ + float minScaleR = 1f; + /** 最大缩放比例*/ + static final float MAX_SCALE = 10f; + + /** 初始状态*/ + static final int NONE = 0; + /** 拖动*/ + static final int DRAG = 1; + /** 缩放*/ + static final int ZOOM = 2; + + /** 当前模式*/ + int mode = NONE; + + PointF prev = new PointF(); + PointF mid = new PointF(); + float dist = 1f; + + /** 设置图片用于浏览 */ + public void setImageBitmap(Bitmap pic) { + this.pic = pic; + if (ivViewer != null) { + ivViewer.setImageBitmap(pic); + } + } + + public void onCreate() { + ivViewer = new ImageView(activity); + ivViewer.setScaleType(ScaleType.MATRIX); + ivViewer.setBackgroundColor(0xc0000000); + ivViewer.setOnTouchListener(this); + if (pic != null && !pic.isRecycled()) { + ivViewer.setImageBitmap(pic); + } + dm = new DisplayMetrics(); + activity.getWindowManager().getDefaultDisplay().getMetrics(dm);// 获取分辨率 + minZoom(); + CheckView(); + ivViewer.setImageMatrix(matrix); + activity.setContentView(ivViewer); + + } + + + + /** + * 触屏监听 + */ + public boolean onTouch(View v, MotionEvent event) { + + switch (event.getAction() & MotionEvent.ACTION_MASK) { + // 主点按下 + case MotionEvent.ACTION_DOWN: + savedMatrix.set(matrix); + prev.set(event.getX(), event.getY()); + mode = DRAG; + break; + // 副点按下 + case MotionEvent.ACTION_POINTER_DOWN: + dist = spacing(event); + // 如果连续两点距离大于10,则判定为多点模式 + if (spacing(event) > 10f) { + savedMatrix.set(matrix); + midPoint(mid, event); + mode = ZOOM; + } + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_POINTER_UP: + mode = NONE; + break; + case MotionEvent.ACTION_MOVE: + if (mode == DRAG) { + matrix.set(savedMatrix); + matrix.postTranslate(event.getX() - prev.x, event.getY() + - prev.y); + } else if (mode == ZOOM) { + float newDist = spacing(event); + if (newDist > 10f) { + matrix.set(savedMatrix); + float tScale = newDist / dist; + matrix.postScale(tScale, tScale, mid.x, mid.y); + } + } + break; + } + ivViewer.setImageMatrix(matrix); + CheckView(); + return true; + } + + /** + * 限制最大最小缩放比例,自动居中 + */ + private void CheckView() { + float p[] = new float[9]; + matrix.getValues(p); + if (mode == ZOOM) { + if (p[0] < minScaleR) { +// Log.d("", "当前缩放级别:"+p[0]+",最小缩放级别:"+minScaleR); + matrix.setScale(minScaleR, minScaleR); + } + if (p[0] > MAX_SCALE) { +// Log.d("", "当前缩放级别:"+p[0]+",最大缩放级别:"+MAX_SCALE); + matrix.set(savedMatrix); + } + } + center(); + } + + /** + * 最小缩放比例,最大为100% + */ + private void minZoom() { + minScaleR = Math.min( + (float) dm.widthPixels / (float) pic.getWidth(), + (float) dm.heightPixels / (float) pic.getHeight()); + //以最小缩放比例显示 + matrix.setScale(minScaleR, minScaleR); + } + + private void center() { + center(true, true); + } + + /** + * 横向、纵向居中 + */ + protected void center(boolean horizontal, boolean vertical) { + + Matrix m = new Matrix(); + m.set(matrix); + RectF rect = new RectF(0, 0, pic.getWidth(), pic.getHeight()); + m.mapRect(rect); + + float height = rect.height(); + float width = rect.width(); + + float deltaX = 0, deltaY = 0; + + if (vertical) { + // 图片小于屏幕大小,则居中显示。大于屏幕,上方留空则往上移,下方留空则往下移 + int screenHeight = dm.heightPixels; + if (height < screenHeight) { + deltaY = (screenHeight - height) / 2 - rect.top; + } else if (rect.top > 0) { + deltaY = -rect.top; + } else if (rect.bottom < screenHeight) { + deltaY = ivViewer.getHeight() - rect.bottom; + } + } + + if (horizontal) { + int screenWidth = dm.widthPixels; + if (width < screenWidth) { + deltaX = (screenWidth - width) / 2 - rect.left; + } else if (rect.left > 0) { + deltaX = -rect.left; + } else if (rect.right < screenWidth) { + deltaX = ivViewer.getWidth() - rect.right; + } + } + matrix.postTranslate(deltaX, deltaY); + } + + /** + * 两点的距离 + */ + @SuppressLint("FloatMath") + private float spacing(MotionEvent event) { + float x = event.getX(0) - event.getX(1); + float y = event.getY(0) - event.getY(1); + return FloatMath.sqrt(x * x + y * y); + } + + /** + * 两点的中点 + */ + private void midPoint(PointF point, MotionEvent event) { + float x = event.getX(0) + event.getX(1); + float y = event.getY(0) + event.getY(1); + point.set(x / 2, y / 2); + } + +} diff --git a/app/src/main/java/cn/sharesdk/onekeyshare/PlatformListFakeActivity.java b/app/src/main/java/cn/sharesdk/onekeyshare/PlatformListFakeActivity.java new file mode 100644 index 0000000000..73e945dd15 --- /dev/null +++ b/app/src/main/java/cn/sharesdk/onekeyshare/PlatformListFakeActivity.java @@ -0,0 +1,213 @@ +package cn.sharesdk.onekeyshare; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import android.content.Context; +import android.content.Intent; +import android.view.KeyEvent; +import android.view.View; +import cn.sharesdk.framework.Platform; +import cn.sharesdk.framework.ShareSDK; + +import com.mob.tools.FakeActivity; + +public class PlatformListFakeActivity extends FakeActivity { + protected HashMap shareParamsMap; + protected boolean silent; + protected ArrayList customerLogos; + protected HashMap hiddenPlatforms; + private boolean canceled = false; + protected View backgroundView; + + protected OnShareButtonClickListener onShareButtonClickListener; + protected boolean dialogMode = false; + protected ThemeShareCallback themeShareCallback; + + public static interface OnShareButtonClickListener { + void onClick(View v, List checkPlatforms); + } + + public void onCreate() { + super.onCreate(); + + canceled = false; + + if(themeShareCallback == null) { + finish(); + } + } + + public boolean onKeyEvent(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + canceled = true; + } + return super.onKeyEvent(keyCode, event); + } + + protected void setCanceled(boolean canceled) { + this.canceled = canceled; + } + + public boolean onFinish() { + + // 取消分享菜单的统计 + if (canceled) { + ShareSDK.logDemoEvent(2, null); + } + + return super.onFinish(); + } + + @Override + public void show(Context context, Intent i) { + super.show(context, i); + } + + public HashMap getShareParamsMap() { + return shareParamsMap; + } + + public void setShareParamsMap(HashMap shareParamsMap) { + this.shareParamsMap = shareParamsMap; + } + + public boolean isSilent() { + return silent; + } + + public void setSilent(boolean silent) { + this.silent = silent; + } + + public ArrayList getCustomerLogos() { + return customerLogos; + } + + public void setCustomerLogos(ArrayList customerLogos) { + this.customerLogos = customerLogos; + } + + public HashMap getHiddenPlatforms() { + return hiddenPlatforms; + } + + public void setHiddenPlatforms(HashMap hiddenPlatforms) { + this.hiddenPlatforms = hiddenPlatforms; + } + + public View getBackgroundView() { + return backgroundView; + } + + public void setBackgroundView(View backgroundView) { + this.backgroundView = backgroundView; + } + + public OnShareButtonClickListener getOnShareButtonClickListener() { + return onShareButtonClickListener; + } + + public void setOnShareButtonClickListener(OnShareButtonClickListener onShareButtonClickListener) { + this.onShareButtonClickListener = onShareButtonClickListener; + } + + public boolean isDialogMode() { + return dialogMode; + } + + public void setDialogMode(boolean dialogMode) { + this.dialogMode = dialogMode; + } + + public ThemeShareCallback getThemeShareCallback() { + return themeShareCallback; + } + + public void setThemeShareCallback(ThemeShareCallback themeShareCallback) { + this.themeShareCallback = themeShareCallback; + } + + protected void onShareButtonClick(View v, List checkedPlatforms) { + + if(onShareButtonClickListener != null) { + onShareButtonClickListener.onClick(v, checkedPlatforms); + } + + HashMap> silentShareData = new HashMap>(); + final List supportEditPagePlatforms = new ArrayList(); + + Platform plat; + HashMap shareParam; + for(Object item : checkedPlatforms) { + if(item instanceof CustomerLogo){ + CustomerLogo customerLogo = (CustomerLogo)item; + customerLogo.listener.onClick(v); + continue; + } + + plat = (Platform)item; + String name = plat.getName(); + + // EditPage不支持微信平台、Google+、QQ分享、Pinterest、信息和邮件,总是执行直接分享 + if(silent || ShareCore.isDirectShare(plat)) { + shareParam = new HashMap(shareParamsMap); + shareParam.put("platform", name); + silentShareData.put(plat, shareParam); + } else { + supportEditPagePlatforms.add(plat); + } + } + if (silentShareData.size() > 0) { + themeShareCallback.doShare(silentShareData); + } + + // 跳转EditPage分享 + if(supportEditPagePlatforms.size() > 0) { + showEditPage(supportEditPagePlatforms); + } + + finish(); + } + + protected void showEditPage(List platforms) { + showEditPage(getContext(), platforms); + } + + public void showEditPage(Context context, Platform platform) { + ArrayList platforms = new ArrayList(1); + platforms.add(platform); + showEditPage(context, platforms); + } + + protected void showEditPage(Context context, List platforms) { + EditPageFakeActivity editPageFakeActivity; + String editPageClass = ((Object)this).getClass().getPackage().getName()+".EditPage"; + try { + editPageFakeActivity = (EditPageFakeActivity) Class.forName(editPageClass).newInstance(); + } catch (Exception e) { + e.printStackTrace(); + return; + } + + editPageFakeActivity.setBackgroundView(backgroundView); + editPageFakeActivity.setShareData(shareParamsMap); + editPageFakeActivity.setPlatforms(platforms); + if (dialogMode) { + editPageFakeActivity.setDialogMode(); + } + editPageFakeActivity.showForResult(context, null, new FakeActivity() { + public void onResult(HashMap data) { + if(data == null) + return; + if (data.containsKey("editRes")) { + @SuppressWarnings("unchecked") + HashMap> editRes + = (HashMap>) data.get("editRes"); + themeShareCallback.doShare(editRes); + } + } + }); + } +} diff --git a/app/src/main/java/cn/sharesdk/onekeyshare/ReflectableShareContentCustomizeCallback.java b/app/src/main/java/cn/sharesdk/onekeyshare/ReflectableShareContentCustomizeCallback.java new file mode 100644 index 0000000000..e56cc752c5 --- /dev/null +++ b/app/src/main/java/cn/sharesdk/onekeyshare/ReflectableShareContentCustomizeCallback.java @@ -0,0 +1,35 @@ +package cn.sharesdk.onekeyshare; + +import android.os.Handler.Callback; +import android.os.Message; +import cn.sharesdk.framework.Platform; +import cn.sharesdk.framework.Platform.ShareParams; + +import com.mob.tools.utils.UIHandler; + +/** + * 此类在Onekeyshare中并无用途,只是在Socialization中考虑到耦合度,需要通过反射的方式操作Onekeyshare, + *而原先的{@link ShareContentCustomizeCallback}无法完成此需求,故创建本类,以供外部设置操作回调。 + * + * @author Brook + */ +public class ReflectableShareContentCustomizeCallback implements ShareContentCustomizeCallback { + private int onShareWhat; + private Callback onShareCallback; + + public void setOnShareCallback(int what, Callback callback) { + onShareWhat = what; + onShareCallback = callback; + } + + @Override + public void onShare(Platform platform, ShareParams paramsToShare) { + if (onShareCallback != null) { + Message msg = new Message(); + msg.what = onShareWhat; + msg.obj = new Object[] {platform, paramsToShare}; + UIHandler.sendMessage(msg, onShareCallback); + } + } + +} diff --git a/app/src/main/java/cn/sharesdk/onekeyshare/Shake2Share.java b/app/src/main/java/cn/sharesdk/onekeyshare/Shake2Share.java new file mode 100644 index 0000000000..1889b51448 --- /dev/null +++ b/app/src/main/java/cn/sharesdk/onekeyshare/Shake2Share.java @@ -0,0 +1,138 @@ +/* + * 官网地站:http://www.mob.com + * 技术支持QQ: 4006852216 + * 官方微信:ShareSDK (如果发布新版本的话,我们将会第一时间通过微信将版本更新内容推送给您。如果使用过程中有任何问题,也可以通过微信与我们取得联系,我们将会在24小时内给予回复) + * + * Copyright (c) 2013年 mob.com. All rights reserved. + */ + +package cn.sharesdk.onekeyshare; + +import static com.mob.tools.utils.R.getBitmapRes; +import static com.mob.tools.utils.R.getStringRes; +import android.app.Activity; +import android.content.Context; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.util.FloatMath; +import android.view.Window; +import android.widget.ImageView; +import android.widget.ImageView.ScaleType; +import android.widget.Toast; + +import com.mob.tools.FakeActivity; + +/** 摇一摇启动分享的例子 */ +public class Shake2Share extends FakeActivity implements SensorEventListener { + // 检测的时间间隔 + private static final int UPDATE_INTERVAL = 100; + // 摇晃检测阈值,决定了对摇晃的敏感程度,越小越敏感 + private static final int SHAKE_THRESHOLD = 1500; + + private OnShakeListener listener; + private SensorManager mSensorManager; + private long mLastUpdateTime; + private float mLastX; + private float mLastY; + private float mLastZ; + private boolean shaken; + + public void setOnShakeListener(OnShakeListener listener) { + this.listener = listener; + } + + public void setActivity(Activity activity) { + super.setActivity(activity); + int resId = getBitmapRes(activity, "ssdk_oks_shake_to_share_back"); + if (resId > 0) { + activity.setTheme(android.R.style.Theme_Dialog); + activity.requestWindowFeature(Window.FEATURE_NO_TITLE); + Window win = activity.getWindow(); + win.setBackgroundDrawableResource(resId); + } + } + + public void onCreate() { + startSensor(); + + int resId = getBitmapRes(activity, "ssdk_oks_yaoyiyao"); + if (resId > 0) { + ImageView iv = new ImageView(activity); + iv.setScaleType(ScaleType.CENTER_INSIDE); + iv.setImageResource(resId); + activity.setContentView(iv); + } + + resId = getStringRes(activity, "shake2share"); + if (resId > 0) { + Toast.makeText(activity, resId, Toast.LENGTH_SHORT).show(); + } + } + + private void startSensor() { + mSensorManager = (SensorManager) activity.getSystemService(Context.SENSOR_SERVICE); + if (mSensorManager == null) { + throw new UnsupportedOperationException(); + } + Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + if (sensor == null) { + throw new UnsupportedOperationException(); + } + boolean success = mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME); + if (!success) { + throw new UnsupportedOperationException(); + } + } + + public void onDestroy() { + stopSensor(); + } + + private void stopSensor() { + if (mSensorManager != null) { + mSensorManager.unregisterListener(this); + mSensorManager = null; + } + } + + public void onSensorChanged(SensorEvent event) { + long currentTime = System.currentTimeMillis(); + long diffTime = currentTime - mLastUpdateTime; + if (diffTime > UPDATE_INTERVAL) { + if(mLastUpdateTime != 0) { + float x = event.values[0]; + float y = event.values[1]; + float z = event.values[2]; + float deltaX = x - mLastX; + float deltaY = y - mLastY; + float deltaZ = z - mLastZ; + float delta = FloatMath.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ) / diffTime * 10000; + if (delta > SHAKE_THRESHOLD) { + if (!shaken) { + shaken = true; + finish(); + } + + if (listener != null) { + listener.onShake(); + } + } + mLastX = x; + mLastY = y; + mLastZ = z; + } + mLastUpdateTime = currentTime; + } + } + + public void onAccuracyChanged(Sensor sensor, int accuracy) { + + } + + public static interface OnShakeListener { + public void onShake(); + } + +} diff --git a/app/src/main/java/cn/sharesdk/onekeyshare/ShareContentCustomizeCallback.java b/app/src/main/java/cn/sharesdk/onekeyshare/ShareContentCustomizeCallback.java new file mode 100644 index 0000000000..1498f8f59f --- /dev/null +++ b/app/src/main/java/cn/sharesdk/onekeyshare/ShareContentCustomizeCallback.java @@ -0,0 +1,10 @@ +package cn.sharesdk.onekeyshare; + +import cn.sharesdk.framework.Platform; +import cn.sharesdk.framework.Platform.ShareParams; + +public interface ShareContentCustomizeCallback { + + public void onShare(Platform platform, ShareParams paramsToShare); + +} diff --git a/app/src/main/java/cn/sharesdk/onekeyshare/ShareCore.java b/app/src/main/java/cn/sharesdk/onekeyshare/ShareCore.java new file mode 100644 index 0000000000..db1a3e0862 --- /dev/null +++ b/app/src/main/java/cn/sharesdk/onekeyshare/ShareCore.java @@ -0,0 +1,140 @@ +/* + * 官网地站:http://www.mob.com + * 技术支持QQ: 4006852216 + * 官方微信:ShareSDK (如果发布新版本的话,我们将会第一时间通过微信将版本更新内容推送给您。如果使用过程中有任何问题,也可以通过微信与我们取得联系,我们将会在24小时内给予回复) + * + * Copyright (c) 2013年 mob.com. All rights reserved. + */ + +package cn.sharesdk.onekeyshare; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.HashMap; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.ResolveInfo; +import android.graphics.Bitmap; +import android.graphics.Bitmap.CompressFormat; +import android.text.TextUtils; +import cn.sharesdk.framework.CustomPlatform; +import cn.sharesdk.framework.Platform; +import cn.sharesdk.framework.Platform.ShareParams; +import cn.sharesdk.framework.ShareSDK; + +import com.mob.tools.utils.R; + +/** + * ShareCore是快捷分享的实际出口,此类使用了反射的方式,配合传递进来的HashMap, + *构造{@link ShareParams}对象,并执行分享,使快捷分享不再需要考虑目标平台 + */ +public class ShareCore { + private ShareContentCustomizeCallback customizeCallback; + + /** 设置用于分享过程中,根据不同平台自定义分享内容的回调 */ + public void setShareContentCustomizeCallback(ShareContentCustomizeCallback callback) { + customizeCallback = callback; + } + + /** + * 向指定平台分享内容 + *

+ * 注意:
+ * 参数data的键值需要严格按照{@link ShareParams}不同子类具体字段来命名, + *否则无法反射此字段,也无法设置其值。 + */ + public boolean share(Platform plat, HashMap data) { + if (plat == null || data == null) { + return false; + } + + try { + String imagePath = (String) data.get("imagePath"); + Bitmap viewToShare = (Bitmap) data.get("viewToShare"); + if (TextUtils.isEmpty(imagePath) && viewToShare != null && !viewToShare.isRecycled()) { + String path = R.getCachePath(plat.getContext(), "screenshot"); + File ss = new File(path, String.valueOf(System.currentTimeMillis()) + ".jpg"); + FileOutputStream fos = new FileOutputStream(ss); + viewToShare.compress(CompressFormat.JPEG, 100, fos); + fos.flush(); + fos.close(); + data.put("imagePath", ss.getAbsolutePath()); + } + } catch (Throwable t) { + t.printStackTrace(); + return false; + } + + ShareParams sp = new ShareParams(data); + if (customizeCallback != null) { + customizeCallback.onShare(plat, sp); + } + plat.share(sp); + return true; + } + + /** 判断指定平台是否使用客户端分享 */ + public static boolean isUseClientToShare(String platform) { + if ("Wechat".equals(platform) || "WechatMoments".equals(platform) + || "WechatFavorite".equals(platform) || "ShortMessage".equals(platform) + || "Email".equals(platform) || "GooglePlus".equals(platform) + || "QQ".equals(platform) || "Pinterest".equals(platform) + || "Instagram".equals(platform) || "Yixin".equals(platform) + || "YixinMoments".equals(platform) || "QZone".equals(platform) + || "Mingdao".equals(platform) || "Line".equals(platform) + || "KakaoStory".equals(platform) || "KakaoTalk".equals(platform) + || "Bluetooth".equals(platform) || "WhatsApp".equals(platform) + || "BaiduTieba".equals(platform) || "Laiwang".equals(platform) + || "LaiwangMoments".equals(platform) + ) { + return true; + } else if ("Evernote".equals(platform)) { + Platform plat = ShareSDK.getPlatform(platform); + if ("true".equals(plat.getDevinfo("ShareByAppClient"))) { + return true; + } + } else if ("SinaWeibo".equals(platform)) { + Platform plat = ShareSDK.getPlatform(platform); + if ("true".equals(plat.getDevinfo("ShareByAppClient"))) { + Intent test = new Intent(Intent.ACTION_SEND); + test.setPackage("com.sina.weibo"); + test.setType("image/*"); + ResolveInfo ri = plat.getContext().getPackageManager().resolveActivity(test, 0); + return (ri != null); + } + } + + return false; + } + + /** 判断指定平台是否可以用来授权 */ + public static boolean canAuthorize(Context context, String platform) { + return !("WechatMoments".equals(platform) + || "WechatFavorite".equals(platform) || "ShortMessage".equals(platform) + || "Email".equals(platform) + || "Pinterest".equals(platform) || "Yixin".equals(platform) + || "YixinMoments".equals(platform) || "Line".equals(platform) + || "Bluetooth".equals(platform) || "WhatsApp".equals(platform) + || "BaiduTieba".equals(platform)) || "Laiwang".equals(platform) + || "LaiwangMoments".equals(platform); + } + + + /** 判断指定平台是否可以用来获取用户资料 */ + public static boolean canGetUserInfo(Context context, String platform) { + return !("WechatMoments".equals(platform) + || "WechatFavorite".equals(platform) || "ShortMessage".equals(platform) + || "Email".equals(platform) + || "Pinterest".equals(platform) || "Yixin".equals(platform) + || "YixinMoments".equals(platform) || "Line".equals(platform) + || "Bluetooth".equals(platform) || "WhatsApp".equals(platform) + || "Pocket".equals(platform) || "BaiduTieba".equals(platform) + || "Laiwang".equals(platform) || "LaiwangMoments".equals(platform)); + } + + /** 判断是否直接分享 */ + public static boolean isDirectShare(Platform platform) { + return platform instanceof CustomPlatform || isUseClientToShare(platform.getName()); + } +} diff --git a/app/src/main/java/cn/sharesdk/onekeyshare/ThemeShareCallback.java b/app/src/main/java/cn/sharesdk/onekeyshare/ThemeShareCallback.java new file mode 100644 index 0000000000..c84267833c --- /dev/null +++ b/app/src/main/java/cn/sharesdk/onekeyshare/ThemeShareCallback.java @@ -0,0 +1,17 @@ +/* + * 官网地站:http://www.mob.com + * 技术支持QQ: 4006852216 + * 官方微信:ShareSDK (如果发布新版本的话,我们将会第一时间通过微信将版本更新内容推送给您。如果使用过程中有任何问题,也可以通过微信与我们取得联系,我们将会在24小时内给予回复) + * + * Copyright (c) 2013年 mob.com. All rights reserved. + */ + +package cn.sharesdk.onekeyshare; + +import java.util.HashMap; + +import cn.sharesdk.framework.Platform; + +public interface ThemeShareCallback { + public void doShare(HashMap> shareData); +} diff --git a/app/src/main/java/cn/sharesdk/onekeyshare/theme/classic/EditPage.java b/app/src/main/java/cn/sharesdk/onekeyshare/theme/classic/EditPage.java new file mode 100644 index 0000000000..58af6a1f96 --- /dev/null +++ b/app/src/main/java/cn/sharesdk/onekeyshare/theme/classic/EditPage.java @@ -0,0 +1,724 @@ +/* + * Offical Website:http://www.mob.com + * Support QQ: 4006852216 + * Offical Wechat Account:ShareSDK (We will inform you our updated news at the first time by Wechat, if we release a new version. If you get any problem, you can also contact us with Wechat, we will reply you within 24 hours.) + * + * Copyright (c) 2013 mob.com. All rights reserved. + */ + +package cn.sharesdk.onekeyshare.theme.classic; + +import static com.mob.tools.utils.BitmapHelper.blur; +import static com.mob.tools.utils.BitmapHelper.captureView; +import static com.mob.tools.utils.R.dipToPx; +import static com.mob.tools.utils.R.getBitmapRes; +import static com.mob.tools.utils.R.getScreenWidth; +import static com.mob.tools.utils.R.getStringRes; + +import java.util.ArrayList; +import java.util.HashMap; + +import android.app.Activity; +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Typeface; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; +import android.os.Handler.Callback; +import android.os.Message; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.Window; +import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.FrameLayout; +import android.widget.HorizontalScrollView; +import android.widget.ImageView; +import android.widget.ImageView.ScaleType; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; +import cn.sharesdk.framework.CustomPlatform; +import cn.sharesdk.framework.Platform; +import cn.sharesdk.framework.ShareSDK; +import cn.sharesdk.framework.TitleLayout; +import cn.sharesdk.onekeyshare.EditPageFakeActivity; +import cn.sharesdk.onekeyshare.PicViewer; +import cn.sharesdk.onekeyshare.ShareCore; + +import com.mob.tools.utils.UIHandler; + +/** + * Photo-text Sharing will be handling in this page + *

+ * note: + * wechat, yixin, qzone, etc. are shared in their clients, not in this page + */ +public class EditPage extends EditPageFakeActivity implements OnClickListener, TextWatcher { + private static final int MAX_TEXT_COUNT = 140; + private static final int DIM_COLOR = 0x7f323232; + private RelativeLayout rlPage; + private TitleLayout llTitle; + private LinearLayout llBody; + private RelativeLayout rlThumb; + // share content editor + private EditText etContent; + // Words counter + private TextView tvCounter; + // the pin + private ImageView ivPin; + // the image info of share image + private ImageInfo imgInfo; + // shared image container + private ImageView ivImage; + private ProgressBar progressBar; + private Bitmap image; + private LinearLayout llPlat; +// private LinearLayout llAt; + private View[] views; + private Drawable background; + + private Platform[] platformList; + + public void setActivity(Activity activity) { + super.setActivity(activity); + Window win = activity.getWindow(); + int orientation = activity.getResources().getConfiguration().orientation; + if (orientation == Configuration.ORIENTATION_LANDSCAPE) { + win.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN + | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); + } else { + win.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE + | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); + } + } + + public void onCreate() { + if (shareParamMap == null || platforms == null || platforms.size() < 1) { + finish(); + return; + } + + genBackground(); + activity.setContentView(getPageView()); + onTextChanged(etContent.getText(), 0, etContent.length(), 0); + showThumb(); + + // requests platform list and remove platforms share in their clients + new Thread(){ + public void run() { + try { + platformList = ShareSDK.getPlatformList(); + if (platformList == null) { + return; + } + + ArrayList list = new ArrayList(); + for (Platform plat : platformList) { + String name = plat.getName(); + if ((plat instanceof CustomPlatform) + || ShareCore.isUseClientToShare(name)) { + continue; + } + list.add(plat); + } + platformList = new Platform[list.size()]; + for (int i = 0; i < platformList.length; i++) { + platformList[i] = list.get(i); + } + + UIHandler.sendEmptyMessage(1, new Callback() { + public boolean handleMessage(Message msg) { + afterPlatformListGot(); + return false; + } + }); + } catch (Throwable t) { + t.printStackTrace(); + } + } + }.start(); + } + + private RelativeLayout getPageView() { + rlPage = new RelativeLayout(getContext()); + rlPage.setBackgroundDrawable(background); + if (dialogMode) { + RelativeLayout rlDialog = new RelativeLayout(getContext()); + rlDialog.setBackgroundColor(0xc0323232); + int dp_8 = dipToPx(getContext(), 8); + int width = getScreenWidth(getContext()) - dp_8 * 2; + RelativeLayout.LayoutParams lpDialog = new RelativeLayout.LayoutParams( + width, LayoutParams.WRAP_CONTENT); + lpDialog.topMargin = dp_8; + lpDialog.bottomMargin = dp_8; + lpDialog.addRule(RelativeLayout.CENTER_IN_PARENT); + rlDialog.setLayoutParams(lpDialog); + rlPage.addView(rlDialog); + + rlDialog.addView(getPageTitle()); + rlDialog.addView(getPageBody()); + rlDialog.addView(getImagePin()); + } else { + rlPage.addView(getPageTitle()); + rlPage.addView(getPageBody()); + rlPage.addView(getImagePin()); + } + return rlPage; + } + + // title bar + private TitleLayout getPageTitle() { + llTitle = new TitleLayout(getContext()); + llTitle.setId(1); +// int resId = getBitmapRes(activity, "title_back"); +// if (resId > 0) { +// llTitle.setBackgroundResource(resId); +// } + llTitle.getBtnBack().setOnClickListener(this); + int resId = getStringRes(activity, "multi_share"); + if (resId > 0) { + llTitle.getTvTitle().setText(resId); + } + llTitle.getBtnRight().setVisibility(View.VISIBLE); + resId = getStringRes(activity, "share"); + if (resId > 0) { + llTitle.getBtnRight().setText(resId); + } + llTitle.getBtnRight().setOnClickListener(this); + RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT); + lp.addRule(RelativeLayout.ALIGN_PARENT_TOP); + lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + llTitle.setLayoutParams(lp); + + return llTitle; + } + + // page body + private LinearLayout getPageBody() { + llBody = new LinearLayout(getContext()); + llBody.setId(2); + int resId = getBitmapRes(activity, "edittext_back"); + if (resId > 0) { + llBody.setBackgroundResource(resId); + } + llBody.setOrientation(LinearLayout.VERTICAL); + RelativeLayout.LayoutParams lpBody = new RelativeLayout.LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + lpBody.addRule(RelativeLayout.ALIGN_LEFT, llTitle.getId()); + lpBody.addRule(RelativeLayout.BELOW, llTitle.getId()); + lpBody.addRule(RelativeLayout.ALIGN_RIGHT, llTitle.getId()); + if (!dialogMode) { + lpBody.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); + } + int dp_3 = dipToPx(getContext(), 3); + lpBody.setMargins(dp_3, dp_3, dp_3, dp_3); + llBody.setLayoutParams(lpBody); + + llBody.addView(getMainBody()); + llBody.addView(getSep()); + llBody.addView(getPlatformList()); + + return llBody; + } + + private LinearLayout getMainBody() { + LinearLayout llMainBody = new LinearLayout(getContext()); + llMainBody.setOrientation(LinearLayout.VERTICAL); + LayoutParams lpMain = new LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + lpMain.weight = 1; + int dp_4 = dipToPx(getContext(), 4); + lpMain.setMargins(dp_4, dp_4, dp_4, dp_4); + llMainBody.setLayoutParams(lpMain); + + LinearLayout llContent = new LinearLayout(getContext()); + LayoutParams lpContent = new LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + lpContent.weight = 1; + llMainBody.addView(llContent, lpContent); + + // share content editor + etContent = new EditText(getContext()); + etContent.setGravity(Gravity.LEFT | Gravity.TOP); + etContent.setBackgroundDrawable(null); + etContent.setText(String.valueOf(shareParamMap.get("text"))); + etContent.addTextChangedListener(this); + LayoutParams lpEt = new LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + lpEt.weight = 1; + etContent.setLayoutParams(lpEt); + llContent.addView(etContent); + + llContent.addView(getThumbView()); + llMainBody.addView(getBodyBottom()); + + return llMainBody; + } + + // shared image container + private RelativeLayout getThumbView() { + rlThumb = new RelativeLayout(getContext()); + rlThumb.setId(1); + int dp_82 = dipToPx(getContext(), 82); + int dp_98 = dipToPx(getContext(), 98); + LayoutParams lpThumb + = new LayoutParams(dp_82, dp_98); + rlThumb.setLayoutParams(lpThumb); + + ivImage = new ImageView(getContext()); + int resId = getBitmapRes(activity, "btn_back_nor"); + if (resId > 0) { + ivImage.setBackgroundResource(resId); + } + ivImage.setScaleType(ScaleType.CENTER_INSIDE); + ivImage.setImageBitmap(image); + + int dp_4 = dipToPx(getContext(), 4); + ivImage.setPadding(dp_4, dp_4, dp_4, dp_4); + int dp_74 = dipToPx(getContext(), 74); + RelativeLayout.LayoutParams lpImage + = new RelativeLayout.LayoutParams(dp_74, dp_74); + int dp_16 = dipToPx(getContext(), 16); + int dp_8 = dipToPx(getContext(), 8); + lpImage.setMargins(0, dp_16, dp_8, 0); + ivImage.setLayoutParams(lpImage); + ivImage.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + if (image != null && !image.isRecycled()) { + PicViewer pv = new PicViewer(); + pv.setImageBitmap(image); + pv.show(activity, null); + } + } + }); + rlThumb.addView(ivImage); + + int dp_24 = dipToPx(getContext(), 24); + progressBar = new ProgressBar(getContext()); + progressBar.setPadding(dp_24, dp_24, dp_24, dp_24); + RelativeLayout.LayoutParams pb + = new RelativeLayout.LayoutParams(dp_74, dp_74); + pb.setMargins(0, dp_16, dp_8, 0); + progressBar.setLayoutParams(pb); + rlThumb.addView(progressBar); + + Button btn = new Button(getContext()); + btn.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + // remove the photo to share + rlThumb.setVisibility(View.GONE); + ivPin.setVisibility(View.GONE); + removeImage(imgInfo); + } + }); + resId = getBitmapRes(activity, "img_cancel"); + if (resId > 0) { + btn.setBackgroundResource(resId); + } + int dp_20 = dipToPx(getContext(), 20); + RelativeLayout.LayoutParams lpBtn + = new RelativeLayout.LayoutParams(dp_20, dp_20); + lpBtn.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + lpBtn.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); + btn.setLayoutParams(lpBtn); + rlThumb.addView(btn); + + if(!haveImage()){ + rlThumb.setVisibility(View.GONE); + } + return rlThumb; + } + + private void showThumb() { + initImageList(new ImageListResultsCallback() { + @Override + public void onFinish(ArrayList results) { + if(results == null || results.size() == 0) + return; + //TODO: 支持多图 + imgInfo = results.get(0); + image = imgInfo.bitmap; + rlThumb.setVisibility(View.VISIBLE); + ivPin.setVisibility(View.VISIBLE); + progressBar.setVisibility(View.GONE); + ivImage.setImageBitmap(image); + } + }); + } + + private LinearLayout getBodyBottom() { + LinearLayout llBottom = new LinearLayout(getContext()); + llBottom.setLayoutParams(new LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); + + LinearLayout line = getAtLine(platforms.get(0).getName()); + if (line != null) { + llBottom.addView(line); + } + + // Words counter + tvCounter = new TextView(getContext()); + tvCounter.setText(String.valueOf(MAX_TEXT_COUNT)); + tvCounter.setTextColor(0xffcfcfcf); + tvCounter.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + tvCounter.setTypeface(Typeface.DEFAULT_BOLD); + LayoutParams lpCounter = new LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + lpCounter.gravity = Gravity.CENTER_VERTICAL; + tvCounter.setLayoutParams(lpCounter); + llBottom.addView(tvCounter); + + return llBottom; + } + + // if platform selected form platform gridview is SinaWeibo, + // TencentWeibo, Facebook, or Twitter, there will be a button + // in the left-bottom of the page, which provides At-friends function + private LinearLayout getAtLine(String platform) { + if (!isShowAtUserLayout(platform)) { + return null; + } + LinearLayout llAt = new LinearLayout(getContext()); + LayoutParams lpAt = new LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + lpAt.rightMargin = dipToPx(getContext(), 4); + lpAt.gravity = Gravity.LEFT | Gravity.BOTTOM; + lpAt.weight = 1; + llAt.setLayoutParams(lpAt); + llAt.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + FollowListPage subPage = new FollowListPage(); + subPage.setPlatform(platforms.get(0)); + subPage.showForResult(activity, null, EditPage.this); + } + }); + + TextView tvAt = new TextView(getContext()); + int resId = getBitmapRes(activity, "btn_back_nor"); + if (resId > 0) { + tvAt.setBackgroundResource(resId); + } + int dp_32 = dipToPx(getContext(), 32); + tvAt.setLayoutParams(new LayoutParams(dp_32, dp_32)); + tvAt.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + tvAt.setText(getAtUserButtonText(platform)); + int dp_2 = dipToPx(getContext(), 2); + tvAt.setPadding(0, 0, 0, dp_2); + tvAt.setTypeface(Typeface.DEFAULT_BOLD); + tvAt.setTextColor(0xff000000); + tvAt.setGravity(Gravity.CENTER); + llAt.addView(tvAt); + + TextView tvName = new TextView(getContext()); + tvName.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + tvName.setTextColor(0xff000000); + resId = getStringRes(activity, "list_friends"); + String text = getContext().getString(resId, getName(platform)); + tvName.setText(text); + LayoutParams lpName = new LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + lpName.gravity = Gravity.CENTER_VERTICAL; + tvName.setLayoutParams(lpName); + llAt.addView(tvName); + + return llAt; + } + + private View getSep() { + View vSep = new View(getContext()); + vSep.setBackgroundColor(0xff000000); + int dp_1 = dipToPx(getContext(), 1); + LayoutParams lpSep = new LayoutParams( + LayoutParams.MATCH_PARENT, dp_1); + vSep.setLayoutParams(lpSep); + return vSep; + } + + // platform logos + private LinearLayout getPlatformList() { + LinearLayout llToolBar = new LinearLayout(getContext()); + LayoutParams lpTb = new LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + llToolBar.setLayoutParams(lpTb); + + TextView tvShareTo = new TextView(getContext()); + int resId = getStringRes(activity, "share_to"); + if (resId > 0) { + tvShareTo.setText(resId); + } + tvShareTo.setTextColor(0xffcfcfcf); + tvShareTo.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + int dp_9 = dipToPx(getContext(), 9); + LayoutParams lpShareTo = new LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + lpShareTo.gravity = Gravity.CENTER_VERTICAL; + lpShareTo.setMargins(dp_9, 0, 0, 0); + tvShareTo.setLayoutParams(lpShareTo); + llToolBar.addView(tvShareTo); + + HorizontalScrollView sv = new HorizontalScrollView(getContext()); + sv.setHorizontalScrollBarEnabled(false); + sv.setHorizontalFadingEdgeEnabled(false); + LayoutParams lpSv = new LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + lpSv.setMargins(dp_9, dp_9, dp_9, dp_9); + sv.setLayoutParams(lpSv); + llToolBar.addView(sv); + + llPlat = new LinearLayout(getContext()); + llPlat.setLayoutParams(new HorizontalScrollView.LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT)); + sv.addView(llPlat); + + return llToolBar; + } + + // the pin + private ImageView getImagePin() { + ivPin = new ImageView(getContext()); + int resId = getBitmapRes(activity, "pin"); + if (resId > 0) { + ivPin.setImageResource(resId); + } + int dp_80 = dipToPx(getContext(), 80); + int dp_36 = dipToPx(getContext(), 36); + RelativeLayout.LayoutParams lp + = new RelativeLayout.LayoutParams(dp_80, dp_36); + lp.topMargin = dipToPx(getContext(), 6); + lp.addRule(RelativeLayout.ALIGN_TOP, llBody.getId()); + lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + ivPin.setLayoutParams(lp); + ivPin.setVisibility(View.GONE); + + return ivPin; + } + + private void genBackground() { + background = new ColorDrawable(DIM_COLOR); + if (backgroundView != null) { + try { + Bitmap bgBm = captureView(backgroundView, backgroundView.getWidth(), backgroundView.getHeight()); + bgBm = blur(bgBm, 20, 8); + BitmapDrawable blurBm = new BitmapDrawable(activity.getResources(), bgBm); + background = new LayerDrawable(new Drawable[] {blurBm, background}); + } catch (Throwable e) { + e.printStackTrace(); + } + } + } + + private String getName(String platform) { + if (platform == null) { + return ""; + } + + int resId = getStringRes(getContext(), platform.toLowerCase()); + return getContext().getString(resId); + } + + public void onClick(View v) { + if (v.equals(llTitle.getBtnBack())) { + Platform plat = null; + for (int i = 0; i < views.length; i++) { + if (views[i].getVisibility() == View.INVISIBLE) { + plat = platformList[i]; + break; + } + } + + // a statistics of Cancel-sharing + if (plat != null) { + ShareSDK.logDemoEvent(5, plat); + } + finish(); + return; + } + + if (v.equals(llTitle.getBtnRight())) { + String text = etContent.getText().toString(); + shareParamMap.put("text", text); + + platforms.clear(); + for (int i = 0; i < views.length; i++) { + if (views[i].getVisibility() != View.VISIBLE) { + platforms.add(platformList[i]); + } + } + + if (platforms.size() > 0) { + setResultAndFinish(); + } else { + int resId = getStringRes(activity, "select_one_plat_at_least"); + if (resId > 0) { + Toast.makeText(getContext(), resId, Toast.LENGTH_SHORT).show(); + } + } + return; + } + + if (v instanceof FrameLayout) { + ((FrameLayout) v).getChildAt(1).performClick(); + return; + } + + if (v.getVisibility() == View.INVISIBLE) { + v.setVisibility(View.VISIBLE); + } else { + v.setVisibility(View.INVISIBLE); + } + } + + /** display platform list */ + public void afterPlatformListGot() { + int size = platformList == null ? 0 : platformList.length; + views = new View[size]; + + final int dp_24 = dipToPx(getContext(), 24); + LayoutParams lpItem = new LayoutParams(dp_24, dp_24); + final int dp_9 = dipToPx(getContext(), 9); + lpItem.setMargins(0, 0, dp_9, 0); + FrameLayout.LayoutParams lpMask = new FrameLayout.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + lpMask.gravity = Gravity.LEFT | Gravity.TOP; + int selection = 0; + for (int i = 0; i < size; i++) { + FrameLayout fl = new FrameLayout(getContext()); + fl.setLayoutParams(lpItem); + if (i >= size - 1) { + fl.setLayoutParams(new LayoutParams(dp_24, dp_24)); + } + llPlat.addView(fl); + fl.setOnClickListener(this); + + ImageView iv = new ImageView(getContext()); + iv.setScaleType(ScaleType.CENTER_INSIDE); + iv.setImageBitmap(getPlatLogo(platformList[i])); + iv.setLayoutParams(new FrameLayout.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + fl.addView(iv); + + views[i] = new View(getContext()); + views[i].setBackgroundColor(0xcfffffff); + views[i].setOnClickListener(this); + String platformName = platformList[i].getName(); + for(Platform plat : platforms) { + if(platformName.equals(plat.getName())) { + views[i].setVisibility(View.INVISIBLE); + selection = i; + } + } + views[i].setLayoutParams(lpMask); + fl.addView(views[i]); + } + + final int postSel = selection; + UIHandler.sendEmptyMessageDelayed(0, 333, new Callback() { + public boolean handleMessage(Message msg) { + HorizontalScrollView hsv = (HorizontalScrollView)llPlat.getParent(); + hsv.scrollTo(postSel * (dp_24 + dp_9), 0); + return false; + } + }); + } + + private Bitmap getPlatLogo(Platform plat) { + if (plat == null) { + return null; + } + + String name = plat.getName(); + if (name == null) { + return null; + } + + String resName = "logo_" + plat.getName(); + int resId = getBitmapRes(activity, resName.toLowerCase()); + if(resId > 0) { + return BitmapFactory.decodeResource(activity.getResources(), resId); + } + return null; + } + + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + + } + + public void onTextChanged(CharSequence s, int start, int before, int count) { + int remain = MAX_TEXT_COUNT - etContent.length(); + tvCounter.setText(String.valueOf(remain)); + tvCounter.setTextColor(remain > 0 ? 0xffcfcfcf : 0xffff0000); + } + + public void afterTextChanged(Editable s) { + + } + + public void onResult(HashMap data) { + String atText = getJoinSelectedUser(data); + if(atText != null) { + etContent.append(atText); + } + } + + private void hideSoftInput() { + try { + InputMethodManager imm = (InputMethodManager) activity.getSystemService( + Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(etContent.getWindowToken(), 0); + } catch (Throwable t) { + t.printStackTrace(); + } + } + + public boolean onFinish() { + hideSoftInput(); + return super.onFinish(); + } + + public void onConfigurationChanged(Configuration newConfig) { + int orientation = activity.getResources().getConfiguration().orientation; + if (orientation == Configuration.ORIENTATION_LANDSCAPE) { + hideSoftInput(); + Window win = activity.getWindow(); + win.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN + | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); + rlPage.setBackgroundColor(DIM_COLOR); + rlPage.postDelayed(new Runnable() { + public void run() { + genBackground(); + rlPage.setBackgroundDrawable(background); + } + }, 1000); + } else { + hideSoftInput(); + Window win = activity.getWindow(); + win.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE + | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); + rlPage.setBackgroundColor(DIM_COLOR); + rlPage.postDelayed(new Runnable() { + public void run() { + genBackground(); + rlPage.setBackgroundDrawable(background); + } + }, 1000); + } + } + +} diff --git a/app/src/main/java/cn/sharesdk/onekeyshare/theme/classic/FollowListPage.java b/app/src/main/java/cn/sharesdk/onekeyshare/theme/classic/FollowListPage.java new file mode 100644 index 0000000000..9e0a42398e --- /dev/null +++ b/app/src/main/java/cn/sharesdk/onekeyshare/theme/classic/FollowListPage.java @@ -0,0 +1,458 @@ +/* + * 官网地站:http://www.mob.com + * 技术支持QQ: 4006852216 + * 官方微信:ShareSDK (如果发布新版本的话,我们将会第一时间通过微信将版本更新内容推送给您。如果使用过程中有任何问题,也可以通过微信与我们取得联系,我们将会在24小时内给予回复) + * + * Copyright (c) 2013年 mob.com. All rights reserved. + */ + +package cn.sharesdk.onekeyshare.theme.classic; + +import static com.mob.tools.utils.R.dipToPx; +import static com.mob.tools.utils.R.getBitmapRes; +import static com.mob.tools.utils.R.getStringRes; + +import java.util.ArrayList; +import java.util.HashMap; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.os.Handler.Callback; +import android.os.Message; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.ProgressBar; +import android.widget.TextView; +import cn.sharesdk.framework.Platform; +import cn.sharesdk.framework.PlatformActionListener; +import cn.sharesdk.framework.TitleLayout; +import cn.sharesdk.onekeyshare.FollowerListFakeActivity; + +import com.mob.tools.gui.AsyncImageView; +import com.mob.tools.gui.BitmapProcessor; +import com.mob.tools.gui.PullToRefreshListAdapter; +import com.mob.tools.gui.PullToRefreshView; +import com.mob.tools.utils.UIHandler; + +/** 获取好友或关注列表 */ +public class FollowListPage extends FollowerListFakeActivity implements OnClickListener, OnItemClickListener { + private TitleLayout llTitle; + private FollowAdapter adapter; + private int lastPosition = -1; + + public void onCreate() { + LinearLayout llPage = new LinearLayout(getContext()); + llPage.setBackgroundColor(0xfff5f5f5); + llPage.setOrientation(LinearLayout.VERTICAL); + activity.setContentView(llPage); + + // 标题栏 + llTitle = new TitleLayout(getContext()); + int resId = getBitmapRes(getContext(), "title_back"); + if (resId > 0) { + llTitle.setBackgroundResource(resId); + } + llTitle.getBtnBack().setOnClickListener(this); + resId = getStringRes(getContext(), "multi_share"); + if (resId > 0) { + llTitle.getTvTitle().setText(resId); + } + llTitle.getBtnRight().setVisibility(View.VISIBLE); + resId = getStringRes(getContext(), "finish"); + if (resId > 0) { + llTitle.getBtnRight().setText(resId); + } + llTitle.getBtnRight().setOnClickListener(this); + llTitle.setLayoutParams(new LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); + llPage.addView(llTitle); + + FrameLayout flPage = new FrameLayout(getContext()); + LayoutParams lpFl = new LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + lpFl.weight = 1; + flPage.setLayoutParams(lpFl); + llPage.addView(flPage); + + // 关注(或朋友)列表 + PullToRefreshView followList = new PullToRefreshView(getContext()); + FrameLayout.LayoutParams lpLv = new FrameLayout.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + followList.setLayoutParams(lpLv); + flPage.addView(followList); + adapter = new FollowAdapter(followList); + adapter.setPlatform(platform); + followList.setAdapter(adapter); + adapter.getListView().setOnItemClickListener(this); + + ImageView ivShadow = new ImageView(getContext()); + resId = getBitmapRes(getContext(), "title_shadow"); + if (resId > 0) { + ivShadow.setBackgroundResource(resId); + } + FrameLayout.LayoutParams lpSd = new FrameLayout.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + ivShadow.setLayoutParams(lpSd); + flPage.addView(ivShadow); + + // 请求数据 + followList.performPulling(true); + } + + public void onClick(View v) { + if (v.equals(llTitle.getBtnRight())) { + ArrayList selected = new ArrayList(); + for (int i = 0, size = adapter.getCount(); i < size; i++) { + if (adapter.getItem(i).checked) { + selected.add(adapter.getItem(i).atName); + } + } + + setResultForChecked(selected); + } + + finish(); + } + + public void onItemClick(AdapterView parent, View view, int position, long id) { + String name = platform.getName(); + if (isRadioMode(name)) { + if(lastPosition >= 0) { + Following lastFollwing = adapter.getItem(lastPosition); + lastFollwing.checked = false; + } + lastPosition = position; + } + Following following = adapter.getItem(position); + following.checked = !following.checked; + adapter.notifyDataSetChanged(); + } + + private static class FollowAdapter extends PullToRefreshListAdapter + implements PlatformActionListener, Callback { + private static final int FOLLOW_LIST_EMPTY = 2; + private int curPage; + private ArrayList follows; + private HashMap map; + private boolean hasNext; + private Platform platform; + private PRTHeader llHeader; + private Bitmap bmChd; + private Bitmap bmUnch; + + public FollowAdapter(PullToRefreshView view) { + super(view); + curPage = -1; + hasNext = true; + map = new HashMap(); + follows = new ArrayList(); + + llHeader = new PRTHeader(getContext()); + + int resId = getBitmapRes(getContext(), "auth_follow_cb_chd"); + if (resId > 0) { + bmChd = BitmapFactory.decodeResource(view.getResources(), resId); + } + resId = getBitmapRes(getContext(), "auth_follow_cb_unc"); + if (resId > 0) { + bmUnch = BitmapFactory.decodeResource(view.getResources(), resId); + } + } + + public void setPlatform(Platform platform) { + this.platform = platform; + platform.setPlatformActionListener(this); + } + + private void next() { + if (hasNext) { + platform.listFriend(15, curPage + 1, null); + } + } + + public View getView(int position, View convertView, ViewGroup parent) { + FollowListItem item = null; + boolean simpleMode = "FacebookMessenger".equals(platform.getName()); + if (convertView == null) { + LinearLayout llItem = new LinearLayout(parent.getContext()); + item = new FollowListItem(); + llItem.setTag(item); + convertView = llItem; + + int dp_52 = com.mob.tools.utils.R.dipToPx(getContext(), 52); + int dp_10 = com.mob.tools.utils.R.dipToPx(parent.getContext(), 10); + int dp_5 = com.mob.tools.utils.R.dipToPx(parent.getContext(), 5); + + if(!simpleMode) { + item.aivIcon = new AsyncImageView(getContext()); + LayoutParams lpIcon = new LayoutParams(dp_52, dp_52); + lpIcon.gravity = Gravity.CENTER_VERTICAL; + lpIcon.setMargins(dp_10, dp_5, dp_10, dp_5); + item.aivIcon.setLayoutParams(lpIcon); + llItem.addView(item.aivIcon); + } + + LinearLayout llText = new LinearLayout(parent.getContext()); + llText.setPadding(0, dp_10, dp_10, dp_10); + llText.setOrientation(LinearLayout.VERTICAL); + LayoutParams lpText = new LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + lpText.gravity = Gravity.CENTER_VERTICAL; + lpText.weight = 1; + llText.setLayoutParams(lpText); + llItem.addView(llText); + + item.tvName = new TextView(parent.getContext()); + item.tvName.setTextColor(0xff000000); + item.tvName.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + item.tvName.setSingleLine(); + if(simpleMode) { + item.tvName.setPadding(dp_10, 0, 0, 0); + } + llText.addView(item.tvName); + + if(!simpleMode) { + item.tvSign = new TextView(parent.getContext()); + item.tvSign.setTextColor(0x7f000000); + item.tvSign.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + item.tvSign.setSingleLine(); + llText.addView(item.tvSign); + } + + item.ivCheck = new ImageView(parent.getContext()); + item.ivCheck.setPadding(0, 0, dp_10, 0); + LayoutParams lpCheck = new LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + lpCheck.gravity = Gravity.CENTER_VERTICAL; + item.ivCheck.setLayoutParams(lpCheck); + llItem.addView(item.ivCheck); + } else { + item = (FollowListItem) convertView.getTag(); + } + + Following following = getItem(position); + item.tvName.setText(following.screenName); + if(!simpleMode) { + item.tvSign.setText(following.description); + } + item.ivCheck.setImageBitmap(following.checked ? bmChd : bmUnch); + if(!simpleMode) { + if (isFling()) { + Bitmap bm = BitmapProcessor.getBitmapFromCache(following.icon); + if (bm != null && !bm.isRecycled()) { + item.aivIcon.setImageBitmap(bm); + } else { + item.aivIcon.execute(null, 0); + } + } else { + item.aivIcon.execute(following.icon,0); + } + } + + if (position == getCount() - 1) { + next(); + } + return convertView; + } + + public Following getItem(int position) { + return follows.get(position); + } + + public long getItemId(int position) { + return position; + } + + public int getCount() { + return follows == null ? 0 : follows.size(); + } + + public View getHeaderView() { + return llHeader; + } + + public void onPullDown(int percent) { + llHeader.onPullDown(percent); + } + + public void onRequest() { + llHeader.onRequest(); + curPage = -1; + hasNext = true; + map.clear(); + next(); + } + + public void onCancel(Platform plat, int action) { + UIHandler.sendEmptyMessage(-1, this); + } + + public void onComplete(Platform plat, int action, HashMap res) { + FollowersResult followersResult = parseFollowers(platform.getName(), res, map); + + if(followersResult == null) { + UIHandler.sendEmptyMessage(FOLLOW_LIST_EMPTY, this); + return; + } + hasNext = followersResult.hasNextPage; + if (followersResult.list != null && followersResult.list.size() > 0) { + curPage++; + Message msg = new Message(); + msg.what = 1; + msg.obj = followersResult.list; + UIHandler.sendMessage(msg, this); + } + } + + public void onError(Platform plat, int action, Throwable t) { + t.printStackTrace(); + } + + public boolean handleMessage(Message msg) { + if (msg.what < 0) { + ((Activity) getContext()).finish(); + } else if(msg.what == FOLLOW_LIST_EMPTY) { + notifyDataSetChanged(); + } else { + if (curPage <= 0) { + follows.clear(); + } + @SuppressWarnings("unchecked") + ArrayList data = (ArrayList) msg.obj; + follows.addAll(data); + notifyDataSetChanged(); + } + return false; + } + + public void onReversed() { + super.onReversed(); + llHeader.reverse(); + } + + } + + private static class FollowListItem { + public AsyncImageView aivIcon; + public TextView tvName; + public TextView tvSign; + public ImageView ivCheck; + } + + private static class PRTHeader extends LinearLayout { + private TextView tvHeader; + private RotateImageView ivArrow; + private ProgressBar pbRefreshing; + + public PRTHeader(Context context) { + super(context); + setOrientation(VERTICAL); + + LinearLayout llInner = new LinearLayout(context); + LayoutParams lpInner = new LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + lpInner.gravity = Gravity.CENTER_HORIZONTAL; + addView(llInner, lpInner); + + ivArrow = new RotateImageView(context); + int resId = getBitmapRes(context, "ssdk_oks_ptr_ptr"); + if (resId > 0) { + ivArrow.setImageResource(resId); + } + int dp_32 = dipToPx(context, 32); + LayoutParams lpIv = new LayoutParams(dp_32, dp_32); + lpIv.gravity = Gravity.CENTER_VERTICAL; + llInner.addView(ivArrow, lpIv); + + pbRefreshing = new ProgressBar(context); + llInner.addView(pbRefreshing, lpIv); + pbRefreshing.setVisibility(View.GONE); + + tvHeader = new TextView(getContext()); + tvHeader.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + tvHeader.setGravity(Gravity.CENTER); + int dp_10 = com.mob.tools.utils.R.dipToPx(getContext(), 10); + tvHeader.setPadding(dp_10, dp_10, dp_10, dp_10); + tvHeader.setTextColor(0xff000000); + LayoutParams lpTv = new LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + lpTv.gravity = Gravity.CENTER_VERTICAL; + llInner.addView(tvHeader, lpTv); + } + + public void onPullDown(int percent) { + if (percent > 100) { + int degree = (percent - 100) * 180 / 20; + if (degree > 180) { + degree = 180; + } + if (degree < 0) { + degree = 0; + } + ivArrow.setRotation(degree); + } else { + ivArrow.setRotation(0); + } + + if (percent < 100) { + int resId = getStringRes(getContext(), "pull_to_refresh"); + if (resId > 0) { + tvHeader.setText(resId); + } + } else { + int resId = getStringRes(getContext(), "release_to_refresh"); + if (resId > 0) { + tvHeader.setText(resId); + } + } + } + + public void onRequest() { + ivArrow.setVisibility(View.GONE); + pbRefreshing.setVisibility(View.VISIBLE); + int resId = getStringRes(getContext(), "refreshing"); + if (resId > 0) { + tvHeader.setText(resId); + } + } + + public void reverse() { + pbRefreshing.setVisibility(View.GONE); + ivArrow.setRotation(180); + ivArrow.setVisibility(View.VISIBLE); + } + + } + + private static class RotateImageView extends ImageView { + private int rotation; + + public RotateImageView(Context context) { + super(context); + } + + public void setRotation(int degree) { + rotation = degree; + invalidate(); + } + + protected void onDraw(Canvas canvas) { + canvas.rotate(rotation, getWidth() / 2, getHeight() / 2); + super.onDraw(canvas); + } + + } + +} diff --git a/app/src/main/java/cn/sharesdk/onekeyshare/theme/classic/PlatformGridView.java b/app/src/main/java/cn/sharesdk/onekeyshare/theme/classic/PlatformGridView.java new file mode 100644 index 0000000000..2c305d828c --- /dev/null +++ b/app/src/main/java/cn/sharesdk/onekeyshare/theme/classic/PlatformGridView.java @@ -0,0 +1,492 @@ +/* + * Offical Website:http://www.mob.com + * Support QQ: 4006852216 + * Offical Wechat Account:ShareSDK (We will inform you our updated news at the first time by Wechat, if we release a new version. If you get any problem, you can also contact us with Wechat, we will reply you within 24 hours.) + * + * Copyright (c) 2013 mob.com. All rights reserved. + */ + +package cn.sharesdk.onekeyshare.theme.classic; + +import static com.mob.tools.utils.R.getBitmapRes; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.Build; +import android.os.Handler.Callback; +import android.os.Message; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.ImageView.ScaleType; +import android.widget.LinearLayout; +import android.widget.TextView; +import cn.sharesdk.framework.Platform; +import cn.sharesdk.framework.ShareSDK; +import cn.sharesdk.onekeyshare.CustomerLogo; + +import com.mob.tools.gui.ViewPagerAdapter; +import com.mob.tools.gui.ViewPagerClassic; +import com.mob.tools.utils.UIHandler; + +/** platform logo list gridview */ +public class PlatformGridView extends LinearLayout implements + OnClickListener, Callback { + private static final int MIN_CLICK_INTERVAL = 1000; + private static final int MSG_PLATFORM_LIST_GOT = 1; + // grids in each line + private int LINE_PER_PAGE; + // lines in each page + private int COLUMN_PER_LINE; + // grids in each page + private int PAGE_SIZE; + // grids container + private ViewPagerClassic pager; + // indicators + private ImageView[] points; + private Bitmap grayPoint; + private Bitmap bluePoint; + // Determine whether don't jump editpage and share directly + private boolean silent; + // platforms + private Platform[] platformList; + // data to share + private HashMap reqData; + private PlatformListPage parent; + private ArrayList customers; + private HashMap hiddenPlatforms; + private View bgView; + private long lastClickTime; + + public PlatformGridView(Context context) { + super(context); + init(context); + } + + public PlatformGridView(Context context, AttributeSet attrs) { + super(context, attrs); + init(context); + } + + private void init(final Context context) { + calPageSize(); + setOrientation(VERTICAL); + + pager = new ViewPagerClassic(context); + disableOverScrollMode(pager); + pager.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); + addView(pager); + + // in order to have a better UI effect, opening a thread request the list of platforms + new Thread() { + public void run() { + try { + platformList = ShareSDK.getPlatformList(); + if (platformList == null) { + platformList = new Platform[0]; + } + UIHandler.sendEmptyMessage(MSG_PLATFORM_LIST_GOT, PlatformGridView.this); + } catch (Throwable t) { + t.printStackTrace(); + } + } + }.start(); + } + + private void calPageSize() { + float scrW = com.mob.tools.utils.R.getScreenWidth(getContext()); + float scrH = com.mob.tools.utils.R.getScreenHeight(getContext()); + float whR = scrW / scrH; + if (whR < 0.63) { + COLUMN_PER_LINE = 3; + LINE_PER_PAGE = 3; + } else if (whR < 0.75) { + COLUMN_PER_LINE = 3; + LINE_PER_PAGE = 2; + } else { + LINE_PER_PAGE = 1; + if (whR >= 1.75) { + COLUMN_PER_LINE = 6; + } else if (whR >= 1.5) { + COLUMN_PER_LINE = 5; + } else if (whR >= 1.3) { + COLUMN_PER_LINE = 4; + } else { + COLUMN_PER_LINE = 3; + } + } + COLUMN_PER_LINE = 2; + LINE_PER_PAGE = 2; + PAGE_SIZE = COLUMN_PER_LINE * LINE_PER_PAGE; + } + + public boolean handleMessage(Message msg) { + switch (msg.what) { + case MSG_PLATFORM_LIST_GOT: { + afterPlatformListGot(); + } + break; + } + return false; + } + + // initializes the girdview of platforms + public void afterPlatformListGot() { + PlatformAdapter adapter = new PlatformAdapter(this); + pager.setAdapter(adapter); + int pageCount = 0; + if (platformList != null) { + int cusSize = customers == null ? 0 : customers.size(); + int platSize = platformList == null ? 0 : platformList.length; + int hideSize = hiddenPlatforms == null ? 0 : hiddenPlatforms.size(); + platSize = platSize-hideSize; + int size = platSize + cusSize; + pageCount = size / PAGE_SIZE; + if (size % PAGE_SIZE > 0) { + pageCount++; + } + } + points = new ImageView[pageCount]; + if (points.length <= 0) { + return; + } + + Context context = getContext(); + LinearLayout llPoints = new LinearLayout(context); + // if the total number of pages exceeds 1, we set the page indicators + llPoints.setVisibility(pageCount > 1 ? View.VISIBLE: View.GONE); + LayoutParams lpLl = new LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + lpLl.gravity = Gravity.CENTER_HORIZONTAL; + llPoints.setLayoutParams(lpLl); + addView(llPoints); + + int dp_5 = com.mob.tools.utils.R.dipToPx(context, 5); + int resId = getBitmapRes(getContext(), "light_blue_point"); + if (resId > 0) { + grayPoint = BitmapFactory.decodeResource(getResources(), resId); + } + resId = getBitmapRes(getContext(), "blue_point"); + if (resId > 0) { + bluePoint = BitmapFactory.decodeResource(getResources(), resId); + } + for (int i = 0; i < pageCount; i++) { + points[i] = new ImageView(context); + points[i].setScaleType(ScaleType.CENTER_INSIDE); + points[i].setImageBitmap(grayPoint); + LayoutParams lpIv = new LayoutParams(dp_5, dp_5); + lpIv.setMargins(dp_5, dp_5, dp_5, 0); + points[i].setLayoutParams(lpIv); + llPoints.addView(points[i]); + } + int curPage = pager.getCurrentScreen(); + points[curPage].setImageBitmap(bluePoint); + } + + /** after the screen rotates, this method will be called to refresh the list of gridviews */ + public void onConfigurationChanged() { + int curFirst = pager.getCurrentScreen() * PAGE_SIZE; + calPageSize(); + int newPage = curFirst / PAGE_SIZE; + + removeViewAt(1); + afterPlatformListGot(); + + pager.setCurrentScreen(newPage); + } + + public void setData(HashMap data, boolean silent) { + reqData = data; + this.silent = silent; + } + + public void setHiddenPlatforms(HashMap hiddenPlatforms) { + this.hiddenPlatforms = hiddenPlatforms; + } + + /** Set the Click event of the custom icon */ + public void setCustomerLogos(ArrayList customers) { + this.customers = customers; + } + + public void setEditPageBackground(View bgView) { + this.bgView = bgView; + } + + /** Sets the callback page sharing operations */ + public void setParent(PlatformListPage parent) { + this.parent = parent; + } + + public void onClick(View v) { + long time = System.currentTimeMillis(); + if (time - lastClickTime < MIN_CLICK_INTERVAL) { + return; + } + lastClickTime = time; + + ArrayList platforms = new ArrayList(1); + platforms.add(v.getTag()); + parent.onPlatformIconClick(v, platforms); + } + + // Disable the flashing effect when viewpages sliding to left/right edge + private void disableOverScrollMode(View view) { + if (Build.VERSION.SDK_INT < 9) { + return; + } + try { + Method m = View.class.getMethod("setOverScrollMode", + new Class[] { Integer.TYPE }); + m.setAccessible(true); + m.invoke(view, new Object[] { Integer.valueOf(2) }); + } catch (Throwable t) { + t.printStackTrace(); + } + } + + /** gridview adapter */ + private static class PlatformAdapter extends ViewPagerAdapter { + private GridView[] girds; + private List logos; + private OnClickListener callback; + private int lines; + private PlatformGridView platformGridView; + + public PlatformAdapter(PlatformGridView platformGridView) { + this.platformGridView = platformGridView; + logos = new ArrayList(); + Platform[] platforms = platformGridView.platformList; + HashMap hiddenPlatforms = platformGridView.hiddenPlatforms; + if (platforms != null) { + if (hiddenPlatforms != null && hiddenPlatforms.size() > 0) { + ArrayList ps = new ArrayList(); + for (Platform p : platforms) { + if (hiddenPlatforms.containsKey(p.getName())) { + continue; + } + ps.add(p); + } + + platforms = new Platform[ps.size()]; + for (int i = 0; i < platforms.length; i++) { + platforms[i] = ps.get(i); + } + } + + logos.addAll(Arrays.asList(platforms)); + } + ArrayList customers = platformGridView.customers; + if (customers != null) { + logos.addAll(customers); + } + this.callback = platformGridView; + girds = null; + + if (logos != null) { + int size = logos.size(); + int PAGE_SIZE = platformGridView.PAGE_SIZE; + int pageCount = size / PAGE_SIZE; + if (size % PAGE_SIZE > 0) { + pageCount++; + } + girds = new GridView[pageCount]; + } + } + + public int getCount() { + return girds == null ? 0 : girds.length; + } + + public View getView(int position, ViewGroup parent) { + if (girds[position] == null) { + int pageSize = platformGridView.PAGE_SIZE; + int curSize = pageSize * position; + int listSize = logos == null ? 0 : logos.size(); + if (curSize + pageSize > listSize) { + pageSize = listSize - curSize; + } + Object[] gridBean = new Object[pageSize]; + for (int i = 0; i < pageSize; i++) { + gridBean[i] = logos.get(curSize + i); + } + + if (position == 0) { + int COLUMN_PER_LINE = platformGridView.COLUMN_PER_LINE; + lines = gridBean.length / COLUMN_PER_LINE; + if (gridBean.length % COLUMN_PER_LINE > 0) { + lines++; + } + } + girds[position] = new GridView(this); + girds[position].setData(lines, gridBean); + } + + return girds[position]; + } + + /** This method will be called after sliding the gridview */ + public void onScreenChange(int currentScreen, int lastScreen) { + ImageView[] points = platformGridView.points; + for (int i = 0; i < points.length; i++) { + points[i].setImageBitmap(platformGridView.grayPoint); + } + + points[currentScreen].setImageBitmap(platformGridView.bluePoint); + } + + } + + /** a simple gridview */ + private static class GridView extends LinearLayout { + private Object[] beans; + private OnClickListener callback; + private int lines; + private PlatformAdapter platformAdapter; + + public GridView(PlatformAdapter platformAdapter) { + super(platformAdapter.platformGridView.getContext()); + this.platformAdapter = platformAdapter; + this.callback = platformAdapter.callback; + } + + public void setData(int lines, Object[] beans) { + this.lines = lines; + this.beans = beans; + init(); + } + + private void init() { + int dp_5 = com.mob.tools.utils.R.dipToPx(getContext(), 5); + setPadding(0, dp_5, 0, dp_5); + setOrientation(VERTICAL); + + int size = beans == null ? 0 : beans.length; + int COLUMN_PER_LINE = platformAdapter.platformGridView.COLUMN_PER_LINE; + int lineSize = size / COLUMN_PER_LINE; + if (size % COLUMN_PER_LINE > 0) { + lineSize++; + } + LayoutParams lp = new LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + lp.weight = 1; + for (int i = 0; i < lines; i++) { + LinearLayout llLine = new LinearLayout(getContext()); + llLine.setLayoutParams(lp); + llLine.setPadding(dp_5, 0, dp_5, 0); + addView(llLine); + + if (i >= lineSize) { + continue; + } + + for (int j = 0; j < COLUMN_PER_LINE; j++) { + final int index = i * COLUMN_PER_LINE + j; + if (index >= size) { + LinearLayout llItem = new LinearLayout(getContext()); + llItem.setLayoutParams(lp); + llLine.addView(llItem); + continue; + } + + final LinearLayout llItem = getView(index, callback, getContext()); + llItem.setTag(beans[index]); + llItem.setLayoutParams(lp); + llLine.addView(llItem); + } + } + } + + private LinearLayout getView(int position, OnClickListener ocL, Context context) { + Bitmap logo; + String label; + OnClickListener listener; + if (beans[position] instanceof Platform) { + logo = getIcon((Platform) beans[position]); + label = getName((Platform) beans[position]); + listener = ocL; + } else { + logo = ((CustomerLogo) beans[position]).enableLogo; + label = ((CustomerLogo) beans[position]).label; + listener = ocL; + } + + LinearLayout ll = new LinearLayout(context); + ll.setOrientation(LinearLayout.VERTICAL); + + ImageView iv = new ImageView(context); + int dp_5 = com.mob.tools.utils.R.dipToPx(context, 5); + iv.setPadding(dp_5, dp_5, dp_5, dp_5); + iv.setScaleType(ScaleType.CENTER_INSIDE); + LayoutParams lpIv = new LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + lpIv.setMargins(dp_5, dp_5, dp_5, dp_5); + lpIv.gravity = Gravity.CENTER_HORIZONTAL; + iv.setLayoutParams(lpIv); + iv.setImageBitmap(logo); + ll.addView(iv); + + TextView tv = new TextView(context); + tv.setTextColor(0xff000000); + tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + tv.setSingleLine(); + tv.setIncludeFontPadding(false); + LayoutParams lpTv = new LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + lpTv.gravity = Gravity.CENTER_HORIZONTAL; + lpTv.weight = 1; + lpTv.setMargins(dp_5, 0, dp_5, dp_5); + tv.setLayoutParams(lpTv); + tv.setText(label); +// ll.addView(tv); + ll.setOnClickListener(listener); + + return ll; + } + + private Bitmap getIcon(Platform plat) { + if (plat == null) { + return null; + } + + String name = plat.getName(); + if (name == null) { + return null; + } + + String resName = "logo_" + plat.getName(); + int resId = getBitmapRes(getContext(), resName.toLowerCase()); + return BitmapFactory.decodeResource(getResources(), resId); + } + + private String getName(Platform plat) { + if (plat == null) { + return ""; + } + + String name = plat.getName(); + if (name == null) { + return ""; + } + + int resId = com.mob.tools.utils.R.getStringRes(getContext(), plat.getName().toLowerCase()); + if (resId > 0) { + return getContext().getString(resId); + } + return null; + } + + } + +} diff --git a/app/src/main/java/cn/sharesdk/onekeyshare/theme/classic/PlatformListPage.java b/app/src/main/java/cn/sharesdk/onekeyshare/theme/classic/PlatformListPage.java new file mode 100644 index 0000000000..6f98ed264c --- /dev/null +++ b/app/src/main/java/cn/sharesdk/onekeyshare/theme/classic/PlatformListPage.java @@ -0,0 +1,216 @@ +/* + * 官网地站:http://www.mob.com + * 技术支持QQ: 4006852216 + * 官方微信:ShareSDK (如果发布新版本的话,我们将会第一时间通过微信将版本更新内容推送给您。如果使用过程中有任何问题,也可以通过微信与我们取得联系,我们将会在24小时内给予回复) + * + * Copyright (c) 2013年 mob.com. All rights reserved. + */ + +package cn.sharesdk.onekeyshare.theme.classic; + +import static com.mob.tools.utils.R.getBitmapRes; +import static com.mob.tools.utils.R.getStringRes; + +import java.util.ArrayList; + +import android.annotation.TargetApi; +import android.content.res.Configuration; +import android.graphics.drawable.ColorDrawable; +import android.os.Build; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.view.animation.Animation; +import android.view.animation.ScaleAnimation; +import android.widget.Button; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import cn.sharesdk.onekeyshare.PlatformListFakeActivity; + +import com.gh.common.util.DisplayUtils; +import com.gh.gamecenter.manager.SystemBarTintManager; + +public class PlatformListPage extends PlatformListFakeActivity implements + View.OnClickListener { + // page container + private FrameLayout flPage; + // gridview of platform list + private PlatformGridView grid; + // cancel button + private Button btnCancel; + // sliding up animation + private Animation animShow; + // sliding down animation + private Animation animHide; + private boolean finishing; + private LinearLayout llPage; + + public void onCreate() { + super.onCreate(); + + finishing = false; + initPageView(); + initAnim(); + activity.setContentView(flPage); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + setTranslucentStatus(true); + SystemBarTintManager tintManager = new SystemBarTintManager( + activity); + tintManager.setStatusBarTintEnabled(true); + tintManager.setStatusBarTintColor(0xff106DA6); + } + + // set the data for platform gridview + grid.setData(shareParamsMap, silent); + grid.setHiddenPlatforms(hiddenPlatforms); + grid.setCustomerLogos(customerLogos); + grid.setParent(this); + btnCancel.setOnClickListener(this); + + // display gridviews + llPage.clearAnimation(); + llPage.startAnimation(animShow); + } + + @TargetApi(19) + protected void setTranslucentStatus(boolean status) { + Window window = activity.getWindow(); + WindowManager.LayoutParams winParams = window.getAttributes(); + final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; + if (status) { + winParams.flags |= bits; + } else { + winParams.flags &= ~bits; + } + window.setAttributes(winParams); + } + + private void initPageView() { + flPage = new FrameLayout(getContext()); + flPage.setOnClickListener(this); + flPage.setBackgroundDrawable(new ColorDrawable(0x55000000)); + + // container of the platform gridview + llPage = new LinearLayout(getContext()) { + public boolean onTouchEvent(MotionEvent event) { + return true; + } + }; + llPage.setOrientation(LinearLayout.VERTICAL); + llPage.setBackgroundDrawable(new ColorDrawable(0xffffffff)); + // FrameLayout.LayoutParams lpLl = new FrameLayout.LayoutParams( + // FrameLayout.LayoutParams.WRAP_CONTENT, + // FrameLayout.LayoutParams.WRAP_CONTENT); + FrameLayout.LayoutParams lpLl = new FrameLayout.LayoutParams( + DisplayUtils.dip2px(getContext(), 166), + FrameLayout.LayoutParams.WRAP_CONTENT); + lpLl.gravity = Gravity.CENTER; + llPage.setLayoutParams(lpLl); + flPage.addView(llPage); + + // gridview + grid = new PlatformGridView(getContext()); + grid.setEditPageBackground(getBackgroundView()); + LinearLayout.LayoutParams lpWg = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT); + grid.setLayoutParams(lpWg); + llPage.addView(grid); + + // cancel button + btnCancel = new Button(getContext()); + // btnCancel.setTextColor(0xff3a65ff); + btnCancel.setTextColor(0xff1BA4FC); + btnCancel.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + int resId = getStringRes(getContext(), "cancel"); + if (resId > 0) { + btnCancel.setText(resId); + } + btnCancel.setPadding(0, 0, 0, + com.mob.tools.utils.R.dipToPx(getContext(), 5)); + + resId = getBitmapRes(getContext(), "classic_platform_corners_bg"); + if (resId > 0) { + btnCancel.setBackgroundResource(resId); + } else { + btnCancel.setBackgroundDrawable(new ColorDrawable(0xffffffff)); + } + + LinearLayout.LayoutParams lpBtn = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + com.mob.tools.utils.R.dipToPx(getContext(), 45)); + int dp_10 = com.mob.tools.utils.R.dipToPx(getContext(), 10); + lpBtn.setMargins(dp_10, dp_10, dp_10, dp_10); + btnCancel.setLayoutParams(lpBtn); + // llPage.addView(btnCancel); + } + + private void initAnim() { +// animShow = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, +// Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 1, +// Animation.RELATIVE_TO_SELF, 0); + animShow = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, + 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); + animShow.setDuration(300); + +// animHide = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, +// Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, +// Animation.RELATIVE_TO_SELF, 1); + animHide = new ScaleAnimation(1, 0, 1, 0, Animation.RELATIVE_TO_SELF, + 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); + animHide.setDuration(300); + } + + public void onConfigurationChanged(Configuration newConfig) { + if (grid != null) { + grid.onConfigurationChanged(); + } + } + + public boolean onFinish() { + if (finishing) { + return super.onFinish(); + } + + if (animHide == null) { + finishing = true; + return false; + } + + finishing = true; + animHide.setAnimationListener(new Animation.AnimationListener() { + public void onAnimationStart(Animation animation) { + + } + + public void onAnimationRepeat(Animation animation) { + + } + + public void onAnimationEnd(Animation animation) { + flPage.setVisibility(View.GONE); + finish(); + } + }); + llPage.clearAnimation(); + llPage.startAnimation(animHide); + // 中断finish操作 + return true; + } + + @Override + public void onClick(View v) { + if (v.equals(flPage) || v.equals(btnCancel)) { + setCanceled(true); + finish(); + } + } + + public void onPlatformIconClick(View v, ArrayList platforms) { + onShareButtonClick(v, platforms); + } +} diff --git a/app/src/main/java/cn/sharesdk/onekeyshare/theme/skyblue/EditPage.java b/app/src/main/java/cn/sharesdk/onekeyshare/theme/skyblue/EditPage.java new file mode 100644 index 0000000000..b1707607f8 --- /dev/null +++ b/app/src/main/java/cn/sharesdk/onekeyshare/theme/skyblue/EditPage.java @@ -0,0 +1,235 @@ +/* + * 官网地站:http://www.mob.com + * 技术支持QQ: 4006852216 + * 官方微信:ShareSDK (如果发布新版本的话,我们将会第一时间通过微信将版本更新内容推送给您。如果使用过程中有任何问题,也可以通过微信与我们取得联系,我们将会在24小时内给予回复) + * + * Copyright (c) 2013年 mob.com. All rights reserved. + */ + +package cn.sharesdk.onekeyshare.theme.skyblue; + +import static com.mob.tools.utils.R.getIdRes; +import static com.mob.tools.utils.R.getLayoutRes; +import static com.mob.tools.utils.R.getStringRes; + +import java.util.ArrayList; +import java.util.HashMap; + +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.EditText; +import android.widget.HorizontalScrollView; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; +import cn.sharesdk.framework.Platform; +import cn.sharesdk.framework.ShareSDK; +import cn.sharesdk.onekeyshare.EditPageFakeActivity; +import cn.sharesdk.onekeyshare.PicViewer; + +/** 执行图文分享的页面,此页面不支持微信平台的分享 */ +public class EditPage extends EditPageFakeActivity implements OnClickListener, TextWatcher { + private static final int MAX_TEXT_COUNT = 140; + + // 字数计算器 + private TextView textCounterTextView; + private EditText titleEditText; + private EditText textEditText; + + public void onCreate() { + if (shareParamMap == null || platforms == null) { + finish(); + return; + } + + activity.setContentView(getLayoutRes(activity, "skyblue_editpage")); + initView(); + } + + private void initView() { + if(!dialogMode) { + RelativeLayout mainRelLayout = (RelativeLayout)findViewByResName("mainRelLayout"); + RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) mainRelLayout.getLayoutParams(); + lp.setMargins(0,0,0,0); + lp.height = RelativeLayout.LayoutParams.MATCH_PARENT; + mainRelLayout.setLayoutParams(lp); + } + initTitleView(); + initBodyView(); + initImageListView(); + } + + private void initTitleView() { + View backImageView = findViewByResName("backImageView"); + backImageView.setTag("close"); + backImageView.setOnClickListener(this); + + View okImageView = findViewByResName("okImageView"); + okImageView.setTag("ok"); + okImageView.setOnClickListener(this); + } + + private void initBodyView() { + View closeImageView = findViewByResName("closeImageView"); + closeImageView.setTag("close"); + closeImageView.setOnClickListener(this); + + if(shareParamMap.containsKey("title")) { + titleEditText = (EditText) findViewByResName("titleEditText"); + titleEditText.setText(String.valueOf(shareParamMap.get("title"))); + } + + textCounterTextView = (TextView) findViewByResName("textCounterTextView"); + textCounterTextView.setText(String.valueOf(MAX_TEXT_COUNT)); + + textEditText = (EditText) findViewByResName("textEditText"); + textEditText.addTextChangedListener(this); + textEditText.setText(String.valueOf(shareParamMap.get("text"))); + + initAtUserView(); + } + + private void initAtUserView() { + LinearLayout atLayout = (LinearLayout) findViewByResName("atLayout"); + for(Platform platform : platforms) { + String platformName = platform.getName(); + if (isShowAtUserLayout(platformName)) { + View view = LayoutInflater.from(activity).inflate(getLayoutRes(activity, "skyblue_editpage_at_layout"), null); + TextView atDescTextView = (TextView) view.findViewById(getIdRes(activity, "atDescTextView")); + TextView atTextView = (TextView) view.findViewById(getIdRes(activity, "atTextView")); + + OnClickListener atBtnClickListener = new OnClickListener() { + public void onClick(View v) { + FollowListPage subPage = new FollowListPage(); + subPage.setPlatform((Platform) v.getTag()); + subPage.showForResult(activity, null, EditPage.this); + } + }; + atTextView.setTag(platform); + atTextView.setOnClickListener(atBtnClickListener); + atDescTextView.setTag(platform); + atDescTextView.setOnClickListener(atBtnClickListener); + + atTextView.setText(getAtUserButtonText(platformName)); + atDescTextView.setText(getContext().getString(getStringRes(activity, "list_friends"), getLogoName(platformName))); + + atLayout.addView(view); + } + } + + } + + private void initImageListView() { + final HorizontalScrollView hScrollView = (HorizontalScrollView) findViewByResName("hScrollView"); + ImageListResultsCallback callback = new ImageListResultsCallback() { + + @Override + public void onFinish(ArrayList results) { + if(results == null) + return; + LinearLayout layout = (LinearLayout) findViewByResName("imagesLinearLayout"); + for(ImageInfo imageInfo : results) { + if(imageInfo.bitmap == null) + continue; + layout.addView(makeImageItemView(imageInfo)); + } + } + }; + if(!initImageList(callback)) { + hScrollView.setVisibility(View.GONE); + } + + } + + private View makeImageItemView(final ImageInfo imageInfo) { + final View view = LayoutInflater.from(activity).inflate(getLayoutRes(activity, "skyblue_editpage_inc_image_layout"), null); + + ImageView imageView = (ImageView) view.findViewById(getIdRes(activity, "imageView")); + imageView.setImageBitmap(imageInfo.bitmap); + imageView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + PicViewer pv = new PicViewer(); + pv.setImageBitmap(imageInfo.bitmap); + pv.show(activity, null); + } + }); + + View removeBtn = view.findViewById(getIdRes(activity, "imageRemoveBtn")); + removeBtn.setTag(imageInfo); + removeBtn.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + view.setVisibility(View.GONE); + removeImage((ImageInfo) v.getTag()); + } + }); + + return view; + } + + public void onClick(View v) { + if(v.getTag() == null) + return; + String tag = (String) v.getTag(); + if (tag.equals("close")) { + // 取消分享的统计 + for(Platform plat : platforms) { + ShareSDK.logDemoEvent(5, plat); + } + finish(); + return; + } + + if (tag.equals("ok")) { + onShareButtonClick(v); + return; + } + } + + private void onShareButtonClick(View v) { + if(shareParamMap.containsKey("title")) { + String title = titleEditText.getText().toString().trim(); + shareParamMap.put("title", title); + } + + String text = textEditText.getText().toString().trim(); + shareParamMap.put("text", text); + + setResultAndFinish(); + } + + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + + } + + public void onTextChanged(CharSequence s, int start, int before, int count) { + int remain = MAX_TEXT_COUNT - textEditText.length(); + textCounterTextView.setText(String.valueOf(remain)); + textCounterTextView.setTextColor(remain > 0 ? 0xffcfcfcf : 0xffff0000); + } + + public void afterTextChanged(Editable s) { + + } + + public void onResult(HashMap data) { + String atText = getJoinSelectedUser(data); + if(atText != null) { + textEditText.append(atText); + } + } + + public boolean onFinish() { + textCounterTextView = null; + textEditText = null; + titleEditText = null; + return super.onFinish(); + } + +} diff --git a/app/src/main/java/cn/sharesdk/onekeyshare/theme/skyblue/FollowListPage.java b/app/src/main/java/cn/sharesdk/onekeyshare/theme/skyblue/FollowListPage.java new file mode 100644 index 0000000000..1cc2f8fcbb --- /dev/null +++ b/app/src/main/java/cn/sharesdk/onekeyshare/theme/skyblue/FollowListPage.java @@ -0,0 +1,459 @@ +/* + * 官网地站:http://www.mob.com + * 技术支持QQ: 4006852216 + * 官方微信:ShareSDK (如果发布新版本的话,我们将会第一时间通过微信将版本更新内容推送给您。如果使用过程中有任何问题,也可以通过微信与我们取得联系,我们将会在24小时内给予回复) + * + * Copyright (c) 2013年 mob.com. All rights reserved. + */ + +package cn.sharesdk.onekeyshare.theme.skyblue; + +import static com.mob.tools.utils.R.dipToPx; +import static com.mob.tools.utils.R.getBitmapRes; +import static com.mob.tools.utils.R.getStringRes; + +import java.util.ArrayList; +import java.util.HashMap; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.os.Handler.Callback; +import android.os.Message; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.ProgressBar; +import android.widget.TextView; +import cn.sharesdk.framework.Platform; +import cn.sharesdk.framework.PlatformActionListener; +import cn.sharesdk.framework.TitleLayout; +import cn.sharesdk.onekeyshare.FollowerListFakeActivity; + +import com.mob.tools.gui.AsyncImageView; +import com.mob.tools.gui.BitmapProcessor; +import com.mob.tools.gui.PullToRefreshListAdapter; +import com.mob.tools.gui.PullToRefreshView; +import com.mob.tools.utils.UIHandler; + +/** 获取好友或关注列表 */ +public class FollowListPage extends FollowerListFakeActivity implements OnClickListener, OnItemClickListener { + private TitleLayout llTitle; + private FollowAdapter adapter; + private int lastPosition = -1; + + + public void onCreate() { + LinearLayout llPage = new LinearLayout(getContext()); + llPage.setBackgroundColor(0xfff5f5f5); + llPage.setOrientation(LinearLayout.VERTICAL); + activity.setContentView(llPage); + + // 标题栏 + llTitle = new TitleLayout(getContext()); + int resId = getBitmapRes(getContext(), "title_back"); + if (resId > 0) { + llTitle.setBackgroundResource(resId); + } + llTitle.getBtnBack().setOnClickListener(this); + resId = getStringRes(getContext(), "multi_share"); + if (resId > 0) { + llTitle.getTvTitle().setText(resId); + } + llTitle.getBtnRight().setVisibility(View.VISIBLE); + resId = getStringRes(getContext(), "finish"); + if (resId > 0) { + llTitle.getBtnRight().setText(resId); + } + llTitle.getBtnRight().setOnClickListener(this); + llTitle.setLayoutParams(new LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); + llPage.addView(llTitle); + + FrameLayout flPage = new FrameLayout(getContext()); + LayoutParams lpFl = new LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + lpFl.weight = 1; + flPage.setLayoutParams(lpFl); + llPage.addView(flPage); + + // 关注(或朋友)列表 + PullToRefreshView followList = new PullToRefreshView(getContext()); + FrameLayout.LayoutParams lpLv = new FrameLayout.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + followList.setLayoutParams(lpLv); + flPage.addView(followList); + adapter = new FollowAdapter(followList); + adapter.setPlatform(platform); + followList.setAdapter(adapter); + adapter.getListView().setOnItemClickListener(this); + + ImageView ivShadow = new ImageView(getContext()); + resId = getBitmapRes(getContext(), "title_shadow"); + if (resId > 0) { + ivShadow.setBackgroundResource(resId); + } + FrameLayout.LayoutParams lpSd = new FrameLayout.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + ivShadow.setLayoutParams(lpSd); + flPage.addView(ivShadow); + + // 请求数据 + followList.performPulling(true); + } + + public void onClick(View v) { + if (v.equals(llTitle.getBtnRight())) { + ArrayList selected = new ArrayList(); + for (int i = 0, size = adapter.getCount(); i < size; i++) { + if (adapter.getItem(i).checked) { + selected.add(adapter.getItem(i).atName); + } + } + + setResultForChecked(selected); + } + + finish(); + } + + public void onItemClick(AdapterView parent, View view, int position, long id) { + String name = platform.getName(); + if (isRadioMode(name)) { + if(lastPosition >= 0) { + Following lastFollwing = adapter.getItem(lastPosition); + lastFollwing.checked = false; + } + lastPosition = position; + } + Following following = adapter.getItem(position); + following.checked = !following.checked; + adapter.notifyDataSetChanged(); + } + + private static class FollowAdapter extends PullToRefreshListAdapter + implements PlatformActionListener, Callback { + private static final int FOLLOW_LIST_EMPTY = 2; + private int curPage; + private ArrayList follows; + private HashMap map; + private boolean hasNext; + private Platform platform; + private PRTHeader llHeader; + private Bitmap bmChd; + private Bitmap bmUnch; + + public FollowAdapter(PullToRefreshView view) { + super(view); + curPage = -1; + hasNext = true; + map = new HashMap(); + follows = new ArrayList(); + + llHeader = new PRTHeader(getContext()); + + int resId = getBitmapRes(getContext(), "auth_follow_cb_chd"); + if (resId > 0) { + bmChd = BitmapFactory.decodeResource(view.getResources(), resId); + } + resId = getBitmapRes(getContext(), "auth_follow_cb_unc"); + if (resId > 0) { + bmUnch = BitmapFactory.decodeResource(view.getResources(), resId); + } + } + + public void setPlatform(Platform platform) { + this.platform = platform; + platform.setPlatformActionListener(this); + } + + private void next() { + if (hasNext) { + platform.listFriend(15, curPage + 1, null); + } + } + + public View getView(int position, View convertView, ViewGroup parent) { + FollowListItem item = null; + boolean simpleMode = "FacebookMessenger".equals(platform.getName()); + if (convertView == null) { + LinearLayout llItem = new LinearLayout(parent.getContext()); + item = new FollowListItem(); + llItem.setTag(item); + convertView = llItem; + + int dp_52 = com.mob.tools.utils.R.dipToPx(getContext(), 52); + int dp_10 = com.mob.tools.utils.R.dipToPx(parent.getContext(), 10); + int dp_5 = com.mob.tools.utils.R.dipToPx(parent.getContext(), 5); + + if(!simpleMode) { + item.aivIcon = new AsyncImageView(getContext()); + LayoutParams lpIcon = new LayoutParams(dp_52, dp_52); + lpIcon.gravity = Gravity.CENTER_VERTICAL; + lpIcon.setMargins(dp_10, dp_5, dp_10, dp_5); + item.aivIcon.setLayoutParams(lpIcon); + llItem.addView(item.aivIcon); + } + + LinearLayout llText = new LinearLayout(parent.getContext()); + llText.setPadding(0, dp_10, dp_10, dp_10); + llText.setOrientation(LinearLayout.VERTICAL); + LayoutParams lpText = new LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + lpText.gravity = Gravity.CENTER_VERTICAL; + lpText.weight = 1; + llText.setLayoutParams(lpText); + llItem.addView(llText); + + item.tvName = new TextView(parent.getContext()); + item.tvName.setTextColor(0xff000000); + item.tvName.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + item.tvName.setSingleLine(); + if(simpleMode) { + item.tvName.setPadding(dp_10, 0, 0, 0); + } + llText.addView(item.tvName); + + if(!simpleMode) { + item.tvSign = new TextView(parent.getContext()); + item.tvSign.setTextColor(0x7f000000); + item.tvSign.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + item.tvSign.setSingleLine(); + llText.addView(item.tvSign); + } + + item.ivCheck = new ImageView(parent.getContext()); + item.ivCheck.setPadding(0, 0, dp_10, 0); + LayoutParams lpCheck = new LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + lpCheck.gravity = Gravity.CENTER_VERTICAL; + item.ivCheck.setLayoutParams(lpCheck); + llItem.addView(item.ivCheck); + } else { + item = (FollowListItem) convertView.getTag(); + } + + Following following = getItem(position); + item.tvName.setText(following.screenName); + if(!simpleMode) { + item.tvSign.setText(following.description); + } + item.ivCheck.setImageBitmap(following.checked ? bmChd : bmUnch); + if(!simpleMode) { + if (isFling()) { + Bitmap bm = BitmapProcessor.getBitmapFromCache(following.icon); + if (bm != null && !bm.isRecycled()) { + item.aivIcon.setImageBitmap(bm); + } else { + item.aivIcon.execute(null, 0); + } + } else { + item.aivIcon.execute(following.icon,0); + } + } + + if (position == getCount() - 1) { + next(); + } + return convertView; + } + + public Following getItem(int position) { + return follows.get(position); + } + + public long getItemId(int position) { + return position; + } + + public int getCount() { + return follows == null ? 0 : follows.size(); + } + + public View getHeaderView() { + return llHeader; + } + + public void onPullDown(int percent) { + llHeader.onPullDown(percent); + } + + public void onRequest() { + llHeader.onRequest(); + curPage = -1; + hasNext = true; + map.clear(); + next(); + } + + public void onCancel(Platform plat, int action) { + UIHandler.sendEmptyMessage(-1, this); + } + + public void onComplete(Platform plat, int action, HashMap res) { + FollowersResult followersResult = parseFollowers(platform.getName(), res, map); + + if(followersResult == null) { + UIHandler.sendEmptyMessage(FOLLOW_LIST_EMPTY, this); + return; + } + hasNext = followersResult.hasNextPage; + if (followersResult.list != null && followersResult.list.size() > 0) { + curPage++; + Message msg = new Message(); + msg.what = 1; + msg.obj = followersResult.list; + UIHandler.sendMessage(msg, this); + } + } + + public void onError(Platform plat, int action, Throwable t) { + t.printStackTrace(); + } + + public boolean handleMessage(Message msg) { + if (msg.what < 0) { + ((Activity) getContext()).finish(); + } else if(msg.what == FOLLOW_LIST_EMPTY) { + notifyDataSetChanged(); + } else { + if (curPage <= 0) { + follows.clear(); + } + @SuppressWarnings("unchecked") + ArrayList data = (ArrayList) msg.obj; + follows.addAll(data); + notifyDataSetChanged(); + } + return false; + } + + public void onReversed() { + super.onReversed(); + llHeader.reverse(); + } + + } + + private static class FollowListItem { + public AsyncImageView aivIcon; + public TextView tvName; + public TextView tvSign; + public ImageView ivCheck; + } + + private static class PRTHeader extends LinearLayout { + private TextView tvHeader; + private RotateImageView ivArrow; + private ProgressBar pbRefreshing; + + public PRTHeader(Context context) { + super(context); + setOrientation(VERTICAL); + + LinearLayout llInner = new LinearLayout(context); + LayoutParams lpInner = new LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + lpInner.gravity = Gravity.CENTER_HORIZONTAL; + addView(llInner, lpInner); + + ivArrow = new RotateImageView(context); + int resId = getBitmapRes(context, "ssdk_oks_ptr_ptr"); + if (resId > 0) { + ivArrow.setImageResource(resId); + } + int dp_32 = dipToPx(context, 32); + LayoutParams lpIv = new LayoutParams(dp_32, dp_32); + lpIv.gravity = Gravity.CENTER_VERTICAL; + llInner.addView(ivArrow, lpIv); + + pbRefreshing = new ProgressBar(context); + llInner.addView(pbRefreshing, lpIv); + pbRefreshing.setVisibility(View.GONE); + + tvHeader = new TextView(getContext()); + tvHeader.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + tvHeader.setGravity(Gravity.CENTER); + int dp_10 = com.mob.tools.utils.R.dipToPx(getContext(), 10); + tvHeader.setPadding(dp_10, dp_10, dp_10, dp_10); + tvHeader.setTextColor(0xff000000); + LayoutParams lpTv = new LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + lpTv.gravity = Gravity.CENTER_VERTICAL; + llInner.addView(tvHeader, lpTv); + } + + public void onPullDown(int percent) { + if (percent > 100) { + int degree = (percent - 100) * 180 / 20; + if (degree > 180) { + degree = 180; + } + if (degree < 0) { + degree = 0; + } + ivArrow.setRotation(degree); + } else { + ivArrow.setRotation(0); + } + + if (percent < 100) { + int resId = getStringRes(getContext(), "pull_to_refresh"); + if (resId > 0) { + tvHeader.setText(resId); + } + } else { + int resId = getStringRes(getContext(), "release_to_refresh"); + if (resId > 0) { + tvHeader.setText(resId); + } + } + } + + public void onRequest() { + ivArrow.setVisibility(View.GONE); + pbRefreshing.setVisibility(View.VISIBLE); + int resId = getStringRes(getContext(), "refreshing"); + if (resId > 0) { + tvHeader.setText(resId); + } + } + + public void reverse() { + pbRefreshing.setVisibility(View.GONE); + ivArrow.setRotation(180); + ivArrow.setVisibility(View.VISIBLE); + } + + } + + private static class RotateImageView extends ImageView { + private int rotation; + + public RotateImageView(Context context) { + super(context); + } + + public void setRotation(int degree) { + rotation = degree; + invalidate(); + } + + protected void onDraw(Canvas canvas) { + canvas.rotate(rotation, getWidth() / 2, getHeight() / 2); + super.onDraw(canvas); + } + + } + +} diff --git a/app/src/main/java/cn/sharesdk/onekeyshare/theme/skyblue/PlatformGridViewAdapter.java b/app/src/main/java/cn/sharesdk/onekeyshare/theme/skyblue/PlatformGridViewAdapter.java new file mode 100644 index 0000000000..e6c7e2f4c6 --- /dev/null +++ b/app/src/main/java/cn/sharesdk/onekeyshare/theme/skyblue/PlatformGridViewAdapter.java @@ -0,0 +1,211 @@ +/* + * 官网地站:http://www.mob.com + * 技术支持QQ: 4006852216 + * 官方微信:ShareSDK (如果发布新版本的话,我们将会第一时间通过微信将版本更新内容推送给您。如果使用过程中有任何问题,也可以通过微信与我们取得联系,我们将会在24小时内给予回复) + * + * Copyright (c) 2013年 mob.com. All rights reserved. + */ + +package cn.sharesdk.onekeyshare.theme.skyblue; + +import static com.mob.tools.utils.R.getBitmapRes; +import static com.mob.tools.utils.R.getIdRes; +import static com.mob.tools.utils.R.getLayoutRes; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.TextView; +import cn.sharesdk.framework.Platform; +import cn.sharesdk.onekeyshare.CustomerLogo; +import cn.sharesdk.onekeyshare.ShareCore; + +public class PlatformGridViewAdapter extends BaseAdapter implements View.OnClickListener { + + private final Context context; + private List logos = new ArrayList(); + private List checkedPositionList = new ArrayList(); + private int directOnlyPosition = -1; + + static class ViewHolder { + public Integer position; + public ImageView logoImageView; + public ImageView checkedImageView; + public TextView nameTextView; + } + + public PlatformGridViewAdapter(Context context) { + this.context = context; + } + + @Override + public int getCount() { + return logos.size(); + } + + @Override + public Object getItem(int i) { + return logos.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(int position, View view, ViewGroup viewGroup) { + ViewHolder viewHolder; + if(view == null) { + view = LayoutInflater.from(context).inflate(getLayoutRes(context, "skyblue_share_platform_list_item"), null); + viewHolder = new ViewHolder(); + viewHolder.checkedImageView = (ImageView) view.findViewById(getIdRes(context, "checkedImageView")); + viewHolder.logoImageView = (ImageView) view.findViewById(getIdRes(context, "logoImageView")); + viewHolder.nameTextView = (TextView) view.findViewById(getIdRes(context, "nameTextView")); + view.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) view.getTag(); + } + + Bitmap logo; + String label; + Object item = getItem(position); + boolean disabled; + boolean isDirectShare = item instanceof Platform ? ShareCore.isDirectShare((Platform) item) : true; + if(directOnlyPosition == -1) { + disabled = !checkedPositionList.isEmpty() && isDirectShare; + } else { + disabled = position != directOnlyPosition; + } + + if (item instanceof Platform) { + logo = getIcon((Platform) item, disabled ? "" : "_checked"); + label = getName((Platform) item); + view.setOnClickListener(this); + } else { + CustomerLogo customerLogo = (CustomerLogo) item; + logo = disabled ? customerLogo.disableLogo : customerLogo.enableLogo; + label = customerLogo.label; + view.setOnClickListener(this); + //TODO 需要整理 + // view.setOnClickListener(((CustomerLogo) item).listener); + } + String checkedResName = directOnlyPosition != -1 && directOnlyPosition != position ? "skyblue_platform_checked_disabled" : "skyblue_platform_checked"; + viewHolder.position = position; + viewHolder.checkedImageView.setImageBitmap(BitmapFactory.decodeResource(context.getResources(), getBitmapRes(context, checkedResName))); + viewHolder.checkedImageView.setVisibility(checkedPositionList.contains(viewHolder.position) ? View.VISIBLE : View.GONE); + viewHolder.nameTextView.setText(label); + viewHolder.logoImageView.setImageBitmap(logo); + + return view; + } + + @Override + public void onClick(View view) { + ViewHolder viewHolder = (ViewHolder) view.getTag(); + Integer position = viewHolder.position; + //直接分享平台选中后,其它的不可用 + if(directOnlyPosition != -1 && position != directOnlyPosition) + return; + + Object item = getItem(position); + boolean direct = false; + //normal platform + if(item instanceof Platform){ + direct = ShareCore.isDirectShare((Platform) item); + }else{ + //自定义图标 + direct = true; + } + //EditPage Platforms only + if(direct && directOnlyPosition == -1 && !checkedPositionList.isEmpty()) + return; + + if(checkedPositionList.contains(position)) { + checkedPositionList.remove(position); + if(direct) + directOnlyPosition = -1; + } else { + checkedPositionList.add(position); + if(direct) + directOnlyPosition = position; + } + + notifyDataSetChanged(); + } + + public void setData(Platform[] platforms, HashMap hiddenPlatforms) { + if(platforms == null) + return; + if (hiddenPlatforms != null && hiddenPlatforms.size() > 0) { + ArrayList ps = new ArrayList(); + for (Platform p : platforms) { + if (hiddenPlatforms.containsKey(p.getName())) { + continue; + } + ps.add(p); + } + + logos.addAll(ps); + } else { + logos.addAll(Arrays.asList(platforms)); + } + checkedPositionList.clear(); + notifyDataSetChanged(); + } + + public void setCustomerLogos(ArrayList customers) { + if(customers == null || customers.size() == 0) + return; + logos.addAll(customers); + } + + public List getCheckedItems() { + ArrayList list = new ArrayList(); + + if(directOnlyPosition != -1) { + list.add(getItem(directOnlyPosition)); + return list; + } + + Object item; + for(Integer position : checkedPositionList) { + item = getItem(position); + list.add(item); + } + return list; + } + + private Bitmap getIcon(Platform plat, String subfix) { + String resName = "skyblue_logo_" + plat.getName() + subfix; + int resId = getBitmapRes(context, resName); + return BitmapFactory.decodeResource(context.getResources(), resId); + } + + private String getName(Platform plat) { + if (plat == null) { + return ""; + } + + String name = plat.getName(); + if (name == null) { + return ""; + } + + int resId = com.mob.tools.utils.R.getStringRes(context, plat.getName()); + if (resId > 0) { + return context.getString(resId); + } + return null; + } +} diff --git a/app/src/main/java/cn/sharesdk/onekeyshare/theme/skyblue/PlatformListPage.java b/app/src/main/java/cn/sharesdk/onekeyshare/theme/skyblue/PlatformListPage.java new file mode 100644 index 0000000000..f32fd96367 --- /dev/null +++ b/app/src/main/java/cn/sharesdk/onekeyshare/theme/skyblue/PlatformListPage.java @@ -0,0 +1,93 @@ +/* + * 官网地站:http://www.mob.com + * 技术支持QQ: 4006852216 + * 官方微信:ShareSDK (如果发布新版本的话,我们将会第一时间通过微信将版本更新内容推送给您。如果使用过程中有任何问题,也可以通过微信与我们取得联系,我们将会在24小时内给予回复) + * + * Copyright (c) 2013年 mob.com. All rights reserved. + */ + +package cn.sharesdk.onekeyshare.theme.skyblue; + +import static com.mob.tools.utils.R.getLayoutRes; +import static com.mob.tools.utils.R.getStringRes; + +import java.util.List; + +import android.os.AsyncTask; +import android.view.View; +import android.widget.GridView; +import android.widget.Toast; +import cn.sharesdk.framework.Platform; +import cn.sharesdk.framework.ShareSDK; +import cn.sharesdk.onekeyshare.PlatformListFakeActivity; + +public class PlatformListPage extends PlatformListFakeActivity implements View.OnClickListener { + private PlatformGridViewAdapter gridViewAdapter; + + public void onCreate() { + super.onCreate(); + activity.setContentView(getLayoutRes(activity, "skyblue_share_platform_list")); + + initView(); + } + + private void initView() { + View backImageView = findViewByResName("backImageView"); + backImageView.setTag(android.R.string.cancel); + backImageView.setOnClickListener(this); + + View okImageView = findViewByResName("okImageView"); + okImageView.setTag(android.R.string.ok); + okImageView.setOnClickListener(this); + + gridViewAdapter = new PlatformGridViewAdapter(activity); + gridViewAdapter.setCustomerLogos(customerLogos); + + GridView gridView = (GridView) findViewByResName("gridView"); + gridView.setAdapter(gridViewAdapter); + + new AsyncTask() { + + @Override + protected Platform[] doInBackground(Void... params) { + return ShareSDK.getPlatformList(); + } + + @Override + protected void onPostExecute(Platform[] platforms) { + gridViewAdapter.setData(platforms, hiddenPlatforms); + } + }.execute(); + } + + public void onClick(View v) { + Object tag = v.getTag(); + if(tag == null || !(tag instanceof Integer)) + return; + + switch ((Integer)tag) { + case android.R.string.cancel: + setCanceled(true); + finish(); + break; + case android.R.string.ok: + onShareButtonClick(v); + break; + } + } + + private void onShareButtonClick(View v) { + if(gridViewAdapter == null || "locked".equals(v.getTag())) + return; + + List checkedPlatforms = gridViewAdapter.getCheckedItems(); + if(checkedPlatforms.size() == 0){ + Toast.makeText(activity, getStringRes(activity, "select_one_plat_at_least"), Toast.LENGTH_SHORT).show(); + return; + } + + v.setTag("locked"); + onShareButtonClick(v, checkedPlatforms); + } + +} diff --git a/app/src/main/java/com/android/volley/AuthFailureError.java b/app/src/main/java/com/android/volley/AuthFailureError.java new file mode 100644 index 0000000000..87c811dfe4 --- /dev/null +++ b/app/src/main/java/com/android/volley/AuthFailureError.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley; + +import android.content.Intent; + +/** + * Error indicating that there was an authentication failure when performing a Request. + */ +@SuppressWarnings("serial") +public class AuthFailureError extends VolleyError { + /** An intent that can be used to resolve this exception. (Brings up the password dialog.) */ + private Intent mResolutionIntent; + + public AuthFailureError() { } + + public AuthFailureError(Intent intent) { + mResolutionIntent = intent; + } + + public AuthFailureError(NetworkResponse response) { + super(response); + } + + public AuthFailureError(String message) { + super(message); + } + + public AuthFailureError(String message, Exception reason) { + super(message, reason); + } + + public Intent getResolutionIntent() { + return mResolutionIntent; + } + + @Override + public String getMessage() { + if (mResolutionIntent != null) { + return "User needs to (re)enter credentials."; + } + return super.getMessage(); + } +} diff --git a/app/src/main/java/com/android/volley/Cache.java b/app/src/main/java/com/android/volley/Cache.java new file mode 100644 index 0000000000..eafd118825 --- /dev/null +++ b/app/src/main/java/com/android/volley/Cache.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley; + +import java.util.Collections; +import java.util.Map; + +/** + * An interface for a cache keyed by a String with a byte array as data. + */ +public interface Cache { + /** + * Retrieves an entry from the cache. + * @param key Cache key + * @return An {@link Entry} or null in the event of a cache miss + */ + public Entry get(String key); + + /** + * Adds or replaces an entry to the cache. + * @param key Cache key + * @param entry Data to store and metadata for cache coherency, TTL, etc. + */ + public void put(String key, Entry entry); + + /** + * Performs any potentially long-running actions needed to initialize the cache; + * will be called from a worker thread. + */ + public void initialize(); + + /** + * Invalidates an entry in the cache. + * @param key Cache key + * @param fullExpire True to fully expire the entry, false to soft expire + */ + public void invalidate(String key, boolean fullExpire); + + /** + * Removes an entry from the cache. + * @param key Cache key + */ + public void remove(String key); + + /** + * Empties the cache. + */ + public void clear(); + + /** + * Data and metadata for an entry returned by the cache. + */ + public static class Entry { + /** The data returned from cache. */ + public byte[] data; + + /** ETag for cache coherency. */ + public String etag; + + /** Date of this response as reported by the server. */ + public long serverDate; + + /** TTL for this record. */ + public long ttl; + + /** Soft TTL for this record. */ + public long softTtl; + + /** Immutable response headers as received from server; must be non-null. */ + public Map responseHeaders = Collections.emptyMap(); + + /** True if the entry is expired. */ + public boolean isExpired() { + return this.ttl < System.currentTimeMillis(); + } + + /** True if a refresh is needed from the original data source. */ + public boolean refreshNeeded() { + return this.softTtl < System.currentTimeMillis(); + } + } + +} diff --git a/app/src/main/java/com/android/volley/CacheDispatcher.java b/app/src/main/java/com/android/volley/CacheDispatcher.java new file mode 100644 index 0000000000..ac30463936 --- /dev/null +++ b/app/src/main/java/com/android/volley/CacheDispatcher.java @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley; + +import java.util.concurrent.BlockingQueue; + +import android.os.Process; + +/** + * Provides a thread for performing cache triage on a queue of requests. + * + * Requests added to the specified cache queue are resolved from cache. + * Any deliverable response is posted back to the caller via a + * {@link ResponseDelivery}. Cache misses and responses that require + * refresh are enqueued on the specified network queue for processing + * by a {@link NetworkDispatcher}. + */ +@SuppressWarnings("rawtypes") +public class CacheDispatcher extends Thread { + + private static final boolean DEBUG = VolleyLog.DEBUG; + + /** The queue of requests coming in for triage. */ + private final BlockingQueue mCacheQueue; + + /** The queue of requests going out to the network. */ + private final BlockingQueue mNetworkQueue; + + /** The cache to read from. */ + private final Cache mCache; + + /** For posting responses. */ + private final ResponseDelivery mDelivery; + + /** Used for telling us to die. */ + private volatile boolean mQuit = false; + + /** + * Creates a new cache triage dispatcher thread. You must call {@link #start()} + * in order to begin processing. + * + * @param cacheQueue Queue of incoming requests for triage + * @param networkQueue Queue to post requests that require network to + * @param cache Cache interface to use for resolution + * @param delivery Delivery interface to use for posting responses + */ + public CacheDispatcher( + BlockingQueue cacheQueue, BlockingQueue networkQueue, + Cache cache, ResponseDelivery delivery) { + mCacheQueue = cacheQueue; + mNetworkQueue = networkQueue; + mCache = cache; + mDelivery = delivery; + } + + /** + * Forces this dispatcher to quit immediately. If any requests are still in + * the queue, they are not guaranteed to be processed. + */ + public void quit() { + mQuit = true; + interrupt(); + } + + @Override + public void run() { + if (DEBUG) VolleyLog.v("start new dispatcher"); + Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); + + // Make a blocking call to initialize the cache. + mCache.initialize(); + + while (true) { + try { + // Get a request from the cache triage queue, blocking until + // at least one is available. + final Request request = mCacheQueue.take(); + request.addMarker("cache-queue-take"); + + // If the request has been canceled, don't bother dispatching it. + if (request.isCanceled()) { + request.finish("cache-discard-canceled"); + continue; + } + + // Attempt to retrieve this item from cache. + Cache.Entry entry = mCache.get(request.getCacheKey()); + if (entry == null) { + request.addMarker("cache-miss"); + // Cache miss; send off to the network dispatcher. + mNetworkQueue.put(request); + continue; + } + + // If it is completely expired, just send it to the network. + if (entry.isExpired()) { + request.addMarker("cache-hit-expired"); + request.setCacheEntry(entry); + mNetworkQueue.put(request); + continue; + } + + // We have a cache hit; parse its data for delivery back to the request. + request.addMarker("cache-hit"); + Response response = request.parseNetworkResponse( + new NetworkResponse(entry.data, entry.responseHeaders)); + request.addMarker("cache-hit-parsed"); + + if (!entry.refreshNeeded()) { + // Completely unexpired cache hit. Just deliver the response. + mDelivery.postResponse(request, response); + } else { + // Soft-expired cache hit. We can deliver the cached response, + // but we need to also send the request to the network for + // refreshing. + request.addMarker("cache-hit-refresh-needed"); + request.setCacheEntry(entry); + + // Mark the response as intermediate. + response.intermediate = true; + + // Post the intermediate response back to the user and have + // the delivery then forward the request along to the network. + mDelivery.postResponse(request, response, new Runnable() { + @Override + public void run() { + try { + mNetworkQueue.put(request); + } catch (InterruptedException e) { + // Not much we can do about this. + } + } + }); + } + + } catch (InterruptedException e) { + // We may have been interrupted because it was time to quit. + if (mQuit) { + return; + } + continue; + } + } + } +} diff --git a/app/src/main/java/com/android/volley/DefaultRetryPolicy.java b/app/src/main/java/com/android/volley/DefaultRetryPolicy.java new file mode 100644 index 0000000000..ce4f9e0a09 --- /dev/null +++ b/app/src/main/java/com/android/volley/DefaultRetryPolicy.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley; + +/** + * Default retry policy for requests. + */ +public class DefaultRetryPolicy implements RetryPolicy { + /** The current timeout in milliseconds. */ + private int mCurrentTimeoutMs; + + /** The current retry count. */ + private int mCurrentRetryCount; + + /** The maximum number of attempts. */ + private final int mMaxNumRetries; + + /** The backoff multiplier for for the policy. */ + private final float mBackoffMultiplier; + + /** The default socket timeout in milliseconds */ + public static final int DEFAULT_TIMEOUT_MS = 2500; + + /** The default number of retries */ + public static final int DEFAULT_MAX_RETRIES = 1; + + /** The default backoff multiplier */ + public static final float DEFAULT_BACKOFF_MULT = 1f; + + /** + * Constructs a new retry policy using the default timeouts. + */ + public DefaultRetryPolicy() { + this(DEFAULT_TIMEOUT_MS, DEFAULT_MAX_RETRIES, DEFAULT_BACKOFF_MULT); + } + + /** + * Constructs a new retry policy. + * @param initialTimeoutMs The initial timeout for the policy. + * @param maxNumRetries The maximum number of retries. + * @param backoffMultiplier Backoff multiplier for the policy. + */ + public DefaultRetryPolicy(int initialTimeoutMs, int maxNumRetries, float backoffMultiplier) { + mCurrentTimeoutMs = initialTimeoutMs; + mMaxNumRetries = maxNumRetries; + mBackoffMultiplier = backoffMultiplier; + } + + /** + * Returns the current timeout. + */ + @Override + public int getCurrentTimeout() { + return mCurrentTimeoutMs; + } + + /** + * Returns the current retry count. + */ + @Override + public int getCurrentRetryCount() { + return mCurrentRetryCount; + } + + /** + * Prepares for the next retry by applying a backoff to the timeout. + * @param error The error code of the last attempt. + */ + @Override + public void retry(VolleyError error) throws VolleyError { + mCurrentRetryCount++; + mCurrentTimeoutMs += (mCurrentTimeoutMs * mBackoffMultiplier); + if (!hasAttemptRemaining()) { + throw error; + } + } + + /** + * Returns true if this policy has attempts remaining, false otherwise. + */ + protected boolean hasAttemptRemaining() { + return mCurrentRetryCount <= mMaxNumRetries; + } +} diff --git a/app/src/main/java/com/android/volley/ExecutorDelivery.java b/app/src/main/java/com/android/volley/ExecutorDelivery.java new file mode 100644 index 0000000000..5d4a5840b9 --- /dev/null +++ b/app/src/main/java/com/android/volley/ExecutorDelivery.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley; + +import java.util.concurrent.Executor; + +import android.os.Handler; + +/** + * Delivers responses and errors. + */ +public class ExecutorDelivery implements ResponseDelivery { + /** Used for posting responses, typically to the main thread. */ + private final Executor mResponsePoster; + + /** + * Creates a new response delivery interface. + * @param handler {@link Handler} to post responses on + */ + public ExecutorDelivery(final Handler handler) { + // Make an Executor that just wraps the handler. + mResponsePoster = new Executor() { + @Override + public void execute(Runnable command) { + handler.post(command); + } + }; + } + + /** + * Creates a new response delivery interface, mockable version + * for testing. + * @param executor For running delivery tasks + */ + public ExecutorDelivery(Executor executor) { + mResponsePoster = executor; + } + + @Override + public void postResponse(Request request, Response response) { + postResponse(request, response, null); + } + + @Override + public void postResponse(Request request, Response response, Runnable runnable) { + request.markDelivered(); + request.addMarker("post-response"); + mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, runnable)); + } + + @Override + public void postError(Request request, VolleyError error) { + request.addMarker("post-error"); + Response response = Response.error(error); + mResponsePoster.execute(new ResponseDeliveryRunnable(request, response, null)); + } + + /** + * A Runnable used for delivering network responses to a listener on the + * main thread. + */ + @SuppressWarnings("rawtypes") + private class ResponseDeliveryRunnable implements Runnable { + private final Request mRequest; + private final Response mResponse; + private final Runnable mRunnable; + + public ResponseDeliveryRunnable(Request request, Response response, Runnable runnable) { + mRequest = request; + mResponse = response; + mRunnable = runnable; + } + + @SuppressWarnings("unchecked") + @Override + public void run() { + // If this request has canceled, finish it and don't deliver. + if (mRequest.isCanceled()) { + mRequest.finish("canceled-at-delivery"); + return; + } + + // Deliver a normal response or error, depending. + if (mResponse.isSuccess()) { + mRequest.deliverResponse(mResponse.result); + } else { + mRequest.deliverError(mResponse.error); + } + + // If this is an intermediate response, add a marker, otherwise we're done + // and the request can be finished. + if (mResponse.intermediate) { + mRequest.addMarker("intermediate-response"); + } else { + mRequest.finish("done"); + } + + // If we have been provided a post-delivery runnable, run it. + if (mRunnable != null) { + mRunnable.run(); + } + } + } +} diff --git a/app/src/main/java/com/android/volley/Network.java b/app/src/main/java/com/android/volley/Network.java new file mode 100644 index 0000000000..ab45830f6a --- /dev/null +++ b/app/src/main/java/com/android/volley/Network.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley; + +/** + * An interface for performing requests. + */ +public interface Network { + /** + * Performs the specified request. + * @param request Request to process + * @return A {@link NetworkResponse} with data and caching metadata; will never be null + * @throws VolleyError on errors + */ + public NetworkResponse performRequest(Request request) throws VolleyError; +} diff --git a/app/src/main/java/com/android/volley/NetworkDispatcher.java b/app/src/main/java/com/android/volley/NetworkDispatcher.java new file mode 100644 index 0000000000..9ae39ba3e3 --- /dev/null +++ b/app/src/main/java/com/android/volley/NetworkDispatcher.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley; + +import java.util.concurrent.BlockingQueue; + +import android.net.TrafficStats; +import android.os.Build; +import android.os.Process; + +/** + * Provides a thread for performing network dispatch from a queue of requests. + * + * Requests added to the specified queue are processed from the network via a + * specified {@link Network} interface. Responses are committed to cache, if + * eligible, using a specified {@link Cache} interface. Valid responses and + * errors are posted back to the caller via a {@link ResponseDelivery}. + */ +@SuppressWarnings("rawtypes") +public class NetworkDispatcher extends Thread { + /** The queue of requests to service. */ + private final BlockingQueue mQueue; + /** The network interface for processing requests. */ + private final Network mNetwork; + /** The cache to write to. */ + private final Cache mCache; + /** For posting responses and errors. */ + private final ResponseDelivery mDelivery; + /** Used for telling us to die. */ + private volatile boolean mQuit = false; + + /** + * Creates a new network dispatcher thread. You must call {@link #start()} + * in order to begin processing. + * + * @param queue Queue of incoming requests for triage + * @param network Network interface to use for performing requests + * @param cache Cache interface to use for writing responses to cache + * @param delivery Delivery interface to use for posting responses + */ + public NetworkDispatcher(BlockingQueue queue, + Network network, Cache cache, + ResponseDelivery delivery) { + mQueue = queue; + mNetwork = network; + mCache = cache; + mDelivery = delivery; + } + + /** + * Forces this dispatcher to quit immediately. If any requests are still in + * the queue, they are not guaranteed to be processed. + */ + public void quit() { + mQuit = true; + interrupt(); + } + + @Override + public void run() { + Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); + Request request; + while (true) { + try { + // Take a request from the queue. + request = mQueue.take(); + } catch (InterruptedException e) { + // We may have been interrupted because it was time to quit. + if (mQuit) { + return; + } + continue; + } + + try { + request.addMarker("network-queue-take"); + + // If the request was cancelled already, do not perform the + // network request. + if (request.isCanceled()) { + request.finish("network-discard-cancelled"); + continue; + } + + // Tag the request (if API >= 14) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + TrafficStats.setThreadStatsTag(request.getTrafficStatsTag()); + } + + // Perform the network request. + NetworkResponse networkResponse = mNetwork.performRequest(request); + request.addMarker("network-http-complete"); + + // If the server returned 304 AND we delivered a response already, + // we're done -- don't deliver a second identical response. + if (networkResponse.notModified && request.hasHadResponseDelivered()) { + request.finish("not-modified"); + continue; + } + + // Parse the response here on the worker thread. + Response response = request.parseNetworkResponse(networkResponse); + request.addMarker("network-parse-complete"); + + // Write to cache if applicable. + // TODO: Only update cache metadata instead of entire record for 304s. + if (request.shouldCache() && response.cacheEntry != null) { + mCache.put(request.getCacheKey(), response.cacheEntry); + request.addMarker("network-cache-written"); + } + + // Post the response back. + request.markDelivered(); + mDelivery.postResponse(request, response); + } catch (VolleyError volleyError) { + parseAndDeliverNetworkError(request, volleyError); + } catch (Exception e) { + VolleyLog.e(e, "Unhandled exception %s", e.toString()); + mDelivery.postError(request, new VolleyError(e)); + } + } + } + + private void parseAndDeliverNetworkError(Request request, VolleyError error) { + error = request.parseNetworkError(error); + mDelivery.postError(request, error); + } +} diff --git a/app/src/main/java/com/android/volley/NetworkError.java b/app/src/main/java/com/android/volley/NetworkError.java new file mode 100644 index 0000000000..63c388e16b --- /dev/null +++ b/app/src/main/java/com/android/volley/NetworkError.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley; + + +/** + * Indicates that there was a network error when performing a Volley request. + */ +@SuppressWarnings("serial") +public class NetworkError extends VolleyError { + public NetworkError() { + super(); + } + + public NetworkError(Throwable cause) { + super(cause); + } + + public NetworkError(NetworkResponse networkResponse) { + super(networkResponse); + } +} diff --git a/app/src/main/java/com/android/volley/NetworkResponse.java b/app/src/main/java/com/android/volley/NetworkResponse.java new file mode 100644 index 0000000000..c200a26269 --- /dev/null +++ b/app/src/main/java/com/android/volley/NetworkResponse.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley; + +import java.util.Collections; +import java.util.Map; + +import org.apache.http.HttpStatus; + +/** + * Data and headers returned from {@link Network#performRequest(Request)}. + */ +public class NetworkResponse { + /** + * Creates a new network response. + * @param statusCode the HTTP status code + * @param data Response body + * @param headers Headers returned with this response, or null for none + * @param notModified True if the server returned a 304 and the data was already in cache + */ + public NetworkResponse(int statusCode, byte[] data, Map headers, + boolean notModified) { + this.statusCode = statusCode; + this.data = data; + this.headers = headers; + this.notModified = notModified; + } + + public NetworkResponse(byte[] data) { + this(HttpStatus.SC_OK, data, Collections.emptyMap(), false); + } + + public NetworkResponse(byte[] data, Map headers) { + this(HttpStatus.SC_OK, data, headers, false); + } + + /** The HTTP status code. */ + public final int statusCode; + + /** Raw data from this response. */ + public final byte[] data; + + /** Response headers. */ + public final Map headers; + + /** True if the server returned a 304 (Not Modified). */ + public final boolean notModified; +} \ No newline at end of file diff --git a/app/src/main/java/com/android/volley/NoConnectionError.java b/app/src/main/java/com/android/volley/NoConnectionError.java new file mode 100644 index 0000000000..fc231562ad --- /dev/null +++ b/app/src/main/java/com/android/volley/NoConnectionError.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley; + +/** + * Error indicating that no connection could be established when performing a Volley request. + */ +@SuppressWarnings("serial") +public class NoConnectionError extends NetworkError { + public NoConnectionError() { + super(); + } + + public NoConnectionError(Throwable reason) { + super(reason); + } +} diff --git a/app/src/main/java/com/android/volley/ParseError.java b/app/src/main/java/com/android/volley/ParseError.java new file mode 100644 index 0000000000..81f32e07c3 --- /dev/null +++ b/app/src/main/java/com/android/volley/ParseError.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley; + + +/** + * Indicates that the server's response could not be parsed. + */ +@SuppressWarnings("serial") +public class ParseError extends VolleyError { + public ParseError() { } + + public ParseError(NetworkResponse networkResponse) { + super(networkResponse); + } + + public ParseError(Throwable cause) { + super(cause); + } +} diff --git a/app/src/main/java/com/android/volley/Request.java b/app/src/main/java/com/android/volley/Request.java new file mode 100644 index 0000000000..a053043733 --- /dev/null +++ b/app/src/main/java/com/android/volley/Request.java @@ -0,0 +1,543 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.Collections; +import java.util.Map; + +import android.net.TrafficStats; +import android.net.Uri; +import android.os.Handler; +import android.os.Looper; +import android.os.SystemClock; +import android.text.TextUtils; + +import com.android.volley.VolleyLog.MarkerLog; + +/** + * Base class for all network requests. + * + * @param The type of parsed response this request expects. + */ +public abstract class Request implements Comparable> { + + /** + * Default encoding for POST or PUT parameters. See {@link #getParamsEncoding()}. + */ + private static final String DEFAULT_PARAMS_ENCODING = "UTF-8"; + + /** + * Supported request methods. + */ + public interface Method { + int DEPRECATED_GET_OR_POST = -1; + int GET = 0; + int POST = 1; + int PUT = 2; + int DELETE = 3; + } + + /** An event log tracing the lifetime of this request; for debugging. */ + private final MarkerLog mEventLog = MarkerLog.ENABLED ? new MarkerLog() : null; + + /** Request method of this request. Currently supports GET, POST, PUT, and DELETE. */ + private final int mMethod; + + /** URL of this request. */ + private final String mUrl; + + /** Default tag for {@link TrafficStats}. */ + private final int mDefaultTrafficStatsTag; + + /** Listener interface for errors. */ + private final Response.ErrorListener mErrorListener; + + /** Sequence number of this request, used to enforce FIFO ordering. */ + private Integer mSequence; + + /** The request queue this request is associated with. */ + private RequestQueue mRequestQueue; + + /** Whether or not responses to this request should be cached. */ + private boolean mShouldCache = true; + + /** Whether or not this request has been canceled. */ + private boolean mCanceled = false; + + /** Whether or not a response has been delivered for this request yet. */ + private boolean mResponseDelivered = false; + + // A cheap variant of request tracing used to dump slow requests. + private long mRequestBirthTime = 0; + + /** Threshold at which we should log the request (even when debug logging is not enabled). */ + private static final long SLOW_REQUEST_THRESHOLD_MS = 3000; + + /** The retry policy for this request. */ + private RetryPolicy mRetryPolicy; + + /** + * When a request can be retrieved from cache but must be refreshed from + * the network, the cache entry will be stored here so that in the event of + * a "Not Modified" response, we can be sure it hasn't been evicted from cache. + */ + private Cache.Entry mCacheEntry = null; + + /** An opaque token tagging this request; used for bulk cancellation. */ + private Object mTag; + + /** + * Creates a new request with the given URL and error listener. Note that + * the normal response listener is not provided here as delivery of responses + * is provided by subclasses, who have a better idea of how to deliver an + * already-parsed response. + * + * @deprecated Use {@link #Request(int, String, com.android.volley.Response.ErrorListener)}. + */ + public Request(String url, Response.ErrorListener listener) { + this(Method.DEPRECATED_GET_OR_POST, url, listener); + } + + /** + * Creates a new request with the given method (one of the values from {@link Method}), + * URL, and error listener. Note that the normal response listener is not provided here as + * delivery of responses is provided by subclasses, who have a better idea of how to deliver + * an already-parsed response. + */ + public Request(int method, String url, Response.ErrorListener listener) { + mMethod = method; + mUrl = url; + mErrorListener = listener; + setRetryPolicy(new DefaultRetryPolicy()); + + mDefaultTrafficStatsTag = TextUtils.isEmpty(url) ? 0: Uri.parse(url).getHost().hashCode(); + } + + /** + * Return the method for this request. Can be one of the values in {@link Method}. + */ + public int getMethod() { + return mMethod; + } + + /** + * Set a tag on this request. Can be used to cancel all requests with this + * tag by {@link RequestQueue#cancelAll(Object)}. + */ + public void setTag(Object tag) { + mTag = tag; + } + + /** + * Returns this request's tag. + * @see Request#setTag(Object) + */ + public Object getTag() { + return mTag; + } + + /** + * @return A tag for use with {@link TrafficStats#setThreadStatsTag(int)} + */ + public int getTrafficStatsTag() { + return mDefaultTrafficStatsTag; + } + + /** + * Sets the retry policy for this request. + */ + public void setRetryPolicy(RetryPolicy retryPolicy) { + mRetryPolicy = retryPolicy; + } + + /** + * Adds an event to this request's event log; for debugging. + */ + public void addMarker(String tag) { + if (MarkerLog.ENABLED) { + mEventLog.add(tag, Thread.currentThread().getId()); + } else if (mRequestBirthTime == 0) { + mRequestBirthTime = SystemClock.elapsedRealtime(); + } + } + + /** + * Notifies the request queue that this request has finished (successfully or with error). + * + *

Also dumps all events from this request's event log; for debugging.

+ */ + void finish(final String tag) { + if (mRequestQueue != null) { + mRequestQueue.finish(this); + } + if (MarkerLog.ENABLED) { + final long threadId = Thread.currentThread().getId(); + if (Looper.myLooper() != Looper.getMainLooper()) { + // If we finish marking off of the main thread, we need to + // actually do it on the main thread to ensure correct ordering. + Handler mainThread = new Handler(Looper.getMainLooper()); + mainThread.post(new Runnable() { + @Override + public void run() { + mEventLog.add(tag, threadId); + mEventLog.finish(this.toString()); + } + }); + return; + } + + mEventLog.add(tag, threadId); + mEventLog.finish(this.toString()); + } else { + long requestTime = SystemClock.elapsedRealtime() - mRequestBirthTime; + if (requestTime >= SLOW_REQUEST_THRESHOLD_MS) { + VolleyLog.d("%d ms: %s", requestTime, this.toString()); + } + } + } + + /** + * Associates this request with the given queue. The request queue will be notified when this + * request has finished. + */ + public void setRequestQueue(RequestQueue requestQueue) { + mRequestQueue = requestQueue; + } + + /** + * Sets the sequence number of this request. Used by {@link RequestQueue}. + */ + public final void setSequence(int sequence) { + mSequence = sequence; + } + + /** + * Returns the sequence number of this request. + */ + public final int getSequence() { + if (mSequence == null) { + throw new IllegalStateException("getSequence called before setSequence"); + } + return mSequence; + } + + /** + * Returns the URL of this request. + */ + public String getUrl() { + return mUrl; + } + + /** + * Returns the cache key for this request. By default, this is the URL. + */ + public String getCacheKey() { + return getUrl(); + } + + /** + * Annotates this request with an entry retrieved for it from cache. + * Used for cache coherency support. + */ + public void setCacheEntry(Cache.Entry entry) { + mCacheEntry = entry; + } + + /** + * Returns the annotated cache entry, or null if there isn't one. + */ + public Cache.Entry getCacheEntry() { + return mCacheEntry; + } + + /** + * Mark this request as canceled. No callback will be delivered. + */ + public void cancel() { + mCanceled = true; + } + + /** + * Returns true if this request has been canceled. + */ + public boolean isCanceled() { + return mCanceled; + } + + /** + * Returns a list of extra HTTP headers to go along with this request. Can + * throw {@link AuthFailureError} as authentication may be required to + * provide these values. + * @throws AuthFailureError In the event of auth failure + */ + public Map getHeaders() throws AuthFailureError { + return Collections.emptyMap(); + } + + /** + * Returns a Map of POST parameters to be used for this request, or null if + * a simple GET should be used. Can throw {@link AuthFailureError} as + * authentication may be required to provide these values. + * + *

Note that only one of getPostParams() and getPostBody() can return a non-null + * value.

+ * @throws AuthFailureError In the event of auth failure + * + * @deprecated Use {@link #getParams()} instead. + */ + protected Map getPostParams() throws AuthFailureError { + return getParams(); + } + + /** + * Returns which encoding should be used when converting POST parameters returned by + * {@link #getPostParams()} into a raw POST body. + * + *

This controls both encodings: + *

    + *
  1. The string encoding used when converting parameter names and values into bytes prior + * to URL encoding them.
  2. + *
  3. The string encoding used when converting the URL encoded parameters into a raw + * byte array.
  4. + *
+ * + * @deprecated Use {@link #getParamsEncoding()} instead. + */ + protected String getPostParamsEncoding() { + return getParamsEncoding(); + } + + /** + * @deprecated Use {@link #getBodyContentType()} instead. + */ + public String getPostBodyContentType() { + return getBodyContentType(); + } + + /** + * Returns the raw POST body to be sent. + * + * @throws AuthFailureError In the event of auth failure + * + * @deprecated Use {@link #getBody()} instead. + */ + public byte[] getPostBody() throws AuthFailureError { + // Note: For compatibility with legacy clients of volley, this implementation must remain + // here instead of simply calling the getBody() function because this function must + // call getPostParams() and getPostParamsEncoding() since legacy clients would have + // overridden these two member functions for POST requests. + Map postParams = getPostParams(); + if (postParams != null && postParams.size() > 0) { + return encodeParameters(postParams, getPostParamsEncoding()); + } + return null; + } + + /** + * Returns a Map of parameters to be used for a POST or PUT request. Can throw + * {@link AuthFailureError} as authentication may be required to provide these values. + * + *

Note that you can directly override {@link #getBody()} for custom data.

+ * + * @throws AuthFailureError in the event of auth failure + */ + protected Map getParams() throws AuthFailureError { + return null; + } + + /** + * Returns which encoding should be used when converting POST or PUT parameters returned by + * {@link #getParams()} into a raw POST or PUT body. + * + *

This controls both encodings: + *

    + *
  1. The string encoding used when converting parameter names and values into bytes prior + * to URL encoding them.
  2. + *
  3. The string encoding used when converting the URL encoded parameters into a raw + * byte array.
  4. + *
+ */ + protected String getParamsEncoding() { + return DEFAULT_PARAMS_ENCODING; + } + + public String getBodyContentType() { + return "application/x-www-form-urlencoded; charset=" + getParamsEncoding(); + } + + /** + * Returns the raw POST or PUT body to be sent. + * + * @throws AuthFailureError in the event of auth failure + */ + public byte[] getBody() throws AuthFailureError { + Map params = getParams(); + if (params != null && params.size() > 0) { + return encodeParameters(params, getParamsEncoding()); + } + return null; + } + + /** + * Converts params into an application/x-www-form-urlencoded encoded string. + */ + private byte[] encodeParameters(Map params, String paramsEncoding) { + StringBuilder encodedParams = new StringBuilder(); + try { + for (Map.Entry entry : params.entrySet()) { + encodedParams.append(URLEncoder.encode(entry.getKey(), paramsEncoding)); + encodedParams.append('='); + encodedParams.append(URLEncoder.encode(entry.getValue(), paramsEncoding)); + encodedParams.append('&'); + } + return encodedParams.toString().getBytes(paramsEncoding); + } catch (UnsupportedEncodingException uee) { + throw new RuntimeException("Encoding not supported: " + paramsEncoding, uee); + } + } + + /** + * Set whether or not responses to this request should be cached. + */ + public final void setShouldCache(boolean shouldCache) { + mShouldCache = shouldCache; + } + + /** + * Returns true if responses to this request should be cached. + */ + public final boolean shouldCache() { + return mShouldCache; + } + + /** + * Priority values. Requests will be processed from higher priorities to + * lower priorities, in FIFO order. + */ + public enum Priority { + LOW, + NORMAL, + HIGH, + IMMEDIATE + } + + /** + * Returns the {@link Priority} of this request; {@link Priority#NORMAL} by default. + */ + public Priority getPriority() { + return Priority.NORMAL; + } + + /** + * Returns the socket timeout in milliseconds per retry attempt. (This value can be changed + * per retry attempt if a backoff is specified via backoffTimeout()). If there are no retry + * attempts remaining, this will cause delivery of a {@link TimeoutError} error. + */ + public final int getTimeoutMs() { + return mRetryPolicy.getCurrentTimeout(); + } + + /** + * Returns the retry policy that should be used for this request. + */ + public RetryPolicy getRetryPolicy() { + return mRetryPolicy; + } + + /** + * Mark this request as having a response delivered on it. This can be used + * later in the request's lifetime for suppressing identical responses. + */ + public void markDelivered() { + mResponseDelivered = true; + } + + /** + * Returns true if this request has had a response delivered for it. + */ + public boolean hasHadResponseDelivered() { + return mResponseDelivered; + } + + /** + * Subclasses must implement this to parse the raw network response + * and return an appropriate response type. This method will be + * called from a worker thread. The response will not be delivered + * if you return null. + * @param response Response from the network + * @return The parsed response, or null in the case of an error + */ + abstract protected Response parseNetworkResponse(NetworkResponse response); + + /** + * Subclasses can override this method to parse 'networkError' and return a more specific error. + * + *

The default implementation just returns the passed 'networkError'.

+ * + * @param volleyError the error retrieved from the network + * @return an NetworkError augmented with additional information + */ + protected VolleyError parseNetworkError(VolleyError volleyError) { + return volleyError; + } + + /** + * Subclasses must implement this to perform delivery of the parsed + * response to their listeners. The given response is guaranteed to + * be non-null; responses that fail to parse are not delivered. + * @param response The parsed response returned by + * {@link #parseNetworkResponse(NetworkResponse)} + */ + abstract protected void deliverResponse(T response); + + /** + * Delivers error message to the ErrorListener that the Request was + * initialized with. + * + * @param error Error details + */ + public void deliverError(VolleyError error) { + if (mErrorListener != null) { + mErrorListener.onErrorResponse(error); + } + } + + /** + * Our comparator sorts from high to low priority, and secondarily by + * sequence number to provide FIFO ordering. + */ + @Override + public int compareTo(Request other) { + Priority left = this.getPriority(); + Priority right = other.getPriority(); + + // High-priority requests are "lesser" so they are sorted to the front. + // Equal priorities are sorted by sequence number to provide FIFO ordering. + return left == right ? + this.mSequence - other.mSequence : + right.ordinal() - left.ordinal(); + } + + @Override + public String toString() { + String trafficStatsTag = "0x" + Integer.toHexString(getTrafficStatsTag()); + return (mCanceled ? "[X] " : "[ ] ") + getUrl() + " " + trafficStatsTag + " " + + getPriority() + " " + mSequence; + } +} diff --git a/app/src/main/java/com/android/volley/RequestQueue.java b/app/src/main/java/com/android/volley/RequestQueue.java new file mode 100644 index 0000000000..94898f479b --- /dev/null +++ b/app/src/main/java/com/android/volley/RequestQueue.java @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Map; +import java.util.Queue; +import java.util.Set; +import java.util.concurrent.PriorityBlockingQueue; +import java.util.concurrent.atomic.AtomicInteger; + +import android.os.Handler; +import android.os.Looper; + +/** + * A request dispatch queue with a thread pool of dispatchers. + * + * Calling {@link #add(Request)} will enqueue the given Request for dispatch, + * resolving from either cache or network on a worker thread, and then delivering + * a parsed response on the main thread. + */ +@SuppressWarnings("rawtypes") +public class RequestQueue { + + /** Used for generating monotonically-increasing sequence numbers for requests. */ + private AtomicInteger mSequenceGenerator = new AtomicInteger(); + + /** + * Staging area for requests that already have a duplicate request in flight. + * + *
    + *
  • containsKey(cacheKey) indicates that there is a request in flight for the given cache + * key.
  • + *
  • get(cacheKey) returns waiting requests for the given cache key. The in flight request + * is not contained in that list. Is null if no requests are staged.
  • + *
+ */ + private final Map> mWaitingRequests = + new HashMap>(); + + /** + * The set of all requests currently being processed by this RequestQueue. A Request + * will be in this set if it is waiting in any queue or currently being processed by + * any dispatcher. + */ + private final Set mCurrentRequests = new HashSet(); + + /** The cache triage queue. */ + private final PriorityBlockingQueue mCacheQueue = + new PriorityBlockingQueue(); + + /** The queue of requests that are actually going out to the network. */ + private final PriorityBlockingQueue mNetworkQueue = + new PriorityBlockingQueue(); + + /** Number of network request dispatcher threads to start. */ + private static final int DEFAULT_NETWORK_THREAD_POOL_SIZE = 4; + + /** Cache interface for retrieving and storing respones. */ + private final Cache mCache; + + /** Network interface for performing requests. */ + private final Network mNetwork; + + /** Response delivery mechanism. */ + private final ResponseDelivery mDelivery; + + /** The network dispatchers. */ + private NetworkDispatcher[] mDispatchers; + + /** The cache dispatcher. */ + private CacheDispatcher mCacheDispatcher; + + /** + * Creates the worker pool. Processing will not begin until {@link #start()} is called. + * + * @param cache A Cache to use for persisting responses to disk + * @param network A Network interface for performing HTTP requests + * @param threadPoolSize Number of network dispatcher threads to create + * @param delivery A ResponseDelivery interface for posting responses and errors + */ + public RequestQueue(Cache cache, Network network, int threadPoolSize, + ResponseDelivery delivery) { + mCache = cache; + mNetwork = network; + mDispatchers = new NetworkDispatcher[threadPoolSize]; + mDelivery = delivery; + } + + /** + * Creates the worker pool. Processing will not begin until {@link #start()} is called. + * + * @param cache A Cache to use for persisting responses to disk + * @param network A Network interface for performing HTTP requests + * @param threadPoolSize Number of network dispatcher threads to create + */ + public RequestQueue(Cache cache, Network network, int threadPoolSize) { + this(cache, network, threadPoolSize, + new ExecutorDelivery(new Handler(Looper.getMainLooper()))); + } + + /** + * Creates the worker pool. Processing will not begin until {@link #start()} is called. + * + * @param cache A Cache to use for persisting responses to disk + * @param network A Network interface for performing HTTP requests + */ + public RequestQueue(Cache cache, Network network) { + this(cache, network, DEFAULT_NETWORK_THREAD_POOL_SIZE); + } + + /** + * Starts the dispatchers in this queue. + */ + public void start() { + stop(); // Make sure any currently running dispatchers are stopped. + // Create the cache dispatcher and start it. + mCacheDispatcher = new CacheDispatcher(mCacheQueue, mNetworkQueue, mCache, mDelivery); + mCacheDispatcher.start(); + + // Create network dispatchers (and corresponding threads) up to the pool size. + for (int i = 0; i < mDispatchers.length; i++) { + NetworkDispatcher networkDispatcher = new NetworkDispatcher(mNetworkQueue, mNetwork, + mCache, mDelivery); + mDispatchers[i] = networkDispatcher; + networkDispatcher.start(); + } + } + + /** + * Stops the cache and network dispatchers. + */ + public void stop() { + if (mCacheDispatcher != null) { + mCacheDispatcher.quit(); + } + for (int i = 0; i < mDispatchers.length; i++) { + if (mDispatchers[i] != null) { + mDispatchers[i].quit(); + } + } + } + + /** + * Gets a sequence number. + */ + public int getSequenceNumber() { + return mSequenceGenerator.incrementAndGet(); + } + + /** + * Gets the {@link Cache} instance being used. + */ + public Cache getCache() { + return mCache; + } + + /** + * A simple predicate or filter interface for Requests, for use by + * {@link RequestQueue#cancelAll(RequestFilter)}. + */ + public interface RequestFilter { + public boolean apply(Request request); + } + + /** + * Cancels all requests in this queue for which the given filter applies. + * @param filter The filtering function to use + */ + public void cancelAll(RequestFilter filter) { + synchronized (mCurrentRequests) { + for (Request request : mCurrentRequests) { + if (filter.apply(request)) { + request.cancel(); + } + } + } + } + + /** + * Cancels all requests in this queue with the given tag. Tag must be non-null + * and equality is by identity. + */ + public void cancelAll(final Object tag) { + if (tag == null) { + throw new IllegalArgumentException("Cannot cancelAll with a null tag"); + } + cancelAll(new RequestFilter() { + @Override + public boolean apply(Request request) { + return request.getTag() == tag; + } + }); + } + + /** + * Adds a Request to the dispatch queue. + * @param request The request to service + * @return The passed-in request + */ + public Request add(Request request) { + // Tag the request as belonging to this queue and add it to the set of current requests. + request.setRequestQueue(this); + synchronized (mCurrentRequests) { + mCurrentRequests.add(request); + } + + // Process requests in the order they are added. + request.setSequence(getSequenceNumber()); + request.addMarker("add-to-queue"); + + // If the request is uncacheable, skip the cache queue and go straight to the network. + if (!request.shouldCache()) { + mNetworkQueue.add(request); + return request; + } + + // Insert request into stage if there's already a request with the same cache key in flight. + synchronized (mWaitingRequests) { + String cacheKey = request.getCacheKey(); + if (mWaitingRequests.containsKey(cacheKey)) { + // There is already a request in flight. Queue up. + Queue stagedRequests = mWaitingRequests.get(cacheKey); + if (stagedRequests == null) { + stagedRequests = new LinkedList(); + } + stagedRequests.add(request); + mWaitingRequests.put(cacheKey, stagedRequests); + if (VolleyLog.DEBUG) { + VolleyLog.v("Request for cacheKey=%s is in flight, putting on hold.", cacheKey); + } + } else { + // Insert 'null' queue for this cacheKey, indicating there is now a request in + // flight. + mWaitingRequests.put(cacheKey, null); + mCacheQueue.add(request); + } + return request; + } + } + + /** + * Called from {@link Request#finish(String)}, indicating that processing of the given request + * has finished. + * + *

Releases waiting requests for request.getCacheKey() if + * request.shouldCache().

+ */ + void finish(Request request) { + // Remove from the set of requests currently being processed. + synchronized (mCurrentRequests) { + mCurrentRequests.remove(request); + } + + if (request.shouldCache()) { + synchronized (mWaitingRequests) { + String cacheKey = request.getCacheKey(); + Queue waitingRequests = mWaitingRequests.remove(cacheKey); + if (waitingRequests != null) { + if (VolleyLog.DEBUG) { + VolleyLog.v("Releasing %d waiting requests for cacheKey=%s.", + waitingRequests.size(), cacheKey); + } + // Process all queued up requests. They won't be considered as in flight, but + // that's not a problem as the cache has been primed by 'request'. + mCacheQueue.addAll(waitingRequests); + } + } + } + } +} diff --git a/app/src/main/java/com/android/volley/Response.java b/app/src/main/java/com/android/volley/Response.java new file mode 100644 index 0000000000..1165595da6 --- /dev/null +++ b/app/src/main/java/com/android/volley/Response.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley; + +/** + * Encapsulates a parsed response for delivery. + * + * @param Parsed type of this response + */ +public class Response { + + /** Callback interface for delivering parsed responses. */ + public interface Listener { + /** Called when a response is received. */ + public void onResponse(T response); + } + + /** Callback interface for delivering error responses. */ + public interface ErrorListener { + /** + * Callback method that an error has been occurred with the + * provided error code and optional user-readable message. + */ + public void onErrorResponse(VolleyError error); + } + + /** Returns a successful response containing the parsed result. */ + public static Response success(T result, Cache.Entry cacheEntry) { + return new Response(result, cacheEntry); + } + + /** + * Returns a failed response containing the given error code and an optional + * localized message displayed to the user. + */ + public static Response error(VolleyError error) { + return new Response(error); + } + + /** Parsed response, or null in the case of error. */ + public final T result; + + /** Cache metadata for this response, or null in the case of error. */ + public final Cache.Entry cacheEntry; + + /** Detailed error information if errorCode != OK. */ + public final VolleyError error; + + /** True if this response was a soft-expired one and a second one MAY be coming. */ + public boolean intermediate = false; + + /** + * Returns whether this response is considered successful. + */ + public boolean isSuccess() { + return error == null; + } + + + private Response(T result, Cache.Entry cacheEntry) { + this.result = result; + this.cacheEntry = cacheEntry; + this.error = null; + } + + private Response(VolleyError error) { + this.result = null; + this.cacheEntry = null; + this.error = error; + } +} diff --git a/app/src/main/java/com/android/volley/ResponseDelivery.java b/app/src/main/java/com/android/volley/ResponseDelivery.java new file mode 100644 index 0000000000..87706afcb7 --- /dev/null +++ b/app/src/main/java/com/android/volley/ResponseDelivery.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley; + +public interface ResponseDelivery { + /** + * Parses a response from the network or cache and delivers it. + */ + public void postResponse(Request request, Response response); + + /** + * Parses a response from the network or cache and delivers it. The provided + * Runnable will be executed after delivery. + */ + public void postResponse(Request request, Response response, Runnable runnable); + + /** + * Posts an error for the given request. + */ + public void postError(Request request, VolleyError error); +} diff --git a/app/src/main/java/com/android/volley/RetryPolicy.java b/app/src/main/java/com/android/volley/RetryPolicy.java new file mode 100644 index 0000000000..0dd198b206 --- /dev/null +++ b/app/src/main/java/com/android/volley/RetryPolicy.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley; + +/** + * Retry policy for a request. + */ +public interface RetryPolicy { + + /** + * Returns the current timeout (used for logging). + */ + public int getCurrentTimeout(); + + /** + * Returns the current retry count (used for logging). + */ + public int getCurrentRetryCount(); + + /** + * Prepares for the next retry by applying a backoff to the timeout. + * @param error The error code of the last attempt. + * @throws VolleyError In the event that the retry could not be performed (for example if we + * ran out of attempts), the passed in error is thrown. + */ + public void retry(VolleyError error) throws VolleyError; +} diff --git a/app/src/main/java/com/android/volley/ServerError.java b/app/src/main/java/com/android/volley/ServerError.java new file mode 100644 index 0000000000..d76f979aae --- /dev/null +++ b/app/src/main/java/com/android/volley/ServerError.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley; + + +/** + * Indicates that the error responded with an error response. + */ +@SuppressWarnings("serial") +public class ServerError extends VolleyError { + public ServerError(NetworkResponse networkResponse) { + super(networkResponse); + } + + public ServerError() { + super(); + } +} diff --git a/app/src/main/java/com/android/volley/TimeoutError.java b/app/src/main/java/com/android/volley/TimeoutError.java new file mode 100644 index 0000000000..0b5d6acb79 --- /dev/null +++ b/app/src/main/java/com/android/volley/TimeoutError.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley; + +/** + * Indicates that the connection or the socket timed out. + */ +@SuppressWarnings("serial") +public class TimeoutError extends VolleyError { } diff --git a/app/src/main/java/com/android/volley/VolleyError.java b/app/src/main/java/com/android/volley/VolleyError.java new file mode 100644 index 0000000000..4f7b883dbc --- /dev/null +++ b/app/src/main/java/com/android/volley/VolleyError.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley; + +/** + * Exception style class encapsulating Volley errors + */ +@SuppressWarnings("serial") +public class VolleyError extends Exception { + public final NetworkResponse networkResponse; + + public VolleyError() { + networkResponse = null; + } + + public VolleyError(NetworkResponse response) { + networkResponse = response; + } + + public VolleyError(String exceptionMessage) { + super(exceptionMessage); + networkResponse = null; + } + + public VolleyError(String exceptionMessage, Throwable reason) { + super(exceptionMessage, reason); + networkResponse = null; + } + + public VolleyError(Throwable cause) { + super(cause); + networkResponse = null; + } +} diff --git a/app/src/main/java/com/android/volley/VolleyLog.java b/app/src/main/java/com/android/volley/VolleyLog.java new file mode 100644 index 0000000000..c3ad580050 --- /dev/null +++ b/app/src/main/java/com/android/volley/VolleyLog.java @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import android.os.SystemClock; +import android.util.Log; + +/** Logging helper class. */ +public class VolleyLog { + public static String TAG = "Volley"; + + public static boolean DEBUG = Log.isLoggable(TAG, Log.VERBOSE); + + /** + * Customize the log tag for your application, so that other apps + * using Volley don't mix their logs with yours. + *
+ * Enable the log property for your tag before starting your app: + *
+ * {@code adb shell setprop log.tag.<tag>} + */ + public static void setTag(String tag) { + d("Changing log tag to %s", tag); + TAG = tag; + + // Reinitialize the DEBUG "constant" + DEBUG = Log.isLoggable(TAG, Log.VERBOSE); + } + + public static void v(String format, Object... args) { + if (DEBUG) { + Log.v(TAG, buildMessage(format, args)); + } + } + + public static void d(String format, Object... args) { + Log.d(TAG, buildMessage(format, args)); + } + + public static void e(String format, Object... args) { + Log.e(TAG, buildMessage(format, args)); + } + + public static void e(Throwable tr, String format, Object... args) { + Log.e(TAG, buildMessage(format, args), tr); + } + + public static void wtf(String format, Object... args) { + Log.wtf(TAG, buildMessage(format, args)); + } + + public static void wtf(Throwable tr, String format, Object... args) { + Log.wtf(TAG, buildMessage(format, args), tr); + } + + /** + * Formats the caller's provided message and prepends useful info like + * calling thread ID and method name. + */ + private static String buildMessage(String format, Object... args) { + String msg = (args == null) ? format : String.format(Locale.US, format, args); + StackTraceElement[] trace = new Throwable().fillInStackTrace().getStackTrace(); + + String caller = ""; + // Walk up the stack looking for the first caller outside of VolleyLog. + // It will be at least two frames up, so start there. + for (int i = 2; i < trace.length; i++) { + Class clazz = trace[i].getClass(); + if (!clazz.equals(VolleyLog.class)) { + String callingClass = trace[i].getClassName(); + callingClass = callingClass.substring(callingClass.lastIndexOf('.') + 1); + callingClass = callingClass.substring(callingClass.lastIndexOf('$') + 1); + + caller = callingClass + "." + trace[i].getMethodName(); + break; + } + } + return String.format(Locale.US, "[%d] %s: %s", + Thread.currentThread().getId(), caller, msg); + } + + /** + * A simple event log with records containing a name, thread ID, and timestamp. + */ + static class MarkerLog { + public static final boolean ENABLED = VolleyLog.DEBUG; + + /** Minimum duration from first marker to last in an marker log to warrant logging. */ + private static final long MIN_DURATION_FOR_LOGGING_MS = 0; + + private static class Marker { + public final String name; + public final long thread; + public final long time; + + public Marker(String name, long thread, long time) { + this.name = name; + this.thread = thread; + this.time = time; + } + } + + private final List mMarkers = new ArrayList(); + private boolean mFinished = false; + + /** Adds a marker to this log with the specified name. */ + public synchronized void add(String name, long threadId) { + if (mFinished) { + throw new IllegalStateException("Marker added to finished log"); + } + + mMarkers.add(new Marker(name, threadId, SystemClock.elapsedRealtime())); + } + + /** + * Closes the log, dumping it to logcat if the time difference between + * the first and last markers is greater than {@link #MIN_DURATION_FOR_LOGGING_MS}. + * @param header Header string to print above the marker log. + */ + public synchronized void finish(String header) { + mFinished = true; + + long duration = getTotalDuration(); + if (duration <= MIN_DURATION_FOR_LOGGING_MS) { + return; + } + + long prevTime = mMarkers.get(0).time; + d("(%-4d ms) %s", duration, header); + for (Marker marker : mMarkers) { + long thisTime = marker.time; + d("(+%-4d) [%2d] %s", (thisTime - prevTime), marker.thread, marker.name); + prevTime = thisTime; + } + } + + @Override + protected void finalize() throws Throwable { + // Catch requests that have been collected (and hence end-of-lifed) + // but had no debugging output printed for them. + if (!mFinished) { + finish("Request on the loose"); + e("Marker log finalized without finish() - uncaught exit point for request"); + } + } + + /** Returns the time difference between the first and last events in this log. */ + private long getTotalDuration() { + if (mMarkers.size() == 0) { + return 0; + } + + long first = mMarkers.get(0).time; + long last = mMarkers.get(mMarkers.size() - 1).time; + return last - first; + } + } +} diff --git a/app/src/main/java/com/android/volley/toolbox/AndroidAuthenticator.java b/app/src/main/java/com/android/volley/toolbox/AndroidAuthenticator.java new file mode 100644 index 0000000000..b5f43ec060 --- /dev/null +++ b/app/src/main/java/com/android/volley/toolbox/AndroidAuthenticator.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley.toolbox; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.accounts.AccountManagerFuture; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; + +import com.android.volley.AuthFailureError; + +/** + * An Authenticator that uses {@link AccountManager} to get auth + * tokens of a specified type for a specified account. + */ +public class AndroidAuthenticator implements Authenticator { + private final Context mContext; + private final Account mAccount; + private final String mAuthTokenType; + private final boolean mNotifyAuthFailure; + + /** + * Creates a new authenticator. + * @param context Context for accessing AccountManager + * @param account Account to authenticate as + * @param authTokenType Auth token type passed to AccountManager + */ + public AndroidAuthenticator(Context context, Account account, String authTokenType) { + this(context, account, authTokenType, false); + } + + /** + * Creates a new authenticator. + * @param context Context for accessing AccountManager + * @param account Account to authenticate as + * @param authTokenType Auth token type passed to AccountManager + * @param notifyAuthFailure Whether to raise a notification upon auth failure + */ + public AndroidAuthenticator(Context context, Account account, String authTokenType, + boolean notifyAuthFailure) { + mContext = context; + mAccount = account; + mAuthTokenType = authTokenType; + mNotifyAuthFailure = notifyAuthFailure; + } + + /** + * Returns the Account being used by this authenticator. + */ + public Account getAccount() { + return mAccount; + } + + @Override + public String getAuthToken() throws AuthFailureError { + final AccountManager accountManager = AccountManager.get(mContext); + AccountManagerFuture future = accountManager.getAuthToken(mAccount, + mAuthTokenType, mNotifyAuthFailure, null, null); + Bundle result; + try { + result = future.getResult(); + } catch (Exception e) { + throw new AuthFailureError("Error while retrieving auth token", e); + } + String authToken = null; + if (future.isDone() && !future.isCancelled()) { + if (result.containsKey(AccountManager.KEY_INTENT)) { + Intent intent = result.getParcelable(AccountManager.KEY_INTENT); + throw new AuthFailureError(intent); + } + authToken = result.getString(AccountManager.KEY_AUTHTOKEN); + } + if (authToken == null) { + throw new AuthFailureError("Got null auth token for type: " + mAuthTokenType); + } + + return authToken; + } + + @Override + public void invalidateAuthToken(String authToken) { + AccountManager.get(mContext).invalidateAuthToken(mAccount.type, authToken); + } +} diff --git a/app/src/main/java/com/android/volley/toolbox/Authenticator.java b/app/src/main/java/com/android/volley/toolbox/Authenticator.java new file mode 100644 index 0000000000..d9f5e3c2f2 --- /dev/null +++ b/app/src/main/java/com/android/volley/toolbox/Authenticator.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley.toolbox; + +import com.android.volley.AuthFailureError; + +/** + * An interface for interacting with auth tokens. + */ +public interface Authenticator { + /** + * Synchronously retrieves an auth token. + * + * @throws AuthFailureError If authentication did not succeed + */ + public String getAuthToken() throws AuthFailureError; + + /** + * Invalidates the provided auth token. + */ + public void invalidateAuthToken(String authToken); +} diff --git a/app/src/main/java/com/android/volley/toolbox/BasicNetwork.java b/app/src/main/java/com/android/volley/toolbox/BasicNetwork.java new file mode 100644 index 0000000000..ea3b507d08 --- /dev/null +++ b/app/src/main/java/com/android/volley/toolbox/BasicNetwork.java @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley.toolbox; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.SocketTimeoutException; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.StatusLine; +import org.apache.http.conn.ConnectTimeoutException; +import org.apache.http.impl.cookie.DateUtils; + +import android.os.SystemClock; + +import com.android.volley.AuthFailureError; +import com.android.volley.Cache; +import com.android.volley.Network; +import com.android.volley.NetworkError; +import com.android.volley.NetworkResponse; +import com.android.volley.NoConnectionError; +import com.android.volley.Request; +import com.android.volley.RetryPolicy; +import com.android.volley.ServerError; +import com.android.volley.TimeoutError; +import com.android.volley.VolleyError; +import com.android.volley.VolleyLog; +import com.gh.common.constant.Config; +import com.gh.common.util.GzipUtils; +import com.gh.gamecenter.volley.extended.JsonArrayExtendedRequest; +import com.gh.gamecenter.volley.extended.JsonObjectExtendedRequest; + +/** + * A network performing Volley requests over an {@link HttpStack}. + */ +public class BasicNetwork implements Network { + protected static final boolean DEBUG = VolleyLog.DEBUG; + + private static int SLOW_REQUEST_THRESHOLD_MS = 3000; + + private static int DEFAULT_POOL_SIZE = 4096; + + protected final HttpStack mHttpStack; + + protected final ByteArrayPool mPool; + + /** + * @param httpStack + * HTTP stack to be used + */ + public BasicNetwork(HttpStack httpStack) { + // If a pool isn't passed in, then build a small default pool that will + // give us a lot of + // benefit and not use too much memory. + this(httpStack, new ByteArrayPool(DEFAULT_POOL_SIZE)); + } + + /** + * @param httpStack + * HTTP stack to be used + * @param pool + * a buffer pool that improves GC performance in copy operations + */ + public BasicNetwork(HttpStack httpStack, ByteArrayPool pool) { + mHttpStack = httpStack; + mPool = pool; + } + + @Override + public NetworkResponse performRequest(Request request) + throws VolleyError { + long requestStart = SystemClock.elapsedRealtime(); + while (true) { + HttpResponse httpResponse = null; + byte[] responseContents = null; + Map responseHeaders = new HashMap(); + try { + // Gather headers. + Map headers = new HashMap(); + addCacheHeaders(headers, request.getCacheEntry()); + httpResponse = mHttpStack.performRequest(request, headers); + StatusLine statusLine = httpResponse.getStatusLine(); + int statusCode = statusLine.getStatusCode(); + + responseHeaders = convertHeaders(httpResponse.getAllHeaders()); + // Handle cache validation. + if (statusCode == HttpStatus.SC_NOT_MODIFIED) { + if (request.getUrl().startsWith(Config.HOST + "v2/version")) { + if (request.getCacheEntry() != null) { + return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, + request.getCacheEntry().data, responseHeaders, true); + } else { + return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, + GzipUtils.compressBytes("{}".getBytes()), responseHeaders, true); + } + } else { + return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, + request.getCacheEntry().data, responseHeaders, true); + } + } + + // Some responses such as 204s do not have content. We must + // check. + if (httpResponse.getEntity() != null) { + responseContents = entityToBytes(httpResponse.getEntity()); + } else { + // Add 0 byte response as a way of honestly representing a + // no-content request. + responseContents = new byte[0]; + } + + // if the request is slow, log it. + long requestLifetime = SystemClock.elapsedRealtime() + - requestStart; + logSlowRequests(requestLifetime, request, responseContents, + statusLine); + + if (statusCode != HttpStatus.SC_OK + && statusCode != HttpStatus.SC_NO_CONTENT) { + throw new IOException(); + } + return new NetworkResponse(statusCode, responseContents, + responseHeaders, false); + } catch (SocketTimeoutException e) { + attemptRetryOnException("socket", request, new TimeoutError()); + } catch (ConnectTimeoutException e) { + attemptRetryOnException("connection", request, + new TimeoutError()); + } catch (MalformedURLException e) { + throw new RuntimeException("Bad URL " + request.getUrl(), e); + } catch (IOException e) { + int statusCode = 0; + NetworkResponse networkResponse = null; + if (httpResponse != null) { + statusCode = httpResponse.getStatusLine().getStatusCode(); + } else { + // If there is no network connection, judge whether the url is cached + // If have cached, return cached + Cache.Entry entry = request.getCacheEntry(); + if (entry != null) { + return new NetworkResponse(HttpStatus.SC_OK, + entry.data, entry.responseHeaders, false); + } + // else throw NoConnectionError + throw new NoConnectionError(e); + } + VolleyLog.e("Unexpected response code %d for %s", statusCode, + request.getUrl()); + if (responseContents != null) { + networkResponse = new NetworkResponse(statusCode, + responseContents, responseHeaders, false); + if (statusCode == HttpStatus.SC_UNAUTHORIZED + || statusCode == HttpStatus.SC_FORBIDDEN) { + attemptRetryOnException("auth", request, + new AuthFailureError(networkResponse)); + } else if (statusCode == HttpStatus.SC_NOT_FOUND) { + if (request.getClass().equals(JsonObjectExtendedRequest.class)) { + return new NetworkResponse(HttpStatus.SC_OK, + GzipUtils.compressBytes("{}".getBytes()), responseHeaders, true); + } else if (request.getClass().equals(JsonArrayExtendedRequest.class)) { + return new NetworkResponse(HttpStatus.SC_OK, + GzipUtils.compressBytes("[]".getBytes()), responseHeaders, true); + } else { + // TODO: Only throw ServerError for 5xx status codes. + throw new ServerError(networkResponse); + } + } else { + // TODO: Only throw ServerError for 5xx status codes. + throw new ServerError(networkResponse); + } + } else { + throw new NetworkError(networkResponse); + } + } + } + } + + /** + * Logs requests that took over SLOW_REQUEST_THRESHOLD_MS to complete. + */ + private void logSlowRequests(long requestLifetime, Request request, + byte[] responseContents, StatusLine statusLine) { + if (DEBUG || requestLifetime > SLOW_REQUEST_THRESHOLD_MS) { + VolleyLog + .d("HTTP response for request=<%s> [lifetime=%d], [size=%s], " + + "[rc=%d], [retryCount=%s]", request, + requestLifetime, + responseContents != null ? responseContents.length + : "null", statusLine.getStatusCode(), + request.getRetryPolicy().getCurrentRetryCount()); + } + } + + /** + * Attempts to prepare the request for a retry. If there are no more + * attempts remaining in the request's retry policy, a timeout exception is + * thrown. + * + * @param request + * The request to use. + */ + private static void attemptRetryOnException(String logPrefix, + Request request, VolleyError exception) throws VolleyError { + RetryPolicy retryPolicy = request.getRetryPolicy(); + int oldTimeout = request.getTimeoutMs(); + + try { + retryPolicy.retry(exception); + } catch (VolleyError e) { + request.addMarker(String.format("%s-timeout-giveup [timeout=%s]", + logPrefix, oldTimeout)); + throw e; + } + request.addMarker(String.format("%s-retry [timeout=%s]", logPrefix, + oldTimeout)); + } + + private void addCacheHeaders(Map headers, Cache.Entry entry) { + // If there's no cache entry, we're done. + if (entry == null) { + return; + } + + if (entry.etag != null) { + headers.put("If-None-Match", entry.etag); + } + + if (entry.serverDate > 0) { + Date refTime = new Date(entry.serverDate); + headers.put("If-Modified-Since", DateUtils.formatDate(refTime)); + } + } + + protected void logError(String what, String url, long start) { + long now = SystemClock.elapsedRealtime(); + VolleyLog.v("HTTP ERROR(%s) %d ms to fetch %s", what, (now - start), + url); + } + + /** Reads the contents of HttpEntity into a byte[]. */ + private byte[] entityToBytes(HttpEntity entity) throws IOException, + ServerError { + PoolingByteArrayOutputStream bytes = new PoolingByteArrayOutputStream( + mPool, (int) entity.getContentLength()); + byte[] buffer = null; + try { + InputStream in = entity.getContent(); + if (in == null) { + throw new ServerError(); + } + buffer = mPool.getBuf(1024); + int count; + while ((count = in.read(buffer)) != -1) { + bytes.write(buffer, 0, count); + } + return bytes.toByteArray(); + } finally { + try { + // Close the InputStream and release the resources by + // "consuming the content". + entity.consumeContent(); + } catch (IOException e) { + // This can happen if there was an exception above that left the + // entity in + // an invalid state. + VolleyLog.v("Error occured when calling consumingContent"); + } + mPool.returnBuf(buffer); + bytes.close(); + } + } + + /** + * Converts Headers[] to Map. + */ + private static Map convertHeaders(Header[] headers) { + Map result = new HashMap(); + for (int i = 0; i < headers.length; i++) { + result.put(headers[i].getName(), headers[i].getValue()); + } + return result; + } +} diff --git a/app/src/main/java/com/android/volley/toolbox/ByteArrayPool.java b/app/src/main/java/com/android/volley/toolbox/ByteArrayPool.java new file mode 100644 index 0000000000..af95076ad1 --- /dev/null +++ b/app/src/main/java/com/android/volley/toolbox/ByteArrayPool.java @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley.toolbox; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedList; +import java.util.List; + +/** + * ByteArrayPool is a source and repository of byte[] objects. Its purpose is to + * supply those buffers to consumers who need to use them for a short period of time and then + * dispose of them. Simply creating and disposing such buffers in the conventional manner can + * considerable heap churn and garbage collection delays on Android, which lacks good management of + * short-lived heap objects. It may be advantageous to trade off some memory in the form of a + * permanently allocated pool of buffers in order to gain heap performance improvements; that is + * what this class does. + *

+ * A good candidate user for this class is something like an I/O system that uses large temporary + * byte[] buffers to copy data around. In these use cases, often the consumer wants + * the buffer to be a certain minimum size to ensure good performance (e.g. when copying data chunks + * off of a stream), but doesn't mind if the buffer is larger than the minimum. Taking this into + * account and also to maximize the odds of being able to reuse a recycled buffer, this class is + * free to return buffers larger than the requested size. The caller needs to be able to gracefully + * deal with getting buffers any size over the minimum. + *

+ * If there is not a suitably-sized buffer in its recycling pool when a buffer is requested, this + * class will allocate a new buffer and return it. + *

+ * This class has no special ownership of buffers it creates; the caller is free to take a buffer + * it receives from this pool, use it permanently, and never return it to the pool; additionally, + * it is not harmful to return to this pool a buffer that was allocated elsewhere, provided there + * are no other lingering references to it. + *

+ * This class ensures that the total size of the buffers in its recycling pool never exceeds a + * certain byte limit. When a buffer is returned that would cause the pool to exceed the limit, + * least-recently-used buffers are disposed. + */ +public class ByteArrayPool { + /** The buffer pool, arranged both by last use and by buffer size */ + private List mBuffersByLastUse = new LinkedList(); + private List mBuffersBySize = new ArrayList(64); + + /** The total size of the buffers in the pool */ + private int mCurrentSize = 0; + + /** + * The maximum aggregate size of the buffers in the pool. Old buffers are discarded to stay + * under this limit. + */ + private final int mSizeLimit; + + /** Compares buffers by size */ + protected static final Comparator BUF_COMPARATOR = new Comparator() { + @Override + public int compare(byte[] lhs, byte[] rhs) { + return lhs.length - rhs.length; + } + }; + + /** + * @param sizeLimit the maximum size of the pool, in bytes + */ + public ByteArrayPool(int sizeLimit) { + mSizeLimit = sizeLimit; + } + + /** + * Returns a buffer from the pool if one is available in the requested size, or allocates a new + * one if a pooled one is not available. + * + * @param len the minimum size, in bytes, of the requested buffer. The returned buffer may be + * larger. + * @return a byte[] buffer is always returned. + */ + public synchronized byte[] getBuf(int len) { + for (int i = 0; i < mBuffersBySize.size(); i++) { + byte[] buf = mBuffersBySize.get(i); + if (buf.length >= len) { + mCurrentSize -= buf.length; + mBuffersBySize.remove(i); + mBuffersByLastUse.remove(buf); + return buf; + } + } + return new byte[len]; + } + + /** + * Returns a buffer to the pool, throwing away old buffers if the pool would exceed its allotted + * size. + * + * @param buf the buffer to return to the pool. + */ + public synchronized void returnBuf(byte[] buf) { + if (buf == null || buf.length > mSizeLimit) { + return; + } + mBuffersByLastUse.add(buf); + int pos = Collections.binarySearch(mBuffersBySize, buf, BUF_COMPARATOR); + if (pos < 0) { + pos = -pos - 1; + } + mBuffersBySize.add(pos, buf); + mCurrentSize += buf.length; + trim(); + } + + /** + * Removes buffers from the pool until it is under its size limit. + */ + private synchronized void trim() { + while (mCurrentSize > mSizeLimit) { + byte[] buf = mBuffersByLastUse.remove(0); + mBuffersBySize.remove(buf); + mCurrentSize -= buf.length; + } + } + +} diff --git a/app/src/main/java/com/android/volley/toolbox/ClearCacheRequest.java b/app/src/main/java/com/android/volley/toolbox/ClearCacheRequest.java new file mode 100644 index 0000000000..f61e34e01c --- /dev/null +++ b/app/src/main/java/com/android/volley/toolbox/ClearCacheRequest.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley.toolbox; + +import android.os.Handler; +import android.os.Looper; + +import com.android.volley.Cache; +import com.android.volley.NetworkResponse; +import com.android.volley.Request; +import com.android.volley.Response; + +/** + * A synthetic request used for clearing the cache. + */ +public class ClearCacheRequest extends Request { + private final Cache mCache; + private final Runnable mCallback; + + /** + * Creates a synthetic request for clearing the cache. + * @param cache Cache to clear + * @param callback Callback to make on the main thread once the cache is clear, + * or null for none + */ + public ClearCacheRequest(Cache cache, Runnable callback) { + super(Method.GET, null, null); + mCache = cache; + mCallback = callback; + } + + @Override + public boolean isCanceled() { + // This is a little bit of a hack, but hey, why not. + mCache.clear(); + if (mCallback != null) { + Handler handler = new Handler(Looper.getMainLooper()); + handler.postAtFrontOfQueue(mCallback); + } + return true; + } + + @Override + public Priority getPriority() { + return Priority.IMMEDIATE; + } + + @Override + protected Response parseNetworkResponse(NetworkResponse response) { + return null; + } + + @Override + protected void deliverResponse(Object response) { + } +} diff --git a/app/src/main/java/com/android/volley/toolbox/DiskBasedCache.java b/app/src/main/java/com/android/volley/toolbox/DiskBasedCache.java new file mode 100644 index 0000000000..af2c47d6d1 --- /dev/null +++ b/app/src/main/java/com/android/volley/toolbox/DiskBasedCache.java @@ -0,0 +1,645 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley.toolbox; + +import java.io.EOFException; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; + +import android.os.SystemClock; +import android.util.Log; + +import com.android.volley.Cache; +import com.android.volley.VolleyLog; +import com.gh.common.util.TimestampUtils; + +/** + * Cache implementation that caches files directly onto the hard disk in the + * specified directory. The default disk usage size is 5MB, but is configurable. + */ +public class DiskBasedCache implements Cache { + + /** Map of the Key, CacheHeader pairs */ + private final Map mEntries = new LinkedHashMap( + 16, .75f, true); + + /** Total amount of space currently used by the cache in bytes. */ + private long mTotalSize = 0; + + /** The root directory to use for the cache. */ + private final File mRootDirectory; + + /** The maximum size of the cache in bytes. */ + private final int mMaxCacheSizeInBytes; + + /** Default maximum disk usage in bytes. */ + private static final int DEFAULT_DISK_USAGE_BYTES = 5 * 1024 * 1024; + + /** High water mark percentage for the cache */ + private static final float HYSTERESIS_FACTOR = 0.9f; + + /** Magic number for current version of cache file format. */ + private static final int CACHE_MAGIC = 0x20120504; + + /** + * Constructs an instance of the DiskBasedCache at the specified directory. + * + * @param rootDirectory + * The root directory of the cache. + * @param maxCacheSizeInBytes + * The maximum size of the cache in bytes. + */ + public DiskBasedCache(File rootDirectory, int maxCacheSizeInBytes) { + mRootDirectory = rootDirectory; + mMaxCacheSizeInBytes = maxCacheSizeInBytes; + } + + /** + * Constructs an instance of the DiskBasedCache at the specified directory + * using the default maximum cache size of 5MB. + * + * @param rootDirectory + * The root directory of the cache. + */ + public DiskBasedCache(File rootDirectory) { + this(rootDirectory, DEFAULT_DISK_USAGE_BYTES); + } + + /** + * Clears the cache. Deletes all cached files from disk. + */ + @Override + public synchronized void clear() { + File[] files = mRootDirectory.listFiles(); + if (files != null) { + for (File file : files) { + file.delete(); + } + } + mEntries.clear(); + mTotalSize = 0; + VolleyLog.d("Cache cleared."); + } + + /** + * Returns the cache entry with the specified key if it exists, null + * otherwise. + */ + @Override + public synchronized Entry get(String key) { + CacheHeader entry = mEntries.get(key); + // if the entry does not exist, return. + if (entry == null) { + if (key.contains("timestamp")) { + key = TimestampUtils.removeTimestamp(key); + entry = mEntries.get(key); + if (entry == null) { + return null; + } + } else { + return null; + } + } + File file = getFileForKey(key); + Log.i("result", "key = " + key); + Log.i("result", "name = " + file.getName()); + CountingInputStream cis = null; + try { + cis = new CountingInputStream(new FileInputStream(file)); + CacheHeader.readHeader(cis); // eat header + byte[] data = streamToBytes(cis, + (int) (file.length() - cis.bytesRead)); + return entry.toCacheEntry(data); + } catch (IOException e) { + VolleyLog.d("%s: %s", file.getAbsolutePath(), e.toString()); + remove(key); + return null; + } finally { + if (cis != null) { + try { + cis.close(); + } catch (IOException ioe) { + return null; + } + } + } + } + + public synchronized byte[] getData(String key) { + File file = getFileForKey(key); + CountingInputStream cis = null; + try { + cis = new CountingInputStream(new FileInputStream(file)); + CacheHeader.readHeader(cis); // eat header + return streamToBytes(cis, (int) (file.length() - cis.bytesRead)); + } catch (IOException e) { + VolleyLog.d("%s: %s", file.getAbsolutePath(), e.toString()); + return null; + } finally { + if (cis != null) { + try { + cis.close(); + } catch (IOException ioe) { + return null; + } + } + } + } + + public synchronized void modify(String key, byte[] data) { + File file = getFileForKey(key); + CountingInputStream cis = null; + try { + cis = new CountingInputStream(new FileInputStream(file)); + CacheHeader e = CacheHeader.readHeader(cis); // eat header + Entry entry = e.toCacheEntry(data); + cis.close(); + put(key, entry); + } catch (IOException e) { + VolleyLog.d("%s: %s", file.getAbsolutePath(), e.toString()); + } + } + + /** + * Initializes the DiskBasedCache by scanning for all files currently in the + * specified root directory. Creates the root directory if necessary. + */ + @Override + public synchronized void initialize() { + if (!mRootDirectory.exists()) { + if (!mRootDirectory.mkdirs()) { + VolleyLog.e("Unable to create cache dir %s", + mRootDirectory.getAbsolutePath()); + } + return; + } + + File[] files = mRootDirectory.listFiles(); + if (files == null) { + return; + } + for (File file : files) { + FileInputStream fis = null; + try { + fis = new FileInputStream(file); + CacheHeader entry = CacheHeader.readHeader(fis); + entry.size = file.length(); + putEntry(entry.key, entry); + } catch (IOException e) { + if (file != null) { + file.delete(); + } + } finally { + try { + if (fis != null) { + fis.close(); + } + } catch (IOException ignored) { + } + } + } + } + + /** + * Invalidates an entry in the cache. + * + * @param key + * Cache key + * @param fullExpire + * True to fully expire the entry, false to soft expire + */ + @Override + public synchronized void invalidate(String key, boolean fullExpire) { + Entry entry = get(key); + if (entry != null) { + entry.softTtl = 0; + if (fullExpire) { + entry.ttl = 0; + } + put(key, entry); + } + + } + + /** + * Puts the entry with the specified key into the cache. + */ + @Override + public synchronized void put(String key, Entry entry) { + pruneIfNeeded(entry.data.length); + File file = getFileForKey(key); + try { + FileOutputStream fos = new FileOutputStream(file); + CacheHeader e = new CacheHeader(key, entry); + e.writeHeader(fos); + fos.write(entry.data); + fos.close(); + putEntry(key, e); + // 如果url包含timestamp参数,则去掉该参数再存一份缓存 + if (key.contains("timestamp")) { + put(TimestampUtils.removeTimestamp(key), entry); + } + return; + } catch (IOException e) { + } + boolean deleted = file.delete(); + if (!deleted) { + VolleyLog.d("Could not clean up file %s", file.getAbsolutePath()); + } + } + + /** + * Removes the specified key from the cache if it exists. + */ + @Override + public synchronized void remove(String key) { + boolean deleted = getFileForKey(key).delete(); + removeEntry(key); + if (!deleted) { + VolleyLog.d("Could not delete cache entry for key=%s, filename=%s", + key, getFilenameForKey(key)); + } + } + + /** + * Creates a pseudo-unique filename for the specified cache key. + * + * @param key + * The key to generate a file name for. + * @return A pseudo-unique filename. + */ + private String getFilenameForKey(String key) { + int firstHalfLength = key.length() / 2; + String localFilename = String.valueOf(key.substring(0, firstHalfLength) + .hashCode()); + localFilename += String.valueOf(key.substring(firstHalfLength) + .hashCode()); + return localFilename; + } + + /** + * Returns a file object for the given cache key. + */ + public File getFileForKey(String key) { + return new File(mRootDirectory, getFilenameForKey(key)); + } + + /** + * Prunes the cache to fit the amount of bytes specified. + * + * @param neededSpace + * The amount of bytes we are trying to fit into the cache. + */ + private void pruneIfNeeded(int neededSpace) { + if ((mTotalSize + neededSpace) < mMaxCacheSizeInBytes) { + return; + } + if (VolleyLog.DEBUG) { + VolleyLog.v("Pruning old cache entries."); + } + + long before = mTotalSize; + int prunedFiles = 0; + long startTime = SystemClock.elapsedRealtime(); + + Iterator> iterator = mEntries.entrySet() + .iterator(); + while (iterator.hasNext()) { + Map.Entry entry = iterator.next(); + CacheHeader e = entry.getValue(); + boolean deleted = getFileForKey(e.key).delete(); + if (deleted) { + mTotalSize -= e.size; + } else { + VolleyLog.d( + "Could not delete cache entry for key=%s, filename=%s", + e.key, getFilenameForKey(e.key)); + } + iterator.remove(); + prunedFiles++; + + if ((mTotalSize + neededSpace) < mMaxCacheSizeInBytes + * HYSTERESIS_FACTOR) { + break; + } + } + + if (VolleyLog.DEBUG) { + VolleyLog.v("pruned %d files, %d bytes, %d ms", prunedFiles, + (mTotalSize - before), SystemClock.elapsedRealtime() + - startTime); + } + } + + /** + * Puts the entry with the specified key into the cache. + * + * @param key + * The key to identify the entry by. + * @param entry + * The entry to cache. + */ + private void putEntry(String key, CacheHeader entry) { + if (!mEntries.containsKey(key)) { + mTotalSize += entry.size; + } else { + CacheHeader oldEntry = mEntries.get(key); + mTotalSize += (entry.size - oldEntry.size); + } + mEntries.put(key, entry); + } + + /** + * Removes the entry identified by 'key' from the cache. + */ + private void removeEntry(String key) { + CacheHeader entry = mEntries.get(key); + if (entry != null) { + mTotalSize -= entry.size; + mEntries.remove(key); + } + } + + /** + * Reads the contents of an InputStream into a byte[]. + * */ + private static byte[] streamToBytes(InputStream in, int length) + throws IOException { + byte[] bytes = new byte[length]; + int count; + int pos = 0; + while (pos < length + && ((count = in.read(bytes, pos, length - pos)) != -1)) { + pos += count; + } + if (pos != length) { + throw new IOException("Expected " + length + " bytes, read " + pos + + " bytes"); + } + return bytes; + } + + /** + * Handles holding onto the cache headers for an entry. + */ + // Visible for testing. + static class CacheHeader { + /** + * The size of the data identified by this CacheHeader. (This is not + * serialized to disk. + */ + public long size; + + /** The key that identifies the cache entry. */ + public String key; + + /** ETag for cache coherence. */ + public String etag; + + /** Date of this response as reported by the server. */ + public long serverDate; + + /** TTL for this record. */ + public long ttl; + + /** Soft TTL for this record. */ + public long softTtl; + + /** Headers from the response resulting in this cache entry. */ + public Map responseHeaders; + + private CacheHeader() { + } + + /** + * Instantiates a new CacheHeader object + * + * @param key + * The key that identifies the cache entry + * @param entry + * The cache entry. + */ + public CacheHeader(String key, Entry entry) { + this.key = key; + this.size = entry.data.length; + this.etag = entry.etag; + this.serverDate = entry.serverDate; + this.ttl = entry.ttl; + this.softTtl = entry.softTtl; + this.responseHeaders = entry.responseHeaders; + } + + /** + * Reads the header off of an InputStream and returns a CacheHeader + * object. + * + * @param is + * The InputStream to read from. + * @throws IOException + */ + public static CacheHeader readHeader(InputStream is) throws IOException { + CacheHeader entry = new CacheHeader(); + int magic = readInt(is); + if (magic != CACHE_MAGIC) { + // don't bother deleting, it'll get pruned eventually + throw new IOException(); + } + entry.key = readString(is); + entry.etag = readString(is); + if (entry.etag.equals("")) { + entry.etag = null; + } + entry.serverDate = readLong(is); + entry.ttl = readLong(is); + entry.softTtl = readLong(is); + entry.responseHeaders = readStringStringMap(is); + return entry; + } + + /** + * Creates a cache entry for the specified data. + */ + public Entry toCacheEntry(byte[] data) { + Entry e = new Entry(); + e.data = data; + e.etag = etag; + e.serverDate = serverDate; + e.ttl = ttl; + e.softTtl = softTtl; + e.responseHeaders = responseHeaders; + return e; + } + + /** + * Writes the contents of this CacheHeader to the specified + * OutputStream. + */ + public boolean writeHeader(OutputStream os) { + try { + writeInt(os, CACHE_MAGIC); + writeString(os, key); + writeString(os, etag == null ? "" : etag); + writeLong(os, serverDate); + writeLong(os, ttl); + writeLong(os, softTtl); + writeStringStringMap(responseHeaders, os); + os.flush(); + return true; + } catch (IOException e) { + VolleyLog.d("%s", e.toString()); + return false; + } + } + + } + + private static class CountingInputStream extends FilterInputStream { + private int bytesRead = 0; + + private CountingInputStream(InputStream in) { + super(in); + } + + @Override + public int read() throws IOException { + int result = super.read(); + if (result != -1) { + bytesRead++; + } + return result; + } + + @Override + public int read(byte[] buffer, int offset, int count) + throws IOException { + int result = super.read(buffer, offset, count); + if (result != -1) { + bytesRead += result; + } + return result; + } + } + + /* + * Homebrewed simple serialization system used for reading and writing cache + * headers on disk. Once upon a time, this used the standard Java + * Object{Input,Output}Stream, but the default implementation relies heavily + * on reflection (even for standard types) and generates a ton of garbage. + */ + + /** + * Simple wrapper around {@link InputStream#read()} that throws EOFException + * instead of returning -1. + */ + private static int read(InputStream is) throws IOException { + int b = is.read(); + if (b == -1) { + throw new EOFException(); + } + return b; + } + + static void writeInt(OutputStream os, int n) throws IOException { + os.write((n >> 0) & 0xff); + os.write((n >> 8) & 0xff); + os.write((n >> 16) & 0xff); + os.write((n >> 24) & 0xff); + } + + static int readInt(InputStream is) throws IOException { + int n = 0; + n |= (read(is) << 0); + n |= (read(is) << 8); + n |= (read(is) << 16); + n |= (read(is) << 24); + return n; + } + + static void writeLong(OutputStream os, long n) throws IOException { + os.write((byte) (n >>> 0)); + os.write((byte) (n >>> 8)); + os.write((byte) (n >>> 16)); + os.write((byte) (n >>> 24)); + os.write((byte) (n >>> 32)); + os.write((byte) (n >>> 40)); + os.write((byte) (n >>> 48)); + os.write((byte) (n >>> 56)); + } + + static long readLong(InputStream is) throws IOException { + long n = 0; + n |= ((read(is) & 0xFFL) << 0); + n |= ((read(is) & 0xFFL) << 8); + n |= ((read(is) & 0xFFL) << 16); + n |= ((read(is) & 0xFFL) << 24); + n |= ((read(is) & 0xFFL) << 32); + n |= ((read(is) & 0xFFL) << 40); + n |= ((read(is) & 0xFFL) << 48); + n |= ((read(is) & 0xFFL) << 56); + return n; + } + + static void writeString(OutputStream os, String s) throws IOException { + byte[] b = s.getBytes("UTF-8"); + writeLong(os, b.length); + os.write(b, 0, b.length); + } + + static String readString(InputStream is) throws IOException { + int n = (int) readLong(is); + byte[] b = streamToBytes(is, n); + return new String(b, "UTF-8"); + } + + static void writeStringStringMap(Map map, OutputStream os) + throws IOException { + if (map != null) { + writeInt(os, map.size()); + for (Map.Entry entry : map.entrySet()) { + writeString(os, entry.getKey()); + writeString(os, entry.getValue()); + } + } else { + writeInt(os, 0); + } + } + + static Map readStringStringMap(InputStream is) + throws IOException { + int size = readInt(is); + Map result = (size == 0) ? Collections + . emptyMap() + : new HashMap(size); + for (int i = 0; i < size; i++) { + String key = readString(is).intern(); + String value = readString(is).intern(); + result.put(key, value); + } + return result; + } + +} diff --git a/app/src/main/java/com/android/volley/toolbox/HttpClientStack.java b/app/src/main/java/com/android/volley/toolbox/HttpClientStack.java new file mode 100644 index 0000000000..7cf69d1ad0 --- /dev/null +++ b/app/src/main/java/com/android/volley/toolbox/HttpClientStack.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley.toolbox; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.params.HttpConnectionParams; +import org.apache.http.params.HttpParams; + +import com.android.volley.AuthFailureError; +import com.android.volley.Request; +import com.android.volley.Request.Method; + +/** + * An HttpStack that performs request over an {@link HttpClient}. + */ +public class HttpClientStack implements HttpStack { + protected final HttpClient mClient; + + private final static String HEADER_CONTENT_TYPE = "Content-Type"; + + public HttpClientStack(HttpClient client) { + mClient = client; + } + + private static void addHeaders(HttpUriRequest httpRequest, Map headers) { + for (String key : headers.keySet()) { + httpRequest.setHeader(key, headers.get(key)); + } + } + + @SuppressWarnings("unused") + private static List getPostParameterPairs(Map postParams) { + List result = new ArrayList(postParams.size()); + for (String key : postParams.keySet()) { + result.add(new BasicNameValuePair(key, postParams.get(key))); + } + return result; + } + + @Override + public HttpResponse performRequest(Request request, Map additionalHeaders) + throws IOException, AuthFailureError { + HttpUriRequest httpRequest = createHttpRequest(request, additionalHeaders); + addHeaders(httpRequest, additionalHeaders); + addHeaders(httpRequest, request.getHeaders()); + onPrepareRequest(httpRequest); + HttpParams httpParams = httpRequest.getParams(); + int timeoutMs = request.getTimeoutMs(); + // TODO: Reevaluate this connection timeout based on more wide-scale + // data collection and possibly different for wifi vs. 3G. + HttpConnectionParams.setConnectionTimeout(httpParams, 5000); + HttpConnectionParams.setSoTimeout(httpParams, timeoutMs); + return mClient.execute(httpRequest); + } + + /** + * Creates the appropriate subclass of HttpUriRequest for passed in request. + */ + @SuppressWarnings("deprecation") + /* protected */ static HttpUriRequest createHttpRequest(Request request, + Map additionalHeaders) throws AuthFailureError { + switch (request.getMethod()) { + case Method.DEPRECATED_GET_OR_POST: { + // This is the deprecated way that needs to be handled for backwards compatibility. + // If the request's post body is null, then the assumption is that the request is + // GET. Otherwise, it is assumed that the request is a POST. + byte[] postBody = request.getPostBody(); + if (postBody != null) { + HttpPost postRequest = new HttpPost(request.getUrl()); + postRequest.addHeader(HEADER_CONTENT_TYPE, request.getPostBodyContentType()); + HttpEntity entity; + entity = new ByteArrayEntity(postBody); + postRequest.setEntity(entity); + return postRequest; + } else { + return new HttpGet(request.getUrl()); + } + } + case Method.GET: + return new HttpGet(request.getUrl()); + case Method.DELETE: + return new HttpDelete(request.getUrl()); + case Method.POST: { + HttpPost postRequest = new HttpPost(request.getUrl()); + postRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType()); + setEntityIfNonEmptyBody(postRequest, request); + return postRequest; + } + case Method.PUT: { + HttpPut putRequest = new HttpPut(request.getUrl()); + putRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType()); + setEntityIfNonEmptyBody(putRequest, request); + return putRequest; + } + default: + throw new IllegalStateException("Unknown request method."); + } + } + + private static void setEntityIfNonEmptyBody(HttpEntityEnclosingRequestBase httpRequest, + Request request) throws AuthFailureError { + byte[] body = request.getBody(); + if (body != null) { + HttpEntity entity = new ByteArrayEntity(body); + httpRequest.setEntity(entity); + } + } + + /** + * Called before the request is executed using the underlying HttpClient. + * + *

Overwrite in subclasses to augment the request.

+ */ + protected void onPrepareRequest(HttpUriRequest request) throws IOException { + // Nothing. + } +} diff --git a/app/src/main/java/com/android/volley/toolbox/HttpHeaderParser.java b/app/src/main/java/com/android/volley/toolbox/HttpHeaderParser.java new file mode 100644 index 0000000000..e782f57096 --- /dev/null +++ b/app/src/main/java/com/android/volley/toolbox/HttpHeaderParser.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley.toolbox; + +import java.util.Map; + +import org.apache.http.impl.cookie.DateParseException; +import org.apache.http.impl.cookie.DateUtils; +import org.apache.http.protocol.HTTP; + +import com.android.volley.Cache; +import com.android.volley.NetworkResponse; + +/** + * Utility methods for parsing HTTP headers. + */ +public class HttpHeaderParser { + + /** + * Extracts a {@link Cache.Entry} from a {@link NetworkResponse}. + * + * @param response The network response to parse headers from + * @return a cache entry for the given response, or null if the response is not cacheable. + */ + public static Cache.Entry parseCacheHeaders(NetworkResponse response) { + long now = System.currentTimeMillis(); + + Map headers = response.headers; + + long serverDate = 0; + long serverExpires = 0; + long softExpire = 0; + long maxAge = 0; + boolean hasCacheControl = false; + + String serverEtag = null; + String headerValue; + + headerValue = headers.get("Date"); + if (headerValue != null) { + serverDate = parseDateAsEpoch(headerValue); + } + + headerValue = headers.get("Cache-Control"); + if (headerValue != null) { + hasCacheControl = true; + String[] tokens = headerValue.split(","); + for (int i = 0; i < tokens.length; i++) { + String token = tokens[i].trim(); + if (token.equals("no-cache") || token.equals("no-store")) { + return null; + } else if (token.startsWith("max-age=")) { + try { + maxAge = Long.parseLong(token.substring(8)); + } catch (Exception e) { + } + } else if (token.equals("must-revalidate") || token.equals("proxy-revalidate")) { + maxAge = 0; + } + } + } + + headerValue = headers.get("Expires"); + if (headerValue != null) { + serverExpires = parseDateAsEpoch(headerValue); + } + + serverEtag = headers.get("ETag"); + + // Cache-Control takes precedence over an Expires header, even if both exist and Expires + // is more restrictive. + if (hasCacheControl) { + softExpire = now + maxAge * 1000; + } else if (serverDate > 0 && serverExpires >= serverDate) { + // Default semantic for Expire header in HTTP specification is softExpire. + softExpire = now + (serverExpires - serverDate); + } + + Cache.Entry entry = new Cache.Entry(); + entry.data = response.data; + entry.etag = serverEtag; + entry.softTtl = softExpire; + entry.ttl = entry.softTtl; + entry.serverDate = serverDate; + entry.responseHeaders = headers; + + return entry; + } + + /** + * Parse date in RFC1123 format, and return its value as epoch + */ + public static long parseDateAsEpoch(String dateStr) { + try { + // Parse date in RFC1123 format if this header contains one + return DateUtils.parseDate(dateStr).getTime(); + } catch (DateParseException e) { + // Date in invalid format, fallback to 0 + return 0; + } + } + + /** + * Returns the charset specified in the Content-Type of this header, + * or the HTTP default (ISO-8859-1) if none can be found. + */ + public static String parseCharset(Map headers) { + String contentType = headers.get(HTTP.CONTENT_TYPE); + if (contentType != null) { + String[] params = contentType.split(";"); + for (int i = 1; i < params.length; i++) { + String[] pair = params[i].trim().split("="); + if (pair.length == 2) { + if (pair[0].equals("charset")) { + return pair[1]; + } + } + } + } + + return HTTP.UTF_8; + } +} diff --git a/app/src/main/java/com/android/volley/toolbox/HttpStack.java b/app/src/main/java/com/android/volley/toolbox/HttpStack.java new file mode 100644 index 0000000000..0f01761526 --- /dev/null +++ b/app/src/main/java/com/android/volley/toolbox/HttpStack.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley.toolbox; + +import java.io.IOException; +import java.util.Map; + +import org.apache.http.HttpResponse; + +import com.android.volley.AuthFailureError; +import com.android.volley.Request; + +/** + * An HTTP stack abstraction. + */ +public interface HttpStack { + /** + * Performs an HTTP request with the given parameters. + * + *

A GET request is sent if request.getPostBody() == null. A POST request is sent otherwise, + * and the Content-Type header is set to request.getPostBodyContentType().

+ * + * @param request the request to perform + * @param additionalHeaders additional headers to be sent together with + * {@link Request#getHeaders()} + * @return the HTTP response + */ + public HttpResponse performRequest(Request request, Map additionalHeaders) + throws IOException, AuthFailureError; + +} diff --git a/app/src/main/java/com/android/volley/toolbox/HurlStack.java b/app/src/main/java/com/android/volley/toolbox/HurlStack.java new file mode 100644 index 0000000000..8b49f99279 --- /dev/null +++ b/app/src/main/java/com/android/volley/toolbox/HurlStack.java @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley.toolbox; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSocketFactory; + +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.ProtocolVersion; +import org.apache.http.StatusLine; +import org.apache.http.entity.BasicHttpEntity; +import org.apache.http.message.BasicHeader; +import org.apache.http.message.BasicHttpResponse; +import org.apache.http.message.BasicStatusLine; + +import com.android.volley.AuthFailureError; +import com.android.volley.Request; +import com.android.volley.Request.Method; + +/** + * An {@link HttpStack} based on {@link HttpURLConnection}. + */ +public class HurlStack implements HttpStack { + + private static final String HEADER_CONTENT_TYPE = "Content-Type"; + + /** + * An interface for transforming URLs before use. + */ + public interface UrlRewriter { + /** + * Returns a URL to use instead of the provided one, or null to indicate + * this URL should not be used at all. + */ + public String rewriteUrl(String originalUrl); + } + + private final UrlRewriter mUrlRewriter; + private final SSLSocketFactory mSslSocketFactory; + + public HurlStack() { + this(null); + } + + /** + * @param urlRewriter + * Rewriter to use for request URLs + */ + public HurlStack(UrlRewriter urlRewriter) { + this(urlRewriter, null); + } + + /** + * @param urlRewriter + * Rewriter to use for request URLs + * @param sslSocketFactory + * SSL factory to use for HTTPS connections + */ + public HurlStack(UrlRewriter urlRewriter, SSLSocketFactory sslSocketFactory) { + mUrlRewriter = urlRewriter; + mSslSocketFactory = sslSocketFactory; + } + + @Override + public HttpResponse performRequest(Request request, + Map additionalHeaders) throws IOException, + AuthFailureError { + String url = request.getUrl(); + HashMap map = new HashMap(); + map.putAll(request.getHeaders()); + map.putAll(additionalHeaders); + if (mUrlRewriter != null) { + String rewritten = mUrlRewriter.rewriteUrl(url); + if (rewritten == null) { + throw new IOException("URL blocked by rewriter: " + url); + } + url = rewritten; + } + URL parsedUrl = new URL(url); + HttpURLConnection connection = openConnection(parsedUrl, request); + + // if have etag, don't use lastmodified + // because the aliyun cnd will use lastmodified do something we don't know + if (map.containsKey("If-None-Match")) { + map.remove("If-Modified-Since"); + } + + for (String headerName : map.keySet()) { + connection.addRequestProperty(headerName, map.get(headerName)); + } + + setConnectionParametersForRequest(connection, request); + // Initialize HttpResponse with data from the HttpURLConnection. + ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 1); + + int responseCode = connection.getResponseCode(); + + if (responseCode == -1) { + // -1 is returned by getResponseCode() if the response code could + // not be retrieved. + // Signal to the caller that something was wrong with the + // connection. + throw new IOException( + "Could not retrieve response code from HttpUrlConnection."); + } + StatusLine responseStatus = new BasicStatusLine(protocolVersion, + connection.getResponseCode(), connection.getResponseMessage()); + BasicHttpResponse response = new BasicHttpResponse(responseStatus); + response.setEntity(entityFromConnection(connection)); + for (Entry> header : connection.getHeaderFields() + .entrySet()) { + if (header.getKey() != null) { + Header h = new BasicHeader(header.getKey(), header.getValue() + .get(0)); + response.addHeader(h); + } + } + return response; + } + + /** + * Initializes an {@link HttpEntity} from the given + * {@link HttpURLConnection}. + * + * @param connection + * @return an HttpEntity populated with data from connection. + */ + private static HttpEntity entityFromConnection(HttpURLConnection connection) { + BasicHttpEntity entity = new BasicHttpEntity(); + InputStream inputStream; + try { + inputStream = connection.getInputStream(); + } catch (IOException ioe) { + inputStream = connection.getErrorStream(); + } + entity.setContent(inputStream); + entity.setContentLength(connection.getContentLength()); + entity.setContentEncoding(connection.getContentEncoding()); + entity.setContentType(connection.getContentType()); + return entity; + } + + /** + * Create an {@link HttpURLConnection} for the specified {@code url}. + */ + protected HttpURLConnection createConnection(URL url) throws IOException { + return (HttpURLConnection) url.openConnection(); + } + + /** + * Opens an {@link HttpURLConnection} with parameters. + * + * @param url + * @return an open connection + * @throws IOException + */ + private HttpURLConnection openConnection(URL url, Request request) + throws IOException { + HttpURLConnection connection = createConnection(url); + + int timeoutMs = request.getTimeoutMs(); + connection.setConnectTimeout(timeoutMs); + connection.setReadTimeout(timeoutMs); + connection.setUseCaches(false); + connection.setDoInput(true); + + // use caller-provided custom SslSocketFactory, if any, for HTTPS + if ("https".equals(url.getProtocol()) && mSslSocketFactory != null) { + ((HttpsURLConnection) connection) + .setSSLSocketFactory(mSslSocketFactory); + } + + return connection; + } + + @SuppressWarnings("deprecation") + /* package */static void setConnectionParametersForRequest( + HttpURLConnection connection, Request request) + throws IOException, AuthFailureError { + switch (request.getMethod()) { + case Method.DEPRECATED_GET_OR_POST: + // This is the deprecated way that needs to be handled for backwards + // compatibility. + // If the request's post body is null, then the assumption is that + // the request is + // GET. Otherwise, it is assumed that the request is a POST. + byte[] postBody = request.getPostBody(); + if (postBody != null) { + // Prepare output. There is no need to set Content-Length + // explicitly, + // since this is handled by HttpURLConnection using the size of + // the prepared + // output stream. + connection.setDoOutput(true); + connection.setRequestMethod("POST"); + connection.addRequestProperty(HEADER_CONTENT_TYPE, + request.getPostBodyContentType()); + DataOutputStream out = new DataOutputStream( + connection.getOutputStream()); + out.write(postBody); + out.close(); + } + break; + case Method.GET: + // Not necessary to set the request method because connection + // defaults to GET but + // being explicit here. + connection.setRequestMethod("GET"); + break; + case Method.DELETE: + connection.setRequestMethod("DELETE"); + break; + case Method.POST: + connection.setRequestMethod("POST"); + addBodyIfExists(connection, request); + break; + case Method.PUT: + connection.setRequestMethod("PUT"); + addBodyIfExists(connection, request); + break; + default: + throw new IllegalStateException("Unknown method type."); + } + } + + private static void addBodyIfExists(HttpURLConnection connection, + Request request) throws IOException, AuthFailureError { + byte[] body = request.getBody(); + if (body != null) { + connection.setDoOutput(true); + connection.addRequestProperty(HEADER_CONTENT_TYPE, + request.getBodyContentType()); + DataOutputStream out = new DataOutputStream( + connection.getOutputStream()); + out.write(body); + out.close(); + } + } +} diff --git a/app/src/main/java/com/android/volley/toolbox/ImageLoader.java b/app/src/main/java/com/android/volley/toolbox/ImageLoader.java new file mode 100644 index 0000000000..4335a89a87 --- /dev/null +++ b/app/src/main/java/com/android/volley/toolbox/ImageLoader.java @@ -0,0 +1,479 @@ +/** + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.volley.toolbox; + +import java.util.HashMap; +import java.util.LinkedList; + +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.os.Handler; +import android.os.Looper; +import android.widget.ImageView; + +import com.android.volley.Request; +import com.android.volley.RequestQueue; +import com.android.volley.Response.ErrorListener; +import com.android.volley.Response.Listener; +import com.android.volley.VolleyError; + +/** + * Helper that handles loading and caching images from remote URLs. + * + * The simple way to use this class is to call {@link ImageLoader#get(String, ImageListener)} + * and to pass in the default image listener provided by + * {@link ImageLoader#getImageListener(ImageView, int, int)}. Note that all function calls to + * this class must be made from the main thead, and all responses will be delivered to the main + * thread as well. + */ +public class ImageLoader { + /** RequestQueue for dispatching ImageRequests onto. */ + private final RequestQueue mRequestQueue; + + /** Amount of time to wait after first response arrives before delivering all responses. */ + private int mBatchResponseDelayMs = 100; + + /** The cache implementation to be used as an L1 cache before calling into volley. */ + private final ImageCache mCache; + + /** + * HashMap of Cache keys -> BatchedImageRequest used to track in-flight requests so + * that we can coalesce multiple requests to the same URL into a single network request. + */ + private final HashMap mInFlightRequests = + new HashMap(); + + /** HashMap of the currently pending responses (waiting to be delivered). */ + private final HashMap mBatchedResponses = + new HashMap(); + + /** Handler to the main thread. */ + private final Handler mHandler = new Handler(Looper.getMainLooper()); + + /** Runnable for in-flight response delivery. */ + private Runnable mRunnable; + + /** + * Simple cache adapter interface. If provided to the ImageLoader, it + * will be used as an L1 cache before dispatch to Volley. Implementations + * must not block. Implementation with an LruCache is recommended. + */ + public interface ImageCache { + public Bitmap getBitmap(String url); + public void putBitmap(String url, Bitmap bitmap); + } + + /** + * Constructs a new ImageLoader. + * @param queue The RequestQueue to use for making image requests. + * @param imageCache The cache to use as an L1 cache. + */ + public ImageLoader(RequestQueue queue, ImageCache imageCache) { + mRequestQueue = queue; + mCache = imageCache; + } + + /** + * The default implementation of ImageListener which handles basic functionality + * of showing a default image until the network response is received, at which point + * it will switch to either the actual image or the error image. + * @param imageView The imageView that the listener is associated with. + * @param defaultImageResId Default image resource ID to use, or 0 if it doesn't exist. + * @param errorImageResId Error image resource ID to use, or 0 if it doesn't exist. + */ + public static ImageListener getImageListener(final ImageView view, + final int defaultImageResId, final int errorImageResId) { + return new ImageListener() { + @Override + public void onErrorResponse(VolleyError error) { + if (errorImageResId != 0) { + view.setImageResource(errorImageResId); + } + } + + @Override + public void onResponse(ImageContainer response, boolean isImmediate) { + if (response.getBitmap() != null) { + view.setImageBitmap(response.getBitmap()); + } else if (defaultImageResId != 0) { + view.setImageResource(defaultImageResId); + } + } + }; + } + + /** + * Interface for the response handlers on image requests. + * + * The call flow is this: + * 1. Upon being attached to a request, onResponse(response, true) will + * be invoked to reflect any cached data that was already available. If the + * data was available, response.getBitmap() will be non-null. + * + * 2. After a network response returns, only one of the following cases will happen: + * - onResponse(response, false) will be called if the image was loaded. + * or + * - onErrorResponse will be called if there was an error loading the image. + */ + public interface ImageListener extends ErrorListener { + /** + * Listens for non-error changes to the loading of the image request. + * + * @param response Holds all information pertaining to the request, as well + * as the bitmap (if it is loaded). + * @param isImmediate True if this was called during ImageLoader.get() variants. + * This can be used to differentiate between a cached image loading and a network + * image loading in order to, for example, run an animation to fade in network loaded + * images. + */ + public void onResponse(ImageContainer response, boolean isImmediate); + } + + /** + * Checks if the item is available in the cache. + * @param requestUrl The url of the remote image + * @param maxWidth The maximum width of the returned image. + * @param maxHeight The maximum height of the returned image. + * @return True if the item exists in cache, false otherwise. + */ + public boolean isCached(String requestUrl, int maxWidth, int maxHeight) { + throwIfNotOnMainThread(); + + String cacheKey = getCacheKey(requestUrl, maxWidth, maxHeight); + return mCache.getBitmap(cacheKey) != null; + } + + /** + * Returns an ImageContainer for the requested URL. + * + * The ImageContainer will contain either the specified default bitmap or the loaded bitmap. + * If the default was returned, the {@link ImageLoader} will be invoked when the + * request is fulfilled. + * + * @param requestUrl The URL of the image to be loaded. + * @param defaultImage Optional default image to return until the actual image is loaded. + */ + public ImageContainer get(String requestUrl, final ImageListener listener) { + return get(requestUrl, listener, 0, 0); + } + + /** + * Issues a bitmap request with the given URL if that image is not available + * in the cache, and returns a bitmap container that contains all of the data + * relating to the request (as well as the default image if the requested + * image is not available). + * @param requestUrl The url of the remote image + * @param imageListener The listener to call when the remote image is loaded + * @param maxWidth The maximum width of the returned image. + * @param maxHeight The maximum height of the returned image. + * @return A container object that contains all of the properties of the request, as well as + * the currently available image (default if remote is not loaded). + */ + public ImageContainer get(String requestUrl, ImageListener imageListener, + int maxWidth, int maxHeight) { + // only fulfill requests that were initiated from the main thread. + throwIfNotOnMainThread(); + + final String cacheKey = getCacheKey(requestUrl, maxWidth, maxHeight); + + // Try to look up the request in the cache of remote images. + Bitmap cachedBitmap = mCache.getBitmap(cacheKey); + if (cachedBitmap != null) { + // Return the cached bitmap. + ImageContainer container = new ImageContainer(cachedBitmap, requestUrl, null, null); + imageListener.onResponse(container, true); + return container; + } + + // The bitmap did not exist in the cache, fetch it! + ImageContainer imageContainer = + new ImageContainer(null, requestUrl, cacheKey, imageListener); + + // Update the caller to let them know that they should use the default bitmap. + imageListener.onResponse(imageContainer, true); + + // Check to see if a request is already in-flight. + BatchedImageRequest request = mInFlightRequests.get(cacheKey); + if (request != null) { + // If it is, add this request to the list of listeners. + request.addContainer(imageContainer); + return imageContainer; + } + + // The request is not already in flight. Send the new request to the network and + // track it. + Request newRequest = + new ImageRequest(requestUrl, new Listener() { + @Override + public void onResponse(Bitmap response) { + onGetImageSuccess(cacheKey, response); + } + }, maxWidth, maxHeight, + Config.RGB_565, new ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + onGetImageError(cacheKey, error); + } + }); + + mRequestQueue.add(newRequest); + mInFlightRequests.put(cacheKey, + new BatchedImageRequest(newRequest, imageContainer)); + return imageContainer; + } + + /** + * Sets the amount of time to wait after the first response arrives before delivering all + * responses. Batching can be disabled entirely by passing in 0. + * @param newBatchedResponseDelayMs The time in milliseconds to wait. + */ + public void setBatchedResponseDelay(int newBatchedResponseDelayMs) { + mBatchResponseDelayMs = newBatchedResponseDelayMs; + } + + /** + * Handler for when an image was successfully loaded. + * @param cacheKey The cache key that is associated with the image request. + * @param response The bitmap that was returned from the network. + */ + private void onGetImageSuccess(String cacheKey, Bitmap response) { + // cache the image that was fetched. + mCache.putBitmap(cacheKey, response); + + // remove the request from the list of in-flight requests. + BatchedImageRequest request = mInFlightRequests.remove(cacheKey); + + if (request != null) { + // Update the response bitmap. + request.mResponseBitmap = response; + + // Send the batched response + batchResponse(cacheKey, request); + } + } + + /** + * Handler for when an image failed to load. + * @param cacheKey The cache key that is associated with the image request. + */ + private void onGetImageError(String cacheKey, VolleyError error) { + // Notify the requesters that something failed via a null result. + // Remove this request from the list of in-flight requests. + BatchedImageRequest request = mInFlightRequests.remove(cacheKey); + + // Set the error for this request + request.setError(error); + + if (request != null) { + // Send the batched response + batchResponse(cacheKey, request); + } + } + + /** + * Container object for all of the data surrounding an image request. + */ + public class ImageContainer { + /** + * The most relevant bitmap for the container. If the image was in cache, the + * Holder to use for the final bitmap (the one that pairs to the requested URL). + */ + private Bitmap mBitmap; + + private final ImageListener mListener; + + /** The cache key that was associated with the request */ + private final String mCacheKey; + + /** The request URL that was specified */ + private final String mRequestUrl; + + /** + * Constructs a BitmapContainer object. + * @param bitmap The final bitmap (if it exists). + * @param requestUrl The requested URL for this container. + * @param cacheKey The cache key that identifies the requested URL for this container. + */ + public ImageContainer(Bitmap bitmap, String requestUrl, + String cacheKey, ImageListener listener) { + mBitmap = bitmap; + mRequestUrl = requestUrl; + mCacheKey = cacheKey; + mListener = listener; + } + + /** + * Releases interest in the in-flight request (and cancels it if no one else is listening). + */ + public void cancelRequest() { + if (mListener == null) { + return; + } + + BatchedImageRequest request = mInFlightRequests.get(mCacheKey); + if (request != null) { + boolean canceled = request.removeContainerAndCancelIfNecessary(this); + if (canceled) { + mInFlightRequests.remove(mCacheKey); + } + } else { + // check to see if it is already batched for delivery. + request = mBatchedResponses.get(mCacheKey); + if (request != null) { + request.removeContainerAndCancelIfNecessary(this); + if (request.mContainers.size() == 0) { + mBatchedResponses.remove(mCacheKey); + } + } + } + } + + /** + * Returns the bitmap associated with the request URL if it has been loaded, null otherwise. + */ + public Bitmap getBitmap() { + return mBitmap; + } + + /** + * Returns the requested URL for this container. + */ + public String getRequestUrl() { + return mRequestUrl; + } + } + + /** + * Wrapper class used to map a Request to the set of active ImageContainer objects that are + * interested in its results. + */ + private class BatchedImageRequest { + /** The request being tracked */ + private final Request mRequest; + + /** The result of the request being tracked by this item */ + private Bitmap mResponseBitmap; + + /** Error if one occurred for this response */ + private VolleyError mError; + + /** List of all of the active ImageContainers that are interested in the request */ + private final LinkedList mContainers = new LinkedList(); + + /** + * Constructs a new BatchedImageRequest object + * @param request The request being tracked + * @param container The ImageContainer of the person who initiated the request. + */ + public BatchedImageRequest(Request request, ImageContainer container) { + mRequest = request; + mContainers.add(container); + } + + /** + * Set the error for this response + */ + public void setError(VolleyError error) { + mError = error; + } + + /** + * Get the error for this response + */ + public VolleyError getError() { + return mError; + } + + /** + * Adds another ImageContainer to the list of those interested in the results of + * the request. + */ + public void addContainer(ImageContainer container) { + mContainers.add(container); + } + + /** + * Detatches the bitmap container from the request and cancels the request if no one is + * left listening. + * @param container The container to remove from the list + * @return True if the request was canceled, false otherwise. + */ + public boolean removeContainerAndCancelIfNecessary(ImageContainer container) { + mContainers.remove(container); + if (mContainers.size() == 0) { + mRequest.cancel(); + return true; + } + return false; + } + } + + /** + * Starts the runnable for batched delivery of responses if it is not already started. + * @param cacheKey The cacheKey of the response being delivered. + * @param request The BatchedImageRequest to be delivered. + * @param error The volley error associated with the request (if applicable). + */ + private void batchResponse(String cacheKey, BatchedImageRequest request) { + mBatchedResponses.put(cacheKey, request); + // If we don't already have a batch delivery runnable in flight, make a new one. + // Note that this will be used to deliver responses to all callers in mBatchedResponses. + if (mRunnable == null) { + mRunnable = new Runnable() { + @Override + public void run() { + for (BatchedImageRequest bir : mBatchedResponses.values()) { + for (ImageContainer container : bir.mContainers) { + // If one of the callers in the batched request canceled the request + // after the response was received but before it was delivered, + // skip them. + if (container.mListener == null) { + continue; + } + if (bir.getError() == null) { + container.mBitmap = bir.mResponseBitmap; + container.mListener.onResponse(container, false); + } else { + container.mListener.onErrorResponse(bir.getError()); + } + } + } + mBatchedResponses.clear(); + mRunnable = null; + } + + }; + // Post the runnable. + mHandler.postDelayed(mRunnable, mBatchResponseDelayMs); + } + } + + private void throwIfNotOnMainThread() { + if (Looper.myLooper() != Looper.getMainLooper()) { + throw new IllegalStateException("ImageLoader must be invoked from the main thread."); + } + } + /** + * Creates a cache key for use with the L1 cache. + * @param url The URL of the request. + * @param maxWidth The max-width of the output. + * @param maxHeight The max-height of the output. + */ + private static String getCacheKey(String url, int maxWidth, int maxHeight) { + return new StringBuilder(url.length() + 12).append("#W").append(maxWidth) + .append("#H").append(maxHeight).append(url).toString(); + } +} diff --git a/app/src/main/java/com/android/volley/toolbox/ImageRequest.java b/app/src/main/java/com/android/volley/toolbox/ImageRequest.java new file mode 100644 index 0000000000..7de78e40fd --- /dev/null +++ b/app/src/main/java/com/android/volley/toolbox/ImageRequest.java @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley.toolbox; + +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.graphics.BitmapFactory; + +import com.android.volley.DefaultRetryPolicy; +import com.android.volley.NetworkResponse; +import com.android.volley.ParseError; +import com.android.volley.Request; +import com.android.volley.Response; +import com.android.volley.VolleyLog; + +/** + * A canned request for getting an image at a given URL and calling + * back with a decoded Bitmap. + */ +public class ImageRequest extends Request { + /** Socket timeout in milliseconds for image requests */ + private static final int IMAGE_TIMEOUT_MS = 1000; + + /** Default number of retries for image requests */ + private static final int IMAGE_MAX_RETRIES = 2; + + /** Default backoff multiplier for image requests */ + private static final float IMAGE_BACKOFF_MULT = 2f; + + private final Response.Listener mListener; + private final Config mDecodeConfig; + private final int mMaxWidth; + private final int mMaxHeight; + + /** Decoding lock so that we don't decode more than one image at a time (to avoid OOM's) */ + private static final Object sDecodeLock = new Object(); + + /** + * Creates a new image request, decoding to a maximum specified width and + * height. If both width and height are zero, the image will be decoded to + * its natural size. If one of the two is nonzero, that dimension will be + * clamped and the other one will be set to preserve the image's aspect + * ratio. If both width and height are nonzero, the image will be decoded to + * be fit in the rectangle of dimensions width x height while keeping its + * aspect ratio. + * + * @param url URL of the image + * @param listener Listener to receive the decoded bitmap + * @param maxWidth Maximum width to decode this bitmap to, or zero for none + * @param maxHeight Maximum height to decode this bitmap to, or zero for + * none + * @param decodeConfig Format to decode the bitmap to + * @param errorListener Error listener, or null to ignore errors + */ + public ImageRequest(String url, Response.Listener listener, int maxWidth, int maxHeight, + Config decodeConfig, Response.ErrorListener errorListener) { + super(Method.GET, url, errorListener); + setRetryPolicy( + new DefaultRetryPolicy(IMAGE_TIMEOUT_MS, IMAGE_MAX_RETRIES, IMAGE_BACKOFF_MULT)); + mListener = listener; + mDecodeConfig = decodeConfig; + mMaxWidth = maxWidth; + mMaxHeight = maxHeight; + } + + @Override + public Priority getPriority() { + return Priority.LOW; + } + + /** + * Scales one side of a rectangle to fit aspect ratio. + * + * @param maxPrimary Maximum size of the primary dimension (i.e. width for + * max width), or zero to maintain aspect ratio with secondary + * dimension + * @param maxSecondary Maximum size of the secondary dimension, or zero to + * maintain aspect ratio with primary dimension + * @param actualPrimary Actual size of the primary dimension + * @param actualSecondary Actual size of the secondary dimension + */ + private static int getResizedDimension(int maxPrimary, int maxSecondary, int actualPrimary, + int actualSecondary) { + // If no dominant value at all, just return the actual. + if (maxPrimary == 0 && maxSecondary == 0) { + return actualPrimary; + } + + // If primary is unspecified, scale primary to match secondary's scaling ratio. + if (maxPrimary == 0) { + double ratio = (double) maxSecondary / (double) actualSecondary; + return (int) (actualPrimary * ratio); + } + + if (maxSecondary == 0) { + return maxPrimary; + } + + double ratio = (double) actualSecondary / (double) actualPrimary; + int resized = maxPrimary; + if (resized * ratio > maxSecondary) { + resized = (int) (maxSecondary / ratio); + } + return resized; + } + + @Override + protected Response parseNetworkResponse(NetworkResponse response) { + // Serialize all decode on a global lock to reduce concurrent heap usage. + synchronized (sDecodeLock) { + try { + return doParse(response); + } catch (OutOfMemoryError e) { + VolleyLog.e("Caught OOM for %d byte image, url=%s", response.data.length, getUrl()); + return Response.error(new ParseError(e)); + } + } + } + + /** + * The real guts of parseNetworkResponse. Broken out for readability. + */ + private Response doParse(NetworkResponse response) { + byte[] data = response.data; + BitmapFactory.Options decodeOptions = new BitmapFactory.Options(); + Bitmap bitmap = null; + if (mMaxWidth == 0 && mMaxHeight == 0) { + decodeOptions.inPreferredConfig = mDecodeConfig; + bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions); + } else { + // If we have to resize this image, first get the natural bounds. + decodeOptions.inJustDecodeBounds = true; + BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions); + int actualWidth = decodeOptions.outWidth; + int actualHeight = decodeOptions.outHeight; + + // Then compute the dimensions we would ideally like to decode to. + int desiredWidth = getResizedDimension(mMaxWidth, mMaxHeight, + actualWidth, actualHeight); + int desiredHeight = getResizedDimension(mMaxHeight, mMaxWidth, + actualHeight, actualWidth); + + // Decode to the nearest power of two scaling factor. + decodeOptions.inJustDecodeBounds = false; + // TODO(ficus): Do we need this or is it okay since API 8 doesn't support it? + // decodeOptions.inPreferQualityOverSpeed = PREFER_QUALITY_OVER_SPEED; + decodeOptions.inSampleSize = + findBestSampleSize(actualWidth, actualHeight, desiredWidth, desiredHeight); + Bitmap tempBitmap = + BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions); + + // If necessary, scale down to the maximal acceptable size. + if (tempBitmap != null && (tempBitmap.getWidth() > desiredWidth || + tempBitmap.getHeight() > desiredHeight)) { + bitmap = Bitmap.createScaledBitmap(tempBitmap, + desiredWidth, desiredHeight, true); + tempBitmap.recycle(); + } else { + bitmap = tempBitmap; + } + } + + if (bitmap == null) { + return Response.error(new ParseError(response)); + } else { + return Response.success(bitmap, HttpHeaderParser.parseCacheHeaders(response)); + } + } + + @Override + protected void deliverResponse(Bitmap response) { + mListener.onResponse(response); + } + + /** + * Returns the largest power-of-two divisor for use in downscaling a bitmap + * that will not result in the scaling past the desired dimensions. + * + * @param actualWidth Actual width of the bitmap + * @param actualHeight Actual height of the bitmap + * @param desiredWidth Desired width of the bitmap + * @param desiredHeight Desired height of the bitmap + */ + // Visible for testing. + static int findBestSampleSize( + int actualWidth, int actualHeight, int desiredWidth, int desiredHeight) { + double wr = (double) actualWidth / desiredWidth; + double hr = (double) actualHeight / desiredHeight; + double ratio = Math.min(wr, hr); + float n = 1.0f; + while ((n * 2) <= ratio) { + n *= 2; + } + + return (int) n; + } +} diff --git a/app/src/main/java/com/android/volley/toolbox/JsonArrayRequest.java b/app/src/main/java/com/android/volley/toolbox/JsonArrayRequest.java new file mode 100644 index 0000000000..df83190b51 --- /dev/null +++ b/app/src/main/java/com/android/volley/toolbox/JsonArrayRequest.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley.toolbox; + +import java.io.UnsupportedEncodingException; + +import org.json.JSONArray; +import org.json.JSONException; + +import com.android.volley.NetworkResponse; +import com.android.volley.ParseError; +import com.android.volley.Response; +import com.android.volley.Response.ErrorListener; +import com.android.volley.Response.Listener; + +/** + * A request for retrieving a {@link JSONArray} response body at a given URL. + */ +public class JsonArrayRequest extends JsonRequest { + + /** + * Creates a new request. + * @param url URL to fetch the JSON from + * @param listener Listener to receive the JSON response + * @param errorListener Error listener, or null to ignore errors. + */ + public JsonArrayRequest(String url, Listener listener, ErrorListener errorListener) { + super(Method.GET, url, null, listener, errorListener); + } + + @Override + protected Response parseNetworkResponse(NetworkResponse response) { + try { + String jsonString = + new String(response.data, HttpHeaderParser.parseCharset(response.headers)); + return Response.success(new JSONArray(jsonString), + HttpHeaderParser.parseCacheHeaders(response)); + } catch (UnsupportedEncodingException e) { + return Response.error(new ParseError(e)); + } catch (JSONException je) { + return Response.error(new ParseError(je)); + } + } +} diff --git a/app/src/main/java/com/android/volley/toolbox/JsonObjectRequest.java b/app/src/main/java/com/android/volley/toolbox/JsonObjectRequest.java new file mode 100644 index 0000000000..dc82277d71 --- /dev/null +++ b/app/src/main/java/com/android/volley/toolbox/JsonObjectRequest.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley.toolbox; + +import java.io.UnsupportedEncodingException; + +import org.json.JSONException; +import org.json.JSONObject; + +import com.android.volley.NetworkResponse; +import com.android.volley.ParseError; +import com.android.volley.Response; +import com.android.volley.Response.ErrorListener; +import com.android.volley.Response.Listener; + +/** + * A request for retrieving a {@link JSONObject} response body at a given URL, allowing for an + * optional {@link JSONObject} to be passed in as part of the request body. + */ +public class JsonObjectRequest extends JsonRequest { + + /** + * Creates a new request. + * @param method the HTTP method to use + * @param url URL to fetch the JSON from + * @param jsonRequest A {@link JSONObject} to post with the request. Null is allowed and + * indicates no parameters will be posted along with request. + * @param listener Listener to receive the JSON response + * @param errorListener Error listener, or null to ignore errors. + */ + public JsonObjectRequest(int method, String url, JSONObject jsonRequest, + Listener listener, ErrorListener errorListener) { + super(method, url, (jsonRequest == null) ? null : jsonRequest.toString(), listener, + errorListener); + } + + /** + * Constructor which defaults to GET if jsonRequest is + * null, POST otherwise. + * + * @see #JsonObjectRequest(int, String, JSONObject, Listener, ErrorListener) + */ + public JsonObjectRequest(String url, JSONObject jsonRequest, Listener listener, + ErrorListener errorListener) { + this(jsonRequest == null ? Method.GET : Method.POST, url, jsonRequest, + listener, errorListener); + } + + @Override + protected Response parseNetworkResponse(NetworkResponse response) { + try { + String jsonString = + new String(response.data, HttpHeaderParser.parseCharset(response.headers)); + return Response.success(new JSONObject(jsonString), + HttpHeaderParser.parseCacheHeaders(response)); + } catch (UnsupportedEncodingException e) { + return Response.error(new ParseError(e)); + } catch (JSONException je) { + return Response.error(new ParseError(je)); + } + } +} diff --git a/app/src/main/java/com/android/volley/toolbox/JsonRequest.java b/app/src/main/java/com/android/volley/toolbox/JsonRequest.java new file mode 100644 index 0000000000..e60bce16ab --- /dev/null +++ b/app/src/main/java/com/android/volley/toolbox/JsonRequest.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley.toolbox; + +import java.io.UnsupportedEncodingException; + +import com.android.volley.NetworkResponse; +import com.android.volley.Request; +import com.android.volley.Response; +import com.android.volley.Response.ErrorListener; +import com.android.volley.Response.Listener; +import com.android.volley.VolleyLog; + +/** + * A request for retrieving a T type response body at a given URL that also + * optionally sends along a JSON body in the request specified. + * + * @param JSON type of response expected + */ +public abstract class JsonRequest extends Request { + /** Charset for request. */ + private static final String PROTOCOL_CHARSET = "utf-8"; + + /** Content type for request. */ + private static final String PROTOCOL_CONTENT_TYPE = + String.format("application/json; charset=%s", PROTOCOL_CHARSET); + + private final Listener mListener; + private final String mRequestBody; + + /** + * Deprecated constructor for a JsonRequest which defaults to GET unless {@link #getPostBody()} + * or {@link #getPostParams()} is overridden (which defaults to POST). + * + * @deprecated Use {@link #JsonRequest(int, String, String, Listener, ErrorListener)}. + */ + public JsonRequest(String url, String requestBody, Listener listener, + ErrorListener errorListener) { + this(Method.DEPRECATED_GET_OR_POST, url, requestBody, listener, errorListener); + } + + public JsonRequest(int method, String url, String requestBody, Listener listener, + ErrorListener errorListener) { + super(method, url, errorListener); + mListener = listener; + mRequestBody = requestBody; + } + + @Override + protected void deliverResponse(T response) { + mListener.onResponse(response); + } + + @Override + abstract protected Response parseNetworkResponse(NetworkResponse response); + + /** + * @deprecated Use {@link #getBodyContentType()}. + */ + @Override + public String getPostBodyContentType() { + return getBodyContentType(); + } + + /** + * @deprecated Use {@link #getBody()}. + */ + @Override + public byte[] getPostBody() { + return getBody(); + } + + @Override + public String getBodyContentType() { + return PROTOCOL_CONTENT_TYPE; + } + + @Override + public byte[] getBody() { + try { + return mRequestBody == null ? null : mRequestBody.getBytes(PROTOCOL_CHARSET); + } catch (UnsupportedEncodingException uee) { + VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", + mRequestBody, PROTOCOL_CHARSET); + return null; + } + } +} diff --git a/app/src/main/java/com/android/volley/toolbox/NetworkImageView.java b/app/src/main/java/com/android/volley/toolbox/NetworkImageView.java new file mode 100644 index 0000000000..74c91597ef --- /dev/null +++ b/app/src/main/java/com/android/volley/toolbox/NetworkImageView.java @@ -0,0 +1,202 @@ +/** + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.volley.toolbox; + +import android.content.Context; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.ViewGroup.LayoutParams; +import android.widget.ImageView; + +import com.android.volley.VolleyError; +import com.android.volley.toolbox.ImageLoader.ImageContainer; +import com.android.volley.toolbox.ImageLoader.ImageListener; + +/** + * Handles fetching an image from a URL as well as the life-cycle of the + * associated request. + */ +public class NetworkImageView extends ImageView { + /** The URL of the network image to load */ + private String mUrl; + + /** + * Resource ID of the image to be used as a placeholder until the network image is loaded. + */ + private int mDefaultImageId; + + /** + * Resource ID of the image to be used if the network response fails. + */ + private int mErrorImageId; + + /** Local copy of the ImageLoader. */ + private ImageLoader mImageLoader; + + /** Current ImageContainer. (either in-flight or finished) */ + private ImageContainer mImageContainer; + + public NetworkImageView(Context context) { + this(context, null); + } + + public NetworkImageView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public NetworkImageView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + /** + * Sets URL of the image that should be loaded into this view. Note that calling this will + * immediately either set the cached image (if available) or the default image specified by + * {@link NetworkImageView#setDefaultImageResId(int)} on the view. + * + * NOTE: If applicable, {@link NetworkImageView#setDefaultImageResId(int)} and + * {@link NetworkImageView#setErrorImageResId(int)} should be called prior to calling + * this function. + * + * @param url The URL that should be loaded into this ImageView. + * @param imageLoader ImageLoader that will be used to make the request. + */ + public void setImageUrl(String url, ImageLoader imageLoader) { + mUrl = url; + mImageLoader = imageLoader; + // The URL has potentially changed. See if we need to load it. + loadImageIfNecessary(false); + } + + /** + * Sets the default image resource ID to be used for this view until the attempt to load it + * completes. + */ + public void setDefaultImageResId(int defaultImage) { + mDefaultImageId = defaultImage; + } + + /** + * Sets the error image resource ID to be used for this view in the event that the image + * requested fails to load. + */ + public void setErrorImageResId(int errorImage) { + mErrorImageId = errorImage; + } + + /** + * Loads the image for the view if it isn't already loaded. + * @param isInLayoutPass True if this was invoked from a layout pass, false otherwise. + */ + private void loadImageIfNecessary(final boolean isInLayoutPass) { + int width = getWidth(); + int height = getHeight(); + + boolean isFullyWrapContent = getLayoutParams() != null + && getLayoutParams().height == LayoutParams.WRAP_CONTENT + && getLayoutParams().width == LayoutParams.WRAP_CONTENT; + // if the view's bounds aren't known yet, and this is not a wrap-content/wrap-content + // view, hold off on loading the image. + if (width == 0 && height == 0 && !isFullyWrapContent) { + return; + } + + // if the URL to be loaded in this view is empty, cancel any old requests and clear the + // currently loaded image. + if (TextUtils.isEmpty(mUrl)) { + if (mImageContainer != null) { + mImageContainer.cancelRequest(); + mImageContainer = null; + } + setImageBitmap(null); + return; + } + + // if there was an old request in this view, check if it needs to be canceled. + if (mImageContainer != null && mImageContainer.getRequestUrl() != null) { + if (mImageContainer.getRequestUrl().equals(mUrl)) { + // if the request is from the same URL, return. + return; + } else { + // if there is a pre-existing request, cancel it if it's fetching a different URL. + mImageContainer.cancelRequest(); + setImageBitmap(null); + } + } + + // The pre-existing content of this view didn't match the current URL. Load the new image + // from the network. + ImageContainer newContainer = mImageLoader.get(mUrl, + new ImageListener() { + @Override + public void onErrorResponse(VolleyError error) { + if (mErrorImageId != 0) { + setImageResource(mErrorImageId); + } + } + + @Override + public void onResponse(final ImageContainer response, boolean isImmediate) { + // If this was an immediate response that was delivered inside of a layout + // pass do not set the image immediately as it will trigger a requestLayout + // inside of a layout. Instead, defer setting the image by posting back to + // the main thread. + if (isImmediate && isInLayoutPass) { + post(new Runnable() { + @Override + public void run() { + onResponse(response, false); + } + }); + return; + } + + if (response.getBitmap() != null) { + setImageBitmap(response.getBitmap()); + } else if (mDefaultImageId != 0) { + setImageResource(mDefaultImageId); + } + } + }); + + // update the ImageContainer to be the new bitmap container. + mImageContainer = newContainer; + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + loadImageIfNecessary(true); + } + + @Override + protected void onDetachedFromWindow() { + if (mImageContainer != null) { + // If the view was bound to an image request, cancel it and clear + // out the image from the view. + mImageContainer.cancelRequest(); + setImageBitmap(null); + // also clear out the container so we can reload the image if necessary. + mImageContainer = null; + } + super.onDetachedFromWindow(); + } + + @Override + protected void drawableStateChanged() { + super.drawableStateChanged(); + invalidate(); + } +} diff --git a/app/src/main/java/com/android/volley/toolbox/NoCache.java b/app/src/main/java/com/android/volley/toolbox/NoCache.java new file mode 100644 index 0000000000..ab6625435c --- /dev/null +++ b/app/src/main/java/com/android/volley/toolbox/NoCache.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley.toolbox; + +import com.android.volley.Cache; + +/** + * A cache that doesn't. + */ +public class NoCache implements Cache { + @Override + public void clear() { + } + + @Override + public Entry get(String key) { + return null; + } + + @Override + public void put(String key, Entry entry) { + } + + @Override + public void invalidate(String key, boolean fullExpire) { + } + + @Override + public void remove(String key) { + } + + @Override + public void initialize() { + } +} diff --git a/app/src/main/java/com/android/volley/toolbox/PoolingByteArrayOutputStream.java b/app/src/main/java/com/android/volley/toolbox/PoolingByteArrayOutputStream.java new file mode 100644 index 0000000000..f9a0c29183 --- /dev/null +++ b/app/src/main/java/com/android/volley/toolbox/PoolingByteArrayOutputStream.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley.toolbox; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +/** + * A variation of {@link ByteArrayOutputStream} that uses a pool of byte[] buffers instead + * of always allocating them fresh, saving on heap churn. + */ +public class PoolingByteArrayOutputStream extends ByteArrayOutputStream { + /** + * If the {@link #PoolingByteArrayOutputStream(ByteArrayPool)} constructor is called, this is + * the default size to which the underlying byte array is initialized. + */ + private static final int DEFAULT_SIZE = 256; + + private final ByteArrayPool mPool; + + /** + * Constructs a new PoolingByteArrayOutputStream with a default size. If more bytes are written + * to this instance, the underlying byte array will expand. + */ + public PoolingByteArrayOutputStream(ByteArrayPool pool) { + this(pool, DEFAULT_SIZE); + } + + /** + * Constructs a new {@code ByteArrayOutputStream} with a default size of {@code size} bytes. If + * more than {@code size} bytes are written to this instance, the underlying byte array will + * expand. + * + * @param size initial size for the underlying byte array. The value will be pinned to a default + * minimum size. + */ + public PoolingByteArrayOutputStream(ByteArrayPool pool, int size) { + mPool = pool; + buf = mPool.getBuf(Math.max(size, DEFAULT_SIZE)); + } + + @Override + public void close() throws IOException { + mPool.returnBuf(buf); + buf = null; + super.close(); + } + + @Override + public void finalize() { + mPool.returnBuf(buf); + } + + /** + * Ensures there is enough space in the buffer for the given number of additional bytes. + */ + private void expand(int i) { + /* Can the buffer handle @i more bytes, if not expand it */ + if (count + i <= buf.length) { + return; + } + byte[] newbuf = mPool.getBuf((count + i) * 2); + System.arraycopy(buf, 0, newbuf, 0, count); + mPool.returnBuf(buf); + buf = newbuf; + } + + @Override + public synchronized void write(byte[] buffer, int offset, int len) { + expand(len); + super.write(buffer, offset, len); + } + + @Override + public synchronized void write(int oneByte) { + expand(1); + super.write(oneByte); + } +} diff --git a/app/src/main/java/com/android/volley/toolbox/RequestFuture.java b/app/src/main/java/com/android/volley/toolbox/RequestFuture.java new file mode 100644 index 0000000000..78bfb7503b --- /dev/null +++ b/app/src/main/java/com/android/volley/toolbox/RequestFuture.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley.toolbox; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import com.android.volley.Request; +import com.android.volley.Response; +import com.android.volley.VolleyError; + +/** + * A Future that represents a Volley request. + * + * Used by providing as your response and error listeners. For example: + *
+ * RequestFuture<JSONObject> future = RequestFuture.newFuture();
+ * MyRequest request = new MyRequest(URL, future, future);
+ *
+ * // If you want to be able to cancel the request:
+ * future.setRequest(requestQueue.add(request));
+ *
+ * // Otherwise:
+ * requestQueue.add(request);
+ *
+ * try {
+ *   JSONObject response = future.get();
+ *   // do something with response
+ * } catch (InterruptedException e) {
+ *   // handle the error
+ * } catch (ExecutionException e) {
+ *   // handle the error
+ * }
+ * 
+ * + * @param The type of parsed response this future expects. + */ +public class RequestFuture implements Future, Response.Listener, + Response.ErrorListener { + private Request mRequest; + private boolean mResultReceived = false; + private T mResult; + private VolleyError mException; + + public static RequestFuture newFuture() { + return new RequestFuture(); + } + + private RequestFuture() {} + + public void setRequest(Request request) { + mRequest = request; + } + + @Override + public synchronized boolean cancel(boolean mayInterruptIfRunning) { + if (mRequest == null) { + return false; + } + + if (!isDone()) { + mRequest.cancel(); + return true; + } else { + return false; + } + } + + @Override + public T get() throws InterruptedException, ExecutionException { + try { + return doGet(null); + } catch (TimeoutException e) { + throw new AssertionError(e); + } + } + + @Override + public T get(long timeout, TimeUnit unit) + throws InterruptedException, ExecutionException, TimeoutException { + return doGet(TimeUnit.MILLISECONDS.convert(timeout, unit)); + } + + private synchronized T doGet(Long timeoutMs) + throws InterruptedException, ExecutionException, TimeoutException { + if (mException != null) { + throw new ExecutionException(mException); + } + + if (mResultReceived) { + return mResult; + } + + if (timeoutMs == null) { + wait(0); + } else if (timeoutMs > 0) { + wait(timeoutMs); + } + + if (mException != null) { + throw new ExecutionException(mException); + } + + if (!mResultReceived) { + throw new TimeoutException(); + } + + return mResult; + } + + @Override + public boolean isCancelled() { + if (mRequest == null) { + return false; + } + return mRequest.isCanceled(); + } + + @Override + public synchronized boolean isDone() { + return mResultReceived || mException != null || isCancelled(); + } + + @Override + public synchronized void onResponse(T response) { + mResultReceived = true; + mResult = response; + notifyAll(); + } + + @Override + public synchronized void onErrorResponse(VolleyError error) { + mException = error; + notifyAll(); + } +} + diff --git a/app/src/main/java/com/android/volley/toolbox/StringRequest.java b/app/src/main/java/com/android/volley/toolbox/StringRequest.java new file mode 100644 index 0000000000..1a5040c240 --- /dev/null +++ b/app/src/main/java/com/android/volley/toolbox/StringRequest.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley.toolbox; + +import java.io.UnsupportedEncodingException; + +import com.android.volley.NetworkResponse; +import com.android.volley.Request; +import com.android.volley.Response; +import com.android.volley.Response.ErrorListener; +import com.android.volley.Response.Listener; + +/** + * A canned request for retrieving the response body at a given URL as a String. + */ +public class StringRequest extends Request { + private final Listener mListener; + + /** + * Creates a new request with the given method. + * + * @param method the request {@link Method} to use + * @param url URL to fetch the string at + * @param listener Listener to receive the String response + * @param errorListener Error listener, or null to ignore errors + */ + public StringRequest(int method, String url, Listener listener, + ErrorListener errorListener) { + super(method, url, errorListener); + mListener = listener; + } + + /** + * Creates a new GET request. + * + * @param url URL to fetch the string at + * @param listener Listener to receive the String response + * @param errorListener Error listener, or null to ignore errors + */ + public StringRequest(String url, Listener listener, ErrorListener errorListener) { + this(Method.GET, url, listener, errorListener); + } + + @Override + protected void deliverResponse(String response) { + mListener.onResponse(response); + } + + @Override + protected Response parseNetworkResponse(NetworkResponse response) { + String parsed; + try { + parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); + } catch (UnsupportedEncodingException e) { + parsed = new String(response.data); + } + return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response)); + } +} diff --git a/app/src/main/java/com/android/volley/toolbox/Volley.java b/app/src/main/java/com/android/volley/toolbox/Volley.java new file mode 100644 index 0000000000..218672887d --- /dev/null +++ b/app/src/main/java/com/android/volley/toolbox/Volley.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.volley.toolbox; + +import java.io.File; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager.NameNotFoundException; +import android.net.http.AndroidHttpClient; +import android.os.Build; + +import com.android.volley.Network; +import com.android.volley.RequestQueue; + +public class Volley { + + /** Default on-disk cache directory. */ + private static final String DEFAULT_CACHE_DIR = "volley"; + + /** + * Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it. + * + * @param context A {@link Context} to use for creating the cache dir. + * @param stack An {@link HttpStack} to use for the network, or null for default. + * @return A started {@link RequestQueue} instance. + */ + public static RequestQueue newRequestQueue(Context context, HttpStack stack) { + File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR); + + String userAgent = "volley/0"; + try { + String packageName = context.getPackageName(); + PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0); + userAgent = packageName + "/" + info.versionCode; + } catch (NameNotFoundException e) { + } + + if (stack == null) { + if (Build.VERSION.SDK_INT >= 9) { + stack = new HurlStack(); + } else { + // Prior to Gingerbread, HttpUrlConnection was unreliable. + // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html + stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent)); + } + } + + Network network = new BasicNetwork(stack); + + RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network); + queue.start(); + + return queue; + } + + /** + * Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it. + * + * @param context A {@link Context} to use for creating the cache dir. + * @return A started {@link RequestQueue} instance. + */ + public static RequestQueue newRequestQueue(Context context) { + return newRequestQueue(context, null); + } +} diff --git a/app/src/main/java/com/gc/materialdesign/views/CustomView.java b/app/src/main/java/com/gc/materialdesign/views/CustomView.java new file mode 100644 index 0000000000..7a76e38e25 --- /dev/null +++ b/app/src/main/java/com/gc/materialdesign/views/CustomView.java @@ -0,0 +1,55 @@ +package com.gc.materialdesign.views; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.util.AttributeSet; +import android.widget.RelativeLayout; + +public class CustomView extends RelativeLayout{ + + + final static String MATERIALDESIGNXML = "http://schemas.android.com/apk/res-auto"; + final static String ANDROIDXML = "http://schemas.android.com/apk/res/android"; + + final int disabledBackgroundColor = Color.parseColor("#E2E2E2"); + int beforeBackground; + + // Indicate if user touched this view the last time + public boolean isLastTouch = false; + + public CustomView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + if(enabled) + setBackgroundColor(beforeBackground); + else + setBackgroundColor(disabledBackgroundColor); + invalidate(); + } + + boolean animation = false; + + @Override + protected void onAnimationStart() { + super.onAnimationStart(); + animation = true; + } + + @Override + protected void onAnimationEnd() { + super.onAnimationEnd(); + animation = false; + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if(animation) + invalidate(); + } +} diff --git a/app/src/main/java/com/gc/materialdesign/views/ProgressBarCircularIndeterminate.java b/app/src/main/java/com/gc/materialdesign/views/ProgressBarCircularIndeterminate.java new file mode 100644 index 0000000000..c6bac5fe83 --- /dev/null +++ b/app/src/main/java/com/gc/materialdesign/views/ProgressBarCircularIndeterminate.java @@ -0,0 +1,183 @@ +package com.gc.materialdesign.views; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.RectF; +import android.util.AttributeSet; + +public class ProgressBarCircularIndeterminate extends CustomView { + + final static String ANDROIDXML = "http://schemas.android.com/apk/res/android"; + + int backgroundColor = Color.parseColor("#1E88E5"); + + public ProgressBarCircularIndeterminate(Context context, AttributeSet attrs) { + super(context, attrs); + setAttributes(attrs); + + } + + // Set atributtes of XML to View + protected void setAttributes(AttributeSet attrs) { + + setMinimumHeight(Utils.dpToPx(32, getResources())); + setMinimumWidth(Utils.dpToPx(32, getResources())); + + // Set background Color + // Color by resource + int bacgroundColor = attrs.getAttributeResourceValue(ANDROIDXML, + "background", -1); + if (bacgroundColor != -1) { + setBackgroundColor(getResources().getColor(bacgroundColor)); + } else { + // Color by hexadecimal + int background = attrs.getAttributeIntValue(ANDROIDXML, + "background", -1); + if (background != -1) + setBackgroundColor(background); + else + setBackgroundColor(Color.parseColor("#1E88E5")); + } + + setMinimumHeight(Utils.dpToPx(3, getResources())); + + } + + /** + * Make a dark color to ripple effect + * + * @return + */ + protected int makePressColor() { + int r = (this.backgroundColor >> 16) & 0xFF; + int g = (this.backgroundColor >> 8) & 0xFF; + int b = (this.backgroundColor >> 0) & 0xFF; + // r = (r+90 > 245) ? 245 : r+90; + // g = (g+90 > 245) ? 245 : g+90; + // b = (b+90 > 245) ? 245 : b+90; + return Color.argb(128, r, g, b); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (firstAnimationOver == false) + drawFirstAnimation(canvas); + if (cont > 0) + drawSecondAnimation(canvas); + invalidate(); + + } + + float radius1 = 0; + float radius2 = 0; + int cont = 0; + boolean firstAnimationOver = false; + + /** + * Draw first animation of view + * + * @param canvas + */ + private void drawFirstAnimation(Canvas canvas) { + if (radius1 < getWidth() / 2) { + Paint paint = new Paint(); + paint.setAntiAlias(true); + paint.setColor(makePressColor()); + radius1 = (radius1 >= getWidth() / 2) ? (float) getWidth() / 2 + : radius1 + 1; + canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius1, paint); + } else { + Bitmap bitmap = Bitmap.createBitmap(canvas.getWidth(), + canvas.getHeight(), Bitmap.Config.ARGB_8888); + Canvas temp = new Canvas(bitmap); + Paint paint = new Paint(); + paint.setAntiAlias(true); + paint.setColor(makePressColor()); + temp.drawCircle(getWidth() / 2, getHeight() / 2, getHeight() / 2, + paint); + Paint transparentPaint = new Paint(); + transparentPaint.setAntiAlias(true); + transparentPaint.setColor(getResources().getColor( + android.R.color.transparent)); + transparentPaint.setXfermode(new PorterDuffXfermode( + PorterDuff.Mode.CLEAR)); + if (cont >= 50) { + radius2 = (radius2 >= getWidth() / 2) ? (float) getWidth() / 2 + : radius2 + 1; + } else { + radius2 = (radius2 >= getWidth() / 2 + - Utils.dpToPx(4, getResources())) ? (float) getWidth() + / 2 - Utils.dpToPx(4, getResources()) : radius2 + 1; + } + temp.drawCircle(getWidth() / 2, getHeight() / 2, radius2, + transparentPaint); + canvas.drawBitmap(bitmap, 0, 0, new Paint()); + if (radius2 >= getWidth() / 2 - Utils.dpToPx(4, getResources())) + cont++; + if (radius2 >= getWidth() / 2) + firstAnimationOver = true; + } + } + + int arcD = 1; + int arcO = 0; + float rotateAngle = 0; + int limite = 0; + + /** + * Draw second animation of view + * + * @param canvas + */ + private void drawSecondAnimation(Canvas canvas) { + if (arcO == limite) + arcD += 6; + if (arcD >= 290 || arcO > limite) { + arcO += 6; + arcD -= 6; + } + if (arcO > limite + 290) { + limite = arcO; + arcO = limite; + arcD = 1; + } + rotateAngle += 4; + canvas.rotate(rotateAngle, getWidth() / 2, getHeight() / 2); + + Bitmap bitmap = Bitmap.createBitmap(canvas.getWidth(), + canvas.getHeight(), Bitmap.Config.ARGB_8888); + Canvas temp = new Canvas(bitmap); + Paint paint = new Paint(); + paint.setAntiAlias(true); + paint.setColor(backgroundColor); + // temp.drawARGB(0, 0, 0, 255); + temp.drawArc(new RectF(0, 0, getWidth(), getHeight()), arcO, arcD, + true, paint); + Paint transparentPaint = new Paint(); + transparentPaint.setAntiAlias(true); + transparentPaint.setColor(getResources().getColor( + android.R.color.transparent)); + transparentPaint.setXfermode(new PorterDuffXfermode( + PorterDuff.Mode.CLEAR)); + temp.drawCircle(getWidth() / 2, getHeight() / 2, (getWidth() / 2) + - Utils.dpToPx(4, getResources()), transparentPaint); + + canvas.drawBitmap(bitmap, 0, 0, new Paint()); + } + + // Set color of background + public void setBackgroundColor(int color) { + super.setBackgroundColor(getResources().getColor( + android.R.color.transparent)); + if (isEnabled()) + beforeBackground = backgroundColor; + this.backgroundColor = color; + } + +} diff --git a/app/src/main/java/com/gc/materialdesign/views/Utils.java b/app/src/main/java/com/gc/materialdesign/views/Utils.java new file mode 100644 index 0000000000..abb6540ae9 --- /dev/null +++ b/app/src/main/java/com/gc/materialdesign/views/Utils.java @@ -0,0 +1,34 @@ +package com.gc.materialdesign.views; + +import android.content.res.Resources; +import android.util.TypedValue; +import android.view.View; + +public class Utils { + + + /** + * Convert Dp to Pixel + */ + public static int dpToPx(float dp, Resources resources){ + float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, resources.getDisplayMetrics()); + return (int) px; + } + + public static int getRelativeTop(View myView) { +// if (myView.getParent() == myView.getRootView()) + if(myView.getId() == android.R.id.content) + return myView.getTop(); + else + return myView.getTop() + getRelativeTop((View) myView.getParent()); + } + + public static int getRelativeLeft(View myView) { +// if (myView.getParent() == myView.getRootView()) + if(myView.getId() == android.R.id.content) + return myView.getLeft(); + else + return myView.getLeft() + getRelativeLeft((View) myView.getParent()); + } + +} diff --git a/app/src/main/java/com/gh/base/AppController.java b/app/src/main/java/com/gh/base/AppController.java new file mode 100644 index 0000000000..5a70b8d999 --- /dev/null +++ b/app/src/main/java/com/gh/base/AppController.java @@ -0,0 +1,230 @@ +package com.gh.base; + +import java.util.ArrayList; +import java.util.List; + +import android.app.Activity; +import android.app.ActivityManager; +import android.app.ActivityManager.RunningAppProcessInfo; +import android.app.Application; +import android.content.Context; +import android.os.Process; +import android.support.v4.util.ArrayMap; +import android.text.TextUtils; +import android.util.Log; + +import com.android.volley.Request; +import com.android.volley.RequestQueue; +import com.android.volley.toolbox.Volley; +import com.gh.base.GHPushMessageReceiver.PushHandler; +import com.gh.common.util.Utils; +import com.tendcloud.tenddata.TCAgent; +import com.xiaomi.channel.commonutils.logger.LoggerInterface; +import com.xiaomi.mipush.sdk.Logger; +import com.xiaomi.mipush.sdk.MiPushClient; + +public class AppController extends Application { + public static final String TAG = AppController.class.getSimpleName(); + + private RequestQueue mRequestQueue; + + private static AppController mInstance; + + // xiaomi push appid + public static final String APP_ID = "2882303761517352993"; + // xiaomi push appkey + public static final String APP_KEY = "5451735292993"; + + private static PushHandler handler = null; + + private static ArrayMap objectMap = new ArrayMap(); + + public static void put(String key, Object object) { + objectMap.put(key, object); + } + + public static Object get(String key, boolean isRemove) { + if (isRemove) { + return objectMap.remove(key); + } else { + return objectMap.get(key); + } + } + + public static void remove(String key) { + objectMap.remove(key); + } + + private ArrayList list = new ArrayList(); + + private boolean isFinish = false; + + /** + * Activity关闭时,删除Activity列表中的Activity对象 + */ + public void removeActivity(Activity a) { + if (!isFinish) { + list.remove(a); + Utils.log("remove = " + a.getClass().getSimpleName()); + } + } + + /** + * 向Activity列表中添加Activity对象 + */ + public void addActivity(Activity a) { + Utils.log("add = " + a.getClass().getSimpleName()); + list.add(a); + } + + /** + * 关闭Activity列表中的所有Activity + */ + public void finishActivity() { + isFinish = true; + for (int i = list.size() - 1; i >= 0; i--) { + Activity activity = list.get(i); + if (null != activity) { + Utils.log("finish = " + activity.getClass().getSimpleName()); + activity.finish(); + } + } + // 杀死该应用进程 + Process.killProcess(Process.myPid()); + } + + @Override + public void onCreate() { + super.onCreate(); + + TCAgent.LOG_ON = true; + TCAgent.init(this); + TCAgent.setReportUncaughtExceptions(true); + AppUncaHandler uncaHandler = new AppUncaHandler(this); + Thread.setDefaultUncaughtExceptionHandler(uncaHandler); + mInstance = this; + + // 注册push服务,注册成功后会向GHPushMessageReceiver发送广播 + // 可以从GHPushMessageReceiver的onCommandResult方法中MiPushCommandMessage对象参数中获取注册信息 + if (shouldInit()) { + MiPushClient.registerPush(this, APP_ID, APP_KEY); + } + + LoggerInterface newLogger = new LoggerInterface() { + + @Override + public void setTag(String tag) { + // ignore + } + + @Override + public void log(String content, Throwable t) { + Log.d(TAG, content, t); + } + + @Override + public void log(String content) { + Log.d(TAG, content); + } + }; + Logger.setLogger(this, newLogger); + if (handler == null) + handler = new PushHandler(this); + + } + + public static String getProcessName(Context cxt, int pid) { + ActivityManager am = (ActivityManager) cxt + .getSystemService(Context.ACTIVITY_SERVICE); + List runningApps = am.getRunningAppProcesses(); + if (runningApps == null) { + return null; + } + for (RunningAppProcessInfo procInfo : runningApps) { + if (procInfo.pid == pid) { + return procInfo.processName; + } + } + return null; + } + + public static synchronized AppController getInstance() { + return mInstance; + } + + public void addRequest(Request request) { + if (mRequestQueue == null) { + mRequestQueue = Volley.newRequestQueue(getApplicationContext()); + } + mRequestQueue.add(request); + } + + public void cancleRequest(Object tag){ + if (mRequestQueue != null) { + mRequestQueue.cancelAll(tag); + } + } + + public static void addToRequestQueue(Request request) { + request.setTag(TAG); + getInstance().addRequest(request); + } + + public static void addToRequestQueue(Request request, String tag) { + request.setTag(TextUtils.isEmpty(tag) ? TAG : tag); + getInstance().addRequest(request); + } + + public static void addToRequestQueue(Request request, Object obj) { + String tag = null; + if (obj != null) { + tag = obj.getClass().getSimpleName(); + } + addToRequestQueue(request, tag); + } + + public static void addToRequestQueue(Request request, Class clazz) { + String tag = null; + if (clazz != null) { + tag = clazz.getSimpleName(); + } + addToRequestQueue(request, tag); + } + + public static void canclePendingRequests(String tag) { + if (tag != null) { + getInstance().cancleRequest(tag); + } + } + + public static void canclePendingRequests(Object obj) { + if (obj != null) { + getInstance().cancleRequest(obj.getClass().getSimpleName()); + } + } + + public static void canclePendingRequests(Class clazz) { + if (clazz != null) { + getInstance().cancleRequest(clazz.getSimpleName()); + } + } + + private boolean shouldInit() { + ActivityManager am = ((ActivityManager) getSystemService(Context.ACTIVITY_SERVICE)); + List processInfos = am.getRunningAppProcesses(); + String mainProcessName = getPackageName(); + Log.d(TAG, mainProcessName); + int myPid = Process.myPid(); + for (RunningAppProcessInfo info : processInfos) { + if (info.pid == myPid && mainProcessName.equals(info.processName)) { + return true; + } + } + return false; + } + + public static PushHandler getHandler() { + return handler; + } + +} diff --git a/app/src/main/java/com/gh/base/AppUncaHandler.java b/app/src/main/java/com/gh/base/AppUncaHandler.java new file mode 100644 index 0000000000..1c63444d39 --- /dev/null +++ b/app/src/main/java/com/gh/base/AppUncaHandler.java @@ -0,0 +1,123 @@ +package com.gh.base; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.lang.Thread.UncaughtExceptionHandler; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.os.Looper; +import android.util.Log; +import android.widget.Toast; + +import com.gh.common.util.FileUtils; +import com.gh.gamecenter.SplashScreenActivity; +import com.gh.gamecenter.manager.DataCollectionManager; + +public class AppUncaHandler implements UncaughtExceptionHandler { + + private UncaughtExceptionHandler mDefaultHandler; + private AppController appController; + + public AppUncaHandler(AppController appController) { + // 获取系统默认的UncaughtException处理器 + mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); + this.appController = appController; + } + + @Override + public void uncaughtException(Thread thread, Throwable ex) { + if (!handleException(ex) && mDefaultHandler != null) { + // 如果用户没有处理则让系统默认的异常处理器来处理 + mDefaultHandler.uncaughtException(thread, ex); + } else { + new Thread() { + @Override + public void run() { + Looper.prepare(); + Toast.makeText(appController.getApplicationContext(), + "\"光环助手\"发生错误", Toast.LENGTH_SHORT).show(); + Looper.loop(); + } + }.start(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + Intent intent = new Intent(appController.getApplicationContext(), + SplashScreenActivity.class); + intent.setAction(Intent.ACTION_MAIN); + intent.addCategory(Intent.CATEGORY_LAUNCHER); + PendingIntent restartIntent = PendingIntent.getActivity( + appController.getApplicationContext(), 0, intent, + Intent.FLAG_ACTIVITY_NEW_TASK); + // 退出程序并重启 + AlarmManager mgr = (AlarmManager) appController + .getSystemService(Context.ALARM_SERVICE); + mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, + restartIntent); // 1秒钟后重启应用 + appController.finishActivity(); + } + } + + // 保存log到本地 + private void saveLog(Throwable ex) { + String errorMsg = Log.getStackTraceString(ex); + + Map map = new HashMap(); + map.put("content", errorMsg); + map.put("createdOn", System.currentTimeMillis() / 1000); + map.put("type", android.os.Build.MODEL); + map.put("system", android.os.Build.VERSION.SDK_INT + "=" + + android.os.Build.VERSION.RELEASE); + DataCollectionManager.onEvent(appController.getApplicationContext(), + "error", map, false); + + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", + Locale.getDefault()); + File file = new File(FileUtils.getLogPath( + appController.getApplicationContext(), + format.format(new Date()) + "_gh_assist" + ".log")); + FileWriter writer = null; + try { + file.createNewFile(); + writer = new FileWriter(file); + writer.write(errorMsg); + writer.flush(); + } catch (IOException e1) { + e1.printStackTrace(); + } finally { + if (writer != null) { + try { + writer.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + /** + * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. + * + * @param ex + * @return true:如果处理了该异常信息;否则返回false. + */ + private boolean handleException(Throwable ex) { + if (ex == null) { + return false; + } + saveLog(ex); + return true; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/base/BaseActivity.java b/app/src/main/java/com/gh/base/BaseActivity.java new file mode 100644 index 0000000000..42217a3790 --- /dev/null +++ b/app/src/main/java/com/gh/base/BaseActivity.java @@ -0,0 +1,250 @@ +package com.gh.base; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.content.Context; +import android.os.Build; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup.LayoutParams; +import android.view.Window; +import android.view.WindowManager; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; +import cn.sharesdk.framework.ShareSDK; +import cn.sharesdk.onekeyshare.OnekeyShare; +import cn.sharesdk.onekeyshare.PlatformListFakeActivity.OnShareButtonClickListener; + +import com.gh.common.constant.Config; +import com.gh.common.util.DialogUtils; +import com.gh.common.util.DisplayUtils; +import com.gh.common.util.RunningUtils; +import com.gh.common.util.Utils; +import com.gh.gamecenter.R; +import com.gh.gamecenter.eventbus.EBShowDialog; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.manager.SystemBarTintManager; +import com.gh.gamecenter.manager.SystemBarTintManager.SystemBarConfig; +import com.tendcloud.tenddata.TCAgent; + +import de.greenrobot.event.EventBus; + +public class BaseActivity extends Activity { + private String LOG = this.getClass().getName(); + private boolean LOG_ON = true; + + private boolean isPause; + + private SystemBarTintManager tintManager; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + AppLog("onCreate"); + Utils.log(this.getClass().getSimpleName()); + AppController.getInstance().addActivity(this); + EventBus.getDefault().register(this); + } + + protected void init(View contentView, String title) { + init(contentView); + TextView actionbar_tv_title = (TextView) findViewById(R.id.actionbar_tv_title); + actionbar_tv_title.setText(title); + } + + protected void init(View contentView) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + setTheme(R.style.AppTheme); + setTranslucentStatus(true); + tintManager = new SystemBarTintManager(this); + tintManager.setStatusBarTintEnabled(true); + tintManager.setStatusBarTintResource(R.color.theme_colors); + SystemBarConfig config = tintManager.getConfig(); + contentView.setPadding(0, config.getPixelInsetTop(false), 0, + config.getPixelInsetBottom()); + } + + setContentView(contentView); + + int actionbar_height = getSharedPreferences(Config.PREFERENCE, + Context.MODE_PRIVATE).getInt("actionbar_height", + DisplayUtils.dip2px(getApplicationContext(), 48)); + + RelativeLayout reuse_actionbar = (RelativeLayout) findViewById(R.id.reuse_actionbar); + LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams( + LayoutParams.MATCH_PARENT, actionbar_height); + reuse_actionbar.setLayoutParams(lparams); + + findViewById(R.id.actionbar_rl_back).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + + //简化findViewById + try { + Class clazz = this.getClass(); + Field[] fields = clazz.getDeclaredFields(); + for (Field field : fields) { + int id = Utils.getId(field.getName()); + if (id != -1) { + Utils.log("reflect name = " + field.getName()); + field.setAccessible(true); + Class fieldType = field.getType(); + Object injectedValue = fieldType.cast(findViewById(id)); + field.set(this, injectedValue); + field.setAccessible(false); + } + } + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + + protected SystemBarTintManager getTintManager() { + return tintManager; + } + + @Override + public void finish() { + super.finish(); + AppController.getInstance().removeActivity(this); + } + + public void AppLog(String str) { + if (LOG_ON) { + Log.i(LOG, str); + } + } + + public void toast(String msg) { + Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); + } + + public void toast(int msg) { + Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); + } + + @TargetApi(19) + protected void setTranslucentStatus(boolean status) { + Window window = getWindow(); + WindowManager.LayoutParams winParams = window.getAttributes(); + final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; + if (status) { + winParams.flags |= bits; + } else { + winParams.flags &= ~bits; + } + window.setAttributes(winParams); + } + + public void showShare(String url, String title, String icon, String entrance, String type) { + ShareSDK.initSDK(this); + + OnekeyShare oks = new OnekeyShare(); + // 关闭sso授权 + oks.disableSSOWhenAuthorize(); + + // 分享时Notification的图标和文字 2.5.9以后的版本不调用此方法 + // oks.setNotification(R.drawable.ic_launcher, + // getString(R.string.app_name)); + // title标题,印象笔记、邮箱、信息、微信、人人网和QQ空间使用 + oks.setTitle(title); + // titleUrl是标题的网络链接,仅在人人网和QQ空间使用 + oks.setTitleUrl(url); + // text是分享文本,所有平台都需要这个字段 + oks.setText(title + " " + url); + // imagePath是图片的本地路径,Linked-In以外的平台都支持此参数 + // oks.setImagePath(icon);//确保SDcard下面存在此张图片 + oks.setImageUrl(icon); + // url仅在微信(包括好友和朋友圈)中使用 + oks.setUrl(url); + // comment是我对这条分享的评论,仅在人人网和QQ空间使用 + oks.setComment("精彩尽在" + url); + // site是分享此内容的网站名称,仅在QQ空间使用 + oks.setSite(this.getString(R.string.app_name)); + // siteUrl是分享此内容的网站地址,仅在QQ空间使用 + oks.setSiteUrl(url); + + final Map map = new HashMap(); + map.put("title", title); + map.put("url", url); + map.put("from", entrance); + map.put("createdOn", System.currentTimeMillis() / 1000); + + oks.setOnShareButtonClickListener(new OnShareButtonClickListener() { + @Override + public void onClick(View v, List checkPlatforms) { + map.put("method", checkPlatforms.get(0).getClass().getSimpleName()); + DataCollectionManager.onEvent(BaseActivity.this, "share", map); + } + }); + + // 启动分享GUI + oks.show(this); + + TCAgent.onEvent(this, "内容分享", title); + } + + public void onEventMainThread(EBShowDialog showDialog) { + if (!isPause && this.getClass().getName().equals(RunningUtils.getTopActivity(this))) { + if ("hijack".equals(showDialog.getType())) { + DialogUtils.showHijackDialog(this); + } else if ("delete".equals(showDialog.getType())) { + DialogUtils.showDeleteDialog(this, showDialog.getPath()); + } + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + protected void onPause() { + super.onPause(); + AppLog("onPause"); + TCAgent.onPause(this); + isPause = true; + } + + @Override + protected void onRestart() { + super.onRestart(); + AppLog("onRestart"); + } + + @Override + protected void onResume() { + super.onResume(); + AppLog("onResume"); + TCAgent.onResume(this); + isPause = false; + } + + @Override + protected void onStart() { + super.onStart(); + AppLog("onStart"); + } + + @Override + protected void onStop() { + super.onStop(); + AppLog("onStop"); + } + +} diff --git a/app/src/main/java/com/gh/base/BaseFragmentActivity.java b/app/src/main/java/com/gh/base/BaseFragmentActivity.java new file mode 100644 index 0000000000..a0988af640 --- /dev/null +++ b/app/src/main/java/com/gh/base/BaseFragmentActivity.java @@ -0,0 +1,244 @@ +package com.gh.base; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import android.annotation.TargetApi; +import android.content.Context; +import android.os.Build; +import android.os.Bundle; +import android.support.v4.app.FragmentActivity; +import android.util.Log; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup.LayoutParams; +import android.view.Window; +import android.view.WindowManager; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; +import cn.sharesdk.framework.ShareSDK; +import cn.sharesdk.onekeyshare.OnekeyShare; +import cn.sharesdk.onekeyshare.PlatformListFakeActivity.OnShareButtonClickListener; + +import com.gh.common.constant.Config; +import com.gh.common.util.DialogUtils; +import com.gh.common.util.DisplayUtils; +import com.gh.common.util.RunningUtils; +import com.gh.common.util.Utils; +import com.gh.gamecenter.R; +import com.gh.gamecenter.eventbus.EBShowDialog; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.manager.SystemBarTintManager; +import com.gh.gamecenter.manager.SystemBarTintManager.SystemBarConfig; +import com.tendcloud.tenddata.TCAgent; + +import de.greenrobot.event.EventBus; + +public class BaseFragmentActivity extends FragmentActivity { + private String LOG = this.getClass().getName(); + private boolean LOG_ON = false; + + private boolean isPause; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + AppLog("onCreate"); + Utils.log(this.getClass().getSimpleName()); + AppController.getInstance().addActivity(this); + EventBus.getDefault().register(this); + } + + public void init(View contentView, String title) { + init(contentView); + TextView actionbar_tv_title = (TextView) findViewById(R.id.actionbar_tv_title); + actionbar_tv_title.setText(title); + } + + public void init(View contentView) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + setTheme(R.style.AppTheme); + setTranslucentStatus(true); + SystemBarTintManager tintManager = new SystemBarTintManager(this); + tintManager.setStatusBarTintEnabled(true); + tintManager.setStatusBarTintResource(R.color.theme_colors); + SystemBarConfig config = tintManager.getConfig(); + contentView.setPadding(0, config.getPixelInsetTop(false), 0, + config.getPixelInsetBottom()); + } + + setContentView(contentView); + + int actionbar_height = getSharedPreferences(Config.PREFERENCE, + Context.MODE_PRIVATE).getInt("actionbar_height", + DisplayUtils.dip2px(getApplicationContext(), 48)); + + RelativeLayout reuse_actionbar = (RelativeLayout) findViewById(R.id.reuse_actionbar); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( + LayoutParams.MATCH_PARENT, actionbar_height); + reuse_actionbar.setLayoutParams(params); + + findViewById(R.id.actionbar_rl_back).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + + try { + Class clazz = this.getClass(); + Field[] fields = clazz.getDeclaredFields(); + for (Field field : fields) { + int id = Utils.getId(field.getName()); + if (id != -1) { + Utils.log("reflect name = " + field.getName()); + field.setAccessible(true); + Class fieldType = field.getType(); + Object injectedValue = fieldType.cast(findViewById(id)); + field.set(this, injectedValue); + field.setAccessible(false); + } + } + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + + @Override + public void finish() { + super.finish(); + AppController.getInstance().removeActivity(this); + } + + public void AppLog(String str) { + if (LOG_ON) { + Log.i(LOG, str); + } + } + + public void toast(String msg) { + Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); + } + + public void toast(int msg) { + Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); + } + + @TargetApi(19) + protected void setTranslucentStatus(boolean status) { + Window window = getWindow(); + WindowManager.LayoutParams winParams = window.getAttributes(); + final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; + if (status) { + winParams.flags |= bits; + } else { + winParams.flags &= ~bits; + } + window.setAttributes(winParams); + } + + public void showShare(String url, String title, String icon, + String entrance, String type) { + + ShareSDK.initSDK(this); + OnekeyShare oks = new OnekeyShare(); + // 关闭sso授权 + oks.disableSSOWhenAuthorize(); + + // 分享时Notification的图标和文字 2.5.9以后的版本不调用此方法 + // oks.setNotification(R.drawable.ic_launcher, + // getString(R.string.app_name)); + // title标题,印象笔记、邮箱、信息、微信、人人网和QQ空间使用 + oks.setTitle(title); + // titleUrl是标题的网络链接,仅在人人网和QQ空间使用 + oks.setTitleUrl(url); + // text是分享文本,所有平台都需要这个字段 + oks.setText(title + " " + url); + // imagePath是图片的本地路径,Linked-In以外的平台都支持此参数 + // oks.setImagePath(icon);//确保SDcard下面存在此张图片 + oks.setImageUrl(icon); + // url仅在微信(包括好友和朋友圈)中使用 + oks.setUrl(url); + // comment是我对这条分享的评论,仅在人人网和QQ空间使用 + oks.setComment("精彩尽在" + url); + // site是分享此内容的网站名称,仅在QQ空间使用 + oks.setSite(this.getString(R.string.app_name)); + // siteUrl是分享此内容的网站地址,仅在QQ空间使用 + oks.setSiteUrl(url); + + final Map map = new HashMap(); + map.put("title", title); + map.put("url", url); + map.put("from", entrance); + map.put("createdOn", System.currentTimeMillis() / 1000); + + oks.setOnShareButtonClickListener(new OnShareButtonClickListener() { + @Override + public void onClick(View v, List checkPlatforms) { + map.put("method", checkPlatforms.get(0).getClass() + .getSimpleName()); + DataCollectionManager.onEvent(BaseFragmentActivity.this, + "share", map); + } + }); + + // 启动分享GUI + oks.show(this); + TCAgent.onEvent(this, "内容分享", title); + } + + public void onEventMainThread(EBShowDialog showDialog) { + if (!isPause && this.getClass().getName().equals(RunningUtils.getTopActivity(this))) { + if ("hijack".equals(showDialog.getType())) { + DialogUtils.showHijackDialog(this); + } else if ("delete".equals(showDialog.getType())) { + DialogUtils.showDeleteDialog(this, showDialog.getPath()); + } + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + protected void onPause() { + super.onPause(); + AppLog("onPause"); + TCAgent.onPause(this); + isPause = true; + } + + @Override + protected void onRestart() { + super.onRestart(); + AppLog("onRestart"); + } + + @Override + protected void onResume() { + super.onResume(); + AppLog("onResume"); + TCAgent.onResume(this); + isPause = false; + } + + @Override + protected void onStart() { + super.onStart(); + AppLog("onStart"); + } + + @Override + protected void onStop() { + super.onStop(); + AppLog("onStop"); + } +} diff --git a/app/src/main/java/com/gh/base/GHPushMessageReceiver.java b/app/src/main/java/com/gh/base/GHPushMessageReceiver.java new file mode 100644 index 0000000000..4127eba84a --- /dev/null +++ b/app/src/main/java/com/gh/base/GHPushMessageReceiver.java @@ -0,0 +1,440 @@ +package com.gh.base; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import android.annotation.SuppressLint; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.graphics.BitmapFactory; +import android.os.Build; +import android.os.Handler; +import android.os.Message; +import android.support.v4.app.NotificationCompat; +import android.support.v4.util.ArrayMap; +import android.text.TextUtils; +import android.util.Log; +import android.widget.RemoteViews; + +import com.gh.common.util.FileUtils; +import com.gh.common.util.PackageUtils; +import com.gh.common.util.Utils; +import com.gh.gamecenter.R; +import com.xiaomi.mipush.sdk.ErrorCode; +import com.xiaomi.mipush.sdk.MiPushClient; +import com.xiaomi.mipush.sdk.MiPushCommandMessage; +import com.xiaomi.mipush.sdk.MiPushMessage; +import com.xiaomi.mipush.sdk.PushMessageReceiver; + +/** + * 1、PushMessageReceiver是个抽象类,该类继承了BroadcastReceiver。 + * 2、需要将自定义的DemoMessageReceiver注册在AndroidManifest.xml文件中 + * + * + * + * + * 3、DemoMessageReceiver的onReceivePassThroughMessage方法用来接收服务器向客户端发送的透传消息 + * 4、DemoMessageReceiver的onNotificationMessageClicked方法用来接收服务器向客户端发送的通知消息, + * 这个回调方法会在用户手动点击通知后触发 + * 5、DemoMessageReceiver的onNotificationMessageArrived方法用来接收服务器向客户端发送的通知消息, + * 这个回调方法是在通知消息到达客户端时触发。另外应用在前台时不弹出通知的通知消息到达客户端也会触发这个回调函数 + * 6、DemoMessageReceiver的onCommandResult方法用来接收客户端向服务器发送命令后的响应结果 + * 7、DemoMessageReceiver的onReceiveRegisterResult方法用来接收客户端向服务器发送注册命令后的响应结果 + * 8、以上这些方法运行在非UI线程中 + * + * @author mayixiang + */ +public class GHPushMessageReceiver extends PushMessageReceiver { + + private String mRegId; + private long mResultCode = -1; + private String mReason; + private String mCommand; + private String mMessage; + private String mTopic; + private String mAlias; + private String mAccount; + private String mStartTime; + private String mEndTime; + + @Override + public void onReceivePassThroughMessage(Context context, + MiPushMessage message) { + // 1判断notifyid是否为4 + try { + if (message.getNotifyId() == 4) { + JSONObject jsonObject = new JSONObject(message.getContent()); + Utils.log(jsonObject.toString()); + String channel = jsonObject.getString("channel"); + Utils.log("channel = " + channel); + // 1判断渠道号是否一致或是否为ALL + String TD_CHANNEL_ID = (String) PackageUtils.getMetaData(context, context.getPackageName(), "TD_CHANNEL_ID"); + if ("ALL".equals(channel) + || TD_CHANNEL_ID + .equalsIgnoreCase(channel)) { + String type = jsonObject.getString("type"); + Utils.log("type = " + type); + if ("NEWS".equals(type)) { + // 新闻推送 + JSONArray jsonArray = jsonObject + .getJSONArray("package"); + ArrayMap map = getInstalledMapFromLocal(context); + for (int i = 0; i < jsonArray.length(); i++) { + Boolean b = map.get(jsonArray.getString(i)); + if (b != null) { + // 显示推送的消息 + showNotification(context, jsonObject, 0); + break; + } + } + } else if ("PLUGIN_UPDATE".equals(type)) { + // 插件更新推送 + JSONArray jsonArray = jsonObject.getJSONArray("apk"); + ArrayMap map = getInstalledMapFromLocal(context); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject apk = jsonArray.getJSONObject(i); + String packageName = apk.getString("package"); + Boolean b = map.get(packageName); + if (b != null) { + // 判断是否gh_version是否相同 + String gh_version = (String) PackageUtils + .getMetaData(context, packageName, "gh_version"); + if (gh_version != null) { + gh_version = gh_version.substring(2); + // 判断gh_version是否相同 + if (gh_version.equals(apk + .getString("gh_version"))) { + // 判断version是否相同 + String version = PackageUtils + .getVersionByPackage(context, + packageName); + if (version.equals(apk + .getString("version"))) { + // 版本相同,无需显示插件更新,继续查看是否有可更新的游戏包 + continue; + } + } + } + // 显示推送的消息 + showNotification(context, jsonObject, 1); + break; + } + } + } else if ("NEW_GAME".equals(type)) { + // 新游推送 + showNotification(context, jsonObject, 2); + } + } + } + } catch (JSONException e) { + e.printStackTrace(); + } + + Log.v(AppController.TAG, "onReceivePassThroughMessage is called. " + + message.toString()); + String log = context.getString(R.string.recv_passthrough_message, + message.getContent()); + + if (!TextUtils.isEmpty(message.getTopic())) { + mTopic = message.getTopic(); + } else if (!TextUtils.isEmpty(message.getAlias())) { + mAlias = message.getAlias(); + } + + Message msg = Message.obtain(); + msg.obj = log; + AppController.getHandler().sendMessage(msg); + } + + private void showNotification(Context context, JSONObject jsonObject, int id) + throws JSONException { + Intent intent = new Intent(); + intent.setAction("com.gh.gamecenter.NOTIFICATION"); + intent.putExtra("notifyId", id); + intent.putExtra("notifyData", jsonObject.toString()); + PendingIntent pendingIntent = PendingIntent.getBroadcast(context, id, + intent, PendingIntent.FLAG_ONE_SHOT); + + NotificationManager nManager = (NotificationManager) context + .getSystemService(Context.NOTIFICATION_SERVICE); + + Notification notification = new NotificationCompat.Builder(context) + .setSmallIcon(R.drawable.logo) + .setTicker(jsonObject.getString("pushTitle")) + .setContentTitle(jsonObject.getString("pushTitle")) + .setContentText(jsonObject.getString("pushDesc")) + .setContentIntent(pendingIntent).build(); + + RemoteViews remoteViews = null; + + if (Build.MANUFACTURER.equals("Meizu") + && (Build.MODEL.startsWith("m") || Build.MODEL.startsWith("MX"))) { + remoteViews = new RemoteViews(context.getPackageName(), + R.layout.notification_meizu); + SimpleDateFormat format = new SimpleDateFormat("HH:mm", + Locale.getDefault()); + remoteViews.setTextViewText(R.id.time, format.format(new Date())); + } else if (Build.MANUFACTURER.equals("Xiaomi") + && (Build.MODEL.startsWith("MI") + || Build.MODEL.startsWith("HM") || Build.MODEL + .startsWith("Redmi"))) { + // 小米系统 + remoteViews = new RemoteViews(context.getPackageName(), + R.layout.notification_xiaomi); + SimpleDateFormat format = new SimpleDateFormat("ah:mm", + Locale.getDefault()); + remoteViews.setTextViewText(R.id.time, format.format(new Date())); + } else if (Build.MANUFACTURER.equals("HUAWEI")) { + // 华为系统 + remoteViews = new RemoteViews(context.getPackageName(), + R.layout.notification_huawei); + } + + String url = jsonObject.getString("icon"); + String path = context.getCacheDir() + File.separator + + url.substring(url.lastIndexOf("/") + 1); + try { + FileUtils.downloadFile(url, path); + } catch (IOException e) { + e.printStackTrace(); + } + if (remoteViews != null) { + remoteViews.setImageViewBitmap(R.id.icon, + BitmapFactory.decodeFile(path)); + // remoteViews.setImageViewResource(R.id.icon, R.drawable.me_icon); + remoteViews.setTextViewText(R.id.title, + jsonObject.getString("pushTitle")); + remoteViews.setTextViewText(R.id.intro, + jsonObject.getString("pushDesc")); + notification.contentView = remoteViews; + } else { + notification = new NotificationCompat.Builder(context) + .setSmallIcon(R.drawable.logo_black) + .setTicker(jsonObject.getString("pushTitle")) + .setContentTitle(jsonObject.getString("pushTitle")) + .setContentText(jsonObject.getString("pushDesc")) + .setContentIntent(pendingIntent) + .setLargeIcon(BitmapFactory.decodeFile(path)).build(); + } + + notification.defaults = Notification.DEFAULT_SOUND;// 添加系统默认声音 + notification.flags |= Notification.FLAG_AUTO_CANCEL; // FLAG_AUTO_CANCEL表明当通知被用户点击时,通知将被清除。 + nManager.notify(((int) System.currentTimeMillis() / 1000), notification);// 通过通知管理器来发起通知。如果id不同,则每click,在status哪里增加一个提示 + } + + private ArrayMap getInstalledMapFromLocal(Context context) { + ArrayMap map = new ArrayMap(); + ArrayList list = getAllPackageName(context); + for (String str : list) { + map.put(str, true); + } + return map; + } + + private ArrayList getAllPackageName(Context context) { + ArrayList list = new ArrayList(); + List packageInfos = context.getPackageManager() + .getInstalledPackages(0); + for (int i = 0, size = packageInfos.size(); i < size; i++) { + PackageInfo packageInfo = packageInfos.get(i); + if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { + list.add(packageInfo.packageName); + } + } + return list; + } + + @Override + public void onNotificationMessageClicked(Context context, + MiPushMessage message) { + Log.v(AppController.TAG, "onNotificationMessageClicked is called. " + + message.toString()); + String log = context.getString(R.string.click_notification_message, + message.getContent()); + + if (!TextUtils.isEmpty(message.getTopic())) { + mTopic = message.getTopic(); + } else if (!TextUtils.isEmpty(message.getAlias())) { + mAlias = message.getAlias(); + } + + Message msg = Message.obtain(); + if (message.isNotified()) { + msg.obj = log; + } + AppController.getHandler().sendMessage(msg); + + } + + @Override + public void onNotificationMessageArrived(Context context, + MiPushMessage message) { + Log.v(AppController.TAG, "onNotificationMessageArrived is called. " + + message.toString()); + String log = context.getString(R.string.arrive_notification_message, + message.getContent()); + + if (!TextUtils.isEmpty(message.getTopic())) { + mTopic = message.getTopic(); + } else if (!TextUtils.isEmpty(message.getAlias())) { + mAlias = message.getAlias(); + } + + Message msg = Message.obtain(); + msg.obj = log; + AppController.getHandler().sendMessage(msg); + } + + @Override + public void onCommandResult(Context context, MiPushCommandMessage message) { + Log.v(AppController.TAG, + "onCommandResult is called. " + message.toString()); + String command = message.getCommand(); + List arguments = message.getCommandArguments(); + String cmdArg1 = ((arguments != null && arguments.size() > 0) ? arguments + .get(0) : null); + String cmdArg2 = ((arguments != null && arguments.size() > 1) ? arguments + .get(1) : null); + String log = ""; + if (MiPushClient.COMMAND_REGISTER.equals(command)) { + if (message.getResultCode() == ErrorCode.SUCCESS) { + mRegId = cmdArg1; + log = context.getString(R.string.register_success); + } else { + log = context.getString(R.string.register_fail); + } + } else if (MiPushClient.COMMAND_SET_ALIAS.equals(command)) { + if (message.getResultCode() == ErrorCode.SUCCESS) { + mAlias = cmdArg1; + log = context.getString(R.string.set_alias_success, mAlias); + } else { + log = context.getString(R.string.set_alias_fail, + message.getReason()); + } + } else if (MiPushClient.COMMAND_UNSET_ALIAS.equals(command)) { + if (message.getResultCode() == ErrorCode.SUCCESS) { + mAlias = cmdArg1; + log = context.getString(R.string.unset_alias_success, mAlias); + } else { + log = context.getString(R.string.unset_alias_fail, + message.getReason()); + } + } else if (MiPushClient.COMMAND_SET_ACCOUNT.equals(command)) { + if (message.getResultCode() == ErrorCode.SUCCESS) { + mAccount = cmdArg1; + log = context.getString(R.string.set_account_success, mAccount); + } else { + log = context.getString(R.string.set_account_fail, + message.getReason()); + } + } else if (MiPushClient.COMMAND_UNSET_ACCOUNT.equals(command)) { + if (message.getResultCode() == ErrorCode.SUCCESS) { + mAccount = cmdArg1; + log = context.getString(R.string.unset_account_success, + mAccount); + } else { + log = context.getString(R.string.unset_account_fail, + message.getReason()); + } + } else if (MiPushClient.COMMAND_SUBSCRIBE_TOPIC.equals(command)) { + if (message.getResultCode() == ErrorCode.SUCCESS) { + mTopic = cmdArg1; + log = context.getString(R.string.subscribe_topic_success, + mTopic); + } else { + log = context.getString(R.string.subscribe_topic_fail, + message.getReason()); + } + } else if (MiPushClient.COMMAND_UNSUBSCRIBE_TOPIC.equals(command)) { + if (message.getResultCode() == ErrorCode.SUCCESS) { + log = context.getString(R.string.unsubscribe_topic_success, + mTopic); + } else { + log = context.getString(R.string.unsubscribe_topic_fail, + message.getReason()); + } + } else if (MiPushClient.COMMAND_SET_ACCEPT_TIME.equals(command)) { + if (message.getResultCode() == ErrorCode.SUCCESS) { + mStartTime = cmdArg1; + mEndTime = cmdArg2; + log = context.getString(R.string.set_accept_time_success, + mStartTime, mEndTime); + } else { + log = context.getString(R.string.set_accept_time_fail, + message.getReason()); + } + } else { + log = message.getReason(); + } + + Message msg = Message.obtain(); + msg.obj = log; + AppController.getHandler().sendMessage(msg); + } + + @Override + public void onReceiveRegisterResult(Context context, + MiPushCommandMessage message) { + Log.v(AppController.TAG, "onReceiveRegisterResult is called. " + + message.toString()); + String command = message.getCommand(); + List arguments = message.getCommandArguments(); + String cmdArg1 = ((arguments != null && arguments.size() > 0) ? arguments + .get(0) : null); + String log; + if (MiPushClient.COMMAND_REGISTER.equals(command)) { + if (message.getResultCode() == ErrorCode.SUCCESS) { + mRegId = cmdArg1; + log = context.getString(R.string.register_success); + } else { + log = context.getString(R.string.register_fail); + } + } else { + log = message.getReason(); + } + + Message msg = Message.obtain(); + msg.obj = log; + AppController.getHandler().sendMessage(msg); + } + + @SuppressLint("SimpleDateFormat") + public static String getSimpleDate() { + return new SimpleDateFormat("MM-dd hh:mm:ss").format(new Date()); + } + + public static class PushHandler extends Handler { + + private Context context; + + public PushHandler(Context context) { + this.context = context; + } + + @Override + public void handleMessage(Message msg) { + String s = (String) msg.obj; + + if (!TextUtils.isEmpty(s)) { + // Toast.makeText(context, s, Toast.LENGTH_LONG).show(); + } + } + } +} diff --git a/app/src/main/java/com/gh/common/constant/Config.java b/app/src/main/java/com/gh/common/constant/Config.java new file mode 100644 index 0000000000..78626f0391 --- /dev/null +++ b/app/src/main/java/com/gh/common/constant/Config.java @@ -0,0 +1,16 @@ +package com.gh.common.constant; + +import com.gh.gamecenter.SplashScreenActivity; + + +public final class Config { + + // test host dev.ghzhushou.com/api + public static final String HOST = "http://api.ghzhushou.com/"; +// public static final String HOST = "http://115.28.145.16:9001/"; + + public static final String PREFERENCE = "ghzhushou"; + +// public static final boolean isShow = true; + public static final boolean isShow = SplashScreenActivity.isShow; +} diff --git a/app/src/main/java/com/gh/common/constant/Constants.java b/app/src/main/java/com/gh/common/constant/Constants.java new file mode 100644 index 0000000000..9b483f164f --- /dev/null +++ b/app/src/main/java/com/gh/common/constant/Constants.java @@ -0,0 +1,41 @@ +package com.gh.common.constant; + +public class Constants { + + public static final int CONTINUE_DOWNLOAD_TASK = 0x123; + public static final int PAUSE_DOWNLOAD_TASK = 0x124; + public static final int DOWNLOAD_ROLL = 0x125; + public static final int SEND_NEWS_FEEDBACK = 0x126; + public static final int SEND_COMMENT_FEEDBACK = 0x127; + + public static final String KEY_DOWNLOAD_ENTRY = "key_download_entry"; + public static final String KEY_DOWNLOAD_ACTION = "key_download_action"; + + public static final int MAX_DOWNLOAD_THREAD_SIZE = 3; + public static final int MAX_DOWNLOADING_SIZE = 3; + public static final long SPEED_CHECK_INTERVAL = 1000;//速度监测频率 + + //手机号码匹配规则 + public static final String REGEX_MOBILE = "^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$"; + public static final String REGEX_ACCOUNT = "^[a-zA-Z_]\\w{5,17}$"; + public static final String REGEX_PASSWORD = "^[a-zA-Z]\\w{5,31}$"; + + //输入规则 + public static final String INPUT_RULE = "0123456789abcdefghijklnmopqrstuvwxyzABCDEFGHIJKLNMOPQRSTUVWXYZ_"; + + //最少需要多少数据才能上传 + public static final int DATA_AMOUNT = 20; + + //游戏 cd间隔 + public static final int GAME_CD = 5 * 60 * 1000; + //新闻 cd间隔 + public static final int NEWS_CD = 10 * 60 * 1000; + //platform cd间隔 + public static final int PLATFORM_CD = 10 * 60 * 1000; + //update cd间隔 + public static final int UPDATE_CD = 5 * 60 * 1000; + //搜索 cd间隔 + public static final int SEARCH_CD = 5 * 60 * 1000; + //评论 cd间隔 + public static final int COMMENT_CD = 5 * 60 * 1000; +} diff --git a/app/src/main/java/com/gh/common/util/DataCollectionUtils.java b/app/src/main/java/com/gh/common/util/DataCollectionUtils.java new file mode 100644 index 0000000000..50218dbd8c --- /dev/null +++ b/app/src/main/java/com/gh/common/util/DataCollectionUtils.java @@ -0,0 +1,89 @@ +package com.gh.common.util; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import android.content.Context; + +import com.android.volley.Request.Method; +import com.android.volley.Response; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.common.constant.Constants; +import com.gh.gamecenter.db.DataCollectionDao; +import com.gh.gamecenter.db.info.DataCollectionInfo; +import com.gh.gamecenter.volley.extended.JsonObjectExtendedRequest; + +public class DataCollectionUtils { + + public static void uploadData(Context context) { + final DataCollectionDao dao = new DataCollectionDao(context); + List list = dao.getAll(); + if (list.size() >= Constants.DATA_AMOUNT) { + String url = "http://114.215.139.210/data/collection/upload"; + HashMap> params = new HashMap>(); + final ArrayList ids = new ArrayList(); + DataCollectionInfo entity = null; + ArrayList data = null; + for (int i = 0, size = list.size(); i < size; i++) { + entity = list.get(i); + ids.add(entity.getId()); + String type = entity.getType(); + entity.getData(); + data = params.get(type); + if (data == null) { + data = new ArrayList(); + params.put(type, data); + } + data.add(entity.getData()); + } + JSONArray body = new JSONArray(); + JSONObject jsonObject = null; + try { + for (String key : params.keySet()) { + data = params.get(key); + jsonObject = new JSONObject(); + jsonObject.put("type", key); + jsonObject.put("data", data); + body.put(jsonObject); + } + } catch (JSONException e) { + e.printStackTrace(); + } + + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Method.POST, url, body.toString(), + new Response.Listener() { + @Override + public void onResponse(JSONObject response) { + Utils.log(response.toString()); + try { + if ("success".equals(response + .getString("status"))) { + // 删除数据库数据 + dao.delete(ids); + } + } catch (JSONException e) { + e.printStackTrace(); + } + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + Utils.log(error.toString()); + if (error.networkResponse != null) { + Utils.log(new String(error.networkResponse.data)); + } + } + }); + AppController.addToRequestQueue(request, DataCollectionUtils.class); + } + + } + +} diff --git a/app/src/main/java/com/gh/common/util/DeviceUtils.java b/app/src/main/java/com/gh/common/util/DeviceUtils.java new file mode 100644 index 0000000000..3d02a34a9d --- /dev/null +++ b/app/src/main/java/com/gh/common/util/DeviceUtils.java @@ -0,0 +1,59 @@ +package com.gh.common.util; + +import java.util.HashMap; +import java.util.Map; + +import android.content.Context; +import android.net.wifi.WifiManager; +import android.provider.Settings.Secure; +import android.telephony.TelephonyManager; +import android.text.TextUtils; + +public class DeviceUtils { + + public synchronized static String getDeviceHeader(Context context) { + StringBuffer buffer = new StringBuffer(); + String imei = ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId(); + if (!TextUtils.isEmpty(imei)) { + buffer.append("imei=" + imei); + } + String android_id = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID); + if (!TextUtils.isEmpty(android_id)) { + if (buffer.length() != 0) { + buffer.append(","); + } + buffer.append("android_id=" + android_id); + } + WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + String mac = wm.getConnectionInfo().getMacAddress(); + if (!TextUtils.isEmpty(mac)) { + if (buffer.length() != 0) { + buffer.append(","); + } + buffer.append("mac=" + mac); + } + return buffer.toString(); + } + + public synchronized static Map getDeviceParams(Context context) { + HashMap params = new HashMap(); + params.put("imei", ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId()); + params.put("android_id", Secure.getString(context.getContentResolver(), Secure.ANDROID_ID)); + WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + params.put("mac", wm.getConnectionInfo().getMacAddress()); + return params; + } + + public synchronized static String getDeviceID(Context context) { + String imei = ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId(); + if (!TextUtils.isEmpty(imei)) { + return imei; + } + String android_id = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID); + if (!TextUtils.isEmpty(android_id)) { + return android_id; + } + return Installation.getUUID(context); + } + +} diff --git a/app/src/main/java/com/gh/common/util/DialogUtils.java b/app/src/main/java/com/gh/common/util/DialogUtils.java new file mode 100644 index 0000000000..c0426e21d9 --- /dev/null +++ b/app/src/main/java/com/gh/common/util/DialogUtils.java @@ -0,0 +1,167 @@ +package com.gh.common.util; + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.Window; +import android.widget.TextView; + +import com.gh.gamecenter.MainActivity; +import com.gh.gamecenter.R; + +public class DialogUtils { + + public static Dialog showWaitDialog(Context context, String msg) { + Dialog dialog = new Dialog(context); + View view = View.inflate(context, R.layout.set_wait_dialog, null); + TextView message = (TextView) view.findViewById(R.id.set_wait_message); + message.setText(msg); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.setCanceledOnTouchOutside(false); + dialog.show(); + return dialog; + } + + public static void showDialog(final Context context, final String path) { + final Dialog dialog = new Dialog(context); + View view = View.inflate(context, + R.layout.search_history_delete_dialog, null); + TextView title = (TextView) view.findViewById(R.id.delete_dialog_title); + title.setText("卸载"); + TextView content = (TextView) view + .findViewById(R.id.delete_dialog_message); + + content.setText("您已安装了官方原版,该版本与插件版本冲突,是否卸载官方原版?"); + + TextView cancel = (TextView) view + .findViewById(R.id.delete_dialog_cancel); + cancel.setText("忽略"); + cancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + TextView confirem = (TextView) view + .findViewById(R.id.delete_dialog_confirm); + confirem.setText("卸载"); + confirem.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Utils.log("packageName = " + + PackageUtils.getPackageNameByPath(context, path)); + MainActivity.uninstallMap.put( + PackageUtils.getPackageNameByPath(context, path), path); + context.startActivity(PackageUtils.getUninstallIntent(context, + path)); + dialog.dismiss(); + } + }); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.show(); + } + + private static boolean isShowHijackDialog = false; + + public static void showHijackDialog(final Context context) { + if (!isShowHijackDialog) { + final Dialog dialog = new Dialog(context); + View view = View.inflate(context, + R.layout.search_history_delete_dialog, null); + TextView title = (TextView) view + .findViewById(R.id.delete_dialog_title); + title.setText("警告"); + TextView content = (TextView) view + .findViewById(R.id.delete_dialog_message); + + content.setText("您当前网络环境异常,下载地址已被替换(网络劫持),请更换网络环境进行下载。"); + + TextView cancel = (TextView) view + .findViewById(R.id.delete_dialog_cancel); + cancel.setText("取消"); + cancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + TextView confirem = (TextView) view + .findViewById(R.id.delete_dialog_confirm); + confirem.setText("确定"); + confirem.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + // 跳转wifi管理界面 + Intent intent = new Intent("android.settings.WIFI_SETTINGS"); + context.startActivity(intent); + dialog.dismiss(); + } + }); + dialog.setOnDismissListener(new Dialog.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + isShowHijackDialog = false; + } + }); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.show(); + isShowHijackDialog = true; + } + } + + private static boolean isShowDeleteDialog = false; + + public static void showDeleteDialog(final Context context, final String path) { + if (!isShowDeleteDialog) { + final Dialog dialog = new Dialog(context); + View view = View.inflate(context, + R.layout.search_history_delete_dialog, null); + TextView title = (TextView) view.findViewById(R.id.delete_dialog_title); + title.setText("卸载"); + TextView content = (TextView) view + .findViewById(R.id.delete_dialog_message); + + content.setText("您已安装了官方原版,该版本与插件版本冲突,是否卸载官方原版?"); + + TextView cancel = (TextView) view + .findViewById(R.id.delete_dialog_cancel); + cancel.setText("忽略"); + cancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + TextView confirem = (TextView) view + .findViewById(R.id.delete_dialog_confirm); + confirem.setText("卸载"); + confirem.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + MainActivity.uninstallMap.put( + PackageUtils.getPackageNameByPath(context, path), path); + context.startActivity(PackageUtils.getUninstallIntent(context, + path)); + dialog.dismiss(); + } + }); + dialog.setOnDismissListener(new Dialog.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + isShowDeleteDialog = false; + } + }); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.show(); + isShowDeleteDialog = true; + } + } + +} diff --git a/app/src/main/java/com/gh/common/util/DisplayUtils.java b/app/src/main/java/com/gh/common/util/DisplayUtils.java new file mode 100644 index 0000000000..3ef710bdd6 --- /dev/null +++ b/app/src/main/java/com/gh/common/util/DisplayUtils.java @@ -0,0 +1,65 @@ +package com.gh.common.util; + +import android.content.Context; +import android.content.res.Resources; + +public class DisplayUtils { + + /** + * 根据手机的分辨率从 dip(像素) 的单位 转成为 px + */ + public static int dip2px(Context context, float dpValue) { + final float scale = context.getResources().getDisplayMetrics().density; + return (int) (dpValue * scale + 0.5f); + } + + /** + * 根据手机的分辨率从 px(像素) 的单位 转成为 dip + */ + public static int px2dip(Context context, float pxValue) { + final float scale = context.getResources().getDisplayMetrics().density; + return (int) (pxValue / scale + 0.5f); + } + + /** + * 将px值转换为sp值,保证文字大小不变 + * + * @param pxValue + * @param fontScale + * (DisplayMetrics类中属性scaledDensity) + * @return + */ + public static int px2sp(Context context, float pxValue) { + final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; + return (int) (pxValue / fontScale + 0.5f); + } + + /** + * 将sp值转换为px值,保证文字大小不变 + * + * @param spValue + * @param fontScale + * (DisplayMetrics类中属性scaledDensity) + * @return + */ + public static int sp2px(Context context, float spValue) { + final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; + return (int) (spValue * fontScale + 0.5f); + } + + /** + * 获取状态栏的高度 + * @param res + * @param key + * @return + */ + public static int getInternalDimensionSize(Resources res, String key) { + int result = 0; + int resourceId = res.getIdentifier(key, "dimen", "android"); + if (resourceId > 0) { + result = res.getDimensionPixelSize(resourceId); + } + return result; + } + +} diff --git a/app/src/main/java/com/gh/common/util/DownloadItemUtils.java b/app/src/main/java/com/gh/common/util/DownloadItemUtils.java new file mode 100644 index 0000000000..eb31448941 --- /dev/null +++ b/app/src/main/java/com/gh/common/util/DownloadItemUtils.java @@ -0,0 +1,793 @@ +package com.gh.common.util; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.LinkedBlockingQueue; + +import android.app.Dialog; +import android.content.Context; +import android.os.Handler; +import android.os.Message; +import android.support.v4.util.ArrayMap; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.Window; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.Toast; + +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.common.view.DownloadDialog; +import com.gh.download.DownloadEntry; +import com.gh.download.DownloadManager; +import com.gh.gamecenter.R; +import com.gh.gamecenter.entity.ApkEntity; +import com.gh.gamecenter.entity.DismissEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.eventbus.EBPutUrl; +import com.gh.gamecenter.eventbus.EBRedDot; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.manager.PackageManager; +import com.tendcloud.tenddata.TCAgent; + +import de.greenrobot.event.EventBus; + +public class DownloadItemUtils { + + public static void initializeGameMap(Context context, + ArrayMap> gameMap) { + gameMap.clear(); + List list = DownloadManager.getInstance(context) + .getAll(); + for (int i = 0, size = list.size(); i < size; i++) { + ArrayMap map = gameMap.get(list.get(i) + .getName()); + if (map == null) { + map = new ArrayMap(); + } + map.put(list.get(i).getMeta().get("platform"), list.get(i)); + gameMap.put(list.get(i).getName(), map); + } + } + + public static void processDate(GameEntity detailedEntity, + DownloadEntry downloadEntry, + ArrayMap> platformMap, + Handler handler, + RecyclerView.Adapter adapter, int index, + ArrayMap statusMap) { + + String platform = downloadEntry.getMeta().get("platform"); + LinkedBlockingQueue queue = platformMap.get(downloadEntry + .getName()); + if (queue == null) { + queue = new LinkedBlockingQueue(); + } + + ArrayMap entryMap = detailedEntity.getEntryMap(); + + switch (downloadEntry.getStatus()) { + case pause: + case cancel: + case done: + queue.remove(platform); + platformMap.put(downloadEntry.getName(), queue); + if (entryMap == null) { + entryMap = new ArrayMap(); + detailedEntity.setEntryMap(entryMap); + } + entryMap.put(platform, downloadEntry); + if (!"pause".equals(statusMap.get(downloadEntry.getUrl()))) { + adapter.notifyItemChanged(index); + } + break; + default: + if (!queue.contains(platform)) { + queue.offer(platform); + if (queue.size() == 2) { + Message msg = Message.obtain(); + msg.obj = downloadEntry.getName(); + msg.what = Constants.DOWNLOAD_ROLL; + handler.sendMessageDelayed(msg, 3000); + } + } + platformMap.put(downloadEntry.getName(), queue); + if (platform.equals(queue.peek())) { + if (entryMap == null) { + entryMap = new ArrayMap(); + detailedEntity.setEntryMap(entryMap); + } + entryMap.put(platform, downloadEntry); + if (!"pause".equals(statusMap.get(downloadEntry.getUrl()))) { + adapter.notifyItemChanged(index); + } + } + break; + } + } + + public static void updateItem(Context context, LinearLayout labelList, + ProgressBar game_progressbar, LinearLayout game_ll_info, + TextView download_speed, TextView download_percentage, + TextView downloadBtn, GameEntity entity, + ArrayMap> platformMap, + ArrayMap statusMap, boolean isShowPlatform) { + + // 控制是否显示下载按钮 + if (Config.isShow) { + downloadBtn.setVisibility(View.VISIBLE); + } else { + downloadBtn.setVisibility(View.GONE); + } + + if (entity.getApk() != null + && entity.getApk().size() == 1 + && PackageManager.isInstalled(entity.getApk().get(0) + .getPackageName())) { + labelList.setVisibility(View.VISIBLE); + game_progressbar.setVisibility(View.GONE); + game_ll_info.setVisibility(View.GONE); + downloadBtn.setText("启动"); + downloadBtn.setBackgroundResource(R.drawable.textview_orange_style); + downloadBtn.setTextColor(0xFFFFFFFF); + } else { + ArrayMap entryMap = entity.getEntryMap(); + + if (entryMap != null && !entryMap.isEmpty()) { + + DownloadEntry downloadEntry; + + LinkedBlockingQueue queue = platformMap.get(entity + .getName()); + + if (queue != null && !queue.isEmpty()) { + downloadEntry = entryMap.get(queue.peek()); + } else { + downloadEntry = entryMap.get(entryMap.keyAt(0)); + } + + if (downloadEntry != null) { + labelList.setVisibility(View.GONE); + game_progressbar.setVisibility(View.VISIBLE); + game_ll_info.setVisibility(View.VISIBLE); + + String platform = PlatformUtils.getInstance(context) + .getPlatformName( + downloadEntry.getMeta().get("platform")); + + switch (downloadEntry.getStatus()) { + case downloading: + if (!"pause".equals(statusMap.get(downloadEntry + .getUrl()))) { + if (isShowPlatform) { + if (platform == null) { + download_speed + .setText(SpeedUtils + .getSpeed(downloadEntry + .getSpeed()) + + "(剩" + + SpeedUtils.getRemainTime( + downloadEntry + .getSize(), + downloadEntry + .getProgress(), + downloadEntry + .getSpeed() * 1024) + + ")"); + } else { + download_speed + .setText(platform + + " - " + + SpeedUtils + .getSpeed(downloadEntry + .getSpeed()) + + "(剩" + + SpeedUtils.getRemainTime( + downloadEntry + .getSize(), + downloadEntry + .getProgress(), + downloadEntry + .getSpeed() * 1024) + + ")"); + } + } else { + download_speed + .setText(SpeedUtils + .getSpeed(downloadEntry + .getSpeed()) + + "(剩" + + SpeedUtils.getRemainTime( + downloadEntry.getSize(), + downloadEntry + .getProgress(), + downloadEntry + .getSpeed() * 1024) + + ")"); + } + } + download_percentage.setText(downloadEntry.getPercent() + + "%"); + if (entity.getApk() != null + && entity.getApk().size() == 1) { + downloadBtn.setText("暂停"); + downloadBtn + .setBackgroundResource(R.drawable.textview_gray_style); + downloadBtn.setTextColor(0xFF999999); + } else { + downloadBtn.setText("下载"); + downloadBtn + .setBackgroundResource(R.drawable.textview_blue_style); + downloadBtn.setTextColor(0xFFFFFFFF); + } + break; + case waiting: + if (isShowPlatform) { + if (platform == null) { + download_speed.setText("等待"); + } else { + download_speed.setText(platform + " - 等待"); + } + } else { + download_speed.setText("等待"); + } + download_percentage.setText(downloadEntry.getPercent() + + "%"); + if (entity.getApk() != null + && entity.getApk().size() == 1) { + downloadBtn.setText("取消"); + downloadBtn + .setBackgroundResource(R.drawable.textview_gray_style); + downloadBtn.setTextColor(0xFF999999); + } else { + downloadBtn.setText("下载"); + downloadBtn + .setBackgroundResource(R.drawable.textview_blue_style); + downloadBtn.setTextColor(0xFFFFFFFF); + } + break; + case done: + if (isShowPlatform) { + if (platform == null) { + download_speed.setText("下载完成"); + } else { + download_speed.setText(platform + " - 下载完成"); + } + } else { + download_speed.setText("下载完成"); + } + download_percentage.setText("100%"); + if (entity.getApk() != null + && entity.getApk().size() == 1) { + EventBus.getDefault().post( + new EBPutUrl(entity.getApk().get(0) + .getPackageName(), downloadEntry + .getUrl())); + downloadBtn.setText("安装"); + downloadBtn + .setBackgroundResource(R.drawable.textview_blue_style); + downloadBtn.setTextColor(0xFFFFFFFF); + } else { + labelList.setVisibility(View.VISIBLE); + game_progressbar.setVisibility(View.GONE); + game_ll_info.setVisibility(View.GONE); + downloadBtn.setText("下载"); + downloadBtn + .setBackgroundResource(R.drawable.textview_blue_style); + downloadBtn.setTextColor(0xFFFFFFFF); + } + break; + case pause: + case neterror: + if (isShowPlatform) { + if (platform == null) { + download_speed.setText("暂停"); + } else { + download_speed.setText(platform + " - 暂停"); + } + } else { + download_speed.setText("暂停"); + } + download_percentage.setText(downloadEntry.getPercent() + + "%"); + if (entity.getApk() != null + && entity.getApk().size() == 1) { + downloadBtn.setText("继续"); + downloadBtn + .setBackgroundResource(R.drawable.textview_blue_style); + downloadBtn.setTextColor(0xFFFFFFFF); + } else { + downloadBtn.setText("下载"); + downloadBtn + .setBackgroundResource(R.drawable.textview_blue_style); + downloadBtn.setTextColor(0xFFFFFFFF); + } + break; + case cancel: + case hijack: + labelList.setVisibility(View.VISIBLE); + game_progressbar.setVisibility(View.GONE); + game_ll_info.setVisibility(View.GONE); + downloadBtn.setText("下载"); + downloadBtn.setBackgroundResource(R.drawable.textview_blue_style); + downloadBtn.setTextColor(0xFFFFFFFF); + break; + default: + break; + } + game_progressbar.setProgress((int) (downloadEntry + .getPercent() * 10)); + } + } else { + labelList.setVisibility(View.VISIBLE); + game_progressbar.setVisibility(View.GONE); + game_ll_info.setVisibility(View.GONE); + if (entity.getApk() != null) { + downloadBtn.setText("下载"); + downloadBtn + .setBackgroundResource(R.drawable.textview_blue_style); + downloadBtn.setTextColor(0xFFFFFFFF); + } + } + } + } + + public static void updateItem(Context context, LinearLayout labelList, + ProgressBar game_progressbar, LinearLayout game_ll_info, + TextView download_speed, TextView download_percentage, + TextView downloadBtn, GameEntity entity, + ArrayMap> platformMap, + ArrayMap statusMap) { + updateItem(context, labelList, game_progressbar, game_ll_info, + download_speed, download_percentage, downloadBtn, entity, + platformMap, statusMap, true); + } + + public static void setOnClickListener(Context context, + TextView downloadBtn, TextView download_speed, + TextView download_percentage, GameEntity entity, int position, + RecyclerView.Adapter adapter, + Handler handler, ArrayMap lastTimeMap, + ArrayMap statusMap, + ArrayMap> platformMap, + String entrance, DismissEntity dismissEntity, String location) { + setOnClickListener(context, downloadBtn, download_speed, + download_percentage, entity, position, adapter, handler, + lastTimeMap, statusMap, platformMap, entrance, true, + dismissEntity, location); + } + + public static void setOnClickListener(final Context context, + final TextView downloadBtn, final TextView download_speed, + final TextView download_percentage, final GameEntity entity, + final int position, + final RecyclerView.Adapter adapter, + final Handler handler, final ArrayMap lastTimeMap, + final ArrayMap statusMap, + final ArrayMap> platformMap, + final String entrance, final boolean isShowPlatform, + final DismissEntity dismissEntity, final String location) { + downloadBtn.setOnClickListener(new OnClickListener() { + @Override + public void onClick(final View viewBtn) { + String str = downloadBtn.getText().toString(); + if ("下载".equals(str)) { + if (entity.getApk() == null || entity.getApk().isEmpty()) { + Toast.makeText(context, "稍等片刻~!游戏正在上传中...", + Toast.LENGTH_SHORT).show(); + } else { + if (NetworkUtils.isWifiConnected(context)) { + if (entity.getApk().size() == 1) { + String msg = FileUtils.isCanDownload(entity + .getApk().get(0).getSize()); + if (TextUtils.isEmpty(msg)) { + Map kv = new HashMap(); + kv.put("版本", entity.getApk().get(0) + .getPlatform()); + kv.put("状态", "下载开始"); + TCAgent.onEvent(context, "游戏下载", + entity.getName(), kv); + + Map kv2 = new HashMap(); + kv2.put("版本", entity.getApk().get(0) + .getPlatform()); + kv2.put("状态", "下载开始"); + kv2.put("位置", entrance + "-开始"); + TCAgent.onEvent(context, "游戏下载位置", + entity.getName(), kv2); + + Map kv3 = new HashMap(); + kv3.put(entrance, "下载数"); + kv3.put(entrance, "下载开始"); + TCAgent.onEvent(context, "应用数据", + entity.getName(), kv3); + + if ("主页-最新插件".equals(entrance)) { + Map kv4 = new HashMap(); + kv4.put(entity.getName(), "下载数"); + TCAgent.onEvent(context, "主页数据", + "最新插件", kv4); + } else if ("主页-热门卡牌".equals(entrance)) { + Map kv4 = new HashMap(); + kv4.put(entity.getName(), "下载数"); + TCAgent.onEvent(context, "主页数据", + "热门卡牌", kv4); + } else if ("主页-新测卡牌".equals(entrance)) { + Map kv4 = new HashMap(); + kv4.put(entity.getName(), "下载数"); + TCAgent.onEvent(context, "主页数据", + "新测卡牌", kv4); + } + + Map map = new HashMap(); + map.put("game", entity.getName()); + map.put("method", "正常"); + map.put("platform", + PlatformUtils + .getInstance(context) + .getPlatformName( + entity.getApk() + .get(0) + .getPlatform())); + map.put("status", "开始"); + map.put("location", + "游戏详情:" + entity.getName()); + map.put("from", entrance); + map.put("network", NetworkUtils + .getConnectedType(context)); + map.put("createdOn", + System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent(context, + "download", map); + + DownloadManager.getInstance(context).add( + getDownloadEntry(context, entity, + 0, entrance)); + Toast.makeText(context, + entity.getName() + "已加入下载队列", + Toast.LENGTH_SHORT).show(); + downloadBtn.setText("暂停"); + downloadBtn + .setBackgroundResource(R.drawable.textview_gray_style); + downloadBtn.setTextColor(0xFF999999); + EventBus.getDefault().post(new EBRedDot(1)); + + statusMap.put(entity.getApk().get(0) + .getUrl(), "downloading"); + } else { + Toast.makeText(context, msg, + Toast.LENGTH_SHORT).show(); + } + } else { + if (!dismissEntity.isShow()) { + dismissEntity.setShow(true); + DownloadDialog.getInstance(context) + .showPopupWindow(viewBtn, entity, + entrance, handler, + lastTimeMap, statusMap, + download_speed, + download_percentage, + location); + } + } + } else { + + final Dialog dialog = new Dialog(context); + View view = View + .inflate( + context, + R.layout.search_history_delete_dialog, + null); + TextView title = (TextView) view + .findViewById(R.id.delete_dialog_title); + title.setText("警告"); + TextView content = (TextView) view + .findViewById(R.id.delete_dialog_message); + + content.setText("您当前的网络为2G/3G/4G,下载将会消耗移动流量,是否继续下载?"); + + TextView cancel = (TextView) view + .findViewById(R.id.delete_dialog_cancel); + cancel.setText("取消"); + cancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + TextView confirem = (TextView) view + .findViewById(R.id.delete_dialog_confirm); + confirem.setText("继续"); + confirem.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + if (entity.getApk() == null + || entity.getApk().isEmpty()) { + Toast.makeText(context, + "稍等片刻~!游戏正在上传中...", + Toast.LENGTH_SHORT).show(); + } else { + if (entity.getApk().size() == 1) { + String msg = FileUtils + .isCanDownload(entity + .getApk().get(0) + .getSize()); + if (TextUtils.isEmpty(msg)) { + Map kv = new HashMap(); + kv.put("版本", entity.getApk() + .get(0).getPlatform()); + kv.put("状态", "下载开始"); + TCAgent.onEvent(context, + "游戏下载", + entity.getName(), kv); + + Map kv2 = new HashMap(); + kv2.put("版本", entity.getApk() + .get(0).getPlatform()); + kv2.put("状态", "下载开始"); + kv2.put("位置", entrance + "-开始"); + TCAgent.onEvent(context, + "游戏下载位置", + entity.getName(), kv2); + + Map map = new HashMap(); + map.put("game", + entity.getName()); + map.put("method", "正常"); + map.put("platform", + PlatformUtils + .getInstance( + context) + .getPlatformName( + entity.getApk() + .get(0) + .getPlatform())); + map.put("status", "开始"); + map.put("location", "游戏详情:" + + entity.getName()); + map.put("from", entrance); + map.put("network", + NetworkUtils + .getConnectedType(context)); + map.put("createdOn", + System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent( + context, "download", + map); + + DownloadManager.getInstance( + context).add( + getDownloadEntry( + context, + entity, 0, + entrance)); + Toast.makeText( + context, + entity.getName() + + "已加入下载队列", + Toast.LENGTH_SHORT) + .show(); + downloadBtn.setText("暂停"); + downloadBtn + .setBackgroundResource(R.drawable.textview_gray_style); + downloadBtn + .setTextColor(0xFF999999); + EventBus.getDefault().post( + new EBRedDot(1)); + + statusMap.put(entity.getApk() + .get(0).getUrl(), + "downloading"); + } else { + Toast.makeText(context, msg, + Toast.LENGTH_SHORT) + .show(); + } + } else { + if (!dismissEntity.isShow()) { + dismissEntity.setShow(true); + DownloadDialog + .getInstance(context) + .showPopupWindow( + viewBtn, + entity, + entrance, + handler, + lastTimeMap, + statusMap, + download_speed, + download_percentage, + location); + } + } + } + } + }); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.show(); + } + } + } else if ("暂停".equals(str)) { + ArrayMap entryMap = entity + .getEntryMap(); + + if (entryMap != null && !entryMap.isEmpty()) { + + DownloadEntry downloadEntry; + + LinkedBlockingQueue queue = platformMap + .get(entity.getName()); + + if (queue != null && !queue.isEmpty()) { + downloadEntry = entryMap.get(queue.peek()); + } else { + downloadEntry = entryMap.get(entryMap.keyAt(0)); + } + + if (downloadEntry != null) { + + String platform = PlatformUtils + .getInstance(context).getPlatformName( + downloadEntry.getMeta().get( + "platform")); + if (isShowPlatform) { + if (platform == null) { + download_speed.setText("暂停"); + } else { + download_speed.setText(platform + " - 暂停"); + } + } else { + download_speed.setText("暂停"); + } + download_percentage.setText(downloadEntry + .getPercent() + "%"); + } + } + downloadBtn.setText("继续"); + downloadBtn + .setBackgroundResource(R.drawable.textview_blue_style); + downloadBtn.setTextColor(0xFFFFFFFF); + statusMap.put(entity.getApk().get(0).getUrl(), "pause"); + Message msg = Message.obtain(); + msg.what = Constants.PAUSE_DOWNLOAD_TASK; + msg.obj = entity.getApk().get(0).getUrl(); + lastTimeMap.put(entity.getApk().get(0).getUrl(), + System.currentTimeMillis()); + handler.sendMessageDelayed(msg, 1000); + } else if ("继续".equals(str)) { + ArrayMap entryMap = entity + .getEntryMap(); + + if (entryMap != null && !entryMap.isEmpty()) { + + DownloadEntry downloadEntry; + + LinkedBlockingQueue queue = platformMap + .get(entity.getName()); + + if (queue != null && !queue.isEmpty()) { + downloadEntry = entryMap.get(queue.peek()); + } else { + downloadEntry = entryMap.get(entryMap.keyAt(0)); + } + + if (downloadEntry != null) { + + String platform = PlatformUtils + .getInstance(context).getPlatformName( + downloadEntry.getMeta().get( + "platform")); + if (isShowPlatform) { + if (platform == null) { + download_speed.setText(SpeedUtils + .getSpeed(downloadEntry.getSpeed()) + + "(剩" + + SpeedUtils.getRemainTime( + downloadEntry.getSize(), + downloadEntry.getProgress(), + downloadEntry.getSpeed() * 1024) + + ")"); + } else { + download_speed.setText(platform + + " - " + + SpeedUtils.getSpeed(downloadEntry + .getSpeed()) + + "(剩" + + SpeedUtils.getRemainTime( + downloadEntry.getSize(), + downloadEntry.getProgress(), + downloadEntry.getSpeed() * 1024) + + ")"); + } + } else { + download_speed.setText(SpeedUtils + .getSpeed(downloadEntry.getSpeed()) + + "(剩" + + SpeedUtils.getRemainTime( + downloadEntry.getSize(), + downloadEntry.getProgress(), + downloadEntry.getSpeed() * 1024) + + ")"); + } + download_percentage.setText(downloadEntry + .getPercent() + "%"); + } + } + downloadBtn.setText("暂停"); + downloadBtn + .setBackgroundResource(R.drawable.textview_gray_style); + downloadBtn.setTextColor(0xFF999999); + statusMap.put(entity.getApk().get(0).getUrl(), + "downloading"); + EventBus.getDefault().post(new EBRedDot(0)); + Message msg = Message.obtain(); + msg.what = Constants.CONTINUE_DOWNLOAD_TASK; + msg.obj = entity.getApk().get(0).getUrl(); + lastTimeMap.put(entity.getApk().get(0).getUrl(), + System.currentTimeMillis()); + handler.sendMessageDelayed(msg, 1000); + } else if ("安装".equals(str)) { + String path = entity.getEntryMap() + .get(entity.getEntryMap().keyAt(0)).getPath(); + if (FileUtils.isEmptyFile(path)) { + Toast.makeText(context, "解析包错误", Toast.LENGTH_SHORT) + .show(); + DownloadManager.getInstance(context).cancel( + entity.getEntryMap() + .get(entity.getEntryMap().keyAt(0)) + .getUrl()); + entity.getEntryMap().remove( + entity.getEntryMap().keyAt(0)); + adapter.notifyItemChanged(position); + } else { + PackageManager manager = new PackageManager(context); + if (manager.launchSetup(path)) { + context.startActivity(PackageUtils + .getInstallIntent(path)); + } else { + DialogUtils.showDialog(context, path); + } + } + } else if ("启动".equals(str)) { + + Map kv = new HashMap(); + kv.put("版本", entity.getApk().get(0).getPlatform()); + TCAgent.onEvent(context, "游戏启动", entity.getName(), kv); + + PackageUtils.launchApplicationByPackageName(context, entity + .getApk().get(0).getPackageName()); + } + } + }); + } + + public static DownloadEntry getDownloadEntry(Context context, + GameEntity game, int position, String entrance) { + ApkEntity apkEntity = game.getApk().get(position); + DownloadEntry entry = new DownloadEntry(); + + entry.setUrl(apkEntity.getUrl()); + entry.setName(game.getName()); + entry.setPath(FileUtils.getDownloadPath( + context, + MD5Utils.getContentMD5(game.getName() + "_" + + System.currentTimeMillis()) + + ".apk")); + HashMap meta = new HashMap(); + meta.put("ETag", apkEntity.getEtag()); + meta.put("icon", game.getIcon()); + meta.put("platform", apkEntity.getPlatform()); + meta.put("gameId", game.getId()); + meta.put("entrance", entrance); + meta.put("location", "游戏详情:" + game.getName()); + entry.setMeta(meta); + return entry; + } +} diff --git a/app/src/main/java/com/gh/common/util/FileUtils.java b/app/src/main/java/com/gh/common/util/FileUtils.java new file mode 100644 index 0000000000..86c3640f83 --- /dev/null +++ b/app/src/main/java/com/gh/common/util/FileUtils.java @@ -0,0 +1,284 @@ +package com.gh.common.util; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.UUID; + +import org.apache.http.HttpStatus; +import org.json.JSONObject; + +import android.content.Context; +import android.os.Environment; +import android.os.StatFs; +import android.os.StrictMode; + +/** + * + * @author guanchao wen + * @email shuwoom.wgc@gmail.com + * @modify hzh 2016/03/16 + * @update 2015-7-29下午2:26:02 + */ +public class FileUtils { + + public static String getDownloadDir(Context context) { + String baseDir; + if (isMounted()) { + baseDir = Environment.getExternalStorageDirectory().getAbsolutePath(); + } else { + baseDir = context.getFilesDir().getAbsolutePath(); + } + String dir = baseDir + File.separator + "gh-download"; + return checkDir(dir); + } + + public static String getDownloadPath(Context context, String name) { + return getDownloadDir(context) + File.separator + name; + } + + public static String getLogPath(Context context, String name) { + return checkDir(getDir(context, "log")) + File.separator + name; + } + + public static String getPlatformPicDir(Context context) { + return checkDir(getDir(context, "PlatformPic")); + } + + public static String getAdPicDir(Context context) { + return checkDir(getDir(context, "AdPic")); + } + + public static String getPicPath(Context context, String name) { + return checkDir(getDir(context, "Pic")) + File.separator + name; + } + + private static String checkDir(String dir) { + File directory = new File(dir); + if (!directory.exists() || !directory.isDirectory()) { + directory.mkdirs(); + } + return dir; + } + + public static void deleteFile(String savePath) { + File file = new File(savePath); + if (file.exists()) { + file.delete(); + } + } + + public static boolean isEmptyFile(String path) { + File file = new File(path); + if (file.exists() && file.length() != 0) { + return false; + } + return true; + } + + public static void checkDirExists(String dirName) { + File file = Environment.getExternalStorageDirectory(); + if (file.isDirectory()) { + File[] fs = file.listFiles(); + for (int i = 0; i < fs.length; i++) { + if (fs[i].isDirectory() + && fs[i].getName().equalsIgnoreCase(dirName) + && !fs[i].getName().equals(dirName)) { + fs[i].delete(); + break; + } + } + } + } + + public static boolean isMounted() { + return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); + } + + public static String getDir(Context context, String dir) { + if (isMounted()) { + // /storage/emulated/0/Android/data/包名/files + File file = context.getExternalFilesDir(null); + if (file != null) { + return file.getAbsolutePath() + File.separator + dir; + } + } + // /data/data/包名/files + return context.getFilesDir().getAbsolutePath() + File.separator + dir; + } + + /* + * 返回剩余空间 单位MB + */ + @SuppressWarnings("deprecation") + public static float getFreeSpaceByPath(String path) { + StatFs statfs = new StatFs(path); + + long blockSize = statfs.getBlockSize(); + + long availableBlocks = statfs.getAvailableBlocks(); + + return availableBlocks * blockSize / 1024f / 1024f; + } + + public static String isCanDownload(String size) { + String msg = null; + String packageSizeStr = ""; + for (int i = 0; i < size.length(); i++) { + if ((size.charAt(i) >= 48 && size.charAt(i) <= 57) || size.charAt(i) == 46) { + packageSizeStr += size.charAt(i); + } + } + float packageSize = 0; + if (packageSizeStr.length() != 0) { + packageSize = Float.valueOf(packageSizeStr); + } + float freeSpace = getFreeSpaceByPath(Environment + .getExternalStorageDirectory().getAbsolutePath()); + if (freeSpace < packageSize) { + msg = "手机存储空间不足,无法进行下载!"; + } + return msg; + } + + // 下载文件 + public static int downloadFile(String url, String savePath) + throws IOException { + DataInputStream dis = null; + FileOutputStream fos = null; + try { + HttpURLConnection connection = (HttpURLConnection) new URL(url) + .openConnection(); + connection.setRequestMethod("GET"); + connection.setConnectTimeout(5 * 1000); + connection.setReadTimeout(5 * 1000); + connection.connect(); + int code = connection.getResponseCode(); + if (code == 200) { + dis = new DataInputStream(connection.getInputStream()); + File file = new File(savePath); + if (file.exists()) { + file.delete(); + } + file.createNewFile(); + fos = new FileOutputStream(file); + byte[] buffer = new byte[1024]; + int len; + while ((len = dis.read(buffer)) != -1) { + fos.write(buffer, 0, len); + } + fos.flush(); + fos.close(); + dis.close(); + } + return code; + } finally { + if (fos != null) { + fos.close(); + } + if (dis != null) { + dis.close(); + } + } + } + + // 上传文件 + public static String uploadFile(String url, String filePath, String token) { + String end = "\r\n"; + String twoHyphens = "--"; + String boundary = UUID.randomUUID().toString().replaceAll("-", "") + .substring(0, 16); + try { + HttpURLConnection connection = (HttpURLConnection) new URL(url) + .openConnection(); + /* + * Output to the connection. Default is false, set to true because + * post method must write something to the connection + */ + connection.setDoOutput(true); + /* Read from the connection. Default is true. */ + connection.setDoInput(true); + /* Post cannot use caches */ + connection.setUseCaches(false); + /* Set the post method. Default is GET */ + connection.setRequestMethod("POST"); + /* 设置请求属性 */ + connection.setRequestProperty("Connection", "Keep-Alive"); + connection.setRequestProperty("Charset", "UTF-8"); + connection.setRequestProperty("Content-Type", + "multipart/form-data;boundary=" + boundary); + if (token != null) { + connection.setRequestProperty("Auth", token); + } + /* 设置StrictMode 否则HTTPURLConnection连接失败,因为这是在主进程中进行网络连接 */ + StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() + .detectDiskReads().detectDiskWrites().detectNetwork() + .penaltyLog().build()); + File file = new File(filePath); + if (file.exists()) { + Utils.log("name = " + file.getName()); + Utils.log("length = " + file.length()); + } + /* 设置DataOutputStream,getOutputStream中默认调用connect() */ + DataOutputStream dos = new DataOutputStream( + connection.getOutputStream()); // output + // to + // the + // connection + dos.writeBytes(twoHyphens + boundary + end); + dos.writeBytes("Content-Disposition: form-data; " + + "name=\"Filedata\";filename=\"" + file.getName() + "\"" + + end); + dos.writeBytes(end); + /* 取得文件的FileInputStream */ + FileInputStream fStream = new FileInputStream(file); + /* 设置每次写入8192bytes */ + int bufferSize = 8192; + byte[] buffer = new byte[bufferSize]; // 8k + int length = -1; + /* 从文件读取数据至缓冲区 */ + while ((length = fStream.read(buffer)) != -1) { + /* 将资料写入DataOutputStream中 */ + dos.write(buffer, 0, length); + } + dos.writeBytes(end); + dos.writeBytes(twoHyphens + boundary + twoHyphens + end); + /* 关闭流,写入的东西自动生成Http正文 */ + fStream.close(); + /* 关闭DataOutputStream */ + dos.close(); + + /* 从返回的输入流读取响应信息 */ + InputStream is = connection.getInputStream(); // input from the + // connection + // 正式建立HTTP连接 + Utils.log("con.getResponseCode() = " + connection.getResponseCode()); + int ch; + StringBuffer b = new StringBuffer(); + while ((ch = is.read()) != -1) { + b.append((char) ch); + } + /* 显示网页响应内容 */ + Utils.log("content = " + b.toString().trim()); + + // {"status":"success","url":"http:\/\/api.ghzhushou.com\/temp\/5688e548d7859e6f278b4567.jpg"} + if (connection.getResponseCode() == HttpStatus.SC_OK) { + JSONObject response = new JSONObject(b.toString().trim()); + if ("success".equals(response.getString("status"))) { + return response.getString("url"); + } + } + } catch (Exception e) { + /* 显示异常信息 */ + Utils.log("Fail:" + e); + } + return null; + } + +} diff --git a/app/src/main/java/com/gh/common/util/GameViewUtils.java b/app/src/main/java/com/gh/common/util/GameViewUtils.java new file mode 100644 index 0000000000..46c8e2acd1 --- /dev/null +++ b/app/src/main/java/com/gh/common/util/GameViewUtils.java @@ -0,0 +1,127 @@ +package com.gh.common.util; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.TimeZone; + +import android.content.Context; +import android.util.TypedValue; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.TextView; + +import com.gh.gamecenter.R; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-8-14 + * @update 2015-8-14 + * @des 设置列表中game item视图上的工具类 + */ +public class GameViewUtils { + + public static void setLabelList(Context context, LinearLayout labelLayout, + List tag) { + labelLayout.removeAllViews(); + if (tag == null || tag.isEmpty()) { + labelLayout.addView(getGameTagView(context, "官方版")); + } else { + for (int i = 0, size = tag.size() > 3 ? 3 : tag.size(); i < size; i++) { + labelLayout.addView(getGameTagView(context, tag.get(i))); + } + } + } + + // 获取游戏标签列表视图 + public static void setLabelList(Context context, LinearLayout labelLayout, + String tag) { + labelLayout.removeAllViews(); + // 添加tag标签 + if (tag != null && !tag.isEmpty()) { + String[] tags = tag.split(","); + if (tags != null && tags.length > 0) { + for (int i = 0; i < tags.length; i++) { + labelLayout.addView(getGameTagView(context, tags[i])); + } + } + } + } + + public static TextView getGameTagView(Context context, String tagStr) { + LayoutParams lp = new LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + lp.setMargins(0, 0, DisplayUtils.dip2px(context, 5), 0); + TextView tag = new TextView(context); + tag.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12); + tag.setSingleLine(true); + tag.setText(tagStr); + if ("官方版".equals(tagStr) || "已关注".equals(tagStr)) { + tag.setBackgroundResource(R.drawable.border_red_bg); + tag.setTextColor(0xffbc2132); + } else if ("已安装".equals(tagStr)) { + tag.setBackgroundResource(R.drawable.border_blue_bg); + tag.setTextColor(0xff1BA4FC); + } else { + tag.setBackgroundResource(R.drawable.border_green_bg); + tag.setTextColor(0xff2ec991); + } + tag.setLayoutParams(lp); + tag.setPadding(DisplayUtils.dip2px(context, 4), + DisplayUtils.dip2px(context, 2), + DisplayUtils.dip2px(context, 4), + DisplayUtils.dip2px(context, 2)); + return tag; + } + + public static String getGameTestDate(long testTime) { + + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd", + Locale.CHINA); + + format.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); + + String testDate; + + try { + long today = format.parse(format.format(new Date())).getTime(); + long day = Long.parseLong(testTime + "000"); + Calendar calendar = Calendar.getInstance(TimeZone + .getTimeZone("Asia/Shanghai")); + calendar.setTimeInMillis(day); + int hour = calendar.get(Calendar.HOUR_OF_DAY); + if (day >= today && day < today + 86400 * 1000) { + testDate = "今天" + hour + "点"; + } else if (day >= today + 86400 * 1000 + && day < today + 86400 * 1000 * 2) { + testDate = "明天" + hour + "点"; + } else if (day >= today + 86400 * 1000 * 2 + && day < today + 86400 * 1000 * 3) { + testDate = "后天" + hour + "点"; + } else if (day >= today - 86400 * 1000 && day < today) { + testDate = "昨天" + hour + "点"; + } else { + format = new SimpleDateFormat("MM-dd", Locale.CHINA); + testDate = format.format(day) + " " + hour + "点"; + } + return testDate; + } catch (ParseException e) { + e.printStackTrace(); + long day = Long.parseLong(testTime + "000"); + Calendar calendar = Calendar.getInstance(TimeZone + .getTimeZone("Asia/Shanghai")); + calendar.setTimeInMillis(day); + int hour = calendar.get(Calendar.HOUR_OF_DAY); + format = new SimpleDateFormat("MM-dd", Locale.CHINA); + testDate = format.format(day) + " " + hour + "点"; + return testDate; + } + + } + +} diff --git a/app/src/main/java/com/gh/common/util/GzipUtils.java b/app/src/main/java/com/gh/common/util/GzipUtils.java new file mode 100644 index 0000000000..144eb3bd43 --- /dev/null +++ b/app/src/main/java/com/gh/common/util/GzipUtils.java @@ -0,0 +1,115 @@ +package com.gh.common.util; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +public class GzipUtils { + + private final static int BUFFER = 1024; + + /* + * 数据压缩 + */ + public static void compress(InputStream is, OutputStream os) + throws IOException { + GZIPOutputStream gos = null; + try { + gos = new GZIPOutputStream(os); + int count; + byte data[] = new byte[BUFFER]; + while ((count = is.read(data, 0, BUFFER)) != -1) { + gos.write(data, 0, count); + } + gos.flush(); + gos.finish(); + gos.close(); + } finally { + if (gos != null) { + gos.close(); + } + } + } + + /* + * 数据解压缩 + */ + public static void decompress(InputStream is, OutputStream os) + throws IOException { + GZIPInputStream gis = null; + try { + gis = new GZIPInputStream(is); + int count; + byte data[] = new byte[BUFFER]; + while ((count = gis.read(data, 0, BUFFER)) != -1) { + os.write(data, 0, count); + } + } finally { + if (gis != null) { + gis.close(); + } + } + } + + public static byte[] compressBytes(byte[] compressed) { + ByteArrayInputStream bais = null; + ByteArrayOutputStream baos = null; + try { + bais = new ByteArrayInputStream(compressed); + baos = new ByteArrayOutputStream(); + compress(bais, baos); + return baos.toByteArray(); + } catch (IOException e) { + e.printStackTrace(); + return compressed; + } finally { + if (bais != null) { + try { + bais.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (baos != null) { + try { + baos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + public static byte[] decompressBytes(byte[] compressed) { + ByteArrayInputStream bais = null; + ByteArrayOutputStream baos = null; + try { + bais = new ByteArrayInputStream(compressed); + baos = new ByteArrayOutputStream(); + decompress(bais, baos); + return baos.toByteArray(); + } catch (IOException e) { + e.printStackTrace(); + return compressed; + } finally { + if (bais != null) { + try { + bais.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (baos != null) { + try { + baos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } +} diff --git a/app/src/main/java/com/gh/common/util/ImageUtils.java b/app/src/main/java/com/gh/common/util/ImageUtils.java new file mode 100644 index 0000000000..9ffe48e04a --- /dev/null +++ b/app/src/main/java/com/gh/common/util/ImageUtils.java @@ -0,0 +1,135 @@ +package com.gh.common.util; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import android.content.Context; +import android.graphics.Bitmap; +import android.view.View; +import android.view.animation.AlphaAnimation; +import android.widget.ImageView; +import android.widget.ImageView.ScaleType; + +import com.gh.common.view.CircleImageView; +import com.gh.gamecenter.R; +import com.nostra13.universalimageloader.core.DisplayImageOptions; +import com.nostra13.universalimageloader.core.ImageLoader; +import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; +import com.nostra13.universalimageloader.core.assist.FailReason; +import com.nostra13.universalimageloader.core.listener.ImageLoadingListener; + +public class ImageUtils { + private static ImageUtils singleton; + private static ImageLoader imageLoader; + private static DisplayImageOptions options; + + ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5); + + public static ImageUtils getInstance(Context context) { + if (singleton == null) { + synchronized (ImageUtils.class) { + if (singleton == null) { + singleton = new ImageUtils(context.getApplicationContext(), + (int) Runtime.getRuntime().maxMemory() / 10); + return singleton; + } + + } + } + return singleton; + } + + private ImageUtils(Context context, int size) { + + options = new DisplayImageOptions.Builder().cacheInMemory(true) + .cacheOnDisk(true).considerExifParams(true) + .bitmapConfig(Bitmap.Config.RGB_565) + // .showImageOnLoading(R.drawable.ocupy) + // .showImageForEmptyUri(R.drawable.ocupy) + // .showImageOnFail(R.drawable.ocupy) + .build(); + + ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder( + context).writeDebugLogs().build(); + + ImageLoader.getInstance().init(config); + imageLoader = ImageLoader.getInstance(); + } + + public void displayFile(String url, ImageView imageView) { + imageLoader.displayImage(url, imageView, options, + new ImageLoadingListener() { + + @Override + public void onLoadingCancelled(String arg0, View arg1) { + + } + + @Override + public void onLoadingComplete(String arg0, View view, + Bitmap arg2) { + AlphaAnimation animation = new AlphaAnimation(0f, 1f); + animation.setDuration(500); + view.startAnimation(animation); + } + + @Override + public void onLoadingFailed(String arg0, View arg1, + FailReason arg2) { + + } + + @Override + public void onLoadingStarted(String arg0, View arg1) { + + } + + }); + } + + public void display(String url, ImageView imageView, int drawable) { + display(url, imageView, drawable, ScaleType.FIT_XY); + } + + public void display(final String url, final ImageView imageView, + final int drawable, final ScaleType scaleType) { + imageLoader.displayImage(url, imageView, options, + new ImageLoadingListener() { + @Override + public void onLoadingComplete(String imageUri, View view, + Bitmap loadedImage) { + if (imageView instanceof CircleImageView) { + imageView.setScaleType(ScaleType.CENTER_CROP); + } else { + imageView.setScaleType(scaleType); + } + } + + @Override + public void onLoadingStarted(String imageUri, View view) { + imageView.setScaleType(ScaleType.CENTER); + imageView.setImageResource(drawable); + } + + @Override + public void onLoadingCancelled(String imageUri, View view) { + + } + + @Override + public void onLoadingFailed(String imageUri, View view, + FailReason reason) { + + } + }); + } + + public void display(String url, ImageView imageView, ScaleType scaleType) { + display(url, imageView, R.drawable.ocupy, scaleType); + } + + public void display(String url, ImageView imageView) { + display(url, imageView, R.drawable.ocupy, ScaleType.FIT_XY); + } + +} diff --git a/app/src/main/java/com/gh/common/util/Installation.java b/app/src/main/java/com/gh/common/util/Installation.java new file mode 100644 index 0000000000..ad06d3675c --- /dev/null +++ b/app/src/main/java/com/gh/common/util/Installation.java @@ -0,0 +1,45 @@ +package com.gh.common.util; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.UUID; + +import android.content.Context; + +public class Installation { + private static String sID = null; + private static final String INSTALLATION = "INSTALLATION"; + + public synchronized static String getUUID(Context context) { + if (sID == null) { + File installation = new File(context.getFilesDir(), INSTALLATION); + try { + if (!installation.exists()) + writeInstallationFile(installation); + sID = readInstallationFile(installation); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + return sID; + } + + private static String readInstallationFile(File installation) + throws IOException { + RandomAccessFile f = new RandomAccessFile(installation, "r"); + byte[] bytes = new byte[(int) f.length()]; + f.readFully(bytes); + f.close(); + return new String(bytes); + } + + private static void writeInstallationFile(File installation) + throws IOException { + FileOutputStream out = new FileOutputStream(installation); + String id = UUID.randomUUID().toString(); + out.write(id.getBytes()); + out.close(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/common/util/MD5Utils.java b/app/src/main/java/com/gh/common/util/MD5Utils.java new file mode 100644 index 0000000000..e472d9be1e --- /dev/null +++ b/app/src/main/java/com/gh/common/util/MD5Utils.java @@ -0,0 +1,77 @@ +package com.gh.common.util; + +import java.io.ByteArrayInputStream; +import java.math.BigInteger; +import java.security.MessageDigest; + +public class MD5Utils { + + public static String getUpdateMD5(String url, String content) { + if (url == null && content == null) { + return null; + } + MessageDigest digest = null; + ByteArrayInputStream bais = null; + byte buffer[] = new byte[1024]; + int len; + try { + digest = MessageDigest.getInstance("MD5"); + bais = new ByteArrayInputStream((url + content).getBytes()); + while ((len = bais.read(buffer, 0, 1024)) != -1) { + digest.update(buffer, 0, len); + } + bais.close(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + BigInteger bigInt = new BigInteger(1, digest.digest()); + return bigInt.toString(16); + } + + public static String getUrlMD5(String url) { + if (url == null) { + return null; + } + MessageDigest digest = null; + ByteArrayInputStream bais = null; + byte buffer[] = new byte[1024]; + int len; + try { + digest = MessageDigest.getInstance("MD5"); + bais = new ByteArrayInputStream(url.getBytes()); + while ((len = bais.read(buffer, 0, 1024)) != -1) { + digest.update(buffer, 0, len); + } + bais.close(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + BigInteger bigInt = new BigInteger(1, digest.digest()); + return bigInt.toString(16); + } + + public static String getContentMD5(String content) { + if (content == null) { + return null; + } + MessageDigest digest = null; + ByteArrayInputStream bais = null; + byte buffer[] = new byte[1024]; + int len; + try { + digest = MessageDigest.getInstance("MD5"); + bais = new ByteArrayInputStream(content.getBytes()); + while ((len = bais.read(buffer, 0, 1024)) != -1) { + digest.update(buffer, 0, len); + } + bais.close(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + BigInteger bigInt = new BigInteger(1, digest.digest()); + return bigInt.toString(16); + } +} diff --git a/app/src/main/java/com/gh/common/util/NetworkUtils.java b/app/src/main/java/com/gh/common/util/NetworkUtils.java new file mode 100644 index 0000000000..1d82e90aad --- /dev/null +++ b/app/src/main/java/com/gh/common/util/NetworkUtils.java @@ -0,0 +1,109 @@ +package com.gh.common.util; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; + +public class NetworkUtils { + + /** + * 判断是否有网络连接 + * + * @param context + * 上下文 + * @return true 有网络连接 false 无网络连接 + */ + public static boolean isNetworkConnected(Context context) { + if (context != null) { + ConnectivityManager mConnectivityManager = (ConnectivityManager) context + .getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo mNetworkInfo = mConnectivityManager + .getActiveNetworkInfo(); + if (mNetworkInfo != null) { + return mNetworkInfo.isAvailable(); + } + } + return false; + } + + /** + * 判断WIFI网络是否可用 + * + * @param context + * 上下文 + * @return true wifi可用 false wifi不可用 + */ + public static boolean isWifiConnected(Context context) { + if (context != null) { + ConnectivityManager mConnectivityManager = (ConnectivityManager) context + .getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo mWiFiNetworkInfo = mConnectivityManager + .getNetworkInfo(ConnectivityManager.TYPE_WIFI); + if (mWiFiNetworkInfo != null) { + return mWiFiNetworkInfo.isConnected(); + } + } + return false; + } + + /** + * 判断MOBILE网络是否可用 + * + * @param context + * 上下文 + * @return true mobile可用 false mobile不可用 + */ + public static boolean isMobileConnected(Context context) { + if (context != null) { + ConnectivityManager mConnectivityManager = (ConnectivityManager) context + .getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo mMobileNetworkInfo = mConnectivityManager + .getNetworkInfo(ConnectivityManager.TYPE_MOBILE); + if (mMobileNetworkInfo != null) { + return mMobileNetworkInfo.isAvailable(); + } + } + return false; + } + + /** + * 获取当前网络连接的类型信息 + * @param context 上下文 + * @return 当前网络连接的类型信息 + */ + public static String getConnectedType(Context context) { + if (context != null) { + ConnectivityManager mConnectivityManager = (ConnectivityManager) context + .getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo mNetworkInfo = mConnectivityManager + .getActiveNetworkInfo(); + if (mNetworkInfo != null && mNetworkInfo.isAvailable()) { + switch (mNetworkInfo.getType()) { + case ConnectivityManager.TYPE_BLUETOOTH: + return "BLUETOOTH"; + case ConnectivityManager.TYPE_DUMMY: + return "DUMMY"; + case ConnectivityManager.TYPE_ETHERNET: + return "ETHERNET"; + case ConnectivityManager.TYPE_MOBILE: + return "MOBILE"; + case ConnectivityManager.TYPE_MOBILE_DUN: + return "MOBILE_DUN"; + case ConnectivityManager.TYPE_MOBILE_HIPRI: + return "MOBILE_HIPRI"; + case ConnectivityManager.TYPE_MOBILE_MMS: + return "MOBILE_MMS"; + case ConnectivityManager.TYPE_MOBILE_SUPL: + return "MOBILE_SUPL"; + case ConnectivityManager.TYPE_WIFI: + return "WIFI"; + case ConnectivityManager.TYPE_WIMAX: + return "WIMAX"; + default: + break; + } + } + } + return "NONE"; + } +} diff --git a/app/src/main/java/com/gh/common/util/NewsUtils.java b/app/src/main/java/com/gh/common/util/NewsUtils.java new file mode 100644 index 0000000000..5cfa74a9c7 --- /dev/null +++ b/app/src/main/java/com/gh/common/util/NewsUtils.java @@ -0,0 +1,53 @@ +package com.gh.common.util; + +import android.content.Context; +import android.content.Intent; + +import com.gh.gamecenter.NewsActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.entity.NewsDetailsEntity; +import com.gh.gamecenter.entity.NewsEntity; + +public class NewsUtils { + + /** + * 根据新闻类型获取标签背景资源 + * + * @param type + * @return + */ + public static int getDrawableIdByType(String type) { + if ("活动".equals(type) || "高阶".equals(type)) { + return R.drawable.textview_red_up; + } else if ("公告".equals(type) || "中期".equals(type)) { + return R.drawable.textview_orange_up; + } else if ("新游".equals(type)) { + return R.drawable.textview_green_up; + } else { + return R.drawable.textview_blue_up; + } + } + + /** + * 启动新闻详情页面 + * + * @param context + * @param newsEntity + * @param entrance + * @return + */ + public static void startNewsActivity(Context context, + NewsEntity newsEntity, String entrance) { + Intent intent = new Intent(context, NewsActivity.class); + NewsDetailsEntity entity = new NewsDetailsEntity(); + entity.setId(newsEntity.getId()); + entity.setTitle(newsEntity.getTitle()); + entity.setType(newsEntity.getType()); + entity.setTime(newsEntity.getPublishOn()); + intent.putExtra("entity", entity); + intent.putExtra("entrance", entrance); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + +} diff --git a/app/src/main/java/com/gh/common/util/PackageUtils.java b/app/src/main/java/com/gh/common/util/PackageUtils.java new file mode 100644 index 0000000000..660e5a32a5 --- /dev/null +++ b/app/src/main/java/com/gh/common/util/PackageUtils.java @@ -0,0 +1,289 @@ +package com.gh.common.util; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.Signature; +import android.net.Uri; +import android.os.Bundle; +import android.support.v4.util.ArrayMap; +import android.text.TextUtils; +import android.util.DisplayMetrics; +import android.widget.Toast; + +import com.gh.gamecenter.manager.FilterManager; + +public class PackageUtils { + + public static final String publicKey = "OpenSSLRSAPublicKey{modulus=a8c4bb5748fec8d5c35db1a7a182d41ba4721a91131a417330af79ef4ddb43f9fa0ff4907b0a613bfe152de0ed8fc1b2e6f94a908aa98a5f7adc1ce814ba7ec919d75d9910bdfd8649b4789da6a90ffb61f0d23ac4f828a78fcd0d6f6120c1c43c1f87f7498a89eb40ca8e32dfc2f9d5c10d612b95192870223674e241e53305abf320d7eed76ded398778576e4db7b17b3bc6a792f13de5e43a6a5fae4276c73e6990ce97f68dff0ec16fc9594f175c8d49cd0d7877340d9de60942ca0efc737e50b6c295dfe0713e4532b4e810e1ea11b702b4a27753e41559cbceb247e7f044ec4e3ab2e8bccd8b9fd71286e63307550bcde86deee95adb8133076269135b,publicExponent=10001}"; + + /* + * 根据apk路径,获取apk的签名信息,耗时 + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static String getApkSignatureByPath(Context context, String path) { + String PATH_PackageParser = "android.content.pm.PackageParser"; + try { + // apk包的文件路径 + // 这是一个Package 解释器, 是隐藏的 + // 构造函数的参数只有一个, apk文件的路径 + // PackageParser packageParser = new PackageParser(apkPath); + Class pkgParserCls = Class.forName(PATH_PackageParser); + Class[] typeArgs = new Class[1]; + typeArgs[0] = String.class; + Constructor pkgParserCt = pkgParserCls.getConstructor(typeArgs); + Object[] valueArgs = new Object[1]; + valueArgs[0] = path; + Object pkgParser = pkgParserCt.newInstance(valueArgs); + // 这个是与显示有关的, 里面涉及到一些像素显示等等, 我们使用默认的情况 + DisplayMetrics metrics = new DisplayMetrics(); + metrics.setToDefaults(); + // PackageParser.Package mPkgInfo = packageParser.parsePackage(new + // File(apkPath), apkPath, + // metrics, 0); + typeArgs = new Class[4]; + typeArgs[0] = File.class; + typeArgs[1] = String.class; + typeArgs[2] = DisplayMetrics.class; + typeArgs[3] = Integer.TYPE; + Method pkgParser_parsePackageMtd = pkgParserCls.getDeclaredMethod( + "parsePackage", typeArgs); + valueArgs = new Object[4]; + valueArgs[0] = new File(path); + valueArgs[1] = path; + valueArgs[2] = metrics; + valueArgs[3] = PackageManager.GET_SIGNATURES; + Object pkgParserPkg = pkgParser_parsePackageMtd.invoke(pkgParser, + valueArgs); + + typeArgs = new Class[2]; + typeArgs[0] = pkgParserPkg.getClass(); + typeArgs[1] = Integer.TYPE; + Method pkgParser_collectCertificatesMtd = pkgParserCls + .getDeclaredMethod("collectCertificates", typeArgs); + valueArgs = new Object[2]; + valueArgs[0] = pkgParserPkg; + valueArgs[1] = PackageManager.GET_SIGNATURES; + pkgParser_collectCertificatesMtd.invoke(pkgParser, valueArgs); + // 应用程序信息包, 这个公开的, 不过有些函数, 变量没公开 + Field packageInfoFld = pkgParserPkg.getClass().getDeclaredField( + "mSignatures"); + Signature[] info = (Signature[]) packageInfoFld.get(pkgParserPkg); + return parseSignature(info[0].toByteArray())[0]; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /* + * 根据路径,获取apk的包名 + */ + public static String getPackageNameByPath(Context context, String path) { + PackageManager packageManager = context.getPackageManager(); + PackageInfo info = packageManager.getPackageArchiveInfo(path, + PackageManager.GET_ACTIVITIES); + if (info != null) { + ApplicationInfo appInfo = info.applicationInfo; + return appInfo.packageName; + } + return null; + } + + public static Object getMetaData(Context context, String packageName, String name) { + try { + Bundle metaDate = context.getPackageManager().getApplicationInfo( + packageName, PackageManager.GET_META_DATA).metaData; + if (metaDate != null) { + return metaDate.get(name); + } + } catch (NameNotFoundException e) { + e.printStackTrace(); + } + return null; + } + + /* + * 根据包名,获取apk的签名信息 + */ + public static String getApkSignatureByPackageName(Context context, + String packageName) { + try { + PackageInfo packageInfo = context.getPackageManager() + .getPackageInfo(packageName, PackageManager.GET_SIGNATURES); + Signature[] signatures = packageInfo.signatures; + return parseSignature(signatures[0].toByteArray())[0]; + } catch (NameNotFoundException e) { + e.printStackTrace(); + } + return null; + } + + /* + * 解析签名 + */ + private static String[] parseSignature(byte[] signature) { + String[] ret = null; + try { + CertificateFactory certFactory = CertificateFactory + .getInstance("X.509"); + X509Certificate cert = (X509Certificate) certFactory + .generateCertificate(new ByteArrayInputStream(signature)); + ret = new String[] { cert.getPublicKey().toString(), + cert.getSerialNumber().toString() }; + } catch (CertificateException e) { + e.printStackTrace(); + } + return ret; + } + + /* + * 返回光环助手的版本信息 + */ + public static String getVersion(Context context) { + try { + PackageInfo pkgInfo = context.getPackageManager().getPackageInfo( + context.getPackageName(), 0); + return pkgInfo.versionName; + } catch (NameNotFoundException e) { + e.printStackTrace(); + } + return null; + } + + public static String getVersionByPackage(Context context, String packageName) { + try { + return context.getPackageManager().getPackageInfo(packageName, + PackageManager.COMPONENT_ENABLED_STATE_DEFAULT).versionName; + } catch (NameNotFoundException e) { + e.printStackTrace(); + } + return null; + } + + public static ArrayList getAllPackageName(Context context) { + FilterManager filterManager = new FilterManager(context); + ArrayList list = new ArrayList(); + List packageInfos = context.getPackageManager() + .getInstalledPackages(0); + for (int i = 0, size = packageInfos.size(); i < size; i++) { + PackageInfo packageInfo = packageInfos.get(i); + if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { + if (!context.getPackageName().equals(packageInfo.packageName)) { + if (!filterManager.isFilter(packageInfo.packageName)) { + list.add(packageInfo.packageName); + } + } + } + } + return list; + } + + public static void launchApplicationByPackageName(Context context, + String packageName) { + Intent intent = context.getPackageManager().getLaunchIntentForPackage( + packageName); + if (intent != null) { + context.startActivity(intent); + } else { + Toast.makeText(context, "启动失败", Toast.LENGTH_SHORT).show(); + } + } + + /* + * 根据包名,获取软件名称 + */ + public static String getNameByPackageName(Context context, + String packageName) { + try { + PackageManager pm = context.getPackageManager(); + ApplicationInfo applicationInfo = pm.getApplicationInfo( + packageName, 0); + return applicationInfo.loadLabel(pm).toString(); + } catch (NameNotFoundException e) { + e.printStackTrace(); + } + return null; + } + + /* + * 根据包名,判断是否已安装该游戏 + */ + public static boolean isInstalled(Context context, String packageName) { + Intent intent = context.getPackageManager().getLaunchIntentForPackage( + packageName); + if (intent == null) { + return false; + } + return true; + } + + private static ArrayMap map; + + public static boolean isContain(Context context, String packageName) { + if (TextUtils.isEmpty(packageName)) { + return false; + } + if (map == null) { + map = new ArrayMap(); + List infos = context.getPackageManager() + .getInstalledPackages(0); + for (PackageInfo info : infos) { + map.put(info.packageName, true); + } + } + Boolean b = map.get(packageName); + if (b != null) { + return true; + } + return false; + } + + /* + * 根据包名,获取卸载游戏的意图 + */ + public static Intent getUninstallIntent(Context context, String path) { + Intent uninstallIntent = new Intent(); + uninstallIntent.setAction("android.intent.action.DELETE"); + uninstallIntent.addCategory("android.intent.category.DEFAULT"); + uninstallIntent.setData(Uri.parse("package:" + + getPackageNameByPath(context, path))); + return uninstallIntent; + } + + /* + * 根据路径,获取安装游戏的意图 + */ + public static Intent getInstallIntent(String path) { + Uri uri = Uri.fromFile(new File(path)); + Intent installIntent = new Intent(Intent.ACTION_VIEW); + installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + installIntent.setDataAndType(uri, + "application/vnd.android.package-archive"); + return installIntent; + } + + public static String getInstalledApkPath(Context context, String packageName) { + try { + return context.getPackageManager().getApplicationInfo(packageName, + 0).sourceDir; + } catch (NameNotFoundException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/app/src/main/java/com/gh/common/util/PlatformUtils.java b/app/src/main/java/com/gh/common/util/PlatformUtils.java new file mode 100644 index 0000000000..d962cdbc66 --- /dev/null +++ b/app/src/main/java/com/gh/common/util/PlatformUtils.java @@ -0,0 +1,299 @@ +package com.gh.common.util; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Properties; +import java.util.Set; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.support.v4.util.ArrayMap; +import android.text.TextUtils; + +import com.android.volley.Response; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.gamecenter.R; +import com.gh.gamecenter.SplashScreenActivity; +import com.gh.gamecenter.eventbus.EBPlatformChanged; +import com.gh.gamecenter.volley.extended.JsonArrayExtendedRequest; + +import de.greenrobot.event.EventBus; + +public class PlatformUtils { + + private ArrayMap platformMap; + private ArrayMap platformPicMap; + private ArrayMap platformPicUrlMap; + private ArrayMap platformColorMap; + + private static PlatformUtils mInstance; + + private Context context; + + private PlatformUtils(Context con) { + this.context = con.getApplicationContext(); + initMap(); + } + + public static PlatformUtils getInstance(Context context) { + if (mInstance == null) { + mInstance = new PlatformUtils(context); + } + return mInstance; + } + + private void initMap() { + ArrayMap platformPicMap = new ArrayMap(); + platformPicMap.put("360", R.drawable.platform_360); + platformPicMap.put("37wan", R.drawable.platform_37); + platformPicMap.put("91", R.drawable.platform_91); + platformPicMap.put("9u", R.drawable.platform_9u); + platformPicMap.put("anzhi", R.drawable.platform_anzhi); + platformPicMap.put("baidu", R.drawable.platform_baidu); + platformPicMap.put("dangle", R.drawable.platform_dl); + platformPicMap.put("ewan", R.drawable.platform_ewan); + platformPicMap.put("gf", R.drawable.platform_gf); + platformPicMap.put("gf-w", R.drawable.platform_gfw); + platformPicMap.put("huawei", R.drawable.platform_hw); + platformPicMap.put("mi", R.drawable.platform_mi); + platformPicMap.put("oppo", R.drawable.platform_oppo); + platformPicMap.put("ouwan", R.drawable.platform_ouwan); + platformPicMap.put("pps", R.drawable.platform_pps); + platformPicMap.put("vivo", R.drawable.platform_vivo); + platformPicMap.put("wdj", R.drawable.platform_wdj); + + ArrayMap platformColorMap = new ArrayMap(); + platformColorMap.put("360", "#218FA4"); + platformColorMap.put("37wan", "#F5BD20"); + platformColorMap.put("91", "#6A63CB"); + platformColorMap.put("9u", "#E17237"); + platformColorMap.put("anzhi", "#58BB3D"); + platformColorMap.put("baidu", "#537CB3"); + platformColorMap.put("dangle", "#E1842B"); + platformColorMap.put("ewan", "#36A3DC"); + platformColorMap.put("gf", "#BB3D42"); + platformColorMap.put("gf-w", "#BB3D42"); + platformColorMap.put("huawei", "#EB2526"); + platformColorMap.put("mi", "#DC552B"); + platformColorMap.put("oppo", "#2A8A64"); + platformColorMap.put("ouwan", "#E6D66D"); + platformColorMap.put("pps", "#FF8C27"); + platformColorMap.put("vivo", "#3FA5E3"); + platformColorMap.put("wdj", "#5ABA3F"); + + ArrayMap platformMap = new ArrayMap(); + ArrayMap platformPicUrlMap = new ArrayMap(); + + SharedPreferences sharedPreferences = context.getSharedPreferences( + "gh_platform", Context.MODE_PRIVATE); + Set set = sharedPreferences.getStringSet("platform", null); + if (set == null) { + Properties properties = new Properties(); + try { + properties + .load(context.getAssets().open("platform.properties")); + Set pset = new HashSet(); + for (Object object : properties.keySet()) { + platformMap.put(object.toString(), + (String) properties.get(object)); + pset.add(object.toString() + "=" + + (String) properties.get(object) + "=" + "="); + } + Editor editor = sharedPreferences.edit(); + editor.putStringSet("platform", pset); + editor.apply(); + } catch (IOException e) { + e.printStackTrace(); + } + } else { + ArrayList urls = new ArrayList(); + for (String str : set) { + String[] platform = str.split("="); + platformMap.put(platform[0], platform[1]); + if (platform.length == 4 && !TextUtils.isEmpty(platform[2])) { + platformPicUrlMap.put(platform[0], platform[2]); + urls.add(platform[2]); + } + if (platform.length == 4 && !TextUtils.isEmpty(platform[3])) { + platformColorMap.put(platform[0], platform[3]); + } + } + if (urls.size() != 0) { + checkPlatformPic(urls); + } + } + + updataPlatform(platformMap, platformPicMap, platformPicUrlMap, + platformColorMap); + } + + private boolean isCheck = false; + + private void updataPlatform(ArrayMap pMap, + ArrayMap pPMap, ArrayMap pUMap, + ArrayMap pCMap) { + platformMap = pMap; + platformPicMap = pPMap; + platformPicUrlMap = pUMap; + platformColorMap = pCMap; + } + + private void checkPlatformPic(final ArrayList urls) { + isCheck = true; + File file = new File(FileUtils.getPlatformPicDir(context)); + if (file.isDirectory()) { + for (File f : file.listFiles()) { + for (int i = 0; i < urls.size(); i++) { + String url = urls.get(i); + String filename = url.substring(url.lastIndexOf("/") + 1); + if (f.getName().equals(filename)) { + urls.remove(i); + break; + } + } + } + } + if (urls.size() != 0) { + new Thread() { + @Override + public void run() { + for (int i = 0; i < urls.size(); i++) { + String url = urls.get(i); + String savePath = FileUtils.getPlatformPicDir(context) + + File.separator + + url.substring(url.lastIndexOf("/") + 1); + try { + FileUtils.downloadFile(url, savePath); + } catch (IOException e) { + e.printStackTrace(); + } + } + EventBus.getDefault().post(new EBPlatformChanged()); + isCheck = false; + } + }.start(); + } else { + isCheck = false; + } + } + + public ArrayMap getPlatformMap() { + return platformMap; + } + + public String getPlatformColor(String platform) { + if ("".equals(platform) || "官方版".equals(platform) + || "local_plugin".equals(platform)) { + return "#BB3D42"; + } + String color = platformColorMap.get(platform); + if (color != null) { + return color; + } + return "#1BA4FC"; + } + + public int getPlatformPic(String platform) { + if ("".equals(platform) || "官方版".equals(platform) + || "local_plugin".equals(platform)) { + return R.drawable.platform_gf; + } + Integer id = platformPicMap.get(platform); + if (id != null) { + return id.intValue(); + } + return 0; + } + + public String getPlatformPicPath(String platform) { + String path = null; + String url = platformPicUrlMap.get(platform); + if (url != null) { + String fileName = url.substring(url.lastIndexOf("/") + 1); + File file = new File(FileUtils.getPlatformPicDir(context)); + if (file.isDirectory()) { + for (File f : file.listFiles()) { + if (f.getName().equals(fileName)) { + path = f.getAbsolutePath(); + break; + } + } + } + if (path == null && !isCheck) { + ArrayList urls = new ArrayList(); + for (String value : platformPicUrlMap.values()) { + urls.add(value); + } + checkPlatformPic(urls); + } + } + return path; + } + + public String getPlatformName(String platform) { + if ("".equals(platform) || "官方版".equals(platform) + || "local_plugin".equals(platform)) { + return "官方版"; + } + String mPlatform = platformMap.get(platform); + if (mPlatform == null && !isUpdate) { + getPlatform(); + } + return mPlatform; + } + + boolean isUpdate = false; + + private void getPlatform() { + isUpdate = true; + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + + "v1d45/support/setting/platform", + Constants.PLATFORM_CD), + new Response.Listener() { + @Override + public void onResponse(JSONArray response) { + try { + Set pset = new HashSet(); + for (int i = 0; i < response.length(); i++) { + JSONObject jsonObject = response + .getJSONObject(i); + String code = jsonObject.getString("code"); + String name = jsonObject.getString("name"); + String pic = jsonObject.getString("pic"); + String color = jsonObject.getString("color"); + pset.add(code + "=" + name + "=" + pic + "=" + + color); + } + SharedPreferences sharedPreferences = context + .getSharedPreferences("gh_platform", + Context.MODE_PRIVATE); + Editor editor = sharedPreferences.edit(); + editor.putStringSet("platform", pset); + editor.apply(); + initMap(); + EventBus.getDefault().post(new EBPlatformChanged()); + } catch (JSONException e) { + e.printStackTrace(); + } + isUpdate = false; + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + isUpdate = false; + } + }); + AppController.addToRequestQueue(request, SplashScreenActivity.class); + } +} diff --git a/app/src/main/java/com/gh/common/util/RSEUtils.java b/app/src/main/java/com/gh/common/util/RSEUtils.java new file mode 100644 index 0000000000..e4cc6191d7 --- /dev/null +++ b/app/src/main/java/com/gh/common/util/RSEUtils.java @@ -0,0 +1,106 @@ +package com.gh.common.util; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.X509EncodedKeySpec; + +import javax.crypto.Cipher; + +import android.util.Base64; + +public class RSEUtils { + + /** + * 公钥 + */ + private static final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQConqikyOCl5f/VO/vZ+s6wVOhFJcI7o7hYvaLQ5Lzt5/HXbozTeRrGonKFPJurapf9hzjkg0F4/BNFMGXRVlReVdwh+Px5rbXU/ceikF8Ouf67qxiGAuDVC+4e3eIHh+mH68DlqWFJ78sB80iSLXelflGuHkbTOTtaC5F2l+AgxQIDAQAB"; + + /** + * 加密算法RSA + */ + private static final String KEY_ALGORITHM = "RSA"; + + /** + * 得到公钥 + * + * @return PublicKey 公钥 + * @throws NoSuchAlgorithmException + * @throws InvalidKeySpecException + */ + private static PublicKey getPublicKeyFromX509() throws Exception { + byte[] decodedKey = Base64.decode(PUBLIC_KEY, Base64.DEFAULT); + X509EncodedKeySpec x509 = new X509EncodedKeySpec(decodedKey); + KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); + return keyFactory.generatePublic(x509); + } + + /** + * 使用公钥加密 + * + * @param content + * @param key + * @return + */ + public static String encryptByPublic(String content) { + try { + PublicKey pubkey = getPublicKeyFromX509(); + + Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + cipher.init(Cipher.ENCRYPT_MODE, pubkey); + + byte[] data = content.getBytes("UTF-8"); + byte[] output = cipher.doFinal(data); + + String s = new String(Base64.encode(output, Base64.DEFAULT)); + + return s; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 使用公钥解密 + * + * @param content + * 密文 + * @param key + * 商户私钥 + * @return 解密后的字符串 + */ + public static String decryptByPublic(String content) { + try { + PublicKey pubkey = getPublicKeyFromX509(); + Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + cipher.init(Cipher.DECRYPT_MODE, pubkey); + InputStream ins = new ByteArrayInputStream(Base64.decode(content, + Base64.DEFAULT)); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buffer = new byte[128]; + int len; + while ((len = ins.read(buffer)) != -1) { + byte[] block = null; + if (buffer.length == len) { + block = buffer; + } else { + block = new byte[len]; + for (int i = 0; i < len; i++) { + block[i] = buffer[i]; + } + } + baos.write(cipher.doFinal(block)); + } + return new String(baos.toByteArray(), "utf-8"); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + +} diff --git a/app/src/main/java/com/gh/common/util/RunningUtils.java b/app/src/main/java/com/gh/common/util/RunningUtils.java new file mode 100644 index 0000000000..9a7a309a55 --- /dev/null +++ b/app/src/main/java/com/gh/common/util/RunningUtils.java @@ -0,0 +1,112 @@ +package com.gh.common.util; + +import java.util.List; + +import android.app.ActivityManager; +import android.app.ActivityManager.RunningAppProcessInfo; +import android.app.ActivityManager.RunningTaskInfo; +import android.content.ComponentName; +import android.content.Context; + +public class RunningUtils { + + /** + * 判断当前应用程序处于前台还是后台 + */ + public static boolean isApplicationBroughtToBackground(final Context context) { + ActivityManager am = (ActivityManager) context + .getSystemService(Context.ACTIVITY_SERVICE); + List tasks = am.getRunningTasks(1); + if (!tasks.isEmpty()) { + ComponentName topActivity = tasks.get(0).topActivity; + if (!topActivity.getPackageName().equals(context.getPackageName())) { + return true; + } + } + return false; + + } + + /** + * 判断当前应用程序处于前台还是后台 + */ + public static boolean isBackground(Context context) { + ActivityManager activityManager = (ActivityManager) context + .getSystemService(Context.ACTIVITY_SERVICE); + List appProcesses = activityManager + .getRunningAppProcesses(); + for (RunningAppProcessInfo appProcess : appProcesses) { + if (appProcess.processName.equals(context.getPackageName())) { + if (appProcess.importance == RunningAppProcessInfo.IMPORTANCE_BACKGROUND) { + return true; + } else { + return false; + } + } + } + return false; + } + + /** + * 判断当前topactivity是否与传入的相同 + */ + public static boolean isEqualsTop(Context context, String activityName) { + ActivityManager activityManager = (ActivityManager) context + .getSystemService(Context.ACTIVITY_SERVICE); + List infos = activityManager.getRunningTasks(100); + for (RunningTaskInfo info : infos) { + if (info.topActivity.getClassName().equals(activityName)) { + return true; + } + } + return false; + } + + /** + * 判断当前baseActivity是否与传入的相同 + */ + public static boolean isEqualsBase(Context context, String activityName) { + ActivityManager activityManager = (ActivityManager) context + .getSystemService(Context.ACTIVITY_SERVICE); + List infos = activityManager.getRunningTasks(100); + for (RunningTaskInfo info : infos) { + if (info.baseActivity.getClassName().equals(activityName)) { + return true; + } + } + return false; + } + + /** + * 判断应用是否正在运行 + */ + public static boolean isRunning(Context context) { + ActivityManager activityManager = (ActivityManager) context + .getSystemService(Context.ACTIVITY_SERVICE); + List infos = activityManager.getRunningTasks(100); + for (RunningTaskInfo info : infos) { + if (info.topActivity.getPackageName().equals( + context.getPackageName())) { + return true; + } + } + return false; + } + + /** + * 获取当前topactivity + */ + public static String getTopActivity(Context context) { + ActivityManager activityManager = (ActivityManager) context + .getSystemService(Context.ACTIVITY_SERVICE); + List infos = activityManager.getRunningTasks(100); + for (RunningTaskInfo info : infos) { + if (info.topActivity.getPackageName().equals( + context.getPackageName())) { + return info.topActivity.getClassName(); + } + } + return null; + } + +} diff --git a/app/src/main/java/com/gh/common/util/SpeedUtils.java b/app/src/main/java/com/gh/common/util/SpeedUtils.java new file mode 100644 index 0000000000..6c34784946 --- /dev/null +++ b/app/src/main/java/com/gh/common/util/SpeedUtils.java @@ -0,0 +1,38 @@ +package com.gh.common.util; + +public class SpeedUtils { + + public static String getSpeed(long kSpeed) { + if (kSpeed >= 1000) { + float mSpeed = kSpeed / 1024f; + String str = mSpeed + ""; + if (str.length() > 4) { + str = str.substring(0, 4); + } + return str + "MB/s"; + } + return kSpeed + "K/s"; + } + + public static String getRemainTime(long totalSize, long currentSize, + long speed) { + long remainSize = totalSize - currentSize; + long remainTime = 0; + if (speed != 0) { + remainTime = remainSize / speed; + } else { + return "0分0秒"; + } + int hour = (int) (remainTime / 3600); + remainTime = (remainTime - hour * 3660); + int minute = (int) (remainTime / 60); + int second = (int) (remainTime - minute * 60); + if (hour != 0) { + return hour + "时" + minute + "分" + second + "秒"; + } else if (minute != 0) { + return minute + "分" + second + "秒"; + } else { + return second + "秒"; + } + } +} diff --git a/app/src/main/java/com/gh/common/util/TimestampUtils.java b/app/src/main/java/com/gh/common/util/TimestampUtils.java new file mode 100644 index 0000000000..5ecd7ffbd5 --- /dev/null +++ b/app/src/main/java/com/gh/common/util/TimestampUtils.java @@ -0,0 +1,43 @@ +package com.gh.common.util; + +public class TimestampUtils { + + // 基准时间 + private static final long BASE = 1426608000000L; + + /* + * 根据CD获取时间戳 + */ + public static long getTimestamp(int cd) { + long now = System.currentTimeMillis(); + return (long) (Math.ceil((now - BASE) / cd) * cd + BASE); + } + + /* + * 为url添加timestamp + */ + public static String addTimestamp(String url, int cd) { + if (url.contains("?")) { + return url + "×tamp=" + getTimestamp(cd); + } else { + return url + "?timestamp=" + getTimestamp(cd); + } + } + + /* + * 去除url中的timestamp + */ + public static String removeTimestamp(String url) { + int index = url.lastIndexOf("timestamp"); + String params = url.substring(index); + //连接符 + String connector = url.substring(index - 1, index); + String key = url.substring(0, index - 1); + index = params.indexOf("&"); + if (index != -1) { + key = key + connector + params.substring(index + 1); + } + return key; + } + +} diff --git a/app/src/main/java/com/gh/common/util/TokenUtils.java b/app/src/main/java/com/gh/common/util/TokenUtils.java new file mode 100644 index 0000000000..1ab39319e5 --- /dev/null +++ b/app/src/main/java/com/gh/common/util/TokenUtils.java @@ -0,0 +1,110 @@ +package com.gh.common.util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import org.json.JSONException; +import org.json.JSONObject; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; + +import com.gh.common.constant.Config; + +public class TokenUtils { + + // 获取用户token + public static synchronized String getToken(Context context) { + SharedPreferences sp = context.getSharedPreferences(Config.PREFERENCE, + Context.MODE_PRIVATE); + String token = sp.getString("token", null); + if (token != null) { + long expire = sp.getLong("token_expire", 0) * 1000 - 10 * 1000; + long time = System.currentTimeMillis(); + // 判断token是否过期 + if (time < expire) { + return token; + } + } + +// Map params = DeviceUtils.getDeviceParams(context); + Map params = new HashMap(); + String url = Config.HOST + "v1d45/token/visit"; + + //判断是否已登录 + if (sp.getBoolean("isLogin", false)) { + // 已登录,获取用户名和密码自动登录 + String username = sp.getString("username", null); + String password = sp.getString("password", null); + if (username == null || password == null) { + url = Config.HOST + "v2/token/user?time=" + System.currentTimeMillis(); + params.put("username", username); + try { + String s = RSEUtils.encryptByPublic(password + username + System.currentTimeMillis() / 1000); + Utils.log("加密 = " + s); + params.put("password", s); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + url = Config.HOST + "v2/token/mobile?time=" + System.currentTimeMillis(); + String mobile = sp.getString("mobile", null); + params.put("mobile_number", mobile); + } + } + + try { + JSONObject body = new JSONObject(params); + HttpURLConnection connection = (HttpURLConnection) new URL(url) + .openConnection(); + connection.setDoInput(true); + connection.setDoOutput(true); + connection.setConnectTimeout(5000); + connection.setRequestMethod("POST"); + + connection.addRequestProperty("Content-Type", "application/json; charset=utf-8"); + connection.addRequestProperty("Device", DeviceUtils.getDeviceHeader(context)); + + connection.connect(); + + OutputStreamWriter outputStream = new OutputStreamWriter( + connection.getOutputStream(), "utf-8"); + outputStream.write(body.toString()); + outputStream.flush(); + outputStream.close(); + + if (connection.getResponseCode() == 200) { + BufferedReader reader = new BufferedReader( + new InputStreamReader(connection.getInputStream())); + StringBuilder builder = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + builder.append(line); + } + reader.close(); + try { + JSONObject jsonObject = new JSONObject(builder.toString()); + Editor editor = sp.edit(); + editor.putString("token", jsonObject.getString("token")); + editor.putLong("token_expire", jsonObject.getLong("expire")); + editor.apply(); + return jsonObject.getString("token"); + } catch (JSONException e) { + e.printStackTrace(); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + + return null; + } + +} diff --git a/app/src/main/java/com/gh/common/util/Trace.java b/app/src/main/java/com/gh/common/util/Trace.java new file mode 100644 index 0000000000..c09fb619e3 --- /dev/null +++ b/app/src/main/java/com/gh/common/util/Trace.java @@ -0,0 +1,64 @@ +package com.gh.common.util; + +import java.util.HashMap; +import java.util.Map; + +import android.util.Log; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-8-19 + * @update 2015-8-19 + * @des 控制debug调试信息 + */ +public class Trace { + private final String TAG = "gh_debug"; + private Map maps;//(tag, boolean), boolean = true,表示debug信息可以显示,否则不能显示 + + private static Trace mInstance; + + private Trace(){ + maps = new HashMap(); + } + + public static Trace getInstance(){ + synchronized (Trace.class) { + if(mInstance == null) + mInstance = new Trace(); + return mInstance; + } + } + + + public void debug(String tag, String msg){ + if(maps.get(tag) == null){ + maps.put(tag, false); + } + + if(maps.get(tag) == true){ + Log.d(TAG, tag + "==>" + msg); + } + } + + /** + * + * @param tag debug的tag + * @param flag true,则输出该tag的debug信息,否则不输出该tag的debug信息 + */ + public void setClassDebug(String tag, boolean flag){ + maps.put(tag, flag); + } + + /** + * + * @param flag true--所有tag的debug消息都可以输出,否则全部都不输出 + */ + public void setDebug(boolean flag){ + for ( String tag : maps.keySet()) { + maps.put(tag, flag); + } + } + +} diff --git a/app/src/main/java/com/gh/common/util/TrafficUtils.java b/app/src/main/java/com/gh/common/util/TrafficUtils.java new file mode 100644 index 0000000000..abf27d3cb0 --- /dev/null +++ b/app/src/main/java/com/gh/common/util/TrafficUtils.java @@ -0,0 +1,195 @@ +package com.gh.common.util; + +import java.util.Calendar; +import java.util.List; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.net.TrafficStats; + +public class TrafficUtils { + + static TrafficUtils instance; + DB db; + Context context; + + public static TrafficUtils getInstance(Context context) { + return getInstance(context, false); + } + + public static TrafficUtils getInstance(Context context, boolean update) { + if (instance == null) { + synchronized (TrafficUtils.class) { + if (instance == null) { + instance = new TrafficUtils(context); + if (update) + instance.update(); + return instance; + } + } + } + if (update) + instance.update(); + return instance; + } + + private TrafficUtils(Context context) { + this.context = context.getApplicationContext(); + db = new DB(this.context); + } + + public void update() { + + // 获取所有的安装在手机上的应用软件的信息,并且获取这些软件里面的权限信息 + PackageManager pm = context.getPackageManager();// 获取系统应用包管理 + // 获取每个包内的androidmanifest.xml信息,它的权限等等 + List pinfos = pm + .getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES + | PackageManager.GET_PERMISSIONS); + // 遍历每个应用包信息 + for (PackageInfo info : pinfos) { + // 请求每个程序包对应的androidManifest.xml里面的权限 + String[] premissions = info.requestedPermissions; + if (premissions != null && premissions.length > 0) { + // 找出需要网络服务的应用程序 + for (String premission : premissions) { + if ("android.permission.INTERNET".equals(premission)) { + // 获取每个应用程序在操作系统内的进程id + int uId = info.applicationInfo.uid; + // 如果返回-1,代表不支持使用该方法,注意必须是2.2以上的 + long rx = TrafficStats.getUidRxBytes(uId); + // 如果返回-1,代表不支持使用该方法,注意必须是2.2以上的 + long tx = TrafficStats.getUidTxBytes(uId); + if (rx < 0 || tx < 0) { + continue; + } else { + db.update(info.packageName, rx + tx); + } + } + } + } + } + + db.clean(Calendar.getInstance().getTimeInMillis() - 3600 * 24 * 30); + } + + public long getTraffic(List packageNameList) { + return this.getTraffic(packageNameList, Calendar.getInstance() + .getTimeInMillis() - 3600 * 24 * 7); + } + + public long getTraffic(List packageNameList, long from) { + return this.getTraffic(packageNameList, from, Calendar.getInstance() + .getTimeInMillis()); + } + + public long getTraffic(List packageNameList, long from, long to) { + long traffic = 0; + for (String packageName : packageNameList) { + traffic += db.getTraffic(packageName, from, to); + } + return traffic; + } + + public long getTraffice(String packageName){ + return db.getTraffic(packageName, Calendar.getInstance() + .getTimeInMillis() - 3600 * 24 * 7); + } + + public long getTraffice(String packageName, long from){ + return db.getTraffic(packageName, from); + } + + class DB extends SQLiteOpenHelper { + + static final String name = "gh_traffic.db"; + static final int version = 1; + + public DB(Context context) { + super(context, name, null, version); + } + + String traffic = "CREATE TABLE traffic(" + "package text," + + "traffic integer not null," + "time integer not null" + ");"; + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL(traffic); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + } + + public void update(String packageName, long traffic) { + String sql = "INSERT INTO traffic (package, traffic, time) VALUES (?, ?, ?)"; + Object[] bindArgs = new Object[] { packageName, traffic, + Calendar.getInstance().getTimeInMillis() }; + this.getWritableDatabase().execSQL(sql, bindArgs); + } + + public void clean(long time) { + String sql = "DELETE FROM traffic WHERE time < ? "; + Object[] bindArgs = new Object[] { time }; + this.getWritableDatabase().execSQL(sql, bindArgs); + } + + public long getTraffic(String packageName, long from) { + return getTraffic(packageName, from, Calendar.getInstance() + .getTimeInMillis()); + } + + public long getTraffic(String packageName, long from, long to) { + long traffic = 0; + String sql = "SELECT * FROM traffic WHERE package = ? AND time >= ? AND time <= ? ORDER BY time DESC"; + String selectionArgs[] = new String[] { packageName, + String.valueOf(from), String.valueOf(to) }; + Cursor cursor = this.getReadableDatabase().rawQuery(sql, + selectionArgs); + if (cursor.getCount() > 1) { + cursor.moveToFirst(); + long traffic1 = cursor + .getLong(cursor.getColumnIndex("traffic")); + // long time1 = cursor.getLong(cursor.getColumnIndex("time")); + cursor.moveToLast(); + long traffic2 = cursor + .getLong(cursor.getColumnIndex("traffic")); + // long time2 = cursor.getLong(cursor.getColumnIndex("time")); + traffic = traffic1 - traffic2; + // long cha = traffic1 - traffic2; + // if(cha > 0){ + // traffic = cha / (time2 - time1); + // } + } else if (cursor.getCount() == 1) { + sql = "SELECT * FROM traffic WHERE package = ? AND time < ? ORDER BY time DESC"; + selectionArgs = new String[] { packageName, + String.valueOf(from) }; + Cursor cursor2 = this.getReadableDatabase().rawQuery(sql, + selectionArgs); + if (cursor2.moveToNext()) { + cursor.moveToFirst(); + long traffic1 = cursor.getLong(cursor + .getColumnIndex("traffic")); + // long time1 = + // cursor.getLong(cursor.getColumnIndex("time")); + long traffic2 = cursor2.getLong(cursor + .getColumnIndex("traffic")); + // long time2 = + // cursor2.getLong(cursor.getColumnIndex("time")); + traffic = traffic1 - traffic2; + // long cha = traffic1 - traffic2; + // if(cha > 0){ + // traffic = cha / (time2 - time1); + // } + } + cursor2.close(); + } + cursor.close(); + return traffic; + } + } +} diff --git a/app/src/main/java/com/gh/common/util/Utils.java b/app/src/main/java/com/gh/common/util/Utils.java new file mode 100644 index 0000000000..4c98aa21ec --- /dev/null +++ b/app/src/main/java/com/gh/common/util/Utils.java @@ -0,0 +1,59 @@ +package com.gh.common.util; + +import java.lang.reflect.Field; + +import android.content.Context; +import android.util.Log; +import android.view.View; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.Toast; + +import com.gh.gamecenter.R; + +public class Utils { + + public static void log(String msg) { + Log.e("result", msg); + } + + public static void log(Object obj) { + Log.e("result", obj.getClass().getSimpleName() + " = " + obj.toString()); + } + + public static void toast(Context context, String text) { + Toast.makeText(context, text, Toast.LENGTH_SHORT).show(); + } + + public static void hideSoftInput(Context context, EditText editText) { + InputMethodManager imm = (InputMethodManager) context + .getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(editText.getWindowToken(), 0); + } + + public static void showSoftInput(Context context, EditText editText) { + InputMethodManager imm = (InputMethodManager) context + .getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(editText, InputMethodManager.SHOW_FORCED); + } + + @SuppressWarnings("unchecked") + public static T getView(View view, int id) { + return (T) view.findViewById(id); + } + + public static int getId(String name) { + try { + Class arrayClass = R.id.class; + for (Field field : arrayClass.getFields()) { + if (field.getName().equals(name)) { + return field.getInt(name); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return -1; + } + +} diff --git a/app/src/main/java/com/gh/common/view/AutoScrollViewPager.java b/app/src/main/java/com/gh/common/view/AutoScrollViewPager.java new file mode 100644 index 0000000000..f19d98b050 --- /dev/null +++ b/app/src/main/java/com/gh/common/view/AutoScrollViewPager.java @@ -0,0 +1,409 @@ +package com.gh.common.view; + +import java.lang.ref.WeakReference; +import java.lang.reflect.Field; + +import android.content.Context; +import android.os.Handler; +import android.os.Message; +import android.support.v4.view.MotionEventCompat; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.animation.Interpolator; + +/** + * Auto Scroll View Pager + *
    + * Basic Setting and Usage + *
  • {@link #startAutoScroll()} start auto scroll, or + * {@link #startAutoScroll(int)} start auto scroll delayed
  • + *
  • {@link #stopAutoScroll()} stop auto scroll
  • + *
  • {@link #setInterval(long)} set auto scroll time in milliseconds, default + * is {@link #DEFAULT_INTERVAL}
  • + *
+ *
    + * Advanced Settings and Usage + *
  • {@link #setDirection(int)} set auto scroll direction
  • + *
  • {@link #setCycle(boolean)} set whether automatic cycle when auto scroll + * reaching the last or first item, default is true
  • + *
  • {@link #setSlideBorderMode(int)} set how to process when sliding at the + * last or first item
  • + *
  • {@link #setStopScrollWhenTouch(boolean)} set whether stop auto scroll + * when touching, default is true
  • + *
+ * + * @author Trinea 2013-12-30 + */ +public class AutoScrollViewPager extends ViewPager { + + public static final int DEFAULT_INTERVAL = 1500; + + public static final int LEFT = 0; + public static final int RIGHT = 1; + + /** do nothing when sliding at the last or first item **/ + public static final int SLIDE_BORDER_MODE_NONE = 0; + /** cycle when sliding at the last or first item **/ + public static final int SLIDE_BORDER_MODE_CYCLE = 1; + /** deliver event to parent when sliding at the last or first item **/ + public static final int SLIDE_BORDER_MODE_TO_PARENT = 2; + + /** auto scroll time in milliseconds, default is {@link #DEFAULT_INTERVAL} **/ + private long interval = DEFAULT_INTERVAL; + /** auto scroll direction, default is {@link #RIGHT} **/ + private int direction = RIGHT; + /** + * whether automatic cycle when auto scroll reaching the last or first item, + * default is true + **/ + private boolean isCycle = true; + /** whether stop auto scroll when touching, default is true **/ + private boolean stopScrollWhenTouch = true; + /** + * how to process when sliding at the last or first item, default is + * {@link #SLIDE_BORDER_MODE_NONE} + **/ + private int slideBorderMode = SLIDE_BORDER_MODE_NONE; + /** whether animating when auto scroll at the last or first item **/ + private boolean isBorderAnimation = true; + /** scroll factor for auto scroll animation, default is 1.0 **/ + private double autoScrollFactor = 10.0; + /** scroll factor for swipe scroll animation, default is 1.0 **/ + private double swipeScrollFactor = 1.0; + + private Handler handler; + private boolean isAutoScroll = false; + private boolean isStopByTouch = false; + private float touchX = 0f, downX = 0f; + private CustomDurationScroller scroller = null; + + public static final int SCROLL_WHAT = 0; + + public AutoScrollViewPager(Context paramContext) { + super(paramContext); + init(); + } + + public AutoScrollViewPager(Context paramContext, + AttributeSet paramAttributeSet) { + super(paramContext, paramAttributeSet); + init(); + } + + private void init() { + handler = new MyHandler(this); + setViewPagerScroller(); + } + + /** + * start auto scroll, first scroll delay time is {@link #getInterval()} + */ + public void startAutoScroll() { + isAutoScroll = true; + sendScrollMessage((long) (interval + scroller.getDuration() + / autoScrollFactor * swipeScrollFactor)); + } + + /** + * start auto scroll + * + * @param delayTimeInMills + * first scroll delay time + */ + public void startAutoScroll(int delayTimeInMills) { + isAutoScroll = true; + sendScrollMessage(delayTimeInMills); + } + + /** + * stop auto scroll + */ + public void stopAutoScroll() { + isAutoScroll = false; + handler.removeMessages(SCROLL_WHAT); + } + + /** + * set the factor by which the duration of sliding animation will change + * while swiping + */ + public void setSwipeScrollDurationFactor(double scrollFactor) { + swipeScrollFactor = scrollFactor; + } + + /** + * set the factor by which the duration of sliding animation will change + * while auto scrolling + */ + public void setAutoScrollDurationFactor(double scrollFactor) { + autoScrollFactor = scrollFactor; + } + + private void sendScrollMessage(long delayTimeInMills) { + /** remove messages before, keeps one message is running at most **/ + handler.removeMessages(SCROLL_WHAT); + handler.sendEmptyMessageDelayed(SCROLL_WHAT, delayTimeInMills); + } + + /** + * set ViewPager scroller to change animation duration when sliding + */ + private void setViewPagerScroller() { + try { + Field scrollerField = ViewPager.class.getDeclaredField("mScroller"); + scrollerField.setAccessible(true); + Field interpolatorField = ViewPager.class + .getDeclaredField("sInterpolator"); + interpolatorField.setAccessible(true); + + scroller = new CustomDurationScroller(getContext(), + (Interpolator) interpolatorField.get(null)); + scrollerField.set(this, scroller); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * scroll only once + */ + public void scrollOnce() { + PagerAdapter adapter = getAdapter(); + int currentItem = getCurrentItem(); + int totalCount; + if (adapter == null || (totalCount = adapter.getCount()) <= 1) { + return; + } + + int nextItem = (direction == LEFT) ? --currentItem : ++currentItem; + if (nextItem < 0) { + if (isCycle) { + setCurrentItem(totalCount - 1, isBorderAnimation); + } + } else if (nextItem == totalCount) { + if (isCycle) { + setCurrentItem(0, isBorderAnimation); + } + } else { + setCurrentItem(nextItem, true); + } + } + + /** + *
    + * if stopScrollWhenTouch is true + *
  • if event is down, stop auto scroll.
  • + *
  • if event is up, start auto scroll again.
  • + *
+ */ + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + int action = MotionEventCompat.getActionMasked(ev); + + if (stopScrollWhenTouch) { + if ((action == MotionEvent.ACTION_DOWN) && isAutoScroll) { + isStopByTouch = true; + stopAutoScroll(); + } else if (ev.getAction() == MotionEvent.ACTION_UP && isStopByTouch) { + startAutoScroll(); + } + } + + if (slideBorderMode == SLIDE_BORDER_MODE_TO_PARENT + || slideBorderMode == SLIDE_BORDER_MODE_CYCLE) { + touchX = ev.getX(); + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + downX = touchX; + } + int currentItem = getCurrentItem(); + PagerAdapter adapter = getAdapter(); + int pageCount = adapter == null ? 0 : adapter.getCount(); + /** + * current index is first one and slide to right or current index is + * last one and slide to left.
+ * if slide border mode is to parent, then + * requestDisallowInterceptTouchEvent false.
+ * else scroll to last one when current item is first one, scroll to + * first one when current item is last one. + */ + if ((currentItem == 0 && downX <= touchX) + || (currentItem == pageCount - 1 && downX >= touchX)) { + if (slideBorderMode == SLIDE_BORDER_MODE_TO_PARENT) { + getParent().requestDisallowInterceptTouchEvent(false); + } else { + if (pageCount > 1) { + setCurrentItem(pageCount - currentItem - 1, + isBorderAnimation); + } + getParent().requestDisallowInterceptTouchEvent(true); + } + return super.dispatchTouchEvent(ev); + } + } + getParent().requestDisallowInterceptTouchEvent(true); + + return super.dispatchTouchEvent(ev); + } + + private static class MyHandler extends Handler { + + private final WeakReference autoScrollViewPager; + + public MyHandler(AutoScrollViewPager autoScrollViewPager) { + this.autoScrollViewPager = new WeakReference( + autoScrollViewPager); + } + + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + + switch (msg.what) { + case SCROLL_WHAT: + AutoScrollViewPager pager = this.autoScrollViewPager.get(); + if (pager != null) { + pager.scroller + .setScrollDurationFactor(pager.autoScrollFactor); + pager.scrollOnce(); + pager.scroller + .setScrollDurationFactor(pager.swipeScrollFactor); + pager.sendScrollMessage(pager.interval + + pager.scroller.getDuration()); + } + default: + break; + } + } + } + + /** + * get auto scroll time in milliseconds, default is + * {@link #DEFAULT_INTERVAL} + * + * @return the interval + */ + public long getInterval() { + return interval; + } + + /** + * set auto scroll time in milliseconds, default is + * {@link #DEFAULT_INTERVAL} + * + * @param interval + * the interval to set + */ + public void setInterval(long interval) { + this.interval = interval; + } + + /** + * get auto scroll direction + * + * @return {@link #LEFT} or {@link #RIGHT}, default is {@link #RIGHT} + */ + public int getDirection() { + return (direction == LEFT) ? LEFT : RIGHT; + } + + /** + * set auto scroll direction + * + * @param direction + * {@link #LEFT} or {@link #RIGHT}, default is {@link #RIGHT} + */ + public void setDirection(int direction) { + this.direction = direction; + } + + /** + * whether automatic cycle when auto scroll reaching the last or first item, + * default is true + * + * @return the isCycle + */ + public boolean isCycle() { + return isCycle; + } + + /** + * set whether automatic cycle when auto scroll reaching the last or first + * item, default is true + * + * @param isCycle + * the isCycle to set + */ + public void setCycle(boolean isCycle) { + this.isCycle = isCycle; + } + + /** + * whether stop auto scroll when touching, default is true + * + * @return the stopScrollWhenTouch + */ + public boolean isStopScrollWhenTouch() { + return stopScrollWhenTouch; + } + + /** + * set whether stop auto scroll when touching, default is true + * + * @param stopScrollWhenTouch + */ + public void setStopScrollWhenTouch(boolean stopScrollWhenTouch) { + this.stopScrollWhenTouch = stopScrollWhenTouch; + } + + /** + * get how to process when sliding at the last or first item + * + * @return the slideBorderMode {@link #SLIDE_BORDER_MODE_NONE}, + * {@link #SLIDE_BORDER_MODE_TO_PARENT}, + * {@link #SLIDE_BORDER_MODE_CYCLE}, default is + * {@link #SLIDE_BORDER_MODE_NONE} + */ + public int getSlideBorderMode() { + return slideBorderMode; + } + + /** + * set how to process when sliding at the last or first item + * + * @param slideBorderMode + * {@link #SLIDE_BORDER_MODE_NONE}, + * {@link #SLIDE_BORDER_MODE_TO_PARENT}, + * {@link #SLIDE_BORDER_MODE_CYCLE}, default is + * {@link #SLIDE_BORDER_MODE_NONE} + */ + public void setSlideBorderMode(int slideBorderMode) { + this.slideBorderMode = slideBorderMode; + } + + /** + * whether animating when auto scroll at the last or first item, default is + * true + * + * @return + */ + public boolean isBorderAnimation() { + return isBorderAnimation; + } + + /** + * set whether animating when auto scroll at the last or first item, default + * is true + * + * @param isBorderAnimation + */ + public void setBorderAnimation(boolean isBorderAnimation) { + this.isBorderAnimation = isBorderAnimation; + } + + public boolean isAutoScroll() { + return isAutoScroll; + } + +} diff --git a/app/src/main/java/com/gh/common/view/BezelImageView.java b/app/src/main/java/com/gh/common/view/BezelImageView.java new file mode 100644 index 0000000000..12e1404f5f --- /dev/null +++ b/app/src/main/java/com/gh/common/view/BezelImageView.java @@ -0,0 +1,224 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gh.common.view; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.support.v4.view.ViewCompat; +import android.util.AttributeSet; +import android.widget.ImageView; + +import com.gh.gamecenter.R; + +/** + * An {@link ImageView} that draws its contents inside a mask and + * draws a border drawable on top. This is useful for applying a beveled look to + * image contents, but is also flexible enough for use with other desired + * aesthetics. + */ +public class BezelImageView extends ImageView { + private Paint mBlackPaint; + private Paint mMaskedPaint; + + private Rect mBounds; + private RectF mBoundsF; + + private Drawable mBorderDrawable; + private Drawable mMaskDrawable; + + private ColorMatrixColorFilter mDesaturateColorFilter; + private boolean mDesaturateOnPress = false; + + private boolean mCacheValid = false; + private Bitmap mCacheBitmap; + private int mCachedWidth; + private int mCachedHeight; + + public BezelImageView(Context context) { + this(context, null); + } + + public BezelImageView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public BezelImageView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + // Attribute initialization + final TypedArray a = context.obtainStyledAttributes(attrs, + R.styleable.BezelImageView, defStyle, 0); + + mMaskDrawable = a.getDrawable(R.styleable.BezelImageView_maskDrawable); + if (mMaskDrawable != null) { + mMaskDrawable.setCallback(this); + } + + mBorderDrawable = a + .getDrawable(R.styleable.BezelImageView_borderDrawable); + if (mBorderDrawable != null) { + mBorderDrawable.setCallback(this); + } + + mDesaturateOnPress = a.getBoolean( + R.styleable.BezelImageView_desaturateOnPress, + mDesaturateOnPress); + + a.recycle(); + + // Other initialization + mBlackPaint = new Paint(); + mBlackPaint.setColor(0xff000000); + + mMaskedPaint = new Paint(); + mMaskedPaint + .setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); + + // Always want a cache allocated. + mCacheBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); + + if (mDesaturateOnPress) { + // Create a desaturate color filter for pressed state. + ColorMatrix cm = new ColorMatrix(); + cm.setSaturation(0); + mDesaturateColorFilter = new ColorMatrixColorFilter(cm); + } + } + + @Override + protected boolean setFrame(int l, int t, int r, int b) { + final boolean changed = super.setFrame(l, t, r, b); + mBounds = new Rect(0, 0, r - l, b - t); + mBoundsF = new RectF(mBounds); + + if (mBorderDrawable != null) { + mBorderDrawable.setBounds(mBounds); + } + if (mMaskDrawable != null) { + mMaskDrawable.setBounds(mBounds); + } + + if (changed) { + mCacheValid = false; + } + + return changed; + } + + @Override + protected void onDraw(Canvas canvas) { + if (mBounds == null) { + return; + } + + int width = mBounds.width(); + int height = mBounds.height(); + + if (width == 0 || height == 0) { + return; + } + + if (!mCacheValid || width != mCachedWidth || height != mCachedHeight) { + // Need to redraw the cache + if (width == mCachedWidth && height == mCachedHeight) { + // Have a correct-sized bitmap cache already allocated. Just + // erase it. + mCacheBitmap.eraseColor(0); + } else { + // Allocate a new bitmap with the correct dimensions. + mCacheBitmap.recycle(); + // noinspection AndroidLintDrawAllocation + mCacheBitmap = Bitmap.createBitmap(width, height, + Bitmap.Config.ARGB_8888); + mCachedWidth = width; + mCachedHeight = height; + } + + Canvas cacheCanvas = new Canvas(mCacheBitmap); + if (mMaskDrawable != null) { + int sc = cacheCanvas.save(); + mMaskDrawable.draw(cacheCanvas); + mMaskedPaint + .setColorFilter((mDesaturateOnPress && isPressed()) ? mDesaturateColorFilter + : null); + cacheCanvas.saveLayer(mBoundsF, mMaskedPaint, + Canvas.HAS_ALPHA_LAYER_SAVE_FLAG + | Canvas.FULL_COLOR_LAYER_SAVE_FLAG); + super.onDraw(cacheCanvas); + cacheCanvas.restoreToCount(sc); + } else if (mDesaturateOnPress && isPressed()) { + int sc = cacheCanvas.save(); + cacheCanvas.drawRect(0, 0, mCachedWidth, mCachedHeight, + mBlackPaint); + mMaskedPaint.setColorFilter(mDesaturateColorFilter); + cacheCanvas.saveLayer(mBoundsF, mMaskedPaint, + Canvas.HAS_ALPHA_LAYER_SAVE_FLAG + | Canvas.FULL_COLOR_LAYER_SAVE_FLAG); + super.onDraw(cacheCanvas); + cacheCanvas.restoreToCount(sc); + } else { + super.onDraw(cacheCanvas); + } + + if (mBorderDrawable != null) { + mBorderDrawable.draw(cacheCanvas); + } + } + + // Draw from cache + canvas.drawBitmap(mCacheBitmap, mBounds.left, mBounds.top, null); + } + + @Override + protected void drawableStateChanged() { + super.drawableStateChanged(); + if (mBorderDrawable != null && mBorderDrawable.isStateful()) { + mBorderDrawable.setState(getDrawableState()); + } + if (mMaskDrawable != null && mMaskDrawable.isStateful()) { + mMaskDrawable.setState(getDrawableState()); + } + if (isDuplicateParentStateEnabled()) { + ViewCompat.postInvalidateOnAnimation(this); + } + } + + @Override + public void invalidateDrawable(Drawable who) { + if (who == mBorderDrawable || who == mMaskDrawable) { + invalidate(); + } else { + super.invalidateDrawable(who); + } + } + + @Override + protected boolean verifyDrawable(Drawable who) { + return who == mBorderDrawable || who == mMaskDrawable + || super.verifyDrawable(who); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/common/view/CircleImageView.java b/app/src/main/java/com/gh/common/view/CircleImageView.java new file mode 100644 index 0000000000..b186ecd069 --- /dev/null +++ b/app/src/main/java/com/gh/common/view/CircleImageView.java @@ -0,0 +1,314 @@ +package com.gh.common.view; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.Shader; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.support.annotation.ColorRes; +import android.support.annotation.DrawableRes; +import android.util.AttributeSet; +import android.widget.ImageView; + +import com.gh.gamecenter.R; + +public class CircleImageView extends ImageView { + + private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP; + + private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888; + private static final int COLORDRAWABLE_DIMENSION = 2; + + private static final int DEFAULT_BORDER_WIDTH = 0; + private static final int DEFAULT_BORDER_COLOR = Color.BLACK; + private static final boolean DEFAULT_BORDER_OVERLAY = false; + + private final RectF mDrawableRect = new RectF(); + private final RectF mBorderRect = new RectF(); + + private final Matrix mShaderMatrix = new Matrix(); + private final Paint mBitmapPaint = new Paint(); + private final Paint mBorderPaint = new Paint(); + + private int mBorderColor = DEFAULT_BORDER_COLOR; + private int mBorderWidth = DEFAULT_BORDER_WIDTH; + + private Bitmap mBitmap; + private BitmapShader mBitmapShader; + private int mBitmapWidth; + private int mBitmapHeight; + + private float mDrawableRadius; + private float mBorderRadius; + + private ColorFilter mColorFilter; + + private boolean mReady; + private boolean mSetupPending; + private boolean mBorderOverlay; + + public CircleImageView(Context context) { + super(context); + + init(); + } + + public CircleImageView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public CircleImageView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + TypedArray a = context.obtainStyledAttributes(attrs, + R.styleable.CircleImageView, defStyle, 0); + + mBorderWidth = a.getDimensionPixelSize( + R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH); + mBorderColor = a.getColor(R.styleable.CircleImageView_border_color, + DEFAULT_BORDER_COLOR); + mBorderOverlay = a.getBoolean( + R.styleable.CircleImageView_border_overlay, + DEFAULT_BORDER_OVERLAY); + + a.recycle(); + + init(); + } + + private void init() { + super.setScaleType(SCALE_TYPE); + mReady = true; + + if (mSetupPending) { + setup(); + mSetupPending = false; + } + } + + @Override + public ScaleType getScaleType() { + return SCALE_TYPE; + } + + @Override + public void setScaleType(ScaleType scaleType) { + if (scaleType != SCALE_TYPE) { + throw new IllegalArgumentException(String.format( + "ScaleType %s not supported.", scaleType)); + } + } + + @Override + public void setAdjustViewBounds(boolean adjustViewBounds) { + if (adjustViewBounds) { + throw new IllegalArgumentException( + "adjustViewBounds not supported."); + } + } + + @Override + protected void onDraw(Canvas canvas) { + if (getDrawable() == null) { + return; + } + + canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, + mBitmapPaint); + if (mBorderWidth != 0) { + canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, + mBorderPaint); + } + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + setup(); + } + + public int getBorderColor() { + return mBorderColor; + } + + public void setBorderColor(int borderColor) { + if (borderColor == mBorderColor) { + return; + } + + mBorderColor = borderColor; + mBorderPaint.setColor(mBorderColor); + invalidate(); + } + + public void setBorderColorResource(@ColorRes int borderColorRes) { + setBorderColor(getContext().getResources().getColor(borderColorRes)); + } + + public int getBorderWidth() { + return mBorderWidth; + } + + public void setBorderWidth(int borderWidth) { + if (borderWidth == mBorderWidth) { + return; + } + + mBorderWidth = borderWidth; + setup(); + } + + public boolean isBorderOverlay() { + return mBorderOverlay; + } + + public void setBorderOverlay(boolean borderOverlay) { + if (borderOverlay == mBorderOverlay) { + return; + } + + mBorderOverlay = borderOverlay; + setup(); + } + + @Override + public void setImageBitmap(Bitmap bm) { + super.setImageBitmap(bm); + mBitmap = bm; + setup(); + } + + @Override + public void setImageDrawable(Drawable drawable) { + super.setImageDrawable(drawable); + mBitmap = getBitmapFromDrawable(drawable); + setup(); + } + + @Override + public void setImageResource(@DrawableRes int resId) { + super.setImageResource(resId); + mBitmap = getBitmapFromDrawable(getDrawable()); + setup(); + } + + @Override + public void setImageURI(Uri uri) { + super.setImageURI(uri); + mBitmap = getBitmapFromDrawable(getDrawable()); + setup(); + } + + @Override + public void setColorFilter(ColorFilter cf) { + if (cf == mColorFilter) { + return; + } + + mColorFilter = cf; + mBitmapPaint.setColorFilter(mColorFilter); + invalidate(); + } + + private Bitmap getBitmapFromDrawable(Drawable drawable) { + if (drawable == null) { + return null; + } + + if (drawable instanceof BitmapDrawable) { + return ((BitmapDrawable) drawable).getBitmap(); + } + + try { + Bitmap bitmap; + + if (drawable instanceof ColorDrawable) { + bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, + COLORDRAWABLE_DIMENSION, BITMAP_CONFIG); + } else { + bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), + drawable.getIntrinsicHeight(), BITMAP_CONFIG); + } + + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + return bitmap; + } catch (OutOfMemoryError e) { + return null; + } + } + + private void setup() { + if (!mReady) { + mSetupPending = true; + return; + } + + if (mBitmap == null) { + return; + } + + mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, + Shader.TileMode.CLAMP); + + mBitmapPaint.setAntiAlias(true); + mBitmapPaint.setShader(mBitmapShader); + + mBorderPaint.setStyle(Paint.Style.STROKE); + mBorderPaint.setAntiAlias(true); + mBorderPaint.setColor(mBorderColor); + mBorderPaint.setStrokeWidth(mBorderWidth); + + mBitmapHeight = mBitmap.getHeight(); + mBitmapWidth = mBitmap.getWidth(); + + mBorderRect.set(0, 0, getWidth(), getHeight()); + mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2, + (mBorderRect.width() - mBorderWidth) / 2); + + mDrawableRect.set(mBorderRect); + if (!mBorderOverlay) { + mDrawableRect.inset(mBorderWidth, mBorderWidth); + } + mDrawableRadius = Math.min(mDrawableRect.height() / 2, + mDrawableRect.width() / 2); + + updateShaderMatrix(); + invalidate(); + } + + private void updateShaderMatrix() { + float scale; + float dx = 0; + float dy = 0; + + mShaderMatrix.set(null); + + if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() + * mBitmapHeight) { + scale = mDrawableRect.height() / (float) mBitmapHeight; + dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f; + } else { + scale = mDrawableRect.width() / (float) mBitmapWidth; + dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f; + } + + mShaderMatrix.setScale(scale, scale); + mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, + (int) (dy + 0.5f) + mDrawableRect.top); + + mBitmapShader.setLocalMatrix(mShaderMatrix); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/common/view/Concern_LinearLayout.java b/app/src/main/java/com/gh/common/view/Concern_LinearLayout.java new file mode 100644 index 0000000000..4621938218 --- /dev/null +++ b/app/src/main/java/com/gh/common/view/Concern_LinearLayout.java @@ -0,0 +1,83 @@ +package com.gh.common.view; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; + +import com.gh.common.util.DisplayUtils; +import com.gh.gamecenter.R; + +public class Concern_LinearLayout extends LinearLayout { + + private RecyclerView concern_rv_recommend; + private ImageView concern_iv_delete; + + private int height; + private int distance; + + Runnable show = new Runnable() { + @Override + public void run() { + LayoutParams lparams = new LayoutParams( + LayoutParams.MATCH_PARENT, height); + lparams.height = concern_rv_recommend.getHeight() + distance; + if (lparams.height > height) { + lparams.height = height; + } + concern_rv_recommend.setLayoutParams(lparams); + invalidate(); + if (concern_rv_recommend.getHeight() < height) { + postDelayed(show, 10); + } else { + concern_iv_delete.setImageResource(R.drawable.concern_delete); + } + } + }; + + Runnable hide = new Runnable() { + @Override + public void run() { + LayoutParams lparams = new LayoutParams( + LayoutParams.MATCH_PARENT, height); + lparams.height = concern_rv_recommend.getHeight() - distance; + if (lparams.height < 0) { + lparams.height = 0; + } + concern_rv_recommend.setLayoutParams(lparams); + invalidate(); + if (concern_rv_recommend.getHeight() > 0) { + postDelayed(hide, 10); + } else { + concern_rv_recommend.setVisibility(View.GONE); + concern_iv_delete.setImageResource(R.drawable.concern_arrow); + } + } + }; + + public Concern_LinearLayout(Context context, AttributeSet attrs) { + super(context, attrs); + height = DisplayUtils.dip2px(context, 121); + distance = DisplayUtils.dip2px(context, 6); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + concern_rv_recommend = (RecyclerView) findViewById(R.id.concern_rv_recommend); + concern_iv_delete = (ImageView) findViewById(R.id.concern_iv_delete); + } + + public void showRecyclerView() { + concern_rv_recommend.setVisibility(View.VISIBLE); + removeCallbacks(hide); + post(show); + } + + public void hideRecyclerView() { + removeCallbacks(show); + post(hide); + } +} diff --git a/app/src/main/java/com/gh/common/view/CropImageBorderView.java b/app/src/main/java/com/gh/common/view/CropImageBorderView.java new file mode 100644 index 0000000000..3ad9ede849 --- /dev/null +++ b/app/src/main/java/com/gh/common/view/CropImageBorderView.java @@ -0,0 +1,93 @@ +package com.gh.common.view; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Paint.Style; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.View; + +public class CropImageBorderView extends View { + + /** + * 水平方向与View的边距 + */ + private int mHorizontalPadding; + /** + * 垂直方向与View的边距 + */ + private int mVerticalPadding; + /** + * 绘制的矩形的宽度 + */ + private int mWidth; + /** + * 边框的宽度 单位dp + */ + private int mBorderWidth = 1; + + private Paint mPaint, mPaintRect; + + public CropImageBorderView(Context context) { + this(context, null); + } + + public CropImageBorderView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public CropImageBorderView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + mBorderWidth = (int) TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, mBorderWidth, getResources() + .getDisplayMetrics()); + + // 绘制阴影 + mPaintRect = new Paint(); + mPaintRect.setARGB(136, 0, 0, 0); + mPaintRect.setStyle(Style.FILL); + + // 绘制边框 + mPaint = new Paint(); + mPaint.setStyle(Style.STROKE); + mPaint.setAntiAlias(true); + mPaint.setColor(Color.WHITE); + mPaint.setStrokeWidth(mBorderWidth); + + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + // 计算矩形区域的宽度 + mWidth = getWidth() - 2 * mHorizontalPadding; + // 计算距离屏幕垂直边界 的边距 + mVerticalPadding = (getHeight() - mWidth) / 2; + + // 绘制左边 + canvas.drawRect(0, 0, mHorizontalPadding, getHeight() + - mVerticalPadding, mPaintRect); + // 绘制右边 + canvas.drawRect(getWidth() - mHorizontalPadding, mVerticalPadding, + getWidth(), getHeight(), mPaintRect); + // 绘制上边 + canvas.drawRect(mHorizontalPadding, 0, getWidth(), mVerticalPadding, + mPaintRect); + // 绘制下边 + canvas.drawRect(0, getHeight() - mVerticalPadding, getWidth() + - mHorizontalPadding, getHeight(), mPaintRect); + + // 绘制边框 + canvas.drawRect(mHorizontalPadding, mVerticalPadding, + mHorizontalPadding + mWidth, mVerticalPadding + mWidth, mPaint); + + } + + public void setHorizontalPadding(int mHorizontalPadding) { + this.mHorizontalPadding = mHorizontalPadding; + + } + +} diff --git a/app/src/main/java/com/gh/common/view/CropImageCustom.java b/app/src/main/java/com/gh/common/view/CropImageCustom.java new file mode 100644 index 0000000000..58120758e8 --- /dev/null +++ b/app/src/main/java/com/gh/common/view/CropImageCustom.java @@ -0,0 +1,84 @@ +package com.gh.common.view; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +import android.content.Context; +import android.graphics.Bitmap; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.widget.ImageView; +import android.widget.RelativeLayout; + +public class CropImageCustom extends RelativeLayout { + + private CropImageZoomView mZoomImageView; + private CropImageBorderView mClipImageView; + + private int mHorizontalPadding = 20; + + public CropImageCustom(Context context, AttributeSet attrs) { + super(context, attrs); + + mZoomImageView = new CropImageZoomView(context); + mClipImageView = new CropImageBorderView(context); + + android.view.ViewGroup.LayoutParams lp = new LayoutParams( + android.view.ViewGroup.LayoutParams.MATCH_PARENT, + android.view.ViewGroup.LayoutParams.MATCH_PARENT); + + this.addView(mZoomImageView, lp); + this.addView(mClipImageView, lp); + + // 计算padding的px + mHorizontalPadding = (int) TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, mHorizontalPadding, getResources() + .getDisplayMetrics()); + mZoomImageView.setHorizontalPadding(mHorizontalPadding); + mClipImageView.setHorizontalPadding(mHorizontalPadding); + } + + /** + * 对外公布设置边距的方法,单位为dp + * + * @param mHorizontalPadding + */ + public void setHorizontalPadding(int mHorizontalPadding) { + this.mHorizontalPadding = mHorizontalPadding; + } + + /** + * 裁切图片 + * + * @return + */ + public Bitmap clip() { + return mZoomImageView.clip(); + } + + public void savePicture(String path) { + Bitmap bitmap = mZoomImageView.clip(); + File file = new File(path); + try { + BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream(file)); + bitmap.compress(Bitmap.CompressFormat.JPEG, 80, bos); + bos.flush(); + bos.close(); + } catch (IOException e) { + file.delete(); + e.printStackTrace(); + } + } + + public ImageView getCropImageZoomView() { + return mZoomImageView; + } + + public void setBitmap(Bitmap bitmap) { + mZoomImageView.setImageBitmap(bitmap); + } + +} diff --git a/app/src/main/java/com/gh/common/view/CropImageZoomView.java b/app/src/main/java/com/gh/common/view/CropImageZoomView.java new file mode 100644 index 0000000000..73902c0d7d --- /dev/null +++ b/app/src/main/java/com/gh/common/view/CropImageZoomView.java @@ -0,0 +1,416 @@ +package com.gh.common.view; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.GestureDetector; +import android.view.GestureDetector.SimpleOnGestureListener; +import android.view.MotionEvent; +import android.view.ScaleGestureDetector; +import android.view.ScaleGestureDetector.OnScaleGestureListener; +import android.view.View; +import android.view.View.OnTouchListener; +import android.view.ViewTreeObserver; +import android.widget.ImageView; + +@SuppressWarnings("deprecation") +public class CropImageZoomView extends ImageView implements + OnScaleGestureListener, OnTouchListener, + ViewTreeObserver.OnGlobalLayoutListener { + + public static float SCALE_MAX = 4.0f; + private static float SCALE_MID = 2.0f; + + /** + * 初始化时的缩放比例,如果图片宽或高大于屏幕,此值将小于0 + */ + private float initScale = 1.0f; + private boolean once = true; + + /** + * 用于存放矩阵的9个值 + */ + private final float[] matrixValues = new float[9]; + + /** + * 缩放的手势检测 + */ + private ScaleGestureDetector mScaleGestureDetector = null; + private final Matrix mScaleMatrix = new Matrix(); + + /** + * 用于双击检测 + */ + private GestureDetector mGestureDetector; + private boolean isAutoScale; + + private int mTouchSlop; + + private float mLastX; + private float mLastY; + + private boolean isCanDrag; + private int lastPointerCount; + + public CropImageZoomView(Context context) { + this(context, null); + } + + public CropImageZoomView(Context context, AttributeSet attrs) { + super(context, attrs); + + setScaleType(ScaleType.MATRIX); + mGestureDetector = new GestureDetector(context, + new SimpleOnGestureListener() { + @Override + public boolean onDoubleTap(MotionEvent e) { + if (isAutoScale == true) + return true; + + float x = e.getX(); + float y = e.getY(); + if (getScale() < SCALE_MID) { + CropImageZoomView.this.postDelayed( + new AutoScaleRunnable(SCALE_MID, x, y), 16); + isAutoScale = true; + } else { + CropImageZoomView.this.postDelayed( + new AutoScaleRunnable(initScale, x, y), 16); + isAutoScale = true; + } + + return true; + } + }); + mScaleGestureDetector = new ScaleGestureDetector(context, this); + this.setOnTouchListener(this); + } + + /** + * 自动缩放的任务 + * + * @author zhy + * + */ + private class AutoScaleRunnable implements Runnable { + static final float BIGGER = 1.07f; + static final float SMALLER = 0.93f; + private float mTargetScale; + private float tmpScale; + + /** + * 缩放的中心 + */ + private float x; + private float y; + + /** + * 传入目标缩放值,根据目标值与当前值,判断应该放大还是缩小 + * + * @param targetScale + */ + public AutoScaleRunnable(float targetScale, float x, float y) { + this.mTargetScale = targetScale; + this.x = x; + this.y = y; + if (getScale() < mTargetScale) { + tmpScale = BIGGER; + } else { + tmpScale = SMALLER; + } + + } + + @Override + public void run() { + // 进行缩放 + mScaleMatrix.postScale(tmpScale, tmpScale, x, y); + checkBorder(); + setImageMatrix(mScaleMatrix); + + final float currentScale = getScale(); + // 如果值在合法范围内,继续缩放 + if (((tmpScale > 1f) && (currentScale < mTargetScale)) + || ((tmpScale < 1f) && (mTargetScale < currentScale))) { + CropImageZoomView.this.postDelayed(this, 16); + } else + // 设置为目标的缩放比例 + { + final float deltaScale = mTargetScale / currentScale; + mScaleMatrix.postScale(deltaScale, deltaScale, x, y); + checkBorder(); + setImageMatrix(mScaleMatrix); + isAutoScale = false; + } + + } + } + + @Override + public boolean onScale(ScaleGestureDetector detector) { + float scale = getScale(); + float scaleFactor = detector.getScaleFactor(); + + if (getDrawable() == null) + return true; + + /** + * 缩放的范围控制 + */ + if ((scale < SCALE_MAX && scaleFactor > 1.0f) + || (scale > initScale && scaleFactor < 1.0f)) { + /** + * 最大值最小值判断 + */ + if (scaleFactor * scale < initScale) { + scaleFactor = initScale / scale; + } + if (scaleFactor * scale > SCALE_MAX) { + scaleFactor = SCALE_MAX / scale; + } + /** + * 设置缩放比例 + */ + mScaleMatrix.postScale(scaleFactor, scaleFactor, + detector.getFocusX(), detector.getFocusY()); + checkBorder(); + setImageMatrix(mScaleMatrix); + } + return true; + + } + + /** + * 根据当前图片的Matrix获得图片的范围 + * + * @return + */ + private RectF getMatrixRectF() { + Matrix matrix = mScaleMatrix; + RectF rect = new RectF(); + Drawable d = getDrawable(); + if (null != d) { + rect.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); + matrix.mapRect(rect); + } + return rect; + } + + @Override + public boolean onScaleBegin(ScaleGestureDetector detector) { + return true; + } + + @Override + public void onScaleEnd(ScaleGestureDetector detector) { + } + + @Override + public boolean onTouch(View v, MotionEvent event) { + + if (mGestureDetector.onTouchEvent(event)) + return true; + mScaleGestureDetector.onTouchEvent(event); + + float x = 0, y = 0; + // 拿到触摸点的个数 + final int pointerCount = event.getPointerCount(); + // 得到多个触摸点的x与y均值 + for (int i = 0; i < pointerCount; i++) { + x += event.getX(i); + y += event.getY(i); + } + x = x / pointerCount; + y = y / pointerCount; + + /** + * 每当触摸点发生变化时,重置mLasX , mLastY + */ + if (pointerCount != lastPointerCount) { + isCanDrag = false; + mLastX = x; + mLastY = y; + } + + lastPointerCount = pointerCount; + switch (event.getAction()) { + case MotionEvent.ACTION_MOVE: + float dx = x - mLastX; + float dy = y - mLastY; + + if (!isCanDrag) { + isCanDrag = isCanDrag(dx, dy); + } + if (isCanDrag) { + if (getDrawable() != null) { + + RectF rectF = getMatrixRectF(); + // 如果宽度小于屏幕宽度,则禁止左右移动 + if (rectF.width() <= getWidth() - mHorizontalPadding * 2) { + dx = 0; + } + // 如果高度小雨屏幕高度,则禁止上下移动 + if (rectF.height() <= getHeight() - mVerticalPadding * 2) { + dy = 0; + } + mScaleMatrix.postTranslate(dx, dy); + checkBorder(); + setImageMatrix(mScaleMatrix); + } + } + mLastX = x; + mLastY = y; + break; + + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + lastPointerCount = 0; + break; + } + + return true; + } + + /** + * 获得当前的缩放比例 + * + * @return + */ + public final float getScale() { + mScaleMatrix.getValues(matrixValues); + return matrixValues[Matrix.MSCALE_X]; + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + getViewTreeObserver().addOnGlobalLayoutListener(this); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + getViewTreeObserver().removeGlobalOnLayoutListener(this); + } + + /** + * 水平方向与View的边距 + */ + private int mHorizontalPadding;// ——屏幕边缘离截图区的宽度 + /** + * 垂直方向与View的边距 + */ + private int mVerticalPadding;// ——屏幕顶部离截图区的高度 + + @Override + public void onGlobalLayout() { + if (once) { + Drawable d = getDrawable(); + if (d == null) + return; + // 垂直方向的边距 + mVerticalPadding = (getHeight() - (getWidth() - 2 * mHorizontalPadding)) / 2; + + int width = getWidth(); + int height = getHeight(); + // 拿到图片的宽和高 + int dw = d.getIntrinsicWidth(); + int dh = d.getIntrinsicHeight(); + float scale = 1.0f; + if (dw <= getWidth() - mHorizontalPadding * 2 + && dh >= getHeight() - mVerticalPadding * 2) {// 如果图片的宽度<截图区宽度,并且图片高度>截图区高度时 + scale = (getWidth() * 1.0f - mHorizontalPadding * 2) / dw; + } + + if (dh <= getHeight() - mVerticalPadding * 2 + && dw >= getWidth() - mHorizontalPadding * 2) {// 如果图片的高度<截图区高度,并且图片宽度>截图区宽度时 + scale = (getHeight() * 1.0f - mVerticalPadding * 2) / dh; + } + + if (dw <= getWidth() - mHorizontalPadding * 2 + && dh <= getHeight() - mVerticalPadding * 2) {// 如果图片的高度<截图区高度,并且图片宽度<截图区宽度时 + float scaleW = (getWidth() * 1.0f - mHorizontalPadding * 2) + / dw; + float scaleH = (getHeight() * 1.0f - mVerticalPadding * 2) / dh; + scale = Math.max(scaleW, scaleH); + } + initScale = scale; + SCALE_MID = initScale * 2; + SCALE_MAX = initScale * 4; + mScaleMatrix.postTranslate((width - dw) / 2, (height - dh) / 2);// 平移至屏幕中心 + mScaleMatrix.postScale(scale, scale, getWidth() / 2, + getHeight() / 2);// 设置缩放比例 + // 图片移动至屏幕中心 + setImageMatrix(mScaleMatrix); + once = false; + } + + } + + /** + * 剪切图片,返回剪切后的bitmap对象 + * + * @return + */ + public Bitmap clip() { + Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), + Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + draw(canvas); + return Bitmap.createBitmap(bitmap, mHorizontalPadding, + mVerticalPadding, getWidth() - 2 * mHorizontalPadding, + getWidth() - 2 * mHorizontalPadding); + } + + /** + * 边界检测 + */ + private void checkBorder() { + + RectF rect = getMatrixRectF(); + float deltaX = 0; + float deltaY = 0; + + int width = getWidth(); + int height = getHeight(); + // 如果宽或高大于屏幕,则控制范围 ; 这里的0.001是因为精度丢失会产生问题,但是误差一般很小,所以我们直接加了一个0.01 + if (rect.width() + 0.01 >= width - 2 * mHorizontalPadding) { + if (rect.left > mHorizontalPadding) { + deltaX = -rect.left + mHorizontalPadding; + } + if (rect.right < width - mHorizontalPadding) { + deltaX = width - mHorizontalPadding - rect.right; + } + } + if (rect.height() + 0.01 >= height - 2 * mVerticalPadding) { + if (rect.top > mVerticalPadding) { + deltaY = -rect.top + mVerticalPadding; + } + if (rect.bottom < height - mVerticalPadding) { + deltaY = height - mVerticalPadding - rect.bottom; + } + } + mScaleMatrix.postTranslate(deltaX, deltaY); + + } + + /** + * 是否是拖动行为 + * + * @param dx + * @param dy + * @return + */ + private boolean isCanDrag(float dx, float dy) { + return Math.sqrt((dx * dx) + (dy * dy)) >= mTouchSlop; + } + + public void setHorizontalPadding(int mHorizontalPadding) { + this.mHorizontalPadding = mHorizontalPadding; + } + +} diff --git a/app/src/main/java/com/gh/common/view/CustomDurationScroller.java b/app/src/main/java/com/gh/common/view/CustomDurationScroller.java new file mode 100644 index 0000000000..c3997b331c --- /dev/null +++ b/app/src/main/java/com/gh/common/view/CustomDurationScroller.java @@ -0,0 +1,49 @@ +package com.gh.common.view; + +import android.content.Context; +import android.view.animation.Interpolator; +import android.widget.Scroller; + +/** + * CustomDurationScroller + * + * @author Trinea 2014-3-2 + */ +public class CustomDurationScroller extends Scroller { + + private double scrollFactor = 1; + + public CustomDurationScroller(Context context) { + super(context); + } + + public CustomDurationScroller(Context context, Interpolator interpolator) { + super(context, interpolator); + } + + /** + * not exist in android 2.3 + * + * @param context + * @param interpolator + * @param flywheel + */ + // @SuppressLint("NewApi") + // public CustomDurationScroller(Context context, Interpolator interpolator, + // boolean flywheel){ + // super(context, interpolator, flywheel); + // } + + /** + * Set the factor by which the duration will change + */ + public void setScrollDurationFactor(double scrollFactor) { + this.scrollFactor = scrollFactor; + } + + @Override + public void startScroll(int startX, int startY, int dx, int dy, int duration) { + super.startScroll(startX, startY, dx, dy, + (int) (duration * scrollFactor)); + } +} diff --git a/app/src/main/java/com/gh/common/view/DownloadDialog.java b/app/src/main/java/com/gh/common/view/DownloadDialog.java new file mode 100644 index 0000000000..9b5af37cd6 --- /dev/null +++ b/app/src/main/java/com/gh/common/view/DownloadDialog.java @@ -0,0 +1,1287 @@ +package com.gh.common.view; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import android.app.Dialog; +import android.content.Context; +import android.content.SharedPreferences; +import android.graphics.Color; +import android.graphics.drawable.ClipDrawable; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.graphics.drawable.LayerDrawable; +import android.os.Handler; +import android.os.Message; +import android.support.v4.util.ArrayMap; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewPager; +import android.support.v4.view.ViewPager.OnPageChangeListener; +import android.support.v7.widget.DefaultItemAnimator; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.Html; +import android.text.Spanned; +import android.text.TextUtils; +import android.util.SparseArray; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.PopupWindow; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.Toast; + +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.common.util.DialogUtils; +import com.gh.common.util.DisplayUtils; +import com.gh.common.util.FileUtils; +import com.gh.common.util.ImageUtils; +import com.gh.common.util.MD5Utils; +import com.gh.common.util.NetworkUtils; +import com.gh.common.util.PackageUtils; +import com.gh.common.util.PlatformUtils; +import com.gh.common.util.SpeedUtils; +import com.gh.common.util.Utils; +import com.gh.download.DataWatcher; +import com.gh.download.DownloadEntry; +import com.gh.download.DownloadManager; +import com.gh.download.DownloadStatus; +import com.gh.gamecenter.MainActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.entity.ApkEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.entity.GameUpdateEntity; +import com.gh.gamecenter.eventbus.EBPWDismiss; +import com.gh.gamecenter.eventbus.EBPackage; +import com.gh.gamecenter.eventbus.EBPlatformChanged; +import com.gh.gamecenter.eventbus.EBPutUrl; +import com.gh.gamecenter.eventbus.EBRedDot; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.manager.PackageManager; +import com.tendcloud.tenddata.TCAgent; + +import de.greenrobot.event.EventBus; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-8-12 + * @update 2015-8-12 + * @des 弹出游戏版本下载按钮,点击并添加到下载任务中 + */ +public class DownloadDialog { + private static DownloadDialog instance; + private Context context; + + private DownloadDialog() { + + } + + public static DownloadDialog getInstance(Context context) { + if (instance == null) { + instance = new DownloadDialog(); + } + instance.context = context; + return instance; + } + + private DataWatcher dataWatcher = new DataWatcher() { + @Override + public void onDataChanged( + HashMap downloadingEntries) { + for (Map.Entry entry : downloadingEntries + .entrySet()) { + if (entry.getValue().getName().equals(gameName)) { + entryMap.put(entry.getValue().getUrl(), entry.getValue()); + Integer location = locationMap.get(entry.getValue() + .getUrl()); + if (location != null) { + if (!"pause".equals(statusMap.get(entry.getValue() + .getUrl()))) { + int index = location.intValue(); + + int position = (int) Math.ceil((index + 1) + / (double) (row * column)); + + if (position - 1 < adapterMap.size()) { + adapterMap.get(position - 1).notifyItemChanged( + index % (row * column)); + } + } + } + } + } + } + }; + + private PopupWindow popupWindow; + + private ArrayMap locationMap; + private ArrayMap entryMap; + private SparseArray adapterMap; + private ArrayMap urlMap; + + private List gameApk; + private String gameName; + private String gameIcon; + private String gameId; + private String gameType; + private String entrance; + private String mlocation; + private ArrayMap lastTimeMap; + private ArrayMap statusMap; + private TextView download_speed; + private TextView download_percentage; + private LinearLayout linearLayout; + private ViewPager viewPager; + + private int row; + private int column; + + private Handler handler; + + public void showPopupWindow(View view, GameEntity game, String entrance, + String location) { + ArrayMap mLastTimeMap = new ArrayMap(); + ArrayMap mStatusMap = new ArrayMap(); + Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (msg.what == Constants.CONTINUE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + DownloadManager.getInstance(context).resume(url); + } + } else if (msg.what == Constants.PAUSE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + DownloadManager.getInstance(context).pause(url); + } + } + } + }; + showPopupWindow(view, game, entrance, mHandler, mLastTimeMap, + mStatusMap, location); + } + + public void showPopupWindow(View view, GameEntity game, String entrance, + Handler hdler, ArrayMap ltMap, + ArrayMap sMap, String location) { + showPopupWindow(view, game, entrance, hdler, ltMap, sMap, null, null, + location); + } + + public void showPopupWindow(View view, GameEntity game, String eStr, + Handler hdler, ArrayMap ltMap, + ArrayMap sMap, TextView dSpeed, + TextView dPercentage, String lstr) { + + SharedPreferences sp = context.getSharedPreferences(Config.PREFERENCE, + Context.MODE_PRIVATE); + row = sp.getInt("download_box_row", 3); + column = sp.getInt("download_box_column", 3); + + mlocation = lstr; + entrance = eStr; + handler = hdler; + lastTimeMap = ltMap; + statusMap = sMap; + download_speed = dSpeed; + download_percentage = dPercentage; + + gameName = game.getName(); + gameIcon = game.getIcon(); + gameId = game.getIcon(); + if (game.getTag() == null || game.getTag().isEmpty()) { + gameType = "normal"; + } else { + gameType = "plugin"; + } + + entryMap = new ArrayMap(); + List entries = DownloadManager.getInstance(context) + .getAll(); + for (int i = 0, size = entries.size(); i < size; i++) { + if (entries.get(i).getName().equals(gameName)) { + entryMap.put(entries.get(i).getUrl(), entries.get(i)); + } + } + + game.setApk(sortApk(game.getId(), + new ArrayList(game.getApk()))); + gameApk = game.getApk(); + + // 一个自定义的布局,作为显示的内容 + View contentView = View.inflate(context, R.layout.game_download_dialog, + null); + + TextView textView = (TextView) contentView + .findViewById(R.id.dialog_title); + textView.setText(gameName); + + linearLayout = (LinearLayout) contentView + .findViewById(R.id.dialog_ll_hint); + viewPager = (ViewPager) contentView.findViewById(R.id.dialog_viewPager); + + init(new ArrayList(gameApk)); + + viewPager.addOnPageChangeListener(new OnPageChangeListener() { + @Override + public void onPageSelected(int position) { + for (int i = 0, size = linearLayout.getChildCount(); i < size; i++) { + if (i == position % size) { + ((ImageView) linearLayout.getChildAt(i)) + .setImageResource(R.drawable.oval_hint_up); + } else { + ((ImageView) linearLayout.getChildAt(i)) + .setImageResource(R.drawable.oval_hint_gray_bg); + } + } + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + + @Override + public void onPageScrolled(int position, float positionOffset, + int positionOffsetPixels) { + + } + }); + + contentView.findViewById(R.id.dialog_ll_bottom).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + + } + }); + + popupWindow = new PopupWindow(contentView, LayoutParams.MATCH_PARENT, + LayoutParams.MATCH_PARENT, true); + + contentView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + popupWindow.dismiss(); + } + }); + contentView.setFocusable(true); + contentView.setFocusableInTouchMode(true); + contentView.setOnKeyListener(new View.OnKeyListener() { + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + + if (keyCode == KeyEvent.KEYCODE_BACK + && event.getRepeatCount() == 0 && popupWindow != null + && popupWindow.isShowing()) { + popupWindow.dismiss(); + } + return false; + } + }); + + popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() { + @Override + public void onDismiss() { + EventBus.getDefault().post(new EBPWDismiss()); + EventBus.getDefault().unregister(DownloadDialog.this); + DownloadManager.getInstance(context) + .removeObserver(dataWatcher); + } + }); + + popupWindow.setTouchable(true); + popupWindow.setFocusable(true); + // ColorDrawable dw = new ColorDrawable(0x88888888); + // popupWindow.setBackgroundDrawable(dw); + + // 设置popWindow的显示和消失动画 + popupWindow.setAnimationStyle(R.style.mypopwindow_anim_style); + + // 设置好参数之后再show + popupWindow.showAtLocation(view, Gravity.BOTTOM, 0, 0); + + if (!EventBus.getDefault().isRegistered(DownloadDialog.this)) { + EventBus.getDefault().register(DownloadDialog.this); + } + + DownloadManager.getInstance(context).addObserver(dataWatcher); + } + + private void init(List apkList) { + for (int i = 0; i < apkList.size(); i++) { + String platformName = PlatformUtils.getInstance(context) + .getPlatformName(apkList.get(i).getPlatform()); + if (platformName == null) { + apkList.remove(i); + i--; + } + } + + locationMap = new ArrayMap(); + adapterMap = new SparseArray(); + urlMap = new ArrayMap(); + + for (int i = 0, size = apkList.size(); i < size; i++) { + locationMap.put(apkList.get(i).getUrl(), i); + urlMap.put(apkList.get(i).getPackageName(), apkList.get(i).getUrl()); + } + + linearLayout.removeAllViews(); + int size = (int) Math.ceil(apkList.size() / (double) (row * column)); + if (size > 1) { + for (int i = 0; i < size; i++) { + ImageView imageView = new ImageView(context); + LayoutParams lparams = new LayoutParams( + DisplayUtils.dip2px(context, 5), DisplayUtils.dip2px( + context, 5)); + if (i == 0) { + lparams.leftMargin = 0; + imageView.setImageResource(R.drawable.oval_hint_up); + } else { + lparams.leftMargin = DisplayUtils.dip2px(context, 8); + imageView.setImageResource(R.drawable.oval_hint_gray_bg); + } + imageView.setLayoutParams(lparams); + linearLayout.addView(imageView); + } + } + + viewPager.setAdapter(new PlatformAdapter(apkList)); + } + + private ArrayList sortApk(String gameId, List apkList) { + DownloadEntry downloadEntry = null; + ArrayList list = new ArrayList(); + List installedList = new ArrayList(); + List doneList = new ArrayList(); + List downloadList = new ArrayList(); + List platformList = new ArrayList(); + List noPicList = new ArrayList(); + + // 获取版本排序 + Set value = null; + SharedPreferences sp = context.getSharedPreferences(Config.PREFERENCE, + Context.MODE_PRIVATE); + Map map = sp.getAll(); + Iterator iterator = map.keySet().iterator(); + while (iterator.hasNext()) { + String key = (String) iterator.next(); + if (key.startsWith("platform_order_special_") + && gameId.equals(key.substring(key.lastIndexOf("_") + 1))) { + value = (Set) map.get(key); + break; + } + } + if (value == null) { + value = sp.getStringSet("platform_order_normal", null); + } + SparseArray sparseArray = new SparseArray(); + Iterator keys = value.iterator(); + String s; + while (keys.hasNext()) { + s = keys.next(); + int index = Integer.valueOf(s.substring(0, s.indexOf("="))); + sparseArray.put(index, s.substring(s.indexOf("=") + 1)); + } + List platforms = new ArrayList(); + for (int i = 0; i < sparseArray.size(); i++) { + platforms.add(sparseArray.get(i)); + } + + for (int i = 0, sizei = platforms.size(); i < sizei; i++) { + for (int j = 0, sizej = apkList.size(); j < sizej; j++) { + String platform = apkList.get(j).getPlatform(); + String packageName = apkList.get(j).getPackageName(); + downloadEntry = entryMap.get(apkList.get(j).getUrl()); + if (platforms.get(i).equals(platform)) { + int id = PlatformUtils.getInstance(context).getPlatformPic( + platform); + if (id == 0) { + String path = PlatformUtils.getInstance(context) + .getPlatformPicPath(platform); + if (path == null) { + continue; + } + } + if (PackageManager.isInstalled(packageName)) { + installedList.add(apkList.remove(j)); + } else if (downloadEntry != null) { + if (downloadEntry.getStatus().equals( + DownloadStatus.done)) { + doneList.add(apkList.remove(j)); + } else { + downloadList.add(apkList.remove(j)); + } + } else { + platformList.add(apkList.remove(j)); + } + sizej--; + break; + } + } + } + for (int i = 0, size = apkList.size(); i < size; i++) { + String packageName = apkList.get(i).getPackageName(); + if (PackageManager.isInstalled(packageName)) { + installedList.add(apkList.remove(i)); + size--; + i--; + } else { + downloadEntry = entryMap.get(apkList.get(i).getUrl()); + if (downloadEntry != null) { + if (downloadEntry.getStatus().equals(DownloadStatus.done)) { + doneList.add(apkList.remove(i)); + } else { + downloadList.add(apkList.remove(i)); + } + size--; + i--; + } else { + String platform = apkList.get(i).getPlatform(); + int id = PlatformUtils.getInstance(context).getPlatformPic( + platform); + if (id == 0) { + String path = PlatformUtils.getInstance(context) + .getPlatformPicPath(platform); + if (path == null) { + noPicList.add(apkList.remove(i)); + size--; + i--; + } + } + } + } + } + list.addAll(installedList); + list.addAll(doneList); + list.addAll(downloadList); + list.addAll(platformList); + list.addAll(apkList); + list.addAll(noPicList); + return list; + } + + // 接受安装成功的消息,更新界面 + public void onEvent(EBPackage busFour) { + String url = urlMap.get(busFour.getPackageName()); + if (url != null) { + Integer location = locationMap.get(url); + int index = location.intValue(); + if ("安装".equals(busFour.getType())) { + entryMap.remove(url); + int position = (int) Math.ceil((index + 1) + / (double) (row * column)); + adapterMap.get(position - 1).notifyItemChanged( + index % (row * column)); + } else if ("卸载".equals(busFour.getType())) { + int position = (int) Math.ceil((index + 1) + / (double) (row * column)); + adapterMap.get(position - 1).notifyItemChanged( + index % (row * column)); + } + } + } + + // 接收platform数据改变消息,更新界面 + public void onEvent(EBPlatformChanged platformChanged) { + DownloadManager.getInstance(context).removeObserver(dataWatcher); + init(new ArrayList(gameApk)); + DownloadManager.getInstance(context).addObserver(dataWatcher); + } + + private class PlatformAdapter extends PagerAdapter { + + private List platforms; + + public PlatformAdapter(List list) { + platforms = list; + } + + @Override + public int getCount() { + + return (int) Math.ceil(platforms.size() / (double) (row * column)); + } + + @Override + public Object instantiateItem(ViewGroup container, int position) { + + RecyclerView recyclerView = new RecyclerView(context); + + int padding = DisplayUtils.dip2px(context, 10); + + recyclerView.setPadding(padding, padding, padding, padding); + + ViewGroup.LayoutParams params = new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + recyclerView.setLayoutParams(params); + + recyclerView.setHasFixedSize(true); + GridLayoutManager gridLayoutManager = new GridLayoutManager( + context, column); + recyclerView.setLayoutManager(gridLayoutManager); + recyclerView.setItemAnimator(new DefaultItemAnimator()); + recyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER); + + RecyclerViewAdapter adapter = new RecyclerViewAdapter(platforms, + position); + + adapterMap.put(position, adapter); + + recyclerView.setAdapter(adapter); + + container.addView(recyclerView); + return recyclerView; + } + + @Override + public boolean isViewFromObject(View view, Object object) { + + return view == object; + } + + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + + container.removeView((View) object); + object = null; + } + + } + + private class RecyclerViewHolder extends RecyclerView.ViewHolder { + + private View view; + private TextView download_item_tv_name, download_item_tv_status, + download_item_tv_hint; + private ProgressBar download_item_progressbar; + private ImageView download_item_iv_pic; + + public RecyclerViewHolder(View convertView) { + super(convertView); + view = convertView; + download_item_tv_name = (TextView) convertView + .findViewById(R.id.download_item_tv_name); + download_item_tv_status = (TextView) convertView + .findViewById(R.id.download_item_tv_status); + download_item_progressbar = (ProgressBar) convertView + .findViewById(R.id.download_item_progressbar); + download_item_iv_pic = (ImageView) convertView + .findViewById(R.id.download_item_iv_pic); + download_item_tv_hint = (TextView) convertView + .findViewById(R.id.download_item_tv_hint); + } + } + + // 显示插件化 + private void showPluginDialog(final ApkEntity apkEntity, + final RecyclerViewAdapter adapter, final int location) { + final Dialog dialog = new Dialog(context); + View view = View.inflate(context, + R.layout.search_history_delete_dialog, null); + TextView title = (TextView) view.findViewById(R.id.delete_dialog_title); + title.setText("插件化安装"); + TextView content = (TextView) view + .findViewById(R.id.delete_dialog_message); + Spanned spanned = Html.fromHtml("您将进行插件化安装以实现插件功能,此过程将" + + "卸载" + "当前使用的版本并" + + "安装插件版本" + "。"); + content.setText(spanned); + + TextView cancel = (TextView) view + .findViewById(R.id.delete_dialog_cancel); + cancel.setText("取消"); + cancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + TextView confirm = (TextView) view + .findViewById(R.id.delete_dialog_confirm); + confirm.setText("确定"); + confirm.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + + Map kv6 = new HashMap(); + kv6.put("操作", "点击插件化安装完成"); + TCAgent.onEvent(context, "插件化", gameName, kv6); + + String path = entryMap.get(apkEntity.getUrl()).getPath(); + if (FileUtils.isEmptyFile(path)) { + Toast.makeText(context, "解析包错误", Toast.LENGTH_SHORT).show(); + entryMap.remove(apkEntity.getUrl()); + DownloadManager.getInstance(context).cancel( + apkEntity.getUrl()); + adapter.notifyItemChanged(location); + } else { + PackageManager manager = new PackageManager(context); + if (manager.launchSetup(path)) { + context.startActivity(PackageUtils + .getInstallIntent(path)); + } else { + MainActivity.uninstallMap.put(PackageUtils + .getPackageNameByPath(context, path), path); + context.startActivity(PackageUtils.getUninstallIntent( + context, path)); + } + } + } + }); + + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.show(); + } + + private class RecyclerViewAdapter extends + RecyclerView.Adapter { + + private List platforms; + private int position; + private int count; + + public RecyclerViewAdapter(List list, int p) { + platforms = list; + position = p; + if (platforms.size() <= (row * column)) { + count = platforms.size(); + } else if (platforms.size() - (row * column) * position >= (row * column)) { + count = (row * column); + } else { + count = platforms.size() - (row * column) * position; + } + } + + @Override + public int getItemCount() { + return count; + } + + @SuppressWarnings("deprecation") + @Override + public void onBindViewHolder(final RecyclerViewHolder viewHolder, + final int location) { + + final ApkEntity apkEntity = platforms.get((row * column) * position + + location); + + viewHolder.view.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (viewHolder.download_item_tv_status.getVisibility() == View.GONE) { + String msg = FileUtils.isCanDownload(apkEntity + .getSize()); + if (TextUtils.isEmpty(msg)) { + Map kv = new HashMap(); + kv.put("版本", apkEntity.getPlatform()); + kv.put("状态", "下载开始"); + TCAgent.onEvent(context, "游戏下载", gameName, kv); + + Map kv2 = new HashMap(); + kv2.put("版本", apkEntity.getPlatform()); + kv2.put("状态", "下载开始"); + kv2.put("位置", entrance + "-开始"); + TCAgent.onEvent(context, "游戏下载位置", gameName, kv2); + + Map kv3 = new HashMap(); + kv3.put(entrance, "下载数"); + kv3.put(entrance, "下载开始"); + TCAgent.onEvent(context, "应用数据", gameName, kv3); + + if ("主页-最新插件".equals(entrance)) { + Map kv4 = new HashMap(); + kv4.put(gameName, "下载数"); + TCAgent.onEvent(context, "主页数据", "最新插件", kv4); + } else if ("主页-热门卡牌".equals(entrance)) { + Map kv4 = new HashMap(); + kv4.put(gameName, "下载数"); + TCAgent.onEvent(context, "主页数据", "热门卡牌", kv4); + } else if ("主页-新测卡牌".equals(entrance)) { + Map kv4 = new HashMap(); + kv4.put(gameName, "下载数"); + TCAgent.onEvent(context, "主页数据", "新测卡牌", kv4); + } + + if (entrance.contains("游戏详情")) { + Map kv5 = new HashMap(); + kv5.put("下载", "下载量"); + kv5.put("下载", apkEntity.getPlatform()); + TCAgent.onEvent(context, "插件数据", gameName, kv5); + } + + Map map = new HashMap(); + map.put("game", gameName); + map.put("method", "正常"); + map.put("platform", + PlatformUtils.getInstance(context) + .getPlatformName( + apkEntity.getPlatform())); + map.put("status", "开始"); + map.put("location", mlocation); + map.put("from", entrance); + map.put("network", + NetworkUtils.getConnectedType(context)); + map.put("createdOn", + System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent(context, "download", + map); + + DownloadEntry entry = new DownloadEntry(); + + entry.setUrl(apkEntity.getUrl()); + entry.setName(gameName); + entry.setPath(FileUtils.getDownloadPath( + context, + MD5Utils.getContentMD5(gameName + "_" + + System.currentTimeMillis()) + + ".apk")); + HashMap meta = new HashMap(); + meta.put("ETag", apkEntity.getEtag()); + meta.put("icon", gameIcon); + meta.put("platform", apkEntity.getPlatform()); + meta.put("gameId", gameId); + meta.put("entrance", entrance); + meta.put("location", mlocation); + entry.setMeta(meta); + + DownloadManager.getInstance(context).add(entry); + + viewHolder.download_item_tv_status.setText("0.0%"); + + EventBus.getDefault().post(new EBRedDot(1)); + + statusMap.put(entry.getUrl(), "downloading"); + + } else { + Toast.makeText(context, msg, Toast.LENGTH_SHORT) + .show(); + } + } else { + String status = viewHolder.download_item_tv_status + .getText().toString(); + Utils.log("status = " + status); + if ("继续".equals(status)) { + statusMap.put(apkEntity.getUrl(), "downloading"); + if (PackageManager.isInstalled(apkEntity + .getPackageName())) { + PackageManager mPackageManager = new PackageManager( + context); + if (!mPackageManager.isSignature(apkEntity + .getPackageName())) { + viewHolder.download_item_tv_status + .setText("插件下载中"); + } else { + viewHolder.download_item_tv_status + .setText("更新中"); + } + } else { + viewHolder.download_item_tv_status + .setText(entryMap.get( + apkEntity.getUrl()) + .getPercent() + + "%"); + } + if (download_speed != null) { + String platform = PlatformUtils.getInstance( + context).getPlatformName( + apkEntity.getPlatform()); + DownloadEntry downloadEntry = entryMap + .get(apkEntity.getUrl()); + if (platform == null) { + download_speed.setText(SpeedUtils + .getSpeed(downloadEntry.getSpeed()) + + "(剩" + + SpeedUtils.getRemainTime( + downloadEntry.getSize(), + downloadEntry.getProgress(), + downloadEntry.getSpeed() * 1024) + + ")"); + } else { + download_speed.setText(platform + + " - " + + SpeedUtils.getSpeed(downloadEntry + .getSpeed()) + + "(剩" + + SpeedUtils.getRemainTime( + downloadEntry.getSize(), + downloadEntry.getProgress(), + downloadEntry.getSpeed() * 1024) + + ")"); + } + } + if (download_percentage != null) { + download_percentage.setText(entryMap.get( + apkEntity.getUrl()).getPercent() + + "%"); + } + Message msg = Message.obtain(); + msg.what = Constants.CONTINUE_DOWNLOAD_TASK; + msg.obj = apkEntity.getUrl(); + lastTimeMap.put(apkEntity.getUrl(), + System.currentTimeMillis()); + handler.sendMessageDelayed(msg, 1000); + EventBus.getDefault().post(new EBRedDot(0)); + } else if ("启动".equals(status)) { + Map kv = new HashMap(); + kv.put("版本", apkEntity.getPlatform()); + TCAgent.onEvent(context, "游戏启动", gameName, kv); + + PackageUtils.launchApplicationByPackageName( + context, apkEntity.getPackageName()); + } else if ("插件化".equals(status)) { + // 下载插件版游戏 + String msg = FileUtils.isCanDownload(apkEntity + .getSize()); + if (TextUtils.isEmpty(msg)) { + Map kv = new HashMap(); + kv.put("版本", apkEntity.getPlatform()); + kv.put("状态", "下载开始"); + TCAgent.onEvent(context, "游戏下载", gameName, kv); + + Map kv2 = new HashMap(); + kv2.put("版本", apkEntity.getPlatform()); + kv2.put("状态", "下载开始"); + kv2.put("位置", entrance + "-开始"); + TCAgent.onEvent(context, "游戏下载位置", gameName, + kv2); + + Map kv3 = new HashMap(); + kv3.put(entrance, "下载数"); + kv3.put(entrance, "下载开始"); + TCAgent.onEvent(context, "应用数据", gameName, kv3); + + if ("主页-最新插件".equals(entrance)) { + Map kv4 = new HashMap(); + kv4.put(gameName, "下载数"); + TCAgent.onEvent(context, "主页数据", "最新插件", + kv4); + } else if ("主页-热门卡牌".equals(entrance)) { + Map kv4 = new HashMap(); + kv4.put(gameName, "下载数"); + TCAgent.onEvent(context, "主页数据", "热门卡牌", + kv4); + } else if ("主页-新测卡牌".equals(entrance)) { + Map kv4 = new HashMap(); + kv4.put(gameName, "下载数"); + TCAgent.onEvent(context, "主页数据", "新测卡牌", + kv4); + } + + if (entrance.contains("游戏详情")) { + Map kv5 = new HashMap(); + kv5.put("下载", "下载开始"); + kv5.put("下载", apkEntity.getPlatform()); + TCAgent.onEvent(context, "插件数据", gameName, + kv5); + } + + Map kv6 = new HashMap(); + kv6.put("下载", "下载开始"); + kv6.put("版本", apkEntity.getPlatform()); + TCAgent.onEvent(context, "插件化", gameName, kv6); + + Map map = new HashMap(); + map.put("game", gameName); + map.put("method", "插件化"); + map.put("platform", + PlatformUtils + .getInstance(context) + .getPlatformName( + apkEntity.getPlatform())); + map.put("status", "开始"); + map.put("location", mlocation); + map.put("from", entrance); + map.put("network", + NetworkUtils.getConnectedType(context)); + map.put("createdOn", + System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent(context, + "download", map); + + DownloadEntry entry = new DownloadEntry(); + + entry.setUrl(apkEntity.getUrl()); + entry.setName(gameName); + entry.setPath(FileUtils.getDownloadPath( + context, + MD5Utils.getContentMD5(gameName + "_" + + System.currentTimeMillis()) + + ".apk")); + HashMap meta = new HashMap(); + meta.put("ETag", apkEntity.getEtag()); + meta.put("icon", gameIcon); + meta.put( + "platform", apkEntity.getPlatform()); + meta.put("gameId", gameId); + meta.put("entrance", entrance); + meta.put("location", mlocation); + meta.put("isPlugin", "true"); + meta.put("package_name", + apkEntity.getPackageName()); + meta.put("size", apkEntity.getSize()); + meta.put("version", apkEntity.getVersion()); + meta.put("gh_version", apkEntity.getGhVersion()); + entry.setMeta(meta); + + DownloadManager.getInstance(context).add(entry); + + EventBus.getDefault().post(new EBRedDot(1)); + + statusMap.put(entry.getUrl(), "downloading"); + + GameUpdateEntity game = new GameUpdateEntity( + gameId, gameName, gameIcon, apkEntity + .getPackageName(), apkEntity + .getSize(), apkEntity + .getVersion(), apkEntity + .getGhVersion(), apkEntity + .getUrl(), apkEntity + .getPlatform(), true); + PackageManager.addUpdate(game); + + } else { + Toast.makeText(context, msg, Toast.LENGTH_SHORT) + .show(); + } + } else if ("插件化安装".equals(status)) { + showPluginDialog(apkEntity, + RecyclerViewAdapter.this, location); + } else if ("安装".equals(status) || "安装更新".equals(status)) { + DownloadEntry downloadEntry = DownloadManager + .getInstance(context).get( + apkEntity.getUrl()); + if (downloadEntry != null + && downloadEntry.getMeta().get("isPlugin") != null) { + Map kv6 = new HashMap(); + kv6.put("操作", "点击安装完成"); + TCAgent.onEvent(context, "插件化", + downloadEntry.getName(), kv6); + } + String path = entryMap.get(apkEntity.getUrl()) + .getPath(); + if (FileUtils.isEmptyFile(path)) { + Toast.makeText(context, "解析包错误", + Toast.LENGTH_SHORT).show(); + entryMap.remove(apkEntity.getUrl()); + DownloadManager.getInstance(context).cancel( + apkEntity.getUrl()); + notifyItemChanged(location); + } else { + PackageManager manager = new PackageManager( + context); + if (manager.launchSetup(path)) { + context.startActivity(PackageUtils + .getInstallIntent(path)); + } else { + DialogUtils.showDialog(context, path); + } + } + } else if ("等待".equals(status)) { + Toast.makeText(context, "最多同时有3个下载任务", + Toast.LENGTH_SHORT).show(); + } else { + viewHolder.download_item_tv_status.setText("继续"); + statusMap.put(apkEntity.getUrl(), "pause"); + if (download_speed != null) { + String platform = PlatformUtils.getInstance( + context).getPlatformName( + apkEntity.getPlatform()); + if (platform == null) { + download_speed.setText("暂停"); + } else { + download_speed.setText(platform + " - 暂停"); + } + } + if (download_percentage != null) { + download_percentage.setText(entryMap.get( + apkEntity.getUrl()).getPercent() + + "%"); + } + Message msg = Message.obtain(); + msg.what = Constants.PAUSE_DOWNLOAD_TASK; + msg.obj = apkEntity.getUrl(); + lastTimeMap.put(apkEntity.getUrl(), + System.currentTimeMillis()); + handler.sendMessageDelayed(msg, 1000); + } + } + } + }); + + if (PackageManager.isInstalled(apkEntity.getPackageName())) { + viewHolder.download_item_iv_pic.setVisibility(View.GONE); + viewHolder.download_item_tv_hint.setVisibility(View.GONE); + viewHolder.download_item_progressbar + .setVisibility(View.VISIBLE); + viewHolder.download_item_tv_name.setVisibility(View.VISIBLE); + viewHolder.download_item_tv_status.setVisibility(View.VISIBLE); + int color = Color.parseColor(PlatformUtils.getInstance(context) + .getPlatformColor(apkEntity.getPlatform())); + GradientDrawable gradientDrawable = new GradientDrawable(); + gradientDrawable.setColor(0xffffffff); + gradientDrawable.setStroke(DisplayUtils.dip2px(context, 1), + color); + viewHolder.view.setBackgroundDrawable(gradientDrawable); + viewHolder.download_item_tv_name.setTextColor(color); + viewHolder.download_item_tv_name.setText(PlatformUtils + .getInstance(context).getPlatformName( + apkEntity.getPlatform())); + Drawable[] layers = new Drawable[2]; + GradientDrawable drawable = new GradientDrawable(); + drawable.setColor(0xFFDCDCDC); + layers[0] = drawable; + ClipDrawable clipDrawable = new ClipDrawable(new ColorDrawable( + color), Gravity.LEFT, ClipDrawable.HORIZONTAL); + layers[1] = clipDrawable; + LayerDrawable layerDrawable = new LayerDrawable(layers); + layerDrawable.setId(0, android.R.id.background); + layerDrawable.setId(1, android.R.id.progress); + viewHolder.download_item_progressbar + .setProgressDrawable(layerDrawable); + DownloadEntry downloadEntry = DownloadManager.getInstance( + context).get(apkEntity.getUrl()); + PackageManager mPackageManager = new PackageManager(context); + if (downloadEntry == null) { + viewHolder.download_item_progressbar.setProgress(1000); + viewHolder.download_item_tv_status.setText("启动"); + if (!"normal".equals(gameType) + && !mPackageManager.isSignature(apkEntity + .getPackageName())) { + viewHolder.download_item_tv_status.setText("插件化"); + } + } else { + viewHolder.download_item_progressbar + .setProgress((int) (downloadEntry.getPercent() * 10)); + if (downloadEntry.getMeta().get("isPlugin") != null) { + if (downloadEntry.getStatus().equals( + DownloadStatus.done)) { + viewHolder.download_item_tv_status.setText("插件化安装"); + } else if (downloadEntry.getStatus().equals( + DownloadStatus.pause) + || "pause".equals(statusMap.get(downloadEntry + .getUrl()))) { + viewHolder.download_item_tv_status.setText("继续"); + } else { + viewHolder.download_item_tv_status.setText("插件下载中"); + } + } else if (downloadEntry.getMeta().get("isUpdate") != null) { + if (downloadEntry.getStatus().equals( + DownloadStatus.done)) { + viewHolder.download_item_tv_status.setText("安装更新"); + } else if (downloadEntry.getStatus().equals( + DownloadStatus.pause)) { + viewHolder.download_item_tv_status.setText("继续"); + } else { + viewHolder.download_item_tv_status.setText("更新中"); + } + } + } + } else { + DownloadEntry downloadEntry = entryMap.get(apkEntity.getUrl()); + if (downloadEntry != null) { + viewHolder.download_item_iv_pic.setVisibility(View.GONE); + viewHolder.download_item_tv_hint.setVisibility(View.GONE); + viewHolder.download_item_progressbar + .setVisibility(View.VISIBLE); + viewHolder.download_item_tv_name + .setVisibility(View.VISIBLE); + viewHolder.download_item_tv_status + .setVisibility(View.VISIBLE); + int color = Color.parseColor(PlatformUtils.getInstance( + context).getPlatformColor(apkEntity.getPlatform())); + GradientDrawable gradientDrawable = new GradientDrawable(); + gradientDrawable.setColor(0xffffffff); + gradientDrawable.setStroke(DisplayUtils.dip2px(context, 1), + color); + viewHolder.view.setBackgroundDrawable(gradientDrawable); + viewHolder.download_item_tv_name.setTextColor(color); + viewHolder.download_item_tv_name.setText(PlatformUtils + .getInstance(context).getPlatformName( + apkEntity.getPlatform())); + Drawable[] layers = new Drawable[2]; + GradientDrawable drawable = new GradientDrawable(); + drawable.setColor(0xFFDCDCDC); + layers[0] = drawable; + ClipDrawable clipDrawable = new ClipDrawable( + new ColorDrawable(color), Gravity.LEFT, + ClipDrawable.HORIZONTAL); + layers[1] = clipDrawable; + LayerDrawable layerDrawable = new LayerDrawable(layers); + layerDrawable.setId(0, android.R.id.background); + layerDrawable.setId(1, android.R.id.progress); + viewHolder.download_item_progressbar + .setProgressDrawable(layerDrawable); + viewHolder.download_item_progressbar + .setProgress((int) (downloadEntry.getPercent() * 10)); + Utils.log("download status = " + downloadEntry.getStatus()); + switch (downloadEntry.getStatus()) { + case pause: + case neterror: + viewHolder.download_item_tv_status.setText("继续"); + break; + case downloading: + if (!"pause".equals(statusMap.get(downloadEntry + .getUrl()))) { + viewHolder.download_item_tv_status + .setText(downloadEntry.getPercent() + "%"); + } + break; + case done: + EventBus.getDefault().post( + new EBPutUrl(PackageUtils.getPackageNameByPath( + context, downloadEntry.getPath()), + downloadEntry.getUrl())); + viewHolder.download_item_tv_status.setText("安装"); + break; + case waiting: + viewHolder.download_item_tv_status.setText("等待"); + break; + case cancel: + case hijack: + int id = PlatformUtils.getInstance(context).getPlatformPic( + apkEntity.getPlatform()); + if (id != 0) { + viewHolder.download_item_iv_pic + .setVisibility(View.VISIBLE); + viewHolder.download_item_iv_pic.setImageResource(id); + viewHolder.download_item_tv_hint + .setVisibility(View.GONE); + viewHolder.download_item_progressbar + .setVisibility(View.GONE); + viewHolder.download_item_tv_name + .setVisibility(View.GONE); + viewHolder.download_item_tv_status + .setVisibility(View.GONE); + viewHolder.view.setBackgroundColor(0xffffff); + } else { + String path = PlatformUtils.getInstance(context) + .getPlatformPicPath(apkEntity.getPlatform()); + if (path != null) { + viewHolder.download_item_iv_pic + .setVisibility(View.VISIBLE); + ImageUtils.getInstance(context).display( + "file://" + path, + viewHolder.download_item_iv_pic); + viewHolder.download_item_tv_hint + .setVisibility(View.GONE); + viewHolder.download_item_progressbar + .setVisibility(View.GONE); + viewHolder.download_item_tv_name + .setVisibility(View.GONE); + viewHolder.download_item_tv_status + .setVisibility(View.GONE); + viewHolder.view.setBackgroundColor(0xffffff); + } else { + viewHolder.download_item_tv_hint + .setVisibility(View.VISIBLE); + viewHolder.download_item_tv_hint + .setText(PlatformUtils.getInstance(context) + .getPlatformName( + apkEntity.getPlatform())); + viewHolder.download_item_iv_pic + .setVisibility(View.GONE); + viewHolder.download_item_progressbar + .setVisibility(View.GONE); + viewHolder.download_item_tv_name + .setVisibility(View.GONE); + viewHolder.download_item_tv_status + .setVisibility(View.GONE); + viewHolder.view.setBackgroundColor(0xffffff); + } + } + break; + default: + break; + } + } else { + int id = PlatformUtils.getInstance(context).getPlatformPic( + apkEntity.getPlatform()); + if (id != 0) { + viewHolder.download_item_iv_pic + .setVisibility(View.VISIBLE); + viewHolder.download_item_iv_pic.setImageResource(id); + viewHolder.download_item_tv_hint + .setVisibility(View.GONE); + viewHolder.download_item_progressbar + .setVisibility(View.GONE); + viewHolder.download_item_tv_name + .setVisibility(View.GONE); + viewHolder.download_item_tv_status + .setVisibility(View.GONE); + viewHolder.view.setBackgroundColor(0xffffff); + } else { + String path = PlatformUtils.getInstance(context) + .getPlatformPicPath(apkEntity.getPlatform()); + if (path != null) { + viewHolder.download_item_iv_pic + .setVisibility(View.VISIBLE); + ImageUtils.getInstance(context).display( + "file://" + path, + viewHolder.download_item_iv_pic); + viewHolder.download_item_tv_hint + .setVisibility(View.GONE); + viewHolder.download_item_progressbar + .setVisibility(View.GONE); + viewHolder.download_item_tv_name + .setVisibility(View.GONE); + viewHolder.download_item_tv_status + .setVisibility(View.GONE); + viewHolder.view.setBackgroundColor(0xffffff); + } else { + viewHolder.download_item_tv_hint + .setVisibility(View.VISIBLE); + viewHolder.download_item_tv_hint + .setText(PlatformUtils.getInstance(context) + .getPlatformName( + apkEntity.getPlatform())); + viewHolder.download_item_iv_pic + .setVisibility(View.GONE); + viewHolder.download_item_progressbar + .setVisibility(View.GONE); + viewHolder.download_item_tv_name + .setVisibility(View.GONE); + viewHolder.download_item_tv_status + .setVisibility(View.GONE); + viewHolder.view.setBackgroundColor(0xffffff); + } + } + } + } + } + + @Override + public int getItemViewType(int position) { + + return position; + } + + @Override + public RecyclerViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { + View view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.game_download_item, viewGroup, false); + return new RecyclerViewHolder(view); + } + } +} diff --git a/app/src/main/java/com/gh/common/view/Gh_ImageView.java b/app/src/main/java/com/gh/common/view/Gh_ImageView.java new file mode 100644 index 0000000000..20a9f3d058 --- /dev/null +++ b/app/src/main/java/com/gh/common/view/Gh_ImageView.java @@ -0,0 +1,51 @@ +package com.gh.common.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.widget.ImageView; + +public class Gh_ImageView extends ImageView { + + private GestureDetector mGestureDetector; + private OnSingleTapListener listener; + + public Gh_ImageView(Context context) { + + this(context, null); + } + + public Gh_ImageView(Context context, AttributeSet attrs) { + super(context, attrs); + + mGestureDetector = new GestureDetector(context, + new GestureDetector.SimpleOnGestureListener() { + + @Override + public boolean onSingleTapUp(MotionEvent e) { + + if (listener != null) { + listener.onSingleTap(); + } + return super.onSingleTapUp(e); + } + + }); + } + + public void setOnSingleTapListener(OnSingleTapListener listener) { + this.listener = listener; + } + + public interface OnSingleTapListener { + void onSingleTap(); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + + mGestureDetector.onTouchEvent(event); + return super.dispatchTouchEvent(event); + } +} diff --git a/app/src/main/java/com/gh/common/view/Gh_LinearLayout.java b/app/src/main/java/com/gh/common/view/Gh_LinearLayout.java new file mode 100644 index 0000000000..f884d2ab1e --- /dev/null +++ b/app/src/main/java/com/gh/common/view/Gh_LinearLayout.java @@ -0,0 +1,105 @@ +package com.gh.common.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.LinearLayout; + +import com.gh.common.util.DisplayUtils; +import com.gh.gamecenter.R; +import com.gh.gamecenter.eventbus.EBShowDone; + +import de.greenrobot.event.EventBus; + +public class Gh_LinearLayout extends LinearLayout { + + private LinearLayout dm_item, dm_item_ll_delete; + + private int height; + private int total; + private int distance; + + private boolean isSliding; + + public boolean isSliding() { + return isSliding; + } + + private int position; + + Runnable show = new Runnable() { + @Override + public void run() { + + LayoutParams lparams = new LayoutParams( + LayoutParams.MATCH_PARENT, height); + lparams.height = dm_item.getHeight() + distance; + if (lparams.height > total) { + lparams.height = total; + } + dm_item.setLayoutParams(lparams); + invalidate(); + if (dm_item.getHeight() < total) { + postDelayed(show, 10); + } else { + isSliding = false; + EventBus.getDefault().post(new EBShowDone("下载管理", position)); + } + } + }; + + Runnable hide = new Runnable() { + @Override + public void run() { + + LayoutParams lparams = new LayoutParams( + LayoutParams.MATCH_PARENT, height); + lparams.height = dm_item.getHeight() - distance; + if (lparams.height < height) { + lparams.height = height; + } + dm_item.setLayoutParams(lparams); + invalidate(); + if (dm_item.getHeight() > height) { + postDelayed(hide, 10); + } else { + dm_item_ll_delete.setVisibility(View.GONE); + isSliding = false; + } + } + }; + + public Gh_LinearLayout(Context context, AttributeSet attrs) { + super(context, attrs); + + + height = DisplayUtils.dip2px(getContext(), 66); + total = DisplayUtils.dip2px(getContext(), 96); + distance = DisplayUtils.dip2px(getContext(), 3); + + isSliding = false; + } + + @Override + protected void onAttachedToWindow() { + + super.onAttachedToWindow(); + dm_item = (LinearLayout) findViewById(R.id.dm_item); + dm_item_ll_delete = (LinearLayout) findViewById(R.id.dm_item_ll_delete); + } + + public void showDeleteView(int position) { + this.position = position; + isSliding = true; + dm_item_ll_delete.setVisibility(View.VISIBLE); + removeCallbacks(hide); + post(show); + getHandler(); + } + + public void hideDeleteView() { + isSliding = true; + removeCallbacks(show); + post(hide); + } +} diff --git a/app/src/main/java/com/gh/common/view/Gh_ViewPager.java b/app/src/main/java/com/gh/common/view/Gh_ViewPager.java new file mode 100644 index 0000000000..c6fe1d828b --- /dev/null +++ b/app/src/main/java/com/gh/common/view/Gh_ViewPager.java @@ -0,0 +1,29 @@ +package com.gh.common.view; + +import android.content.Context; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; +import android.view.MotionEvent; + +public class Gh_ViewPager extends ViewPager { + + public Gh_ViewPager(Context context) { + + this(context, null); + } + + public Gh_ViewPager(Context context, AttributeSet attrs) { + super(context, attrs); + + } + + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + + for (int i = 0; i < getChildCount(); i++) { + getChildAt(i).dispatchTouchEvent(event); + } + return super.dispatchTouchEvent(event); + } + +} diff --git a/app/src/main/java/com/gh/common/view/HorizontalItemDecoration.java b/app/src/main/java/com/gh/common/view/HorizontalItemDecoration.java new file mode 100644 index 0000000000..85b973733e --- /dev/null +++ b/app/src/main/java/com/gh/common/view/HorizontalItemDecoration.java @@ -0,0 +1,47 @@ +package com.gh.common.view; + +import android.content.Context; +import android.graphics.Paint; +import android.graphics.Rect; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.gh.common.util.DisplayUtils; + +public class HorizontalItemDecoration extends RecyclerView.ItemDecoration { + + private Paint paint; + private int mInterval = 0; + private int mSize = 0; + + public HorizontalItemDecoration(Context context, int interval, int size) { + paint = new Paint(); + paint.setColor(0xffffffff); + mInterval = DisplayUtils.dip2px(context, interval); + mSize = size; + } + +// @Override +// public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { +// int top = parent.getPaddingTop(); +// int bottom = parent.getMeasuredHeight() - parent.getPaddingBottom(); +// for (int i = 0, size = parent.getChildCount(); i < size; i++) { +// View child = parent.getChildAt(i); +// RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child +// .getLayoutParams(); +// int left = child.getRight() + layoutParams.rightMargin; +// int right = left + mInterval; +// c.drawRect(left, top, right, bottom, paint); +// } +// } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, + RecyclerView.State state) { + if (parent.getChildPosition(view) == mSize - 1) { + outRect.set(0, 0, 0, 0); + } else { + outRect.set(0, 0, mInterval, 0); + } + } +} diff --git a/app/src/main/java/com/gh/common/view/KeyboardLayout.java b/app/src/main/java/com/gh/common/view/KeyboardLayout.java new file mode 100644 index 0000000000..2733099d2e --- /dev/null +++ b/app/src/main/java/com/gh/common/view/KeyboardLayout.java @@ -0,0 +1,38 @@ +package com.gh.common.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.RelativeLayout; + +public class KeyboardLayout extends RelativeLayout { + + private OnKeyboardChangedListener mListener; + + public KeyboardLayout(Context context) { + super(context); + + } + + public KeyboardLayout(Context context, AttributeSet attrs) { + super(context, attrs); + + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + + super.onSizeChanged(w, h, oldw, oldh); + if (mListener != null) { + mListener.OnKeyboardChanged(w, h, oldw, oldh); + } + } + + public interface OnKeyboardChangedListener { + void OnKeyboardChanged(int w, int h, int oldw, int oldh); + } + + public void setOnKeyboardChangedListener(OnKeyboardChangedListener listener) { + this.mListener = listener; + } + +} diff --git a/app/src/main/java/com/gh/common/view/MyGame_LinearLayout.java b/app/src/main/java/com/gh/common/view/MyGame_LinearLayout.java new file mode 100644 index 0000000000..ac733b538f --- /dev/null +++ b/app/src/main/java/com/gh/common/view/MyGame_LinearLayout.java @@ -0,0 +1,91 @@ +package com.gh.common.view; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.View; +import android.widget.LinearLayout; + +import com.gh.common.util.DisplayUtils; +import com.gh.gamecenter.R; +import com.gh.gamecenter.eventbus.EBShowDone; + +import de.greenrobot.event.EventBus; + +public class MyGame_LinearLayout extends LinearLayout { + + private LinearLayout mygame_ll; + private RecyclerView mygame_rv_show; + + private int height; + private int distance; + private int total; + + private int position; + + Runnable show = new Runnable() { + @Override + public void run() { + LayoutParams lparams = new LayoutParams( + LayoutParams.MATCH_PARENT, height); + lparams.height = mygame_ll.getHeight() + distance; + if (lparams.height > total) { + lparams.height = total; + } + mygame_ll.setLayoutParams(lparams); + invalidate(); + if (lparams.height < total) { + postDelayed(show, 10); + } else { + EventBus.getDefault().post(new EBShowDone("我的游戏", position)); + } + } + }; + + Runnable hide = new Runnable() { + @Override + public void run() { + LayoutParams lparams = new LayoutParams( + LayoutParams.MATCH_PARENT, height); + lparams.height = mygame_ll.getHeight() - distance; + if (lparams.height < height) { + lparams.height = height; + } + mygame_ll.setLayoutParams(lparams); + invalidate(); + if (lparams.height > height) { + postDelayed(hide, 10); + } else { + mygame_rv_show.setVisibility(View.GONE); + } + } + }; + + public MyGame_LinearLayout(Context context, AttributeSet attrs) { + super(context, attrs); + + height = DisplayUtils.dip2px(getContext(), 66); + distance = DisplayUtils.dip2px(getContext(), 5); + total = DisplayUtils.dip2px(getContext(), 136); + } + + @Override + protected void onAttachedToWindow() { + + super.onAttachedToWindow(); + mygame_rv_show = (RecyclerView) findViewById(R.id.mygame_rv_show); + mygame_ll = (LinearLayout) findViewById(R.id.mygame_ll); + } + + public void showRecyclerView(int position) { + this.position = position; + mygame_rv_show.setVisibility(View.VISIBLE); + removeCallbacks(hide); + post(show); + } + + public void hideRecyclerView() { + removeCallbacks(show); + post(hide); + } +} diff --git a/app/src/main/java/com/gh/common/view/MyRecyclerView.java b/app/src/main/java/com/gh/common/view/MyRecyclerView.java new file mode 100644 index 0000000000..fd0c18f1ba --- /dev/null +++ b/app/src/main/java/com/gh/common/view/MyRecyclerView.java @@ -0,0 +1,48 @@ +package com.gh.common.view; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.MotionEvent; + +/** + * 重写RecyclerView 解决触摸事件 + * + * @author 黄壮华 + * + */ +public class MyRecyclerView extends RecyclerView { + + public static boolean isCanMove = false; + + public MyRecyclerView(Context context, AttributeSet attrs) { + super(context, attrs); + + } + + private float xDis; + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + + switch (ev.getAction()) { + case MotionEvent.ACTION_DOWN: + xDis = ev.getX(); + break; + case MotionEvent.ACTION_MOVE: + if (isCanMove) { + if (xDis - ev.getX() > 0) { + MyViewPager.isCanMove = true; + return false; + } else if (xDis - ev.getX() < 0) { + isCanMove = false; + } + } + xDis = ev.getX(); + break; + default: + break; + } + return super.dispatchTouchEvent(ev); + } +} diff --git a/app/src/main/java/com/gh/common/view/MyViewPager.java b/app/src/main/java/com/gh/common/view/MyViewPager.java new file mode 100644 index 0000000000..dac749a28c --- /dev/null +++ b/app/src/main/java/com/gh/common/view/MyViewPager.java @@ -0,0 +1,60 @@ +package com.gh.common.view; + +import android.content.Context; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; +import android.view.MotionEvent; + +/** + * 重写ViewPager 解决触摸事件 + * + * @author 黄壮华 + * + */ +public class MyViewPager extends ViewPager { + + public static boolean isCanMove = false; + + public MyViewPager(Context context, AttributeSet attrs) { + super(context, attrs); + + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + + switch (ev.getAction()) { + case MotionEvent.ACTION_MOVE: + if (isCanMove) { + return true; + } + break; + default: + break; + } + return super.onInterceptTouchEvent(ev); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + + switch (ev.getAction()) { + case MotionEvent.ACTION_DOWN: + isCanMove = false; + break; + case MotionEvent.ACTION_MOVE: + if (isCanMove) { + return onTouchEvent(ev); + } + break; + case MotionEvent.ACTION_UP: + if (isCanMove) { + return onTouchEvent(ev); + } + break; + default: + break; + } + return super.dispatchTouchEvent(ev); + } +} diff --git a/app/src/main/java/com/gh/common/view/VerticalItemDecoration.java b/app/src/main/java/com/gh/common/view/VerticalItemDecoration.java new file mode 100644 index 0000000000..282a702e81 --- /dev/null +++ b/app/src/main/java/com/gh/common/view/VerticalItemDecoration.java @@ -0,0 +1,43 @@ +package com.gh.common.view; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.gh.common.util.DisplayUtils; +import com.gh.gamecenter.R; + +public class VerticalItemDecoration extends RecyclerView.ItemDecoration { + + private Paint paint; + private int mInterval = 0; + + public VerticalItemDecoration(Context context, int interval) { + paint = new Paint(); + paint.setColor(context.getResources().getColor(R.color.bg_color)); + mInterval = DisplayUtils.dip2px(context, interval); + } + + @Override + public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { + int left = parent.getPaddingLeft(); + int right = parent.getMeasuredWidth() - parent.getPaddingRight(); + for (int i = 0, size = parent.getChildCount() - 1; i < size; i++) { + View child = parent.getChildAt(i); + RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child + .getLayoutParams(); + int top = child.getBottom() + layoutParams.bottomMargin; + int bottom = top + mInterval; + c.drawRect(left, top, right, bottom, paint); + } + } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, + RecyclerView.State state) { + outRect.set(0, 0, 0, mInterval); + } +} diff --git a/app/src/main/java/com/gh/download/DBHelper.java b/app/src/main/java/com/gh/download/DBHelper.java new file mode 100644 index 0000000000..0b9a24714e --- /dev/null +++ b/app/src/main/java/com/gh/download/DBHelper.java @@ -0,0 +1,96 @@ +package com.gh.download; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.util.Log; + +import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper; +import com.j256.ormlite.dao.Dao; +import com.j256.ormlite.support.ConnectionSource; +import com.j256.ormlite.table.TableUtils; + +public class DBHelper extends OrmLiteSqliteOpenHelper +{ + private static final String DB_NAME = "gh_download.db"; + private static final int VERSION = 3; + + + /** + * downloadDao ,每张表对应一个 + */ + private Dao downloadDao; + + private DBHelper(Context context) + { + super(context, DB_NAME, null, VERSION); + } + + @Override + public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) + { + try { + Log.v("ormlite_test", "onCreate ===================="); + TableUtils.createTable(connectionSource, DownloadEntry.class); + } catch (java.sql.SQLException e) { + e.printStackTrace(); + } + } + + @Override + public void onUpgrade(SQLiteDatabase database, + ConnectionSource connectionSource, int oldVersion, int newVersion) + { + try { + TableUtils.dropTable(connectionSource, DownloadEntry.class, true); + onCreate(database, connectionSource); + } catch (java.sql.SQLException e) { + e.printStackTrace(); + } + + } + + private static DBHelper mInstance; + + /** + * 单例获取该Helper + * + * @param context + * @return + */ + public static synchronized DBHelper getInstance(Context context) + { + context = context.getApplicationContext(); + if (mInstance == null) + { + synchronized (DBHelper.class) + { + if (mInstance == null) + mInstance = new DBHelper(context); + } + } + + return mInstance; + } + + public Dao getDownloadDao(){ + try { + if(downloadDao == null){ + downloadDao = getDao(DownloadEntry.class); + } + } catch (java.sql.SQLException e) { + e.printStackTrace(); + } + return downloadDao; + } + + /** + * 释放资源 + */ + @Override + public void close() + { + super.close(); + downloadDao= null; + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/download/DataChanger.java b/app/src/main/java/com/gh/download/DataChanger.java new file mode 100644 index 0000000000..4171d2311b --- /dev/null +++ b/app/src/main/java/com/gh/download/DataChanger.java @@ -0,0 +1,81 @@ +package com.gh.download; + +import java.util.HashMap; +import java.util.Observable; + + +public class DataChanger extends Observable{ + private HashMap mDownloadingTasks;//当前正在下载的任务队列 + private HashMap mDownloadEntries;//包含所有下载任务的任务队列 + + private static DataChanger mInstance; + + private DataChanger() { + mDownloadingTasks = new HashMap(); + mDownloadEntries = new HashMap(); + } + + public static DataChanger getInstance(){ + if(mInstance == null){ + mInstance = new DataChanger(); + } + return mInstance; + } + + public HashMap getDownloadingTasks() { + return mDownloadingTasks; + } + + public HashMap getDownloadEntries() { + return mDownloadEntries; + } + + public void addToDownloadEntries(DownloadEntry entry) { + mDownloadEntries.put(entry.getUrl(), entry); + } + + public int getDownloadingSize() { + return mDownloadingTasks.size(); + } + + public synchronized void notifyDataChanged(DownloadEntry entry) { + if(entry != null){ + if(mDownloadEntries.get(entry.getUrl()) != null){ + mDownloadEntries.put(entry.getUrl(), entry); + setChanged(); + notifyObservers(); + } + } + + } + + public void addToDownloadingTask(String url, DownloadTask task) { + mDownloadingTasks.put(url, task); + } + + public void removeDownloadingTask(String url) { + getDownloadingTasks().remove(url); + } + + public void removeDownloadEntry(String url) { + getDownloadEntries().remove(url); + } + + public void pauseDownloadingTasks(String url) { + DownloadTask downloadTask = getDownloadingTasks().get(url); + if(downloadTask != null){ + downloadTask.pause(); + removeDownloadingTask(url); + } + pauseDownloadEntries(url); + } + + public void pauseDownloadEntries(String url) { + DownloadEntry entry = getDownloadEntries().get(url); + if(entry != null){ + entry.setStatus(DownloadStatus.pause); + } + } + + +} diff --git a/app/src/main/java/com/gh/download/DataWatcher.java b/app/src/main/java/com/gh/download/DataWatcher.java new file mode 100644 index 0000000000..50334b32f4 --- /dev/null +++ b/app/src/main/java/com/gh/download/DataWatcher.java @@ -0,0 +1,18 @@ +package com.gh.download; + +import java.util.HashMap; +import java.util.Observable; +import java.util.Observer; + + +public abstract class DataWatcher implements Observer{ + + @Override + public void update(Observable observable, Object data) { + onDataChanged(DataChanger.getInstance().getDownloadEntries()); + } + + public abstract void onDataChanged(HashMap downloadingEntries); + + +} diff --git a/app/src/main/java/com/gh/download/DownloadDao.java b/app/src/main/java/com/gh/download/DownloadDao.java new file mode 100644 index 0000000000..cf1be0171a --- /dev/null +++ b/app/src/main/java/com/gh/download/DownloadDao.java @@ -0,0 +1,80 @@ +package com.gh.download; + +import java.util.List; + +import android.content.Context; +import android.database.SQLException; + +import com.j256.ormlite.dao.Dao; + +public class DownloadDao { + private static Dao downloadDaoOpe; + private static DBHelper helper; + private static DownloadDao mInstance; + + private DownloadDao(Context context) throws java.sql.SQLException { + try { + helper = DBHelper.getInstance(context); + downloadDaoOpe = helper.getDownloadDao(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + public static DownloadDao getInstance(Context context) { + helper = DBHelper.getInstance(context); + try { + if (mInstance == null) { + synchronized (DownloadDao.class) { + if (mInstance == null) { + mInstance = new DownloadDao(context); + } + } + } + } catch (java.sql.SQLException e) { + e.printStackTrace(); + } + return mInstance; + } + + public void newOrUpdate(DownloadEntry entry) { + try { + if (DownloadStatus.cancel.equals(entry.getStatus())) { + downloadDaoOpe.delete(entry); + } else { + downloadDaoOpe.createOrUpdate(entry); + } + } catch (java.sql.SQLException e) { + e.printStackTrace(); + } + } + + public DownloadEntry get(String url) { + try { + return downloadDaoOpe.queryForId(url); + } catch (java.sql.SQLException e) { + e.printStackTrace(); + } + + return null; + } + + public List getAll() { + List list = null; + try { + list = downloadDaoOpe.queryForAll(); + } catch (java.sql.SQLException e) { + e.printStackTrace(); + } + return list; + } + + public void delete(String url) { + try { + downloadDaoOpe.deleteById(url); + } catch (java.sql.SQLException e) { + e.printStackTrace(); + } + + } +} diff --git a/app/src/main/java/com/gh/download/DownloadEntry.java b/app/src/main/java/com/gh/download/DownloadEntry.java new file mode 100644 index 0000000000..3116796281 --- /dev/null +++ b/app/src/main/java/com/gh/download/DownloadEntry.java @@ -0,0 +1,144 @@ +package com.gh.download; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map.Entry; + +import com.j256.ormlite.field.DataType; +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; + +@DatabaseTable(tableName = "download") +public class DownloadEntry implements Serializable{ + + /** + * + */ + private static final long serialVersionUID = 1L; + + @DatabaseField(id = true,columnName="url") + private String url; + +// @DatabaseField(columnName="id") +// private String id; + + @DatabaseField(columnName="name") + private String name; + + @DatabaseField(columnName="status") + private DownloadStatus status; + + @DatabaseField(columnName="path") + private String path; + + @DatabaseField(columnName="progress") + private long progress; + + @DatabaseField(columnName="size") + private long size; + + @DatabaseField(columnName="percent") + private double percent; + + @DatabaseField(columnName="speed") + private long speed; + + @DatabaseField(columnName="meta", dataType=DataType.SERIALIZABLE) + private HashMap meta;//其他 + + public long getSpeed() { + return speed; + } + public void setSpeed(long speed) { + this.speed = speed; + } + + public HashMap getMeta() { + return meta; + } + public void setMeta(HashMap meta) { + this.meta = meta; + } + public double getPercent() { + return percent; + } + public void setPercent(double percent) { + this.percent = percent; + } +// public String getId() { +// return id; +// } +// public void setId(String id) { +// this.id = id; +// } + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + public DownloadStatus getStatus() { + return status; + } + public void setStatus(DownloadStatus status) { + this.status = status; + } + public String getUrl() { + return url; + } + public void setUrl(String url) { + this.url = url; + } + public String getPath() { + return path; + } + public void setPath(String path) { + this.path = path; + } + 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; + } + + @Override + public String toString() { + StringBuilder metas = new StringBuilder(); + metas.append("("); + + + int i = 1; + + if(meta != null){ + for (Entry entry : meta.entrySet()) { + metas.append(entry.getKey()); + metas.append(":"); + metas.append(entry.getValue()); + if(i != meta.size()){ + metas.append(","); + } + } + } + metas.append(")"); + return "[" + + name + "===" + + url + "===" + + path + "===" + + status + "===" + + progress + "===" + + size + "===" + + percent + "%===" + + speed + "k/s===" + + metas + + "]"; + } + + +} diff --git a/app/src/main/java/com/gh/download/DownloadListener.java b/app/src/main/java/com/gh/download/DownloadListener.java new file mode 100644 index 0000000000..da2afbb21c --- /dev/null +++ b/app/src/main/java/com/gh/download/DownloadListener.java @@ -0,0 +1,22 @@ +package com.gh.download; + + +/** + * @author Stay + * @version create time:Sep 23, 2014 5:52:11 PM + */ +public interface DownloadListener { + /** + * 更新每一次下载的大小 + * @param downloadedSize + */ + void onProgressChanged(int downloadedSize); + + /** + * 更新任务下载状态 + * @param status + */ + void onStatusChanged(DownloadStatus status); + + +} diff --git a/app/src/main/java/com/gh/download/DownloadManager.java b/app/src/main/java/com/gh/download/DownloadManager.java new file mode 100644 index 0000000000..41c4cace99 --- /dev/null +++ b/app/src/main/java/com/gh/download/DownloadManager.java @@ -0,0 +1,253 @@ +package com.gh.download; + +import java.io.File; +import java.util.List; +import java.util.Map.Entry; + +import android.content.Context; +import android.content.Intent; +import android.widget.Toast; + +import com.gh.common.constant.Constants; +import com.gh.common.util.FileUtils; +import com.gh.common.util.Trace; + +public class DownloadManager { + private static DownloadManager mInstance; + private Context context; + + private DownloadManager(Context context) { + this.context = context; + context.startService(new Intent(context, DownloadService.class)); + } + + public static DownloadManager getInstance(Context context) { + if (mInstance == null) { + mInstance = new DownloadManager(context.getApplicationContext()); + } + + return mInstance; + } + + private Intent getIntent(DownloadEntry entry, DownloadStatus status) { + Intent service = new Intent(context, DownloadService.class); + service.putExtra(Constants.KEY_DOWNLOAD_ENTRY, entry); + service.putExtra(Constants.KEY_DOWNLOAD_ACTION, status.name()); + return service; + } + + /** + * 根据url到本地sqlite数据库中查找并获取该文件的保存路径, 并检查改路径下文件是否存在,不存在则删除该条无效记录 + * + * @param url + * 下载任务的标识url + */ + private boolean checkDownloadEntryRecordValidate(String url) { + DownloadEntry entry = get(url); + if (entry != null) { + File file = new File(entry.getPath()); + if (!file.exists()) { + DownloadDao.getInstance(context).delete(url); + Trace.getInstance().debug( + DownloadManager.class.getSimpleName(), + "文件不存在,删除该条无效数据库记录!"); + return true; + } + } + return false; + } + + /** + * 检查任务是否已经下载完成 + * + * @param url + * @return + */ + public boolean isFileCompleted(String url) { + DownloadEntry entry = get(url); + + if (entry != null) { + if (entry.getPercent() == 100) { + Trace.getInstance().debug( + DownloadManager.class.getSimpleName(), "文件已经下载完成!"); + return true; + } + } + + return false; + } + + public boolean isTaskDownloading(String url) { + if (DataChanger.getInstance().getDownloadingTasks().get(url) != null) { + Trace.getInstance().debug(DownloadManager.class.getSimpleName(), + url + "正在下载!"); + return true; + } + return false; + } + + /** + * 添加一个下载任务 + * + * @param entry + */ + public void add(DownloadEntry entry) { + if (entry != null) { + String url = entry.getUrl(); + checkDownloadEntryRecordValidate(url); + if (!isFileCompleted(url) && !isTaskDownloading(url)) { + context.startService(getIntent(entry, DownloadStatus.add)); + } + } + Trace.getInstance().debug(DownloadManager.class.getSimpleName(), "add"); + } + + /** + * 根据任务url暂停下载 + * + * @param url + */ + public void pause(String url) { + checkDownloadEntryRecordValidate(url); + DownloadEntry entry = DataChanger.getInstance().getDownloadEntries() + .get(url); + if (entry != null) { + context.startService(getIntent(entry, DownloadStatus.pause)); + } + Trace.getInstance().debug(DownloadManager.class.getSimpleName(), + "pause"); + } + + /** + * 根据url恢复下载 + * + * @param url + */ + public void resume(String url) { + DownloadEntry entry = get(url); + + // 暂停任务后,把文件删除,然后点继续,文件不存在,需要重新加入下载队列进行下载 + if (checkDownloadEntryRecordValidate(url)) { + Toast.makeText(context, "文件不存在!已重新加入下载队列", Toast.LENGTH_SHORT) + .show(); + add(entry); + } else { + if (entry != null) { + if (!isFileCompleted(url) && !isTaskDownloading(url)) { + context.startService(getIntent(entry, DownloadStatus.resume)); + } + } + } + Trace.getInstance().debug(DownloadManager.class.getSimpleName(), + "resume"); + } + + /** + * 根据url取消下载,并删除已下载的文件 + * + * @param id + */ + public void cancel(String url) { + cancel(url, true); + } + + public void cancel(String url, boolean isDeleteFile) { + + DownloadEntry temp = DownloadDao.getInstance(context).get(url); + if (temp != null) { + if (isDeleteFile) { + FileUtils.deleteFile(temp.getPath()); + } + DownloadDao.getInstance(context).delete(url); + Trace.getInstance().debug(DownloadManager.class.getSimpleName(), + "cancle==>file and record were deleted!"); + } + + DownloadEntry entry = DataChanger.getInstance().getDownloadEntries() + .get(url); + if (entry != null) { + context.startService(getIntent(entry, DownloadStatus.cancel)); + Trace.getInstance().debug(DownloadManager.class.getSimpleName(), + "cancel"); + } + + } + + /** + * 取消并删除所有下载任务(包括下载中、等待、暂停状态的任务) + */ + public void cancleAll() { + for (Entry entry : DataChanger.getInstance() + .getDownloadEntries().entrySet()) { + cancel(entry.getValue().getUrl(), true); + } + Trace.getInstance().debug(DownloadManager.class.getSimpleName(), + "cancel all"); + } + + /** + * 开始所有下载任务 + */ + public void startAll() { + for (Entry entry : DataChanger.getInstance() + .getDownloadEntries().entrySet()) { + add(entry.getValue()); + } + Trace.getInstance().debug(DownloadManager.class.getSimpleName(), + "start all"); + } + + /** + * 暂停所有正在下载的任务 + */ + public void pauseAll() { + for (Entry entry : DataChanger.getInstance() + .getDownloadEntries().entrySet()) { + if (entry.getValue().getStatus() == DownloadStatus.downloading) { + pause(entry.getValue().getUrl()); + } + } + Trace.getInstance().debug(DownloadManager.class.getSimpleName(), + "pause all"); + } + + /** + * 根据url获取某一个下载任务 + * + * @param url + * @return null表示下载列表中不存在该任务,否则返回下载任务 + */ + public DownloadEntry get(String url) { + return DownloadDao.getInstance(context).get(url); + } + + /** + * 获取所有下载列表中的任务 + * + * @return null表示没有下载任务 + */ + public List getAll() { + Trace.getInstance().debug(DownloadManager.class.getSimpleName(), + "getAll"); + return DownloadDao.getInstance(context).getAll(); + } + + public void addObserver(DataWatcher dataWatcher) { + DataChanger.getInstance().addObserver(dataWatcher); + Trace.getInstance().debug(DownloadManager.class.getSimpleName(), + "addObserver"); + } + + public void removeObserver(DataWatcher dataWatcher) { + DataChanger.getInstance().deleteObserver(dataWatcher); + Trace.getInstance().debug(DownloadManager.class.getSimpleName(), + "removeObserver"); + } + + public void removeObservers() { + DataChanger.getInstance().deleteObservers(); + Trace.getInstance().debug(DownloadManager.class.getSimpleName(), + "removeObservers"); + } + +} diff --git a/app/src/main/java/com/gh/download/DownloadService.java b/app/src/main/java/com/gh/download/DownloadService.java new file mode 100644 index 0000000000..4b1db28cdd --- /dev/null +++ b/app/src/main/java/com/gh/download/DownloadService.java @@ -0,0 +1,184 @@ +package com.gh.download; + +import java.util.Map.Entry; + +import android.annotation.SuppressLint; +import android.app.Service; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.ConnectivityManager; +import android.os.Handler; +import android.os.IBinder; + +import com.gh.common.constant.Constants; +import com.gh.common.util.Trace; + +public class DownloadService extends Service { + + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + public void onCreate() { + super.onCreate(); + IntentFilter filter = new IntentFilter(); + filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Trace.getInstance().debug(DownloadService.class.getSimpleName(), + "onStartCommand"); + if (intent != null && intent.getExtras() != null) { + DownloadStatus status = DownloadStatus.valueOf(intent + .getStringExtra(Constants.KEY_DOWNLOAD_ACTION)); + DownloadEntry entry = (DownloadEntry) intent + .getSerializableExtra(Constants.KEY_DOWNLOAD_ENTRY); + switch (status) { + case add: + addDownload(entry); + break; + case pause: + case neterror: + case timeout: + pauseDownload(entry); + break; + case resume: + resumeDownload(entry); + break; + case cancel: + cancelDownload(entry); + break; + default: + break; + } + } + return super.onStartCommand(intent, flags, startId); + } + + private synchronized void addDownload(DownloadEntry entry) { + DownloadEntry downloadEntry = DownloadDao.getInstance(this).get( + entry.getUrl()); + // 数据库下载历史中有这个任务的下载记录 + if (downloadEntry != null) { + entry = downloadEntry; + } + + if (DataChanger.getInstance().getDownloadingSize() >= Constants.MAX_DOWNLOADING_SIZE) { + // 1.改任务队列的状态 + entry.setStatus(DownloadStatus.waiting); + DataChanger.getInstance().addToDownloadEntries(entry); + // 2.改数据库状态 + DownloadDao.getInstance(this).newOrUpdate(entry); + // 3.通知更新 + DataChanger.getInstance().notifyDataChanged(entry); + } else { + startDownload(entry); + } + Trace.getInstance().debug(DownloadService.class.getSimpleName(), + "addDownload==>" + entry); + } + + private synchronized void startDownload(DownloadEntry entry) { + // 1.改任务队列的状态 + entry.setStatus(DownloadStatus.downloading); + DataChanger.getInstance().addToDownloadEntries(entry); + DownloadTask task = new DownloadTask(handler, entry, this); + task.start(); + DataChanger.getInstance().addToDownloadingTask(entry.getUrl(), task); + // 2.改数据库状态 + DownloadDao.getInstance(this).newOrUpdate(entry); + // 3.通知更新 + DataChanger.getInstance().notifyDataChanged(entry); + + Trace.getInstance().debug(DownloadService.class.getSimpleName(), + "startDownload==>" + entry); + } + + private synchronized void resumeDownload(DownloadEntry entry) { + addDownload(entry); + Trace.getInstance().debug(DownloadService.class.getSimpleName(), + "resumeDownload==>" + entry); + } + + private synchronized void pauseDownload(DownloadEntry entry) { + + if (entry != null) { + DownloadTask task = DataChanger.getInstance().getDownloadingTasks() + .get(entry.getUrl()); + if (task != null) { + // 1.改任务队列的状态 + entry.setStatus(DownloadStatus.pause); + } + DataChanger.getInstance().pauseDownloadingTasks(entry.getUrl()); + entry.setStatus(DownloadStatus.pause); + // 2.改数据库状态 + DownloadDao.getInstance(this).newOrUpdate(entry); + // 3.通知更新 + DataChanger.getInstance().notifyDataChanged(entry); + } + Trace.getInstance().debug(DownloadService.class.getSimpleName(), + "pauseDownload==>" + entry); + } + + private synchronized void cancelDownload(DownloadEntry entry) { + DownloadTask task = DataChanger.getInstance().getDownloadingTasks() + .get(entry.getUrl()); + if (task != null) { + task.cancel(); + // 改任务队列的状态 + DataChanger.getInstance().removeDownloadingTask(entry.getUrl()); + DataChanger.getInstance().notifyDataChanged(entry); + } + if (entry != null) { + DataChanger.getInstance().removeDownloadEntry(entry.getUrl()); + DataChanger.getInstance().notifyDataChanged(entry); + } + Trace.getInstance().debug(DownloadService.class.getSimpleName(), + "cancelDownload==>" + entry); + } + + @SuppressLint("HandlerLeak") + private Handler handler = new Handler() { + public void handleMessage(android.os.Message msg) { + DownloadEntry entry = (DownloadEntry) msg.obj; + DataChanger.getInstance().notifyDataChanged(entry); + + if (msg.what == 1 && msg.obj != null) { + switch (entry.getStatus()) { + case downloading: + break; + case done: + removeAndCheckNext(entry); + break; + case pause: +// pauseDownload(entry); + removeAndCheckNext(entry); + break; + case cancel: + removeAndCheckNext(entry); + break; + default: + break; + } + } + } + }; + + private synchronized void removeAndCheckNext(DownloadEntry obj) { + DataChanger.getInstance().removeDownloadingTask(obj.getUrl()); + DataChanger.getInstance().removeDownloadEntry(obj.getUrl()); + for (Entry entry : DataChanger.getInstance() + .getDownloadEntries().entrySet()) { + if (entry.getValue().getStatus() == DownloadStatus.waiting) { + startDownload(entry.getValue()); + return; + } + } + Trace.getInstance().debug(DownloadService.class.getSimpleName(), + "removeAndCheckNext==>" + obj); + }; + +} diff --git a/app/src/main/java/com/gh/download/DownloadStatus.java b/app/src/main/java/com/gh/download/DownloadStatus.java new file mode 100644 index 0000000000..b38dd71a5f --- /dev/null +++ b/app/src/main/java/com/gh/download/DownloadStatus.java @@ -0,0 +1,5 @@ +package com.gh.download; + +public enum DownloadStatus { + add, pause, cancel, downloading, done, waiting, resume, timeout, neterror, hijack +} diff --git a/app/src/main/java/com/gh/download/DownloadTask.java b/app/src/main/java/com/gh/download/DownloadTask.java new file mode 100644 index 0000000000..c385dff763 --- /dev/null +++ b/app/src/main/java/com/gh/download/DownloadTask.java @@ -0,0 +1,187 @@ +package com.gh.download; + +import java.text.DecimalFormat; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map.Entry; + +import android.content.Context; +import android.os.Handler; +import android.os.Message; + +import com.gh.common.constant.Constants; +import com.gh.common.util.FileUtils; +import com.gh.common.util.Trace; + +public class DownloadTask implements DownloadListener { + + private DownloadEntry entry; + private Handler handler; + private Context context; + private DownloadThread downloadThread; + + private double currPercent; + private long totalSize; + private long currSize; + + // 计算下载速度 + private long lastTime; + private long intervalDownloadedSize; + + public DownloadTask(Handler handler, final DownloadEntry entry, + Context context) { + + this.entry = entry; + this.handler = handler; + + this.context = context; + DownloadEntry historyEntry = DownloadDao.getInstance(context).get( + entry.getUrl()); + if (historyEntry != null && historyEntry.getSize() != 0) { + // 历史下载任务,初始化数据 + this.totalSize = entry.getSize(); + this.currPercent = (int) (entry.getProgress() * 100l / totalSize); + Trace.getInstance().debug(DownloadTask.class.getSimpleName(), + "DownloadTask==>" + "历史下载任务,初始化数据"); + } else { + // 第一次下载 + this.currSize = 0; + this.currPercent = 0; + } + + } + + public void start() { + // 从下载历史里获取过去下载的进度信息 + DownloadEntry downloadEntry = null; + downloadEntry = DownloadDao.getInstance(context).get(entry.getUrl()); + + if (downloadEntry != null) { + entry = downloadEntry; + entry.setStatus(DownloadStatus.downloading); + Trace.getInstance().debug( + DownloadTask.class.getSimpleName(), + "start==>" + "load from history:" + entry.getUrl() + "--" + + entry.getProgress() + "," + entry.getSize()); + currSize = entry.getProgress(); + currPercent = entry.getPercent(); + } else { + Trace.getInstance().debug(DownloadTask.class.getSimpleName(), + "start==>" + "First log into history!"); + + } + + downloadThread = new DownloadThread(context, this.entry, this); + downloadThread.setPriority(Thread.MAX_PRIORITY); + downloadThread.start(); + } + + @Override + public synchronized void onProgressChanged(int len) { + currSize += len; + double percent = 0; + if (entry.getSize() != 0) { + percent = currSize * 100.0 / entry.getSize(); + DecimalFormat df = new DecimalFormat("#.0"); + percent = Double.parseDouble(df.format(percent)); + } + entry.setProgress(currSize); + entry.setPercent(percent); + + if (percent > currPercent) { + currPercent = percent; + Message msg = handler.obtainMessage(); + handler.removeMessages(0); + msg.what = 0; + msg.obj = entry; + handler.sendMessage(msg); + DownloadDao.getInstance(context).newOrUpdate(entry); + } + + // 计算下载速度 + if (System.currentTimeMillis() - lastTime > Constants.SPEED_CHECK_INTERVAL) { + entry.setSpeed(intervalDownloadedSize + / (Constants.SPEED_CHECK_INTERVAL)); + lastTime = System.currentTimeMillis(); + intervalDownloadedSize = 0; + DownloadDao.getInstance(context).newOrUpdate(entry); + } else { + intervalDownloadedSize += len; + } + + Trace.getInstance() + .debug(DownloadTask.class.getSimpleName(), + "onProgressChanged==>" + entry.getName() + "**" + + entry.getPercent() + "%**" + entry.getSpeed() + + "k/s"); + } + + @Override + public void onStatusChanged(DownloadStatus status) { + + if (status == DownloadStatus.cancel + || status == DownloadStatus.hijack) { + entry.setProgress(0); + entry.setPercent(0); + FileUtils.deleteFile(entry.getPath()); + DownloadDao.getInstance(context).delete(entry.getUrl()); + Trace.getInstance().debug(DownloadTask.class.getSimpleName(), + "onStatusChanged==>" + entry.getUrl() + " is calcled!"); + } + + if (status == DownloadStatus.done) { + entry.setSpeed(0); + entry.setProgress(entry.getSize()); + entry.setPercent(100); + } + + if (status == DownloadStatus.pause) { + entry.setSpeed(0); + } + + /*********************** 处理网络异常 ***********************/ + if (status == DownloadStatus.timeout + || status == DownloadStatus.neterror) { + HashMap map = DataChanger.getInstance().getDownloadingTasks(); + Iterator iterator = map.keySet().iterator(); + String key = null; + while (iterator.hasNext()) { + key = iterator.next(); + DownloadTask task = map.get(key); + if (task != null) { + task.pause(); + } + iterator.remove(); + } + for (Entry entry : DataChanger.getInstance() + .getDownloadEntries().entrySet()) { + DataChanger.getInstance().pauseDownloadEntries(entry.getKey()); + DownloadDao.getInstance(context).newOrUpdate(entry.getValue()); + } + + } + + entry.setStatus(status); + DownloadDao.getInstance(context).newOrUpdate(entry); + Message msg = handler.obtainMessage(); + // handler.removeMessages(1); + msg.what = 1; + msg.obj = entry; + handler.sendMessage(msg); + Trace.getInstance().debug(DownloadTask.class.getSimpleName(), + "onStatusChanged:" + status); + } + + public void cancel() { + downloadThread.cancle(); + + } + + public void pause() { + downloadThread.pause(); + + } + + // check download progress + // DataChanger notify progress +} diff --git a/app/src/main/java/com/gh/download/DownloadThread.java b/app/src/main/java/com/gh/download/DownloadThread.java new file mode 100644 index 0000000000..e65d0266a8 --- /dev/null +++ b/app/src/main/java/com/gh/download/DownloadThread.java @@ -0,0 +1,165 @@ +package com.gh.download; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.net.HttpURLConnection; +import java.net.URL; + +import org.apache.http.HttpStatus; + +import android.content.Context; +import android.text.TextUtils; +import android.util.Log; + +import com.gh.common.util.Trace; +import com.gh.common.util.Utils; + +public class DownloadThread extends Thread { + private static final int CONNECT_TIME = 5000; + private static final int READ_TIME = 5000; + + private DownloadEntry entry; + private DownloadListener listener; + private DownloadStatus status; + private Context context; + + public DownloadThread(Context context, DownloadEntry entry, + DownloadListener listener) { + this.entry = entry; + this.listener = listener; + this.context = context; + } + + @Override + public void run() { + super.run(); + + try { + File targetFile = new File(entry.getPath()); + if (!targetFile.exists()) { + File dir = targetFile.getParentFile(); + if (dir.exists() || dir.mkdirs()) { + targetFile.createNewFile(); + } + } + + BufferedInputStream bis = null; + BufferedOutputStream bos = null; + + FileOutputStream fileOutputStream = null; + if (targetFile.length() > 0) { + fileOutputStream = new FileOutputStream(entry.getPath(), true); + } else { + fileOutputStream = new FileOutputStream(entry.getPath()); + } + + URL url = new URL(entry.getUrl()); + HttpURLConnection connection = (HttpURLConnection) url + .openConnection(); + connection.setRequestMethod("GET"); + connection.setConnectTimeout(CONNECT_TIME); + connection.setReadTimeout(READ_TIME); + connection.setRequestProperty("RANGE", + "bytes=" + targetFile.length() + "-"); + //设置自动重定向 + connection.setInstanceFollowRedirects(true); + Trace.getInstance().debug(DownloadThread.class.getSimpleName(), + "startPosition-->" + targetFile.length()); + + int code = connection.getResponseCode(); + if (code == HttpStatus.SC_MOVED_PERMANENTLY || code == HttpStatus.SC_MOVED_TEMPORARILY) { + //未自动重定向 + String location = connection.getHeaderField("Location"); + Utils.log("location = " + location); +// entry.setUrl(location); + url = new URL(location); + connection = (HttpURLConnection) url + .openConnection(); + connection.setRequestMethod("GET"); + connection.setConnectTimeout(CONNECT_TIME); + connection.setReadTimeout(READ_TIME); + connection.setRequestProperty("RANGE", + "bytes=" + targetFile.length() + "-"); + //设置自动重定向 + connection.setInstanceFollowRedirects(true); + } + + bis = new BufferedInputStream(connection.getInputStream()); + bos = new BufferedOutputStream(fileOutputStream); + long conentLength = connection.getContentLength(); + String eTag = connection.getHeaderField("ETag"); + if (!TextUtils.isEmpty(eTag) && eTag.startsWith("\"") && eTag.endsWith("\"")) { + eTag = eTag.substring(1, eTag.length() - 1); + } + String eTag2 = entry.getMeta().get("ETag"); + if (!TextUtils.isEmpty(eTag2) && !eTag2.equals(eTag)) { + //链接被劫持,抛出异常 + Utils.log("eTag = " + eTag); + Utils.log("eTag2 = " + eTag2); + listener.onStatusChanged(DownloadStatus.hijack); + Trace.getInstance().debug(DownloadThread.class.getSimpleName(), + "error-->链接被劫持"); + interrupt(); + } else { + // 第一次下载记录文件长度 + if (entry.getSize() == 0) { + entry.setSize(conentLength); + DownloadDao.getInstance(context).newOrUpdate(entry); + Trace.getInstance().debug(DownloadThread.class.getSimpleName(), + "记录第一次长度"); + } + Trace.getInstance().debug( + DownloadThread.class.getSimpleName(), + "progress:" + entry.getProgress() + "/curfilesize:" + + targetFile.length() + "=====contentLength:" + + conentLength + "/ totalSize:" + entry.getSize()); + + byte[] buffer = new byte[2048]; + int len; + while ((len = bis.read(buffer)) != -1) { + bos.write(buffer, 0, len); + listener.onProgressChanged(len); + if (status == DownloadStatus.pause + || status == DownloadStatus.cancel) { + listener.onStatusChanged(status); + break; + } + } + if (status != DownloadStatus.pause + && status != DownloadStatus.cancel) { + listener.onStatusChanged(DownloadStatus.done); + } + bos.flush(); + Log.v("bug_test", "flush==>" + targetFile.length() + ",progress==>" + + entry.getProgress()); + Trace.getInstance().debug( + DownloadThread.class.getSimpleName(), + "flush==>" + targetFile.length() + ",progress==>" + + entry.getProgress()); + + bis.close(); + bos.close(); + } + } catch (Exception e) { + //e.getMessage() will null error + if (!TextUtils.isEmpty(e.getMessage()) && e.getMessage().contains("connection timeout")) { + listener.onStatusChanged(DownloadStatus.timeout); + } else { + listener.onStatusChanged(DownloadStatus.neterror); + } + Trace.getInstance().debug(DownloadThread.class.getSimpleName(), + "exception-->" + e.toString()); + } + } + + public void pause() { + status = DownloadStatus.pause; + } + + public void cancle() { + status = DownloadStatus.cancel; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/AccountActivity.java b/app/src/main/java/com/gh/gamecenter/AccountActivity.java new file mode 100644 index 0000000000..d7cd7efdad --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/AccountActivity.java @@ -0,0 +1,85 @@ +package com.gh.gamecenter; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.TextView; + +import com.gh.base.AppController; +import com.gh.base.BaseActivity; +import com.gh.gamecenter.entity.UserEntity; + +public class AccountActivity extends BaseActivity implements OnClickListener { + + private TextView account_tv_mobile_title, account_tv_mobile; + private UserEntity user; + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + user = (UserEntity) AppController.get("user", false); + + View contentView = View.inflate(this, R.layout.activity_account, null); + + init(contentView, "账户安全设置"); + + findViewById(R.id.account_ll_account).setOnClickListener(this); + findViewById(R.id.account_ll_mobile).setOnClickListener(this); + findViewById(R.id.account_rl_password).setOnClickListener(this); + + TextView account_tv_account = (TextView) findViewById(R.id.account_tv_account); + account_tv_account.setText(user.getAccount()); + + if (user.getMobileNumber() != null) { + account_tv_mobile_title.setText("修改绑定手机"); + account_tv_mobile.setText(user.getMobileNumber()); + } else { + account_tv_mobile_title.setText("绑定手机"); + account_tv_mobile.setVisibility(View.GONE); + } + + TextView account_tv_password = (TextView) findViewById(R.id.account_tv_password); + if (user.isActivation()) { + account_tv_password.setText("修改登录密码"); + } else { + account_tv_password.setText("设置登录密码"); + } + } + + private final static int MOBILEACTIVITY = 0x123; + + @Override + public void onClick(View v) { + if (v.getId() == R.id.account_ll_mobile) { + if (user.getMobileNumber() != null) { + startActivity(new Intent(AccountActivity.this, + ModifyMobileActivity.class)); + } else { + Intent intent = new Intent(AccountActivity.this, + MobileActivity.class); + startActivityForResult(intent, MOBILEACTIVITY); + } + } else if (v.getId() == R.id.account_rl_password) { + Intent intent = new Intent(AccountActivity.this, + PasswordActivity.class); + startActivity(intent); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK && requestCode == MOBILEACTIVITY) { + if (user.getMobileNumber() != null) { + account_tv_mobile_title.setText("修改绑定手机"); + account_tv_mobile.setVisibility(View.VISIBLE); + account_tv_mobile.setText(user.getMobileNumber()); + } + } + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/ConcernActivity.java b/app/src/main/java/com/gh/gamecenter/ConcernActivity.java new file mode 100644 index 0000000000..e78b7668a2 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/ConcernActivity.java @@ -0,0 +1,446 @@ +package com.gh.gamecenter; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.json.JSONArray; +import org.json.JSONObject; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.volley.NoConnectionError; +import com.android.volley.Response; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.base.BaseActivity; +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.common.util.ImageUtils; +import com.gh.common.util.TimestampUtils; +import com.gh.common.view.Concern_LinearLayout; +import com.gh.gamecenter.db.info.ConcernInfo; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.manager.ConcernManager; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.volley.extended.JsonArrayExtendedRequest; +import com.gh.gamecenter.volley.extended.JsonObjectExtendedRequest; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.tendcloud.tenddata.TCAgent; + +public class ConcernActivity extends BaseActivity implements OnClickListener { + + private Concern_LinearLayout view; + private RecyclerView concern_rv_show, concern_rv_recommend; + private ConcernManager manager; + private ImageView concern_iv_delete; + private RelativeLayout concern_rl_title; + private TextView concern_tv_none; + + private List list; + private List recommendList; + private List concernList; + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + view = (Concern_LinearLayout) View.inflate(this, + R.layout.activity_concern, null); + + init(view, "我的关注"); + + manager = new ConcernManager(getApplicationContext()); + + list = manager.getConcernGame(); + + if (list == null) { + list = new ArrayList(); + } + + recommendList = new ArrayList(); + + concernList = new ArrayList(); + + if (!list.isEmpty()) { + initConcernGame(); + } else { + concern_tv_none.setVisibility(View.VISIBLE); + concern_rv_show.setVisibility(View.GONE); + } + + concern_iv_delete.setOnClickListener(this); + + concern_rv_show.setHasFixedSize(true); + GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 3); + concern_rv_show.setLayoutManager(gridLayoutManager); + concern_rv_show.setAdapter(new ConcernViewAdapter()); + + concern_rv_recommend.setLayoutManager(new GridLayoutManager(this, 4)); + concern_rv_recommend.setAdapter(new RecommendViewAdapter()); + + initRecommendGame(); + } + + @Override + public void onClick(View v) { + if (v == concern_iv_delete) { + if (concern_rv_recommend.getVisibility() == View.VISIBLE) { + view.hideRecyclerView(); + } else { + view.showRecyclerView(); + } + } + } + + private void initRecommendGame() { + JsonArrayExtendedRequest recommendRequest = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + + "v1d45/game/remenkapai", Constants.GAME_CD), + new Response.Listener() { + + @Override + public void onResponse(JSONArray response) { + + processingData(response); + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + + // 无网络连接 + if (error.getClass().equals(NoConnectionError.class)) { + + } + } + }); + AppController + .addToRequestQueue(recommendRequest, ConcernActivity.class); + } + + private void processingData(JSONArray response) { + Type listType = new TypeToken>() { + }.getType(); + Gson gson = new Gson(); + List list = gson.fromJson(response.toString(), listType); + for (int i = 0, size = list.size(); i < size; i++) { + if (!manager.isConcern(list.get(i).getId())) { + recommendList.add(list.get(i)); + } + } + if (!recommendList.isEmpty()) { + concern_rl_title.setVisibility(View.VISIBLE); + concern_rv_recommend.setVisibility(View.VISIBLE); + concern_rv_recommend.setLayoutManager(new GridLayoutManager(this, + recommendList.size() > 4 ? 4 : recommendList.size())); + concern_rv_recommend.getAdapter().notifyDataSetChanged(); + } + } + + private void initConcernGame() { + final List result = new ArrayList(); + final int count = list.size(); + for (int i = 0, size = list.size(); i < size; i++) { + JsonObjectExtendedRequest concernObjectRequest = new JsonObjectExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + "v1d45/game/" + + list.get(i).getId() + "/digest", + Constants.GAME_CD), + new Response.Listener() { + @Override + public void onResponse(JSONObject response) { + result.add(response); + if (result.size() == count) { + processingConcernGame(result); + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + // 无网络连接 + if (error.getClass() + .equals(NoConnectionError.class)) { + + } + } + }); + AppController.addToRequestQueue(concernObjectRequest, + ConcernActivity.class); + } + } + + private void processingConcernGame(List data) { + List gameList = new ArrayList(); + Gson gson = new Gson(); + for (int i = 0; i < data.size(); i++) { + gameList.add(gson + .fromJson(data.get(i).toString(), GameEntity.class)); + } + for (int i = 0, sizei = list.size(); i < sizei; i++) { + for (int j = 0, sizej = gameList.size(); j < sizej; j++) { + if (list.get(i).getId().equals(gameList.get(j).getId())) { + concernList.add(gameList.get(j)); + break; + } + } + } + } + + private class ConcernViewHolder extends RecyclerView.ViewHolder implements + OnClickListener { + + private ImageView concern_item_icon; + private TextView concern_item_name, concern_item_btn; + private View view; + + public ConcernViewHolder(View convertView) { + super(convertView); + + concern_item_icon = (ImageView) convertView + .findViewById(R.id.concern_item_icon); + concern_item_name = (TextView) convertView + .findViewById(R.id.concern_item_name); + concern_item_btn = (TextView) convertView + .findViewById(R.id.concern_item_btn); + concern_item_btn.setOnClickListener(this); + convertView.setOnClickListener(this); + view = convertView; + } + + @Override + public void onClick(View v) { + int position = getPosition(); + if (v == concern_item_btn) { + // 删除关注表中的数据,并更新界面 + if (manager.findConcernById(list.get(position).getId()) != null) { + ConcernInfo concernInfo = list.remove(position); + + Map kv = new HashMap(); + kv.put("状态", "取消关注"); + TCAgent.onEvent(ConcernActivity.this, "游戏关注", + concernInfo.getGameName(), kv); + + Map map = new HashMap(); + map.put("game", concernInfo.getGameName()); + map.put("type", "取消关注"); + map.put("createdOn", System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent(ConcernActivity.this, "concern", map); + + manager.deleteConcern(concernInfo.getId()); + concernList.remove(position); + concern_rv_show.getAdapter().notifyItemRemoved(position); + if (list.isEmpty()) { + concern_tv_none.setVisibility(View.VISIBLE); + concern_rv_show.setVisibility(View.GONE); + } + concern_item_btn.setClickable(false); + view.setClickable(false); + } else { + Toast.makeText(ConcernActivity.this, "取消失败,请稍后再试", + Toast.LENGTH_SHORT).show(); + } + } else { + if (concernList != null && !concernList.isEmpty()) { + GameEntity gameEntity = concernList.get(position); + + Map map = new HashMap(); + map.put("location", "关注列表"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", gameEntity.getName()); + map.put("page", "我的关注"); + DataCollectionManager.onEvent(ConcernActivity.this, "click-item", map); + + AppController.put("GameEntity", gameEntity); + Intent intent = new Intent(ConcernActivity.this, + GameDetailsActivity.class); + intent.putExtra("entrance", "我的关注-列表"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + } + } + } + + } + + private class ConcernViewAdapter extends + RecyclerView.Adapter { + + @Override + public int getItemCount() { + return list.size(); + } + + @Override + public void onBindViewHolder(ConcernViewHolder holder, int position) { + ConcernInfo concernEntity = list.get(position); + ImageUtils.getInstance(getApplicationContext()).display( + concernEntity.getIcon(), holder.concern_item_icon); + holder.concern_item_name.setText(concernEntity.getGameName()); + holder.concern_item_btn.setText("取消关注"); + holder.concern_item_btn + .setBackgroundResource(R.drawable.textview_cancel_style); + holder.concern_item_btn.setClickable(true); + holder.view.setClickable(true); + } + + @Override + public ConcernViewHolder onCreateViewHolder(ViewGroup viewGroup, + int type) { + View view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.concern_item, viewGroup, false); + return new ConcernViewHolder(view); + } + + } + + private class RecommendViewHolder extends RecyclerView.ViewHolder implements + OnClickListener { + + private ImageView concern_item_icon; + private TextView concern_item_name, concern_item_btn; + private View view; + + public RecommendViewHolder(View convertView) { + super(convertView); + + concern_item_icon = (ImageView) convertView + .findViewById(R.id.concern_item_icon); + concern_item_name = (TextView) convertView + .findViewById(R.id.concern_item_name); + concern_item_btn = (TextView) convertView + .findViewById(R.id.concern_item_btn); + concern_item_btn.setOnClickListener(this); + convertView.setOnClickListener(this); + view = convertView; + } + + @Override + public void onClick(View v) { + int position = getPosition(); + if (v == concern_item_btn) { + // 添加关注到表,并更新当前界面,插入一个关注 + GameEntity gameEntity = recommendList.get(position); + + Map kv = new HashMap(); + kv.put("状态", "关注"); + TCAgent.onEvent(ConcernActivity.this, "游戏关注", + gameEntity.getName(), kv); + + Map map = new HashMap(); + map.put("game", gameEntity.getName()); + map.put("type", "关注"); + map.put("createdOn", System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent(ConcernActivity.this, "concern", map); + + manager.addByEntity(gameEntity); + ConcernInfo concernEntity = new ConcernInfo(); + concernEntity.setGameName(gameEntity.getName()); + concernEntity.setConcern(true); + concernEntity.setIcon(gameEntity.getIcon()); + concernEntity.setId(gameEntity.getId()); + list.add(concernEntity); + if (list.size() == 1) { + concern_tv_none.setVisibility(View.GONE); + concern_rv_show.setVisibility(View.VISIBLE); + } + concern_rv_show.getAdapter() + .notifyItemInserted(list.size() - 1); + + concernList.add(recommendList.remove(position)); + if (recommendList.isEmpty()) { + concern_rl_title.setVisibility(View.GONE); + concern_rv_recommend.setVisibility(View.GONE); + } else { + if (recommendList.size() < 4) { + concern_rv_recommend + .setLayoutManager(new GridLayoutManager( + ConcernActivity.this, recommendList + .size())); + } + concern_rv_recommend.getAdapter().notifyItemRemoved( + position); + } + concern_item_btn.setClickable(false); + view.setClickable(false); + } else { + GameEntity gameEntity = recommendList.get(position); + + Map map = new HashMap(); + map.put("location", "热门游戏推荐"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", gameEntity.getName()); + map.put("page", "我的关注"); + DataCollectionManager.onEvent(ConcernActivity.this, "click-item", map); + + AppController.put("GameEntity", gameEntity); + + Intent intent = new Intent(ConcernActivity.this, + GameDetailsActivity.class); + intent.putExtra("entrance", "我的关注-推荐"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + } + } + } + + private class RecommendViewAdapter extends + RecyclerView.Adapter { + + @Override + public int getItemCount() { + return recommendList.size(); + } + + @Override + public void onBindViewHolder(RecommendViewHolder holder, int position) { + GameEntity gameEntity = recommendList.get(position); + ImageUtils.getInstance(getApplicationContext()).display( + gameEntity.getIcon(), holder.concern_item_icon); + holder.concern_item_name.setText(gameEntity.getName()); + holder.concern_item_btn.setText("关注"); + holder.concern_item_btn.setBackgroundResource(R.drawable.textview_red_style); + holder.concern_item_btn.setClickable(true); + holder.view.setClickable(true); + } + + @Override + public RecommendViewHolder onCreateViewHolder(ViewGroup viewGroup, + int type) { + View view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.concern_item, viewGroup, false); + return new RecommendViewHolder(view); + } + + } + + @Override + protected void onDestroy() { + super.onDestroy(); + view = null; + concern_rv_show = null; + concern_rv_recommend = null; + manager = null; + concern_iv_delete = null; + concern_rl_title = null; + concern_tv_none = null; + list = null; + recommendList = null; + concernList = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/CropImageActivity.java b/app/src/main/java/com/gh/gamecenter/CropImageActivity.java new file mode 100644 index 0000000000..f363050d7c --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/CropImageActivity.java @@ -0,0 +1,105 @@ +package com.gh.gamecenter; + +import java.io.File; + +import android.app.Dialog; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.util.TypedValue; +import android.view.View; +import android.view.ViewGroup.LayoutParams; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +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.FileUtils; +import com.gh.common.util.ImageUtils; +import com.gh.common.util.TokenUtils; +import com.gh.common.view.CropImageCustom; + +public class CropImageActivity extends BaseActivity { + + private CropImageCustom cropimage_custom; + + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (msg.what == 0) { + Toast.makeText(CropImageActivity.this, "上传成功", + Toast.LENGTH_SHORT).show(); + } else if (msg.what == 1) { + Toast.makeText(CropImageActivity.this, "上传失败", + Toast.LENGTH_SHORT).show(); + } + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + View contentView = View + .inflate(this, R.layout.activity_cropimage, null); + + init(contentView, "图片裁剪"); + + RelativeLayout reuse_actionbar = (RelativeLayout) findViewById(R.id.reuse_actionbar); + + TextView confirm = new TextView(this); + confirm.setText("确定"); + confirm.setTextColor(0xffffffff); + confirm.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + int padding = DisplayUtils.dip2px(getApplicationContext(), 10); + confirm.setPadding(padding, padding, padding, padding); + confirm.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + final Dialog dialog = DialogUtils.showWaitDialog( + CropImageActivity.this, "上传中..."); + new Thread(new Runnable() { + @Override + public void run() { + String path = getCacheDir() + File.separator + + System.currentTimeMillis() + ".jpg"; + // String path = getExternalCacheDir() + File.separator + // + System.currentTimeMillis() + ".jpg"; + cropimage_custom.savePicture(path); + // 上传图片 + String token = TokenUtils + .getToken(CropImageActivity.this); + String url = FileUtils.uploadFile(Config.HOST + "v2/user/upload_user_icon", path, token); + dialog.dismiss(); + if (url != null) { + Intent data = new Intent(); + data.putExtra("url", url); + setResult(RESULT_OK, data); + finish(); + handler.sendEmptyMessage(0); + } else { + handler.sendEmptyMessage(1); + } + } + }).start(); + } + }); + RelativeLayout.LayoutParams rparams = new RelativeLayout.LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + rparams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + rparams.addRule(RelativeLayout.CENTER_VERTICAL); + confirm.setLayoutParams(rparams); + reuse_actionbar.addView(confirm); + + String path = getIntent().getStringExtra("path"); + + ImageUtils.getInstance(getApplicationContext()).displayFile( + "file://" + path, cropimage_custom.getCropImageZoomView()); + + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/DatabaseActivity.java b/app/src/main/java/com/gh/gamecenter/DatabaseActivity.java new file mode 100644 index 0000000000..98ac2e4f98 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/DatabaseActivity.java @@ -0,0 +1,180 @@ +package com.gh.gamecenter; + +import android.app.ActionBar; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.gh.base.BaseActivity; +import com.gh.common.util.GameViewUtils; + +public class DatabaseActivity extends BaseActivity implements OnClickListener { + + private RecyclerView database_rv_show; + private LinearLayoutManager linearLayoutManager; + private DatabaseAdapter adapter; + private LinearLayout database_ll_loading; + private EditText database_et_search; + private TextView database_tv_search; + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_database); + + // 自定义ActionBar + ActionBar mActionBar = getActionBar(); + mActionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); + View view = View.inflate(this, R.layout.resue_actionbar, null); + view.findViewById(R.id.actionbar_rl_back).setOnClickListener(this); + ((TextView) view.findViewById(R.id.actionbar_tv_title)).setText("数据库"); + ActionBar.LayoutParams params = new ActionBar.LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + mActionBar.setCustomView(view, params);// 自定义ActionBar布局 + + database_tv_search.setOnClickListener(this); + + linearLayoutManager = new LinearLayoutManager(this); + linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + database_rv_show.setLayoutManager(linearLayoutManager); + database_rv_show.setHasFixedSize(true); + adapter = new DatabaseAdapter(); + database_rv_show.setAdapter(adapter); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.actionbar_rl_back: + finish(); + break; + case R.id.database_tv_search: + + break; + default: + break; + } + } + + private class DatabaseViewHolder extends RecyclerView.ViewHolder { + + private TextView tv_label; + + private ImageView home1_game_thumb; + private TextView home1_game_nameAndsize, home1_game_des, + database_item1, database_item2, database_item3, database_item4; + private LinearLayout home1_label_list; + private TextView home1_download_btn; + + public DatabaseViewHolder(View convertView) { + super(convertView); + + int tag = (Integer) convertView.getTag(); + if (tag == 0 || tag == 2) { + tv_label = (TextView) convertView.findViewById(R.id.tv_label); + } else { + home1_game_thumb = (ImageView) convertView + .findViewById(R.id.home1_game_thumb); + home1_game_nameAndsize = (TextView) convertView + .findViewById(R.id.home1_game_nameAndsize); + home1_game_des = (TextView) convertView + .findViewById(R.id.home1_game_des); + home1_label_list = (LinearLayout) convertView + .findViewById(R.id.home1_label_list); + home1_download_btn = (TextView) convertView + .findViewById(R.id.home1_download_btn); + database_item1 = (TextView) convertView + .findViewById(R.id.database_item1); + database_item2 = (TextView) convertView + .findViewById(R.id.database_item2); + database_item3 = (TextView) convertView + .findViewById(R.id.database_item3); + database_item4 = (TextView) convertView + .findViewById(R.id.database_item4); + } + } + + } + + private class DatabaseAdapter extends + RecyclerView.Adapter { + + @Override + public int getItemCount() { + + return 4; + } + + @Override + public void onBindViewHolder(DatabaseViewHolder viewHolder, int position) { + + if (position == 0 || position == 2) { + viewHolder.tv_label.setText("我的游戏"); + viewHolder.tv_label + .setBackgroundResource(R.drawable.title_blue); + } else if (position == 1) { + viewHolder.home1_game_thumb.setImageResource(R.drawable.logo); + viewHolder.home1_game_nameAndsize.setText("少年三国志"); + GameViewUtils.setLabelList(DatabaseActivity.this, + viewHolder.home1_label_list, "已关注,已安装"); + viewHolder.home1_download_btn.setVisibility(View.GONE); + viewHolder.home1_game_des.setVisibility(View.GONE); + viewHolder.database_item1.setText("阵容模拟器"); + viewHolder.database_item2.setText("阵容推荐"); + viewHolder.database_item3.setText("装备资料"); + viewHolder.database_item4.setText("武将资料"); + } else if (position == 2) { + viewHolder.tv_label.setText("其他游戏"); + viewHolder.tv_label + .setBackgroundResource(R.drawable.border_scarlet_bg); + } else { + viewHolder.home1_game_thumb.setImageResource(R.drawable.logo); + viewHolder.home1_game_nameAndsize.setText("全民卡牌 | 121M"); + GameViewUtils.setLabelList(DatabaseActivity.this, + viewHolder.home1_label_list, "加速,跳过"); + viewHolder.home1_download_btn.setVisibility(View.VISIBLE); + viewHolder.home1_download_btn.setText("查看"); + viewHolder.home1_game_des.setVisibility(View.VISIBLE); + viewHolder.home1_game_des + .setText("2015最萌即时战斗手游,无处不在的指尖争锋呼醒真正的魔兽情怀。"); + viewHolder.database_item1.setText("阵容模拟器"); + viewHolder.database_item2.setText("阵容推荐"); + viewHolder.database_item3.setText("装备资料"); + viewHolder.database_item4.setText("武将资料"); + } + } + + @Override + public DatabaseViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { + + View view; + if (i == 0 || i == 2) { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.news_list_item_category, viewGroup, false); + } else { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.datebase_item, viewGroup, false); + } + view.setTag(i); + return new DatabaseViewHolder(view); + } + + @Override + public int getItemViewType(int position) { + + return position; + } + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/DownloadManagerActivity.java b/app/src/main/java/com/gh/gamecenter/DownloadManagerActivity.java new file mode 100644 index 0000000000..ce2c1c5f07 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/DownloadManagerActivity.java @@ -0,0 +1,257 @@ +package com.gh.gamecenter; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; +import android.support.v4.view.ViewPager.OnPageChangeListener; +import android.util.DisplayMetrics; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.gh.base.BaseFragmentActivity; +import com.gh.common.util.DisplayUtils; +import com.gh.download.DownloadManager; +import com.gh.gamecenter.download.DownLoadManagerFragment; +import com.gh.gamecenter.download.GameUpdateFragment; +import com.gh.gamecenter.eventbus.EBDownloadChanged; +import com.gh.gamecenter.eventbus.EBMiPush; +import com.gh.gamecenter.eventbus.EBPerformClick; +import com.gh.gamecenter.eventbus.EBUISwitch; +import com.gh.gamecenter.manager.PackageManager; + +import de.greenrobot.event.EventBus; + +/** + * 下载更新管理页面 + * + * @author 黄壮华 + * + */ +public class DownloadManagerActivity extends BaseFragmentActivity implements + OnClickListener, OnPageChangeListener { + + private ViewPager downloadmanager_viewPager; + private TextView downloadmanager_tv_download, downloadmanager_tv_update, + downloadmanager_download_number, downloadmanager_update_number; + private LinearLayout downloadmanager_ll_download, + downloadmanager_ll_update; + private View downloadmanager_slide_line; + private LinearLayout.LayoutParams lparams; + + private int width; + + @Override + protected void onSaveInstanceState(Bundle outState) { + + super.onSaveInstanceState(outState); + outState.putInt("CurrentItem", downloadmanager_viewPager.getCurrentItem()); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + View contentView = View.inflate(this, + R.layout.activity_downloadmanager, null); + + init(contentView, "下载更新管理"); + + downloadmanager_ll_download.setOnClickListener(this); + downloadmanager_ll_update.setOnClickListener(this); + + int currentItem = getIntent().getIntExtra("currentItem", -1); + + int updateSize = PackageManager.getUpdateList().size(); + + int downloadSize = DownloadManager.getInstance(getApplicationContext()) + .getAll().size(); + + if (updateSize != 0) { + downloadmanager_update_number.setVisibility(View.VISIBLE); + downloadmanager_update_number.setText("" + updateSize); + } else { + downloadmanager_update_number.setVisibility(View.GONE); + } + + if (downloadSize != 0) { + downloadmanager_download_number.setVisibility(View.VISIBLE); + downloadmanager_download_number.setText("" + downloadSize); + } else { + downloadmanager_download_number.setVisibility(View.GONE); + } + + if (currentItem == -1) { + if (updateSize != 0 && downloadSize == 0) { + currentItem = 1; + } else { + currentItem = 0; + } + } + + DisplayMetrics outMetrics = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(outMetrics); + width = outMetrics.widthPixels / 2; + lparams = new LinearLayout.LayoutParams(width / 2, DisplayUtils.dip2px( + getApplicationContext(), 2)); + lparams.leftMargin = outMetrics.widthPixels / 8; + if (currentItem != 0) { + downloadmanager_ll_download.setClickable(true); + downloadmanager_ll_update.setClickable(false); + lparams.leftMargin = width + width / 4; + } else { + downloadmanager_ll_download.setClickable(false); + downloadmanager_ll_update.setClickable(true); + } + downloadmanager_slide_line.setLayoutParams(lparams); + + downloadmanager_viewPager.setAdapter(new FragmentAdapter( + getSupportFragmentManager())); + downloadmanager_viewPager.addOnPageChangeListener(this); + + if (savedInstanceState != null) { + lparams.leftMargin = width * savedInstanceState.getInt("CurrentItem") + width / 4; + downloadmanager_slide_line.setLayoutParams(lparams); + } else { + downloadmanager_viewPager.setCurrentItem(currentItem); + } + } + + private class FragmentAdapter extends FragmentPagerAdapter { + + public FragmentAdapter(FragmentManager fm) { + super(fm); + + } + + @Override + public Fragment getItem(int position) { + + if (position == 0) { + return new DownLoadManagerFragment(getIntent().getStringExtra("path")); + } else { + return new GameUpdateFragment(getIntent().getStringExtra( + "packageName"), getIntent().getBooleanExtra( + "isPushIntent", false)); + } + } + + @Override + public int getCount() { + + return 2; + } + + } + + @Override + public void onPageSelected(int position) { + + if (position == 0) { + EventBus.getDefault().post( + new EBUISwitch("DownloadManagerActivity", 0)); + downloadmanager_ll_download.setClickable(false); + downloadmanager_ll_update.setClickable(true); + downloadmanager_tv_download.setTextColor(getResources().getColor( + R.color.theme_colors)); + downloadmanager_tv_update.setTextColor(0xFF333333); + } else { + EventBus.getDefault().post( + new EBUISwitch("DownloadManagerActivity", 1)); + downloadmanager_ll_download.setClickable(true); + downloadmanager_ll_update.setClickable(false); + downloadmanager_tv_download.setTextColor(0xFF333333); + downloadmanager_tv_update.setTextColor(getResources().getColor( + R.color.theme_colors)); + } + } + + @Override + public void onPageScrolled(int position, float positionOffset, + int positionOffsetPixels) { + + if (positionOffset != 0) { + lparams.leftMargin = (int) (width * positionOffset) + width / 4; + downloadmanager_slide_line.setLayoutParams(lparams); + } + } + + @Override + public void onPageScrollStateChanged(int state) { + + + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.actionbar_rl_back: + finish(); + break; + case R.id.downloadmanager_ll_download: + downloadmanager_viewPager.setCurrentItem(0); + break; + case R.id.downloadmanager_ll_update: + downloadmanager_viewPager.setCurrentItem(1); + break; + default: + break; + } + } + + public void onEventMainThread(EBMiPush mipush){ + if ("plugin_install".equals(mipush.getFrom())) { + downloadmanager_ll_download.performClick(); + } + } + + public void onEventMainThread(EBDownloadChanged changed) { + if (changed.getType() == "download") { + downloadmanager_download_number.setVisibility(changed + .getVisibility()); + downloadmanager_download_number.setText(changed.getSize() + ""); + } else if (changed.getType() == "update") { + if (changed.getSize() == -1) { + int number = Integer.valueOf(downloadmanager_update_number + .getText().toString()); + if (number == 1) { + downloadmanager_update_number.setVisibility(View.GONE); + } else { + downloadmanager_update_number.setText((number - 1) + ""); + } + } else { + if (changed.getSize() != 0) { + downloadmanager_update_number.setVisibility(changed + .getVisibility()); + downloadmanager_update_number.setText(changed.getSize() + ""); + } else { + downloadmanager_update_number.setVisibility(View.GONE); + } + } + } + } + + public void onEventMainThread(EBPerformClick click) { + if (click.getFrom().equals("update")) { + downloadmanager_ll_download.performClick(); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + downloadmanager_viewPager = null; + downloadmanager_tv_download = null; + downloadmanager_tv_update = null; + downloadmanager_download_number = null; + downloadmanager_update_number = null; + downloadmanager_ll_download = null; + downloadmanager_ll_update = null; + downloadmanager_slide_line = null; + lparams = null; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/GameActivity.java b/app/src/main/java/com/gh/gamecenter/GameActivity.java new file mode 100644 index 0000000000..f1cf962113 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/GameActivity.java @@ -0,0 +1,183 @@ +package com.gh.gamecenter; + +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; +import android.support.v4.view.ViewPager.OnPageChangeListener; +import android.util.DisplayMetrics; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.gh.base.BaseFragmentActivity; +import com.gh.common.util.DisplayUtils; +import com.gh.common.util.Utils; +import com.gh.gamecenter.eventbus.EBUISwitch; +import com.gh.gamecenter.game.Game1Fragment; +import com.gh.gamecenter.game.Game2Fragment; + +import de.greenrobot.event.EventBus; + +public class GameActivity extends BaseFragmentActivity implements + OnClickListener, OnPageChangeListener { + + private ViewPager game_viewpager; + private TextView new_game_text, test_game_text; + private RelativeLayout.LayoutParams rparams; + private View slide_line; + + private int width; + + @Override + protected void onSaveInstanceState(Bundle outState) { + + super.onSaveInstanceState(outState); + Utils.log(this.getClass().getSimpleName() + " onSaveInstanceState"); + outState.putInt("CurrentItem", game_viewpager.getCurrentItem()); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + View contentView = View.inflate(this, R.layout.activity_game, null); + + init(contentView, "游戏"); + + initView(); + if (savedInstanceState != null) { + rparams.leftMargin = width + * savedInstanceState.getInt("CurrentItem") + width / 4; + slide_line.setLayoutParams(rparams); + } + + } + + public void initView() { + new_game_text.setOnClickListener(this); + test_game_text.setOnClickListener(this); + + DisplayMetrics outMetrics = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(outMetrics); + width = outMetrics.widthPixels / 2; + rparams = new RelativeLayout.LayoutParams(width / 2, + DisplayUtils.dip2px(getApplicationContext(), 2)); + rparams.addRule(RelativeLayout.BELOW, R.id.game_ll_top); + rparams.leftMargin = outMetrics.widthPixels / 8; + slide_line.setLayoutParams(rparams); + + game_viewpager.setAdapter(new ViewPagerAdapter( + getSupportFragmentManager())); + game_viewpager.addOnPageChangeListener(this); + int currTab = getIntent().getIntExtra("tab", 0); + setcurrTab(currTab); + } + + private void setcurrTab(int position) { + game_viewpager.setCurrentItem(position); + if (position == 0) { + new_game_text.setClickable(false); + test_game_text.setClickable(true); + new_game_text.setTextColor(getResources().getColor( + R.color.theme_colors)); + test_game_text.setTextColor(0xFF333333); + } else { + new_game_text.setClickable(true); + test_game_text.setClickable(false); + new_game_text.setTextColor(0xFF333333); + test_game_text.setTextColor(getResources().getColor( + R.color.theme_colors)); + } + if (position != 0) { + rparams.leftMargin = (int) (width * position) + width / 4; + slide_line.setLayoutParams(rparams); + } else { + rparams.leftMargin = (int) (width * position) + width / 4; + slide_line.setLayoutParams(rparams); + } + } + + public class ViewPagerAdapter extends FragmentPagerAdapter { + public ViewPagerAdapter(FragmentManager fm) { + super(fm); + } + + @Override + public Fragment getItem(int position) { + if (position == 0) { + return new Game1Fragment(); + } else { + return new Game2Fragment(); + } + } + + @Override + public int getCount() { + return 2; + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.actionbar_rl_back: + finish(); + break; + case R.id.new_game_text: + game_viewpager.setCurrentItem(0); + break; + case R.id.test_game_text: + game_viewpager.setCurrentItem(1); + break; + default: + break; + } + } + + @Override + public void onPageSelected(int position) { + if (position == 0) { + EventBus.getDefault().post(new EBUISwitch("GameActivity", 0)); + new_game_text.setClickable(false); + test_game_text.setClickable(true); + new_game_text.setTextColor(getResources().getColor( + R.color.theme_colors)); + test_game_text.setTextColor(0xFF333333); + } else { + EventBus.getDefault().post(new EBUISwitch("GameActivity", 1)); + new_game_text.setClickable(true); + test_game_text.setClickable(false); + new_game_text.setTextColor(0xFF333333); + test_game_text.setTextColor(getResources().getColor( + R.color.theme_colors)); + } + } + + @Override + public void onPageScrolled(int position, float positionOffset, + int positionOffsetPixels) { + if (positionOffset != 0) { + rparams.leftMargin = (int) (width * positionOffset) + width / 4; + slide_line.setLayoutParams(rparams); + } + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + + @Override + protected void onDestroy() { + + super.onDestroy(); + game_viewpager = null; + new_game_text = null; + test_game_text = null; + rparams = null; + slide_line = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/GameDetailsActivity.java b/app/src/main/java/com/gh/gamecenter/GameDetailsActivity.java new file mode 100644 index 0000000000..b99eed523b --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/GameDetailsActivity.java @@ -0,0 +1,1315 @@ +package com.gh.gamecenter; + +import java.util.Calendar; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.json.JSONObject; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.util.ArrayMap; +import android.support.v4.view.ViewPager; +import android.support.v4.view.ViewPager.OnPageChangeListener; +import android.text.Html; +import android.text.Spanned; +import android.text.TextUtils; +import android.util.DisplayMetrics; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup.LayoutParams; +import android.view.Window; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.volley.NoConnectionError; +import com.android.volley.Response; +import com.android.volley.TimeoutError; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.base.BaseFragmentActivity; +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.common.util.DialogUtils; +import com.gh.common.util.DisplayUtils; +import com.gh.common.util.FileUtils; +import com.gh.common.util.ImageUtils; +import com.gh.common.util.MD5Utils; +import com.gh.common.util.NetworkUtils; +import com.gh.common.util.PackageUtils; +import com.gh.common.util.PlatformUtils; +import com.gh.common.util.RunningUtils; +import com.gh.common.util.TimestampUtils; +import com.gh.common.util.Utils; +import com.gh.common.view.DownloadDialog; +import com.gh.download.DataWatcher; +import com.gh.download.DownloadEntry; +import com.gh.download.DownloadManager; +import com.gh.download.DownloadStatus; +import com.gh.gamecenter.entity.ApkEntity; +import com.gh.gamecenter.entity.DismissEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.eventbus.EBMoveTop; +import com.gh.gamecenter.eventbus.EBNetworkState; +import com.gh.gamecenter.eventbus.EBPWDismiss; +import com.gh.gamecenter.eventbus.EBPackage; +import com.gh.gamecenter.eventbus.EBPutUrl; +import com.gh.gamecenter.eventbus.EBRedDot; +import com.gh.gamecenter.eventbus.EBSlide; +import com.gh.gamecenter.gamedetails.GameDetailsFragment; +import com.gh.gamecenter.gamedetails.GameInformationFragment; +import com.gh.gamecenter.gamedetails.GameStrategyFragment; +import com.gh.gamecenter.manager.ConcernManager; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.manager.PackageManager; +import com.gh.gamecenter.personal.PersonalFragmentAdapter; +import com.gh.gamecenter.volley.extended.JsonObjectExtendedRequest; +import com.google.gson.Gson; +import com.tendcloud.tenddata.TCAgent; + +import de.greenrobot.event.EventBus; + +/** + * 游戏详情页面 如果要启动该页面,需要传 GameEntity 对象进来 对应key game + * + * @author 黄壮华 + * + */ +public class GameDetailsActivity extends BaseFragmentActivity implements + OnClickListener, OnPageChangeListener { + + private TextView gamedetails_tv_details, gamedetails_tv_information, + gamedetails_tv_strategy, gamedetails_tv_download, top_tv_name, + top_tv_info, top_tv_attention, titlebar_tv_details, + titlebar_tv_information, titlebar_tv_strategy, gamedetails_tv_per, + actionbar_tv_title; + // private TextView gamedetails_tv_database,titlebar_tv_database; + private ImageView top_iv_icon, gamedetails_iv_share; + private View gamedetails_slide_line, titlebar_slide_line; + private LinearLayout gamedetails_ll_top, gamedetails_ll_topbar, + gamedetails_ll_bottom, gamedetails_ll_loading, reuse_no_connection; + private ViewPager gamedetails_vp_show; + private ProgressBar gamedetails_progressbar; + private LinearLayout.LayoutParams lparams; + private RelativeLayout.LayoutParams rparams; + + private ConcernManager concernManager; + private DownloadEntry downloadEntry; + private GameEntity entity; + + private int currentItem = -1; + private int previous = 0; + private int width; + private String gameId; + private String entrance; + + private DismissEntity dismissEntity; + + private long start = 0L; + private boolean isShowPluginDialog = false; + private boolean isDestroy = false; + + private ArrayMap lastTimeMap; + private ArrayMap statusMap; + + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (!isDestroy) { + if (msg.what == Constants.CONTINUE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + DownloadManager.getInstance(GameDetailsActivity.this) + .resume(url); + } + } else if (msg.what == Constants.PAUSE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + DownloadManager.getInstance(GameDetailsActivity.this) + .pause(url); + } + } + } + } + }; + + private DataWatcher dataWatcher = new DataWatcher() { + @Override + public void onDataChanged( + HashMap downloadingEntries) { + if (entity != null && entity.getApk().size() == 1) { + String url = entity.getApk().get(0).getUrl(); + for (Entry entry : downloadingEntries + .entrySet()) { + if (url.equals(entry.getValue().getUrl())) { + if (!"pause".equals(statusMap.get(entry.getValue() + .getUrl()))) { + downloadEntry = entry.getValue(); + invalidate(); + } + break; + } + } + } + for (Entry entry : downloadingEntries + .entrySet()) { + DownloadEntry downloadEntry = entry.getValue(); + if (DownloadStatus.done.equals(downloadEntry.getStatus()) + && downloadEntry.getMeta().get("isPlugin") != null) { + if (!RunningUtils + .isApplicationBroughtToBackground(getApplicationContext()) + && RunningUtils.isEqualsTop( + getApplicationContext(), + GameDetailsActivity.class.getName())) { + if (!isShowPluginDialog) { + isShowPluginDialog = true; + showPluginDialog(downloadEntry.getPath(), + downloadEntry.getName()); + } + } + } + } + } + }; + + @Override + protected void onSaveInstanceState(Bundle outState) { + + super.onSaveInstanceState(outState); + Utils.log(this.getClass().getSimpleName() + " onSaveInstanceState"); + outState.putInt("CurrentItem", gamedetails_vp_show.getCurrentItem()); + AppController.put("GameEntity", entity); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + View contentView = View.inflate(this, R.layout.activity_gamedetails, + null); + + gameId = getIntent().getStringExtra("gameId"); + entrance = getIntent().getStringExtra("entrance"); + if (savedInstanceState != null) { + currentItem = savedInstanceState.getInt("CurrentItem"); + } + + init(contentView); + + dismissEntity = new DismissEntity(false); + + if (gameId != null) { + reuse_no_connection.setOnClickListener(this); + } else { + entity = (GameEntity) AppController.get("GameEntity", true); + } + + lastTimeMap = new ArrayMap(); + statusMap = new ArrayMap(); + + concernManager = new ConcernManager(getApplicationContext()); + + gamedetails_ll_bottom.setOnClickListener(this); + if (Config.isShow) { + gamedetails_ll_bottom.setVisibility(View.VISIBLE); + } else { + gamedetails_ll_bottom.setVisibility(View.GONE); + } + + gamedetails_tv_download.setOnClickListener(this); + gamedetails_progressbar.setOnClickListener(this); + gamedetails_tv_per.setOnClickListener(this); + gamedetails_iv_share.setOnClickListener(this); + + gamedetails_tv_details.setOnClickListener(this); + gamedetails_tv_information.setOnClickListener(this); + gamedetails_tv_strategy.setOnClickListener(this); + // gamedetails_tv_database.setOnClickListener(this); + + titlebar_tv_details.setOnClickListener(this); + titlebar_tv_information.setOnClickListener(this); + titlebar_tv_strategy.setOnClickListener(this); + // titlebar_tv_database.setOnClickListener(this); + + titlebar_tv_details.setClickable(false); + titlebar_tv_information.setClickable(true); + titlebar_tv_strategy.setClickable(true); + // titlebar_tv_database.setClickable(true); + + gamedetails_tv_details.setClickable(false); + gamedetails_tv_information.setClickable(true); + gamedetails_tv_strategy.setClickable(true); + // gamedetails_tv_database.setClickable(true); + + top_tv_attention.setOnClickListener(this); + + DisplayMetrics outMetrics = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(outMetrics); + width = outMetrics.widthPixels / 3; + lparams = new LinearLayout.LayoutParams(width / 2, DisplayUtils.dip2px( + getApplicationContext(), 2)); + lparams.leftMargin = outMetrics.widthPixels / 12; + gamedetails_slide_line.setLayoutParams(lparams); + titlebar_slide_line.setLayoutParams(lparams); + + rparams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, + LayoutParams.WRAP_CONTENT); + + start = Calendar.getInstance().getTimeInMillis(); + + if (entity != null) { + init(); + } else { + gamedetails_ll_loading.setVisibility(View.VISIBLE); + gamedetails_vp_show.setVisibility(View.GONE); + gamedetails_ll_top.setVisibility(View.GONE); + gamedetails_ll_bottom.setVisibility(View.GONE); + getGameDetails(); + } + } + + private void getGameDetails() { + JsonObjectExtendedRequest objectRequest = new JsonObjectExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + "v1d45/game/" + + gameId + "/digest", Constants.GAME_CD), + new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + Gson gson = new Gson(); + entity = gson.fromJson(response.toString(), + GameEntity.class); + gamedetails_ll_loading.setVisibility(View.GONE); + gamedetails_vp_show.setVisibility(View.VISIBLE); + gamedetails_ll_top.setVisibility(View.VISIBLE); + gamedetails_ll_bottom.setVisibility(View.VISIBLE); + init(); + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + // 无网络连接和访问超时 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + Toast.makeText(GameDetailsActivity.this, "网络错误", + Toast.LENGTH_SHORT).show(); + reuse_no_connection.setVisibility(View.VISIBLE); + gamedetails_ll_loading.setVisibility(View.GONE); + } + } + }); + AppController.addToRequestQueue(objectRequest, + PersonalFragmentAdapter.class); + } + + private void init() { + + actionbar_tv_title.setText(entity.getName()); + + top_tv_name.setText(entity.getName()); + + for (int i = 0, size = entity.getApk().size(); i < size; i++) { + ApkEntity apkEntity = entity.getApk().get(i); + if ("9u".equals(apkEntity.getPlatform())) { + top_tv_info.setText("V" + apkEntity.getVersion() + " | " + + apkEntity.getSize()); + break; + } + if (i == size - 1) { + top_tv_info.setText("V" + apkEntity.getVersion() + " | " + + apkEntity.getSize()); + } + } + + if (entity.getApk() == null || entity.getApk().isEmpty()) { + gamedetails_tv_download.setText("暂无下载"); + gamedetails_tv_download + .setBackgroundResource(R.drawable.textview_gray_style); + gamedetails_tv_download.setTextColor(0xFF999999); + gamedetails_tv_download.setClickable(false); + } else { + boolean isInstalled = false; + if (entity.getApk() != null + && entity.getApk().size() == 1 + && PackageManager.isInstalled(entity.getApk().get(0) + .getPackageName())) { + isInstalled = true; + } + gamedetails_tv_download.setVisibility(View.VISIBLE); + gamedetails_progressbar.setVisibility(View.GONE); + gamedetails_tv_per.setVisibility(View.GONE); + if (isInstalled) { + if (TextUtils.isEmpty(entity.getDownloadAddWord())) { + gamedetails_tv_download.setText("启动《" + entity.getName() + + "》"); + } else { + gamedetails_tv_download.setText("启动《" + entity.getName() + + "》" + entity.getDownloadAddWord()); + } + } else { + if (TextUtils.isEmpty(entity.getDownloadAddWord())) { + gamedetails_tv_download.setText("下载《" + entity.getName() + + "》"); + } else { + gamedetails_tv_download.setText("下载《" + entity.getName() + + "》" + entity.getDownloadAddWord()); + } + } + } + + if (concernManager.isConcern(entity.getId())) { + top_tv_attention.setText("取消关注"); + top_tv_attention.setBackgroundResource(R.drawable.border_red_bg); + top_tv_attention.setTextColor(0xffbc2132); + } else { + top_tv_attention.setText("关注"); + top_tv_attention + .setBackgroundResource(R.drawable.textview_red_style); + top_tv_attention.setTextColor(0xffffffff); + } + + ImageUtils.getInstance(this).display(entity.getIcon(), top_iv_icon); + + gamedetails_vp_show.setAdapter(new FragmentAdapter( + getSupportFragmentManager())); + gamedetails_vp_show.setOffscreenPageLimit(3); + gamedetails_vp_show.addOnPageChangeListener(this); + + if (currentItem != -1) { + lparams.leftMargin = width * currentItem + width / 4; + gamedetails_slide_line.setLayoutParams(lparams); + titlebar_slide_line.setLayoutParams(lparams); + } else { + int current = getIntent().getIntExtra("current", -1); + if (current != -1) { + gamedetails_vp_show.setCurrentItem(current); + lparams.leftMargin = width * current + width / 4; + gamedetails_slide_line.setLayoutParams(lparams); + titlebar_slide_line.setLayoutParams(lparams); + } + } + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.actionbar_rl_back: + finish(); + break; + case R.id.gamedetails_tv_details: + case R.id.titlebar_tv_details: + gamedetails_vp_show.setCurrentItem(0); + break; + case R.id.gamedetails_tv_information: + case R.id.titlebar_tv_information: + gamedetails_vp_show.setCurrentItem(1); + break; + case R.id.gamedetails_tv_strategy: + case R.id.titlebar_tv_strategy: + gamedetails_vp_show.setCurrentItem(2); + break; + // case R.id.gamedetails_tv_database: + // case R.id.titlebar_tv_database: + // gamedetails_vp_show.setCurrentItem(3); + // break; + case R.id.top_tv_attention: + if ("关注".equals(top_tv_attention.getText().toString())) { + + Map kv = new HashMap(); + kv.put("状态", "关注"); + TCAgent.onEvent(GameDetailsActivity.this, "游戏关注", + entity.getName(), kv); + + Map kv2 = new HashMap(); + kv2.put("点击", "关注"); + TCAgent.onEvent(GameDetailsActivity.this, "插件数据", + entity.getName(), kv2); + + Map map = new HashMap(); + map.put("game", entity.getName()); + map.put("type", "关注"); + map.put("createdOn", System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent(GameDetailsActivity.this, + "concern", map); + + concernManager.addByEntity(entity); + top_tv_attention.setText("取消关注"); + top_tv_attention + .setBackgroundResource(R.drawable.border_red_bg); + top_tv_attention.setTextColor(0xffbc2132); + showSuccessDialog(); + } else { + Map kv2 = new HashMap(); + kv2.put("点击", "取消关注"); + TCAgent.onEvent(GameDetailsActivity.this, "插件数据", + entity.getName(), kv2); + + showCancelDialog(); + } + break; + case R.id.gamedetails_tv_download: + Map kv0 = new HashMap(); + kv0.put("点击", "下载"); + TCAgent.onEvent(GameDetailsActivity.this, "插件数据", entity.getName(), + kv0); + if (entity.getApk() != null && !entity.getApk().isEmpty()) { + if (NetworkUtils.isWifiConnected(this)) { + if (entity.getApk().size() == 1) { + if (gamedetails_tv_download.getText().toString() + .contains("启动")) { + + Map kv = new HashMap(); + kv.put("版本", entity.getApk().get(0).getPlatform()); + TCAgent.onEvent(GameDetailsActivity.this, "游戏启动", + entity.getName(), kv); + + PackageUtils.launchApplicationByPackageName( + getApplicationContext(), entity.getApk() + .get(0).getPackageName()); + } else { + ApkEntity apkEntity = entity.getApk().get(0); + String msg = FileUtils.isCanDownload(apkEntity + .getSize()); + if (TextUtils.isEmpty(msg)) { + Map kv = new HashMap(); + kv.put("版本", apkEntity.getPlatform()); + kv.put("状态", "下载开始"); + TCAgent.onEvent(GameDetailsActivity.this, + "游戏下载", entity.getName(), kv); + + Map kv2 = new HashMap(); + kv2.put("版本", apkEntity.getPlatform()); + kv2.put("状态", "下载开始"); + kv2.put("位置", entrance + "-游戏详情-开始"); + TCAgent.onEvent(GameDetailsActivity.this, + "游戏下载位置", entity.getName(), kv2); + + Map kv3 = new HashMap(); + kv3.put(entrance, "下载数"); + kv3.put(entrance, "下载开始"); + TCAgent.onEvent(GameDetailsActivity.this, + "应用数据", entity.getName(), kv3); + + Map map = new HashMap(); + map.put("game", entity.getName()); + map.put("method", "正常"); + map.put("platform", + PlatformUtils.getInstance( + getApplicationContext()) + .getPlatformName( + entity.getApk().get(0) + .getPlatform())); + map.put("status", "开始"); + map.put("location", "游戏详情:" + entity.getName()); + map.put("from", entrance); + map.put("network", + NetworkUtils.getConnectedType(this)); + map.put("createdOn", + System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent(this, "download", + map); + + DownloadEntry entry = new DownloadEntry(); + + entry.setUrl(apkEntity.getUrl()); + entry.setName(entity.getName()); + entry.setPath(FileUtils.getDownloadPath( + GameDetailsActivity.this, + MD5Utils.getContentMD5(entity.getName() + + "_" + + System.currentTimeMillis()) + + ".apk")); + HashMap meta = new HashMap(); + meta.put("ETag", apkEntity.getEtag()); + meta.put("icon", entity.getIcon()); + meta.put("platform", apkEntity.getPlatform()); + meta.put("gameId", entity.getId()); + meta.put("entrance", entrance + "-游戏详情"); + meta.put("location", "游戏详情:" + entity.getName()); + entry.setMeta(meta); + + DownloadManager.getInstance( + getApplicationContext()).add(entry); + + EventBus.getDefault().post(new EBRedDot(1)); + + gamedetails_tv_download + .setVisibility(View.GONE); + gamedetails_progressbar + .setVisibility(View.VISIBLE); + gamedetails_tv_per.setVisibility(View.VISIBLE); + gamedetails_progressbar.setProgress(0); + gamedetails_tv_per.setText("0.0%"); + + statusMap.put(entry.getUrl(), "downloading"); + + } else { + Toast.makeText(GameDetailsActivity.this, msg, + Toast.LENGTH_SHORT).show(); + } + } + } else { + if (!dismissEntity.isShow()) { + dismissEntity.setShow(true); + DownloadDialog + .getInstance(GameDetailsActivity.this) + .showPopupWindow(v, entity, + entrance + "-游戏详情", handler, + lastTimeMap, statusMap, + "游戏详情:" + entity.getName()); + } + } + } else { + final Dialog dialog = new Dialog(this); + View view = View.inflate(this, + R.layout.search_history_delete_dialog, null); + TextView title = (TextView) view + .findViewById(R.id.delete_dialog_title); + title.setText("警告"); + TextView content = (TextView) view + .findViewById(R.id.delete_dialog_message); + + content.setText("您当前的网络为2G/3G/4G,下载将会消耗移动流量,是否继续下载?"); + + TextView cancel = (TextView) view + .findViewById(R.id.delete_dialog_cancel); + cancel.setText("取消"); + cancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + TextView confirem = (TextView) view + .findViewById(R.id.delete_dialog_confirm); + confirem.setText("继续"); + confirem.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + if (entity.getApk().size() == 1) { + if (gamedetails_tv_download.getText() + .toString().contains("启动")) { + + Map kv = new HashMap(); + kv.put("版本", entity.getApk().get(0) + .getPlatform()); + TCAgent.onEvent(GameDetailsActivity.this, + "游戏启动", entity.getName(), kv); + + PackageUtils + .launchApplicationByPackageName( + getApplicationContext(), + entity.getApk().get(0) + .getPackageName()); + } else { + ApkEntity apkEntity = entity.getApk() + .get(0); + String msg = FileUtils + .isCanDownload(apkEntity.getSize()); + if (TextUtils.isEmpty(msg)) { + Map kv = new HashMap(); + kv.put("版本", apkEntity.getPlatform()); + kv.put("状态", "下载开始"); + TCAgent.onEvent( + GameDetailsActivity.this, + "游戏下载", entity.getName(), kv); + + Map kv2 = new HashMap(); + kv2.put("版本", apkEntity.getPlatform()); + kv2.put("状态", "下载开始"); + kv2.put("位置", entrance + "-游戏详情-开始"); + TCAgent.onEvent( + GameDetailsActivity.this, + "游戏下载位置", entity.getName(), kv2); + + Map kv3 = new HashMap(); + kv3.put("下载", "下载量"); + kv3.put("下载", apkEntity.getPlatform()); + TCAgent.onEvent( + GameDetailsActivity.this, + "插件数据", entity.getName(), kv3); + + Map map = new HashMap(); + map.put("game", entity.getName()); + map.put("method", "正常"); + map.put("platform", + PlatformUtils + .getInstance( + getApplicationContext()) + .getPlatformName( + entity.getApk() + .get(0) + .getPlatform())); + map.put("status", "开始"); + map.put("location", + "游戏详情:" + entity.getName()); + map.put("from", entrance); + map.put("network", + NetworkUtils + .getConnectedType(GameDetailsActivity.this)); + map.put("createdOn", + System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent( + GameDetailsActivity.this, + "download", map); + + DownloadEntry entry = new DownloadEntry(); + + entry.setUrl(apkEntity.getUrl()); + entry.setName(entity.getName()); + entry.setPath(FileUtils + .getDownloadPath( + GameDetailsActivity.this, + MD5Utils.getContentMD5(entity + .getName() + + "_" + + System.currentTimeMillis()) + + ".apk")); + HashMap meta = new HashMap(); + meta.put("ETag", apkEntity.getEtag()); + meta.put("icon", entity.getIcon()); + meta.put("platform", + apkEntity.getPlatform()); + meta.put("gameId", entity.getId()); + meta.put("entrance", entrance + "-游戏详情"); + meta.put("location", + "游戏详情:" + entity.getName()); + entry.setMeta(meta); + + DownloadManager.getInstance( + getApplicationContext()).add( + entry); + + EventBus.getDefault().post( + new EBRedDot(1)); + + gamedetails_tv_download + .setVisibility(View.GONE); + gamedetails_progressbar + .setVisibility(View.VISIBLE); + gamedetails_tv_per + .setVisibility(View.VISIBLE); + gamedetails_progressbar.setProgress(0); + gamedetails_tv_per.setText("0.0%"); + + statusMap.put(entry.getUrl(), + "downloading"); + + } else { + Toast.makeText( + GameDetailsActivity.this, msg, + Toast.LENGTH_SHORT).show(); + } + } + } else { + if (!dismissEntity.isShow()) { + dismissEntity.setShow(true); + DownloadDialog.getInstance( + GameDetailsActivity.this) + .showPopupWindow(v, entity, + entrance + "-游戏详情", + handler, lastTimeMap, + statusMap, + "游戏详情:" + entity.getName()); + } + } + } + }); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.show(); + } + } else { + Toast.makeText(this, "稍等片刻~!游戏正在上传中...", Toast.LENGTH_SHORT) + .show(); + } + break; + case R.id.gamedetails_iv_share: + // http://news.ghzhushou.com + Map kv = new HashMap(); + kv.put("点击", "分享"); + TCAgent.onEvent(this, "插件数据", entity.getName(), kv); + + Map map = new HashMap(); + map.put("location", "分享"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("news", entity.getName()); + map.put("page", "游戏详情"); + DataCollectionManager.onEvent(this, "click-item", map); + + String url = "http://112.124.59.31/game_center/static/game_" + + entity.getId() + ".html"; + showShare(url, entity.getName(), entity.getIcon(), entrance, "游戏"); + break; + case R.id.gamedetails_progressbar: + case R.id.gamedetails_tv_per: + String str = gamedetails_tv_per.getText().toString(); + if ("继续".equals(str)) { + statusMap.put(downloadEntry.getUrl(), "downloading"); + gamedetails_tv_per.setText(downloadEntry.getPercent() + "%"); + Message msg = Message.obtain(); + msg.what = Constants.CONTINUE_DOWNLOAD_TASK; + msg.obj = downloadEntry.getUrl(); + lastTimeMap.put(downloadEntry.getUrl(), + System.currentTimeMillis()); + handler.sendMessageDelayed(msg, 1000); + } else if ("安装".equals(str)) { + String path = downloadEntry.getPath(); + PackageManager manager = new PackageManager( + getApplicationContext()); + if (manager.launchSetup(path)) { + startActivity(PackageUtils.getInstallIntent(path)); + } else { + DialogUtils.showDialog(GameDetailsActivity.this, path); + } + } else { + statusMap.put(downloadEntry.getUrl(), "pause"); + gamedetails_tv_per.setText("继续"); + Message msg = Message.obtain(); + msg.what = Constants.PAUSE_DOWNLOAD_TASK; + msg.obj = downloadEntry.getUrl(); + lastTimeMap.put(downloadEntry.getUrl(), + System.currentTimeMillis()); + handler.sendMessageDelayed(msg, 1000); + } + break; + case R.id.reuse_no_connection: + gamedetails_ll_loading.setVisibility(View.VISIBLE); + reuse_no_connection.setVisibility(View.GONE); + handler.postDelayed(runnable, 1000); + break; + default: + break; + } + } + + private void showSuccessDialog() { + final Dialog dialog = new Dialog(this); + View view = View.inflate(this, R.layout.gamedetails_attention_dialog, + null); + TextView title = (TextView) view.findViewById(R.id.dialog_title); + title.setText("关注成功"); + TextView confirm = (TextView) view.findViewById(R.id.dialog_confirm); + confirm.setText("我知道了"); + confirm.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + TextView message = (TextView) view.findViewById(R.id.dialog_message); + message.setText("游戏的最新动态消息会优先提醒您,包括攻略、资讯、开服信息、开测信息以及最新的插件。"); + view.findViewById(R.id.dialog_rl_cancel).setVisibility(View.GONE); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.show(); + } + + private void showCancelDialog() { + final Dialog dialog = new Dialog(this); + View view = View.inflate(this, R.layout.gamedetails_attention_dialog, + null); + TextView title = (TextView) view.findViewById(R.id.dialog_title); + title.setText("取消关注"); + TextView cancel = (TextView) view.findViewById(R.id.dialog_cancel); + cancel.setText("取消"); + cancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + TextView message = (TextView) view.findViewById(R.id.dialog_message); + + Spanned content = Html + .fromHtml("取消关注游戏后,您将无法及时收到游戏的攻略资讯等最新动态提醒,您确定取消吗?"); + message.setText(content); + + view.findViewById(R.id.dialog_rl_confirm).setVisibility(View.VISIBLE); + view.findViewById(R.id.dialog_confirm).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + + Map kv = new HashMap(); + kv.put("状态", "取消关注"); + TCAgent.onEvent(GameDetailsActivity.this, "游戏关注", + entity.getName(), kv); + + Map map = new HashMap(); + map.put("game", entity.getName()); + map.put("type", "关注"); + map.put("createdOn", System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent(GameDetailsActivity.this, + "concern", map); + + concernManager.deleteConcern(entity.getId()); + dialog.dismiss(); + top_tv_attention.setText("关注"); + top_tv_attention + .setBackgroundResource(R.drawable.textview_red_style); + top_tv_attention.setTextColor(0xffffffff); + } + }); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.show(); + } + + private void showPluginDialog(final String path, final String gameName) { + final Dialog dialog = new Dialog(this); + View view = View.inflate(this, R.layout.search_history_delete_dialog, + null); + TextView title = (TextView) view.findViewById(R.id.delete_dialog_title); + title.setText("插件化安装"); + TextView content = (TextView) view + .findViewById(R.id.delete_dialog_message); + Spanned spanned = Html.fromHtml("您将进行插件化安装以实现插件功能,此过程将" + + "卸载" + "当前使用的版本并" + + "安装插件版本" + "。"); + content.setText(spanned); + + TextView cancel = (TextView) view + .findViewById(R.id.delete_dialog_cancel); + cancel.setText("取消"); + cancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + TextView confirm = (TextView) view + .findViewById(R.id.delete_dialog_confirm); + confirm.setText("确定"); + confirm.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + Map kv6 = new HashMap(); + kv6.put("操作", "一次性完成"); + TCAgent.onEvent(GameDetailsActivity.this, "插件化", gameName, kv6); + if (FileUtils.isEmptyFile(path)) { + Toast.makeText(GameDetailsActivity.this, "解析包错误", + Toast.LENGTH_SHORT).show(); + } else { + MainActivity.uninstallMap.put( + PackageUtils.getPackageNameByPath( + getApplicationContext(), path), path); + startActivity(PackageUtils.getUninstallIntent( + getApplicationContext(), path)); + } + } + }); + + dialog.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + isShowPluginDialog = false; + } + }); + + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.show(); + } + + @Override + public void onPageSelected(int position) { + switch (position) { + case 0: + if (gamedetails_ll_topbar.getVisibility() == View.VISIBLE) { + EventBus.getDefault().post(new EBSlide(0, previous, true)); + } + previous = 0; + + titlebar_tv_details.setClickable(false); + titlebar_tv_information.setClickable(true); + titlebar_tv_strategy.setClickable(true); + // titlebar_tv_database.setClickable(true); + + gamedetails_tv_details.setClickable(false); + gamedetails_tv_information.setClickable(true); + gamedetails_tv_strategy.setClickable(true); + // gamedetails_tv_database.setClickable(true); + + titlebar_tv_details.setTextColor(getResources().getColor( + R.color.theme_colors)); + titlebar_tv_information.setTextColor(0xFF333333); + titlebar_tv_strategy.setTextColor(0xFF333333); + // titlebar_tv_database.setTextColor(0xFF333333); + + gamedetails_tv_details.setTextColor(getResources().getColor( + R.color.theme_colors)); + gamedetails_tv_information.setTextColor(0xFF333333); + gamedetails_tv_strategy.setTextColor(0xFF333333); + // gamedetails_tv_database.setTextColor(0xFF333333); + break; + case 1: + if (gamedetails_ll_topbar.getVisibility() == View.VISIBLE) { + EventBus.getDefault().post(new EBSlide(0, previous, true)); + } + previous = 1; + + titlebar_tv_details.setClickable(true); + titlebar_tv_information.setClickable(false); + titlebar_tv_strategy.setClickable(true); + // titlebar_tv_database.setClickable(true); + + gamedetails_tv_details.setClickable(true); + gamedetails_tv_information.setClickable(false); + gamedetails_tv_strategy.setClickable(true); + // gamedetails_tv_database.setClickable(true); + + titlebar_tv_details.setTextColor(0xFF333333); + titlebar_tv_information.setTextColor(getResources().getColor( + R.color.theme_colors)); + titlebar_tv_strategy.setTextColor(0xFF333333); + // titlebar_tv_database.setTextColor(0xFF333333); + + gamedetails_tv_details.setTextColor(0xFF333333); + gamedetails_tv_information.setTextColor(getResources().getColor( + R.color.theme_colors)); + gamedetails_tv_strategy.setTextColor(0xFF333333); + // gamedetails_tv_database.setTextColor(0xFF333333); + break; + case 2: + if (gamedetails_ll_topbar.getVisibility() == View.VISIBLE) { + EventBus.getDefault().post(new EBSlide(0, previous, true)); + } + previous = 2; + + titlebar_tv_details.setClickable(true); + titlebar_tv_information.setClickable(true); + titlebar_tv_strategy.setClickable(false); + // titlebar_tv_database.setClickable(true); + + gamedetails_tv_details.setClickable(true); + gamedetails_tv_information.setClickable(true); + gamedetails_tv_strategy.setClickable(false); + // gamedetails_tv_database.setClickable(true); + + titlebar_tv_details.setTextColor(0xFF333333); + titlebar_tv_information.setTextColor(0xFF333333); + titlebar_tv_strategy.setTextColor(getResources().getColor( + R.color.theme_colors)); + // titlebar_tv_database.setTextColor(0xFF333333); + + gamedetails_tv_details.setTextColor(0xFF333333); + gamedetails_tv_information.setTextColor(0xFF333333); + gamedetails_tv_strategy.setTextColor(getResources().getColor( + R.color.theme_colors)); + // gamedetails_tv_database.setTextColor(0xFF333333); + break; + case 3: + titlebar_tv_details.setClickable(true); + titlebar_tv_information.setClickable(true); + titlebar_tv_strategy.setClickable(true); + // titlebar_tv_database.setClickable(false); + + gamedetails_tv_details.setClickable(true); + gamedetails_tv_information.setClickable(true); + gamedetails_tv_strategy.setClickable(true); + // gamedetails_tv_database.setClickable(false); + + titlebar_tv_details.setTextColor(0xFF333333); + titlebar_tv_information.setTextColor(0xFF333333); + titlebar_tv_strategy.setTextColor(0xFF333333); + // titlebar_tv_database.setTextColor(getResources().getColor(R.color.theme_colors)); + + gamedetails_tv_details.setTextColor(0xFF333333); + gamedetails_tv_information.setTextColor(0xFF333333); + gamedetails_tv_strategy.setTextColor(0xFF333333); + // gamedetails_tv_database.setTextColor(getResources().getColor(R.color.theme_colors)); + break; + } + } + + @Override + public void onPageScrolled(int position, float positionOffset, + int positionOffsetPixels) { + + if (positionOffset != 0) { + lparams.leftMargin = (int) (width * (positionOffset + position)) + + width / 4; + gamedetails_slide_line.setLayoutParams(lparams); + titlebar_slide_line.setLayoutParams(lparams); + } + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + + private class FragmentAdapter extends FragmentPagerAdapter { + + public FragmentAdapter(FragmentManager fm) { + super(fm); + } + + @Override + public Fragment getItem(int position) { + Fragment fragment; + if (position == 0) { + fragment = new GameDetailsFragment(entity.getId(), + entity.getName(), entrance); + } else if (position == 1) { + fragment = new GameInformationFragment(entity.getId(), + entity.getName(), entrance); + } else { + fragment = new GameStrategyFragment(entity.getId(), + entity.getName(), entrance); + } + return fragment; + } + + @Override + public int getCount() { + return 3; + } + + } + + private void invalidate() { + gamedetails_progressbar + .setProgress((int) (downloadEntry.getPercent() * 10)); + switch (downloadEntry.getStatus()) { + case downloading: + gamedetails_tv_per.setText(downloadEntry.getPercent() + "%"); + break; + case pause: + case neterror: + gamedetails_tv_per.setText("继续"); + break; + case done: + EventBus.getDefault().post( + new EBPutUrl(entity.getApk().get(0).getPackageName(), + downloadEntry.getUrl())); + gamedetails_tv_per.setText("安装"); + break; + case cancel: + case hijack: + gamedetails_tv_download.setVisibility(View.VISIBLE); + gamedetails_progressbar.setVisibility(View.GONE); + gamedetails_tv_per.setVisibility(View.GONE); + if (TextUtils.isEmpty(entity.getDownloadAddWord())) { + gamedetails_tv_download.setText("下载《" + entity.getName() + "》"); + } else { + gamedetails_tv_download.setText("下载《" + entity.getName() + "》" + + entity.getDownloadAddWord()); + } + break; + default: + break; + } + } + + @Override + protected void onResume() { + super.onResume(); + if (entity != null && entity.getApk().size() == 1) { + if (PackageManager.isInstalled(entity.getApk().get(0) + .getPackageName())) { + gamedetails_tv_download.setVisibility(View.VISIBLE); + gamedetails_progressbar.setVisibility(View.GONE); + gamedetails_tv_per.setVisibility(View.GONE); + gamedetails_tv_download.setText("启动《" + entity.getName() + "》"); + if (TextUtils.isEmpty(entity.getDownloadAddWord())) { + gamedetails_tv_download.setText("启动《" + entity.getName() + + "》"); + } else { + gamedetails_tv_download.setText("启动《" + entity.getName() + + "》" + entity.getDownloadAddWord()); + } + } else { + String url = entity.getApk().get(0).getUrl(); + for (DownloadEntry entry : DownloadManager.getInstance( + getApplicationContext()).getAll()) { + if (url.equals(entry.getUrl())) { + downloadEntry = entry; + gamedetails_tv_download.setVisibility(View.GONE); + gamedetails_progressbar.setVisibility(View.VISIBLE); + gamedetails_tv_per.setVisibility(View.VISIBLE); + invalidate(); + break; + } + } + } + } + DownloadManager.getInstance(getApplicationContext()).addObserver( + dataWatcher); + } + + @Override + protected void onPause() { + super.onPause(); + statusMap.clear(); + DownloadManager.getInstance(getApplicationContext()).removeObserver(dataWatcher); + } + + public void onEventMainThread(EBPWDismiss dismiss) { + if (dismissEntity != null) { + dismissEntity.setShow(false); + } + } + + public void onEventMainThread(EBPackage busFour) { + if (entity.getApk().size() == 1) { + String packageName = entity.getApk().get(0).getPackageName(); + if (packageName.equals(busFour.getPackageName())) { + if ("安装".equals(busFour.getType())) { + gamedetails_tv_download.setVisibility(View.VISIBLE); + gamedetails_progressbar.setVisibility(View.GONE); + gamedetails_tv_per.setVisibility(View.GONE); + gamedetails_tv_download.setText("启动《" + entity.getName() + + "》"); + } else if ("卸载".equals(busFour.getType())) { + gamedetails_tv_download.setVisibility(View.VISIBLE); + gamedetails_progressbar.setVisibility(View.GONE); + gamedetails_tv_per.setVisibility(View.GONE); + gamedetails_tv_download.setText("下载《" + entity.getName() + + "》"); + } + } + } + } + + public void onEventMainThread(EBNetworkState busNetworkState) { + if (gameId != null && busNetworkState.isNetworkConnected() + && reuse_no_connection.getVisibility() == View.VISIBLE) { + gamedetails_ll_loading.setVisibility(View.VISIBLE); + reuse_no_connection.setVisibility(View.GONE); + handler.postDelayed(runnable, 1000); + } + } + + public void onEventMainThread(EBMoveTop moveTop) { + if (moveTop.getType().equals("top")) { + if (gamedetails_ll_topbar.getVisibility() != moveTop + .getVisibility()) { + gamedetails_ll_topbar.setVisibility(moveTop.getVisibility()); + } + if (rparams.topMargin != moveTop.getTopMargin()) { + rparams.topMargin = moveTop.getTopMargin(); + gamedetails_ll_top.setLayoutParams(rparams); + } + } else if (moveTop.getType().equals("topbar")) { + gamedetails_vp_show.setCurrentItem(2); + } + } + + Runnable runnable = new Runnable() { + @Override + public void run() { + getGameDetails(); + } + }; + + @Override + public void finish() { + + long end = Calendar.getInstance().getTimeInMillis(); + + int seconds = (int) ((end - start) / 1000); + + String cost = ""; + if (seconds < 5) { + cost = "小于5秒"; + } else if (seconds < 30) { + cost = "5秒-30秒"; + } else if (seconds < 60) { + cost = "30秒-60秒"; + } else { + cost = "大于60秒"; + } + + Map kv = new HashMap(); + kv.put("停留时长", cost); + TCAgent.onEvent(this, "插件数据", entity.getName(), kv); + + if ("主页-最新插件".equals(entrance)) { + Map kv2 = new HashMap(); + kv2.put(entity.getName(), "阅读时长:" + cost); + TCAgent.onEvent(this, "主页数据", "最新插件", kv2); + } else if ("主页-热门卡牌".equals(entrance)) { + Map kv2 = new HashMap(); + kv2.put(entity.getName(), "阅读时长:" + cost); + TCAgent.onEvent(this, "主页数据", "热门卡牌", kv2); + } else if ("主页-新测卡牌".equals(entrance)) { + Map kv2 = new HashMap(); + kv2.put(entity.getName(), "阅读时长:" + cost); + TCAgent.onEvent(this, "主页数据", "新测卡牌", kv2); + } + + Map map = new HashMap(); + map.put("game", entity.getName()); + map.put("time", seconds); + map.put("from", entrance); + map.put("createdOn", System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent(this, "game", map); + + super.finish(); + // if (gameId != null + // && !RunningUtils.isEqualsBase(this, + // MainActivity.class.getName())) { + // Intent intent = new Intent(GameDetailsActivity.this, + // MainActivity.class); + // startActivity(intent); + // } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + isDestroy = true; + gamedetails_tv_details = null; + gamedetails_tv_information = null; + gamedetails_tv_strategy = null; + gamedetails_tv_download = null; + top_tv_name = null; + top_tv_info = null; + top_tv_attention = null; + titlebar_tv_details = null; + titlebar_tv_information = null; + titlebar_tv_strategy = null; + gamedetails_tv_per = null; + actionbar_tv_title = null; + top_iv_icon = null; + gamedetails_iv_share = null; + gamedetails_slide_line = null; + titlebar_slide_line = null; + gamedetails_ll_top = null; + gamedetails_ll_topbar = null; + gamedetails_ll_bottom = null; + gamedetails_ll_loading = null; + reuse_no_connection = null; + gamedetails_vp_show = null; + gamedetails_progressbar = null; + lparams = null; + rparams = null; + concernManager = null; + downloadEntry = null; + entity = null; + gameId = null; + entrance = null; + dismissEntity = null; + lastTimeMap = null; + statusMap = null; + handler = null; + dataWatcher = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/HotCardActivity.java b/app/src/main/java/com/gh/gamecenter/HotCardActivity.java new file mode 100644 index 0000000000..6ecd1e15ea --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/HotCardActivity.java @@ -0,0 +1,293 @@ +package com.gh.gamecenter; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; + +import org.json.JSONArray; + +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.support.v4.util.ArrayMap; +import android.support.v7.widget.DefaultItemAnimator; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.LinearLayout; + +import com.android.volley.NoConnectionError; +import com.android.volley.Response; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.base.BaseActivity; +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.common.util.DownloadItemUtils; +import com.gh.common.util.TimestampUtils; +import com.gh.common.view.VerticalItemDecoration; +import com.gh.download.DataWatcher; +import com.gh.download.DownloadEntry; +import com.gh.download.DownloadManager; +import com.gh.gamecenter.adapter.HotCardAdapter; +import com.gh.gamecenter.db.info.GameInfo; +import com.gh.gamecenter.entity.ApkEntity; +import com.gh.gamecenter.entity.DismissEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.eventbus.EBPWDismiss; +import com.gh.gamecenter.eventbus.EBPackage; +import com.gh.gamecenter.manager.GameManager; +import com.gh.gamecenter.plugin.Plugin2Fragment; +import com.gh.gamecenter.volley.extended.JsonArrayExtendedRequest; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +public class HotCardActivity extends BaseActivity { + + private RecyclerView hotcard_list; + private HotCardAdapter adapter; + private LinearLayout hotcard_ll_loading; + + // 黄壮华 添加 记录信息的map 修改2015/8/15 + private ArrayMap locationMap; + private ArrayMap> gameMap; + private ArrayMap> platformMap; + private ArrayMap nameMap; + + private boolean isEverpause = false; + private boolean isDestroy = false; + + private ArrayMap lastTimeMap; + private ArrayMap statusMap; + + private DismissEntity dismissEntity; + + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (!isDestroy) { + if (msg.what == Constants.DOWNLOAD_ROLL) { + String name = (String) msg.obj; + if (platformMap != null) { + LinkedBlockingQueue queue = platformMap + .get(name); + if (queue.size() > 1) { + queue.offer(queue.poll()); + Message msg2 = Message.obtain(); + msg2.obj = name; + msg2.what = Constants.DOWNLOAD_ROLL; + sendMessageDelayed(msg2, 3000); + } + } + } else if (msg.what == Constants.CONTINUE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + DownloadManager.getInstance(HotCardActivity.this) + .resume(url); + } + } else if (msg.what == Constants.PAUSE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + DownloadManager.getInstance(HotCardActivity.this) + .pause(url); + } + } + } + } + }; + + // 黄壮华 添加观察者 修改2015/8/15 + private DataWatcher dataWatcher = new DataWatcher() { + + @Override + public void onDataChanged( + HashMap downloadingEntries) { + for (java.util.Map.Entry entry : downloadingEntries + .entrySet()) { + DownloadEntry downloadEntry = entry.getValue(); + + Integer location = locationMap.get(downloadEntry.getName()); + if (location != null) { + int index = location.intValue(); + + GameEntity detailedEntity = adapter.getList().get(index); + + if (detailedEntity != null) { + DownloadItemUtils.processDate(detailedEntity, + downloadEntry, platformMap, handler, adapter, + index, statusMap); + } + + } + } + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + View contentView = View.inflate(this, R.layout.activity_hotcard, null); + + init(contentView, "热门卡牌"); + + dismissEntity = new DismissEntity(false); + + lastTimeMap = new ArrayMap(); + statusMap = new ArrayMap(); + locationMap = new ArrayMap(); + gameMap = new ArrayMap>(); + platformMap = new ArrayMap>(); + nameMap = new ArrayMap(); + + hotcard_list.setHasFixedSize(true); + hotcard_list.setLayoutManager(new LinearLayoutManager(this)); + hotcard_list.setItemAnimator(new DefaultItemAnimator()); + + // 黄壮华 添加 初始化游戏状态 修改2015/8/21 + DownloadItemUtils.initializeGameMap(this, gameMap); + + // 黄壮华 传递引用 修改2015/8/15 + adapter = new HotCardAdapter(this, platformMap, handler, lastTimeMap, + statusMap, dismissEntity); + hotcard_list.setAdapter(adapter); + hotcard_list.addItemDecoration(new VerticalItemDecoration(this, 1)); + + addList(); + + } + + private void addList() { + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + + "v1d45/game/remenkapai", Constants.GAME_CD), + new Response.Listener() { + + @Override + public void onResponse(JSONArray response) { + processingData(response); + } + + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + // 无网络连接 + if (error.getClass().equals(NoConnectionError.class)) { + + } + } + + }); + AppController.addToRequestQueue(request, Plugin2Fragment.class); + } + + private void processingData(JSONArray response) { + Type listType = new TypeToken>() { + }.getType(); + Gson gson = new Gson(); + GameManager manager = new GameManager(getApplicationContext()); + List gameList = gson + .fromJson(response.toString(), listType); + if (gameList != null && !gameList.isEmpty()) { + for (GameEntity entity : gameList) { + // 黄壮华 初始化游戏状态 修改2015/8/15 + entity.setEntryMap(gameMap.get(entity.getName())); + adapter.getList().add(entity); + adapter.notifyItemInserted(adapter.getList().size() - 1); + for (ApkEntity apkEntity : entity.getApk()) { + manager.addOrUpdate(new GameInfo( + apkEntity.getPackageName(), entity.getId(), entity + .getName())); + } + } + } + + // 黄壮华 获取游戏位置信息 修改2015/8/15 + for (int i = 0, size = adapter.getList().size(); i < size; i++) { + GameEntity entity = adapter.getList().get(i); + locationMap.put(entity.getName(), i); + for (ApkEntity apkEntity : entity.getApk()) { + nameMap.put(apkEntity.getPackageName(), entity.getName()); + } + } + + hotcard_list.setVisibility(View.VISIBLE); + hotcard_ll_loading.setVisibility(View.GONE); + } + + public void onEventMainThread(EBPWDismiss dismiss) { + if (dismissEntity != null) { + dismissEntity.setShow(false); + } + } + + public void onEventMainThread(EBPackage busFour) { + String name = nameMap.get(busFour.getPackageName()); + if (name != null) { + int location = locationMap.get(name); + if ("安装".equals(busFour.getType())) { + GameEntity entity = adapter.getList().get(location); + for (ApkEntity apkEntity : entity.getApk()) { + if (apkEntity.getPackageName().equals( + busFour.getPackageName())) { + entity.getEntryMap().remove(apkEntity.getPlatform()); + adapter.notifyItemChanged(location); + break; + } + } + } else if ("卸载".equals(busFour.getType())) { + adapter.notifyItemChanged(location); + } + } + } + + @Override + public void onResume() { + super.onResume(); + if (isEverpause) { + // 黄壮华 添加 初始化游戏状态 修改2015/8/21 + DownloadItemUtils.initializeGameMap(this, gameMap); + List entities = new ArrayList(); + for (GameEntity entity : adapter.getList()) { + entity.setEntryMap(gameMap.get(entity.getName())); + entities.add(entity); + } + adapter.setList(entities); + } + isEverpause = false; + DownloadManager.getInstance(getApplicationContext()).addObserver( + dataWatcher); + } + + @Override + public void onPause() { + super.onPause(); + isEverpause = true; + statusMap.clear(); + DownloadManager.getInstance(getApplicationContext()).removeObserver( + dataWatcher); + } + + @Override + public void onDestroy() { + super.onDestroy(); + isDestroy = true; + AppController.canclePendingRequests(Plugin2Fragment.class); + hotcard_list = null; + adapter = null; + hotcard_ll_loading = null; + locationMap = null; + gameMap = null; + platformMap = null; + nameMap = null; + lastTimeMap = null; + statusMap = null; + dismissEntity = null; + handler = null; + dataWatcher = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/MainActivity.java b/app/src/main/java/com/gh/gamecenter/MainActivity.java new file mode 100644 index 0000000000..d945c87197 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/MainActivity.java @@ -0,0 +1,1153 @@ +package com.gh.gamecenter; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Type; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import android.app.Dialog; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.ApplicationInfo; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.SystemClock; +import android.support.v4.app.FragmentTransaction; +import android.support.v4.app.NotificationCompat; +import android.support.v4.util.ArrayMap; +import android.text.Html; +import android.text.Spanned; +import android.text.TextUtils; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.Window; +import android.widget.ImageView; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.volley.Request.Method; +import com.android.volley.Response; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.base.BaseFragmentActivity; +import com.gh.common.constant.Config; +import com.gh.common.util.FileUtils; +import com.gh.common.util.MD5Utils; +import com.gh.common.util.NetworkUtils; +import com.gh.common.util.PackageUtils; +import com.gh.common.util.PlatformUtils; +import com.gh.common.util.RunningUtils; +import com.gh.common.util.SpeedUtils; +import com.gh.common.util.Utils; +import com.gh.download.DataWatcher; +import com.gh.download.DownloadEntry; +import com.gh.download.DownloadManager; +import com.gh.download.DownloadStatus; +import com.gh.gamecenter.db.info.ConcernInfo; +import com.gh.gamecenter.db.info.GameInfo; +import com.gh.gamecenter.db.info.SuspectedGameInfo; +import com.gh.gamecenter.entity.AppEntity; +import com.gh.gamecenter.entity.GameUpdateEntity; +import com.gh.gamecenter.eventbus.EBPackage; +import com.gh.gamecenter.eventbus.EBPutUrl; +import com.gh.gamecenter.eventbus.EBRedDot; +import com.gh.gamecenter.eventbus.EBShowDialog; +import com.gh.gamecenter.eventbus.EBSkipNewPlugin; +import com.gh.gamecenter.eventbus.EBTopState; +import com.gh.gamecenter.eventbus.EBUISwitch; +import com.gh.gamecenter.home.HomeFragment; +import com.gh.gamecenter.manager.ConcernManager; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.manager.FilterManager; +import com.gh.gamecenter.manager.GameManager; +import com.gh.gamecenter.manager.PackageManager; +import com.gh.gamecenter.manager.SuspectedGameManager; +import com.gh.gamecenter.personal.PersonalFragment; +import com.gh.gamecenter.plugin.PluginFragment; +import com.gh.gamecenter.volley.extended.JsonArrayExtendedRequest; +import com.gh.gamecenter.volley.extended.JsonObjectExtendedRequest; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.tendcloud.tenddata.TCAgent; + +import de.greenrobot.event.EventBus; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @update 2015-8-11 + * @des 项目的主Activity,3个Fragment都嵌入在这里。 + */ +public class MainActivity extends BaseFragmentActivity implements + OnClickListener { + + public static ArrayMap uninstallMap; + public static String searchHint; + + private HomeFragment home1Fragment; + private PluginFragment pluginFragmentActivity; + private PersonalFragment home3Fragment; + private View home1Layout, home2Layout, home3Layout; + private ImageView home1Image, home2Image, home3Image; + private TextView home1Title, home2Title, home3Title; + + private SharedPreferences sp; + + private ArrayMap entryMap; + private ArrayMap doneMap; + + private boolean isFirst; + private boolean isDestroy = false; + private boolean isShowDownload = false; + + private Dialog dialog; + private ProgressBar app_pb_progress; + private TextView app_tv_speed; + private TextView app_tv_percent; + private TextView app_btn_cancel; + private AppEntity appEntity; + + // 黄壮华 添加观察者 修改2015/8/15 + private DataWatcher dataWatcher = new DataWatcher() { + @Override + public void onDataChanged( + HashMap downloadingEntries) { + for (Map.Entry entry : downloadingEntries + .entrySet()) { + final DownloadEntry downloadEntry = entry.getValue(); + // 链接被劫持 + if (DownloadStatus.hijack.equals(downloadEntry.getStatus())) { + // 删除任务 + DownloadManager.getInstance(getApplicationContext()).cancel(downloadEntry.getUrl()); + // 弹出提示框 + EventBus.getDefault().post(new EBShowDialog("hijack")); + continue; + } + if (downloadEntry.getName().contains("光环助手") && isShowDownload) { + app_tv_speed.setText(SpeedUtils.getSpeed(downloadEntry + .getSpeed()) + + "(剩" + + SpeedUtils.getRemainTime(downloadEntry.getSize(), + downloadEntry.getProgress(), + downloadEntry.getSpeed() * 1024) + ")"); + app_pb_progress.setProgress((int) (downloadEntry + .getPercent() * 10)); + app_tv_percent.setText(downloadEntry.getPercent() + "%"); + if (DownloadStatus.done.equals(downloadEntry.getStatus())) { + DownloadManager.getInstance(getApplicationContext()) + .cancel(downloadEntry.getUrl(), false); + dialog.dismiss(); + isShowDownload = false; + } + } + if (DownloadStatus.done.equals(downloadEntry.getStatus())) { + if (doneMap.get(downloadEntry.getUrl()) == null) { + doneMap.put(downloadEntry.getUrl(), "done"); + if (downloadEntry.getName().contains("光环助手")) { + TCAgent.onEvent(MainActivity.this, "软件更新", "下载完成"); + startActivity(PackageUtils + .getInstallIntent(downloadEntry.getPath())); + if (appEntity != null && appEntity.isIs_force()) { + finish(); + } + } else { + + Map kv = new HashMap(); + kv.put("版本", downloadEntry.getMeta() + .get("platform")); + kv.put("状态", "下载完成"); + + String isUpdate = downloadEntry.getMeta().get( + "isUpdate"); + String entrance = downloadEntry.getMeta().get( + "entrance"); + if (isUpdate != null && "true".equals(isUpdate)) { + TCAgent.onEvent(MainActivity.this, "游戏更新", + downloadEntry.getName(), kv); + } else { + TCAgent.onEvent(MainActivity.this, "游戏下载", + downloadEntry.getName(), kv); + + Map kv2 = new HashMap(); + kv2.put("版本", + downloadEntry.getMeta().get("platform")); + kv2.put("状态", "下载完成"); + kv2.put("位置", entrance + "-完成"); + TCAgent.onEvent(MainActivity.this, "游戏下载位置", + downloadEntry.getName(), kv2); + } + if (downloadEntry.getMeta().get("isPlugin") != null) { + Map kv6 = new HashMap(); + kv6.put("下载", "下载完成"); + kv6.put("版本", + downloadEntry.getMeta().get("platform")); + TCAgent.onEvent(MainActivity.this, "插件化", + downloadEntry.getName(), kv6); + } + + Map map = new HashMap(); + map.put("game", downloadEntry.getName()); + if (downloadEntry.getMeta().get("isPlugin") != null) { + map.put("method", "插件化"); + } else { + map.put("method", "正常"); + } + map.put("platform", + PlatformUtils.getInstance( + getApplicationContext()) + .getPlatformName( + downloadEntry.getMeta() + .get("platform"))); + map.put("status", "完成"); + map.put("location", + downloadEntry.getMeta().get("location")); + map.put("from", entrance); + map.put("network", NetworkUtils + .getConnectedType(MainActivity.this)); + map.put("createdOn", + System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent(MainActivity.this, + "download", map); + + entryMap.put(PackageUtils.getPackageNameByPath( + getApplicationContext(), + downloadEntry.getPath()), downloadEntry + .getUrl()); + + if (RunningUtils + .isApplicationBroughtToBackground(getApplicationContext())) { + if (downloadEntry.getMeta().get("isPlugin") != null) { + NotificationManager nManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + + String path = downloadEntry.getPath(); + Intent intent = new Intent(); + intent.putExtra("path", path); + intent.setAction("com.gh.gamecenter.UNINSTALL"); + PendingIntent pendingIntent = PendingIntent + .getBroadcast(MainActivity.this, 0, + intent, + PendingIntent.FLAG_ONE_SHOT); + + String platform = PlatformUtils + .getInstance( + getApplicationContext()) + .getPlatformName( + downloadEntry.getMeta() + .get("platform")); + String title = downloadEntry.getName() + + " - " + platform; + + Notification notification = new NotificationCompat.Builder( + MainActivity.this) + .setSmallIcon(R.drawable.logo) + .setTicker(title) + .setContentTitle(title) + .setContentText("下载完成,点击继续插件化。") + .setContentIntent(pendingIntent) + .build(); + + notification.defaults = Notification.DEFAULT_SOUND;// 添加系统默认声音 + notification.flags |= Notification.FLAG_AUTO_CANCEL; // FLAG_AUTO_CANCEL表明当通知被用户点击时,通知将被清除。 + nManager.notify( + ((int) System.currentTimeMillis() / 1000), + notification); + + uninstallMap.put(PackageUtils + .getPackageNameByPath( + getApplicationContext(), + path), path); + } + } else { + String platform = PlatformUtils.getInstance( + getApplicationContext()) + .getPlatformName( + downloadEntry.getMeta().get( + "platform")); + if (platform != null) { + String msg = downloadEntry.getName() + + " - " + platform; + if (downloadEntry.getMeta().get("isPlugin") != null) { + msg = msg + " - 插件化安装包下载完成"; + } else { + msg = msg + " - 下载完成"; + } + Toast.makeText(getApplicationContext(), + msg, Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText( + getApplicationContext(), + downloadEntry.getName() + " - 下载完成", + Toast.LENGTH_SHORT).show(); + } + if (downloadEntry.getMeta().get("isPlugin") == null) { + if (sp.getBoolean("autoinstall", true)) { + if (FileUtils.isEmptyFile(entry + .getValue().getPath())) { + Toast.makeText( + getApplicationContext(), + "解析包错误", Toast.LENGTH_SHORT) + .show(); + } else { + PackageManager manager = new PackageManager( + getApplicationContext()); + if (manager.launchSetup(entry + .getValue().getPath())) { + startActivity(PackageUtils + .getInstallIntent(downloadEntry + .getPath())); + } else { + // 记录自动弹出卸载框 + // 弹出卸载提示框 + EventBus.getDefault().post(new EBShowDialog("delete", downloadEntry + .getPath())); + } + } + } + } + + } + + // 统计下载完成 + uploadData(downloadEntry.getMeta().get("gameId"), + downloadEntry.getMeta().get("platform")); + } + } else { + Utils.log("It is already done!"); + TCAgent.onEvent( + MainActivity.this, + "多次弹框数据", + downloadEntry.getName() + + "-" + + downloadEntry.getMeta().get( + "platform")); + } + } else { + if (doneMap.containsKey(downloadEntry.getUrl())) { + doneMap.remove(downloadEntry.getUrl()); + } + } + } + } + }; + + /* + * 黄壮华 按连续按返回键两次才退出应用 + */ + private long[] mHits = new long[2]; + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) { + System.arraycopy(mHits, 1, mHits, 0, mHits.length - 1); + mHits[mHits.length - 1] = SystemClock.uptimeMillis(); + if (mHits[0] >= (SystemClock.uptimeMillis() - 1000)) { + finish(); + } else { + Toast.makeText(this, "再按一次退出", Toast.LENGTH_SHORT).show(); + return true; + } + } + return super.onKeyDown(keyCode, event); + } + + private Handler handler = new Handler(); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + View contentView = View.inflate(this, R.layout.activity_main, null); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + setTheme(R.style.AppTheme); + setTranslucentStatus(true); + } + + setContentView(contentView); + + initViews(); + setTabSelection(0); + + entryMap = new ArrayMap(); + doneMap = new ArrayMap(); + uninstallMap = new ArrayMap(); + + isFirst = true; + + getSearchHints(); + + sp = getSharedPreferences(Config.PREFERENCE, Context.MODE_PRIVATE); + + if (!sp.getBoolean("isFirstLaunch", true) + && sp.getBoolean("autoupdate", true)) { + checkUpdate(); + } + + if (sp.getBoolean("isFirstLaunch", true)) { + getPluginUpdate(); + getDisclaimer(true); + sp.edit().putBoolean("isFirstLaunch", false).apply(); + } else { + getDisclaimer(false); + handler.postDelayed(runnable, 500); + } + + // 初始化PlatformUtils + PlatformUtils.getInstance(getApplicationContext()); + + DownloadManager.getInstance(this).addObserver(dataWatcher); + + handler.postDelayed(new Runnable() { + @Override + public void run() { + ArrayList concernList = new ArrayList(); + ConcernManager concernManager = new ConcernManager( + MainActivity.this); + for (ConcernInfo entity : concernManager.getAllConcern()) { + if (entity.isConcern()) { + concernList.add(entity.getGameName()); + } + } + Map map = new HashMap(); + map.put("type", Build.MODEL); + map.put("system", Build.VERSION.SDK_INT + "=" + + Build.VERSION.RELEASE); + map.put("install", PackageManager.getInstalledList()); + map.put("concern", concernList); + map.put("createdOn", System.currentTimeMillis() / 1000); + DataCollectionManager.upsert(MainActivity.this, "user", map); + } + }, 1000); + } + + // 获取免责声明 + private void getDisclaimer(final boolean isFirst) { + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Config.HOST + "v2/disclaimer", + new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + + Utils.log(response.toString()); + if (!isDestroy) { + try { + boolean isShow = response.getBoolean("isShow"); + sp.edit() + .putBoolean("isShowDisclaimer", isShow) + .apply(); + if (isShow) { + String content = response + .getString("content"); + sp.edit().putString("disclaimer", content) + .apply(); + if (isFirst) { + showDisclaimerDialog(content); + } + } + } catch (JSONException e) { + + e.printStackTrace(); + } + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + + Utils.log(error.toString()); + sp.edit().putBoolean("isShowDisclaimer", false).apply(); + } + }); + AppController.addToRequestQueue(request, MainActivity.class); + } + + // 弹出免责声明的窗口 + private void showDisclaimerDialog(String content) { + final Dialog disclaimerDialog = new Dialog(this); + View view = View + .inflate(this, R.layout.setting_disclaimer_dialog, null); + TextView title = (TextView) view + .findViewById(R.id.disclaimer_dialog_title); + title.setText("免责声明"); + TextView message = (TextView) view + .findViewById(R.id.disclaimer_dialog_message); + Spanned spanned = Html.fromHtml(content); + message.setText(spanned); + view.findViewById(R.id.disclaimer_dialog_confirm).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + disclaimerDialog.dismiss(); + } + }); + disclaimerDialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + disclaimerDialog.setContentView(view); + disclaimerDialog.show(); + } + + Runnable runnable = new Runnable() { + @Override + public void run() { + String from = getIntent().getStringExtra("from"); + if (!TextUtils.isEmpty(from)) { + if (from.equals("plugin")) { + String packageName = getIntent().getStringExtra( + "packageName"); + Intent intent = new Intent(MainActivity.this, + DownloadManagerActivity.class); + intent.putExtra("currentItem", 1); + intent.putExtra("packageName", packageName); + startActivity(intent); + } else if (from.equals("mipush_news")) { + Intent intent = new Intent(MainActivity.this, + NewsActivity.class); + intent.putExtra("entrance", "小米推送"); + intent.putExtra("entity", + getIntent().getSerializableExtra("entity")); + startActivity(intent); + } else if (from.equals("mipush_new_game")) { + Intent intent = new Intent(MainActivity.this, + GameDetailsActivity.class); + intent.putExtra("entrance", "小米推送"); + startActivity(intent); + } else if (from.equals("mipush_plugin")) { + try { + JSONObject jsonObject = new JSONObject(getIntent() + .getStringExtra("data")); + JSONArray jsonArray = jsonObject.getJSONArray("apk"); + ArrayList list = new ArrayList(); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject apk = jsonArray.getJSONObject(i); + String packageName = apk.getString("package"); + if (PackageManager.isInstalled(packageName)) { + // 判断是否gh_version是否相同 + String gh_version = (String) PackageUtils + .getMetaData(getApplicationContext(), + packageName, "gh_version"); + if (gh_version != null) { + gh_version = gh_version.substring(2); + // 判断gh_version是否相同 + if (gh_version.equals(apk + .getString("gh_version"))) { + // 判断version是否相同 + String version = PackageUtils + .getVersionByPackage( + getApplicationContext(), + packageName); + if (version.equals(apk + .getString("version"))) { + // 版本相同,无需显示插件更新,继续查看是否有可更新的游戏包 + continue; + } + } + } + list.add(packageName); + } + } + Intent intent = new Intent(MainActivity.this, + DownloadManagerActivity.class); + intent.putExtra("currentItem", 1); + intent.putExtra("isPushIntent", true); + startActivity(intent); + } catch (JSONException e) { + + e.printStackTrace(); + } + } else if (from.equals("plugin_install")) { + Intent intent = new Intent(MainActivity.this, + DownloadManagerActivity.class); + intent.putExtra("currentItem", 0); + intent.putExtra("path", getIntent().getStringExtra("path")); + startActivity(intent); + } + } + } + }; + + private void getSearchHints() { + final String url = Config.HOST + "v1d45/search/game/default"; + JsonArrayExtendedRequest searchRequst = new JsonArrayExtendedRequest( + url, new Response.Listener() { + @Override + public void onResponse(JSONArray response) { + if (!isDestroy) { + Type listType = new TypeToken>() { + }.getType(); + Gson gson = new Gson(); + List searchHintList = gson.fromJson( + response.toString(), listType); + if (searchHintList != null + && !searchHintList.isEmpty()) { + searchHint = searchHintList.get(0); + EventBus.getDefault().post( + new EBTopState("搜索", searchHintList + .get(0))); + } + } + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + Utils.log("error = " + error.toString()); + } + }); + AppController.addToRequestQueue(searchRequst, MainActivity.class); + } + + private void checkUpdate() { + String TD_CHANNEL_ID = (String) PackageUtils.getMetaData(this, + getPackageName(), "TD_CHANNEL_ID"); + String url = Config.HOST + "v2/version?version_name=" + + PackageUtils.getVersion(getApplicationContext()) + + "&channel=" + TD_CHANNEL_ID; + JsonObjectExtendedRequest updateRequest = new JsonObjectExtendedRequest( + url, new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + + Utils.log("update=" + response.toString()); + if (!isDestroy) { + if (response.length() != 0) { + Gson gson = new Gson(); + appEntity = gson.fromJson(response.toString(), + AppEntity.class); + + float version = Float.valueOf(appEntity + .getVersion()); + float currentVersion = Float.valueOf(PackageUtils + .getVersion(getApplicationContext())); + + if (version > currentVersion) { + // 光环助手 有更新 + GameUpdateEntity game = new GameUpdateEntity(); + game.setName("光环助手V" + + appEntity.getVersion()); + game.setPackageName(getPackageName()); + game.setSize(appEntity.getSize()); + game.setVersion(appEntity.getVersion()); + game.setUrl(appEntity.getUrl()); + game.setPlatform("官方版"); + PackageManager.addUpdate(0, game); + EventBus.getDefault() + .post(new EBRedDot(-1)); + + String updateMD5 = MD5Utils.getUpdateMD5( + appEntity.getUrl(), + appEntity.getContent()); + + if (appEntity.isIs_force()) { + // 强制更新 + showUpdateDialog(updateMD5); + } else { + // 非强制更新 + if ("EVERY_TIME_OPEN".equals(appEntity + .getAlet_type())) { + // 每次都提示 + showUpdateDialog(updateMD5); + } else { + // 一天提示一次 + String showUpdateTime = sp + .getString( + "show_update_tiem", + null); + SimpleDateFormat format = new SimpleDateFormat( + "yyyy-MM-dd", Locale + .getDefault()); + String today = format + .format(new Date()); + if (!today.equals(showUpdateTime)) { + sp.edit() + .putString( + "show_update_tiem", + today).apply(); + showUpdateDialog(updateMD5); + } + } + } + } + } + } + + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + + Utils.log("update=" + error.toString()); + } + }); + AppController.addToRequestQueue(updateRequest, MainActivity.class); + } + + private void showUpdateDialog(final String md5) { + dialog = new Dialog(this); + View view = View.inflate(this, R.layout.search_history_delete_dialog, + null); + TextView title = (TextView) view.findViewById(R.id.delete_dialog_title); + title.setText("更新"); + TextView content = (TextView) view + .findViewById(R.id.delete_dialog_message); + + Spanned dialogContent = Html + .fromHtml("

发现新版本!

" + + "更新不会影响用户信息!
" + + "最新版本:V" + + appEntity.getVersion() + + "
" + + "更新包大小:" + + appEntity.getSize() + + "
" + + "更新内容:
" + + appEntity.getContent() + "
" + + "
确定更新吗?"); + + content.setText(dialogContent); + + if (appEntity.isIs_force()) { + dialog.setCanceledOnTouchOutside(false); + dialog.setCancelable(false); + } + view.findViewById(R.id.delete_dialog_cancel).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + if (appEntity.isIs_force()) { + finish(); + } else { + dialog.dismiss(); + } + } + }); + view.findViewById(R.id.delete_dialog_confirm).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + String path = FileUtils.getDownloadPath( + MainActivity.this, + "光环助手V" + appEntity.getVersion() + "_" + md5 + + ".apk"); + File file = new File(path); + if (file.exists() && file.length() > 0) { + startActivity(PackageUtils.getInstallIntent(path)); + } else { + TCAgent.onEvent(MainActivity.this, "软件更新", "下载开始"); + showDownloadDialog(md5); + } + } + }); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.show(); + } + + private void showDownloadDialog(String md5) { + dialog = new Dialog(this); + dialog.setCanceledOnTouchOutside(false); + dialog.setCancelable(false); + dialog.closeOptionsMenu(); + View view = View.inflate(this, R.layout.app_updating_dialog, null); + + app_pb_progress = (ProgressBar) view.findViewById(R.id.app_pb_progress); + app_tv_speed = (TextView) view.findViewById(R.id.app_tv_speed); + app_tv_percent = (TextView) view.findViewById(R.id.app_tv_percent); + app_btn_cancel = (TextView) view.findViewById(R.id.app_btn_cancel); + + app_btn_cancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + DownloadManager.getInstance(getApplicationContext()).cancel( + appEntity.getUrl()); + if (appEntity.isIs_force()) { + finish(); + } else { + dialog.dismiss(); + isShowDownload = false; + } + } + }); + + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.show(); + + isShowDownload = true; + + String path = FileUtils.getDownloadPath(MainActivity.this, "光环助手V" + + appEntity.getVersion() + "_" + md5 + ".apk"); + + File file = new File(path); + + if (file.exists()) { + file.delete(); + } + + DownloadEntry downloadEntry = new DownloadEntry(); + downloadEntry.setUrl(appEntity.getUrl()); + downloadEntry.setName("光环助手V" + appEntity.getVersion()); + downloadEntry.setPath(path); + HashMap meta = new HashMap(); + meta.put("platform", "官方版"); + downloadEntry.setMeta(meta); + + DownloadManager.getInstance(getApplicationContext()).cancel( + downloadEntry.getUrl(), false); + + DownloadManager.getInstance(getApplicationContext()).pauseAll(); + + DownloadManager.getInstance(getApplicationContext()).add(downloadEntry); + } + + // 获取META-INF中的plugin_update 文件,判断是否从游戏插件中下载的app,是则获取游戏id,启动游戏更新,下载该游戏 + private void getPluginUpdate() { + ApplicationInfo appinfo = getApplicationInfo(); + String sourceDir = appinfo.sourceDir; + ZipFile zipfile = null; + try { + zipfile = new ZipFile(sourceDir); + Enumeration entries = zipfile.entries(); + while (entries.hasMoreElements()) { + ZipEntry entry = ((ZipEntry) entries.nextElement()); + String entryName = entry.getName(); + if (entryName.contains("gh_assist")) { + String packageName = entryName.substring(entryName + .lastIndexOf("_") + 1); + Intent intent = new Intent(MainActivity.this, + DownloadManagerActivity.class); + intent.putExtra("currentItem", 1); + intent.putExtra("packageName", packageName); + startActivity(intent); + break; + } + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (zipfile != null) { + try { + zipfile.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + private void initViews() { + home1Layout = findViewById(R.id.home1_layout); + home2Layout = findViewById(R.id.home2_layout); + home3Layout = findViewById(R.id.home3_layout); + home1Image = (ImageView) findViewById(R.id.message_image); + home2Image = (ImageView) findViewById(R.id.contacts_image); + home3Image = (ImageView) findViewById(R.id.news_image); + home1Title = (TextView) findViewById(R.id.message_title); + home2Title = (TextView) findViewById(R.id.contacts_title); + home3Title = (TextView) findViewById(R.id.news_title); + home1Layout.setOnClickListener(this); + home2Layout.setOnClickListener(this); + home3Layout.setOnClickListener(this); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.home1_layout: + EventBus.getDefault().post(new EBUISwitch("MainActivity", 0)); + setTabSelection(0); + break; + case R.id.home2_layout: + EventBus.getDefault().post(new EBUISwitch("MainActivity", 1)); + if (isFirst) { + isFirst = false; + } + setTabSelection(1); + break; + case R.id.home3_layout: + EventBus.getDefault().post(new EBUISwitch("MainActivity", 2)); + setTabSelection(2); + break; + default: + break; + } + } + + private void setTabSelection(int index) { + clearSelection(); + FragmentTransaction transaction = getSupportFragmentManager() + .beginTransaction(); + hideFragments(transaction); + switch (index) { + case 0: + home1Layout.setClickable(false); + home1Image.setImageResource(R.drawable.home1_selected); + home1Title.setTextColor(getResources().getColor( + R.color.theme_colors)); + if (home1Fragment == null) { + home1Fragment = new HomeFragment(); + transaction.add(R.id.main_content, home1Fragment); + } else { + transaction.show(home1Fragment); + } + break; + case 1: + home2Layout.setClickable(false); + home2Image.setImageResource(R.drawable.home2_selected); + home2Title.setTextColor(getResources().getColor( + R.color.theme_colors)); + if (pluginFragmentActivity == null) { + pluginFragmentActivity = new PluginFragment(); + transaction.add(R.id.main_content, pluginFragmentActivity); + } else { + transaction.show(pluginFragmentActivity); + } + break; + case 2: + home3Layout.setClickable(false); + home3Image.setImageResource(R.drawable.home3_selected); + home3Title.setTextColor(getResources().getColor( + R.color.theme_colors)); + if (home3Fragment == null) { + home3Fragment = new PersonalFragment(); + transaction.add(R.id.main_content, home3Fragment); + } else { + transaction.show(home3Fragment); + } + break; + default: + break; + } + transaction.commit(); + } + + /** + * 清除掉所有的选中状态。 + */ + private void clearSelection() { + home1Layout.setClickable(true); + home2Layout.setClickable(true); + home3Layout.setClickable(true); + home1Image.setImageResource(R.drawable.home1_unselected); + home2Image.setImageResource(R.drawable.home2_unselected); + home3Image.setImageResource(R.drawable.home3_unselected); + home1Title.setTextColor(0xFF333333); + home2Title.setTextColor(0xFF333333); + home3Title.setTextColor(0xFF333333); + } + + /** + * 将所有的Fragment都置为隐藏状态。 + */ + private void hideFragments(FragmentTransaction transaction) { + if (home3Fragment != null) { + transaction.hide(home3Fragment); + } + if (pluginFragmentActivity != null) { + transaction.hide(pluginFragmentActivity); + } + if (home1Fragment != null) { + transaction.hide(home1Fragment); + } + } + + private void uploadData(String id, String platform) { + HashMap params = new HashMap(); + params.put("game", id); + params.put("platform", platform); + JSONObject jsonObject = new JSONObject(params); + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Method.POST, Config.HOST + "v2/stat/download", + jsonObject.toString(), new Response.Listener() { + @Override + public void onResponse(JSONObject response) { + + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + + } + }); + AppController.addToRequestQueue(request, MainActivity.class); + } + + public void onEventMainThread(EBPutUrl url) { + entryMap.put(url.getPackageName(), url.getUrl()); + } + + public void onEventMainThread(EBSkipNewPlugin busFive) { + if (busFive.getType() == 0) { + if (isFirst) { + PluginFragment.isFirst = true; + } + onClick(home2Layout); + EventBus.getDefault().post(new EBSkipNewPlugin(1)); + } + } + + public void onEventMainThread(EBPackage busFour) { + String packageName = busFour.getPackageName(); + // 添加进已安装map中 + if ("安装".equals(busFour.getType())) { + PackageManager.addInstalled(packageName); + EventBus.getDefault().post(new EBRedDot(-1)); + } else if ("卸载".equals(busFour.getType())) { + PackageManager.removeInstalled(packageName); + } + if ("安装".equals(busFour.getType())) { + String url = entryMap.get(packageName); + if (url != null) { + entryMap.remove(packageName); + + DownloadEntry downloadEntry = DownloadManager.getInstance( + getApplicationContext()).get(url); + if (downloadEntry != null + && downloadEntry.getMeta().get("isPlugin") != null) { + Map kv6 = new HashMap(); + kv6.put("安装或卸载", "安装完成"); + TCAgent.onEvent(this, "插件化", downloadEntry.getName(), kv6); + } + + // 删除数据库 和 文件 + DownloadManager.getInstance(getApplicationContext()).cancel( + url, sp.getBoolean("autodelete", true)); + } + } else if ("卸载".equals(busFour.getType())) { + for (DownloadEntry downloadEntry : DownloadManager.getInstance( + getApplicationContext()).getAll()) { + if (downloadEntry.getMeta().get("isPlugin") != null + && downloadEntry.getMeta().get("package_name") + .equals(packageName)) { + Map kv6 = new HashMap(); + kv6.put("安装或卸载", "卸载完成"); + TCAgent.onEvent(this, "插件化", downloadEntry.getName(), kv6); + break; + } + } + + String path = uninstallMap.get(packageName); + if (path != null) { + uninstallMap.remove(packageName); + + startActivity(PackageUtils.getInstallIntent(path)); + } + } + if ("安装".equals(busFour.getType())) { + GameManager gameManager = new GameManager(getApplicationContext()); + GameInfo gameEntity = gameManager.findGame(packageName); + if (gameEntity != null) { + ConcernManager concernManager = new ConcernManager( + getApplicationContext()); + concernManager.updateByEntity(gameEntity, true); + } else { + FilterManager filterManager = new FilterManager( + getApplicationContext()); + if (!filterManager.isFilter(packageName)) { + SuspectedGameManager suspectedGameManager = new SuspectedGameManager( + getApplicationContext()); + suspectedGameManager.addGame(new SuspectedGameInfo( + packageName, System.currentTimeMillis())); + } + } + } else if ("卸载".equals(busFour.getType())) { + FilterManager filterManager = new FilterManager( + getApplicationContext()); + if (!filterManager.isFilter(packageName)) { + SuspectedGameManager suspectedGameManager = new SuspectedGameManager( + getApplicationContext()); + suspectedGameManager.deleteSuspectedGame(packageName); + + ConcernManager concernManager = new ConcernManager( + getApplicationContext()); + concernManager.updateByPackageName(packageName); + } + } + if ("卸载".equals(busFour.getType())) { + ArrayList list = PackageManager.getUpdateList(); + GameUpdateEntity game = null; + int index = -1; + for (int i = 0, size = list.size(); i < size; i++) { + game = list.get(i); + if (!game.isPlugin()) { + continue; + } + if (game.getPackageName().equals(packageName)) { + index = i; + break; + } + } + if (index != -1) { + PackageManager.removeUpdateList(packageName); + } + } + + Map map = new HashMap(); + map.put("type", busFour.getType()); + map.put("packageName", busFour.getPackageName()); + map.put("createdOn", System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent(this, "inorunstall", map); + } + + @Override + public void finish() { + // 上传数据 + DataCollectionManager.getInstance(getApplicationContext()) + .statClickData(); + super.finish(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + isDestroy = true; + AppController.canclePendingRequests(HomeFragment.class); + AppController.canclePendingRequests(PluginFragment.class); + DownloadManager.getInstance(this).removeObserver(dataWatcher); + home1Fragment = null; + pluginFragmentActivity = null; + home3Fragment = null; + home1Layout = null; + home2Layout = null; + home3Layout = null; + home1Image = null; + home2Image = null; + home3Image = null; + home1Title = null; + home2Title = null; + home3Title = null; + sp = null; + entryMap = null; + doneMap = null; + dialog = null; + app_pb_progress = null; + app_tv_speed = null; + app_tv_percent = null; + app_btn_cancel = null; + appEntity = null; + handler = null; + dataWatcher = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/MobileActivity.java b/app/src/main/java/com/gh/gamecenter/MobileActivity.java new file mode 100644 index 0000000000..f49a82cda2 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/MobileActivity.java @@ -0,0 +1,492 @@ +package com.gh.gamecenter; + +import java.util.HashMap; +import java.util.regex.Pattern; + +import org.json.JSONException; +import org.json.JSONObject; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.volley.Request.Method; +import com.android.volley.Response; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.base.BaseActivity; +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.common.util.DialogUtils; +import com.gh.common.util.TokenUtils; +import com.gh.common.util.Utils; +import com.gh.gamecenter.entity.UserEntity; +import com.gh.gamecenter.eventbus.EBSms; +import com.gh.gamecenter.volley.extended.JsonObjectExtendedRequest; + +public class MobileActivity extends BaseActivity implements OnClickListener { + + private TextView mobile_tv_title, mobile_tv_hint, mobile_tv_send_again, + mobile_tv_confirm; + private EditText mobile_et_mobile, mobile_et_code; + private ImageView mobile_iv_mobile, mobile_iv_mobile_clean; + private LinearLayout mobile_ll_code; + private RelativeLayout mobile_rl_mobile; + private View mobile_mobile_cutting_line; + + private int countdown = 60; + + private boolean isDestroy = false; + + private UserEntity user; + + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (!isDestroy) { + if (msg.what == 0) { + if (countdown == 0) { + mobile_tv_send_again.setText("重新获取"); + mobile_tv_send_again.setClickable(true); + } else if (countdown > 0) { + mobile_tv_send_again.setText("重新获取(" + countdown-- + + ")"); + sendEmptyMessageDelayed(0, 1000); + } + } + } + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + user = (UserEntity) AppController.get("user", false); + + View contentView = View.inflate(this, R.layout.activity_mobile, null); + + init(contentView, "绑定手机"); + + TextView mobile_tv_account = (TextView) findViewById(R.id.mobile_tv_account); + mobile_tv_account.setText(user.getAccount()); + + mobile_et_mobile.requestFocus(); + mobile_iv_mobile_clean.setOnClickListener(this); + mobile_et_mobile.addTextChangedListener(new TextWatcher() { + + @Override + public void onTextChanged(CharSequence s, int start, int before, + int count) { + + if (s.length() > 0) { + mobile_iv_mobile_clean.setVisibility(View.VISIBLE); + } else { + mobile_iv_mobile_clean.setVisibility(View.GONE); + } + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + + + } + + @Override + public void afterTextChanged(Editable s) { + + + } + }); + + mobile_et_mobile + .setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, + KeyEvent event) { + + if (actionId == EditorInfo.IME_ACTION_DONE) { + String mobileNumber = mobile_et_mobile.getText() + .toString(); + if (TextUtils.isEmpty(mobileNumber)) { + Toast.makeText(MobileActivity.this, "请输入手机号码", + Toast.LENGTH_SHORT).show(); + return true; + } else if (mobileNumber.length() != 11) { + Toast.makeText(MobileActivity.this, "手机号码长度错误", + Toast.LENGTH_SHORT).show(); + return true; + } else if (!Pattern.matches(Constants.REGEX_MOBILE, + mobileNumber)) { + Toast.makeText(MobileActivity.this, "手机号码错误", + Toast.LENGTH_SHORT).show(); + return true; + } else { + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow( + mobile_et_mobile.getWindowToken(), 0); + getCode(mobileNumber); + } + } + return false; + } + }); + + mobile_et_code + .setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, + KeyEvent event) { + + if (actionId == EditorInfo.IME_ACTION_DONE) { + String code = mobile_et_code.getText().toString() + .trim(); + if (TextUtils.isEmpty(code)) { + Toast.makeText(MobileActivity.this, "请输入验证码", + Toast.LENGTH_SHORT).show(); + return true; + } else if (code.length() != 6) { + Toast.makeText(MobileActivity.this, "验证码长度错误", + Toast.LENGTH_SHORT).show(); + return true; + } else { + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow( + mobile_et_code.getWindowToken(), 0); + binding(mobile_et_mobile.getHint().toString(), + code); + } + } + return false; + } + }); + + mobile_tv_send_again.setOnClickListener(this); + mobile_tv_send_again.setClickable(false); + + mobile_tv_confirm.setOnClickListener(this); + } + + Runnable showSoftInput = new Runnable() { + @Override + public void run() { + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(mobile_et_code, InputMethodManager.SHOW_FORCED); + } + }; + + @Override + public void onClick(View v) { + if (v.getId() == R.id.mobile_iv_mobile_clean) { + mobile_et_mobile.setText(""); + } else if (v.getId() == R.id.mobile_tv_confirm) { + String str = mobile_tv_confirm.getText().toString().trim(); + if ("发送验证码".equals(str)) { + String mobileNumber = mobile_et_mobile.getText().toString(); + if (TextUtils.isEmpty(mobileNumber)) { + Toast.makeText(MobileActivity.this, "请输入手机号码", + Toast.LENGTH_SHORT).show(); + } else if (mobileNumber.length() != 11) { + Toast.makeText(MobileActivity.this, "手机号码长度错误", + Toast.LENGTH_SHORT).show(); + } else if (!Pattern.matches(Constants.REGEX_MOBILE, + mobileNumber)) { + Toast.makeText(MobileActivity.this, "手机号码错误", + Toast.LENGTH_SHORT).show(); + } else { + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow( + mobile_et_mobile.getWindowToken(), 0); + getCode(mobileNumber); + } + } else if ("确定绑定号码".equals(str)) { + String code = mobile_et_code.getText().toString().trim(); + if (TextUtils.isEmpty(code)) { + Toast.makeText(MobileActivity.this, "请输入验证码", + Toast.LENGTH_SHORT).show(); + } else if (code.length() != 6) { + Toast.makeText(MobileActivity.this, "验证码长度错误", + Toast.LENGTH_SHORT).show(); + } else { + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow( + mobile_et_code.getWindowToken(), 0); + binding(mobile_et_mobile.getHint().toString(), code); + } + } else if ("确定".equals(str)) { + finish(); + } + } else if (v.getId() == R.id.mobile_tv_send_again) { + getCode(mobile_et_mobile.getHint().toString()); + } + } + + // 绑定手机号码 + private void binding(final String mobileNumber, final String code) { + final Dialog waitDialog = DialogUtils.showWaitDialog( + MobileActivity.this, "绑定中..."); + new Thread() { + @Override + public void run() { + String token = TokenUtils.getToken(MobileActivity.this); + String url = Config.HOST + "v2/user/mobile?time=" + + System.currentTimeMillis(); + HashMap params = new HashMap(); + params.put("code", code); + params.put("mobile_number", mobileNumber); + params.put("type", "binding"); + JSONObject body = new JSONObject(params); + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Method.POST, url, body.toString(), + new Response.Listener() { + @Override + public void onResponse(JSONObject response) { + Utils.log(response.toString()); + waitDialog.dismiss(); + if (!isDestroy) { + try { + if ("success".equals(response + .getString("status"))) { + Toast.makeText(MobileActivity.this, + "绑定成功", Toast.LENGTH_SHORT) + .show(); + mobile_tv_confirm.setText("确定"); + + user.setMobileNumber(mobileNumber + .substring(0, 3) + + "****" + + mobileNumber.substring(7, + 11)); + + mobile_tv_title + .setVisibility(View.VISIBLE); + mobile_tv_hint.setText("您已成功绑定手机" + + user.getMobileNumber()); + mobile_tv_hint + .setTextColor(0xff666666); + + mobile_rl_mobile + .setVisibility(View.GONE); + mobile_ll_code + .setVisibility(View.GONE); + + handler.removeMessages(0); + } + } catch (JSONException e) { + + e.printStackTrace(); + } + } + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + Utils.log(error.toString()); + waitDialog.dismiss(); + try { + if (error.networkResponse != null) { + JSONObject response = new JSONObject( + new String( + error.networkResponse.data)); + if (!response.isNull("reason") + && "MOBILE_NUMBER_ERROR".equals(response + .getString("reason"))) { + Toast.makeText(MobileActivity.this, + "手机号码错误", + Toast.LENGTH_SHORT).show(); + return; + } else if (!response.isNull("reason") + && "CODE_ERROR".equals(response + .getString("reason"))) { + Toast.makeText(MobileActivity.this, + "验证码错误", Toast.LENGTH_SHORT) + .show(); + return; + } else if (!response.isNull("reason") + && "CODE_EXPIRE".equals(response + .getString("reason"))) { + Toast.makeText(MobileActivity.this, + "验证码过期", Toast.LENGTH_SHORT) + .show(); + return; + } + } + } catch (Exception e) { + + e.printStackTrace(); + } + Toast.makeText(MobileActivity.this, "发送失败", + Toast.LENGTH_SHORT).show(); + } + }); + request.addHeader("Auth", token); + AppController.addToRequestQueue(request, + MobileActivity.class); + } + }.start(); + } + + // 获取验证码 + private void getCode(final String mobileNumber) { + final Dialog waitDialog = DialogUtils.showWaitDialog(this, "发送中..."); + new Thread() { + @Override + public void run() { + String url = Config.HOST + "v2/user/mobile/code/" + + mobileNumber + "?time=" + System.currentTimeMillis(); + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + url, new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + + Utils.log(response.toString()); + waitDialog.dismiss(); + if (!isDestroy) { + try { + if ("success".equals(response + .getString("status"))) { + Toast.makeText(MobileActivity.this, + "发送成功", Toast.LENGTH_SHORT) + .show(); + if (mobile_tv_send_again != null) { + mobile_tv_send_again + .setClickable(false); + } + waitDialog.dismiss(); + + mobile_tv_confirm.setText("确定绑定号码"); + + mobile_rl_mobile + .setBackgroundResource(R.drawable.border_input_up); + mobile_et_mobile.setEnabled(false); + mobile_et_mobile.setText(""); + mobile_et_mobile + .setHint(mobileNumber); + mobile_iv_mobile + .setImageResource(R.drawable.register_mobile_up); + mobile_mobile_cutting_line + .setBackgroundColor(0xffDBDBDB); + mobile_iv_mobile_clean + .setVisibility(View.GONE); + + mobile_ll_code + .setVisibility(View.VISIBLE); + countdown = 60; + handler.removeMessages(0); + handler.sendEmptyMessage(0); + + mobile_et_code.requestFocus(); + handler.postDelayed(showSoftInput, + 300); + } + } catch (JSONException e) { + + e.printStackTrace(); + } + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + + Utils.log(error.toString()); + waitDialog.dismiss(); + try { + if (error.networkResponse != null) { + JSONObject response = new JSONObject( + new String( + error.networkResponse.data)); + if (!response.isNull("reason") + && "MOBILE_NUMBER_ERROR".equals(response + .getString("reason"))) { + Toast.makeText(MobileActivity.this, + "手机号码错误", + Toast.LENGTH_SHORT).show(); + return; + } else if (!response.isNull("reason") + && "USER_EXIST".equals(response + .getString("reason"))) { + Toast.makeText(MobileActivity.this, + "用户已存在", Toast.LENGTH_SHORT) + .show(); + return; + } else if (!response.isNull("reason") + && "TIME_IS_NOT".equals(response + .getString("reason"))) { + Toast.makeText(MobileActivity.this, + "稍后再试", Toast.LENGTH_SHORT) + .show(); + return; + } + } + } catch (Exception e) { + + e.printStackTrace(); + } + Toast.makeText(MobileActivity.this, "发送失败", + Toast.LENGTH_SHORT).show(); + } + }); + String token = TokenUtils.getToken(MobileActivity.this); + request.addHeader("Auth", token); + AppController.addToRequestQueue(request, + MobileActivity.class); + } + }.start(); + } + + public void onEventMainThread(EBSms sms) { + if ("身份验证".equals(sms.getType()) && mobile_et_code != null) { + mobile_et_code.setText(sms.getCode()); + } + } + + @Override + public void finish() { + + if (user.getMobileNumber() != null) { + setResult(RESULT_OK); + } + super.finish(); + } + + @Override + protected void onDestroy() { + + super.onDestroy(); + isDestroy = true; + mobile_tv_title = null; + mobile_tv_hint = null; + mobile_tv_send_again = null; + mobile_tv_confirm = null; + mobile_et_mobile = null; + mobile_et_code = null; + mobile_iv_mobile = null; + mobile_iv_mobile_clean = null; + mobile_ll_code = null; + mobile_rl_mobile = null; + mobile_mobile_cutting_line = null; + handler = null; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/ModifyMobileActivity.java b/app/src/main/java/com/gh/gamecenter/ModifyMobileActivity.java new file mode 100644 index 0000000000..57729b3475 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/ModifyMobileActivity.java @@ -0,0 +1,418 @@ +package com.gh.gamecenter; + +import java.util.HashMap; +import java.util.regex.Pattern; + +import org.json.JSONException; +import org.json.JSONObject; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.text.TextUtils; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.volley.Request.Method; +import com.android.volley.Response; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.base.BaseActivity; +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.common.util.DialogUtils; +import com.gh.common.util.TokenUtils; +import com.gh.common.util.Utils; +import com.gh.gamecenter.entity.UserEntity; +import com.gh.gamecenter.eventbus.EBSms; +import com.gh.gamecenter.volley.extended.JsonObjectExtendedRequest; + +public class ModifyMobileActivity extends BaseActivity implements + OnClickListener { + + private TextView modify_tv_title, modify_tv_step_one, mobile_tv_step_two, + mobile_tv_step_three, modify_tv_send_again, modify_tv_confirm, + modify_tv_mobile; + private RelativeLayout modify_rl_mobile; + private ImageView modify_iv_mobile, modify_iv_mobile_clean; + private View modify_mobile_cutting_line; + private EditText modify_et_mobile, modify_et_code; + private LinearLayout modify_ll_code; + + private UserEntity user; + + private int step; + private int countdown; + + private boolean isDestroy = false; + + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (!isDestroy) { + if (msg.what == 0) { + if (countdown == 0) { + modify_tv_send_again.setText("重新获取"); + modify_tv_send_again.setClickable(true); + } else if (countdown > 0) { + modify_tv_send_again.setText("重新获取(" + countdown-- + ")"); + sendEmptyMessageDelayed(0, 1000); + } + } + } + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + user = (UserEntity) AppController.get("user", false); + + View contentView = View.inflate(this, R.layout.activity_modifymobile, + null); + + init(contentView, "更换绑定手机"); + + TextView modify_tv_account = (TextView) findViewById(R.id.modify_tv_account); + modify_tv_account.setText(user.getAccount()); + + modify_tv_mobile.setText(user.getMobileNumber()); + + modify_tv_send_again.setOnClickListener(this); + modify_tv_send_again.setClickable(false); + + modify_tv_confirm.setOnClickListener(this); + + step = 1; + } + + Runnable showSoftInput = new Runnable() { + @Override + public void run() { + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + if (step == 2 || step == 4) { + imm.showSoftInput(modify_et_code, + InputMethodManager.SHOW_FORCED); + } else if (step == 3) { + imm.showSoftInput(modify_et_mobile, + InputMethodManager.SHOW_FORCED); + } + } + }; + + @Override + public void onClick(View v) { + if (v.getId() == R.id.modify_tv_confirm) { + if (step == 1 || step == 3) { + String mobileNumber = modify_et_mobile.getText().toString(); + if (TextUtils.isEmpty(mobileNumber)) { + Toast.makeText(ModifyMobileActivity.this, "请输入手机号码", + Toast.LENGTH_SHORT).show(); + } else if (mobileNumber.length() != 11) { + Toast.makeText(ModifyMobileActivity.this, "手机号码长度错误", + Toast.LENGTH_SHORT).show(); + } else if (!Pattern.matches(Constants.REGEX_MOBILE, + mobileNumber)) { + Toast.makeText(ModifyMobileActivity.this, "手机号码格式错误", + Toast.LENGTH_SHORT).show(); + } else { + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow( + modify_et_mobile.getWindowToken(), 0); + getCode(mobileNumber); + } + } else if (step == 2 || step == 4) { + String code = modify_et_code.getText().toString().trim(); + if (TextUtils.isEmpty(code)) { + Toast.makeText(ModifyMobileActivity.this, "请输入验证码", + Toast.LENGTH_SHORT).show(); + } else if (code.length() != 6) { + Toast.makeText(ModifyMobileActivity.this, "验证码长度错误", + Toast.LENGTH_SHORT).show(); + } else { + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow( + modify_et_code.getWindowToken(), 0); + if (step == 2) { + verifyMobile(modify_et_mobile.getHint().toString(), + code); + } else if (step == 4) { + binding(modify_et_mobile.getHint().toString(), code); + } + } + } else if (step == 0) { + finish(); + } + } else if (v.getId() == R.id.modify_tv_send_again) { + getCode(modify_et_mobile.getText().toString()); + } + } + + private void getCode(final String mobileNumber) { + final Dialog waitDialog = DialogUtils.showWaitDialog(this, "发送中..."); + new Thread() { + @Override + public void run() { + String url = null; + if (step == 1) { + url = Config.HOST + "v2/user/verifymobile/code/" + + mobileNumber + "?time=" + + System.currentTimeMillis(); + } else if (step == 3) { + url = Config.HOST + "v2/user/modifymobile/code/" + + mobileNumber + "?time=" + + System.currentTimeMillis(); + } + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + url, new Response.Listener() { + @Override + public void onResponse(JSONObject response) { + + Utils.log(response.toString()); + waitDialog.dismiss(); + try { + if ("success".equals(response + .getString("status"))) { + Toast.makeText( + ModifyMobileActivity.this, + "发送成功", Toast.LENGTH_SHORT) + .show(); + if (modify_tv_send_again != null) { + modify_tv_send_again + .setClickable(false); + } + if (step == 1) { + step = 2; + } else if (step == 3) { + step = 4; + } + if (step == 2) { + modify_tv_confirm + .setText("验证原绑定号码"); + } else if (step == 4) { + modify_tv_confirm.setText("确定绑定号码"); + } + + modify_rl_mobile + .setBackgroundResource(R.drawable.border_input_up); + modify_et_mobile.setEnabled(false); + modify_et_mobile.setText(""); + modify_et_mobile.setHint(mobileNumber); + modify_iv_mobile + .setImageResource(R.drawable.register_mobile_up); + modify_mobile_cutting_line + .setBackgroundColor(0xffDBDBDB); + modify_iv_mobile_clean + .setVisibility(View.GONE); + + modify_ll_code + .setVisibility(View.VISIBLE); + countdown = 60; + handler.removeMessages(0); + handler.sendEmptyMessage(0); + + modify_et_code.setText(""); + modify_et_code.requestFocus(); + handler.postDelayed(showSoftInput, 300); + } + } catch (JSONException e) { + + e.printStackTrace(); + } + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + + Utils.log(error.toString()); + waitDialog.dismiss(); + } + }); + String token = TokenUtils.getToken(ModifyMobileActivity.this); + request.addHeader("Auth", token); + AppController.addToRequestQueue(request, + ModifyMobileActivity.class); + } + }.start(); + } + + private void verifyMobile(final String mobileNumber, final String code) { + final Dialog waitDialog = DialogUtils.showWaitDialog(this, "验证中..."); + new Thread() { + @Override + public void run() { + String url = Config.HOST + + "v2/user/mobile/verify?mobile_number=" + mobileNumber + + "&code=" + code + "&time=" + + System.currentTimeMillis(); + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + url, new Response.Listener() { + @Override + public void onResponse(JSONObject response) { + + Utils.log(response.toString()); + waitDialog.dismiss(); + try { + if ("success".equals(response + .getString("status"))) { + Toast.makeText( + ModifyMobileActivity.this, + "验证成功", Toast.LENGTH_SHORT) + .show(); + step = 3; + + modify_tv_confirm.setText("发送验证码"); + + modify_tv_step_one + .setTextColor(0xff666666); + mobile_tv_step_three + .setVisibility(View.VISIBLE); + + modify_rl_mobile.setBackgroundResource(R.drawable.border_input_dn); + modify_et_mobile.setEnabled(true); + modify_et_mobile.setText(""); + modify_et_mobile.setHint("请输入新号码"); + modify_iv_mobile + .setImageResource(R.drawable.register_mobile_dn); + modify_mobile_cutting_line + .setBackgroundColor(0xff1BA4FC); + + modify_ll_code.setVisibility(View.GONE); + + mobile_tv_step_two + .setVisibility(View.GONE); + + modify_et_mobile.requestFocus(); + handler.postDelayed(showSoftInput, 300); + } + } catch (JSONException e) { + + e.printStackTrace(); + } + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + + Utils.log(error.toString()); + waitDialog.dismiss(); + } + }); + String token = TokenUtils.getToken(ModifyMobileActivity.this); + request.addHeader("Auth", token); + AppController.addToRequestQueue(request, + ModifyMobileActivity.class); + } + }.start(); + } + + private void binding(final String mobileNumber, final String code) { + final Dialog waitDialog = DialogUtils.showWaitDialog(this, "绑定中..."); + new Thread() { + @Override + public void run() { + String url = Config.HOST + "v2/user/mobile?time=" + + System.currentTimeMillis(); + HashMap params = new HashMap(); + params.put("mobile_number", mobileNumber); + params.put("code", code); + params.put("type", "modify"); + JSONObject body = new JSONObject(params); + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Method.POST, url, body.toString(), + new Response.Listener() { + @Override + public void onResponse(JSONObject response) { + + Utils.log(response.toString()); + waitDialog.dismiss(); + try { + if ("success".equals(response + .getString("status"))) { + step = 0; + + modify_tv_confirm.setText("确定"); + + modify_tv_title.setText("绑定成功"); + modify_tv_title + .setTextColor(0xff1BA4FC); + + user.setMobileNumber(mobileNumber + .substring(0, 3) + + "****" + + mobileNumber.substring(7, 11)); + + modify_tv_step_one.setText("您已成功绑定手机" + + user.getMobileNumber()); + mobile_tv_step_three + .setVisibility(View.GONE); + modify_rl_mobile + .setVisibility(View.GONE); + modify_ll_code.setVisibility(View.GONE); + + modify_tv_mobile.setText(user + .getMobileNumber()); + } + } catch (JSONException e) { + + e.printStackTrace(); + } + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + + Utils.log(error.toString()); + waitDialog.dismiss(); + } + }); + String token = TokenUtils.getToken(ModifyMobileActivity.this); + request.addHeader("Auth", token); + AppController.addToRequestQueue(request, + ModifyMobileActivity.class); + } + }.start(); + } + + public void onEventMainThread(EBSms sms) { + if ("身份验证".equals(sms.getType()) && modify_et_code != null) { + modify_et_code.setText(sms.getCode()); + } else if ("变更验证".equals(sms.getType()) && modify_et_code != null) { + modify_et_code.setText(sms.getCode()); + } + } + + @Override + protected void onDestroy() { + + super.onDestroy(); + isDestroy = true; + modify_tv_title = null; + modify_tv_step_one = null; + mobile_tv_step_two = null; + mobile_tv_step_three = null; + modify_tv_send_again = null; + modify_tv_confirm = null; + modify_tv_mobile = null; + modify_rl_mobile = null; + modify_iv_mobile = null; + modify_iv_mobile_clean = null; + modify_mobile_cutting_line = null; + modify_et_mobile = null; + modify_et_code = null; + modify_ll_code = null; + user = null; + handler = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/NewsActivity.java b/app/src/main/java/com/gh/gamecenter/NewsActivity.java new file mode 100644 index 0000000000..96e3b8d228 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/NewsActivity.java @@ -0,0 +1,2918 @@ +package com.gh.gamecenter; + +import java.io.File; +import java.lang.reflect.Type; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Random; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; +import android.content.res.ColorStateList; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.os.SystemClock; +import android.support.v4.util.ArrayMap; +import android.text.Editable; +import android.text.Html; +import android.text.Spanned; +import android.text.TextUtils; +import android.text.TextUtils.TruncateAt; +import android.text.TextWatcher; +import android.util.DisplayMetrics; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.view.Window; +import android.view.WindowManager; +import android.view.animation.TranslateAnimation; +import android.webkit.JavascriptInterface; +import android.webkit.WebSettings; +import android.webkit.WebSettings.LayoutAlgorithm; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.AbsListView; +import android.widget.BaseAdapter; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.PopupWindow; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.volley.NoConnectionError; +import com.android.volley.Request.Method; +import com.android.volley.Response; +import com.android.volley.TimeoutError; +import com.android.volley.VolleyError; +import com.android.volley.toolbox.DiskBasedCache; +import com.gh.base.AppController; +import com.gh.base.BaseActivity; +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.common.util.DeviceUtils; +import com.gh.common.util.DialogUtils; +import com.gh.common.util.DisplayUtils; +import com.gh.common.util.FileUtils; +import com.gh.common.util.GzipUtils; +import com.gh.common.util.ImageUtils; +import com.gh.common.util.MD5Utils; +import com.gh.common.util.NetworkUtils; +import com.gh.common.util.NewsUtils; +import com.gh.common.util.PackageUtils; +import com.gh.common.util.PlatformUtils; +import com.gh.common.util.TimestampUtils; +import com.gh.common.util.TokenUtils; +import com.gh.common.util.Utils; +import com.gh.common.view.BezelImageView; +import com.gh.common.view.DownloadDialog; +import com.gh.common.view.KeyboardLayout; +import com.gh.common.view.KeyboardLayout.OnKeyboardChangedListener; +import com.gh.download.DataWatcher; +import com.gh.download.DownloadEntry; +import com.gh.download.DownloadManager; +import com.gh.gamecenter.entity.ApkEntity; +import com.gh.gamecenter.entity.CommentEntity; +import com.gh.gamecenter.entity.DismissEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.entity.NewsDetailsEntity; +import com.gh.gamecenter.entity.NewsEntity; +import com.gh.gamecenter.eventbus.EBNetworkState; +import com.gh.gamecenter.eventbus.EBPWDismiss; +import com.gh.gamecenter.eventbus.EBPackage; +import com.gh.gamecenter.eventbus.EBPutUrl; +import com.gh.gamecenter.eventbus.EBRedDot; +import com.gh.gamecenter.manager.ConcernManager; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.manager.PackageManager; +import com.gh.gamecenter.volley.extended.JsonArrayExtendedRequest; +import com.gh.gamecenter.volley.extended.JsonObjectExtendedRequest; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.tendcloud.tenddata.TCAgent; + +import de.greenrobot.event.EventBus; + +/** + * 文章详情页面 要启动该页面 需要传入一下参数 放入 EssayEntity中传过来 文章 id 文章标题 title 文章发表时间 time + * + * @author 黄壮华 + * + */ +public class NewsActivity extends BaseActivity implements OnClickListener { + + private static final String DEFAULT_CACHE_DIR = "volley"; + + private LinearLayout essaydetails_ll_loading, essaydetails_ll_bottom, + reuse_no_connection, essaydetails_ll_comment; + private NewsDetailsEntity entity; + private TextView actionbar_tv_title, essaydetails_tv_download, + essaydetails_tv_per, essaydetails_tv_comment_content, + essaydetails_tv_comment_send; + private ImageView essaydetails_iv_share; + private ProgressBar essaydetails_progressbar; + private GameEntity gameEntity; + private DownloadEntry downloadEntry; + private ListView essaydetails_lv_show; + private ListViewAdapter adapter; + + private String entrance; + private String newsId; + + private long start = 0L; + private int width; + + private boolean isSentReport = false; + private boolean isDestroy = false; + private boolean isShowBottom = false; + private boolean isLoading = true; + private boolean isNetworkError = false; + private boolean isFinish; + + private DismissEntity dismissEntity; + + private ArrayMap lastTimeMap; + private ArrayMap statusMap; + private ArrayMap timeMap; + private ArrayList commentList; + private ArrayMap commentFeedbackMap; + private ArrayMap fullMap; + + private PopupWindow popupWindow; + + private ConcernManager concernManager; + + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (!isDestroy) { + if (msg.what == Constants.CONTINUE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + DownloadManager.getInstance(NewsActivity.this).resume( + url); + } + } else if (msg.what == Constants.PAUSE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + DownloadManager.getInstance(NewsActivity.this).pause( + url); + } + } else if (msg.what == Constants.SEND_NEWS_FEEDBACK) { + String key = (String) msg.obj; + if (System.currentTimeMillis() - timeMap.get(key) >= 1000) { + if (msg.arg1 == 0) { + modifyUserNewsFeedbackVolleyCache("up"); + modifyNewsFeedback(entity.getId(), "up"); + } else if (msg.arg1 == 1) { + modifyUserNewsFeedbackVolleyCache("down"); + modifyNewsFeedback(entity.getId(), "down"); + } else if (msg.arg1 == 2) { + modifyUserNewsFeedbackVolleyCache(null); + cancelNewsFeedback(entity.getId()); + } + } + } else if (msg.what == Constants.SEND_COMMENT_FEEDBACK) { + String key = (String) msg.obj; + if (System.currentTimeMillis() - timeMap.get(key) >= 1000) { + int index = msg.arg2; + CommentEntity commentEntity = null; + commentEntity = commentList.get(index); + final String id = commentEntity.getId(); + if (msg.arg1 == 0) { + modifyUserCommentFeedbackVolleyCache(id, "up"); + modifyCommentFeedback(entity.getId(), id, "up"); + } else if (msg.arg1 == 1) { + modifyUserCommentFeedbackVolleyCache(id, "down"); + modifyCommentFeedback(entity.getId(), id, "down"); + } else if (msg.arg1 == 2) { + modifyUserCommentFeedbackVolleyCache(id, null); + cancelCommentFeedback(entity.getId(), id); + } + } + } + } + } + }; + + private DataWatcher dataWatcher = new DataWatcher() { + @Override + public void onDataChanged( + HashMap downloadingEntries) { + if (gameEntity != null && gameEntity.getApk().size() == 1) { + String url = gameEntity.getApk().get(0).getUrl(); + for (Map.Entry entry : downloadingEntries + .entrySet()) { + if (url.equals(entry.getValue().getUrl())) { + if (!"pause".equals(statusMap.get(entry.getValue() + .getUrl()))) { + downloadEntry = entry.getValue(); + invalidate(); + } + break; + } + } + } + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + View contentView = View.inflate(this, R.layout.activity_essaydetails, + null); + + init(contentView); + + dismissEntity = new DismissEntity(false); + concernManager = new ConcernManager(getApplicationContext()); + + DisplayMetrics outMetrics = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(outMetrics); + width = outMetrics.widthPixels + - DisplayUtils.dip2px(getApplicationContext(), 73); + + RelativeLayout reuse_actionbar = (RelativeLayout) findViewById(R.id.reuse_actionbar); + + View share = View.inflate(this, R.layout.reuse_ico, null); + share.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + String url = "http://news.ghzhushou.com/" + entity.getId() + + ".html"; + showShare(url, entity.getTitle(), gameEntity.getIcon(), + entrance, "新闻"); + } + }); + ((ImageView) share.findViewById(R.id.reuse_iv_ico)) + .setImageResource(R.drawable.essay_share); + RelativeLayout.LayoutParams rparams1 = new RelativeLayout.LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + rparams1.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + rparams1.addRule(RelativeLayout.CENTER_VERTICAL); + rparams1.rightMargin = DisplayUtils.dip2px(getApplicationContext(), 8); + share.setLayoutParams(rparams1); + reuse_actionbar.addView(share); + + View comment = View.inflate(this, R.layout.reuse_ico, null); + comment.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (essaydetails_ll_comment.getVisibility() != View.VISIBLE) { + essaydetails_ll_comment.setVisibility(View.VISIBLE); + essaydetails_ll_bottom.setVisibility(View.GONE); + TranslateAnimation animation = new TranslateAnimation(0, 0, + DisplayUtils.dip2px(getApplicationContext(), 48), 0); + animation.setDuration(500); + essaydetails_ll_comment.startAnimation(animation); + } + essaydetails_lv_show.setSelection(2); + } + }); + ((ImageView) comment.findViewById(R.id.reuse_iv_ico)) + .setImageResource(R.drawable.essay_comment); + RelativeLayout.LayoutParams rparams2 = new RelativeLayout.LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + rparams2.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + rparams2.addRule(RelativeLayout.CENTER_VERTICAL); + rparams2.rightMargin = DisplayUtils.dip2px(getApplicationContext(), 46); + comment.setLayoutParams(rparams2); + reuse_actionbar.addView(comment); + + entrance = (String) getIntent().getExtras().get("entrance"); + newsId = getIntent().getStringExtra("newsId"); + if (newsId == null) { + entity = (NewsDetailsEntity) getIntent().getExtras().get("entity"); + actionbar_tv_title.setText(entity.getType()); + } + + commentList = new ArrayList(); + + lastTimeMap = new ArrayMap(); + statusMap = new ArrayMap(); + fullMap = new ArrayMap(); + + timeMap = new ArrayMap(); + + WebView essaydetails_webView = (WebView) findViewById(R.id.essaydetails_webView); + if (NetworkUtils.isWifiConnected(this)) { + essaydetails_webView.setVisibility(View.INVISIBLE); + if (newsId != null) { + essaydetails_webView.loadUrl("http://news.ghzhushou.com/" + + newsId + ".html"); + } else { + essaydetails_webView.loadUrl("http://news.ghzhushou.com/" + + entity.getId() + ".html"); + } + } else { + essaydetails_webView.setVisibility(View.GONE); + } + + essaydetails_ll_bottom.setOnClickListener(this); + + reuse_no_connection.setOnClickListener(this); + + essaydetails_tv_download.setOnClickListener(this); + + essaydetails_iv_share.setOnClickListener(this); + + essaydetails_progressbar.setOnClickListener(this); + + essaydetails_tv_per.setOnClickListener(this); + + essaydetails_tv_comment_content.setOnClickListener(this); + essaydetails_tv_comment_content + .addTextChangedListener(new TextWatcher() { + + @Override + public void onTextChanged(CharSequence s, int start, + int before, int count) { + + if (s.length() > 0) { + essaydetails_tv_comment_content + .setBackgroundResource(R.drawable.essaydetails_comment_dn); + essaydetails_tv_comment_send.setClickable(true); + essaydetails_tv_comment_send + .setTextColor(0xffffffff); + essaydetails_tv_comment_send + .setBackgroundResource(R.drawable.textview_blue_style); + } else { + essaydetails_tv_comment_content + .setBackgroundResource(R.drawable.essaydetails_comment_up); + essaydetails_tv_comment_send.setClickable(false); + essaydetails_tv_comment_send + .setTextColor(0xff999999); + essaydetails_tv_comment_send + .setBackgroundResource(R.drawable.textview_again_up); + } + int line = essaydetails_tv_comment_content + .getLineCount(); + if (line != 0) { + LinearLayout.LayoutParams lparams = (LinearLayout.LayoutParams) essaydetails_tv_comment_content + .getLayoutParams(); + if (line == 1) { + lparams.height = DisplayUtils.dip2px( + getApplicationContext(), 34); + } else { + lparams.height = DisplayUtils.dip2px( + getApplicationContext(), 20) + + (line > 3 ? 3 : line) + * DisplayUtils.dip2px( + getApplicationContext(), 12); + } + essaydetails_tv_comment_content + .setLayoutParams(lparams); + } + } + + @Override + public void beforeTextChanged(CharSequence s, int start, + int count, int after) { + + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + essaydetails_tv_comment_send.setOnClickListener(this); + essaydetails_tv_comment_send.setClickable(false); + + adapter = new ListViewAdapter(); + essaydetails_lv_show.setAdapter(adapter); + essaydetails_lv_show.setDividerHeight(0); + essaydetails_lv_show + .setOnScrollListener(new AbsListView.OnScrollListener() { + + @Override + public void onScrollStateChanged(AbsListView view, + int scrollState) { + + if (scrollState == 0) { + if (view.getLastVisiblePosition() >= 3) { + if (essaydetails_ll_comment.getVisibility() != View.VISIBLE) { + essaydetails_ll_comment + .setVisibility(View.VISIBLE); + essaydetails_ll_bottom + .setVisibility(View.GONE); + TranslateAnimation animation = new TranslateAnimation( + 0, + 0, + DisplayUtils + .dip2px(getApplicationContext(), + 48), 0); + animation.setDuration(500); + essaydetails_ll_comment + .startAnimation(animation); + } + } else { + if (essaydetails_ll_bottom.getVisibility() != View.VISIBLE) { + if (isShowBottom) { + essaydetails_ll_comment + .setVisibility(View.GONE); + essaydetails_ll_bottom + .setVisibility(View.VISIBLE); + TranslateAnimation animation = new TranslateAnimation( + 0, + 0, + DisplayUtils + .dip2px(getApplicationContext(), + 48), 0); + animation.setDuration(500); + essaydetails_ll_bottom + .startAnimation(animation); + } + } + } + if (view.getLastVisiblePosition() == view + .getCount() - 1 && isLoading) { + getComment(commentList.size()); + } + } + } + + @Override + public void onScroll(AbsListView view, + int firstVisibleItem, int visibleItemCount, + int totalItemCount) { + + } + }); + + if (newsId != null) { + getNewDigest(newsId); + } else { + getContent(); + } + + start = Calendar.getInstance().getTimeInMillis(); + + if (isShowBottom) { + essaydetails_ll_bottom.setVisibility(View.VISIBLE); + } + + View view = getWindow().findViewById(Window.ID_ANDROID_CONTENT); + if (view != null) { + view.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + System.arraycopy(mHits, 1, mHits, 0, mHits.length - 1); + mHits[mHits.length - 1] = SystemClock.uptimeMillis(); + if (mHits[0] >= (SystemClock.uptimeMillis() - 1000)) { + essaydetails_lv_show.setSelection(0); + } + } + }); + } + } + + private void getNewDigest(final String news_id) { + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Config.HOST + "v1d45/news/" + news_id + "/digest", + new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + Gson gson = new Gson(); + NewsEntity newsEntity = gson.fromJson( + response.toString(), NewsEntity.class); + NewsDetailsEntity essayEntity = new NewsDetailsEntity(); + essayEntity.setTitle(newsEntity.getTitle()); + essayEntity.setType(newsEntity.getType()); + essayEntity.setId(news_id); + entity = essayEntity; + actionbar_tv_title.setText(entity.getType()); + getContent(); + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + // 无网络连接和访问超时 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + if (!isDestroy) { + essaydetails_lv_show.setVisibility(View.GONE); + essaydetails_ll_loading + .setVisibility(View.GONE); + essaydetails_ll_bottom.setVisibility(View.GONE); + reuse_no_connection.setVisibility(View.VISIBLE); + } + } + } + }); + AppController.addToRequestQueue(request, NewsActivity.class); + } + + private long[] mHits = new long[2]; + + @Override + public void onClick(View v) { + if (v == essaydetails_tv_download) { + if (gameEntity != null && !gameEntity.getApk().isEmpty()) { + if (NetworkUtils.isWifiConnected(this)) { + if (gameEntity.getApk().size() == 1) { + if (essaydetails_tv_download.getText().toString() + .contains("启动")) { + + Map kv = new HashMap(); + kv.put("版本", gameEntity.getApk().get(0) + .getPlatform()); + TCAgent.onEvent(NewsActivity.this, "游戏启动", + gameEntity.getName(), kv); + + PackageUtils.launchApplicationByPackageName( + getApplicationContext(), gameEntity + .getApk().get(0).getPackageName()); + } else { + ApkEntity apkEntity = gameEntity.getApk().get(0); + String msg = FileUtils.isCanDownload(apkEntity + .getSize()); + if (TextUtils.isEmpty(msg)) { + Map kv = new HashMap(); + kv.put("版本", apkEntity.getPlatform()); + kv.put("状态", "下载开始"); + TCAgent.onEvent(NewsActivity.this, "游戏下载", + gameEntity.getName(), kv); + + Map kv2 = new HashMap(); + kv2.put("版本", apkEntity.getPlatform()); + kv2.put("状态", "下载开始"); + kv2.put("位置", entrance + "-文章详情-开始"); + TCAgent.onEvent(NewsActivity.this, "游戏下载位置", + gameEntity.getName(), kv2); + + Map kv3 = new HashMap(); + kv3.put(entrance, "下载数"); + kv3.put(entrance, "下载开始"); + TCAgent.onEvent(NewsActivity.this, "应用数据", + gameEntity.getName(), kv3); + + Map map = new HashMap(); + map.put("game", gameEntity.getName()); + map.put("method", "正常"); + map.put("platform", + PlatformUtils.getInstance( + getApplicationContext()) + .getPlatformName( + gameEntity.getApk() + .get(0) + .getPlatform())); + map.put("status", "开始"); + map.put("location", "新闻详情:" + entity.getTitle()); + map.put("from", entrance); + map.put("network", + NetworkUtils.getConnectedType(this)); + map.put("createdOn", + System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent(this, "download", + map); + + DownloadEntry entry = new DownloadEntry(); + + entry.setUrl(apkEntity.getUrl()); + entry.setName(gameEntity.getName()); + entry.setPath(FileUtils.getDownloadPath( + NewsActivity.this, + MD5Utils.getContentMD5(gameEntity + .getName() + + "_" + + System.currentTimeMillis()) + + ".apk")); + HashMap meta = new HashMap(); + meta.put("ETag", apkEntity.getEtag()); + meta.put("icon", gameEntity.getIcon()); + meta.put("platform", apkEntity.getPlatform()); + meta.put("gameId", gameEntity.getId()); + meta.put("entrance", entrance + "-文章详情"); + meta.put("location", + "新闻详情:" + entity.getTitle()); + entry.setMeta(meta); + + DownloadManager.getInstance( + getApplicationContext()).add(entry); + + EventBus.getDefault().post(new EBRedDot(1)); + + essaydetails_tv_download + .setVisibility(View.GONE); + essaydetails_progressbar + .setVisibility(View.VISIBLE); + essaydetails_tv_per.setVisibility(View.VISIBLE); + essaydetails_progressbar.setProgress(0); + essaydetails_tv_per.setText("0.0%"); + + statusMap.put(entry.getUrl(), "downloading"); + + } else { + Toast.makeText(NewsActivity.this, msg, + Toast.LENGTH_SHORT).show(); + } + } + } else { + if (!dismissEntity.isShow()) { + dismissEntity.setShow(true); + DownloadDialog.getInstance(NewsActivity.this) + .showPopupWindow(v, gameEntity, + entrance + "-文章详情", handler, + lastTimeMap, statusMap, + "新闻详情:" + entity.getTitle()); + } + } + } else { + final Dialog dialog = new Dialog(this); + View view = View.inflate(this, + R.layout.search_history_delete_dialog, null); + TextView title = (TextView) view + .findViewById(R.id.delete_dialog_title); + title.setText("警告"); + TextView content = (TextView) view + .findViewById(R.id.delete_dialog_message); + + content.setText("您当前的网络为2G/3G/4G,下载将会消耗移动流量,是否继续下载?"); + + TextView cancel = (TextView) view + .findViewById(R.id.delete_dialog_cancel); + cancel.setText("取消"); + cancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + TextView confirem = (TextView) view + .findViewById(R.id.delete_dialog_confirm); + confirem.setText("继续"); + confirem.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + if (gameEntity.getApk().size() == 1) { + if (essaydetails_tv_download.getText() + .toString().contains("启动")) { + + Map kv = new HashMap(); + kv.put("版本", gameEntity.getApk().get(0) + .getPlatform()); + TCAgent.onEvent(NewsActivity.this, "游戏启动", + gameEntity.getName(), kv); + + PackageUtils + .launchApplicationByPackageName( + getApplicationContext(), + gameEntity.getApk().get(0) + .getPackageName()); + } else { + ApkEntity apkEntity = gameEntity.getApk() + .get(0); + String msg = FileUtils + .isCanDownload(apkEntity.getSize()); + if (TextUtils.isEmpty(msg)) { + Map kv = new HashMap(); + kv.put("版本", apkEntity.getPlatform()); + kv.put("状态", "下载开始"); + TCAgent.onEvent(NewsActivity.this, + "游戏下载", gameEntity.getName(), + kv); + + Map kv2 = new HashMap(); + kv2.put("版本", apkEntity.getPlatform()); + kv2.put("状态", "下载开始"); + kv2.put("位置", entrance + "-文章详情-开始"); + TCAgent.onEvent(NewsActivity.this, + "游戏下载位置", gameEntity.getName(), + kv2); + + Map map = new HashMap(); + map.put("game", gameEntity.getName()); + map.put("method", "正常"); + map.put("platform", + PlatformUtils + .getInstance( + getApplicationContext()) + .getPlatformName( + gameEntity + .getApk() + .get(0) + .getPlatform())); + map.put("status", "开始"); + map.put("location", + "新闻详情:" + entity.getTitle()); + map.put("from", entrance); + map.put("network", + NetworkUtils + .getConnectedType(NewsActivity.this)); + map.put("createdOn", + System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent( + NewsActivity.this, "download", + map); + + DownloadEntry entry = new DownloadEntry(); + + entry.setUrl(apkEntity.getUrl()); + entry.setName(gameEntity.getName()); + entry.setPath(FileUtils + .getDownloadPath( + NewsActivity.this, + MD5Utils.getContentMD5(gameEntity + .getName() + + "_" + + System.currentTimeMillis()) + + ".apk")); + HashMap meta = new HashMap(); + meta.put("ETag", apkEntity.getEtag()); + meta.put("icon", gameEntity.getIcon()); + meta.put("platform", + apkEntity.getPlatform()); + meta.put("gameId", gameEntity.getId()); + meta.put("entrance", entrance + "-文章详情"); + meta.put("location", + "新闻详情:" + entity.getTitle()); + entry.setMeta(meta); + + DownloadManager.getInstance( + getApplicationContext()).add( + entry); + + EventBus.getDefault().post( + new EBRedDot(1)); + + essaydetails_tv_download + .setVisibility(View.GONE); + essaydetails_progressbar + .setVisibility(View.VISIBLE); + essaydetails_tv_per + .setVisibility(View.VISIBLE); + essaydetails_progressbar.setProgress(0); + essaydetails_tv_per.setText("0.0%"); + + statusMap.put(entry.getUrl(), + "downloading"); + + } else { + Toast.makeText(NewsActivity.this, msg, + Toast.LENGTH_SHORT).show(); + } + } + } else { + if (!dismissEntity.isShow()) { + dismissEntity.setShow(true); + DownloadDialog.getInstance( + NewsActivity.this).showPopupWindow( + v, gameEntity, entrance + "-文章详情", + handler, lastTimeMap, statusMap, + "新闻详情:" + entity.getTitle()); + } + } + } + }); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.show(); + } + } else { + Toast.makeText(this, "稍等片刻~!游戏正在上传中...", Toast.LENGTH_SHORT) + .show(); + } + } else if (v == essaydetails_iv_share) { + Map map = new HashMap(); + map.put("location", "分享"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("news", entity.getTitle()); + map.put("page", "新闻详情"); + DataCollectionManager.onEvent(this, "click-item", map); + + String url = "http://news.ghzhushou.com/" + entity.getId() + + ".html"; + showShare(url, entity.getTitle(), gameEntity.getIcon(), entrance, + "新闻"); + } else if (v == essaydetails_progressbar || v == essaydetails_tv_per) { + String str = essaydetails_tv_per.getText().toString(); + if ("继续".equals(str)) { + statusMap.put(downloadEntry.getUrl(), "downloading"); + essaydetails_tv_per.setText(downloadEntry.getPercent() + "%"); + Message msg = Message.obtain(); + msg.what = Constants.CONTINUE_DOWNLOAD_TASK; + msg.obj = downloadEntry.getUrl(); + lastTimeMap.put(downloadEntry.getUrl(), + System.currentTimeMillis()); + handler.sendMessageDelayed(msg, 1000); + } else if ("安装".equals(str)) { + String path = downloadEntry.getPath(); + PackageManager manager = new PackageManager( + getApplicationContext()); + if (manager.launchSetup(path)) { + startActivity(PackageUtils.getInstallIntent(path)); + } else { + DialogUtils.showDialog(NewsActivity.this, path); + } + } else { + statusMap.put(downloadEntry.getUrl(), "pause"); + essaydetails_tv_per.setText("继续"); + Message msg = Message.obtain(); + msg.what = Constants.PAUSE_DOWNLOAD_TASK; + msg.obj = downloadEntry.getUrl(); + lastTimeMap.put(downloadEntry.getUrl(), + System.currentTimeMillis()); + handler.sendMessageDelayed(msg, 1000); + } + } else if (v == reuse_no_connection) { + essaydetails_lv_show.setVisibility(View.VISIBLE); + essaydetails_ll_loading.setVisibility(View.VISIBLE); + essaydetails_ll_bottom.setVisibility(View.VISIBLE); + reuse_no_connection.setVisibility(View.GONE); + handler.postDelayed(runnable, 1000); + } else if (v == essaydetails_tv_comment_content) { + showCommentDialog(v, essaydetails_tv_comment_content.getText(), + essaydetails_tv_comment_content.getLineCount()); + } else if (v == essaydetails_tv_comment_send) { + sendComment(essaydetails_tv_comment_content.getText()); + } + } + + Runnable runnable = new Runnable() { + @Override + public void run() { + if (newsId != null) { + getNewDigest(newsId); + } else { + getContent(); + } + } + }; + + private void getContent() { + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Config.HOST + "v1d45/news/" + entity.getId() + "/detail", + // Config.HOST + "newsV1d45/test_news/" + // + System.currentTimeMillis(), + new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + + if (!isDestroy) { + Gson gson = new Gson(); + NewsDetailsEntity essayEntity = gson.fromJson( + response.toString(), + NewsDetailsEntity.class); + essayEntity.setTitle(entity.getTitle()); + if (entity.getTime() != null) { + essayEntity.setTime(entity.getTime()); + } + essayEntity.setType(entity.getType()); + if (entity.getId() != null) { + essayEntity.setId(entity.getId()); + } + entity = essayEntity; + + adapter.notifyDataSetChanged(); + + // 获取相关推荐 + getNewsMore(); + + // 获取游戏数据 + getGameDetails(); + + // 获取文章反馈数据 + getNewsFeedback(); + + // 获取用户反馈数据 + getUserFeedback(); + } + } + + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + Utils.log(error.toString()); + if (error.networkResponse != null) { + Utils.log(new String(error.networkResponse.data)); + } + // 无网络连接和访问超时 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + if (!isDestroy) { + essaydetails_lv_show.setVisibility(View.GONE); + essaydetails_ll_loading + .setVisibility(View.GONE); + essaydetails_ll_bottom.setVisibility(View.GONE); + reuse_no_connection.setVisibility(View.VISIBLE); + } + } + } + }); + AppController.addToRequestQueue(request, NewsActivity.class); + } + + private void getNewsMore() { + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + "v1d45/news/" + + entity.getId() + "/suggestion", Constants.NEWS_CD), + new Response.Listener() { + @Override + public void onResponse(JSONArray response) { + Utils.log(response); + if (!isDestroy) { + Type listType = new TypeToken>() { + }.getType(); + Gson gson = new Gson(); + List list = gson.fromJson( + response.toString(), listType); + // 去除与当前文章重复的文章 + for (int i = 0, size = list.size(); i < size; i++) { + if (entity.getId().equals(list.get(i).getId())) { + list.remove(i); + break; + } + } + List more = new ArrayList(); + // TODO 随机三篇文章 + int[] index = new int[list.size() > 3 ? 3 : list + .size()]; + Random random = new Random(System + .currentTimeMillis()); + for (int i = 0; i < index.length; i++) { + if (i == 0) { + index[i] = random.nextInt(list.size()); + } else { + index[i] = random(random, index, i, + list.size()); + } + } + for (int i = 0; i < index.length; i++) { + more.add(list.get(index[i])); + } + entity.setMore(more); + + adapter.notifyDataSetChanged(); + } + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + Utils.log(error); + } + }); + AppController.addToRequestQueue(request, NewsActivity.class); + } + + private int random(Random random, int[] index, int i, int size) { + int seed = random.nextInt(size); + for (int j = 0; j < i; j++) { + if (index[j] == seed) { + return random(random, index, i, size); + } + } + return seed; + } + + private void getGameDetails() { + JsonObjectExtendedRequest gameRequest = new JsonObjectExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + "v1d45/game/" + + entity.getGame() + "/news_digest", Constants.GAME_CD), + new Response.Listener() { + @Override + public void onResponse(JSONObject response) { + if (!isDestroy) { + processingGameData(response.toString()); + } + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + + } + }); + AppController.addToRequestQueue(gameRequest, NewsActivity.class); + } + + private void processingGameData(String data) { + Gson gson = new Gson(); + gameEntity = gson.fromJson(data, GameEntity.class); + boolean isInstalled = false; + if (gameEntity.getApk() != null + && gameEntity.getApk().size() == 1 + && PackageManager.isInstalled(gameEntity.getApk().get(0) + .getPackageName())) { + isInstalled = true; + } + if (TextUtils.isEmpty(gameEntity.getDownloadAddWord())) { + essaydetails_tv_download.setVisibility(View.VISIBLE); + essaydetails_progressbar.setVisibility(View.GONE); + essaydetails_tv_per.setVisibility(View.GONE); + if (isInstalled) { + essaydetails_tv_download.setText("启动《" + gameEntity.getName() + + "》"); + } else { + essaydetails_tv_download.setText("下载《" + gameEntity.getName() + + "》"); + } + } else { + essaydetails_tv_download.setVisibility(View.VISIBLE); + essaydetails_progressbar.setVisibility(View.GONE); + essaydetails_tv_per.setVisibility(View.GONE); + if (isInstalled) { + essaydetails_tv_download.setText("启动《" + gameEntity.getName() + + "》" + gameEntity.getDownloadAddWord()); + } else { + essaydetails_tv_download.setText("下载《" + gameEntity.getName() + + "》" + gameEntity.getDownloadAddWord()); + } + } + if (gameEntity.getApk() == null) { + essaydetails_ll_bottom.setVisibility(View.GONE); + isShowBottom = false; + } else { + for (int i = 0, size = gameEntity.getApk().size(); i < size; i++) { + String packageName = gameEntity.getApk().get(i) + .getPackageName(); + if (PackageManager.isInstalled(packageName) + || getPackageName().equals(packageName)) { + essaydetails_ll_bottom.setVisibility(View.GONE); + essaydetails_ll_comment.setVisibility(View.VISIBLE); + TranslateAnimation animation = new TranslateAnimation(0, 0, + DisplayUtils.dip2px(getApplicationContext(), 48), 0); + animation.setDuration(500); + essaydetails_ll_comment.startAnimation(animation); + isShowBottom = false; + break; + } else if (i == size - 1) { + isShowBottom = true; + essaydetails_ll_bottom.setVisibility(View.VISIBLE); + TranslateAnimation animation = new TranslateAnimation(0, 0, + DisplayUtils.dip2px(getApplicationContext(), 48), 0); + animation.setDuration(500); + essaydetails_ll_bottom.startAnimation(animation); + } + } + } + adapter.updateSingleRow(essaydetails_lv_show, 0); + } + + private void getNewsFeedback() { + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + "v1d45/news/" + + entity.getId() + "/feedback", Constants.COMMENT_CD), + new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + Utils.log("getNewsFeedback = " + response.toString()); + if (!isDestroy) { + try { + entity.setUp(response.getLong("up")); + entity.setDown(response.getLong("down")); + // adapter.notifyDataSetChanged(); + } catch (JSONException e) { + e.printStackTrace(); + } + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + + } + }); + AppController.addToRequestQueue(request, NewsActivity.class); + } + + private void getUserFeedback() { + new Thread() { + @Override + public void run() { + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + "v1d45/news/" + + entity.getId() + "/user/feedback", + Constants.COMMENT_CD), + new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + Utils.log("getUserFeedback = " + + response.toString()); + if (!isDestroy) { + try { + String action = response.getJSONObject( + "news").getString("action"); + if (!TextUtils.isEmpty(action)) { + entity.setAction(action); + } + JSONArray comment = response + .getJSONArray("comment"); + if (comment.length() != 0) { + commentFeedbackMap = new ArrayMap(); + for (int i = 0; i < comment + .length(); i++) { + JSONObject jsonObject = comment + .getJSONObject(i); + commentFeedbackMap.put( + jsonObject + .getString("id"), + jsonObject + .getString("action")); + } + } + // adapter.notifyDataSetChanged(); + } catch (JSONException e) { + e.printStackTrace(); + } + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + Utils.log("getUserFeedback = " + + error.toString()); + } + }); + String token = TokenUtils.getToken(NewsActivity.this); + request.addHeader("Auth", token); + AppController.addToRequestQueue(request, NewsActivity.class); + } + }.start(); + } + + private class ViewHolder implements OnClickListener { + + private int type; + + private LinearLayout essaydetails_ll_top; + private View essaydetails_line; + private ImageView essaydetails_icon; + private TextView essaydetails_name, essaydetails_info, + essaydetails_attention, essaydetails_title, essaydetails_time, + essaydetails_author, essaydetails_tv_more; + private WebView essaydetails_wv_content; + + private LinearLayout news_item_ll; + private TextView news_type, news_title; + + private LinearLayout essaydetails_ll_liked, essaydetails_ll_unliked; + private ImageView essaydetails_iv_liked, essaydetails_iv_unliked; + private TextView essaydetails_tv_liked, essaydetails_tv_unliked; + + private BezelImageView comment_item_iv_icon; + private LinearLayout comment_item_ll_full; + private TextView comment_item_tv_username, comment_item_tv_time, + comment_item_tv_content, comment_item_tv_like, + comment_item_tv_unlike; + + private ProgressBar footerview_progressbar; + private TextView footerview_tv_loading; + private View rootView; + + public ViewHolder(View view, int type) { + this.type = type; + switch (type) { + case 0: + essaydetails_ll_top = (LinearLayout) view + .findViewById(R.id.essaydetails_ll_top); + essaydetails_ll_top.setOnClickListener(this); + essaydetails_line = view.findViewById(R.id.essaydetails_line); + essaydetails_icon = (ImageView) view + .findViewById(R.id.essaydetails_icon); + essaydetails_name = (TextView) view + .findViewById(R.id.essaydetails_name); + essaydetails_info = (TextView) view + .findViewById(R.id.essaydetails_info); + essaydetails_attention = (TextView) view + .findViewById(R.id.essaydetails_attention); + essaydetails_attention.setOnClickListener(this); + essaydetails_title = (TextView) view + .findViewById(R.id.essaydetails_title); + essaydetails_time = (TextView) view + .findViewById(R.id.essaydetails_time); + essaydetails_author = (TextView) view + .findViewById(R.id.essaydetails_author); + essaydetails_wv_content = (WebView) view + .findViewById(R.id.essaydetails_wv_content); + essaydetails_tv_more = (TextView) view + .findViewById(R.id.essaydetails_tv_more); + break; + case 1: + news_type = (TextView) view.findViewById(R.id.news_type); + news_title = (TextView) view.findViewById(R.id.news_title); + news_item_ll = (LinearLayout) view + .findViewById(R.id.news_item_ll); + break; + case 2: + essaydetails_ll_liked = (LinearLayout) view + .findViewById(R.id.essaydetails_ll_liked); + essaydetails_ll_liked.setOnClickListener(this); + essaydetails_ll_unliked = (LinearLayout) view + .findViewById(R.id.essaydetails_ll_unliked); + essaydetails_ll_unliked.setOnClickListener(this); + essaydetails_iv_liked = (ImageView) view + .findViewById(R.id.essaydetails_iv_liked); + essaydetails_iv_unliked = (ImageView) view + .findViewById(R.id.essaydetails_iv_unliked); + essaydetails_tv_liked = (TextView) view + .findViewById(R.id.essaydetails_tv_liked); + essaydetails_tv_unliked = (TextView) view + .findViewById(R.id.essaydetails_tv_unliked); + break; + case 3: + comment_item_iv_icon = (BezelImageView) view + .findViewById(R.id.comment_item_iv_icon); + comment_item_ll_full = (LinearLayout) view + .findViewById(R.id.comment_item_ll_full); + comment_item_tv_username = (TextView) view + .findViewById(R.id.comment_item_tv_username); + comment_item_tv_content = (TextView) view + .findViewById(R.id.comment_item_tv_content); + comment_item_tv_time = (TextView) view + .findViewById(R.id.comment_item_tv_time); + comment_item_tv_like = (TextView) view + .findViewById(R.id.comment_item_tv_like); + comment_item_tv_unlike = (TextView) view + .findViewById(R.id.comment_item_tv_unlike); + break; + case 4: + footerview_progressbar = (ProgressBar) view + .findViewById(R.id.footerview_progressbar); + footerview_tv_loading = (TextView) view + .findViewById(R.id.footerview_tv_loading); + rootView = view; + default: + break; + } + view.setTag(this); + } + + @Override + public void onClick(View v) { + if (v == essaydetails_ll_liked) { + if (entity.getAction() != null) { + if ("up".equals(entity.getAction())) { + entity.setAction(null); + entity.setUp(entity.getUp() - 1); + if (entity.getMore() == null) { + adapter.updateSingleRow(essaydetails_lv_show, 1); + } else { + adapter.updateSingleRow(essaydetails_lv_show, + 1 + entity.getMore().size()); + } + Message msg = Message.obtain(); + msg.what = Constants.SEND_NEWS_FEEDBACK; + msg.arg1 = 2; + msg.obj = "CancelNewsLike"; + timeMap.put("CancelNewsLike", + System.currentTimeMillis()); + handler.sendMessageDelayed(msg, 1000); + return; + } else if ("down".equals(entity.getAction())) { + entity.setDown(entity.getDown() - 1); + } + } + entity.setAction("up"); + entity.setUp(entity.getUp() + 1); + if (entity.getMore() == null) { + adapter.updateSingleRow(essaydetails_lv_show, 1); + } else { + adapter.updateSingleRow(essaydetails_lv_show, 1 + entity + .getMore().size()); + } + Message msg = Message.obtain(); + msg.what = Constants.SEND_NEWS_FEEDBACK; + msg.arg1 = 0; + msg.obj = "SendNewsLike"; + timeMap.put("SendNewsLike", System.currentTimeMillis()); + handler.sendMessageDelayed(msg, 1000); + } else if (v == essaydetails_ll_unliked) { + if (entity.getAction() != null) { + if ("down".equals(entity.getAction())) { + entity.setAction(null); + entity.setDown(entity.getDown() - 1); + if (entity.getMore() == null) { + adapter.updateSingleRow(essaydetails_lv_show, 1); + } else { + adapter.updateSingleRow(essaydetails_lv_show, + 1 + entity.getMore().size()); + } + Message msg = Message.obtain(); + msg.what = Constants.SEND_NEWS_FEEDBACK; + msg.arg1 = 2; + msg.obj = "CancelNewsLike"; + timeMap.put("CancelNewsLike", + System.currentTimeMillis()); + handler.sendMessageDelayed(msg, 1000); + return; + } else if ("up".equals(entity.getAction())) { + entity.setUp(entity.getUp() - 1); + } + } + entity.setAction("down"); + entity.setDown(entity.getDown() + 1); + if (entity.getMore() == null) { + adapter.updateSingleRow(essaydetails_lv_show, 1); + } else { + adapter.updateSingleRow(essaydetails_lv_show, 1 + entity + .getMore().size()); + } + Message msg = Message.obtain(); + msg.what = Constants.SEND_NEWS_FEEDBACK; + msg.arg1 = 1; + msg.obj = "SendNewsUnlike"; + timeMap.put("SendNewsUnlike", System.currentTimeMillis()); + handler.sendMessageDelayed(msg, 1000); + } else if (v == essaydetails_ll_top) { + Intent intent = new Intent(NewsActivity.this, + GameDetailsActivity.class); + intent.putExtra("gameId", gameEntity.getId()); + intent.putExtra("entrance", entrance); + startActivity(intent); + } else if (v == essaydetails_attention) { + if ("关注".equals(essaydetails_attention.getText().toString())) { + + Map kv = new HashMap(); + kv.put("状态", "关注"); + TCAgent.onEvent(NewsActivity.this, "游戏关注", + gameEntity.getName(), kv); + + Map kv2 = new HashMap(); + kv2.put("点击", "关注"); + TCAgent.onEvent(NewsActivity.this, "插件数据", + gameEntity.getName(), kv2); + + Map map = new HashMap(); + map.put("game", gameEntity.getName()); + map.put("type", "关注"); + map.put("createdOn", System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent(NewsActivity.this, "concern", + map); + + concernManager.addByEntity(gameEntity); + essaydetails_attention.setText("取消关注"); + essaydetails_attention + .setBackgroundResource(R.drawable.border_red_bg); + essaydetails_attention.setTextColor(0xffbc2132); + showSuccessDialog(); + } else { + Map kv2 = new HashMap(); + kv2.put("点击", "取消关注"); + TCAgent.onEvent(NewsActivity.this, "插件数据", + gameEntity.getName(), kv2); + + showCancelDialog(essaydetails_attention); + } + } + } + } + + private void showSuccessDialog() { + final Dialog dialog = new Dialog(this); + View view = View.inflate(this, R.layout.gamedetails_attention_dialog, + null); + TextView title = (TextView) view.findViewById(R.id.dialog_title); + title.setText("关注成功"); + TextView confirm = (TextView) view.findViewById(R.id.dialog_confirm); + confirm.setText("我知道了"); + confirm.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + TextView message = (TextView) view.findViewById(R.id.dialog_message); + message.setText("游戏的最新动态消息会优先提醒您,包括攻略、资讯、开服信息、开测信息以及最新的插件。"); + view.findViewById(R.id.dialog_rl_cancel).setVisibility(View.GONE); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.show(); + } + + private void showCancelDialog(final TextView attention) { + final Dialog dialog = new Dialog(this); + View view = View.inflate(this, R.layout.gamedetails_attention_dialog, + null); + TextView title = (TextView) view.findViewById(R.id.dialog_title); + title.setText("取消关注"); + TextView cancel = (TextView) view.findViewById(R.id.dialog_cancel); + cancel.setText("取消"); + cancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + TextView message = (TextView) view.findViewById(R.id.dialog_message); + + Spanned content = Html + .fromHtml("取消关注游戏后,您将无法及时收到游戏的攻略资讯等最新动态提醒,您确定取消吗?"); + message.setText(content); + + view.findViewById(R.id.dialog_rl_confirm).setVisibility(View.VISIBLE); + view.findViewById(R.id.dialog_confirm).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + + Map kv = new HashMap(); + kv.put("状态", "取消关注"); + TCAgent.onEvent(NewsActivity.this, "游戏关注", + gameEntity.getName(), kv); + + Map map = new HashMap(); + map.put("game", gameEntity.getName()); + map.put("type", "关注"); + map.put("createdOn", System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent(NewsActivity.this, + "concern", map); + + concernManager.deleteConcern(gameEntity.getId()); + dialog.dismiss(); + attention.setText("关注"); + attention + .setBackgroundResource(R.drawable.textview_red_style); + attention.setTextColor(0xffffffff); + } + }); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.show(); + } + + public class JsInterface { + private Context context; + private ArrayList imgs = new ArrayList(); + + public JsInterface(Context context) { + this.context = context; + } + + @JavascriptInterface + public void openImage(String url) { + int current = 0; + for (int i = 0, size = imgs.size(); i < size; i++) { + if (url.equals(imgs.get(i))) { + current = i; + } + } + Intent checkIntent = new Intent(context, ViewImageActivity.class); + checkIntent.putExtra("urls", imgs); + checkIntent.putExtra("current", current); + checkIntent.putExtra("ScaleType", "FIT_CENTER"); + context.startActivity(checkIntent); + } + + @JavascriptInterface + public void addImage(String url) { + if (!imgs.contains(url)) { + imgs.add(url); + } + } + + @JavascriptInterface + public void skip(String id, String type) { + if ("game".equals(type)) { + Intent intent = new Intent(NewsActivity.this, + GameDetailsActivity.class); + intent.putExtra("gameId", id); + intent.putExtra("entrance", entrance); + startActivity(intent); + } else if ("news".equals(type)) { + Intent intent = new Intent(NewsActivity.this, + NewsActivity.class); + intent.putExtra("newsId", id); + intent.putExtra("entrance", entrance); + startActivity(intent); + } + } + + } + + private class ListViewAdapter extends BaseAdapter { + + @Override + public int getCount() { + if (entity == null) { + return 0; + } + if (entity.getAuthor() == null) { + return 0; + } + if (!isFinish) { + return 1; + } + int commentSize = commentList.size(); + if (isLoading) { + if (entity.getMore() != null) { + return 4 + entity.getMore().size() + commentSize; + } else { + return 4 + commentSize; + } + } else { + if (entity.getMore() != null) { + return 3 + entity.getMore().size() + commentSize; + } else { + return 3 + commentSize; + } + } + } + + @Override + public Object getItem(int position) { + return position; + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View view; + final ViewHolder holder; + if (position == 0) { + if (convertView != null + && ((ViewHolder) convertView.getTag()).type == 0) { + view = convertView; + holder = (ViewHolder) view.getTag(); + } else { + view = LayoutInflater.from(parent.getContext()).inflate( + R.layout.essaydetails_item_top, parent, false); + holder = new ViewHolder(view, 0); + + holder.essaydetails_title.setText(entity.getTitle()); + + SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd", + Locale.getDefault()); + try { + long today = format.parse(format.format(new Date())) + .getTime(); + long day = Long.valueOf(entity.getTime() + "000"); + if (day >= today && day < today + 86400 * 1000) { + format.applyPattern("HH:mm"); + holder.essaydetails_time.setText("今天 " + + format.format(day)); + } else if (day >= today - 86400 * 1000 && day < today) { + format.applyPattern("HH:mm"); + holder.essaydetails_time.setText("昨天 " + + format.format(day)); + } else { + format.applyPattern("yyyy年MM月dd日 HH:mm"); + holder.essaydetails_time + .setText(format.format(day)); + } + } catch (ParseException e) { + e.printStackTrace(); + format.applyPattern("yyyy年MM月dd日 HH:mm"); + holder.essaydetails_time.setText(format.format(Long + .valueOf(entity.getTime() + "000"))); + } + + if (entity.getAuthor() != null) { + holder.essaydetails_author.setText(entity.getAuthor()); + } + + isFinish = false; + + holder.essaydetails_wv_content + .addJavascriptInterface(new JsInterface( + NewsActivity.this), "imagelistener"); + WebSettings webSettings = holder.essaydetails_wv_content + .getSettings(); + webSettings + .setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN); + webSettings.setJavaScriptEnabled(true); + holder.essaydetails_wv_content.loadDataWithBaseURL(null, + entity.getContent(), "text/html", "utf-8", null); + holder.essaydetails_wv_content + .setWebViewClient(new WebViewClient() { + @Override + public void onPageFinished(WebView view, + String url) { + view.loadUrl("javascript:(function(){" + + "var imgs = document.getElementsByTagName(\"img\");" + + "for(var i = 0; i < imgs.length - 1; i++) {" + + " window.imagelistener.addImage(imgs[i].src);" + + "}" + + "for(var i = 0; i < imgs.length - 1; i++) {" + + " imgs[i].onclick = function() {" + + " window.imagelistener.openImage(this.src);" + + " }" + + "}" + + "var as = document.getElementsByTagName(\"a\");" + + "for(var i = 0; i < as.length; i++) {" + + " as[i].onclick = function() {" + + " window.imagelistener.skip(this.id, this.type);" + + " }" + "}" + "})()"); + super.onPageFinished(view, url); + if (essaydetails_ll_loading != null) { + essaydetails_ll_loading + .setVisibility(View.GONE); + essaydetails_lv_show + .setVisibility(View.VISIBLE); + } + if (!isFinish) { + isFinish = true; + // adapter.notifyDataSetChanged(); + } + } + }); + } + if (gameEntity != null + && !gameEntity.getName().contains("光环助手")) { + holder.essaydetails_ll_top.setVisibility(View.VISIBLE); + holder.essaydetails_line.setVisibility(View.VISIBLE); + ImageUtils.getInstance(getApplicationContext()) + .displayFile(gameEntity.getIcon(), + holder.essaydetails_icon); + holder.essaydetails_name.setText(gameEntity.getName()); + if (concernManager.isConcern(gameEntity.getId())) { + holder.essaydetails_attention.setText("取消关注"); + holder.essaydetails_attention + .setBackgroundResource(R.drawable.border_red_bg); + holder.essaydetails_attention.setTextColor(0xffbc2132); + } else { + holder.essaydetails_attention.setText("关注"); + holder.essaydetails_attention + .setBackgroundResource(R.drawable.textview_red_style); + holder.essaydetails_attention.setTextColor(0xffffffff); + } + if (gameEntity.getApk() != null + && !gameEntity.getApk().isEmpty()) { + for (int i = 0, size = gameEntity.getApk().size(); i < size; i++) { + ApkEntity apkEntity = gameEntity.getApk().get(i); + if ("9u".equals(apkEntity.getPlatform())) { + holder.essaydetails_info.setText("V" + + apkEntity.getVersion() + " | " + + apkEntity.getSize()); + break; + } + if (i == size - 1) { + holder.essaydetails_info.setText("V" + + apkEntity.getVersion() + " | " + + apkEntity.getSize()); + } + } + } + } else { + holder.essaydetails_ll_top.setVisibility(View.GONE); + holder.essaydetails_line.setVisibility(View.GONE); + } + if (entity.getMore() != null) { + holder.essaydetails_tv_more.setVisibility(View.VISIBLE); + } else { + holder.essaydetails_tv_more.setVisibility(View.GONE); + } + } else if (entity.getMore() != null && position >= 1 + && position < 1 + entity.getMore().size()) { + if (convertView != null + && ((ViewHolder) convertView.getTag()).type == 1) { + view = convertView; + holder = (ViewHolder) view.getTag(); + } else { + view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.essaydetails_more_news_item, + parent, false); + holder = new ViewHolder(view, 1); + } + final NewsEntity newsEntity = entity.getMore() + .get(position - 1); + holder.news_type.setBackgroundResource(NewsUtils + .getDrawableIdByType(newsEntity.getType())); + holder.news_type.setText(newsEntity.getType()); + holder.news_title.setText(newsEntity.getTitle()); + holder.news_item_ll + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(NewsActivity.this, + NewsActivity.class); + intent.putExtra("newsId", newsEntity.getId()); + intent.putExtra("entrance", entrance); + startActivity(intent); + } + }); + } else if ((entity.getMore() == null && position == 1) + || (entity.getMore() != null && position == 1 + entity + .getMore().size())) { + if (convertView != null + && ((ViewHolder) convertView.getTag()).type == 2) { + view = convertView; + holder = (ViewHolder) view.getTag(); + } else { + view = LayoutInflater.from(parent.getContext()).inflate( + R.layout.essaydetails_comment_evaluate, parent, + false); + holder = new ViewHolder(view, 2); + } + holder.essaydetails_ll_liked + .setBackgroundResource(R.drawable.essay_liked_style); + holder.essaydetails_ll_unliked + .setBackgroundResource(R.drawable.essay_unliked_style); + holder.essaydetails_iv_liked + .setImageResource(R.drawable.essay_like_style); + ColorStateList colorStateList = getResources() + .getColorStateList(R.drawable.essay_text_style); + holder.essaydetails_tv_liked.setTextColor(colorStateList); + holder.essaydetails_iv_unliked + .setImageResource(R.drawable.essay_unlike_style); + if (entity.getAction() != null) { + if ("up".equals(entity.getAction())) { + holder.essaydetails_ll_liked + .setBackgroundResource(R.drawable.essay_liked_dn); + holder.essaydetails_iv_liked + .setImageResource(R.drawable.essay_like_dn); + holder.essaydetails_tv_liked.setTextColor(0xFFFFFFFF); + } else if ("down".equals(entity.getAction())) { + holder.essaydetails_ll_unliked + .setBackgroundResource(R.drawable.essay_unliked_dn); + holder.essaydetails_iv_unliked + .setImageResource(R.drawable.essay_unlike_dn); + } + } + holder.essaydetails_tv_liked.setText(entity.getUp() + ""); + holder.essaydetails_tv_unliked.setText(entity.getDown() + ""); + } else if ((entity.getMore() == null && !commentList.isEmpty() + && position >= 2 && position < 2 + commentList.size()) + || (entity.getMore() != null && !commentList.isEmpty() + && position >= 2 + entity.getMore().size() && position < 2 + + entity.getMore().size() + commentList.size())) { + if (convertView != null + && ((ViewHolder) convertView.getTag()).type == 3) { + view = convertView; + holder = (ViewHolder) convertView.getTag(); + } else { + view = LayoutInflater.from(parent.getContext()).inflate( + R.layout.essaydetails_comment_item, parent, false); + holder = new ViewHolder(view, 3); + } + final int index; + if (entity.getMore() != null) { + index = position - 2 - entity.getMore().size(); + } else { + index = position - 2; + } + final CommentEntity commentEntity = commentList.get(index); + + ImageUtils.getInstance(getApplicationContext()).display( + commentEntity.getUser().getIcon(), + holder.comment_item_iv_icon, + R.drawable.default_user_icon); + holder.comment_item_tv_username.setText(commentEntity.getUser() + .getName()); + holder.comment_item_tv_content.setText(commentEntity + .getContent().replaceAll("\n", " ")); + + Boolean b = fullMap.get(commentEntity.getId()); + if (b != null && b) { + holder.comment_item_tv_content + .setMaxLines(Integer.MAX_VALUE); + holder.comment_item_ll_full.setVisibility(View.GONE); + } else { + holder.comment_item_tv_content.setMaxLines(4); + holder.comment_item_tv_content.setEllipsize(TruncateAt.END); + if (holder.comment_item_tv_content.getPaint() + .measureText( + holder.comment_item_tv_content.getText() + .toString()) + - 4 * width > 0) { + holder.comment_item_ll_full.setVisibility(View.VISIBLE); + holder.comment_item_ll_full + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + fullMap.put(commentEntity.getId(), true); + if (entity.getMore() == null) { + updateSingleRow( + essaydetails_lv_show, + index + 2); + essaydetails_lv_show + .setSelection(index + 2); + } else { + updateSingleRow( + essaydetails_lv_show, index + + 2 + + entity.getMore() + .size()); + essaydetails_lv_show + .setSelection(index + + 2 + + entity.getMore() + .size()); + } + } + }); + } else { + holder.comment_item_ll_full.setVisibility(View.GONE); + } + } + + String date = null; + long time = System.currentTimeMillis() + - commentEntity.getTime() * 1000; + if (time <= 3600 * 1000) { + // 一小时内 + int minute = (int) (time / 1000 / 60); + if (minute == 0) { + date = "刚刚"; + } else { + date = minute + "分钟之前"; + } + } else if (time <= 86400 * 1000) { + // 今天 + int hour = (int) (time / 1000 / 3600); + if (hour == 0) { + hour = 1; + } + date = hour + "小时之前"; + } else if (time <= 2 * 86400 * 1000) { + // 昨天 + date = "昨天"; + } else { + SimpleDateFormat format = new SimpleDateFormat("MM月dd日", + Locale.getDefault()); + date = format.format(new Date( + commentEntity.getTime() * 1000)); + } + if (entity.getMore() != null) { + holder.comment_item_tv_time.setText((position - 1 - entity + .getMore().size()) + "楼\t\t\t\t" + date); + } else { + holder.comment_item_tv_time.setText((position - 1) + + "楼\t\t\t\t" + date); + } + + holder.comment_item_tv_like.setText(commentEntity.getFeedback() + .getUp() + " 赞"); + holder.comment_item_tv_unlike.setText(commentEntity + .getFeedback().getDown() + " 踩"); + + holder.comment_item_tv_like + .setBackgroundResource(R.drawable.essay_comment_liked_style); + holder.comment_item_tv_unlike + .setBackgroundResource(R.drawable.essay_comment_unliked_style); + ColorStateList colorStateList = getResources() + .getColorStateList(R.drawable.essay_text_style); + holder.comment_item_tv_like.setTextColor(colorStateList); + if (commentFeedbackMap != null) { + String action = commentFeedbackMap.get(commentEntity + .getId()); + if (action != null) { + if ("up".equals(action)) { + holder.comment_item_tv_like + .setBackgroundResource(R.drawable.essay_comment_liked_dn); + holder.comment_item_tv_like + .setTextColor(0xFFFFFFFF); + } else if ("down".equals(action)) { + holder.comment_item_tv_unlike + .setBackgroundResource(R.drawable.essay_comment_unliked_dn); + } + } + } + + holder.comment_item_tv_like + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (commentFeedbackMap != null) { + String key = commentEntity.getId(); + String action = commentFeedbackMap.get(key); + if (action != null) { + if ("up".equals(action)) { + commentFeedbackMap.remove(key); + commentEntity.getFeedback().setUp( + commentEntity.getFeedback() + .getUp() - 1); + if (entity.getMore() == null) { + updateSingleRow( + essaydetails_lv_show, + index + 2); + } else { + updateSingleRow( + essaydetails_lv_show, + index + + 2 + + entity.getMore() + .size()); + } + Message msg = Message.obtain(); + msg.what = Constants.SEND_COMMENT_FEEDBACK; + msg.arg1 = 2; + msg.arg2 = index; + msg.obj = "CancelCommentLike"; + timeMap.put("CancelCommentLike", + System.currentTimeMillis()); + handler.sendMessageDelayed(msg, + 1000); + return; + } else { + commentEntity + .getFeedback() + .setDown( + commentEntity + .getFeedback() + .getDown() - 1); + } + } + } else { + commentFeedbackMap = new ArrayMap(); + } + commentFeedbackMap.put(commentEntity.getId(), + "up"); + commentEntity.getFeedback() + .setUp(commentEntity.getFeedback() + .getUp() + 1); + if (entity.getMore() == null) { + updateSingleRow(essaydetails_lv_show, + index + 2); + } else { + updateSingleRow(essaydetails_lv_show, index + + 2 + entity.getMore().size()); + } + Message msg = Message.obtain(); + msg.what = Constants.SEND_COMMENT_FEEDBACK; + msg.arg1 = 0; + msg.arg2 = index; + msg.obj = "SendCommentLike"; + timeMap.put("SendCommentLike", + System.currentTimeMillis()); + handler.sendMessageDelayed(msg, 1000); + } + }); + holder.comment_item_tv_unlike + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (commentFeedbackMap != null) { + String key = commentList.get(index).getId(); + String action = commentFeedbackMap.get(key); + if (action != null) { + if ("down".equals(action)) { + commentFeedbackMap.remove(key); + commentList + .get(index) + .getFeedback() + .setDown( + commentList + .get(index) + .getFeedback() + .getDown() - 1); + if (entity.getMore() == null) { + updateSingleRow( + essaydetails_lv_show, + index + 2); + } else { + updateSingleRow( + essaydetails_lv_show, + index + + 2 + + entity.getMore() + .size()); + } + Message msg = Message.obtain(); + msg.what = Constants.SEND_COMMENT_FEEDBACK; + msg.arg1 = 2; + msg.arg2 = index; + msg.obj = "CancelCommentLike"; + timeMap.put("CancelCommentLike", + System.currentTimeMillis()); + handler.sendMessageDelayed(msg, + 1000); + return; + } else { + commentList + .get(index) + .getFeedback() + .setUp(commentList + .get(index) + .getFeedback() + .getUp() - 1); + } + } + } else { + commentFeedbackMap = new ArrayMap(); + } + commentFeedbackMap.put(commentList.get(index) + .getId(), "down"); + commentList + .get(index) + .getFeedback() + .setDown( + commentList.get(index) + .getFeedback() + .getDown() + 1); + if (entity.getMore() == null) { + updateSingleRow(essaydetails_lv_show, + index + 2); + } else { + updateSingleRow(essaydetails_lv_show, index + + 2 + entity.getMore().size()); + } + Message msg = Message.obtain(); + msg.what = Constants.SEND_COMMENT_FEEDBACK; + msg.arg1 = 1; + msg.arg2 = index; + msg.obj = "SendCommentUnlike"; + timeMap.put("SendCommentUnlike", + System.currentTimeMillis()); + handler.sendMessageDelayed(msg, 1000); + } + }); + } else if (isLoading + && ((entity.getMore() == null && position == 2 + commentList + .size()) || (entity.getMore() != null && position == 2 + + entity.getMore().size() + commentList.size()))) { + view = LayoutInflater.from(parent.getContext()).inflate( + R.layout.refresh_footerview, parent, false); + holder = new ViewHolder(view, 4); + if (isNetworkError) { + holder.footerview_progressbar.setVisibility(View.GONE); + holder.footerview_tv_loading.setText("加载失败,点击重试"); + holder.rootView.setClickable(true); + holder.rootView + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + isNetworkError = false; + adapter.notifyDataSetChanged(); + getComment(commentList.size()); + } + }); + } else { + holder.footerview_progressbar.setVisibility(View.VISIBLE); + holder.footerview_tv_loading.setText("加载中..."); + holder.rootView.setClickable(false); + } + } else { + if (convertView != null + && ((ViewHolder) convertView.getTag()).type == 5) { + view = convertView; + } else { + RelativeLayout relativeLayout = new RelativeLayout( + NewsActivity.this); + AbsListView.LayoutParams params = new AbsListView.LayoutParams( + LayoutParams.MATCH_PARENT, DisplayUtils.dip2px( + getApplicationContext(), 48)); + relativeLayout.setLayoutParams(params); + view = relativeLayout; + holder = new ViewHolder(view, 5); + } + } + return view; + } + + public void updateSingleRow(ListView listView, int item) { + if (listView != null) { + int start = listView.getFirstVisiblePosition(); + int end = listView.getLastVisiblePosition(); + if (item >= start && item <= end) { + View view = listView.getChildAt(item - start); + getView(item, view, listView); + } + } + } + + } + + public void onEventMainThread(EBPackage busFour) { + if (gameEntity != null && gameEntity.getApk().size() == 1) { + String packageName = gameEntity.getApk().get(0).getPackageName(); + if (packageName.equals(busFour.getPackageName())) { + if ("安装".equals(busFour.getType())) { + essaydetails_tv_download.setVisibility(View.VISIBLE); + essaydetails_progressbar.setVisibility(View.GONE); + essaydetails_tv_per.setVisibility(View.GONE); + essaydetails_tv_download.setText("启动《" + + gameEntity.getName() + "》"); + } else if ("卸载".equals(busFour.getType())) { + essaydetails_tv_download.setVisibility(View.VISIBLE); + essaydetails_progressbar.setVisibility(View.GONE); + essaydetails_tv_per.setVisibility(View.GONE); + essaydetails_tv_download.setText("下载《" + + gameEntity.getName() + "》"); + } + } + } + } + + public void onEventMainThread(EBNetworkState busNetworkState) { + if (busNetworkState.isNetworkConnected()) { + if (reuse_no_connection.getVisibility() == View.VISIBLE) { + essaydetails_lv_show.setVisibility(View.VISIBLE); + essaydetails_ll_loading.setVisibility(View.VISIBLE); + essaydetails_ll_bottom.setVisibility(View.VISIBLE); + reuse_no_connection.setVisibility(View.GONE); + handler.postDelayed(runnable, 1000); + } else if (isNetworkError) { + isNetworkError = false; + adapter.notifyDataSetChanged(); + getComment(commentList.size()); + } + } + } + + public void onEventMainThread(EBPWDismiss dismiss) { + if (dismissEntity != null) { + dismissEntity.setShow(false); + } + } + + private void invalidate() { + essaydetails_progressbar + .setProgress((int) (downloadEntry.getPercent() * 10)); + switch (downloadEntry.getStatus()) { + case downloading: + essaydetails_tv_per.setText(downloadEntry.getPercent() + "%"); + break; + case pause: + case neterror: + essaydetails_tv_per.setText("继续"); + break; + case done: + EventBus.getDefault().post( + new EBPutUrl(gameEntity.getApk().get(0).getPackageName(), + downloadEntry.getUrl())); + essaydetails_tv_per.setText("安装"); + break; + case cancel: + case hijack: + essaydetails_tv_download.setVisibility(View.VISIBLE); + essaydetails_progressbar.setVisibility(View.GONE); + essaydetails_tv_per.setVisibility(View.GONE); + if (TextUtils.isEmpty(gameEntity.getDownloadAddWord())) { + essaydetails_tv_download.setText("下载《" + gameEntity.getName() + + "》"); + } else { + essaydetails_tv_download.setText("下载《" + gameEntity.getName() + + "》" + gameEntity.getDownloadAddWord()); + } + break; + default: + break; + } + } + + // 获取文章评论 + private void getComment(int offset) { + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp( + Config.HOST + "v1d45/news/" + entity.getId() + + "/comment?limit=10&offset=" + offset, + Constants.COMMENT_CD), + new Response.Listener() { + + @Override + public void onResponse(JSONArray response) { + Utils.log(response.toString()); + if (!isDestroy) { + Gson gson = new Gson(); + Type listType = new TypeToken>() { + }.getType(); + ArrayList list = gson.fromJson( + response.toString(), listType); + if (list.size() < 10) { + isLoading = false; + } + commentList.addAll(list); + adapter.notifyDataSetChanged(); + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + // 无网络连接和访问超时 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + if (!isDestroy) { + // TODO 处理加载时断网或超时情况 + Toast.makeText(NewsActivity.this, "网络错误", + Toast.LENGTH_SHORT).show(); + isNetworkError = true; + adapter.notifyDataSetChanged(); + } + } + } + }); + AppController.addToRequestQueue(request, NewsActivity.class); + } + + private void showCommentDialog(final View v, CharSequence text, + int lineCount) { + KeyboardLayout contentView = (KeyboardLayout) View.inflate(this, + R.layout.dialog_essay_comment, null); + popupWindow = new PopupWindow(contentView, LayoutParams.MATCH_PARENT, + LayoutParams.MATCH_PARENT, true); + + final EditText content = (EditText) contentView + .findViewById(R.id.dialog_et_comment_content); + + final TextView send = (TextView) contentView + .findViewById(R.id.dialog_tv_comment_send); + + contentView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + popupWindow.dismiss(); + essaydetails_tv_comment_content.setText(content.getText()); + } + }); + contentView + .setOnKeyboardChangedListener(new OnKeyboardChangedListener() { + @Override + public void OnKeyboardChanged(int w, int h, int oldw, + int oldh) { + if (oldh != 0 && h > oldh) { + if (popupWindow != null && popupWindow.isShowing()) { + popupWindow.dismiss(); + essaydetails_tv_comment_content.setText(content + .getText()); + } + } + } + }); + + content.addTextChangedListener(new TextWatcher() { + + @Override + public void onTextChanged(CharSequence s, int start, int before, + int count) { + + int line = content.getLineCount(); + if (line != 0) { + LinearLayout.LayoutParams lparams = (LinearLayout.LayoutParams) content + .getLayoutParams(); + if (line == 1) { + lparams.height = DisplayUtils.dip2px( + getApplicationContext(), 34); + } else { + lparams.height = DisplayUtils.dip2px( + getApplicationContext(), 20) + + (line > 3 ? 3 : line) + * DisplayUtils.dip2px(getApplicationContext(), + 12); + } + content.setLayoutParams(lparams); + } + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + content.setText(text); + if (lineCount != 0) { + LinearLayout.LayoutParams lparams = (LinearLayout.LayoutParams) content + .getLayoutParams(); + if (lineCount == 1) { + lparams.height = DisplayUtils.dip2px(getApplicationContext(), + 34); + } else { + lparams.height = DisplayUtils.dip2px(getApplicationContext(), + 20) + + (lineCount > 3 ? 3 : lineCount) + * DisplayUtils.dip2px(getApplicationContext(), 12); + } + content.setLayoutParams(lparams); + } + content.requestFocus(); + + send.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + popupWindow.dismiss(); + essaydetails_tv_comment_content.setText(content.getText()); + sendComment(content.getText()); + } + }); + + popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() { + @Override + public void onDismiss() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + getTintManager().setStatusBarTintResource( + R.color.theme_colors); + } + } + }); + + popupWindow.setFocusable(true); + popupWindow + .setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE + | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); + popupWindow.showAtLocation(v, Gravity.BOTTOM, 0, 0); + + // #0E6295 #0E6195 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + getTintManager().setStatusBarTintColor(0xff0E6295); + } + } + + // 发送评论 + private void sendComment(final CharSequence text) { + + if (text.length() == 0) { + Toast.makeText(this, "请输入评论内容!", Toast.LENGTH_SHORT).show(); + return; + } + + final Dialog dialog = DialogUtils.showWaitDialog(this, "发送中..."); + + new Thread() { + @Override + public void run() { + String url = Config.HOST + "v1d45/news/" + entity.getId() + + "/comment?time=" + System.currentTimeMillis(); + Map params = new HashMap(); + params.put("content", text.toString()); + JSONObject body = new JSONObject(params); + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Method.POST, url, body.toString(), + new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + Utils.log(response.toString()); + dialog.dismiss(); + try { + if (response.getString("status").equals( + "success")) { + essaydetails_tv_comment_content + .setText(""); + Toast.makeText(NewsActivity.this, + "发送成功", Toast.LENGTH_SHORT) + .show(); + Gson gson = new Gson(); + CommentEntity commentEntity = gson + .fromJson( + response.getJSONObject( + "comment") + .toString(), + CommentEntity.class); + commentList.add(0, commentEntity); + adapter.notifyDataSetChanged(); + + modifyNewsCommentVolleyCache( + 0, + response.getJSONObject("comment")); + } else if (response.getString("status") + .equals("refuse")) { + Toast.makeText(NewsActivity.this, + "评论太频繁,请稍后再试", + Toast.LENGTH_SHORT).show(); + } else if (response.getString("status") + .equals("device_block") + || response.getString("status") + .equals("user_block")) { + Toast.makeText(NewsActivity.this, + "你已被禁言,请稍后再试", + Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(NewsActivity.this, + "发送失败", Toast.LENGTH_SHORT) + .show(); + } + } catch (JSONException e) { + e.printStackTrace(); + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + + Utils.log(error.toString()); + if (error.networkResponse != null) { + Utils.log(new String( + error.networkResponse.data)); + } + dialog.dismiss(); + Toast.makeText(NewsActivity.this, "发送失败", + Toast.LENGTH_SHORT).show(); + } + }); + String token = TokenUtils.getToken(NewsActivity.this); + request.addHeader("Auth", token); + request.addHeader("Device", + DeviceUtils.getDeviceHeader(NewsActivity.this)); + request.setShouldCache(false); + AppController.addToRequestQueue(request, NewsActivity.class); + } + }.start(); + } + + /* + * 修改新闻评论的volley缓存 + */ + private void modifyNewsCommentVolleyCache(int offset, JSONObject commentData) { + File cacheDir = new File(getCacheDir(), DEFAULT_CACHE_DIR); + DiskBasedCache cache = new DiskBasedCache(cacheDir); + String key = TimestampUtils.addTimestamp(Config.HOST + "v1d45/news/" + + entity.getId() + "/comment?limit=10&offset=" + offset, + Constants.COMMENT_CD); + byte[] data = cache.getData(key); + if (data != null) { + try { + JSONArray jsonArray = new JSONArray(new String( + GzipUtils.decompressBytes(data))); + JSONArray newComment = new JSONArray(); + newComment.put(commentData); + for (int i = 0, size = jsonArray.length() > 9 ? 9 : jsonArray + .length(); i < size; i++) { + newComment.put(jsonArray.get(i)); + } + Utils.log(newComment.toString()); + cache.modify(key, GzipUtils.compressBytes(newComment.toString() + .getBytes())); + if (jsonArray.length() == 10) { + modifyNewsCommentVolleyCache(offset + 10, + jsonArray.getJSONObject(9)); + } + } catch (JSONException e) { + e.printStackTrace(); + } + } + } + + /* + * 修改新闻反馈的volley缓存 + */ + private void modifyNewsFeedbackVolleyCache(String action, int value) { + if (TextUtils.isEmpty(action)) { + return; + } + String key = TimestampUtils.addTimestamp(Config.HOST + "v1d45/news/" + + entity.getId() + "/feedback", Constants.COMMENT_CD); + File cacheDir = new File(getCacheDir(), DEFAULT_CACHE_DIR); + DiskBasedCache cache = new DiskBasedCache(cacheDir); + byte[] data = cache.getData(key); + if (data != null) { + try { + JSONObject jsonObject = new JSONObject(new String( + GzipUtils.decompressBytes(data))); + jsonObject.put(action, jsonObject.getInt(action) + value); + Utils.log(jsonObject.toString()); + cache.modify(key, GzipUtils.compressBytes(jsonObject.toString() + .getBytes())); + } catch (JSONException e) { + e.printStackTrace(); + } + } + } + + /* + * 修改用户对新闻的反馈的volley缓存 + */ + private void modifyUserNewsFeedbackVolleyCache(String action) { + String key = TimestampUtils.addTimestamp(Config.HOST + "v1d45/news/" + + entity.getId() + "/user/feedback", Constants.COMMENT_CD); + File cacheDir = new File(getCacheDir(), DEFAULT_CACHE_DIR); + DiskBasedCache cache = new DiskBasedCache(cacheDir); + byte[] data = cache.getData(key); + if (data != null) { + try { + JSONObject jsonObject = new JSONObject(new String( + GzipUtils.decompressBytes(data))); + if (!jsonObject.isNull("news")) { + if (action == null) { + modifyNewsFeedbackVolleyCache( + jsonObject.getJSONObject("news").getString( + "action"), -1); + jsonObject.getJSONObject("news").put("action", ""); + } else { + modifyNewsFeedbackVolleyCache( + jsonObject.getJSONObject("news").getString( + "action"), -1); + jsonObject.getJSONObject("news").put("action", action); + modifyNewsFeedbackVolleyCache( + jsonObject.getJSONObject("news").getString( + "action"), 1); + } + } else { + if (action != null) { + JSONObject news = new JSONObject(); + news.put("action", action); + jsonObject.put("news", news); + modifyNewsFeedbackVolleyCache(action, 1); + } + } + Utils.log(jsonObject.toString()); + cache.modify(key, GzipUtils.compressBytes(jsonObject.toString() + .getBytes())); + } catch (JSONException e) { + e.printStackTrace(); + } + } + } + + /* + * 修改用户对评论的反馈的volley缓存 + */ + private void modifyUserCommentFeedbackVolleyCache(String id, String action) { + String key = TimestampUtils.addTimestamp(Config.HOST + "v1d45/news/" + + entity.getId() + "/user/feedback", Constants.COMMENT_CD); + File cacheDir = new File(getCacheDir(), DEFAULT_CACHE_DIR); + DiskBasedCache cache = new DiskBasedCache(cacheDir); + byte[] data = cache.getData(key); + if (data != null) { + try { + JSONObject jsonObject = new JSONObject(new String( + GzipUtils.decompressBytes(data))); + JSONArray comment = jsonObject.getJSONArray("comment"); + if (comment.length() != 0) { + if (action == null) { + JSONArray newComment = new JSONArray(); + for (int i = 0; i < comment.length(); i++) { + JSONObject item = comment.getJSONObject(i); + if (!item.getString("id").equals(id)) { + newComment.put(item); + } else { + modifyCommentFeedbackVolleyCache(0, id, + item.getString("action"), -1); + } + } + jsonObject.put("comment", newComment); + } else { + for (int i = 0; i < comment.length(); i++) { + JSONObject item = comment.getJSONObject(i); + if (item.getString("id").equals(id)) { + modifyCommentFeedbackVolleyCache(0, id, + item.getString("action"), -1); + item.put("action", action); + modifyCommentFeedbackVolleyCache(0, id, + item.getString("action"), 1); + break; + } + } + jsonObject.put("comment", comment); + } + } else { + if (action != null) { + JSONObject item = new JSONObject(); + item.put("id", id); + item.put("action", action); + comment.put(item); + jsonObject.put("comment", comment); + modifyCommentFeedbackVolleyCache(0, id, action, 1); + } + } + Utils.log(jsonObject.toString()); + cache.modify(key, GzipUtils.compressBytes(jsonObject.toString() + .getBytes())); + } catch (JSONException e) { + e.printStackTrace(); + } + } + } + + /* + * 修改评论反馈的volley缓存 + */ + private void modifyCommentFeedbackVolleyCache(int offset, String id, + String action, int value) { + String key = TimestampUtils.addTimestamp(Config.HOST + "v1d45/news/" + + entity.getId() + "/comment?limit=10&offset=" + offset, + Constants.COMMENT_CD); + File cacheDir = new File(getCacheDir(), DEFAULT_CACHE_DIR); + DiskBasedCache cache = new DiskBasedCache(cacheDir); + byte[] data = cache.getData(key); + if (data != null) { + try { + JSONArray jsonArray = new JSONArray(new String( + GzipUtils.decompressBytes(data))); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject comment = jsonArray.getJSONObject(i); + if (comment.getString("_id").equals(id)) { + JSONObject feedback = comment.getJSONObject("feedback"); + feedback.put(action, feedback.getLong(action) + value); + feedback.put( + "val", + feedback.getLong("up") + - feedback.getLong("down")); + Utils.log(jsonArray.toString()); + cache.modify(key, GzipUtils.compressBytes(jsonArray + .toString().getBytes())); + return; + } + } + if (jsonArray.length() == 10) { + modifyCommentFeedbackVolleyCache(offset + 10, id, action, + value); + } + } catch (JSONException e) { + e.printStackTrace(); + } + } + } + + /* + * 修改新闻的反馈 + */ + private void modifyNewsFeedback(String news_id, String action) { + final String url = Config.HOST + "v1d45/news/" + news_id + "/feedback/" + + action; + new Thread() { + @Override + public void run() { + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Method.POST, url, new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + Utils.log("modifyNewsFeedback = " + + response.toString()); + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + Utils.log("modifyNewsFeedback = " + + error.toString()); + } + }); + String token = TokenUtils.getToken(NewsActivity.this); + request.addHeader("Auth", token); + request.setShouldCache(false); + AppController.addToRequestQueue(request, NewsActivity.this); + } + }.start(); + } + + /* + * 取消对新闻的反馈 + */ + private void cancelNewsFeedback(String news_id) { + final String url = Config.HOST + "v1d45/news/" + news_id + "/feedback"; + new Thread() { + @Override + public void run() { + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Method.POST, url, new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + Utils.log("cancelNewsFeedback = " + + response.toString()); + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + Utils.log("cancelNewsFeedback = " + + error.toString()); + } + }); + String token = TokenUtils.getToken(NewsActivity.this); + request.addHeader("Auth", token); + request.setShouldCache(false); + AppController.addToRequestQueue(request, NewsActivity.this); + } + }.start(); + } + + /* + * 修改评论的反馈 + */ + private void modifyCommentFeedback(String news_id, String comment_id, + String action) { + final String url = Config.HOST + "v1d45/news/" + news_id + "/comment/" + + comment_id + "/feedback/" + action; + new Thread() { + @Override + public void run() { + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Method.POST, url, new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + Utils.log("modifyCommentFeedback = " + + response.toString()); + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + Utils.log("modifyCommentFeedback = " + + error.toString()); + } + }); + String token = TokenUtils.getToken(NewsActivity.this); + request.addHeader("Auth", token); + request.setShouldCache(false); + AppController.addToRequestQueue(request, NewsActivity.this); + } + }.start(); + } + + /* + * 取消对评论的反馈 + */ + + private void cancelCommentFeedback(String news_id, String comment_id) { + final String url = Config.HOST + "v1d45/news/" + news_id + "/comment/" + + comment_id + "/feedback"; + new Thread() { + @Override + public void run() { + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Method.POST, url, new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + Utils.log("cancelCommentFeedback = " + + response.toString()); + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + Utils.log("cancelCommentFeedback = " + + error.toString()); + } + }); + String token = TokenUtils.getToken(NewsActivity.this); + request.addHeader("Auth", token); + request.setShouldCache(false); + AppController.addToRequestQueue(request, NewsActivity.this); + } + }.start(); + } + + @Override + public void onResume() { + super.onResume(); + if (gameEntity != null && gameEntity.getApk().size() == 1) { + if (PackageManager.isInstalled(gameEntity.getApk().get(0) + .getPackageName())) { + essaydetails_tv_download.setVisibility(View.VISIBLE); + essaydetails_progressbar.setVisibility(View.GONE); + essaydetails_tv_per.setVisibility(View.GONE); + if (TextUtils.isEmpty(gameEntity.getDownloadAddWord())) { + essaydetails_tv_download.setText("启动《" + + gameEntity.getName() + "》"); + } else { + essaydetails_tv_download.setText("启动《" + + gameEntity.getName() + "》" + + gameEntity.getDownloadAddWord()); + } + } else { + String url = gameEntity.getApk().get(0).getUrl(); + for (DownloadEntry entry : DownloadManager.getInstance( + getApplicationContext()).getAll()) { + if (url.equals(entry.getUrl())) { + downloadEntry = entry; + essaydetails_tv_download.setVisibility(View.GONE); + essaydetails_progressbar.setVisibility(View.VISIBLE); + essaydetails_tv_per.setVisibility(View.VISIBLE); + invalidate(); + break; + } + } + } + } + DownloadManager.getInstance(this).addObserver(dataWatcher); + } + + @Override + public void finish() { + + long end = Calendar.getInstance().getTimeInMillis(); + + int seconds = (int) ((end - start) / 1000); + + String cost = ""; + if (seconds < 5) { + cost = "小于5秒"; + } else if (seconds < 30) { + cost = "5秒-30秒"; + } else if (seconds < 60) { + cost = "30秒-60秒"; + } else { + cost = "大于60秒"; + } + + // 阅读报告 + Map kv = new HashMap(); + kv.put(entrance, "阅读数"); + kv.put(entrance, "用时:" + cost); + TCAgent.onEvent(NewsActivity.this, "文章数据", entity.getTitle(), kv); + + if ("主页-卡牌头条".equals(entrance)) { + Map kv2 = new HashMap(); + kv2.put(entity.getTitle(), "阅读数"); + kv2.put(entity.getTitle(), "用时:" + cost); + TCAgent.onEvent(this, "主页数据", "卡牌头条", kv2); + } else if ("主页-卡牌攻略".equals(entrance)) { + Map kv2 = new HashMap(); + kv2.put(entity.getTitle(), "阅读数"); + kv2.put(entity.getTitle(), "用时:" + cost); + TCAgent.onEvent(this, "主页数据", "卡牌攻略", kv2); + } + + Map map = new HashMap(); + map.put("title", entity.getTitle()); + map.put("type", entity.getType()); + map.put("author", entity.getAuthor()); + if (gameEntity != null) { + map.put("game", gameEntity.getName()); + } + map.put("time", seconds); + map.put("createdOn", System.currentTimeMillis() / 1000); + map.put("from", entrance); + DataCollectionManager.onEvent(this, "news", map); + + super.finish(); + } + + @Override + protected void onPause() { + super.onPause(); + statusMap.clear(); + DownloadManager.getInstance(this).removeObserver(dataWatcher); + if (!isSentReport) { + long end = Calendar.getInstance().getTimeInMillis(); + + int seconds = (int) ((end - start) / 1000); + + String cost = ""; + if (seconds < 5) { + cost = "小于5秒"; + } else if (seconds < 30) { + cost = "5秒-30秒"; + } else if (seconds < 60) { + cost = "30秒-60秒"; + } else { + cost = "大于60秒"; + } + + // 阅读报告 + Map kv = new HashMap(); + kv.put("用时", cost); + TCAgent.onEvent(NewsActivity.this, "阅读文章", entity.getTitle(), kv); + isSentReport = true; + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + isDestroy = true; + AppController.canclePendingRequests(NewsActivity.class); + essaydetails_ll_loading = null; + essaydetails_ll_bottom = null; + reuse_no_connection = null; + essaydetails_ll_comment = null; + entity = null; + actionbar_tv_title = null; + essaydetails_tv_download = null; + essaydetails_tv_per = null; + essaydetails_tv_comment_content = null; + essaydetails_tv_comment_send = null; + essaydetails_iv_share = null; + essaydetails_progressbar = null; + gameEntity = null; + downloadEntry = null; + essaydetails_lv_show = null; + adapter = null; + entrance = null; + dismissEntity = null; + lastTimeMap = null; + statusMap = null; + timeMap = null; + commentList = null; + commentFeedbackMap = null; + popupWindow = null; + handler = null; + dataWatcher = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/NewsOrRaidersActivity.java b/app/src/main/java/com/gh/gamecenter/NewsOrRaidersActivity.java new file mode 100644 index 0000000000..1618cca214 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/NewsOrRaidersActivity.java @@ -0,0 +1,192 @@ +package com.gh.gamecenter; + +import android.os.Bundle; +import android.support.v7.widget.DefaultItemAnimator; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup.LayoutParams; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.gh.base.AppController; +import com.gh.base.BaseActivity; +import com.gh.common.view.VerticalItemDecoration; +import com.gh.gamecenter.adapter.NewsOrRaidersListAdapter; +import com.gh.gamecenter.eventbus.EBConcernChanged; +import com.gh.gamecenter.eventbus.EBNetworkState; + +/** + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-8-10 首页资讯或攻略板块 + */ +public class NewsOrRaidersActivity extends BaseActivity { + + private RecyclerView news_list; + private LinearLayoutManager layoutManager; + private NewsOrRaidersListAdapter adapter; + private LinearLayout news_ll_loading, reuse_no_connection; + private TextView news_tv_label; + private RelativeLayout news_rl_label; + private RelativeLayout.LayoutParams rparams; + + private String type; + + private boolean isDestroy; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + type = getIntent().getStringExtra("type"); + + isDestroy = false; + + View contentView = View.inflate(this, + R.layout.activity_news_or_raiders, null); + + init(contentView, type); + + reuse_no_connection.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + news_list.setVisibility(View.GONE); + news_ll_loading.setVisibility(View.VISIBLE); + reuse_no_connection.setVisibility(View.GONE); + adapter = new NewsOrRaidersListAdapter( + NewsOrRaidersActivity.this, news_list, news_ll_loading, + reuse_no_connection, type, news_rl_label, news_tv_label); + news_list.setAdapter(adapter); + } + }); + + rparams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, + LayoutParams.WRAP_CONTENT); + + news_list.setHasFixedSize(true); + layoutManager = new LinearLayoutManager(this); + news_list.setLayoutManager(layoutManager); + news_list.setItemAnimator(new DefaultItemAnimator()); + + adapter = new NewsOrRaidersListAdapter(this, news_list, + news_ll_loading, reuse_no_connection, type, news_rl_label, + news_tv_label); + + news_list.setAdapter(adapter); + news_list.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + + if (event.getAction() == MotionEvent.ACTION_UP) { + v.performClick(); + } + if (news_ll_loading.getVisibility() == View.VISIBLE) { + return true; + } else { + return false; + } + } + }); + news_list.setOnScrollListener(new RecyclerView.OnScrollListener() { + + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + + super.onScrolled(recyclerView, dx, dy); + + int position = layoutManager.findFirstVisibleItemPosition(); + + if (adapter.getPosition_today() != -1 + && position >= adapter.getPosition_today() + && position <= adapter.getTodaySize() + + adapter.getPosition_today()) { + news_tv_label.setText("今天"); + news_tv_label.setBackgroundResource(R.drawable.title_red); + } else if (adapter.getPosition_before() != -1 + && position >= adapter.getPosition_before()) { + news_tv_label.setText("昨天/以前"); + news_tv_label.setBackgroundResource(R.drawable.title_gray); + } else if (adapter.getPosition_mygame() != -1) { + news_tv_label.setText("我的游戏"); + news_tv_label.setBackgroundResource(R.drawable.title_blue); + } + + if (position == adapter.getPosition_today() - 1 + || position == adapter.getPosition_before() - 1) { + int buttom = layoutManager.findViewByPosition(position) + .getBottom(); + if (buttom <= news_rl_label.getHeight()) { + rparams.topMargin = buttom - news_rl_label.getHeight(); + news_rl_label.setLayoutParams(rparams); + } else { + rparams.topMargin = 0; + news_rl_label.setLayoutParams(rparams); + } + } else { + rparams.topMargin = 0; + news_rl_label.setLayoutParams(rparams); + } + } + + @Override + public void onScrollStateChanged(RecyclerView recyclerView, + int newState) { + super.onScrollStateChanged(recyclerView, newState); + + if (!isDestroy + && newState == RecyclerView.SCROLL_STATE_IDLE + && layoutManager.findLastVisibleItemPosition() + 1 == adapter + .getItemCount()) { + if (!adapter.isRemove() && !adapter.isLoading() + && !adapter.isNetworkError()) { + adapter.addList(); + } + } + } + }); + news_list.addItemDecoration(new VerticalItemDecoration(this, 1)); + } + + public void onEventMainThread(EBConcernChanged busSeven) { + adapter.updateMyGameNews(); + } + + public void onEventMainThread(EBNetworkState busNetworkState) { + if (busNetworkState.isNetworkConnected()) { + if (reuse_no_connection.getVisibility() == View.VISIBLE) { + news_list.setVisibility(View.GONE); + news_ll_loading.setVisibility(View.VISIBLE); + reuse_no_connection.setVisibility(View.GONE); + adapter = new NewsOrRaidersListAdapter(this, news_list, + news_ll_loading, reuse_no_connection, type, + news_rl_label, news_tv_label); + news_list.setAdapter(adapter); + } else if (adapter.isNetworkError()) { + adapter.setNetworkError(false); + adapter.notifyItemChanged(adapter.getItemCount()); + adapter.addList(); + } + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + isDestroy = true; + AppController.canclePendingRequests(NewsOrRaidersActivity.class); + news_list = null; + layoutManager = null; + adapter = null; + news_ll_loading = null; + reuse_no_connection = null; + news_tv_label = null; + news_rl_label = null; + rparams = null; + type = null; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/PasswordActivity.java b/app/src/main/java/com/gh/gamecenter/PasswordActivity.java new file mode 100644 index 0000000000..a8696ad919 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/PasswordActivity.java @@ -0,0 +1,392 @@ +package com.gh.gamecenter; + +import java.util.HashMap; +import java.util.regex.Pattern; + +import org.json.JSONException; +import org.json.JSONObject; + +import android.app.Dialog; +import android.os.Bundle; +import android.text.InputType; +import android.text.TextUtils; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.volley.Request.Method; +import com.android.volley.Response; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.base.BaseActivity; +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.common.util.DialogUtils; +import com.gh.common.util.RSEUtils; +import com.gh.common.util.TokenUtils; +import com.gh.common.util.Utils; +import com.gh.gamecenter.entity.UserEntity; +import com.gh.gamecenter.volley.extended.JsonObjectExtendedRequest; + +public class PasswordActivity extends BaseActivity implements OnClickListener { + + private EditText password_et_current, password_et_new, password_et_again; + private View password_line_one, password_line_two, password_line_three; + private ImageView password_iv_show; + + private UserEntity user; + + private boolean isShowPassword = true; + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + user = (UserEntity) AppController.get("user", false); + + View contentView = View.inflate(this, R.layout.activity_password, null); + + if (user.isActivation()) { + init(contentView, "修改密码"); + } else { + init(contentView, "设置密码"); + } + + findViewById(R.id.password_tv_confirm).setOnClickListener(this); + + findViewById(R.id.password_ll_show).setOnClickListener(this); + + password_et_current + .setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (hasFocus) { + password_line_one.setBackgroundColor(0xff1BA4FC); + } else { + password_line_one.setBackgroundColor(0xffCCCCCC); + } + } + }); + password_et_new + .setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (hasFocus) { + password_line_two.setBackgroundColor(0xff1BA4FC); + } else { + password_line_two.setBackgroundColor(0xffCCCCCC); + } + } + }); + password_et_again + .setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (hasFocus) { + password_line_three.setBackgroundColor(0xff1BA4FC); + } else { + password_line_three.setBackgroundColor(0xffCCCCCC); + } + } + }); + + password_et_current + .setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, + KeyEvent event) { + + if (actionId == EditorInfo.IME_ACTION_NEXT) { + String currentPassword = password_et_current + .getText().toString().trim(); + if (TextUtils.isEmpty(currentPassword)) { + Toast.makeText(PasswordActivity.this, "请输入旧密码", + Toast.LENGTH_SHORT).show(); + password_et_current.requestFocus(); + return true; + } + } + return false; + } + }); + password_et_new + .setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, + KeyEvent event) { + + if (actionId == EditorInfo.IME_ACTION_NEXT) { + String newPassword = password_et_new.getText() + .toString().trim(); + if (TextUtils.isEmpty(newPassword)) { + Toast.makeText(PasswordActivity.this, "请输入新密码", + Toast.LENGTH_SHORT).show(); + password_et_new.requestFocus(); + return true; + } else if (newPassword.length() < 6 + || newPassword.length() > 32) { + Toast.makeText(PasswordActivity.this, + "新密码长度错误", Toast.LENGTH_SHORT).show(); + password_et_new.requestFocus(); + return true; + } else if (!Pattern.matches( + Constants.REGEX_PASSWORD, newPassword)) { + Toast.makeText(PasswordActivity.this, + "新密码格式错误", Toast.LENGTH_SHORT).show(); + password_et_new.requestFocus(); + return true; + } + } + return false; + } + }); + password_et_again + .setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, + KeyEvent event) { + + if (actionId == EditorInfo.IME_ACTION_DONE) { + String newPassword = password_et_new.getText() + .toString().trim(); + String confirmPassword = password_et_again + .getText().toString().trim(); + if (TextUtils.isEmpty(newPassword)) { + Toast.makeText(PasswordActivity.this, "请输入新密码", + Toast.LENGTH_SHORT).show(); + password_et_new.requestFocus(); + return true; + } else if (newPassword.length() < 6 + || newPassword.length() > 32) { + Toast.makeText(PasswordActivity.this, + "新密码长度错误", Toast.LENGTH_SHORT).show(); + password_et_new.requestFocus(); + return true; + } else if (!Pattern.matches( + Constants.REGEX_PASSWORD, newPassword)) { + Toast.makeText(PasswordActivity.this, + "新密码格式错误", Toast.LENGTH_SHORT).show(); + password_et_new.requestFocus(); + return true; + } else if (!newPassword.equals(confirmPassword)) { + Toast.makeText(PasswordActivity.this, + "两次输入的密码不相同", Toast.LENGTH_SHORT) + .show(); + password_et_again.requestFocus(); + return true; + } else { + if (user.isActivation()) { + String currentPassword = password_et_current + .getText().toString().trim(); + if (TextUtils.isEmpty(currentPassword)) { + Toast.makeText(PasswordActivity.this, + "请输入旧密码", Toast.LENGTH_SHORT) + .show(); + password_et_current.requestFocus(); + return true; + } else { + Dialog dialog = DialogUtils + .showWaitDialog( + PasswordActivity.this, + "修改中..."); + modifyPassword(dialog, currentPassword, + newPassword); + } + } else { + Dialog dialog = DialogUtils.showWaitDialog( + PasswordActivity.this, "设置中..."); + modifyPassword(dialog, null, newPassword); + } + } + } + return false; + } + }); + + password_et_current.setInputType(InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_NORMAL); + password_et_new.setInputType(InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_NORMAL); + password_et_again.setInputType(InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_NORMAL); + + if (user.isActivation()) { + password_et_current.requestFocus(); + } else { + findViewById(R.id.password_tv_current).setVisibility(View.GONE); + password_et_current.setVisibility(View.GONE); + password_line_one.setVisibility(View.GONE); + password_et_new.requestFocus(); + } + + } + + @Override + public void onClick(View v) { + if (v.getId() == R.id.password_tv_confirm) { + String newPassword = password_et_new.getText().toString().trim(); + String confirmPassword = password_et_again.getText().toString() + .trim(); + if (TextUtils.isEmpty(newPassword)) { + Toast.makeText(this, "请输入新密码", Toast.LENGTH_SHORT).show(); + password_et_new.requestFocus(); + } else if (newPassword.length() < 6 || newPassword.length() > 32) { + Toast.makeText(this, "新密码长度错误", Toast.LENGTH_SHORT).show(); + password_et_new.requestFocus(); + } else if (!Pattern.matches(Constants.REGEX_PASSWORD, newPassword)) { + Toast.makeText(this, "新密码格式错误", Toast.LENGTH_SHORT).show(); + password_et_new.requestFocus(); + } else if (!newPassword.equals(confirmPassword)) { + Toast.makeText(this, "两次输入的密码不相同", Toast.LENGTH_SHORT).show(); + password_et_again.requestFocus(); + } else { + if (user.isActivation()) { + String currentPassword = password_et_current.getText() + .toString().trim(); + if (TextUtils.isEmpty(currentPassword)) { + Toast.makeText(this, "请输入旧密码", Toast.LENGTH_SHORT) + .show(); + password_et_current.requestFocus(); + } else { + Dialog dialog = DialogUtils.showWaitDialog(this, + "修改中..."); + modifyPassword(dialog, currentPassword, newPassword); + } + } else { + Dialog dialog = DialogUtils.showWaitDialog(this, "设置中..."); + modifyPassword(dialog, null, newPassword); + } + } + } else if (v.getId() == R.id.password_ll_show) { + if (isShowPassword) { + isShowPassword = false; + password_iv_show + .setBackgroundResource(R.drawable.login_auto_style); + password_et_current.setInputType(InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_PASSWORD); + password_et_new.setInputType(InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_PASSWORD); + password_et_again.setInputType(InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_PASSWORD); + } else { + isShowPassword = true; + password_iv_show + .setBackgroundResource(R.drawable.login_auto_dn); + password_et_current.setInputType(InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_NORMAL); + password_et_new.setInputType(InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_NORMAL); + password_et_again.setInputType(InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_VARIATION_NORMAL); + } + if (password_et_current.isFocused()) { + password_et_current.setSelection(password_et_current.getText() + .length()); + } + if (password_et_new.isFocused()) { + password_et_new + .setSelection(password_et_new.getText().length()); + } + if (password_et_again.isFocused()) { + password_et_again.setSelection(password_et_again.getText() + .length()); + } + } + } + + // 修改密码 + private void modifyPassword(final Dialog dialog, + final String currentPassword, final String newPassword) { + new Thread() { + @Override + public void run() { + String token = TokenUtils.getToken(PasswordActivity.this); + String url = Config.HOST + "v2/user/password?time=" + + System.currentTimeMillis(); + HashMap params = new HashMap(); + if (currentPassword != null) { + try { + String s = RSEUtils.encryptByPublic(currentPassword + user.getAccount() + System.currentTimeMillis() / 1000); + Utils.log("加密 = " + s); + params.put("current_password", s); + } catch (Exception e) { + + e.printStackTrace(); + } + } + try { + String s = RSEUtils.encryptByPublic(newPassword + user.getAccount() + System.currentTimeMillis() / 1000); + Utils.log("加密 = " + s); + params.put("new_password", s); + } catch (Exception e) { + + e.printStackTrace(); + } + JSONObject body = new JSONObject(params); + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Method.POST, url, body.toString(), + new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + + Utils.log(response.toString()); + dialog.dismiss(); + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + + Utils.log(error.toString()); + dialog.dismiss(); + try { + if (error.networkResponse != null) { + JSONObject response = new JSONObject( + new String(error.networkResponse.data)); + if (!response.isNull("reason")) { + String reason = response + .getString("reason"); + if ("PASSWORD_ERROR".equals(reason)) { + Toast.makeText(PasswordActivity.this, + "两次输入的密码不相同", Toast.LENGTH_SHORT) + .show(); + password_et_again.requestFocus(); + return; + } else if ("PASSWORD_ILLEGAL".equals(reason)) { + Toast.makeText(PasswordActivity.this, + "新密码格式错误", Toast.LENGTH_SHORT) + .show(); + password_et_new.requestFocus(); + return; + } + } + } + } catch (JSONException e) { + + e.printStackTrace(); + } + if (currentPassword != null) { + Toast.makeText(PasswordActivity.this, "修改密码失败", + Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(PasswordActivity.this, "设置密码失败", + Toast.LENGTH_SHORT).show(); + } + } + }); + request.addHeader("Auth", token); + request.setShouldCache(false); + AppController.addToRequestQueue(request, + PasswordActivity.class); + } + }.start(); + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/RetrieveActivity.java b/app/src/main/java/com/gh/gamecenter/RetrieveActivity.java new file mode 100644 index 0000000000..2001b77ffe --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/RetrieveActivity.java @@ -0,0 +1,632 @@ +package com.gh.gamecenter; + +import java.util.HashMap; +import java.util.regex.Pattern; + +import org.json.JSONException; +import org.json.JSONObject; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.text.TextUtils; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.volley.Request.Method; +import com.android.volley.Response; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.base.BaseActivity; +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.common.util.DialogUtils; +import com.gh.common.util.RSEUtils; +import com.gh.common.util.TokenUtils; +import com.gh.common.util.Utils; +import com.gh.gamecenter.eventbus.EBSms; +import com.gh.gamecenter.volley.extended.JsonObjectExtendedRequest; + +public class RetrieveActivity extends BaseActivity implements OnClickListener { + + private LinearLayout retrieve_ll_mobile, retrieve_ll_title, + retrieve_ll_account; + private ImageView retrieve_iv_title, retrieve_iv_mobile_clean, + retrieve_iv_password_clean, retrieve_iv_mobile; + private TextView retrieve_tv_title, retrieve_tv_hint, retrieve_tv_again, + retrieve_tv_confrim, retrieve_tv_account, retrieve_tv_mobile; + private RelativeLayout retrieve_rl_mobile, retrieve_rl_password; + private EditText retrieve_et_account, retrieve_et_password, + retrieve_et_mobile; + private View retrieve_line_one, retrieve_line_two, + retrieve_mobile_cutting_line, retrieve_line; + + private int countdown = 60; + private boolean isDestroy = false; + + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (!isDestroy) { + if (msg.what == 0) { + if (countdown == 0) { + retrieve_tv_again.setText("重新获取"); + retrieve_tv_again + .setBackgroundResource(R.drawable.textview_logout_style); + retrieve_tv_again.setClickable(true); + } else if (countdown > 0) { + retrieve_tv_again.setText("重新获取(" + countdown-- + ")"); + sendEmptyMessageDelayed(0, 1000); + } + } + } + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + View contentView = View.inflate(this, R.layout.activity_retrieve, null); + + init(contentView, "找回密码"); + + retrieve_et_account.requestFocus(); + + retrieve_line = findViewById(R.id.retrieve_line); + + retrieve_tv_again.setOnClickListener(this); + + retrieve_tv_confrim.setOnClickListener(this); + + retrieve_et_account + .setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, + KeyEvent event) { + + if (actionId == EditorInfo.IME_ACTION_DONE) { + String account = retrieve_et_account.getText() + .toString().trim(); + if (TextUtils.isEmpty(account)) { + Toast.makeText(RetrieveActivity.this, "请输入光环号", + Toast.LENGTH_SHORT).show(); + retrieve_et_account.requestFocus(); + return true; + } else if (account.length() < 6 + || account.length() > 18) { + Toast.makeText(RetrieveActivity.this, + "光环号长度错误", Toast.LENGTH_SHORT).show(); + retrieve_et_account.requestFocus(); + return true; + } else { + verifyAccount(account); + } + } + return false; + } + }); + + retrieve_et_mobile + .setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, + KeyEvent event) { + + if (actionId == EditorInfo.IME_ACTION_DONE) { + Utils.log("retrieve_et_mobile"); + } + return false; + } + }); + retrieve_et_mobile + .setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + + if (hasFocus) { + retrieve_rl_mobile.setBackgroundResource(R.drawable.border_input_dn); + } else { + retrieve_rl_mobile.setBackgroundResource(R.drawable.border_input_up); + } + } + }); + + retrieve_et_password + .setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, + KeyEvent event) { + + if (actionId == EditorInfo.IME_ACTION_DONE) { + Utils.log("retrieve_et_password"); + } + return false; + } + }); + retrieve_et_password + .setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + + if (hasFocus) { + retrieve_rl_password.setBackgroundResource(R.drawable.border_input_dn); + } else { + retrieve_rl_password.setBackgroundResource(R.drawable.border_input_up); + } + } + }); + } + + @Override + public void onClick(View v) { + if (v.getId() == R.id.retrieve_tv_confrim) { + String str = retrieve_tv_confrim.getText().toString(); + if ("下一步".equals(str)) { + String account = retrieve_et_account.getText().toString() + .trim(); + if (TextUtils.isEmpty(account)) { + Toast.makeText(RetrieveActivity.this, "请输入光环号", + Toast.LENGTH_SHORT).show(); + retrieve_et_account.requestFocus(); + } else if (account.length() < 6 || account.length() > 18) { + Toast.makeText(RetrieveActivity.this, "光环号长度错误", + Toast.LENGTH_SHORT).show(); + retrieve_et_account.requestFocus(); + } else { + verifyAccount(account); + } + } else if ("返回登录页面".equals(str)) { + finish(); + } else if ("获取验证码".equals(str)) { + String mobileNumber = retrieve_et_mobile.getText().toString() + .trim(); + if (TextUtils.isEmpty(mobileNumber)) { + Toast.makeText(RetrieveActivity.this, "请输入手机号码", + Toast.LENGTH_SHORT).show(); + retrieve_et_mobile.requestFocus(); + } else if (mobileNumber.length() != 11) { + Toast.makeText(RetrieveActivity.this, "手机号码长度错误", + Toast.LENGTH_SHORT).show(); + retrieve_et_mobile.requestFocus(); + } else if (!Pattern.matches(Constants.REGEX_MOBILE, + mobileNumber)) { + Toast.makeText(RetrieveActivity.this, "手机号码错误", + Toast.LENGTH_SHORT).show(); + retrieve_et_mobile.requestFocus(); + } else { + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow( + retrieve_et_mobile.getWindowToken(), 0); + String account = retrieve_et_account.getText().toString() + .trim(); + getCode(account, mobileNumber, true); + } + } else if ("确定修改密码".equals(str)) { + String account = retrieve_tv_account.getText().toString(); + String mobile_number = retrieve_tv_mobile.getText().toString(); + String code = retrieve_et_mobile.getText().toString().trim(); + String password = retrieve_et_password.getText().toString() + .trim(); + if (TextUtils.isEmpty(code)) { + Toast.makeText(RetrieveActivity.this, "验证码为空", + Toast.LENGTH_SHORT).show(); + retrieve_et_mobile.requestFocus(); + } else if (code.length() != 6) { + Toast.makeText(RetrieveActivity.this, "验证码长度错误", + Toast.LENGTH_SHORT).show(); + retrieve_et_mobile.requestFocus(); + } else if (!Pattern.matches("^\\d{6}$", code)) { + Toast.makeText(RetrieveActivity.this, "验证码格式错误", + Toast.LENGTH_SHORT).show(); + retrieve_et_mobile.requestFocus(); + } else if (TextUtils.isEmpty(password)) { + Toast.makeText(RetrieveActivity.this, "请输入密码", + Toast.LENGTH_SHORT).show(); + retrieve_et_password.requestFocus(); + } else if (password.length() < 6 || password.length() > 32) { + Toast.makeText(RetrieveActivity.this, "密码长度错误", + Toast.LENGTH_SHORT).show(); + retrieve_et_password.requestFocus(); + } else if (!Pattern.matches(Constants.REGEX_PASSWORD, password)) { + Toast.makeText(RetrieveActivity.this, "密码格式错误", + Toast.LENGTH_SHORT).show(); + retrieve_et_password.requestFocus(); + } else { + resetPassword(account, mobile_number, code, password); + } + } else if ("确定".equals(str)) { + finish(); + } + } else if (v.getId() == R.id.retrieve_tv_again) { + String account = retrieve_tv_account.getText().toString(); + String mobile_number = retrieve_tv_mobile.getText().toString(); + getCode(account, mobile_number, false); + } + } + + Runnable showSoftInput = new Runnable() { + @Override + public void run() { + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(retrieve_et_mobile, + InputMethodManager.SHOW_FORCED); + } + }; + + private void verifyAccount(final String account) { + final Dialog waitDialog = DialogUtils.showWaitDialog( + RetrieveActivity.this, "检查中..."); + new Thread() { + @Override + public void run() { + String url = Config.HOST + "v2/user/account/verify?account=" + + account + "&time=" + System.currentTimeMillis(); + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + url, new Response.Listener() { + @Override + public void onResponse(JSONObject response) { + + Utils.log(response.toString()); + waitDialog.dismiss(); + try { + String status = response + .getString("status"); + if ("success".equals(status)) { + retrieve_et_account + .setVisibility(View.GONE); + retrieve_line.setVisibility(View.GONE); + retrieve_rl_mobile + .setVisibility(View.VISIBLE); + retrieve_ll_account + .setVisibility(View.VISIBLE); + retrieve_tv_account.setText(account); + retrieve_tv_confrim.setText("获取验证码"); + retrieve_iv_mobile + .setVisibility(View.VISIBLE); + retrieve_mobile_cutting_line + .setVisibility(View.VISIBLE); + retrieve_et_mobile.setText(""); + retrieve_et_mobile.setHint("请输入绑定的手机号"); + retrieve_line_one + .setVisibility(View.VISIBLE); + retrieve_line_two + .setVisibility(View.VISIBLE); + retrieve_et_mobile.requestFocus(); + handler.postDelayed(showSoftInput, 300); + } else if ("nomobile".equals(status)) { + retrieve_et_account + .setVisibility(View.GONE); + retrieve_line.setVisibility(View.GONE); + retrieve_ll_account + .setVisibility(View.VISIBLE); + retrieve_rl_mobile + .setVisibility(View.GONE); + retrieve_tv_confrim.setText("返回登录页面"); + retrieve_tv_account.setText(account); + retrieve_ll_title + .setVisibility(View.VISIBLE); + retrieve_tv_hint + .setVisibility(View.VISIBLE); + retrieve_line_two + .setVisibility(View.VISIBLE); + } + } catch (JSONException e) { + + e.printStackTrace(); + } + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + + Utils.log(error.toString()); + waitDialog.dismiss(); + try { + if (error.networkResponse != null) { + JSONObject response = new JSONObject( + new String( + error.networkResponse.data)); + if (!response.isNull("reason")) { + String reason = response + .getString("reason"); + if ("USER_NO_EXIST".equals(reason)) { + Toast.makeText( + RetrieveActivity.this, + "用户不存在", + Toast.LENGTH_SHORT) + .show(); + return; + } + } + } + } catch (JSONException e) { + + e.printStackTrace(); + } + Toast.makeText(RetrieveActivity.this, "验证失败", + Toast.LENGTH_SHORT).show(); + } + }); + String token = TokenUtils.getToken(RetrieveActivity.this); + request.addHeader("Auth", token); + AppController.addToRequestQueue(request, + RetrieveActivity.class); + } + }.start(); + } + + private void getCode(final String account, final String mobileNumber, + final boolean isFirst) { + final Dialog waitDialog = DialogUtils.showWaitDialog( + RetrieveActivity.this, "发送中..."); + new Thread() { + @Override + public void run() { + String url = Config.HOST + "v2/user/modifypassword/code/" + + mobileNumber + "?account=" + account + "&time=" + + System.currentTimeMillis(); + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + url, new Response.Listener() { + @Override + public void onResponse(JSONObject response) { + + Utils.log(response.toString()); + waitDialog.dismiss(); + try { + if ("success".equals(response + .getString("status"))) { + Toast.makeText(RetrieveActivity.this, + "发送成功", Toast.LENGTH_SHORT) + .show(); + if (isFirst) { + retrieve_ll_mobile + .setVisibility(View.VISIBLE); + retrieve_tv_mobile + .setText(mobileNumber); + retrieve_tv_confrim + .setText("确定修改密码"); + retrieve_iv_mobile + .setVisibility(View.GONE); + retrieve_mobile_cutting_line + .setVisibility(View.GONE); + retrieve_et_mobile.setText(""); + retrieve_et_mobile + .setHint("请输入短信验证码"); + retrieve_rl_password + .setVisibility(View.VISIBLE); + retrieve_tv_again + .setVisibility(View.VISIBLE); + retrieve_line_one + .setVisibility(View.VISIBLE); + retrieve_line_two + .setVisibility(View.VISIBLE); + } + retrieve_tv_again.setClickable(false); + + countdown = 60; + handler.removeMessages(0); + handler.sendEmptyMessage(0); + + retrieve_et_mobile.requestFocus(); + handler.postDelayed(showSoftInput, 300); + } + } catch (JSONException e) { + + e.printStackTrace(); + } + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + + Utils.log(error.toString()); + waitDialog.dismiss(); + try { + if (error.networkResponse != null) { + JSONObject response = new JSONObject( + new String( + error.networkResponse.data)); + if (!response.isNull("reason")) { + String reason = response + .getString("reason"); + if ("TIME_IS_NOT".equals(reason)) { + Toast.makeText( + RetrieveActivity.this, + "请稍后再试", + Toast.LENGTH_SHORT) + .show(); + return; + } else if ("MOBILE_NUMBER_ERROR" + .equals(reason)) { + Toast.makeText( + RetrieveActivity.this, + "手机号码错误", + Toast.LENGTH_SHORT) + .show(); + return; + } + } + } + } catch (JSONException e) { + + e.printStackTrace(); + } + Toast.makeText(RetrieveActivity.this, "发送失败", + Toast.LENGTH_SHORT).show(); + } + }); + String token = TokenUtils.getToken(RetrieveActivity.this); + request.addHeader("Auth", token); + AppController.addToRequestQueue(request, + RetrieveActivity.class); + } + }.start(); + } + + private void resetPassword(final String account, final String mobileNumber, + final String code, final String password) { + final Dialog waitDialog = DialogUtils.showWaitDialog( + RetrieveActivity.this, "修改中..."); + new Thread() { + @Override + public void run() { + String url = Config.HOST + "v2/user/password/reset"; + HashMap params = new HashMap(); + params.put("account", account); + params.put("mobile_number", mobileNumber); + params.put("code", code); + try { + String s = RSEUtils.encryptByPublic(password + account + System.currentTimeMillis() / 1000); + Utils.log("加密 = " + s); + params.put("password", s); + } catch (Exception e) { + + e.printStackTrace(); + } + JSONObject body = new JSONObject(params); + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Method.POST, url, body.toString(), + new Response.Listener() { + @Override + public void onResponse(JSONObject response) { + + Utils.log(response.toString()); + waitDialog.dismiss(); + try { + if ("success".equals(response + .getString("status"))) { + retrieve_tv_confrim.setText("确定"); + retrieve_rl_mobile + .setVisibility(View.GONE); + retrieve_rl_password + .setVisibility(View.GONE); + retrieve_tv_again + .setVisibility(View.GONE); + retrieve_ll_title + .setVisibility(View.VISIBLE); + retrieve_iv_title + .setVisibility(View.GONE); + retrieve_tv_title + .setVisibility(View.VISIBLE); + retrieve_tv_title.setText("操作成功"); + retrieve_tv_hint + .setVisibility(View.VISIBLE); + retrieve_tv_hint.setText("您的密码已经修改成功!"); + } + } catch (JSONException e) { + + e.printStackTrace(); + } + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + + Utils.log(error.toString()); + waitDialog.dismiss(); + try { + if (error.networkResponse != null) { + JSONObject response = new JSONObject( + new String( + error.networkResponse.data)); + if (!response.isNull("reason")) { + String reason = response + .getString("reason"); + if ("USER_NO_EXIST".equals(reason)) { + Toast.makeText( + RetrieveActivity.this, + "用户不存在", + Toast.LENGTH_SHORT) + .show(); + return; + } else if ("CODE_ERROR" + .equals(reason)) { + Toast.makeText( + RetrieveActivity.this, + "验证码错误", + Toast.LENGTH_SHORT) + .show(); + return; + } else if ("CODE_EXPIRE" + .equals(reason)) { + Toast.makeText( + RetrieveActivity.this, + "验证码已过期", + Toast.LENGTH_SHORT) + .show(); + return; + } else if ("PASSWORD_ILLEGAL" + .equals(reason)) { + Toast.makeText( + RetrieveActivity.this, + "密码格式错误", + Toast.LENGTH_SHORT) + .show(); + return; + } + } + } + } catch (JSONException e) { + + e.printStackTrace(); + } + Toast.makeText(RetrieveActivity.this, "修改失败", + Toast.LENGTH_SHORT).show(); + } + }); + String token = TokenUtils.getToken(RetrieveActivity.this); + request.addHeader("Auth", token); + AppController.addToRequestQueue(request, + RetrieveActivity.class); + } + }.start(); + } + + public void onEventMainThread(EBSms sms) { + if ("变更验证".equals(sms.getType()) && retrieve_et_mobile != null) { + retrieve_et_mobile.setText(sms.getCode()); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + isDestroy = true; + retrieve_ll_mobile = null; + retrieve_ll_title = null; + retrieve_ll_account = null; + retrieve_iv_title = null; + retrieve_iv_mobile_clean = null; + retrieve_iv_password_clean = null; + retrieve_iv_mobile = null; + retrieve_tv_title = null; + retrieve_tv_hint = null; + retrieve_tv_again = null; + retrieve_tv_confrim = null; + retrieve_tv_account = null; + retrieve_tv_mobile = null; + retrieve_rl_mobile = null; + retrieve_rl_password = null; + retrieve_et_account = null; + retrieve_et_password = null; + retrieve_et_mobile = null; + retrieve_line_one = null; + retrieve_line_two = null; + retrieve_mobile_cutting_line = null; + retrieve_line = null; + handler = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/SearchActivity.java b/app/src/main/java/com/gh/gamecenter/SearchActivity.java new file mode 100644 index 0000000000..89319863be --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/SearchActivity.java @@ -0,0 +1,314 @@ +package com.gh.gamecenter; + +import java.util.HashMap; +import java.util.Map; + +import android.app.ActionBar.LayoutParams; +import android.app.FragmentManager; +import android.app.FragmentTransaction; +import android.content.Context; +import android.os.Build; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.TextView.OnEditorActionListener; +import android.widget.Toast; + +import com.gh.base.BaseActivity; +import com.gh.common.constant.Config; +import com.gh.common.util.DisplayUtils; +import com.gh.gamecenter.db.SearchHistoryDao; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.manager.SystemBarTintManager; +import com.gh.gamecenter.manager.SystemBarTintManager.SystemBarConfig; +import com.gh.gamecenter.search.Search1DetailFragment; +import com.gh.gamecenter.search.Search2GameListFragment; +import com.gh.gamecenter.search.Search3HistoryFragment; +import com.tendcloud.tenddata.TCAgent; + +public class SearchActivity extends BaseActivity { + + private final static int SEARCH_HISTORY_MODEL = 0; + private final static int GAME_LIST_MODEL = 1; + private final static int GAME_DETAIL_MODEL = 2; + private final static int FIND_NOTHING_MODEL = 3; + + public static String searchKey; + public static boolean readyToSearch = true; + public static TextView searchButton; + public static EditText searchInput; + + private SearchHistoryDao dao; + + private Search1DetailFragment game_detail_fragment; + private Search2GameListFragment game_list_fragment; + private Search3HistoryFragment search_history_fragment; + + private FragmentManager fragmentManager; + + private ImageView searchCancel; + private RelativeLayout searchBack; + + private String hint; + private boolean isFromHome = false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + View contentView = View.inflate(this, R.layout.activity_search, null); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + setTheme(R.style.AppTheme); + setTranslucentStatus(true); + SystemBarTintManager tintManager = new SystemBarTintManager(this); + tintManager.setStatusBarTintEnabled(true); + tintManager.setStatusBarTintResource(R.color.search_theme_colors); + SystemBarConfig config = tintManager.getConfig(); + contentView.setPadding(0, config.getPixelInsetTop(false), 0, + config.getPixelInsetBottom()); + } + + setContentView(contentView); + + dao = new SearchHistoryDao(this); + + fragmentManager = getFragmentManager(); + + isFromHome = getIntent().getExtras().getBoolean("clicked"); + hint = getIntent().getExtras().getString("hint"); + + setActionBarLayout(); + + if (isFromHome && !TextUtils.isEmpty(hint)) { + searchKey = hint; + setResultPresentModel(GAME_DETAIL_MODEL); + } else { + setResultPresentModel(SEARCH_HISTORY_MODEL); + } + } + + public void setActionBarLayout() { + int actionbar_height = getSharedPreferences(Config.PREFERENCE, + Context.MODE_PRIVATE).getInt("actionbar_height", + DisplayUtils.dip2px(getApplicationContext(), 48)); + + LinearLayout reuse_actionbar = (LinearLayout) findViewById(R.id.search_actionbar); + LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams( + LayoutParams.MATCH_PARENT, actionbar_height); + reuse_actionbar.setLayoutParams(lparams); + + searchInput = (EditText) findViewById(R.id.etSearch); + searchInput.setOnEditorActionListener(new OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, + KeyEvent event) { + + if (actionId == EditorInfo.IME_ACTION_SEARCH) { + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(v.getWindowToken(), 0); + searchKey = searchInput.getText().toString().trim(); + if (searchKey.length() < 1) { + if (!TextUtils.isEmpty(hint)) { + searchInput.setText(hint); + searchInput.setSelection(searchInput.getText() + .length()); + searchKey = searchInput.getHint().toString(); + } + } + if (!TextUtils.isEmpty(searchKey)) { + if (readyToSearch) { + readyToSearch = false; + setResultPresentModel(GAME_DETAIL_MODEL); + } + // TODO: add new history + dao.add(searchKey); + } else { + Toast.makeText(SearchActivity.this, "请输入搜索内容", + Toast.LENGTH_SHORT).show(); + } + } + return false; + } + }); + searchButton = (TextView) findViewById(R.id.btnSearch); + searchCancel = (ImageView) findViewById(R.id.ivDeleteText); + searchBack = (RelativeLayout) findViewById(R.id.btnGoBack); + + if (isFromHome && !TextUtils.isEmpty(hint)) { + searchInput.setText(hint); + searchInput.setSelection(searchInput.getText().length()); + } else if (!TextUtils.isEmpty(hint)) { + searchInput.setHint(hint); + } else { + searchInput.setHint("搜索游戏..."); + } + + searchButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(v.getWindowToken(), 0); + searchKey = searchInput.getText().toString().trim(); + if (searchKey.length() < 1) { + if (!TextUtils.isEmpty(hint)) { + searchInput.setText(hint); + searchInput + .setSelection(searchInput.getText().length()); + searchKey = searchInput.getHint().toString(); + } + } + if (!TextUtils.isEmpty(searchKey)) { + if (readyToSearch) { + readyToSearch = false; + setResultPresentModel(GAME_DETAIL_MODEL); + } + // TODO: add new history + dao.add(searchKey); + } else { + Toast.makeText(SearchActivity.this, "请输入搜索内容", + Toast.LENGTH_SHORT).show(); + } + } + }); + + searchCancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + searchCancel.setVisibility(View.GONE); + searchInput.setText(""); + } + + }); + searchInput.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, + int count) { + if (s.length() > 0) { + searchCancel.setVisibility(View.VISIBLE); + } else { + searchCancel.setVisibility(View.GONE); + } + } + + @Override + public void afterTextChanged(Editable s) { + searchKey = s.toString().trim(); + if (searchKey.length() < 1) { + setResultPresentModel(SEARCH_HISTORY_MODEL); + } else { + setResultPresentModel(GAME_LIST_MODEL); + } + } + }); + + searchBack.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + finish(); + } + }); + + } + + private void setResultPresentModel(int model) { + FragmentTransaction transaction = fragmentManager.beginTransaction(); + hideFragments(transaction); + switch (model) { + case GAME_DETAIL_MODEL: + TCAgent.onEvent(SearchActivity.this, "搜索页面", searchKey); + + Map map = new HashMap(); + map.put("key", searchKey); + map.put("from", "搜索页面"); + map.put("createdOn", System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent(this, "search", map); + + if (game_detail_fragment != null) { + transaction.remove(game_detail_fragment); + game_detail_fragment.clearSearchResult(); + game_detail_fragment = null; + } + game_detail_fragment = new Search1DetailFragment(); + game_detail_fragment.SetKeys(searchKey); + transaction.add(R.id.search_result, game_detail_fragment); + break; + + case SEARCH_HISTORY_MODEL: + if (search_history_fragment != null) { + transaction.remove(search_history_fragment); + search_history_fragment.clearSearchResult(); + search_history_fragment = null; + } + search_history_fragment = new Search3HistoryFragment(dao); + transaction.add(R.id.search_result, search_history_fragment); + break; + + case GAME_LIST_MODEL: + if (game_list_fragment != null) { + transaction.remove(game_list_fragment); + game_list_fragment.clearSearchResult(); + game_list_fragment = null; + } + game_list_fragment = new Search2GameListFragment(); + game_list_fragment.SetKeys(searchKey); + transaction.add(R.id.search_result, game_list_fragment); + break; + + case FIND_NOTHING_MODEL: + break; + default: + break; + } + transaction.commit(); + } + + private void hideFragments(FragmentTransaction transaction) { + if (game_detail_fragment != null) { + transaction.hide(game_detail_fragment); + } + if (game_list_fragment != null) { + transaction.hide(game_list_fragment); + } + if (search_history_fragment != null) { + transaction.hide(search_history_fragment); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + return true; + } + + @Override + protected void onDestroy() { + + super.onDestroy(); + dao = null; + game_detail_fragment = null; + game_list_fragment = null; + search_history_fragment = null; + fragmentManager = null; + searchCancel = null; + searchBack = null; + hint = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/SettingActivity.java b/app/src/main/java/com/gh/gamecenter/SettingActivity.java new file mode 100644 index 0000000000..bdff4f115c --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/SettingActivity.java @@ -0,0 +1,588 @@ +package com.gh.gamecenter; + +import java.io.File; +import java.util.HashMap; +import java.util.Map.Entry; + +import org.json.JSONObject; + +import android.app.Activity; +import android.app.Dialog; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.os.Bundle; +import android.os.Handler; +import android.text.Html; +import android.text.Spanned; +import android.text.TextUtils; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.Window; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.volley.Response; +import com.android.volley.VolleyError; +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.FileUtils; +import com.gh.common.util.MD5Utils; +import com.gh.common.util.PackageUtils; +import com.gh.common.util.SpeedUtils; +import com.gh.common.util.Utils; +import com.gh.download.DataWatcher; +import com.gh.download.DownloadEntry; +import com.gh.download.DownloadManager; +import com.gh.download.DownloadStatus; +import com.gh.gamecenter.entity.AppEntity; +import com.gh.gamecenter.entity.GameUpdateEntity; +import com.gh.gamecenter.manager.PackageManager; +import com.gh.gamecenter.volley.extended.JsonObjectExtendedRequest; +import com.google.gson.Gson; +import com.kyleduo.switchbutton.SwitchButton; +import com.tendcloud.tenddata.TCAgent; + +/** + * + * 游戏设置页面 + * + * @author 吕方 + * @since 0814 + * + */ +public class SettingActivity extends BaseActivity implements OnClickListener { + + private SwitchButton setting_sb_autoinstall, setting_sb_autodelete, + setting_sb_deletedata, setting_sb_autoupdate; + private TextView setting_tv_version, app_tv_speed, app_tv_percent, + app_btn_cancel, setting_tv_cache; + private ProgressBar app_pb_progress; + + private SharedPreferences sp; + + private Dialog dialog = null; + + private AppEntity appEntity; + + private boolean isChecking = false; + private boolean isShowDownload = false; + + private Handler handler = new Handler(); + + private DataWatcher dataWatcher = new DataWatcher() { + + @Override + public void onDataChanged(HashMap downloads) { + for (Entry entry : downloads.entrySet()) { + DownloadEntry downloadEntry = entry.getValue(); + if (downloadEntry.getName().contains("光环助手") && isShowDownload) { + app_tv_speed.setText(SpeedUtils.getSpeed(downloadEntry + .getSpeed()) + + "(剩" + + SpeedUtils.getRemainTime(downloadEntry.getSize(), + downloadEntry.getProgress(), + downloadEntry.getSpeed() * 1024) + ")"); + app_pb_progress.setProgress((int) (downloadEntry + .getPercent() * 10)); + app_tv_percent.setText(downloadEntry.getPercent() + "%"); + if (DownloadStatus.done.equals(downloadEntry.getStatus())) { + DownloadManager.getInstance(getApplicationContext()) + .cancel(downloadEntry.getUrl(), false); + if (appEntity != null && appEntity.isIs_force()) { + AppController.getInstance().finishActivity(); + } else { + if (dialog != null) { + dialog.dismiss(); + } + isShowDownload = false; + } + } + } + } + } + + }; + + @Override + public void finish() { + saveCurrentSetting(); + super.finish(); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + View contentView = View.inflate(this, R.layout.activity_setting, null); + + init(contentView, "设置"); + + findViewById(R.id.setting_rl_autoinstall).setOnClickListener(this); + findViewById(R.id.setting_rl_autodelete).setOnClickListener(this); + findViewById(R.id.setting_rl_deletedata).setOnClickListener(this); + findViewById(R.id.setting_rl_autoupdate).setOnClickListener(this); + findViewById(R.id.setting_rl_update).setOnClickListener(this); + findViewById(R.id.setting_rl_feedback).setOnClickListener(this); + findViewById(R.id.setting_rl_cache).setOnClickListener(this); + + if (AppController.get("user", false) != null) { + findViewById(R.id.setting_tv_account).setOnClickListener(this); + } else { + findViewById(R.id.setting_tv_account).setVisibility(View.GONE); + } + + setting_tv_version.setText("当前版本:V" + + PackageUtils.getVersion(getApplicationContext())); + + setting_tv_cache.setText(getCacheSize()); + + sp = getSharedPreferences(Config.PREFERENCE, Activity.MODE_PRIVATE); + + setting_sb_autoinstall.setChecked(sp.getBoolean("autoinstall", true)); + setting_sb_autodelete.setChecked(sp.getBoolean("autodelete", true)); + setting_sb_deletedata.setChecked(sp.getBoolean("deletedata", true)); + setting_sb_autoupdate.setChecked(sp.getBoolean("autoupdate", true)); + + if (sp.getBoolean("isShowDisclaimer", false)) { + TextView setting_tv_disclaimer = (TextView) findViewById(R.id.setting_tv_disclaimer); + setting_tv_disclaimer.setVisibility(View.VISIBLE); + setting_tv_disclaimer.setOnClickListener(this); + } + } + + // 获取缓存大小 + private String getCacheSize() { + File ecDir = getExternalCacheDir(); + long cacheLength = getFolderSize(getCacheDir()); + if (ecDir != null) { + cacheLength += getFolderSize(ecDir); + } + return long2Size(cacheLength); + } + + private long getFolderSize(File folder) { + long size = 0; + size += folder.length(); + if (folder.isDirectory()) { + for (File file : folder.listFiles()) { + if (file.isDirectory()) { + size += getFolderSize(file); + } else { + size += file.length(); + } + } + } + return size; + } + + private String long2Size(Long length) { + float m = length / 1024f / 1024f; + String str = Float.toString(m); + int index = str.lastIndexOf("."); + if (index != -1 && str.length() > index + 3) { + str = str.substring(0, index + 3); + } + return str + "M"; + } + + private void saveCurrentSetting() { + Editor mEditor = sp.edit(); + mEditor.putBoolean("autoinstall", setting_sb_autoinstall.isChecked()); + mEditor.putBoolean("autodelete", setting_sb_autodelete.isChecked()); + mEditor.putBoolean("deletedata", setting_sb_deletedata.isChecked()); + mEditor.putBoolean("autoupdate", setting_sb_autoupdate.isChecked()); + mEditor.apply(); + } + + @Override + public void onClick(final View v) { + switch (v.getId()) { + case R.id.actionbar_rl_back: + finish(); + break; + case R.id.setting_rl_autoinstall: + setting_sb_autoinstall.performClick(); + break; + case R.id.setting_rl_autodelete: + setting_sb_autodelete.performClick(); + break; + case R.id.setting_rl_deletedata: + setting_sb_deletedata.performClick(); + break; + case R.id.setting_rl_autoupdate: + setting_sb_autoupdate.performClick(); + break; + case R.id.setting_rl_update: + dialog = DialogUtils.showWaitDialog(this, "检查更新中..."); + if (isChecking) + break; + isChecking = true; + checkUpdate(); + break; + case R.id.setting_rl_cache: + dialog = DialogUtils.showWaitDialog(this, "清除缓存中..."); + claerCache(); + break; + case R.id.setting_rl_feedback: + startActivity(new Intent(SettingActivity.this, + SuggestionActivity.class)); + break; + case R.id.setting_tv_disclaimer: + String content = sp.getString("disclaimer", null); + if (!TextUtils.isEmpty(content)) { + showDisclaimerDialog(content); + } + break; + case R.id.setting_tv_account: + startActivity(new Intent(SettingActivity.this, + AccountActivity.class)); + break; + default: + break; + } + } + + // 清除缓存 + private void claerCache() { + new Thread() { + @Override + public void run() { + long start = System.currentTimeMillis(); + deleteFolder(getCacheDir()); + deleteFolder(getExternalCacheDir()); + long time = System.currentTimeMillis() - start; + if (time < 1000) { + try { + sleep(1000 - time); + } catch (InterruptedException e) { + + e.printStackTrace(); + } + } + if (dialog != null) { + dialog.dismiss(); + } + handler.post(new Runnable() { + @Override + public void run() { + setting_tv_cache.setText(getCacheSize()); + } + }); + } + }.start(); + } + + private void deleteFolder(File folder) { + if (folder != null) { + if (folder.isDirectory()) { + for (File file : folder.listFiles()) { + if (file.isDirectory()) { + deleteFolder(file); + } else { + file.delete(); + } + } + } + folder.delete(); + } + } + + // 弹出免责声明的窗口 + private void showDisclaimerDialog(String content) { + final Dialog disclaimerDialog = new Dialog(this); + View view = View + .inflate(this, R.layout.setting_disclaimer_dialog, null); + TextView title = (TextView) view + .findViewById(R.id.disclaimer_dialog_title); + title.setText("免责声明"); + TextView message = (TextView) view + .findViewById(R.id.disclaimer_dialog_message); + Spanned spanned = Html.fromHtml(content); + message.setText(spanned); + view.findViewById(R.id.disclaimer_dialog_confirm).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + disclaimerDialog.dismiss(); + } + }); + disclaimerDialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + disclaimerDialog.setContentView(view); + disclaimerDialog.show(); + } + + private void checkUpdate() { + String TD_CHANNEL_ID = (String) PackageUtils.getMetaData(this, + getPackageName(), "TD_CHANNEL_ID"); + String url = Config.HOST + "v2/version?version_name=" + + PackageUtils.getVersion(getApplicationContext()) + + "&channel=" + TD_CHANNEL_ID; + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest(url, + new Response.Listener() { + @Override + public void onResponse(JSONObject response) { + + isChecking = false; + if (dialog != null) { + dialog.dismiss(); + } + + if (response.length() == 0) { + Toast.makeText(SettingActivity.this, "已是最新版本", + Toast.LENGTH_SHORT).show(); + } else { + Gson gson = new Gson(); + appEntity = gson.fromJson(response.toString(), + AppEntity.class); + + float version = Float.valueOf(appEntity + .getVersion()); + float currentVersion = Float.valueOf(PackageUtils + .getVersion(getApplicationContext())); + + if (version > currentVersion) { + // 光环助手 有更新 + GameUpdateEntity game = new GameUpdateEntity(); + game.setName("光环助手V" + appEntity.getVersion()); + game.setPackageName(getPackageName()); + game.setSize(appEntity.getSize()); + game.setVersion(appEntity.getVersion()); + game.setUrl(appEntity.getUrl()); + game.setPlatform("官方版"); + PackageManager.addUpdate(0, game); + + String updateMD5 = MD5Utils.getUpdateMD5( + appEntity.getUrl(), + appEntity.getContent()); + + showUpdateDialog(updateMD5); + } else { + showCancelDialog(); + } + + } + + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + isChecking = false; + if (dialog != null) { + dialog.dismiss(); + } + + Utils.log("error = " + error.toString()); + + Toast.makeText(SettingActivity.this, "检查更新失败", + Toast.LENGTH_SHORT).show(); + } + }); + AppController.addToRequestQueue(request, SettingActivity.class); + } + + private void showUpdateDialog(final String md5) { + dialog = new Dialog(this); + View view = View.inflate(this, R.layout.search_history_delete_dialog, + null); + TextView title = (TextView) view.findViewById(R.id.delete_dialog_title); + title.setText("更新"); + TextView content = (TextView) view + .findViewById(R.id.delete_dialog_message); + + Spanned dialogContent = Html + .fromHtml("

发现新版本!

" + + "更新不会影响用户信息!
" + + "最新版本:V" + + appEntity.getVersion() + + "
" + + "更新包大小:" + + appEntity.getSize() + + "
" + + "更新内容:
" + + appEntity.getContent() + "
" + + "
确定更新吗?"); + + content.setText(dialogContent); + + if (appEntity.isIs_force()) { + dialog.setCanceledOnTouchOutside(false); + dialog.setCancelable(false); + } + view.findViewById(R.id.delete_dialog_cancel).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + if (appEntity.isIs_force()) { + Intent data = new Intent(); + data.putExtra("isForce", true); + setResult(RESULT_OK, data); + finish(); + } else { + if (dialog != null) { + dialog.dismiss(); + } + } + } + }); + view.findViewById(R.id.delete_dialog_confirm).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + if (dialog != null) { + dialog.dismiss(); + } + String path = FileUtils.getDownloadPath( + SettingActivity.this, + "光环助手V" + appEntity.getVersion() + "_" + md5 + + ".apk"); + File file = new File(path); + if (file.exists() && file.length() > 0) { + startActivity(PackageUtils.getInstallIntent(path)); + } else { + TCAgent.onEvent(SettingActivity.this, "软件更新", + "下载开始"); + showDownloadDialog(md5); + } + } + }); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.show(); + } + + private void showDownloadDialog(String md5) { + dialog = new Dialog(SettingActivity.this); + dialog.setCanceledOnTouchOutside(false); + dialog.setCancelable(false); + dialog.closeOptionsMenu(); + View view = View.inflate(this, R.layout.app_updating_dialog, null); + + app_pb_progress = (ProgressBar) view.findViewById(R.id.app_pb_progress); + app_tv_speed = (TextView) view.findViewById(R.id.app_tv_speed); + app_tv_percent = (TextView) view.findViewById(R.id.app_tv_percent); + app_btn_cancel = (TextView) view.findViewById(R.id.app_btn_cancel); + + app_btn_cancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + DownloadManager.getInstance(getApplicationContext()).cancel( + appEntity.getUrl()); + if (appEntity.isIs_force()) { + Intent data = new Intent(); + data.putExtra("isForce", true); + setResult(RESULT_OK, data); + finish(); + } else { + if (dialog != null) { + dialog.dismiss(); + } + isShowDownload = false; + } + } + }); + + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.show(); + + isShowDownload = true; + + String path = FileUtils.getDownloadPath(SettingActivity.this, "光环助手V" + + appEntity.getVersion() + "_" + md5 + ".apk"); + + File file = new File(path); + + if (file.exists()) { + file.delete(); + } + + DownloadEntry downloadEntry = new DownloadEntry(); + downloadEntry.setUrl(appEntity.getUrl()); + downloadEntry.setName("光环助手V" + appEntity.getVersion()); + downloadEntry.setPath(path); + HashMap meta = new HashMap(); + meta.put("platform", "官方版"); + downloadEntry.setMeta(meta); + + DownloadManager.getInstance(getApplicationContext()).cancel( + downloadEntry.getUrl(), false); + + DownloadManager.getInstance(getApplicationContext()).pauseAll(); + + DownloadManager.getInstance(getApplicationContext()).add(downloadEntry); + } + + private void showCancelDialog() { + + final Dialog dialog = new Dialog(SettingActivity.this); + View view = View.inflate(SettingActivity.this, + R.layout.search_history_delete_dialog, null); + TextView title = (TextView) view.findViewById(R.id.delete_dialog_title); + title.setText("更新提示"); + TextView content = (TextView) view + .findViewById(R.id.delete_dialog_message); + + content.setText("已经是最新版本!"); + + view.findViewById(R.id.delete_dialog_rl_cancel) + .setVisibility(View.GONE); + view.findViewById(R.id.delete_dialog_rl_confirm).setVisibility( + View.VISIBLE); + + TextView cancel = (TextView) view + .findViewById(R.id.delete_dialog_confirm); + + cancel.setVisibility(View.VISIBLE); + cancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.show(); + } + + @Override + public void onResume() { + super.onResume(); + DownloadManager.getInstance(SettingActivity.this).addObserver( + dataWatcher); + } + + @Override + public void onPause() { + saveCurrentSetting(); + super.onPause(); + DownloadManager.getInstance(SettingActivity.this).removeObserver( + dataWatcher); + } + + @Override + protected void onDestroy() { + saveCurrentSetting(); + super.onDestroy(); + setting_sb_autoinstall = null; + setting_sb_autodelete = null; + setting_sb_deletedata = null; + setting_sb_autoupdate = null; + setting_tv_version = null; + app_tv_speed = null; + app_tv_percent = null; + app_btn_cancel = null; + setting_tv_cache = null; + app_pb_progress = null; + sp = null; + dialog = null; + appEntity = null; + handler = null; + dataWatcher = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/SplashScreenActivity.java b/app/src/main/java/com/gh/gamecenter/SplashScreenActivity.java new file mode 100644 index 0000000000..a8d16cbe01 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/SplashScreenActivity.java @@ -0,0 +1,705 @@ +package com.gh.gamecenter; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.Type; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Set; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import android.app.ActionBar; +import android.app.ActionBar.LayoutParams; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.os.Bundle; +import android.support.v4.util.ArrayMap; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewPager; +import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.RelativeLayout; + +import com.android.volley.Response; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.base.BaseActivity; +import com.gh.common.constant.Config; +import com.gh.common.util.FileUtils; +import com.gh.common.util.PackageUtils; +import com.gh.common.util.TrafficUtils; +import com.gh.common.util.Utils; +import com.gh.gamecenter.db.info.ConcernInfo; +import com.gh.gamecenter.db.info.FilterInfo; +import com.gh.gamecenter.db.info.GameInfo; +import com.gh.gamecenter.entity.ApkEntity; +import com.gh.gamecenter.entity.GameDigestEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.entity.GameUpdateEntity; +import com.gh.gamecenter.manager.ConcernManager; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.manager.FilterManager; +import com.gh.gamecenter.manager.PackageManager; +import com.gh.gamecenter.manager.SuspectedGameManager; +import com.gh.gamecenter.volley.extended.JsonArrayExtendedRequest; +import com.gh.gamecenter.volley.extended.JsonObjectExtendedRequest; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +/** + * 引导页面 + * + * @author 黄壮华 + * + */ +public class SplashScreenActivity extends BaseActivity { + + private ConcernManager concernManager; + private PackageManager manager; + private SharedPreferences sp; + private boolean isFirst; + + public static boolean isShow = true; + + private String from; + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + isFirst = true; + + sp = getSharedPreferences(Config.PREFERENCE, Context.MODE_PRIVATE); + + from = getIntent().getStringExtra("from"); + + if (sp.getBoolean("isFirstLaunch", true) + || sp.getInt("actionbar_height", 0) != 0) { + setTheme(R.style.AppTheme_Guide); + } else { + setTheme(R.style.AppTheme_Fullscreen); + // 自定义ActionBar + ActionBar mActionBar = getActionBar(); + if (mActionBar != null) { + mActionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); + RelativeLayout relativeLayout = new RelativeLayout(this); + relativeLayout.setBackgroundResource(R.color.theme_colors); + LayoutParams params = new LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + mActionBar.setCustomView(relativeLayout, params);// 自定义ActionBar布局 + } + } + + setContentView(R.layout.activity_splash); + + if (sp.getBoolean("isFirstLaunch", true)) { + findViewById(R.id.splash_ll_normal).setVisibility(View.GONE); + + ViewPager splash_viewPager = (ViewPager) findViewById(R.id.splash_viewPager); + splash_viewPager.setVisibility(View.VISIBLE); + splash_viewPager.setAdapter(new ViewPagerAdapter()); + } + } + + private class ViewPagerAdapter extends PagerAdapter { + + private int[] pics = { R.drawable.splash_01, R.drawable.splash_02, + R.drawable.splash_03, R.drawable.splash_04 }; + + @Override + public int getCount() { + + return pics.length; + } + + @Override + public Object instantiateItem(ViewGroup container, int position) { + + ImageView iv = new ImageView(SplashScreenActivity.this); + iv.setBackgroundResource(pics[position]); + if (position == pics.length - 1) { + iv.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(SplashScreenActivity.this, + MainActivity.class); + startActivity(intent); + finish(); + } + }); + } + container.addView(iv); + return iv; + } + + @Override + public boolean isViewFromObject(View view, Object object) { + + return view == object; + } + + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + + container.removeView((View) object); + object = null; + } + + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + + if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) { + if (sp.getBoolean("isFirstLaunch", true)) { + Intent intent = new Intent(SplashScreenActivity.this, + MainActivity.class); + startActivity(intent); + finish(); + } else { + return true; + } + } + return super.onKeyDown(keyCode, event); + } + + @Override + public void onWindowFocusChanged(boolean hasFocus) { + + super.onWindowFocusChanged(hasFocus); + if (hasFocus && isFirst) { + + // 第一次启动,把package.txt文件内容加载进数据库 + if (sp.getBoolean("isFirstLaunch", true)) { + try { + List list = new ArrayList(); + BufferedReader reader = new BufferedReader( + new InputStreamReader(getAssets().open( + "package.txt"))); + String line = null; + while ((line = reader.readLine()) != null) { + list.add(new FilterInfo(line)); + } + reader.close(); + FilterManager filterManager = new FilterManager( + getApplicationContext()); + filterManager.addAllFilter(list); + } catch (IOException e1) { + + e1.printStackTrace(); + } + } + + isFirst = false; + + checkUpdateFile(); + + concernManager = new ConcernManager(getApplicationContext()); + + /* + * 更新过滤表,获取自动刷新的cd,获取版本对应表 + */ + String time = sp.getString("filter_time", null); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd", + Locale.getDefault()); + String today = format.format(new Date()); + if (!today.equals(time)) { + FilterManager manager = new FilterManager( + getApplicationContext()); + manager.getFilterFromServer(today); + getPlatform(); + } + + getDownloadStatus(); + + getUISetting(); + + /* + * 上传数据 + */ + DataCollectionManager.getInstance(getApplicationContext()).upload(); + + /* + * 初始化已安装软件map,获取游戏更新列表和已安装列表 + */ + manager = new PackageManager(getApplicationContext()); + manager.getInstalledMapFromLocal(); + + getInstalledListFromServer(); + } + } + + /* + * 获取界面设置 + */ + private void getUISetting() { + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Config.HOST + "v1d45/support/setting/ui", + new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + + Utils.log(response.toString()); + // "platform_order":{"normal":["9u","baidu","360"]}} + try { + Editor editor = sp.edit(); + editor.putInt("download_box_row", response + .getJSONObject("download_box") + .getInt("row")); + editor.putInt("download_box_column", + response.getJSONObject("download_box") + .getInt("column")); + editor.putInt( + "game_detail_news_type_tab_column", + response.getJSONObject( + "game_detail_news_type_tab") + .getInt("column")); + JSONObject platformOrder = response + .getJSONObject("platform_order"); + Iterator iterator = platformOrder.keys(); + while (iterator.hasNext()) { + String key = (String) iterator.next(); + JSONArray value = platformOrder + .getJSONArray(key); + Set values = new HashSet(); + for (int i = 0; i < value.length(); i++) { + values.add(i + "=" + value.getString(i)); + } + if ("normal".equals(key)) { + editor.putStringSet( + "platform_order_normal", values); + } else { + editor.putStringSet( + "platform_order_special_" + key, + values); + } + } + editor.apply(); + } catch (JSONException e) { + + e.printStackTrace(); + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + String[] platforms = { "9u", "baidu", "360", "ouwan", + "dangle", "mi", "gf", "huawei", "oppo", + "lenvono", "vivo", "gp", "jifeng", "anzhi", + "ttyy", "07073", "19196", "ayx" }; + if (sp.getStringSet("platform_order_normal", null) == null) { + Set values = new HashSet(); + for (int i = 0; i < platforms.length; i++) { + values.add(i + "=" + platforms[i]); + } + sp.edit().putStringSet("platform_order_normal", values).apply(); + } + + } + }); + AppController.addToRequestQueue(request, SplashScreenActivity.class); + } + + /* + * 获取下载按钮显示状态 + */ + private void getDownloadStatus() { + String TD_CHANNEL_ID = (String) PackageUtils.getMetaData(this, + getPackageName(), "TD_CHANNEL_ID"); + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Config.HOST + "v1d45/support/setting/download/" + TD_CHANNEL_ID + + "/switch", new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + try { + isShow = response.getBoolean("status"); + } catch (JSONException e) { + e.printStackTrace(); + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + isShow = true; + } + }); + AppController.addToRequestQueue(request, SplashScreenActivity.class); + } + + /* + * 检查下载文件夹下是否有旧版本的光环助手的包,有这删除 + */ + private void checkUpdateFile() { + File file = new File(FileUtils.getDownloadDir(this) + File.separator); + if (file.isDirectory()) { + for (File f : file.listFiles()) { + if (!f.isDirectory() && f.getName().startsWith("光环助手V")) { + String name = f.getName(); + int index = name.indexOf("_"); + if (index != -1) { + float version = Float.valueOf(name.substring( + name.indexOf("V") + 1, index)); + float currentVersion = Float.valueOf(PackageUtils + .getVersion(getApplicationContext())); + if (version <= currentVersion) { + f.delete(); + } + } + } + } + } + } + + private void getPlatform() { + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest( + Config.HOST + "v1d45/support/setting/platform", + new Response.Listener() { + @Override + public void onResponse(JSONArray response) { + try { + Set pset = new HashSet(); + for (int i = 0; i < response.length(); i++) { + JSONObject jsonObject = response + .getJSONObject(i); + String code = jsonObject.getString("code"); + String name = jsonObject.getString("name"); + String pic = jsonObject.getString("pic"); + String color = jsonObject.getString("color"); + pset.add(code + "=" + name + "=" + pic + "=" + + color); + } + SharedPreferences sharedPreferences = getSharedPreferences( + "gh_platform", Context.MODE_PRIVATE); + Editor editor = sharedPreferences.edit(); + editor.putStringSet("platform", pset); + editor.apply(); + } catch (JSONException e) { + + e.printStackTrace(); + } + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + + } + }); + AppController.addToRequestQueue(request, SplashScreenActivity.class); + } + + private int iCount; + + private void getInstalledListFromServer() { + List list = manager.getLocalPackageName(); + final int count = list.size(); + final List data = new ArrayList(); + final List useParams = new ArrayList(); + iCount = 0; + for (int i = 0, size = list.size(); i < size; i++) { + final String packageName = list.get(i); + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Config.HOST + "v1d45/support/package/" + list.get(i) + + "/game/digest", + new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + iCount++; + if (response.length() != 0) { + data.add(response); + useParams.add(packageName); + } + if (iCount == count) { + processingInstalledData(data, useParams); + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + iCount++; + if (iCount == count) { + processingInstalledData(data, useParams); + } + } + }); + AppController.addToRequestQueue(request, SplashScreenActivity.class); + } + } + + private void processingInstalledData(List data, + List useParams) { + List list = new ArrayList(); + Gson gson = new Gson(); + ConcernManager manager = new ConcernManager(getApplicationContext()); + for (int i = 0, size = data.size(); i < size; i++) { + GameDigestEntity gameDigestEntity = gson.fromJson(data.get(i) + .toString(), GameDigestEntity.class); + GameInfo gameEntity = new GameInfo(); + gameEntity.setId(gameDigestEntity.getId()); + gameEntity.setPackageName(useParams.get(i)); + manager.updateByEntity(gameEntity, false); + list.add(useParams.get(i)); + } + + // 移除疑似游戏数据库中所有数据 + SuspectedGameManager suspectedGameManager = new SuspectedGameManager( + getApplicationContext()); + suspectedGameManager.deleteAll(); + + getUpdateListFromServer(list); + + updateConcern(); + } + + private void getUpdateListFromServer(List list) { + + Comparator comparator = new Comparator() { + @Override + public int compare(String lhs, String rhs) { + + char[] clhs = lhs.toCharArray(); + char[] crhs = rhs.toCharArray(); + int length = 0; + if (clhs.length < crhs.length) { + length = clhs.length; + } else if (clhs.length > crhs.length) { + length = crhs.length; + } else { + length = clhs.length; + } + for (int i = 0; i < length; i++) { + if (clhs[i] > crhs[i]) { + return 1; + } else if (clhs[i] < crhs[i]) { + return -1; + } else if (i == length - 1) { + if (clhs.length < crhs.length) { + return -1; + } else if (clhs.length > crhs.length) { + return 1; + } else { + return 0; + } + } + } + return 0; + } + }; + + Collections.sort(list, comparator); + + StringBuilder builder = new StringBuilder(); + String packages = null; + PackageManager.clearUpdateList(); + for (int i = 0, sizei = (list.size() / 10) + 1; i < sizei; i++) { + builder.delete(0, builder.length()); + for (int j = i * 10, sizej = (i + 1) * 10 > list.size() ? list + .size() : (i + 1) * 10; j < sizej; j++) { + builder.append(list.get(j) + "-"); + } + if (builder.length() != 0) { + packages = builder.substring(0, builder.length() - 1); + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest( + Config.HOST + "v1d45/support/package/update?package=" + + packages, new Response.Listener() { + + @Override + public void onResponse(JSONArray response) { + + Utils.log("getUpdateList=" + + response.toString()); + if (response.length() != 0) { + + Gson gson = new Gson(); + Type listType = new TypeToken>() {}.getType(); + ArrayList games = gson + .fromJson(response.toString(), + listType); + PackageManager.addUpdateList(games); + } + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + + } + }); + AppController.addToRequestQueue(request, + SplashScreenActivity.class); + } + } + } + + private int cCount; + + private void updateConcern() { + + ArrayList concernId = new ArrayList(); + for (ConcernInfo entity : concernManager.getAllConcern()) { + concernId.add(entity.getId()); + } + + if (concernId.size() != 0) { + cCount = 0; + final int count = concernId.size(); + for (int i = 0, size = concernId.size(); i < size; i++) { + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Config.HOST + "v1d45/game/" + concernId.get(i) + + "/digest", + new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + + cCount++; + Gson gson = new Gson(); + GameEntity gameEntity = gson.fromJson( + response.toString(), GameEntity.class); + + ArrayMap map = concernManager + .getConcernMap(); + ConcernInfo entity = map.get(gameEntity.getId()); + if (entity != null) { + List list = gameEntity.getApk(); + HashMap packageNames = new HashMap(); + for (int j = 0, sizej = list.size(); j < sizej; j++) { + packageNames.put( + list.get(j).getPackageName(), false); + } + entity.setTime(System.currentTimeMillis()); + entity.setPackageNames(packageNames); + concernManager.updateByConcern(entity); + } + if (cCount == count) { + update(); + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + + cCount++; + if (cCount == count) { + update(); + } + } + }); + AppController.addToRequestQueue(request, + SplashScreenActivity.class); + } + } else { + new Thread() { + @Override + public void run() { + update(); + } + }.start(); + } + } + + private void update() { + /* + * 更新关注列表数据 + */ + TrafficUtils spy = TrafficUtils.getInstance(getApplicationContext(), + true); + List concernEntities = concernManager.getAllConcern(); + for (ConcernInfo concernEntity : concernEntities) { + concernEntity.setTime(System.currentTimeMillis()); + int quantity = 0; + HashMap packageNames = new HashMap(); + for (String packageName : concernEntity.getPackageNames().keySet()) { + if (PackageManager.isInstalled(packageName)) { + quantity++; + packageNames.put(packageName, true); + } else { + packageNames.put(packageName, false); + } + } + concernEntity.setPackageNames(packageNames); + concernEntity.setInstalled(quantity > 0 ? true : false); + concernEntity.setInstalledQuantity(quantity); + String tag = null; + int weight = 0; + if (concernEntity.isConcern() && concernEntity.isInstalled()) { + tag = "已关注,已安装"; + weight = 2; + } else if (concernEntity.isConcern() + && !concernEntity.isInstalled()) { + tag = "已关注"; + weight = 1; + } else if (!concernEntity.isConcern() + && concernEntity.isInstalled()) { + tag = "已安装"; + weight = 1; + } + concernEntity.setTag(tag); + long traffic = spy.getTraffic(new ArrayList(concernEntity + .getPackageNames().keySet())); + concernEntity.setTraffic(traffic); + if (traffic > 0) { + weight++; + } + concernEntity.setWeight(weight); + if (weight == 0) { + concernManager.deleteConcern(concernEntity.getId()); + } else { + concernManager.updateByConcern(concernEntity); + } + } + if (!sp.getBoolean("isFirstLaunch", true)) { + + int height = sp.getInt("actionbar_height", 0); + if (height == 0) { + final ActionBar actionBar = getActionBar(); + if (actionBar != null) { + sp.edit().putInt("actionbar_height", actionBar.getHeight()) + .apply(); + } + } + + Intent intent = new Intent(SplashScreenActivity.this, + MainActivity.class); + intent.putExtra("from", from); + if ("plugin".equals(from)) { + intent.putExtra("packageName", + getIntent().getStringExtra("packageName")); + } else if ("mipush_news".equals(from)) { + intent.putExtra("entity", + getIntent().getSerializableExtra("entity")); + } else if ("mipush_plugin".equals(from)) { + intent.putExtra("data", getIntent().getStringExtra("data")); + } else if ("plugin_install".equals(from)) { + intent.putExtra("path", getIntent().getStringExtra("path")); + } + + startActivity(intent); + finish(); + } + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/SuggestionActivity.java b/app/src/main/java/com/gh/gamecenter/SuggestionActivity.java new file mode 100644 index 0000000000..de111b6d3a --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/SuggestionActivity.java @@ -0,0 +1,276 @@ +package com.gh.gamecenter; + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.json.JSONException; +import org.json.JSONObject; + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.text.Editable; +import android.text.Html; +import android.text.Spanned; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.Window; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.volley.Request.Method; +import com.android.volley.Response; +import com.android.volley.VolleyError; +import com.android.volley.toolbox.JsonObjectRequest; +import com.gh.base.AppController; +import com.gh.base.BaseActivity; +import com.gh.common.constant.Config; + +/** + * @author fang + * @from SettingActivity + * @function 填写反馈页面 + * + * */ +public class SuggestionActivity extends BaseActivity implements OnClickListener { + + private TextView tv_suggest_title, tv_suggest_connectway; + private EditText et_suggest_content, et_suggest_connectway; + private TextView btn_suggest_post; + + private boolean isShowing = false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + View contentView = View.inflate(this, R.layout.activity_suggest, null); + + init(contentView, "意见反馈"); + + btn_suggest_post.setOnClickListener(this); + btn_suggest_post.setClickable(false); + + Spanned title = Html.fromHtml("*意见描述"); + tv_suggest_title.setText(title); + + et_suggest_content + .setHint("使用过程中发现的任何问题或者其他建议都欢迎提交给我们~光环助手会努力变得更好更强大!"); + + et_suggest_content.requestFocus(); + + tv_suggest_connectway.setText("邮箱"); + + et_suggest_connectway.setHint("留下您的邮箱,以便我们更好地回复您!"); + et_suggest_content.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, + int count) { + if (s.length() > 0) { + btn_suggest_post.setBackgroundColor(getResources() + .getColor(R.color.theme_colors)); + btn_suggest_post.setClickable(true); + } else { + btn_suggest_post.setClickable(false); + btn_suggest_post.setBackgroundColor(0x881BA4FC); + } + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.actionbar_rl_back: + finish(); + break; + case R.id.btn_suggest_post: + String email = et_suggest_connectway.getText().toString().trim(); + if (TextUtils.isEmpty(email)) { + showConfirmDialog(email); + } else if (isEmailAddress(email)) { + isShowing = true; + Dialog dialog = new Dialog(this); + View view = View.inflate(this, R.layout.set_wait_dialog, null); + TextView message = (TextView) view + .findViewById(R.id.set_wait_message); + message.setText("正在上传中..."); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.setCanceledOnTouchOutside(false); + dialog.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + if (isShowing) { + AppController + .canclePendingRequests(SuggestionActivity.class); + Toast.makeText(SuggestionActivity.this, "取消发送", + Toast.LENGTH_SHORT).show(); + } + } + }); + dialog.show(); + sendSuggestion(dialog, email); + } else { + Toast.makeText(this, "邮箱错误", Toast.LENGTH_SHORT).show(); + } + break; + default: + break; + } + } + + // 弹出确认对话框 + private void showConfirmDialog(final String email) { + final Dialog confirmDialog = new Dialog(this); + View view = View.inflate(this, R.layout.search_history_delete_dialog, + null); + TextView title = (TextView) view.findViewById(R.id.delete_dialog_title); + title.setText("温馨提示"); + TextView content = (TextView) view + .findViewById(R.id.delete_dialog_message); + + content.setText("填写联系方式有助于我们更好的一对一地解决您的问题,确定不填写吗?"); + + TextView cancel = (TextView) view + .findViewById(R.id.delete_dialog_cancel); + cancel.setText("填写"); + cancel.setTextColor(0xffFFFFFF); + cancel.setBackgroundResource(R.drawable.textview_blue_style); + cancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + confirmDialog.dismiss(); + et_suggest_connectway.requestFocus(); + + new Thread() { + public void run() { + try { + sleep(300); + } catch (InterruptedException e) { + + e.printStackTrace(); + } + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(et_suggest_connectway, 0); + } + }.start(); + + } + }); + TextView confirm = (TextView) view + .findViewById(R.id.delete_dialog_confirm); + confirm.setText("提交"); + confirm.setTextColor(0xff999999); + confirm.setBackgroundResource(R.drawable.textview_cancel_style); + confirm.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + confirmDialog.dismiss(); + isShowing = true; + Dialog dialog = new Dialog(SuggestionActivity.this); + View view = View.inflate(SuggestionActivity.this, + R.layout.set_wait_dialog, null); + TextView message = (TextView) view + .findViewById(R.id.set_wait_message); + message.setText("正在上传中..."); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.setCanceledOnTouchOutside(false); + dialog.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + if (isShowing) { + AppController + .canclePendingRequests(SuggestionActivity.class); + Toast.makeText(SuggestionActivity.this, "取消发送", + Toast.LENGTH_SHORT).show(); + } + } + }); + dialog.show(); + sendSuggestion(dialog, email); + } + }); + confirmDialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + confirmDialog.setContentView(view); + confirmDialog.show(); + } + + private void sendSuggestion(final Dialog dialog, String email) { + Map map = new HashMap(); + map.put("message", et_suggest_content.getText().toString().trim()); + map.put("from", email); + JsonObjectRequest request = new JsonObjectRequest(Method.POST, + Config.HOST + "v1d45/support/suggestion", new JSONObject(map), + new Response.Listener() { + @Override + public void onResponse(JSONObject object) { + isShowing = false; + dialog.dismiss(); + + try { + if ("ok".equals(object.getString("status"))) { + Toast.makeText(SuggestionActivity.this, + "提交成功,感谢您的反馈!", Toast.LENGTH_SHORT) + .show(); + finish(); + } else { + Toast.makeText(SuggestionActivity.this, + "提交失败,请稍后尝试!", Toast.LENGTH_SHORT) + .show(); + } + } catch (JSONException e) { + e.printStackTrace(); + } + + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + isShowing = false; + dialog.dismiss(); + Toast.makeText(SuggestionActivity.this, + "发送失败,请检查网络情况!", Toast.LENGTH_LONG).show(); + } + }); + request.setShouldCache(false); + AppController.addToRequestQueue(request, SuggestionActivity.class); + } + + private boolean isEmailAddress(String email) { + Pattern p = Pattern + .compile("^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$"); + Matcher m = p.matcher(email); + return m.matches(); + } + + @Override + protected void onDestroy() { + + super.onDestroy(); + tv_suggest_title = null; + tv_suggest_connectway = null; + et_suggest_content = null; + et_suggest_connectway = null; + btn_suggest_post = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/UserInfoActivity.java b/app/src/main/java/com/gh/gamecenter/UserInfoActivity.java new file mode 100644 index 0000000000..acc4eed8d2 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/UserInfoActivity.java @@ -0,0 +1,464 @@ +package com.gh.gamecenter; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +import org.json.JSONObject; + +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.database.Cursor; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.provider.MediaStore; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup.LayoutParams; +import android.view.WindowManager; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.PopupWindow; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.volley.Request.Method; +import com.android.volley.Response; +import com.android.volley.VolleyError; +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.FileUtils; +import com.gh.common.util.ImageUtils; +import com.gh.common.util.TokenUtils; +import com.gh.common.util.Utils; +import com.gh.common.view.KeyboardLayout; +import com.gh.common.view.KeyboardLayout.OnKeyboardChangedListener; +import com.gh.gamecenter.entity.UserEntity; +import com.gh.gamecenter.eventbus.EBLogout; +import com.gh.gamecenter.volley.extended.JsonObjectExtendedRequest; + +import de.greenrobot.event.EventBus; + +public class UserInfoActivity extends BaseActivity implements OnClickListener { + + private ImageView userinfo_tv_icon; + private TextView userinfo_tv_nickname, userinfo_tv_sign; + + private UserEntity user; + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + user = (UserEntity) AppController.get("user", false); + + View contentView = View.inflate(this, R.layout.activity_userinfo, null); + + init(contentView, "个人设置"); + + contentView.findViewById(R.id.userinfo_tv_logout).setOnClickListener( + this); + contentView.findViewById(R.id.userinfo_ll_icon) + .setOnClickListener(this); + contentView.findViewById(R.id.userinfo_ll_nickname).setOnClickListener( + this); + contentView.findViewById(R.id.userinfo_ll_account).setOnClickListener( + this); + contentView.findViewById(R.id.userinfo_ll_sign) + .setOnClickListener(this); + + TextView userinfo_tv_account = (TextView) findViewById(R.id.userinfo_tv_account); + userinfo_tv_account.setText(user.getAccount()); + + ImageUtils.getInstance(getApplicationContext()).display(user.getIcon(), + userinfo_tv_icon); + userinfo_tv_nickname.setText(user.getName()); + if (user.getSign() != null) { + userinfo_tv_sign.setText(user.getSign()); + } + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == R.id.userinfo_tv_logout) { + DialogUtils.showWaitDialog(this, "退出中..."); + SharedPreferences sp = getSharedPreferences(Config.PREFERENCE, + Context.MODE_PRIVATE); + Editor editor = sp.edit(); + editor.remove("token"); + editor.remove("token_expire"); + editor.remove("isLogin"); + editor.remove("username"); + editor.remove("password"); + editor.apply(); + AppController.remove("user"); + new Thread() { + @Override + public void run() { + try { + sleep(1000); + } catch (InterruptedException e) { + + e.printStackTrace(); + } + EventBus.getDefault().post(new EBLogout(0)); + finish(); + } + }.start(); + } else if (id == R.id.userinfo_ll_icon) { + showModifyIconSelectDialog(v); + } else if (id == R.id.userinfo_ll_nickname) { + showModifyNicknameDialog(v); + } else if (id == R.id.userinfo_ll_sign) { + showModifySignDialog(v); + } + } + + private void showModifyIconSelectDialog(View view) { + View contentView = View.inflate(this, R.layout.dialog_modify_select, + null); + final PopupWindow popupWindow = new PopupWindow(contentView, + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, true); + contentView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + popupWindow.dismiss(); + } + }); + contentView.findViewById(R.id.modify_ll_bottom).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + + } + }); + TextView dialog_register_tv_register = (TextView) contentView + .findViewById(R.id.modify_tv_register); + dialog_register_tv_register.setText("拍照"); + dialog_register_tv_register + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + popupWindow.dismiss(); + openCamera(); + } + }); + TextView dialog_register_tv_onekey = (TextView) contentView + .findViewById(R.id.modify_tv_onekey); + dialog_register_tv_onekey.setText("从相册选择"); + dialog_register_tv_onekey + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + popupWindow.dismiss(); + openAlbum(); + } + }); + contentView.setFocusable(true); + contentView.setFocusableInTouchMode(true); + contentView.setOnKeyListener(new View.OnKeyListener() { + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + + if (keyCode == KeyEvent.KEYCODE_BACK + && event.getRepeatCount() == 0 && popupWindow != null + && popupWindow.isShowing()) { + popupWindow.dismiss(); + } + return false; + } + }); + popupWindow.setTouchable(true); + popupWindow.setFocusable(true); + popupWindow.setAnimationStyle(R.style.mypopwindow_anim_style); + popupWindow.showAtLocation(view, Gravity.BOTTOM, 0, 0); + } + + private static final int TAKEAPICTURE = 0x123; + private static final int OPENALBUM = 0x124; + private static final int CROPIMAGE = 0x125; + + // 打开相机 + private void openCamera() { + File outFile = new File(FileUtils.getPicPath(this, System.currentTimeMillis() + ".jpg")); + picturePath = outFile.getAbsolutePath(); + Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(outFile)); + intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); + startActivityForResult(intent, TAKEAPICTURE); + } + + private String picturePath; + + // 打开相册 + private void openAlbum() { + Intent intent = new Intent(Intent.ACTION_PICK, + MediaStore.Images.Media.EXTERNAL_CONTENT_URI); + startActivityForResult(intent, OPENALBUM); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + + super.onActivityResult(requestCode, resultCode, data); + if (resultCode == RESULT_OK) { + if (requestCode == TAKEAPICTURE) { + Utils.log("picturePath = " + picturePath); + Intent intent = new Intent(this, CropImageActivity.class); + intent.putExtra("path", picturePath); + startActivityForResult(intent, CROPIMAGE); + } else if (requestCode == OPENALBUM) { + Uri selectedImage = data.getData(); + String[] filePathColumn = { MediaStore.Images.Media.DATA }; + + Cursor cursor = getContentResolver().query(selectedImage, + filePathColumn, null, null, null); + cursor.moveToFirst(); + + int columnIndex = cursor.getColumnIndex(filePathColumn[0]); + String picturePath = cursor.getString(columnIndex); + cursor.close(); + + Utils.log("picturePath = " + picturePath); + Intent intent = new Intent(this, CropImageActivity.class); + intent.putExtra("path", picturePath); + startActivityForResult(intent, CROPIMAGE); + } else if (requestCode == CROPIMAGE) { + String url = data.getExtras().getString("url"); + user.setIcon(url); + ImageUtils.getInstance(getApplicationContext()).display(url, + userinfo_tv_icon); + } + } + } + + private void showModifyNicknameDialog(View v) { + KeyboardLayout contentView = (KeyboardLayout) View.inflate(this, + R.layout.dialog_modify_nickname, null); + final PopupWindow popupWindow = new PopupWindow(contentView, + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, true); + + final EditText nickname = (EditText) contentView + .findViewById(R.id.dialog_et_nickname); + nickname.setHint(userinfo_tv_nickname.getText()); + nickname.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, + KeyEvent event) { + + if (actionId == EditorInfo.IME_ACTION_DONE) { + popupWindow.dismiss(); + if (!TextUtils + .isEmpty(nickname.getText().toString().trim())) { + userinfo_tv_nickname.setText(nickname.getText()); + } + } + return false; + } + }); + nickname.requestFocus(); + + contentView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + popupWindow.dismiss(); + } + }); + contentView + .setOnKeyboardChangedListener(new OnKeyboardChangedListener() { + @Override + public void OnKeyboardChanged(int w, int h, int oldw, + int oldh) { + if (oldh != 0 && h > oldh) { + if (popupWindow != null && popupWindow.isShowing()) { + popupWindow.dismiss(); + } + } + } + }); + + contentView.findViewById(R.id.dialog_tv_modify).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + popupWindow.dismiss(); + if (!TextUtils.isEmpty(nickname.getText().toString() + .trim())) { + userinfo_tv_nickname.setText(nickname.getText()); + } + } + }); + + popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() { + @Override + public void onDismiss() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + getTintManager().setStatusBarTintResource( + R.color.theme_colors); + } + } + }); + + popupWindow.setTouchable(true); + popupWindow.setFocusable(true); + popupWindow + .setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE + | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); + popupWindow.showAtLocation(v, Gravity.BOTTOM, 0, 0); + + // #0E6295 #0E6195 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + getTintManager().setStatusBarTintColor(0xff0E6295); + } + + } + + private void showModifySignDialog(View v) { + KeyboardLayout contentView = (KeyboardLayout) View.inflate(this, + R.layout.dialog_modify_sign, null); + final PopupWindow popupWindow = new PopupWindow(contentView, + LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, true); + + final EditText sign = (EditText) contentView + .findViewById(R.id.dialog_et_sign); + sign.requestFocus(); + sign.setHint(userinfo_tv_sign.getText()); + contentView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + popupWindow.dismiss(); + } + }); + contentView + .setOnKeyboardChangedListener(new OnKeyboardChangedListener() { + @Override + public void OnKeyboardChanged(int w, int h, int oldw, + int oldh) { + if (oldh != 0 && h > oldh) { + if (popupWindow != null && popupWindow.isShowing()) { + popupWindow.dismiss(); + } + } + } + }); + + contentView.findViewById(R.id.dialog_tv_confirm).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + popupWindow.dismiss(); + if (!TextUtils + .isEmpty(sign.getText().toString().trim())) { + userinfo_tv_sign.setText(sign.getText()); + } + } + }); + + contentView.findViewById(R.id.dialog_rl_sign).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + + } + }); + + popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() { + @Override + public void onDismiss() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + getTintManager().setStatusBarTintResource( + R.color.theme_colors); + } + } + }); + + popupWindow.setTouchable(true); + popupWindow.setFocusable(true); + popupWindow + .setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE + | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); + popupWindow.showAtLocation(v, Gravity.BOTTOM, 0, 0); + + // #0E6295 #0E6195 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + getTintManager().setStatusBarTintColor(0xff0E6295); + } + } + + @Override + public void finish() { + + String nickname = userinfo_tv_nickname.getText().toString().trim(); + String sign = userinfo_tv_sign.getText().toString().trim(); + if ((!TextUtils.isEmpty(nickname) && !nickname.equals(user.getName())) + || (!TextUtils.isEmpty(sign)) && !sign.equals(user.getSign())) { + updateUserInfo(nickname, sign); + } else { + super.finish(); + } + } + + // 修改用户信息 + private void updateUserInfo(final String name, final String sign) { + final Dialog dialog = DialogUtils.showWaitDialog(this, "保存中..."); + new Thread() { + @Override + public void run() { + String url = Config.HOST + "v2/user/info?time=" + + System.currentTimeMillis(); + Map params = new HashMap(); + if (!TextUtils.isEmpty(name)) { + params.put("name", name); + } + if (!TextUtils.isEmpty(sign)) { + params.put("sign", sign); + } + JSONObject body = new JSONObject(params); + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Method.POST, url, body.toString(), + new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + + Utils.log(response.toString()); + dialog.dismiss(); + user.setName(name); + user.setSign(sign); + EventBus.getDefault().post(new EBLogout(1)); + Toast.makeText(UserInfoActivity.this, "保存成功", + Toast.LENGTH_SHORT).show(); + finish(); + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + + Utils.log(error.toString()); + dialog.dismiss(); + Toast.makeText(UserInfoActivity.this, "保存失败", + Toast.LENGTH_SHORT).show(); + } + }); + String token = TokenUtils.getToken(UserInfoActivity.this); + request.addHeader("Auth", token); + AppController + .addToRequestQueue(request, UserInfoActivity.class); + } + }.start(); + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/ViewImageActivity.java b/app/src/main/java/com/gh/gamecenter/ViewImageActivity.java new file mode 100644 index 0000000000..d86b1824c7 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/ViewImageActivity.java @@ -0,0 +1,150 @@ +package com.gh.gamecenter; + +import java.util.ArrayList; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewPager; +import android.support.v4.view.ViewPager.OnPageChangeListener; +import android.util.DisplayMetrics; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView.ScaleType; +import android.widget.RelativeLayout; + +import com.gh.base.BaseActivity; +import com.gh.common.util.DisplayUtils; +import com.gh.common.util.ImageUtils; +import com.gh.common.view.Gh_ImageView; +import com.gh.common.view.Gh_ImageView.OnSingleTapListener; + +/** + * 查看游戏截图页面 + * + * @author 黄壮华 + * + */ +public class ViewImageActivity extends BaseActivity implements + OnPageChangeListener { + + private ViewPager viewimage_vp_show; + private ViewImageAdapter adapter; + private View viewimage_slide_line; + private RelativeLayout.LayoutParams rparams; + + private ArrayList urls; + + private int current; + private int width; + private String scaleType; + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + Intent intent = getIntent(); + urls = intent.getStringArrayListExtra("urls"); + current = intent.getIntExtra("current", 0); + scaleType = intent.getStringExtra("ScaleType"); + + setContentView(R.layout.activity_viewimage); + + DisplayMetrics outMetrics = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(outMetrics); + width = outMetrics.widthPixels / urls.size(); + + rparams = new RelativeLayout.LayoutParams(width, DisplayUtils.dip2px( + getApplicationContext(), 1)); + rparams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); + rparams.bottomMargin = DisplayUtils.dip2px(getApplicationContext(), 10); + rparams.leftMargin = width * current; + viewimage_slide_line = findViewById(R.id.viewimage_slide_line); + viewimage_slide_line.setLayoutParams(rparams); + + viewimage_vp_show = (ViewPager) findViewById(R.id.viewimage_vp_show); + adapter = new ViewImageAdapter(); + viewimage_vp_show.setAdapter(adapter); + viewimage_vp_show.setCurrentItem(current); + viewimage_vp_show.addOnPageChangeListener(this); + } + + private class ViewImageAdapter extends PagerAdapter implements + OnSingleTapListener { + + @Override + public int getCount() { + + return urls.size(); + } + + @Override + public Object instantiateItem(ViewGroup container, int position) { + + Gh_ImageView imageView = new Gh_ImageView(ViewImageActivity.this); + imageView.setOnSingleTapListener(this); + if (scaleType != null) { + ImageUtils.getInstance(getApplicationContext()).display( + urls.get(position), imageView, ScaleType.FIT_CENTER); + } else { + ImageUtils.getInstance(getApplicationContext()).display( + urls.get(position), imageView); + } + container.addView(imageView); + return imageView; + } + + @Override + public boolean isViewFromObject(View view, Object object) { + + return view == object; + } + + @Override + public void destroyItem(ViewGroup container, int position, Object object) { + + container.removeView((View) object); + object = null; + } + + @Override + public void onSingleTap() { + + finish(); + } + } + + @Override + public void onPageScrollStateChanged(int newState) { + + + } + + @Override + public void onPageScrolled(int position, float positionOffset, + int positionOffsetPixels) { + + if (positionOffset != 0) { + rparams.leftMargin = (int) (width * (positionOffset + position)); + viewimage_slide_line.setLayoutParams(rparams); + } + } + + @Override + public void onPageSelected(int position) { + + + } + + @Override + protected void onDestroy() { + + super.onDestroy(); + viewimage_vp_show = null; + adapter = null; + viewimage_slide_line = null; + rparams = null; + urls = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/adapter/HotCardAdapter.java b/app/src/main/java/com/gh/gamecenter/adapter/HotCardAdapter.java new file mode 100644 index 0000000000..7345be89a4 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/adapter/HotCardAdapter.java @@ -0,0 +1,153 @@ +package com.gh.gamecenter.adapter; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.LinkedBlockingQueue; + +import android.content.Context; +import android.content.Intent; +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 com.gh.base.AppController; +import com.gh.common.util.DownloadItemUtils; +import com.gh.common.util.GameViewUtils; +import com.gh.common.util.ImageUtils; +import com.gh.gamecenter.GameDetailsActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.adapter.viewholder.GameViewHolder; +import com.gh.gamecenter.entity.DismissEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.tendcloud.tenddata.TCAgent; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-8-8 + * @update 2015-8-11 + * @des 首页插件fragment适配器 + */ +public class HotCardAdapter extends + RecyclerView.Adapter { + + private Context context; + + private List list; + + // 黄壮华 获取引用 修改2015/8/15 + private ArrayMap> platformMap; + + private Handler handler; + private ArrayMap lastTimeMap; + private ArrayMap statusMap; + + private DismissEntity dismissEntity; + + // 黄壮华 获取引用 修改2015/8/15 + public HotCardAdapter(Context context, + ArrayMap> pMap, Handler hdler, + ArrayMap ltMap, ArrayMap sMap, + DismissEntity dEntity) { + + // 黄壮华 获取引用 修改2015/8/15 + platformMap = pMap; + handler = hdler; + lastTimeMap = ltMap; + statusMap = sMap; + dismissEntity = dEntity; + + this.context = context; + + list = new ArrayList(); + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + notifyDataSetChanged(); + } + + @Override + public int getItemCount() { + return list.size(); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, + int position) { + if (position != list.size()) { + + GameViewHolder holder = (GameViewHolder) viewHolder; + + final GameEntity entity = list.get(position); + + ImageUtils.getInstance(context).display(entity.getIcon(), + holder.gameThumb); + if (entity.getApk() == null || entity.getApk().isEmpty()) { + holder.gameNameAndSize.setText(entity.getName()); + } else { + holder.gameNameAndSize.setText(entity.getName() + " | " + + entity.getApk().get(0).getSize()); + } + holder.gameDes.setText(entity.getBrief()); + + GameViewUtils.setLabelList(context, holder.labelList, + entity.getTag()); + + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + Map kv = new HashMap(); + kv.put("入口", "热门卡牌"); + TCAgent.onEvent(context, "游戏详情", entity.getName(), kv); + + AppController.put("GameEntity", entity); + Intent intent = new Intent(context, GameDetailsActivity.class); + intent.putExtra("entrance", "热门卡牌"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + }); + + DownloadItemUtils.setOnClickListener(context, holder.downloadBtn, + holder.downloadSpeed, holder.downloadPercentage, + entity, position, this, handler, lastTimeMap, + statusMap, platformMap, "热门卡牌", dismissEntity, "hotcard:" + entity.getName()); + + DownloadItemUtils.updateItem(context, holder.labelList, + holder.gameProgressbar, holder.gameInfo, + holder.downloadSpeed, holder.downloadPercentage, + holder.downloadBtn, entity, platformMap, statusMap); + } + } + + @Override + public int getItemViewType(int position) { + return position; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { + View view; + if (i != list.size()) { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.home_list_item_gamenormal_type, viewGroup, false); + } else { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.refresh_footerview, viewGroup, false); + } + return new GameViewHolder(view); + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/adapter/ImagePagerAdapter.java b/app/src/main/java/com/gh/gamecenter/adapter/ImagePagerAdapter.java new file mode 100644 index 0000000000..d89c1dc9b3 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/adapter/ImagePagerAdapter.java @@ -0,0 +1,132 @@ +/* + * Copyright 2014 trinea.cn All right reserved. This software is the confidential and proprietary information of + * trinea.cn ("Confidential Information"). You shall not disclose such Confidential Information and shall use it only in + * accordance with the terms of the license agreement you entered into with trinea.cn. + */ +package com.gh.gamecenter.adapter; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import android.content.Context; +import android.content.Intent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.gh.base.AppController; +import com.gh.common.util.ImageUtils; +import com.gh.gamecenter.GameDetailsActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.tendcloud.tenddata.TCAgent; + +/** + * ImagePagerAdapter + * + * @author Trinea 2014-2-23 + */ +public class ImagePagerAdapter extends RecyclingPagerAdapter { + + private Context context; + // private List imageIdList; + private List slideList = null; + + private int size; + private boolean isInfiniteLoop; + + // private ImageIndicator indicator; + + public ImagePagerAdapter(Context context, List slideList, + boolean isInfiniteLoop) { + this.context = context; + this.slideList = slideList; + this.size = getSize(slideList); + this.isInfiniteLoop = isInfiniteLoop; + } + + @Override + public int getCount() { + // Infinite loop + return isInfiniteLoop ? Integer.MAX_VALUE : getSize(slideList); + } + + public int getSize(List sourceList) { + return sourceList == null ? 0 : sourceList.size(); + } + + /** + * get really position + * + * @param position + * @return + */ + private int getPosition(int position) { + return isInfiniteLoop ? position % size : position; + } + + @Override + public View getView(int position, View view, ViewGroup container) { + ViewHolder holder; + if (view == null) { + holder = new ViewHolder(); + view = holder.imageView = new ImageView(context); + view.setTag(holder); + } else { + holder = (ViewHolder) view.getTag(); + } + + final GameEntity gameEntity = slideList.get(getPosition(position)); + + ImageUtils.getInstance(context).display(gameEntity.getSlide(), + holder.imageView, R.drawable.preload); + // indicator.setPosition(slideList.size(), getPosition(position)); + + holder.imageView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + Map kv = new HashMap(); + kv.put("入口", "插件-精品-滚动图"); + TCAgent.onEvent(context, "游戏详情", gameEntity.getName(), kv); + + Map map = new HashMap(); + map.put("location", "精品-滚动图"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", gameEntity.getName()); + map.put("page", "插件"); + DataCollectionManager.onEvent(context, "click-item", map); + + AppController.put("GameEntity", gameEntity); + Intent intent = new Intent(context, GameDetailsActivity.class); + intent.putExtra("entrance", "插件-精品滚动图"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + }); + + return view; + } + + private static class ViewHolder { + ImageView imageView; + } + + /** + * @return the isInfiniteLoop + */ + public boolean isInfiniteLoop() { + return isInfiniteLoop; + } + + /** + * @param isInfiniteLoop + * the isInfiniteLoop to set + */ + public ImagePagerAdapter setInfiniteLoop(boolean isInfiniteLoop) { + this.isInfiniteLoop = isInfiniteLoop; + return this; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/adapter/NewsOrRaidersListAdapter.java b/app/src/main/java/com/gh/gamecenter/adapter/NewsOrRaidersListAdapter.java new file mode 100644 index 0000000000..1f37193789 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/adapter/NewsOrRaidersListAdapter.java @@ -0,0 +1,1062 @@ +package com.gh.gamecenter.adapter; + +import java.lang.reflect.Type; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.json.JSONArray; +import org.json.JSONObject; + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.support.v4.util.ArrayMap; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.volley.NoConnectionError; +import com.android.volley.Response; +import com.android.volley.TimeoutError; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.common.util.GameViewUtils; +import com.gh.common.util.ImageUtils; +import com.gh.common.util.NewsUtils; +import com.gh.common.util.TimestampUtils; +import com.gh.gamecenter.GameDetailsActivity; +import com.gh.gamecenter.NewsOrRaidersActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.adapter.viewholder.FooterViewHolder; +import com.gh.gamecenter.db.info.ConcernInfo; +import com.gh.gamecenter.db.info.GameInfo; +import com.gh.gamecenter.db.info.SuspectedGameInfo; +import com.gh.gamecenter.entity.ApkEntity; +import com.gh.gamecenter.entity.GameDigestEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.entity.NewsEntity; +import com.gh.gamecenter.manager.ConcernManager; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.manager.GameManager; +import com.gh.gamecenter.manager.SuspectedGameManager; +import com.gh.gamecenter.volley.extended.JsonArrayExtendedRequest; +import com.gh.gamecenter.volley.extended.JsonObjectExtendedRequest; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.tendcloud.tenddata.TCAgent; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-8-5 modified 2015-8-21 资讯首页模块 + */ +public class NewsOrRaidersListAdapter extends + RecyclerView.Adapter { + + public static class ITEM_TYPE { + public static final int head = 1;// head + public static final int game_type = 2;// 游戏布局类型 + public static final int game_text = 3;// 游戏新闻列表类型 + public static final int news_text = 4;// 新闻列表1类型 + public static final int news_image = 5;// 新闻列表2类型 + public static final int refresh_footer = 6;// 刷新布局类型 + } + + private int position_mygame = -1;// 我的游戏head的位置 + private int position_today = -1;// 今天head的位置 + private int position_before = -1;// 昨天/以前head的位置 + + private int count_game = 0;// 游戏+游戏新闻 的数目 + + private ConcernManager concernManager; + private List concernList; + private List concernGameList; + private ArrayMap> concernNewsMap; + private List todayNewsList; + private List beforeNewsList; + + private boolean isRemove = false; + private boolean isLoading = false; + private boolean isNetworkError = false; + + private LayoutInflater layoutInflater; + private Context context; + + private RecyclerView recyclerView; + private LinearLayout ll_loading, ll_noconnection; + + private RelativeLayout relativeLayout; + private TextView textView; + + private String type; + + public NewsOrRaidersListAdapter(Context con, RecyclerView recyclerView, + LinearLayout linearLayout1, LinearLayout linearLayout2, String str, + RelativeLayout relativeLayout, TextView textView) { + context = con; + + type = str; + + todayNewsList = new ArrayList(); + beforeNewsList = new ArrayList(); + + this.relativeLayout = relativeLayout; + this.textView = textView; + + this.recyclerView = recyclerView; + ll_loading = linearLayout1; + ll_noconnection = linearLayout2; + + concernManager = new ConcernManager(context); + this.layoutInflater = LayoutInflater.from(context); + + // 获取关注的信息 + concernList = concernManager.getAllConcernBySort(); + + if (concernList != null && !concernList.isEmpty()) { + sortList(concernList); + initConcernNews(true); + } else { + initDatas(); + } + } + + private void sortList(List list) { + Comparator comparator = new Comparator() { + @Override + public int compare(ConcernInfo lhs, ConcernInfo rhs) { + + if (rhs.getWeight() == 2 && lhs.getWeight() == 2) { + return 0; + } else if (rhs.getWeight() == 2 && lhs.getWeight() == 1) { + return 1; + } else if (rhs.getWeight() == 1 && lhs.getWeight() == 2) { + return -1; + } else { + if ("已关注".equals(rhs.getTag()) + && "已安装".equals(lhs.getTag())) { + return 1; + } else if ("已安装".equals(rhs.getTag()) + && "已关注".equals(lhs.getTag())) { + return -1; + } else { + return 0; + } + } + } + }; + Collections.sort(concernList, comparator); + } + + public void updateMyGameNews() { + ll_loading.setVisibility(View.VISIBLE); + concernList = concernManager.getAllConcernBySort(); + if (concernList != null && !concernList.isEmpty()) { + sortList(concernList); + initConcernNews(false); + } else { + ll_loading.setVisibility(View.GONE); + refreshCount(); + } + } + + private void showRecyclerView() { + recyclerView.setVisibility(View.VISIBLE); + ll_loading.setVisibility(View.GONE); + SuspectedGameManager manager = new SuspectedGameManager(context); + List list = manager.getAllGame(); + if (list != null && !list.isEmpty()) { + ll_loading.setVisibility(View.VISIBLE); + List params = new ArrayList(); + for (SuspectedGameInfo entity : list) { + params.add(entity.getPackageName()); + } + initSuspectedGame(params); + } + } + + private int iCount; + + private void initSuspectedGame(final List params) { + iCount = 0; + final List list = new ArrayList(); + final List useParams = new ArrayList(); + for (int i = 0, size = params.size(); i < size; i++) { + final String packageName = params.get(i); + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + + "v1d45/support/package/" + packageName + + "/game/digest", Constants.GAME_CD), + new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + iCount++; + if (response.length() != 0) { + list.add(response); + useParams.add(packageName); + } + if (params.size() == iCount) { + processingData(list, params, useParams); + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + iCount++; + if (params.size() == iCount) { + if (list.isEmpty()) { + ll_loading.setVisibility(View.GONE); + } else { + processingData(list, params, useParams); + } + } + } + }); + AppController.addToRequestQueue(request, + NewsOrRaidersActivity.class); + } + } + + private void processingData(List data, List params, + List useParams) { + Gson gson = new Gson(); + ConcernManager manager = new ConcernManager(context); + for (int i = 0, size = data.size(); i < size; i++) { + GameDigestEntity gameDigestEntity = gson.fromJson(data.get(i) + .toString(), GameDigestEntity.class); + GameInfo gameEntity = new GameInfo(); + gameEntity.setId(gameDigestEntity.getId()); + gameEntity.setPackageName(useParams.get(i)); + manager.updateByEntity(gameEntity, false); + } + + SuspectedGameManager suspectedGameManager = new SuspectedGameManager( + context); + for (String packageName : params) { + suspectedGameManager.deleteSuspectedGame(packageName); + } + + if (data.size() > 0) { + updateMyGameNews(); + } else { + ll_loading.setVisibility(View.GONE); + } + } + + private void initDatas() { + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + + "v1d45/news?type_group=" + Uri.encode(type) + + "&offset=0&limit=20", Constants.NEWS_CD), + new Response.Listener() { + + @Override + public void onResponse(JSONArray response) { + SimpleDateFormat format = new SimpleDateFormat("Mdd", + Locale.getDefault()); + int today = Integer.valueOf(format.format(new Date())); + + Type listType = new TypeToken>() { + }.getType(); + Gson gson = new Gson(); + List newsLists = gson.fromJson( + response.toString(), listType); + int size = newsLists.size(); + for (int i = 0; i < size; i++) { + int day = Integer.valueOf(format.format(new Date( + Long.valueOf(newsLists.get(i) + .getPublishOn() + "000")))); + if (day == today) { + todayNewsList.add(newsLists.get(i)); + } else { + beforeNewsList.add(newsLists.get(i)); + } + } + if (size < 20) { + isRemove = true; + } + refreshCount(); + showRecyclerView(); + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + // 无网络连接和访问超时 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + Toast.makeText(context, "获取" + type + "失败", + Toast.LENGTH_SHORT).show(); + recyclerView.setVisibility(View.GONE); + ll_loading.setVisibility(View.GONE); + ll_noconnection.setVisibility(View.VISIBLE); + } + } + + }); + AppController.addToRequestQueue(request, NewsOrRaidersActivity.class); + } + + public void addList() { + isLoading = true; + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + + "v1d45/news?type_group=" + Uri.encode(type) + + "&offset=" + getAllListSize() + "&limit=20", + Constants.NEWS_CD), new Response.Listener() { + + @Override + public void onResponse(JSONArray response) { + Type listType = new TypeToken>() { + }.getType(); + Gson gson = new Gson(); + List lists = gson.fromJson( + response.toString(), listType); + if (lists != null) { + if (lists.isEmpty()) { + isRemove = true; + notifyItemRemoved(getItemCount()); + } else { + addDatas(lists); + } + } + isLoading = false; + } + + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + isLoading = false; + Toast.makeText(context, "网络错误", Toast.LENGTH_SHORT) + .show(); + isNetworkError = true; + notifyItemChanged(getItemCount() - 1); + } + + }); + AppController.addToRequestQueue(request, NewsOrRaidersActivity.class); + } + + private void addDatas(List datas) { + final int dataSize = datas.size(); + // 去重 + for (int i = 0; i < datas.size(); i++) { + String id = datas.get(i).getId(); + final int index = i; + + if (!todayNewsList.isEmpty()) { + for (int j = 0; j < todayNewsList.size(); j++) { + if (id.equals(todayNewsList.get(j).getId())) { + datas.remove(i); + i--; + break; + } + } + if (index != i) { + continue; + } + } + + if (!beforeNewsList.isEmpty()) { + for (int j = 0; j < beforeNewsList.size(); j++) { + if (id.equals(beforeNewsList.get(j).getId())) { + datas.remove(i); + i--; + break; + } + } + if (index != i) { + continue; + } + } + } + + if (dataSize < 20 && datas.size() == 0) { + isRemove = true; + notifyItemRemoved(getItemCount()); + } + + SimpleDateFormat format = new SimpleDateFormat("Mdd", + Locale.getDefault()); + int today = Integer.valueOf(format.format(new Date())); + + for (int i = 0, size = datas.size(); i < size; i++) { + int day = Integer.valueOf(format.format(new Date(Long.valueOf(datas + .get(i).getPublishOn() + "000")))); + if (day == today) { + todayNewsList.add(datas.get(i)); + notifyItemInserted(getItemCount() - 2); + } else { + beforeNewsList.add(datas.get(i)); + if (beforeNewsList.size() == 1 && position_before == -1) { + if (position_mygame != -1 && position_today != -1) { + position_before = position_today + todayNewsList.size() + + 1; + } else if (position_mygame != -1 && position_today == -1) { + position_before = count_game + 1; + } else if (position_mygame == -1 && position_today != -1) { + position_before = todayNewsList.size() + 1; + } else if (position_mygame == -1 && position_today == -1) { + position_before = 0; + } + notifyItemRangeChanged(getItemCount() - 2, getItemCount()); + } else { + notifyItemInserted(getItemCount() - 2); + } + } + } + } + + private int count; + + private void initConcernNews(final boolean isInitDatas) { + final List cList = new ArrayList(); + concernNewsMap = new ArrayMap>(); + count = concernList.size(); + for (int i = 0, size = concernList.size(); i < size; i++) { + final int index = i; + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp( + Config.HOST + "v1d45/game/" + + concernList.get(i).getId() + + "/news?limit=3&offset=0&type_group=" + + Uri.encode(type), Constants.NEWS_CD), + new Response.Listener() { + @Override + public void onResponse(JSONArray response) { + Gson gson = new Gson(); + Type listType = new TypeToken>() { + }.getType(); + List list = gson.fromJson( + response.toString(), listType); + if (list != null && !list.isEmpty()) { + cList.add(concernList.get(index)); + concernNewsMap.put(concernList.get(index) + .getGameName(), list); + } + refresh(cList, isInitDatas); + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + // 无网络连接和网络超时 + if (error.getClass() + .equals(NoConnectionError.class) + || error.getClass().equals( + TimeoutError.class)) { + if (isInitDatas) { + Toast.makeText(context, "获取" + type + "失败", + Toast.LENGTH_SHORT).show(); + recyclerView.setVisibility(View.GONE); + ll_loading.setVisibility(View.GONE); + ll_noconnection.setVisibility(View.VISIBLE); + } else { + Toast.makeText(context, "网络错误", + Toast.LENGTH_SHORT).show(); + ll_loading.setVisibility(View.GONE); + } + } + } + }); + AppController.addToRequestQueue(request, + NewsOrRaidersActivity.class); + } + } + + private void refresh(List cList, boolean isInitDatas) { + if (count != 1) { + count--; + } else { + concernList = cList; + if (!concernList.isEmpty()) { + List ids = new ArrayList(); + for (int i = 0; i < concernList.size(); i++) { + ids.add(concernList.get(i).getId()); + } + initConcernDatas(ids, isInitDatas); + } else { + if (isInitDatas) { + initDatas(); + } else { + refreshCount(); + showRecyclerView(); + } + } + } + } + + private void initConcernDatas(List ids, final boolean isInitDatas) { + final List result = new ArrayList(); + final int count = ids.size(); + for (int i = 0, size = ids.size(); i < size; i++) { + JsonObjectExtendedRequest gameObjectRequest = new JsonObjectExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + "v1d45/game/" + + ids.get(i) + "/digest", Constants.GAME_CD), + new Response.Listener() { + @Override + public void onResponse(JSONObject response) { + result.add(response); + if (result.size() == count) { + processingConcernData(result, isInitDatas); + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + // 无网络连接和网络超时 + if (error.getClass() + .equals(NoConnectionError.class) + || error.getClass().equals( + TimeoutError.class)) { + if (isInitDatas) { + initDatas(); + } else { + refreshCount(); + showRecyclerView(); + } + } + } + + }); + AppController.addToRequestQueue(gameObjectRequest, + NewsOrRaidersActivity.class); + } + } + + private void processingConcernData(List data, + boolean isInitDatas) { + Gson gson = new Gson(); + concernGameList = new ArrayList(); + for (int i = 0, size = data.size(); i < size; i++) { + JSONObject response = data.get(i); + concernGameList.add(gson.fromJson(response.toString(), + GameEntity.class)); + } + if (concernGameList != null && !concernGameList.isEmpty()) { + List list = new ArrayList(); + for (int i = 0, size = concernList.size(); i < size; i++) { + String id = concernList.get(i).getId(); + for (GameEntity gameEntity : concernGameList) { + if (gameEntity.getId().equals(id)) { + list.add(gameEntity); + break; + } + } + } + concernGameList = list; + GameManager manager = new GameManager(context); + for (int i = 0, size = concernGameList.size(); i < size; i++) { + for (ApkEntity apkEntity : concernGameList.get(i).getApk()) { + manager.addOrUpdate(new GameInfo(apkEntity.getPackageName(), + concernGameList.get(i).getId(), concernGameList + .get(i).getName())); + } + } + } + if (isInitDatas) { + initDatas(); + } else { + refreshCount(); + showRecyclerView(); + } + } + + private void refreshCount() { + + position_mygame = -1; + position_today = -1; + position_before = -1; + count_game = 0; + + if (!concernList.isEmpty()) { + position_mygame = 0; + int count = 0; + for (int i = 0, size = concernList.size(); i < size; i++) { + count += (concernNewsMap.get(concernList.get(i).getGameName()) + .size() + 1); + } + count_game = count; + } + + if (!todayNewsList.isEmpty()) { + if (position_mygame != -1) { + position_today = count_game + 1; + } else { + position_today = 0; + } + } + + if (!beforeNewsList.isEmpty()) { + if (position_mygame != -1 && position_today != -1) { + position_before = position_today + todayNewsList.size() + 1; + } else if (position_mygame != -1 && position_today == -1) { + position_before = count_game + 1; + } else if (position_mygame == -1 && position_today != -1) { + position_before = todayNewsList.size() + 1; + } else if (position_mygame == -1 && position_today == -1) { + position_before = 0; + } + } + if (position_mygame != -1) { + relativeLayout.setVisibility(View.VISIBLE); + textView.setText("我的游戏"); + textView.setBackgroundResource(R.drawable.title_blue); + } else if (position_today != -1) { + relativeLayout.setVisibility(View.VISIBLE); + textView.setText("今天"); + textView.setBackgroundResource(R.drawable.title_red); + } else if (position_before != -1) { + relativeLayout.setVisibility(View.VISIBLE); + textView.setText("昨天/以前"); + textView.setBackgroundResource(R.drawable.title_gray); + } + notifyDataSetChanged(); + } + + @Override + public int getItemCount() { + int head = 0; + if (position_mygame != -1) + head++; + if (position_today != -1) + head++; + if (position_before != -1) + head++; + + if (isRemove) { + return head + count_game + todayNewsList.size() + + beforeNewsList.size(); + } else { + return head + count_game + todayNewsList.size() + + beforeNewsList.size() + 1; + } + } + + @Override + public int getItemViewType(int position) { + + if (position_mygame != -1) { + if (position == 0) { + return ITEM_TYPE.head; + } + if (position > 0 && position <= count_game) { + for (int i = 0, size = concernList.size(); i < size; i++) { + int offset = 0; + for (int j = 0; j < i; j++) { + offset += (concernNewsMap.get( + concernList.get(j).getGameName()).size() + 1); + } + if (position == offset + 1) { + return ITEM_TYPE.game_type; + } else if (position > offset + 1 + && position <= concernNewsMap.get( + concernList.get(i).getGameName()).size() + + offset + 1) { + return ITEM_TYPE.game_text; + } + } + } + } + + if (position_today != -1) { + if (position == position_today) { + return ITEM_TYPE.head; + } + if (position == position_today + 1) { + if (!TextUtils.isEmpty(todayNewsList.get(0).getThumb())) { + return ITEM_TYPE.news_image; + } else { + return ITEM_TYPE.news_text; + } + } + if (position > position_today + 1 + && position <= todayNewsList.size() + position_today) { + return ITEM_TYPE.news_text; + } + } + + if (position_before != -1) { + if (position == position_before) { + return ITEM_TYPE.head; + } + if (position > position_before + && position <= beforeNewsList.size() + position_before) { + return ITEM_TYPE.news_text; + } + } + + return ITEM_TYPE.refresh_footer; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, + int viewType) { + if (viewType == ITEM_TYPE.head) { + return new HeadViewHolder(layoutInflater.inflate( + R.layout.news_list_item_category, parent, false)); + } else if (viewType == ITEM_TYPE.game_type) { + return new GameNormalViewHolder(layoutInflater.inflate( + R.layout.news_list_item_gamenormal_type, parent, false)); + } else if (viewType == ITEM_TYPE.news_image) { + return new ImageNewsTypeViewHolder(layoutInflater.inflate( + R.layout.home_list_item_newsimage_type, parent, false)); + } else if (viewType == ITEM_TYPE.news_text + || viewType == ITEM_TYPE.game_text) { + return new TextNewsTypeViewHolder(layoutInflater.inflate( + R.layout.home_list_item_newsnormal_type, parent, false), + viewType); + } else { + return new FooterViewHolder(layoutInflater.inflate( + R.layout.refresh_footerview, parent, false)); + } + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, + int position) { + if (viewHolder instanceof HeadViewHolder) { + ((HeadViewHolder) viewHolder).initViewHolder(position, viewHolder); + } else if (viewHolder instanceof GameNormalViewHolder) { + ((GameNormalViewHolder) viewHolder).initViewHolder(position); + } else if (viewHolder instanceof ImageNewsTypeViewHolder) { + ((ImageNewsTypeViewHolder) viewHolder).initViewHolder(position); + } else if (viewHolder instanceof TextNewsTypeViewHolder) { + ((TextNewsTypeViewHolder) viewHolder).initViewHolder(position); + } else if (viewHolder instanceof FooterViewHolder) { + FooterViewHolder holder = (FooterViewHolder) viewHolder; + if (isNetworkError) { + holder.footerview_progressbar.setVisibility(View.GONE); + holder.footerview_tv_loading.setText("加载失败,点击重试"); + holder.rootView.setClickable(true); + holder.rootView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + isNetworkError = false; + notifyItemChanged(getItemCount()); + addList(); + } + }); + } else { + holder.footerview_progressbar.setVisibility(View.VISIBLE); + holder.footerview_tv_loading.setText("加载中..."); + holder.rootView.setClickable(false); + } + } + } + + private class HeadViewHolder extends RecyclerView.ViewHolder { + public TextView headType; + + public HeadViewHolder(View v) { + super(v); + headType = (TextView) v.findViewById(R.id.tv_label); + } + + public void initViewHolder(int position, + RecyclerView.ViewHolder viewHolder) { + if (position == position_mygame) { + headType.setText("我的游戏"); + headType.setBackgroundResource(R.drawable.title_blue); + } + + if (position == position_today) { + headType.setText("今天"); + headType.setBackgroundResource(R.drawable.title_red); + } + + if (position == position_before) { + headType.setText("昨天/以前"); + headType.setBackgroundResource(R.drawable.title_gray); + } + } + } + + private class GameNormalViewHolder extends RecyclerView.ViewHolder { + public ImageView gameThumb; + public TextView gameName; + public LinearLayout labelList; + private View rootItem; + + public GameNormalViewHolder(View v) { + super(v); + this.rootItem = v; + gameThumb = (ImageView) v.findViewById(R.id.news_game_thumb); + gameName = (TextView) v.findViewById(R.id.news_game_name); + labelList = (LinearLayout) v.findViewById(R.id.news_label_list); + } + + public void initViewHolder(int position) { + if (position > 0 && position <= count_game) { + for (int i = 0, size = concernList.size(); i < size; i++) { + int offset = 0; + for (int j = 0; j < i; j++) { + offset += (concernNewsMap.get( + concernList.get(j).getGameName()).size() + 1); + } + if (position == offset + 1) { + if (concernGameList == null) { + init(concernList.get(i)); + } else { + init(concernGameList.get(i), concernList.get(i) + .getTag()); + } + } + } + } + } + + private void init(ConcernInfo concernEntity) { + ImageUtils.getInstance(context).display(concernEntity.getIcon(), + gameThumb); + gameName.setText(concernEntity.getGameName()); + String tag = concernEntity.getTag(); + if (tag != null) { + GameViewUtils.setLabelList(context, labelList, tag); + } + rootItem.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + + } + }); + } + + private void init(final GameEntity entry, String tag) { + ImageUtils.getInstance(context).display(entry.getIcon(), gameThumb); + gameName.setText(entry.getName()); + if (tag != null) { + GameViewUtils.setLabelList(context, labelList, tag); + } + rootItem.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + + Map kv = new HashMap(); + kv.put("入口", type + "-我的游戏"); + TCAgent.onEvent(context, "游戏详情", entry.getName(), kv); + + Map map = new HashMap(); + map.put("location", "我的游戏"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", entry.getName()); + map.put("page", type); + DataCollectionManager.onEvent(context, "click-item", map); + + AppController.put("GameEntity", entry); + Intent intent = new Intent(context, + GameDetailsActivity.class); + intent.putExtra("entrance", type + "-我的游戏"); + if ("资讯".equals(type)) { + intent.putExtra("current", 1); + } else if ("攻略".equals(type)) { + intent.putExtra("current", 2); + } + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + }); + } + } + + public class ImageNewsTypeViewHolder extends RecyclerView.ViewHolder { + private ImageView newsThumb; + private TextView newsMainTitle, newsSubTitle; + private View rootItem; + + public ImageNewsTypeViewHolder(View v) { + super(v); + rootItem = v; + newsThumb = (ImageView) v.findViewById(R.id.news_thumb); + newsMainTitle = (TextView) v.findViewById(R.id.news_main_title); + newsSubTitle = (TextView) v.findViewById(R.id.news_sub_title); + } + + public void initViewHolder(int position) { + final NewsEntity newsEntity = todayNewsList.get(0); + ImageUtils.getInstance(context).display(newsEntity.getThumb(), newsThumb); + String title = newsEntity.getTitle(); + if (title.contains("》")) { + newsMainTitle.setText(title.substring(0, title.indexOf("》") + 1)); + newsSubTitle.setVisibility(View.VISIBLE); + newsSubTitle.setText(title.substring(title.indexOf("》") + 1)); + } else if (title.contains(" ")) { + newsMainTitle.setText(title.substring(0, title.indexOf(" ") + 1)); + newsSubTitle.setVisibility(View.VISIBLE); + newsSubTitle.setText(title.substring(title.indexOf(" ") + 1)); + } else { + newsMainTitle.setText(title); + newsSubTitle.setVisibility(View.GONE); + } + rootItem.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Map kv = new HashMap(); + kv.put("文章类型", newsEntity.getType()); + kv.put("入口", type + "-今天"); + TCAgent.onEvent(context, "文章阅读-" + type, newsEntity.getTitle(), kv); + + Map map = new HashMap(); + map.put("location", "今天"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("news", newsEntity.getTitle()); + map.put("page", type); + DataCollectionManager.onEvent(context, "click-item", map); + + NewsUtils.startNewsActivity(context, newsEntity, type + + "-今天"); + } + }); + } + + } + + private class TextNewsTypeViewHolder extends RecyclerView.ViewHolder { + public TextView newsType; + public TextView newsTitle; + private int column; + private View rootItem; + + public TextNewsTypeViewHolder(View v, int column) { + super(v); + rootItem = v; + this.column = column; + newsType = (TextView) v.findViewById(R.id.news_type); + newsTitle = (TextView) v.findViewById(R.id.news_title); + } + + public void initViewHolder(final int position) { + NewsEntity newsEntity = null; + String from = null; + if (column == ITEM_TYPE.news_text) { + if (position > position_today + && position <= todayNewsList.size() + position_today) { + newsEntity = todayNewsList.get(position - position_today + - 1); + from = "今天"; + } else if (position > position_before + && position <= beforeNewsList.size() + position_before) { + newsEntity = beforeNewsList.get(position - position_before + - 1); + from = "昨天/以前"; + } + } else if (column == ITEM_TYPE.game_text) { + if (position > 0 && position <= count_game) { + for (int i = 0, size = concernList.size(); i < size; i++) { + int offset = 0; + for (int j = 0; j < i; j++) { + offset += (concernNewsMap.get( + concernList.get(j).getGameName()).size() + 1); + } + if (position > offset + 1 + && position <= concernNewsMap.get( + concernList.get(i).getGameName()) + .size() + + offset + 1) { + newsEntity = concernNewsMap.get( + concernList.get(i).getGameName()).get( + position - offset - 2); + from = "我的游戏"; + } + } + } + } + if (newsEntity != null) { + final NewsEntity entity = newsEntity; + final String entrance = from; + newsType.setBackgroundResource(NewsUtils + .getDrawableIdByType(entity.getType())); + newsType.setText(entity.getType()); + newsTitle.setText(entity.getTitle()); + rootItem.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Map kv = new HashMap(); + kv.put("文章类型", entity.getType()); + kv.put("入口", type + "-" + entrance); + TCAgent.onEvent(context, "文章阅读-" + type, entity.getTitle(), kv); + + Map map = new HashMap(); + map.put("location", entrance); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("news", entity.getTitle()); + map.put("page", type); + DataCollectionManager.onEvent(context, "click-item", map); + + NewsUtils.startNewsActivity(context, entity, type + "-" + + entrance); + } + }); + } + } + + } + + public int getAllListSize() { + return todayNewsList.size() + beforeNewsList.size(); + } + + public int getTodaySize() { + return todayNewsList.size(); + } + + public int getBeforeSize() { + return beforeNewsList.size(); + } + + public int getPosition_mygame() { + return position_mygame; + } + + public int getPosition_today() { + return position_today; + } + + public int getPosition_before() { + return position_before; + } + + public boolean isRemove() { + return isRemove; + } + + public void setRemove(boolean isRemove) { + this.isRemove = isRemove; + } + + public boolean isLoading() { + return isLoading; + } + + public void setLoading(boolean isLoading) { + this.isLoading = isLoading; + } + + public boolean isNetworkError() { + return isNetworkError; + } + + public void setNetworkError(boolean isNetworkError) { + this.isNetworkError = isNetworkError; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/adapter/RecycleBin.java b/app/src/main/java/com/gh/gamecenter/adapter/RecycleBin.java new file mode 100644 index 0000000000..882213e259 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/adapter/RecycleBin.java @@ -0,0 +1,156 @@ +package com.gh.gamecenter.adapter; + +import android.os.Build; +import android.util.SparseArray; +import android.view.View; + +/** + * The RecycleBin facilitates reuse of views across layouts. The RecycleBin has + * two levels of storage: ActiveViews and ScrapViews. ActiveViews are those + * views which were onscreen at the start of a layout. By construction, they are + * displaying current information. At the end of layout, all views in + * ActiveViews are demoted to ScrapViews. ScrapViews are old views that could + * potentially be used by the adapter to avoid allocating views unnecessarily. + *

+ * This class was taken from Android's implementation of + * {@link android.widget.AbsListView} which is copyrighted 2006 The Android Open + * Source Project. + */ +public class RecycleBin { + /** + * Views that were on screen at the start of layout. This array is populated + * at the start of layout, and at the end of layout all view in activeViews + * are moved to scrapViews. Views in activeViews represent a contiguous + * range of Views, with position of the first view store in + * mFirstActivePosition. + */ + private View[] activeViews = new View[0]; + private int[] activeViewTypes = new int[0]; + + /** Unsorted views that can be used by the adapter as a convert view. */ + private SparseArray[] scrapViews; + + private int viewTypeCount; + + private SparseArray currentScrapViews; + + public void setViewTypeCount(int viewTypeCount) { + if (viewTypeCount < 1) { + throw new IllegalArgumentException("Can't have a viewTypeCount < 1"); + } + // noinspection unchecked + SparseArray[] scrapViews = new SparseArray[viewTypeCount]; + for (int i = 0; i < viewTypeCount; i++) { + scrapViews[i] = new SparseArray(); + } + this.viewTypeCount = viewTypeCount; + currentScrapViews = scrapViews[0]; + this.scrapViews = scrapViews; + } + + protected boolean shouldRecycleViewType(int viewType) { + return viewType >= 0; + } + + /** @return A view from the ScrapViews collection. These are unordered. */ + View getScrapView(int position, int viewType) { + if (viewTypeCount == 1) { + return retrieveFromScrap(currentScrapViews, position); + } else if (viewType >= 0 && viewType < scrapViews.length) { + return retrieveFromScrap(scrapViews[viewType], position); + } + return null; + } + + /** + * Put a view into the ScrapViews list. These views are unordered. + * + * @param scrap + * The view to add + */ + void addScrapView(View scrap, int position, int viewType) { + if (viewTypeCount == 1) { + currentScrapViews.put(position, scrap); + } else { + scrapViews[viewType].put(position, scrap); + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + scrap.setAccessibilityDelegate(null); + } + } + + /** Move all views remaining in activeViews to scrapViews. */ + void scrapActiveViews() { + final View[] activeViews = this.activeViews; + final int[] activeViewTypes = this.activeViewTypes; + final boolean multipleScraps = viewTypeCount > 1; + + SparseArray scrapViews = currentScrapViews; + final int count = activeViews.length; + for (int i = count - 1; i >= 0; i--) { + final View victim = activeViews[i]; + if (victim != null) { + int whichScrap = activeViewTypes[i]; + + activeViews[i] = null; + activeViewTypes[i] = -1; + + if (!shouldRecycleViewType(whichScrap)) { + continue; + } + + if (multipleScraps) { + scrapViews = this.scrapViews[whichScrap]; + } + scrapViews.put(i, victim); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + victim.setAccessibilityDelegate(null); + } + } + } + + pruneScrapViews(); + } + + /** + * Makes sure that the size of scrapViews does not exceed the size of + * activeViews. (This can happen if an adapter does not recycle its views). + */ + private void pruneScrapViews() { + final int maxViews = activeViews.length; + final int viewTypeCount = this.viewTypeCount; + final SparseArray[] scrapViews = this.scrapViews; + for (int i = 0; i < viewTypeCount; ++i) { + final SparseArray scrapPile = scrapViews[i]; + int size = scrapPile.size(); + final int extras = size - maxViews; + size--; + for (int j = 0; j < extras; j++) { + scrapPile.remove(scrapPile.keyAt(size--)); + } + } + } + + static View retrieveFromScrap(SparseArray scrapViews, int position) { + int size = scrapViews.size(); + if (size > 0) { + // See if we still have a view for this position. + for (int i = 0; i < size; i++) { + int fromPosition = scrapViews.keyAt(i); + View view = scrapViews.get(fromPosition); + if (fromPosition == position) { + scrapViews.remove(fromPosition); + return view; + } + } + int index = size - 1; + View r = scrapViews.valueAt(index); + scrapViews.remove(scrapViews.keyAt(index)); + return r; + } else { + return null; + } + } +} diff --git a/app/src/main/java/com/gh/gamecenter/adapter/RecyclingPagerAdapter.java b/app/src/main/java/com/gh/gamecenter/adapter/RecyclingPagerAdapter.java new file mode 100644 index 0000000000..0fc5893062 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/adapter/RecyclingPagerAdapter.java @@ -0,0 +1,124 @@ +package com.gh.gamecenter.adapter; + +import android.support.v4.view.PagerAdapter; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; + +/** + * A {@link PagerAdapter} which behaves like an {@link android.widget.Adapter} + * with view types and view recycling. + */ +public abstract class RecyclingPagerAdapter extends PagerAdapter { + static final int IGNORE_ITEM_VIEW_TYPE = AdapterView.ITEM_VIEW_TYPE_IGNORE; + + private final RecycleBin recycleBin; + + public RecyclingPagerAdapter() { + this(new RecycleBin()); + } + + RecyclingPagerAdapter(RecycleBin recycleBin) { + this.recycleBin = recycleBin; + recycleBin.setViewTypeCount(getViewTypeCount()); + } + + @Override + public void notifyDataSetChanged() { + recycleBin.scrapActiveViews(); + super.notifyDataSetChanged(); + } + + @Override + public final Object instantiateItem(ViewGroup container, int position) { + int viewType = getItemViewType(position); + View view = null; + if (viewType != IGNORE_ITEM_VIEW_TYPE) { + view = recycleBin.getScrapView(position, viewType); + } + view = getView(position, view, container); + container.addView(view); + return view; + } + + @Override + public final void destroyItem(ViewGroup container, int position, + Object object) { + View view = (View) object; + container.removeView(view); + int viewType = getItemViewType(position); + if (viewType != IGNORE_ITEM_VIEW_TYPE) { + recycleBin.addScrapView(view, position, viewType); + } + } + + @Override + public final boolean isViewFromObject(View view, Object object) { + return view == object; + } + + /** + *

+ * Returns the number of types of Views that will be created by + * {@link #getView}. Each type represents a set of views that can be + * converted in {@link #getView}. If the adapter always returns the same + * type of View for all items, this method should return 1. + *

+ *

+ * This method will only be called when when the adapter is set on the the + * {@link AdapterView}. + *

+ * + * @return The number of types of Views that will be created by this adapter + */ + public int getViewTypeCount() { + return 1; + } + + /** + * Get the type of View that will be created by {@link #getView} for the + * specified item. + * + * @param position + * The position of the item within the adapter's data set whose + * view type we want. + * @return An integer representing the type of View. Two views should share + * the same type if one can be converted to the other in + * {@link #getView}. Note: Integers must be in the range 0 to + * {@link #getViewTypeCount} - 1. {@link #IGNORE_ITEM_VIEW_TYPE} can + * also be returned. + * @see #IGNORE_ITEM_VIEW_TYPE + */ + @SuppressWarnings("UnusedParameters") + // Argument potentially used by subclasses. + public int getItemViewType(int position) { + return 0; + } + + /** + * Get a View that displays the data at the specified position in the data + * set. You can either create a View manually or inflate it from an XML + * layout file. When the View is inflated, the parent View (GridView, + * ListView...) will apply default layout parameters unless you use + * {@link android.view.LayoutInflater#inflate(int, ViewGroup, boolean)} + * to specify a root view and to prevent attachment to the root. + * + * @param position + * The position of the item within the adapter's data set of the + * item whose view we want. + * @param convertView + * The old view to reuse, if possible. Note: You should check + * that this view is non-null and of an appropriate type before + * using. If it is not possible to convert this view to display + * the correct data, this method can create a new view. + * Heterogeneous lists can specify their number of view types, so + * that this View is always of the right type (see + * {@link #getViewTypeCount()} and {@link #getItemViewType(int)} + * ). + * @param parent + * The parent that this view will eventually be attached to + * @return A View corresponding to the data at the specified position. + */ + public abstract View getView(int position, View convertView, + ViewGroup container); +} diff --git a/app/src/main/java/com/gh/gamecenter/adapter/viewholder/FooterViewHolder.java b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/FooterViewHolder.java new file mode 100644 index 0000000000..0cf6853cc6 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/FooterViewHolder.java @@ -0,0 +1,32 @@ +package com.gh.gamecenter.adapter.viewholder; + +import android.support.v4.widget.ContentLoadingProgressBar; +import android.support.v7.widget.RecyclerView.ViewHolder; +import android.view.View; +import android.widget.TextView; + +import com.gh.gamecenter.R; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-8-11 + * @update 2015-8-11 + * @des 下拉或上啦刷新中,进度显示控件 + */ +public class FooterViewHolder extends ViewHolder { + public View rootView; + public ContentLoadingProgressBar footerview_progressbar; + public TextView footerview_tv_loading; + + public FooterViewHolder(View view) { + super(view); + rootView = view; + footerview_progressbar = (ContentLoadingProgressBar) view + .findViewById(R.id.footerview_progressbar); + footerview_tv_loading = (TextView) view + .findViewById(R.id.footerview_tv_loading); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/adapter/viewholder/GameViewHolder.java b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/GameViewHolder.java new file mode 100644 index 0000000000..7d06b4b88b --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/GameViewHolder.java @@ -0,0 +1,45 @@ +package com.gh.gamecenter.adapter.viewholder; + +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; + +import com.gh.gamecenter.R; + +public class GameViewHolder extends RecyclerView.ViewHolder { + + public View view; + public TextView gameSeq, gameNameAndSize, downloadSpeed, + downloadPercentage, gameDes; + public TextView downloadBtn; + public ImageView gameThumb; + public LinearLayout labelList, gameInfo; + public ProgressBar gameProgressbar; + + public GameViewHolder(View convertView) { + super(convertView); + + view = convertView; + gameSeq = (TextView) convertView.findViewById(R.id.home1_game_seq); + gameNameAndSize = (TextView) convertView + .findViewById(R.id.home1_game_nameAndsize); + downloadSpeed = (TextView) convertView + .findViewById(R.id.home1_download_speed); + downloadPercentage = (TextView) convertView + .findViewById(R.id.home1_download_percentage); + downloadBtn = (TextView) convertView + .findViewById(R.id.home1_download_btn); + gameDes = (TextView) convertView.findViewById(R.id.home1_game_des); + gameThumb = (ImageView) convertView.findViewById(R.id.home1_game_thumb); + labelList = (LinearLayout) convertView + .findViewById(R.id.home1_label_list); + gameInfo = (LinearLayout) convertView + .findViewById(R.id.home1_game_ll_info); + gameProgressbar = (ProgressBar) convertView + .findViewById(R.id.home1_game_progressbar); + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/db/ConcernDao.java b/app/src/main/java/com/gh/gamecenter/db/ConcernDao.java new file mode 100644 index 0000000000..45f17085d3 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/db/ConcernDao.java @@ -0,0 +1,168 @@ +package com.gh.gamecenter.db; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import android.content.Context; + +import com.gh.gamecenter.db.info.ConcernInfo; +import com.j256.ormlite.dao.Dao; +import com.j256.ormlite.stmt.QueryBuilder; + +public class ConcernDao { + + private DatabaseHelper helper; + private Dao dao; + + public ConcernDao(Context context) { + try { + helper = DatabaseHelper.getHelper(context); + dao = helper.getDao(ConcernInfo.class); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + /** + * 获取权重和流量排序靠前的关注 + */ + public List get(int number) { + List concernEntities = new ArrayList(); + try { + QueryBuilder builder = dao.queryBuilder(); + + builder.orderBy("weight", false).orderBy("traffic", false); + + List list = builder.query(); + + if (number == 0 || number >= list.size()) { + return list; + } else { + for (int i = 0; i < number; i++) { + concernEntities.add(list.get(i)); + } + return concernEntities; + } + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 获取所有的已关注游戏的集合 + */ + public List getConcern(int number) { + List concernEntities = new ArrayList(); + try { + QueryBuilder builder = dao.queryBuilder(); + builder.where().eq("isConcern", true); + + List list = builder.query(); + + if (number == 0 || number >= list.size()) { + return list; + } else { + for (int i = 0; i < number; i++) { + concernEntities.add(list.get(i)); + } + return concernEntities; + } + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 获取所有的已安装游戏的集合 + */ + public List getInstalled() { + try { + QueryBuilder builder = dao.queryBuilder(); + builder.where().eq("isInstalled", true); + return builder.query(); + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + + public boolean isConcern(String id){ + try { + QueryBuilder builder = dao.queryBuilder(); + builder.where().eq("id", id).eq("isConcern", true); + ConcernInfo concernEntity = builder.queryForFirst(); + if (concernEntity != null) { + return true; + } + } catch (SQLException e) { + + e.printStackTrace(); + } + return false; + } + + /** + * 添加一个关注 + */ + public void add(ConcernInfo entity) { + try { + dao.create(entity); + } catch (SQLException e) { + + e.printStackTrace(); + } + } + + /** + * 删除一个关注 + */ + public void delete(String id) { + try { + dao.deleteById(id); + } catch (SQLException e) { + + e.printStackTrace(); + } + } + + /** + * 根据id获取某一个关注 + */ + public ConcernInfo find(String id) { + try { + return dao.queryForId(id); + } catch (SQLException e) { + + e.printStackTrace(); + } + return null; + } + + /** + * 获取所有的关注 + */ + public List getAll() { + try { + return dao.queryForAll(); + } catch (SQLException e) { + + e.printStackTrace(); + } + return null; + } + + /** + * 更新关注 + */ + public void update(ConcernInfo entity) { + try { + dao.update(entity); + } catch (SQLException e) { + + e.printStackTrace(); + } + } +} diff --git a/app/src/main/java/com/gh/gamecenter/db/DataCollectionDao.java b/app/src/main/java/com/gh/gamecenter/db/DataCollectionDao.java new file mode 100644 index 0000000000..34a0464da7 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/db/DataCollectionDao.java @@ -0,0 +1,118 @@ +package com.gh.gamecenter.db; + +import java.sql.SQLException; +import java.util.List; + +import android.content.Context; + +import com.gh.gamecenter.db.info.DataCollectionInfo; +import com.j256.ormlite.dao.Dao; + +public class DataCollectionDao { + + private DatabaseHelper helper; + private Dao dao; + + public DataCollectionDao(Context context) { + try { + helper = DatabaseHelper.getHelper(context); + dao = helper.getDao(DataCollectionInfo.class); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + /** + * 查找一个数据 + */ + public List findByType(String type) { + try { + return dao.queryForEq("type", type); + } catch (SQLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return null; + } + + /** + * 添加一个数据 + */ + public void add(DataCollectionInfo entity) { + try { + dao.create(entity); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + /** + * 删除一个数据 + */ + public void delete(String id) { + try { + dao.deleteById(id); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + /** + * 删除一组数据 + */ + public void delete(List ids) { + try { + dao.deleteIds(ids); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + /** + * 根据id获取某一个数据 + */ + public DataCollectionInfo find(String id) { + try { + return dao.queryForId(id); + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 获取所有的数据 + */ + public List getAll() { + try { + return dao.queryForAll(); + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 获取点击数据 + */ + public List getClickData() { + try { + return dao.queryForEq("type", "click-item"); + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 更新数据 + */ + public void update(DataCollectionInfo entity) { + try { + dao.update(entity); + } catch (SQLException e) { + e.printStackTrace(); + } + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/db/DatabaseHelper.java b/app/src/main/java/com/gh/gamecenter/db/DatabaseHelper.java new file mode 100644 index 0000000000..09c61d4141 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/db/DatabaseHelper.java @@ -0,0 +1,113 @@ +package com.gh.gamecenter.db; + +import java.sql.SQLException; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.support.v4.util.ArrayMap; + +import com.gh.common.util.Utils; +import com.gh.gamecenter.db.info.ConcernInfo; +import com.gh.gamecenter.db.info.DataCollectionInfo; +import com.gh.gamecenter.db.info.FilterInfo; +import com.gh.gamecenter.db.info.GameInfo; +import com.gh.gamecenter.db.info.SearchHistoryInfo; +import com.gh.gamecenter.db.info.SuspectedGameInfo; +import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper; +import com.j256.ormlite.dao.Dao; +import com.j256.ormlite.support.ConnectionSource; +import com.j256.ormlite.table.TableUtils; + +public class DatabaseHelper extends OrmLiteSqliteOpenHelper { + + private static final String DATABASE_NAME = "gh_assist.db"; + private static final int DATABASE_VERSION = 2; + + private static DatabaseHelper instance; + private ArrayMap daos = new ArrayMap(); + + private DatabaseHelper(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + } + + /** + * 单例获取该Helper + * + * @param context + * @return + */ + public static synchronized DatabaseHelper getHelper(Context context) { + context = context.getApplicationContext(); + if (instance == null) { + synchronized (DatabaseHelper.class) { + if (instance == null) { + instance = new DatabaseHelper(context); + } + } + } + return instance; + } + + @Override + public void onCreate(SQLiteDatabase database, + ConnectionSource connectionSource) { + + try { + Utils.log("onCreate"); + TableUtils.createTable(connectionSource, ConcernInfo.class); + TableUtils.createTable(connectionSource, SearchHistoryInfo.class); + TableUtils.createTable(connectionSource, GameInfo.class); + TableUtils.createTable(connectionSource, SuspectedGameInfo.class); + TableUtils.createTable(connectionSource, FilterInfo.class); + TableUtils.createTable(connectionSource, DataCollectionInfo.class); + } catch (SQLException e) { + + e.printStackTrace(); + } + } + + @Override + public void onUpgrade(SQLiteDatabase database, + ConnectionSource connectionSource, int oldVersion, int newVersion) { + + try { + Utils.log("onUpgrade"); + TableUtils.dropTable(connectionSource, ConcernInfo.class, true); + TableUtils.dropTable(connectionSource, SearchHistoryInfo.class, true); + TableUtils.dropTable(connectionSource, GameInfo.class, true); + TableUtils.dropTable(connectionSource, SuspectedGameInfo.class, true); + TableUtils.dropTable(connectionSource, FilterInfo.class, true); + TableUtils.dropTable(connectionSource, DataCollectionInfo.class, true); + onCreate(database, connectionSource); + } catch (SQLException e) { + + e.printStackTrace(); + } + } + + public synchronized Dao getDao(Class clazz) throws SQLException { + Dao dao = null; + String className = clazz.getSimpleName(); + + if (daos.containsKey(className)) { + dao = daos.get(className); + } + if (dao == null) { + dao = super.getDao(clazz); + daos.put(className, dao); + } + return dao; + } + + /** + * 释放资源 + */ + @Override + public void close() { + super.close(); + for (String key : daos.keySet()) { + Dao dao = daos.get(key); + dao = null; + } + } +} diff --git a/app/src/main/java/com/gh/gamecenter/db/FilterDao.java b/app/src/main/java/com/gh/gamecenter/db/FilterDao.java new file mode 100644 index 0000000000..fc86212754 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/db/FilterDao.java @@ -0,0 +1,101 @@ +package com.gh.gamecenter.db; + +import java.sql.SQLException; +import java.util.List; + +import android.content.Context; + +import com.gh.gamecenter.db.info.FilterInfo; +import com.j256.ormlite.dao.Dao; + +public class FilterDao { + + private DatabaseHelper helper; + private Dao dao; + + public FilterDao(Context context) { + try { + helper = DatabaseHelper.getHelper(context); + dao = helper.getDao(FilterInfo.class); + } catch (SQLException e) { + + e.printStackTrace(); + } + } + + public boolean isFilter(String packageName){ + try { + FilterInfo filterEntity = dao.queryForId(packageName); + if (filterEntity != null) { + return true; + } + } catch (SQLException e) { + + e.printStackTrace(); + } + return false; + } + + /** + * 添加一个过滤包名 + */ + public void add(FilterInfo entity) { + try { + dao.create(entity); + } catch (SQLException e) { + + e.printStackTrace(); + } + } + + /** + * 添加一堆过滤包名 + */ + public void addAll(List list) { + try { + dao.create(list); + } catch (SQLException e) { + + e.printStackTrace(); + } + } + + /** + * 删除一个过滤包名 + */ + public void delete(String packageName) { + try { + dao.deleteById(packageName); + } catch (SQLException e) { + + e.printStackTrace(); + } + } + + /** + * 获取所有的过滤包名 + */ + public List getAll() { + try { + return dao.queryForAll(); + } catch (SQLException e) { + + e.printStackTrace(); + } + return null; + } + + /** + * 获取表中数据总数 + */ + public long getCount() { + try { + return dao.countOf(); + } catch (SQLException e) { + + e.printStackTrace(); + } + return 0; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/db/GameDao.java b/app/src/main/java/com/gh/gamecenter/db/GameDao.java new file mode 100644 index 0000000000..93d63b578e --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/db/GameDao.java @@ -0,0 +1,87 @@ +package com.gh.gamecenter.db; + +import java.sql.SQLException; +import java.util.List; + +import android.content.Context; + +import com.gh.gamecenter.db.info.GameInfo; +import com.j256.ormlite.dao.Dao; + +public class GameDao { + + private DatabaseHelper helper; + private Dao dao; + + public GameDao(Context context) { + try { + helper = DatabaseHelper.getHelper(context); + dao = helper.getDao(GameInfo.class); + } catch (SQLException e) { + + e.printStackTrace(); + } + } + + /** + * 添加一个游戏 + */ + public void add(GameInfo entity) { + try { + dao.create(entity); + } catch (SQLException e) { + + e.printStackTrace(); + } + } + + /** + * 删除一个游戏 + */ + public void delete(String packageName) { + try { + dao.deleteById(packageName); + } catch (SQLException e) { + + e.printStackTrace(); + } + } + + /** + * 根据包名获取某一个游戏 + */ + public GameInfo find(String packageName) { + try { + return dao.queryForId(packageName); + } catch (SQLException e) { + + e.printStackTrace(); + } + return null; + } + + /** + * 获取所有的游戏 + */ + public List getAll() { + try { + return dao.queryForAll(); + } catch (SQLException e) { + + e.printStackTrace(); + } + return null; + } + + /** + * 更新游戏 + */ + public void update(GameInfo entity) { + try { + dao.update(entity); + } catch (SQLException e) { + + e.printStackTrace(); + } + } +} diff --git a/app/src/main/java/com/gh/gamecenter/db/SearchHistoryDao.java b/app/src/main/java/com/gh/gamecenter/db/SearchHistoryDao.java new file mode 100644 index 0000000000..bcbd2aeebd --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/db/SearchHistoryDao.java @@ -0,0 +1,78 @@ +package com.gh.gamecenter.db; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import android.content.Context; + +import com.gh.gamecenter.db.info.SearchHistoryInfo; +import com.j256.ormlite.dao.CloseableIterator; +import com.j256.ormlite.dao.Dao; + +public class SearchHistoryDao { + + private DatabaseHelper helper; + private Daodao; + + public SearchHistoryDao(Context context){ + try{ + helper = DatabaseHelper.getHelper(context); + dao = helper.getDao(SearchHistoryInfo.class); + } catch (SQLException e) { + + e.printStackTrace(); + } + } + + public void add(String item){ + try{ + dao.createOrUpdate(new SearchHistoryInfo(item)); + } catch (SQLException e) { + + e.printStackTrace(); + } + } + + public void delete(String item){ + try { + dao.deleteById(item); + } catch (SQLException e) { + + e.printStackTrace(); + } + } + + public void deleteAll(){ + + CloseableIterator iterator = dao.iterator(); + while(iterator.hasNext()){ + try { + dao.delete(iterator.next()); + } catch (SQLException e) { + + e.printStackTrace(); + } + } + return; + } + + public List getAll(){ + List history = new ArrayList(); + + try { + List his = dao.queryBuilder().orderBy("time", false).query(); + Iterator hisIterator = his.iterator(); + while(hisIterator.hasNext()){ + history.add(hisIterator.next().getItem()); + } + } catch (SQLException e) { + + e.printStackTrace(); + } + return history; + } + + +} diff --git a/app/src/main/java/com/gh/gamecenter/db/SuspectedGameDao.java b/app/src/main/java/com/gh/gamecenter/db/SuspectedGameDao.java new file mode 100644 index 0000000000..6ff6a63b79 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/db/SuspectedGameDao.java @@ -0,0 +1,99 @@ +package com.gh.gamecenter.db; + +import java.sql.SQLException; +import java.util.List; + +import android.content.Context; + +import com.gh.gamecenter.db.info.SuspectedGameInfo; +import com.j256.ormlite.dao.Dao; + +public class SuspectedGameDao { + + private DatabaseHelper helper; + private Dao dao; + + public SuspectedGameDao(Context context) { + try { + helper = DatabaseHelper.getHelper(context); + dao = helper.getDao(SuspectedGameInfo.class); + } catch (SQLException e) { + + e.printStackTrace(); + } + } + + /** + * 添加一个疑似游戏 + */ + public void add(SuspectedGameInfo entity) { + try { + dao.create(entity); + } catch (SQLException e) { + + e.printStackTrace(); + } + } + + /** + * 删除一个疑似游戏 + */ + public void delete(String packageName) { + try { + dao.deleteById(packageName); + } catch (SQLException e) { + + e.printStackTrace(); + } + } + + /** + * 根据包名获取某一个疑似游戏 + */ + public SuspectedGameInfo find(String packageName) { + try { + return dao.queryForId(packageName); + } catch (SQLException e) { + + e.printStackTrace(); + } + return null; + } + + /** + * 获取所有的疑似游戏 + */ + public List getAll() { + try { + return dao.queryForAll(); + } catch (SQLException e) { + + e.printStackTrace(); + } + return null; + } + + /** + * 更新疑似游戏 + */ + public void update(SuspectedGameInfo entity) { + try { + dao.update(entity); + } catch (SQLException e) { + + e.printStackTrace(); + } + } + + public void deleteAll() { + try { + List list = dao.queryForAll(); + for (int i = 0, size = list.size(); i < size; i++) { + dao.deleteById(list.get(i).getPackageName()); + } + } catch (SQLException e) { + + e.printStackTrace(); + } + } +} diff --git a/app/src/main/java/com/gh/gamecenter/db/info/ConcernInfo.java b/app/src/main/java/com/gh/gamecenter/db/info/ConcernInfo.java new file mode 100644 index 0000000000..fcf8a15201 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/db/info/ConcernInfo.java @@ -0,0 +1,171 @@ +package com.gh.gamecenter.db.info; + +import java.io.Serializable; +import java.util.HashMap; + +import com.j256.ormlite.field.DataType; +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; + +@DatabaseTable(tableName = "tb_concern") +public class ConcernInfo implements Serializable { + + /** + * + */ + private static final long serialVersionUID = -7284046360961851205L; + + @DatabaseField(id = true, columnName = "id") + private String id; + + @DatabaseField(columnName = "time") + private long time; + + @DatabaseField(columnName = "gameName") + private String gameName; + + @DatabaseField(columnName = "icon") + private String icon; + + @DatabaseField(columnName = "tag") + private String tag; + + @DatabaseField(columnName = "isConcern") + private boolean isConcern; + + @DatabaseField(columnName = "isInstalled") + private boolean isInstalled; + + @DatabaseField(columnName = "installedQuantity") + private int installedQuantity; + + @DatabaseField(columnName = "packageNames", dataType = DataType.SERIALIZABLE) + private HashMap packageNames; + + @DatabaseField(columnName = "weight") + private int weight; + + @DatabaseField(columnName = "traffic") + private long traffic; + + public ConcernInfo() { + + } + + public ConcernInfo(String id, long time, String gameName, String icon, + String tag, boolean isConcern, boolean isInstalled, + int installedQuantity, HashMap packageNames, + int weight, long traffic) { + super(); + this.id = id; + this.time = time; + this.gameName = gameName; + this.icon = icon; + this.tag = tag; + this.isConcern = isConcern; + this.isInstalled = isInstalled; + this.installedQuantity = installedQuantity; + this.packageNames = packageNames; + this.weight = weight; + this.traffic = traffic; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + public String getGameName() { + return gameName; + } + + public void setGameName(String gameName) { + this.gameName = gameName; + } + + public String getIcon() { + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + public boolean isConcern() { + return isConcern; + } + + public void setConcern(boolean isConcern) { + this.isConcern = isConcern; + } + + public boolean isInstalled() { + return isInstalled; + } + + public void setInstalled(boolean isInstalled) { + this.isInstalled = isInstalled; + } + + public int getInstalledQuantity() { + return installedQuantity; + } + + public void setInstalledQuantity(int installedQuantity) { + this.installedQuantity = installedQuantity; + } + + public HashMap getPackageNames() { + return packageNames; + } + + public void setPackageNames(HashMap packageNames) { + this.packageNames = packageNames; + } + + public int getWeight() { + return weight; + } + + public void setWeight(int weight) { + this.weight = weight; + } + + public long getTraffic() { + return traffic; + } + + public void setTraffic(long traffic) { + this.traffic = traffic; + } + + @Override + public String toString() { + return "ConcernEntity [id=" + id + ", time=" + time + ", gameName=" + + gameName + ", icon=" + icon + ", tag=" + tag + ", isConcern=" + + isConcern + ", isInstalled=" + isInstalled + + ", installedQuantity=" + installedQuantity + + ", packageNames=" + packageNames + ", weight=" + weight + + ", traffic=" + traffic + "]"; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/db/info/DataCollectionInfo.java b/app/src/main/java/com/gh/gamecenter/db/info/DataCollectionInfo.java new file mode 100644 index 0000000000..03e13073ac --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/db/info/DataCollectionInfo.java @@ -0,0 +1,65 @@ +package com.gh.gamecenter.db.info; + +import java.io.Serializable; + +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; + +@DatabaseTable(tableName = "tb_datacollection") +public class DataCollectionInfo implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 3196892351397147390L; + + @DatabaseField(id = true, columnName = "id") + private String id; + + @DatabaseField(columnName = "type") + private String type; + + @DatabaseField(columnName = "data") + private String data; + + public DataCollectionInfo() { + + } + + public DataCollectionInfo(String id, String type, String data) { + this.id = id; + this.type = type; + this.data = data; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } + + @Override + public String toString() { + return "DataCollectionEntity [id=" + id + ", type=" + type + ", data=" + + data + "]"; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/db/info/FilterInfo.java b/app/src/main/java/com/gh/gamecenter/db/info/FilterInfo.java new file mode 100644 index 0000000000..603b25dafe --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/db/info/FilterInfo.java @@ -0,0 +1,41 @@ +package com.gh.gamecenter.db.info; + +import java.io.Serializable; + +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; + +@DatabaseTable(tableName = "tb_filter") +public class FilterInfo implements Serializable { + + /** + * + */ + private static final long serialVersionUID = -7081532992425638784L; + + @DatabaseField(id = true, columnName = "packageName") + private String packageName; + + public FilterInfo() { + + } + + public FilterInfo(String packageName) { + super(); + this.packageName = packageName; + } + + public String getPackageName() { + return packageName; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + @Override + public String toString() { + return "FilterEntity [packageName=" + packageName + "]"; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/db/info/GameInfo.java b/app/src/main/java/com/gh/gamecenter/db/info/GameInfo.java new file mode 100644 index 0000000000..17d7a2e0ab --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/db/info/GameInfo.java @@ -0,0 +1,66 @@ +package com.gh.gamecenter.db.info; + +import java.io.Serializable; + +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; + +@DatabaseTable(tableName = "tb_game") +public class GameInfo implements Serializable { + + /** + * + */ + private static final long serialVersionUID = -5260664512970779554L; + + @DatabaseField(id = true, columnName = "packageName") + private String packageName; + + @DatabaseField(columnName = "id") + private String id; + + @DatabaseField(columnName = "gameName") + private String gameName; + + public GameInfo() { + + } + + public GameInfo(String packageName, String id, String gameName) { + super(); + this.packageName = packageName; + this.id = id; + this.gameName = gameName; + } + + public String getPackageName() { + return packageName; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getGameName() { + return gameName; + } + + public void setGameName(String gameName) { + this.gameName = gameName; + } + + @Override + public String toString() { + return "GameEntity [packageName=" + packageName + ", id=" + id + + ", gameName=" + gameName + "]"; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/db/info/SearchHistoryInfo.java b/app/src/main/java/com/gh/gamecenter/db/info/SearchHistoryInfo.java new file mode 100644 index 0000000000..c939b433cb --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/db/info/SearchHistoryInfo.java @@ -0,0 +1,59 @@ +package com.gh.gamecenter.db.info; + +import java.io.Serializable; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; + +@DatabaseTable(tableName = "tb_search") +public class SearchHistoryInfo implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 1L; + + @DatabaseField(id = true, columnName = "item") + private String item; + + @DatabaseField(useGetSet = true, columnName = "time") + private String time; + + public String getTime() { + return time; + } + + public void setTime(String time) { + this.time = time; + } + + public String getItem() { + return item; + } + + public SearchHistoryInfo() { + + } + + public SearchHistoryInfo(String item) { + this.item = item; + Date date = new Date(); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", + Locale.getDefault()); + this.time = format.format(date); + } + + public SearchHistoryInfo(String item, String time) { + this.item = item; + this.time = time; + } + + @Override + public String toString() { + return "SearchHistoryEntity [item=" + item + ", time=" + time + "]"; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/db/info/SuspectedGameInfo.java b/app/src/main/java/com/gh/gamecenter/db/info/SuspectedGameInfo.java new file mode 100644 index 0000000000..d29e6089a3 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/db/info/SuspectedGameInfo.java @@ -0,0 +1,54 @@ +package com.gh.gamecenter.db.info; + +import java.io.Serializable; + +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; + +@DatabaseTable(tableName = "tb_suspectedgame") +public class SuspectedGameInfo implements Serializable { + + /** + * + */ + private static final long serialVersionUID = -5623387326449838895L; + + @DatabaseField(id = true, columnName = "packageName") + private String packageName; + + @DatabaseField(columnName = "time") + private long time; + + public SuspectedGameInfo() { + + } + + public SuspectedGameInfo(String packageName, long time) { + super(); + this.packageName = packageName; + this.time = time; + } + + public String getPackageName() { + return packageName; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + @Override + public String toString() { + return "SuspectedGameEntity [packageName=" + packageName + ", time=" + + time + "]"; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/download/DownLoadManagerFragment.java b/app/src/main/java/com/gh/gamecenter/download/DownLoadManagerFragment.java new file mode 100644 index 0000000000..1609cc0a2b --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/download/DownLoadManagerFragment.java @@ -0,0 +1,875 @@ +package com.gh.gamecenter.download; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import android.app.Dialog; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.util.ArrayMap; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.Html; +import android.text.Spanned; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.View.OnLongClickListener; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.Toast; + +import com.gh.common.constant.Constants; +import com.gh.common.util.DialogUtils; +import com.gh.common.util.DisplayUtils; +import com.gh.common.util.FileUtils; +import com.gh.common.util.ImageUtils; +import com.gh.common.util.PackageUtils; +import com.gh.common.util.PlatformUtils; +import com.gh.common.util.SpeedUtils; +import com.gh.common.view.Gh_LinearLayout; +import com.gh.common.view.VerticalItemDecoration; +import com.gh.download.DataWatcher; +import com.gh.download.DownloadEntry; +import com.gh.download.DownloadManager; +import com.gh.download.DownloadStatus; +import com.gh.gamecenter.MainActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.eventbus.EBDownloadChanged; +import com.gh.gamecenter.eventbus.EBDownloadDelete; +import com.gh.gamecenter.eventbus.EBMiPush; +import com.gh.gamecenter.eventbus.EBPackage; +import com.gh.gamecenter.eventbus.EBPutUrl; +import com.gh.gamecenter.eventbus.EBShowDone; +import com.gh.gamecenter.eventbus.EBUISwitch; +import com.gh.gamecenter.manager.PackageManager; +import com.tendcloud.tenddata.TCAgent; + +import de.greenrobot.event.EventBus; + +/** + * 下载管理 fragment + * + * @author 黄壮华 + * + */ +public class DownLoadManagerFragment extends Fragment { + + private View view; + private RecyclerView downloadmanager_rv_show; + private LinearLayoutManager linearLayoutManager; + + private TextView downloadmanager_tv_none; + + private ArrayMap lastTimeMap; + private ArrayMap locationMap; + private ArrayMap statusMap; + private ArrayMap urlMap; + private List statusList; + private List list; + private ArrayMap isShowMap; + private ArrayList deleteList; + + private int oldClickViewPosition; + + private String path; + + private boolean isDestroy = false; + + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (!isDestroy) { + if (msg.what == Constants.CONTINUE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + DownloadManager.getInstance(getActivity()).resume(url); + } + } else if (msg.what == Constants.PAUSE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + DownloadManager.getInstance(getActivity()).pause(url); + } + } + } + } + }; + + private DataWatcher dataWatcher = new DataWatcher() { + @Override + public void onDataChanged( + HashMap downloadingEntries) { + for (Entry entry : downloadingEntries + .entrySet()) { + + Integer location = locationMap.get(entry.getValue().getUrl()); + + if (location != null) { + if (!"pause".equals(statusMap + .get(entry.getValue().getUrl()))) { + list.set(location.intValue(), entry.getValue()); + downloadmanager_rv_show.getAdapter().notifyItemChanged( + location.intValue() + 1); + statusList.set(location.intValue(), entry.getValue() + .getStatus()); + if (entry.getValue().getStatus() == DownloadStatus.neterror) { + downloadmanager_rv_show.getAdapter() + .notifyItemChanged(0); + } + } + } else { + if (!deleteList.contains(entry.getValue().getUrl())) { + DownloadStatus status = entry.getValue().getStatus(); + if (status.equals(DownloadStatus.downloading) + || status.equals(DownloadStatus.waiting)) { + list.add(entry.getValue()); + if (list.size() == 1) { + EventBus.getDefault().post( + new EBDownloadChanged("download", + View.VISIBLE, 1)); + } else { + EventBus.getDefault().post( + new EBDownloadChanged("download", + View.VISIBLE, list.size())); + } + locationMap.put(entry.getValue().getUrl(), + list.size() - 1); + downloadmanager_rv_show.getAdapter() + .notifyItemInserted(list.size()); + statusList.add(list.size() - 1, status); + if (list.size() == 1) { + downloadmanager_rv_show.getAdapter() + .notifyDataSetChanged(); + if (downloadmanager_tv_none.getVisibility() == View.VISIBLE) { + downloadmanager_tv_none + .setVisibility(View.GONE); + } + } else { + downloadmanager_rv_show.getAdapter() + .notifyItemInserted(list.size()); + downloadmanager_rv_show.getAdapter() + .notifyItemChanged(0); + } + } + } + } + + if (entry.getValue().getStatus().equals(DownloadStatus.done)) { + urlMap.put(PackageUtils.getPackageNameByPath(getActivity(), + entry.getValue().getPath()), entry.getValue() + .getUrl()); + statusList.set(location, DownloadStatus.done); + downloadmanager_rv_show.getAdapter().notifyItemChanged(0); + } + } + } + }; + + public DownLoadManagerFragment() { + + } + + public DownLoadManagerFragment(String path) { + this.path = path; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + view = View.inflate(getActivity(), R.layout.downloadmanager, null); + + list = new ArrayList(); + lastTimeMap = new ArrayMap(); + locationMap = new ArrayMap(); + statusMap = new ArrayMap(); + urlMap = new ArrayMap(); + statusList = new ArrayList(); + isShowMap = new ArrayMap(); + deleteList = new ArrayList(); + oldClickViewPosition = -1; + + linearLayoutManager = new LinearLayoutManager(getActivity()); + linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + downloadmanager_rv_show = (RecyclerView) view + .findViewById(R.id.downloadmanager_rv_show); + downloadmanager_rv_show.setHasFixedSize(true); + downloadmanager_rv_show.addItemDecoration(new VerticalItemDecoration( + getActivity(), 1)); + downloadmanager_rv_show.setAdapter(new DownLoadListAdapter()); + downloadmanager_rv_show.setLayoutManager(linearLayoutManager); + + if (path != null) { + showPluginDialog(path); + } + + EventBus.getDefault().register(this); + + downloadmanager_tv_none = (TextView) view + .findViewById(R.id.downloadmanager_tv_none); + } + + @Override + @Nullable + public View onCreateView(LayoutInflater inflater, + @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + + if (container != null) { + container.removeView(view); + } + return view; + } + + private class DownloadViewHolder extends RecyclerView.ViewHolder implements + OnClickListener, OnLongClickListener { + private Gh_LinearLayout view; + private ImageView dm_item_iv_icon; + private ProgressBar dm_item_progressbar; + private TextView dm_item_tv_title, dm_item_tv_downloads, + dm_item_tv_speed, dm_item_tv_startorpause; + private LinearLayout dm_item, dm_item_ll_delete; + + private TextView dm_item_top_tv_allstart; + + public DownloadViewHolder(View convertView) { + super(convertView); + if ((Integer) convertView.getTag() == 1) { + dm_item_top_tv_allstart = (TextView) convertView + .findViewById(R.id.dm_item_top_tv_allstart); + dm_item_top_tv_allstart.setOnClickListener(this); + } else { + view = (Gh_LinearLayout) convertView; + view.setOnClickListener(this); + view.setOnLongClickListener(this); + dm_item = (LinearLayout) convertView.findViewById(R.id.dm_item); + dm_item_iv_icon = (ImageView) convertView + .findViewById(R.id.dm_item_iv_icon); + dm_item_tv_title = (TextView) convertView + .findViewById(R.id.dm_item_tv_title); + dm_item_progressbar = (ProgressBar) convertView + .findViewById(R.id.dm_item_progressbar); + dm_item_tv_downloads = (TextView) convertView + .findViewById(R.id.dm_item_tv_downloads); + dm_item_tv_speed = (TextView) convertView + .findViewById(R.id.dm_item_tv_speed); + dm_item_tv_startorpause = (TextView) convertView + .findViewById(R.id.dm_item_tv_startorpause); + dm_item_tv_startorpause.setOnClickListener(this); + dm_item_ll_delete = (LinearLayout) convertView + .findViewById(R.id.dm_item_ll_delete); + dm_item_ll_delete.setOnClickListener(this); + } + } + + @Override + public boolean onLongClick(View v) { + + if (dm_item_ll_delete.getVisibility() == View.VISIBLE) { + ((Gh_LinearLayout) v).hideDeleteView(); + isShowMap.put(list.get(getPosition() - 1).getUrl(), false); + oldClickViewPosition = -1; + } else { + if (oldClickViewPosition != getPosition() + && oldClickViewPosition != -1) { + if (linearLayoutManager + .findViewByPosition(oldClickViewPosition) != null) { + ((Gh_LinearLayout) linearLayoutManager + .findViewByPosition(oldClickViewPosition)) + .hideDeleteView(); + } else { + downloadmanager_rv_show.getAdapter().notifyItemChanged( + oldClickViewPosition); + } + isShowMap.put(list.get(oldClickViewPosition - 1).getUrl(), + false); + } + ((Gh_LinearLayout) v).showDeleteView(getPosition()); + isShowMap.put(list.get(getPosition() - 1).getUrl(), true); + oldClickViewPosition = getPosition(); + } + return true; + } + + @Override + public void onClick(View v) { + if (v == view) { + if (dm_item_ll_delete.getVisibility() == View.VISIBLE) { + ((Gh_LinearLayout) v).hideDeleteView(); + isShowMap.put(list.get(getPosition() - 1).getUrl(), false); + oldClickViewPosition = -1; + } else { + if (oldClickViewPosition != getPosition() + && oldClickViewPosition != -1) { + if (linearLayoutManager + .findViewByPosition(oldClickViewPosition) != null) { + ((Gh_LinearLayout) linearLayoutManager + .findViewByPosition(oldClickViewPosition)) + .hideDeleteView(); + } else { + downloadmanager_rv_show.getAdapter() + .notifyItemChanged(oldClickViewPosition); + } + isShowMap.put(list.get(oldClickViewPosition - 1) + .getUrl(), false); + } + ((Gh_LinearLayout) v).showDeleteView(getPosition()); + isShowMap.put(list.get(getPosition() - 1).getUrl(), true); + oldClickViewPosition = getPosition(); + } + } else if (v == dm_item_tv_startorpause) { + String str = dm_item_tv_startorpause.getText().toString(); + String url = list.get(getPosition() - 1).getUrl(); + lastTimeMap.put(url, System.currentTimeMillis()); + if ("继续".equals(str) || "下载".equals(str)) { + dm_item_tv_startorpause + .setBackgroundResource(R.drawable.textview_gray_style); + dm_item_tv_startorpause.setTextColor(0xFF999999); + dm_item_tv_startorpause.setText("暂停"); + dm_item_tv_downloads.setText(SpeedUtils.getSpeed(list.get( + getPosition() - 1).getSpeed()) + + "(剩" + + SpeedUtils + .getRemainTime(list.get(getPosition() - 1) + .getSize(), + list.get(getPosition() - 1) + .getProgress(), + list.get(getPosition() - 1) + .getSpeed() * 1024) + ")"); + statusMap.put(url, "downloading"); + statusList.set(getPosition() - 1, + DownloadStatus.downloading); + downloadmanager_rv_show.getAdapter().notifyItemChanged(0); + Message msg = Message.obtain(); + msg.what = Constants.CONTINUE_DOWNLOAD_TASK; + msg.obj = url; + handler.sendMessageDelayed(msg, 1000); + } else if ("安装".equals(str)) { + DownloadEntry downloadEntry = list.get(getPosition() - 1); + String path = downloadEntry.getPath(); + if (downloadEntry != null + && downloadEntry.getMeta().get("isPlugin") != null) { + Map kv6 = new HashMap(); + kv6.put("操作", "点击安装完成"); + TCAgent.onEvent(getActivity(), "插件化", + downloadEntry.getName(), kv6); + } + if (FileUtils.isEmptyFile(path)) { + Toast.makeText(getActivity(), "解析包错误", + Toast.LENGTH_SHORT).show(); + dm_item_ll_delete.performClick(); + } else { + if (list.get(getPosition() - 1).getName() + .contains("光环助手")) { + startActivity(PackageUtils.getInstallIntent(path)); + } else { + PackageManager manager = new PackageManager( + getActivity()); + if (manager.launchSetup(path)) { + startActivity(PackageUtils + .getInstallIntent(path)); + } else { + DialogUtils.showDialog(getActivity(), path); + } + } + } + } else if ("插件化".equals(str)) { + DownloadEntry downloadEntry = list.get(getPosition() - 1); + showPluginDialog(downloadEntry.getPath()); + } else if ("暂停".equals(str)) { + dm_item_tv_startorpause + .setBackgroundResource(R.drawable.textview_blue_style); + dm_item_tv_startorpause.setTextColor(0xFFFFFFFF); + dm_item_tv_startorpause.setText("继续"); + dm_item_tv_downloads.setText(""); + statusMap.put(url, "pause"); + statusList.set(getPosition() - 1, DownloadStatus.pause); + downloadmanager_rv_show.getAdapter().notifyItemChanged(0); + Message msg = Message.obtain(); + msg.what = Constants.PAUSE_DOWNLOAD_TASK; + msg.obj = url; + handler.sendMessageDelayed(msg, 1000); + } else if ("等待".equals(str)) { + Toast.makeText(getActivity(), "最多同时有3个下载任务", + Toast.LENGTH_SHORT).show(); + } else if ("启动".equals(str)) { + + Map kv = new HashMap(); + kv.put("版本", + list.get(getPosition() - 1).getMeta() + .get("platform")); + TCAgent.onEvent(getActivity(), "游戏启动", + list.get(getPosition() - 1).getName(), kv); + + PackageUtils.launchApplicationByPackageName( + getActivity(), + list.get(getPosition() - 1).getMeta() + .get("packageName")); + } + } else if (v == dm_item_top_tv_allstart) { + String str = dm_item_top_tv_allstart.getText().toString(); + if ("全部开始".equals(str)) { + for (int i = 0, size = list.size(); i < size; i++) { + if (!DownloadStatus.done + .equals(list.get(i).getStatus())) { + View view = downloadmanager_rv_show + .getChildAt(i + 1); + if (view != null) { + TextView tv = (TextView) view + .findViewById(R.id.dm_item_tv_startorpause); + if (tv.getText().toString().equals("继续")) { + tv.performClick(); + } + } else { + lastTimeMap.put(list.get(i).getUrl(), + System.currentTimeMillis()); + Message msg = Message.obtain(); + msg.what = Constants.CONTINUE_DOWNLOAD_TASK; + msg.obj = list.get(i).getUrl(); + handler.sendMessageDelayed(msg, 1000); + statusMap.put(list.get(i).getUrl(), + "downloading"); + statusList.set(i, DownloadStatus.downloading); + } + } + } + dm_item_top_tv_allstart.setText("全部暂停"); + dm_item_top_tv_allstart.setTextColor(0xff999999); + } else { + for (int i = 0, size = list.size(); i < size; i++) { + if (!DownloadStatus.done + .equals(list.get(i).getStatus())) { + View view = downloadmanager_rv_show + .getChildAt(i + 1); + if (view != null) { + TextView tv = (TextView) view + .findViewById(R.id.dm_item_tv_startorpause); + if (tv.getText().toString().equals("暂停")) { + tv.performClick(); + } else if (tv.getText().toString().equals("等待")) { + DownloadManager.getInstance(getActivity()) + .pause(list.get(i).getUrl()); + statusList.set(i, DownloadStatus.pause); + } + } else { + lastTimeMap.put(list.get(i).getUrl(), + System.currentTimeMillis()); + Message msg = Message.obtain(); + msg.what = Constants.PAUSE_DOWNLOAD_TASK; + msg.obj = list.get(i).getUrl(); + handler.sendMessageDelayed(msg, 1000); + statusList.set(i, DownloadStatus.pause); + } + } + } + dm_item_top_tv_allstart.setText("全部开始"); + dm_item_top_tv_allstart.setTextColor(0xff1BA4FC); + } + } else if (v == dm_item_ll_delete) { + final int position = getPosition(); + if (position - 1 < list.size()) { + DownloadEntry entry = list.remove(position - 1); + deleteList.add(entry.getUrl()); + isShowMap.put(entry.getUrl(), false); + if (oldClickViewPosition == position) { + oldClickViewPosition = -1; + } + statusMap.remove(entry.getUrl()); + locationMap.remove(entry.getUrl()); + if (position - 1 < statusList.size()) { + statusList.remove(position - 1); + } + downloadmanager_rv_show.getAdapter().notifyItemChanged(0); + if (list.isEmpty()) { + EventBus.getDefault().post( + new EBDownloadChanged("download", View.GONE, 0)); + locationMap.clear(); + downloadmanager_rv_show.getAdapter().notifyDataSetChanged(); + if (downloadmanager_tv_none.getVisibility() == View.GONE) { + downloadmanager_tv_none.setVisibility(View.VISIBLE); + } + } else { + EventBus.getDefault().post( + new EBDownloadChanged("download", View.VISIBLE, + list.size())); + for (int i = 0, size = list.size(); i < size; i++) { + locationMap.put(list.get(i).getUrl(), i); + } + downloadmanager_rv_show.getAdapter().notifyItemRemoved( + position); + } + + EventBus.getDefault().post( + new EBDownloadDelete(entry.getName(), entry.getMeta() + .get("platform"), entry.getUrl())); + + DownloadManager.getInstance(getActivity()).cancel( + entry.getUrl()); + } + } + } + } + + // 显示插件化 + private void showPluginDialog(final String path) { + final Dialog dialog = new Dialog(getActivity()); + View view = View.inflate(getActivity(), + R.layout.search_history_delete_dialog, null); + TextView title = (TextView) view.findViewById(R.id.delete_dialog_title); + title.setText("插件化安装"); + TextView content = (TextView) view + .findViewById(R.id.delete_dialog_message); + Spanned spanned = Html.fromHtml("您将进行插件化安装以实现插件功能,此过程将" + + "卸载" + "当前使用的版本并" + + "安装插件版本" + "。"); + content.setText(spanned); + + TextView cancel = (TextView) view + .findViewById(R.id.delete_dialog_cancel); + cancel.setText("取消"); + cancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + TextView confirm = (TextView) view + .findViewById(R.id.delete_dialog_confirm); + confirm.setText("确定"); + confirm.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + + for (DownloadEntry downloadEntry : DownloadManager.getInstance( + getActivity()).getAll()) { + if (downloadEntry.getMeta().get("isPlugin") != null + && downloadEntry.getPath().equals(path)) { + Map kv6 = new HashMap(); + kv6.put("操作", "点击插件化安装完成"); + TCAgent.onEvent(getActivity(), "插件化", + downloadEntry.getName(), kv6); + break; + } + } + + if (FileUtils.isEmptyFile(path)) { + Toast.makeText(getActivity(), "解析包错误", Toast.LENGTH_SHORT) + .show(); + } else { + MainActivity.uninstallMap.put(PackageUtils + .getPackageNameByPath(getActivity(), path), path); + startActivity(PackageUtils.getUninstallIntent( + getActivity(), path)); + } + } + }); + + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.show(); + } + + private class DownLoadListAdapter extends + RecyclerView.Adapter { + + @Override + public int getItemCount() { + if (list.isEmpty()) { + return 0; + } + return list.size() + 1; + } + + @Override + public void onBindViewHolder(DownloadViewHolder viewHolder, int position) { + if (position == 0) { + int dlNumber = 0; + int dnNumber = 0; + int wtNumber = 0; + for (int i = 0, size = statusList.size(); i < size; i++) { + if (DownloadStatus.downloading.equals(statusList.get(i))) { + dlNumber++; + } else if (DownloadStatus.done.equals(statusList.get(i))) { + dnNumber++; + } else if (DownloadStatus.waiting.equals(statusList.get(i))) { + wtNumber++; + } + } + if (dnNumber == statusList.size()) { + viewHolder.dm_item_top_tv_allstart.setVisibility(View.GONE); + } else if ((dlNumber + wtNumber) != (statusList.size() - dnNumber)) { + viewHolder.dm_item_top_tv_allstart + .setVisibility(View.VISIBLE); + viewHolder.dm_item_top_tv_allstart.setText("全部开始"); + viewHolder.dm_item_top_tv_allstart.setTextColor(0xff1BA4FC); + } else { + viewHolder.dm_item_top_tv_allstart + .setVisibility(View.VISIBLE); + viewHolder.dm_item_top_tv_allstart.setText("全部暂停"); + viewHolder.dm_item_top_tv_allstart.setTextColor(0xff999999); + } + } else { + + DownloadEntry entry = list.get(position - 1); + + if (!viewHolder.view.isSliding()) { + Boolean isShow = isShowMap.get(entry.getUrl()); + if (isShow != null && isShow.booleanValue()) { + LayoutParams lparams = new LayoutParams( + LayoutParams.MATCH_PARENT, DisplayUtils.dip2px( + getActivity(), 96)); + viewHolder.dm_item.setLayoutParams(lparams); + viewHolder.dm_item_ll_delete + .setVisibility(View.VISIBLE); + } else { + LayoutParams lparams = new LayoutParams( + LayoutParams.MATCH_PARENT, DisplayUtils.dip2px( + getActivity(), 66)); + viewHolder.dm_item.setLayoutParams(lparams); + viewHolder.dm_item_ll_delete.setVisibility(View.GONE); + } + } + + String icon = entry.getMeta().get("icon"); + if (!TextUtils.isEmpty(icon)) { + ImageUtils.getInstance(getActivity()).display(icon, + viewHolder.dm_item_iv_icon); + } else { + viewHolder.dm_item_iv_icon + .setImageResource(R.drawable.logo); + } + if (entry.getName().contains("光环助手")) { + viewHolder.dm_item_tv_title.setText(entry.getName()); + } else { + String platform = entry.getMeta().get("platform"); + if ("local_plugin".equals(platform)) { + viewHolder.dm_item_tv_title.setText(entry.getName()); + } else { + platform = PlatformUtils.getInstance(getActivity()) + .getPlatformName(platform); + if (platform == null) { + viewHolder.dm_item_tv_title + .setText(entry.getName()); + } else { + viewHolder.dm_item_tv_title.setText(entry.getName() + + " - " + platform); + } + } + } + viewHolder.dm_item_progressbar.setProgress((int) (entry + .getPercent() * 10)); + switch (entry.getStatus()) { + case done: + EventBus.getDefault().post( + new EBPutUrl(PackageUtils.getPackageNameByPath( + getActivity(), entry.getPath()), entry + .getUrl())); + viewHolder.dm_item_tv_downloads.setText("下载完成"); + viewHolder.dm_item_tv_startorpause + .setBackgroundResource(R.drawable.textview_blue_style); + viewHolder.dm_item_tv_startorpause.setTextColor(0xFFFFFFFF); + if (entry.getMeta().get("isPlugin") != null + && PackageManager.isInstalled(entry.getMeta().get( + "package_name"))) { + viewHolder.dm_item_tv_startorpause.setText("插件化"); + viewHolder.dm_item_tv_startorpause + .setBackgroundResource(R.drawable.textview_orange_style); + } else { + viewHolder.dm_item_tv_startorpause.setText("安装"); + viewHolder.dm_item_tv_startorpause + .setBackgroundResource(R.drawable.textview_blue_style); + } + viewHolder.dm_item_tv_speed.setText("100%"); + break; + case downloading: + if (!"pause".equals(statusMap.get(entry.getUrl()))) { + viewHolder.dm_item_tv_downloads.setText(SpeedUtils + .getSpeed(entry.getSpeed()) + + "(剩" + + SpeedUtils.getRemainTime(entry.getSize(), + entry.getProgress(), + entry.getSpeed() * 1024) + ")"); + viewHolder.dm_item_tv_startorpause + .setBackgroundResource(R.drawable.textview_gray_style); + viewHolder.dm_item_tv_startorpause + .setTextColor(0xFF999999); + viewHolder.dm_item_tv_startorpause.setText("暂停"); + viewHolder.dm_item_tv_speed.setText(entry.getPercent() + + "%"); + } + break; + case waiting: + viewHolder.dm_item_tv_downloads.setText(""); + viewHolder.dm_item_tv_startorpause + .setBackgroundResource(R.drawable.textview_gray_style); + viewHolder.dm_item_tv_startorpause.setTextColor(0xFF999999); + viewHolder.dm_item_tv_startorpause.setText("等待"); + viewHolder.dm_item_tv_speed.setText(entry.getPercent() + + "%"); + break; + case pause: + case neterror: + viewHolder.dm_item_tv_downloads.setText(""); + viewHolder.dm_item_tv_startorpause + .setBackgroundResource(R.drawable.textview_blue_style); + viewHolder.dm_item_tv_startorpause.setTextColor(0xFFFFFFFF); + viewHolder.dm_item_tv_startorpause.setText("继续"); + viewHolder.dm_item_tv_speed.setText(entry.getPercent() + + "%"); + break; + default: + break; + } + } + } + + @Override + public int getItemViewType(int position) { + + if (position == 0) { + return 1; + } + return super.getItemViewType(position); + } + + @Override + public DownloadViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { + View view; + if (i == 1) { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.downloadmanager_item_top, viewGroup, false); + } else { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.downloadmanager_item, viewGroup, false); + } + view.setTag(i); + return new DownloadViewHolder(view); + } + } + + public void onEventMainThread(EBMiPush mipush) { + if ("plugin_install".equals(mipush.getFrom())) { + String path = (String) mipush.getObj(); + showPluginDialog(path); + } + } + + public void onEventMainThread(EBPackage busFour) { + String packageName = busFour.getPackageName(); + String url = urlMap.get(packageName); + if (url != null) { + int location = locationMap.get(url).intValue(); + if ("安装".equals(busFour.getType())) { + list.remove(location); + if (list.isEmpty()) { + EventBus.getDefault().post( + new EBDownloadChanged("download", View.GONE, 0)); + locationMap.clear(); + downloadmanager_rv_show.getAdapter().notifyDataSetChanged(); + if (downloadmanager_tv_none.getVisibility() == View.GONE) { + downloadmanager_tv_none.setVisibility(View.VISIBLE); + } + } else { + EventBus.getDefault().post( + new EBDownloadChanged("download", View.VISIBLE, + list.size())); + for (int i = 0, size = list.size(); i < size; i++) { + locationMap.put(list.get(i).getUrl(), i); + } + downloadmanager_rv_show.getAdapter().notifyItemRemoved( + location + 1); + } + } else if ("卸载".equals(busFour.getType())) { + downloadmanager_rv_show.getAdapter().notifyItemChanged( + location + 1); + } + } + } + + public void onEventMainThread(EBUISwitch busNine) { + if ("DownloadManagerActivity".equals(busNine.getFrom())) { + if (busNine.getPosition() != 0) { + deleteList.clear(); + } + } + } + + public void onEventMainThread(EBShowDone showDone) { + if ("下载管理".equals(showDone.getFrom()) + && downloadmanager_rv_show != null) { + downloadmanager_rv_show.smoothScrollToPosition(showDone + .getPosition()); + } + } + + @Override + public void onResume() { + super.onResume(); + list = DownloadManager.getInstance(getActivity()).getAll(); + locationMap.clear(); + statusMap.clear(); + urlMap.clear(); + for (int i = 0, size = list.size(); i < size; i++) { + DownloadEntry downloadEntry = list.get(i); + locationMap.put(downloadEntry.getUrl(), i); + statusMap.put(downloadEntry.getUrl(), downloadEntry.getStatus() + .name()); + statusList.add(downloadEntry.getStatus()); + if (DownloadStatus.done.equals(downloadEntry.getStatus())) { + urlMap.put(PackageUtils.getPackageNameByPath(getActivity(), + downloadEntry.getPath()), downloadEntry.getUrl()); + } + } + + DownloadManager.getInstance(getActivity()).addObserver(dataWatcher); + + downloadmanager_rv_show.getAdapter().notifyDataSetChanged(); + + if (list.isEmpty()) { + downloadmanager_tv_none.setVisibility(View.VISIBLE); + } + + } + + @Override + public void onPause() { + super.onPause(); + DownloadManager.getInstance(getActivity()).removeObserver(dataWatcher); + } + + @Override + public void onDestroy() { + + super.onDestroy(); + isDestroy = true; + EventBus.getDefault().unregister(this); + view = null; + downloadmanager_rv_show = null; + linearLayoutManager = null; + downloadmanager_tv_none = null; + lastTimeMap = null; + locationMap = null; + statusMap = null; + urlMap = null; + statusList = null; + list = null; + isShowMap = null; + deleteList = null; + path = null; + handler = null; + dataWatcher = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/download/GameUpdateFragment.java b/app/src/main/java/com/gh/gamecenter/download/GameUpdateFragment.java new file mode 100644 index 0000000000..c9c5140e55 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/download/GameUpdateFragment.java @@ -0,0 +1,873 @@ +package com.gh.gamecenter.download; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.json.JSONArray; + +import android.os.Bundle; +import android.os.Handler; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.util.ArrayMap; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.util.SparseArray; +import android.util.SparseBooleanArray; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.android.volley.Response; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.common.util.DisplayUtils; +import com.gh.common.util.FileUtils; +import com.gh.common.util.ImageUtils; +import com.gh.common.util.MD5Utils; +import com.gh.common.util.PackageUtils; +import com.gh.common.util.PlatformUtils; +import com.gh.common.util.TimestampUtils; +import com.gh.common.util.Utils; +import com.gh.common.view.VerticalItemDecoration; +import com.gh.download.DownloadEntry; +import com.gh.download.DownloadManager; +import com.gh.gamecenter.R; +import com.gh.gamecenter.db.info.ConcernInfo; +import com.gh.gamecenter.entity.GameUpdateEntity; +import com.gh.gamecenter.eventbus.EBDownloadChanged; +import com.gh.gamecenter.eventbus.EBDownloadDelete; +import com.gh.gamecenter.eventbus.EBMiPush; +import com.gh.gamecenter.eventbus.EBPackage; +import com.gh.gamecenter.eventbus.EBPerformClick; +import com.gh.gamecenter.manager.ConcernManager; +import com.gh.gamecenter.manager.PackageManager; +import com.gh.gamecenter.volley.extended.JsonArrayExtendedRequest; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.tendcloud.tenddata.TCAgent; + +import de.greenrobot.event.EventBus; + +/** + * 游戏更新管理fragment + * + * @author 黄壮华 + * + */ +public class GameUpdateFragment extends Fragment { + + private View view; + private RecyclerView gameupdate_rv_show; + private LinearLayout gameupdate_ll_loading; + + private TextView gameupdate_tv_none; + + private ArrayList list; + private ArrayMap locationMap; + private ArrayMap packageNameMap; + private SparseArray entryMap; + private SparseBooleanArray successMap; + + private String packageName; + + private boolean isUpdate; + + private Handler handler = new Handler(); + + @Override + public void onSaveInstanceState(Bundle outState) { + + super.onSaveInstanceState(outState); + Utils.log(this.getClass().getSimpleName() + " onSaveInstanceState"); + outState.putString("packageName", packageName); + outState.putBoolean("isUpdate", isUpdate); + } + + public GameUpdateFragment() { + + } + + public GameUpdateFragment(String str, boolean flag) { + packageName = str; + isUpdate = flag; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + if (savedInstanceState != null) { + if (savedInstanceState.containsKey("packageName")) { + packageName = savedInstanceState.getString("packageName"); + } + if (savedInstanceState.containsKey("isUpdate")) { + isUpdate = savedInstanceState.getBoolean("isUpdate"); + } + } + + view = View.inflate(getActivity(), R.layout.gameupdate, null); + + gameupdate_ll_loading = (LinearLayout) view + .findViewById(R.id.gameupdate_ll_loading); + + list = new ArrayList(); + if (packageName != null) { + getUpdateByPackageName(); + } else if (isUpdate) { + getUpdateListFromServer(); + } else { + for (GameUpdateEntity game : PackageManager.getUpdateList()) { + list.add(game); + } + sortList(list); + } + + List entries = DownloadManager + .getInstance(getActivity()).getAll(); + + for (int i = 0, size = entries.size(); i < size; i++) { + DownloadEntry downloadEntry = entries.get(i); + if (downloadEntry.getMeta().get("isPlugin") != null + && PackageManager.isInstalled(downloadEntry.getMeta().get( + "package_name"))) { + GameUpdateEntity game = new GameUpdateEntity(downloadEntry + .getMeta().get("game_id"), downloadEntry.getName(), + downloadEntry.getMeta().get("icon"), downloadEntry + .getMeta().get("package_name"), downloadEntry + .getMeta().get("size"), downloadEntry.getMeta() + .get("version"), downloadEntry.getMeta().get( + "gh_version"), downloadEntry.getUrl(), + downloadEntry.getMeta().get("platform"), true); + if (list.isEmpty()) { + PackageManager.addUpdate(game); + list.add(game); + } else { + for (int j = 0; j < list.size(); j++) { + if (list.get(j).getUrl().equals(game.getUrl())) { + break; + } else if (j == list.size() - 1) { + PackageManager.addUpdate(game); + list.add(game); + } + } + } + EventBus.getDefault().post( + new EBDownloadChanged("update", View.VISIBLE, list + .size())); + } + } + + locationMap = new ArrayMap(); + packageNameMap = new ArrayMap(); + entryMap = new SparseArray(); + successMap = new SparseBooleanArray(); + + for (int i = 0, size = list.size(); i < size; i++) { + GameUpdateEntity game = list.get(i); + locationMap.put(game.getPackageName(), i); + packageNameMap.put(game.getUrl(), game.getPackageName()); + successMap.put(i, false); + for (DownloadEntry downloadEntry : entries) { + if (game.getUrl().equals(downloadEntry.getUrl())) { + entryMap.put(i, downloadEntry); + break; + } + } + } + + LinearLayoutManager linearLayoutManager = new LinearLayoutManager( + getActivity()); + linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + gameupdate_rv_show = (RecyclerView) view + .findViewById(R.id.gameupdate_rv_show); + gameupdate_rv_show.setHasFixedSize(true); + gameupdate_rv_show.addItemDecoration(new VerticalItemDecoration( + getActivity(), 1)); + gameupdate_rv_show.setLayoutManager(linearLayoutManager); + gameupdate_rv_show.setAdapter(new GameUpdateListAdapter()); + + EventBus.getDefault().register(this); + + gameupdate_tv_none = (TextView) view + .findViewById(R.id.gameupdate_tv_none); + + if (list.isEmpty()) { + gameupdate_tv_none.setVisibility(View.VISIBLE); + } + + } + + private void getUpdateByPackageName() { + gameupdate_ll_loading.setVisibility(View.VISIBLE); + + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp( + Config.HOST + "v1d45/support/package/update?package=" + + packageName, Constants.UPDATE_CD), + new Response.Listener() { + + @Override + public void onResponse(JSONArray response) { + + if (response.length() != 0) { + Gson gson = new Gson(); + GameUpdateEntity game = gson.fromJson( + response.toString(), GameUpdateEntity.class); + list.add(game); + + int i = list.size() - 1; + locationMap.put(list.get(i).getPackageName(), i); + packageNameMap.put(list.get(i).getUrl(), list + .get(i).getPackageName()); + successMap.put(i, false); + + PackageManager.addUpdateList(list); + gameupdate_ll_loading.setVisibility(View.GONE); + + EventBus.getDefault().post( + new EBDownloadChanged("update", + View.VISIBLE, list.size())); + + gameupdate_rv_show.getAdapter() + .notifyDataSetChanged(); + + if (!list.isEmpty() + && gameupdate_tv_none.getVisibility() == View.VISIBLE) { + gameupdate_tv_none.setVisibility(View.GONE); + } + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + + gameupdate_ll_loading.setVisibility(View.GONE); + } + }); + AppController.addToRequestQueue(request, GameUpdateFragment.class); + } + + @Override + @Nullable + public View onCreateView(LayoutInflater inflater, + @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + + if (container != null) { + container.removeView(view); + } + return view; + } + + private List getInstalledList() { + List packages = new ArrayList(); + ConcernManager concernManager = new ConcernManager(getActivity()); + for (ConcernInfo info : concernManager.getInstalledGame()) { + for (String key : info.getPackageNames().keySet()) { + if (info.getPackageNames().get(key)) { + packages.add(key); + } + } + } + return packages; + } + + private void getUpdateListFromServer() { + + gameupdate_ll_loading.setVisibility(View.VISIBLE); + + List packages = getInstalledList(); + + if (packages.size() != 0) { + Comparator comparator = new Comparator() { + @Override + public int compare(String lhs, String rhs) { + + char[] clhs = lhs.toCharArray(); + char[] crhs = rhs.toCharArray(); + int length = 0; + if (clhs.length < crhs.length) { + length = clhs.length; + } else if (clhs.length > crhs.length) { + length = crhs.length; + } else { + length = clhs.length; + } + for (int i = 0; i < length; i++) { + if (clhs[i] > crhs[i]) { + return 1; + } else if (clhs[i] < crhs[i]) { + return -1; + } else if (i == length - 1) { + if (clhs.length < crhs.length) { + return -1; + } else if (clhs.length > crhs.length) { + return 1; + } else { + return 0; + } + } + } + return 0; + } + }; + + Collections.sort(packages, comparator); + + StringBuilder builder = new StringBuilder(); + String params = null; + PackageManager.clearUpdateList(); + final int count = (packages.size() / 10) + 1; + mCount = 0; + for (int i = 0, sizei = count; i < sizei; i++) { + builder.delete(0, builder.length()); + for (int j = i * 10, sizej = (i + 1) * 10 > packages.size() ? packages + .size() : (i + 1) * 10; j < sizej; j++) { + builder.append(packages.get(j) + "-"); + } + params = builder.substring(0, builder.length() - 1); + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + + "v1d45/support/package/update?package=" + + params, Constants.UPDATE_CD), + new Response.Listener() { + + @Override + public void onResponse(JSONArray response) { + + Utils.log("getUpdateList=" + + response.toString()); + + if (response.length() != 0) { + Gson gson = new Gson(); + Type listType = new TypeToken>() {}.getType(); + ArrayList games = gson + .fromJson(response.toString(), + listType); + PackageManager.addUpdateList(games); + + list.addAll(games); + + } + mCount++; + if (mCount == count) { + processingData(); + } + } + + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + mCount++; + if (mCount == count) { + processingData(); + } + } + }); + AppController.addToRequestQueue(request, + GameUpdateFragment.class); + } + + } else { + gameupdate_ll_loading.setVisibility(View.GONE); + } + + } + + private int mCount; + + private void processingData() { + sortList(list); + + gameupdate_ll_loading.setVisibility(View.GONE); + + gameupdate_rv_show.getAdapter().notifyDataSetChanged(); + + EventBus.getDefault().post( + new EBDownloadChanged("update", View.VISIBLE, list.size())); + + for (int i = 0, size = list.size(); i < size; i++) { + locationMap.put(list.get(i).getPackageName(), i); + packageNameMap.put(list.get(i).getUrl(), list.get(i) + .getPackageName()); + successMap.put(i, false); + } + + if (!list.isEmpty() + && gameupdate_tv_none.getVisibility() == View.VISIBLE) { + gameupdate_tv_none.setVisibility(View.GONE); + } + } + + private void sortList(List list) { + Comparator comparator = new Comparator() { + @Override + public int compare(GameUpdateEntity lhs, GameUpdateEntity rhs) { + + if (rhs.getName().contains("光环助手")) { + return 1; + } else if (lhs.getName().contains("光环助手")) { + return -1; + } + if (!lhs.isPlugin() && rhs.isPlugin()) { + return 1; + } else if (lhs.isPlugin() && !rhs.isPlugin()) { + return -1; + } else { + return 0; + } + } + }; + Collections.sort(list, comparator); + } + + private class GameUpdateViewHolder extends RecyclerView.ViewHolder + implements OnClickListener { + + private TextView gu_item_top_updateHint, gu_item_top_updateAll; + + private ImageView gu_item_iv_icon; + private TextView gu_item_tv_name, gu_item_tv_current, gu_item_tv_new, + gu_item_btv_update, gu_item_tv_nameHint; + + public GameUpdateViewHolder(View convertView) { + super(convertView); + + int position = (Integer) convertView.getTag(); + if (position == 0) { + gu_item_top_updateHint = (TextView) convertView + .findViewById(R.id.gu_item_top_updateHint); + gu_item_top_updateAll = (TextView) convertView + .findViewById(R.id.gu_item_top_updateAll); + gu_item_top_updateAll.setOnClickListener(this); + } else { + gu_item_iv_icon = (ImageView) convertView + .findViewById(R.id.gu_item_iv_icon); + gu_item_tv_name = (TextView) convertView + .findViewById(R.id.gu_item_tv_name); + gu_item_tv_nameHint = (TextView) convertView + .findViewById(R.id.gu_item_tv_nameHint); + gu_item_tv_current = (TextView) convertView + .findViewById(R.id.gu_item_tv_current); + gu_item_tv_new = (TextView) convertView + .findViewById(R.id.gu_item_tv_new); + gu_item_btv_update = (TextView) convertView + .findViewById(R.id.gu_item_btv_update); + gu_item_btv_update.setOnClickListener(this); + convertView.setOnClickListener(this); + } + } + + @Override + public void onClick(View v) { + if (v == gu_item_btv_update) { + String str = gu_item_btv_update.getText().toString(); + if ("更新".equals(str) || "插件化".equals(str)) { + LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams( + LayoutParams.WRAP_CONTENT, DisplayUtils.dip2px( + getActivity(), 27)); + lparams.leftMargin = DisplayUtils.dip2px(getActivity(), 8); + gu_item_btv_update.setPadding( + DisplayUtils.dip2px(getActivity(), 3), 0, + DisplayUtils.dip2px(getActivity(), 3), 0); + gu_item_btv_update.setLayoutParams(lparams); + if ("插件化".equals(str)) { + gu_item_btv_update.setText("插件化中"); + } else { + gu_item_btv_update.setText("更新中"); + } + gu_item_btv_update.setTextColor(0xFF2EC990); + gu_item_btv_update + .setBackgroundResource(R.drawable.border_update_bg); + + addUpdateTask(getPosition() - 1); + + if (packageName == null) { + gameupdate_rv_show.getAdapter().notifyItemChanged(0); + } + + } else if ("启动".equals(str)) { + GameUpdateEntity game = list.get(getPosition() - 1); + + Map kv = new HashMap(); + kv.put("版本", game.getPlatform()); + TCAgent.onEvent(getActivity(), "游戏启动", game.getName(), kv); + + PackageUtils.launchApplicationByPackageName(getActivity(), + game.getPackageName()); + } + } else if (v == gu_item_top_updateAll) { + String str = gu_item_top_updateAll.getText().toString(); + if ("全部更新".equals(str)) { + // 全部更新 + gu_item_top_updateAll.setText("更新中"); + for (int i = 0; i < list.size(); i++) { + if (entryMap.get(i) == null) { + addUpdateTask(i); + gameupdate_rv_show.getAdapter().notifyItemChanged( + i + 1); + } + } + } + } + } + + } + + private void addUpdateTask(int position) { + GameUpdateEntity game = list.get(position); + + Map kv = new HashMap(); + kv.put("版本", game.getPlatform()); + kv.put("状态", "下载开始"); + TCAgent.onEvent(getActivity(), "游戏更新", game.getName(), kv); + + DownloadEntry entry = new DownloadEntry(); + entry.setUrl(game.getUrl()); + entry.setName(game.getName()); + entry.setPath(FileUtils.getDownloadPath( + getActivity(), + MD5Utils.getContentMD5(game.getName() + "_" + + System.currentTimeMillis()) + + ".apk")); + HashMap meta = new HashMap(); + meta.put("ETag", game.getEtag()); + meta.put("icon", game.getIcon()); + meta.put("platform", game.getPlatform()); + if (game.isPlugin()) { + meta.put("isPlugin", "true"); + } else { + meta.put("isUpdate", "true"); + } + entry.setMeta(meta); + if (entry.getName().contains("光环助手")) { + DownloadManager.getInstance(getActivity()).pauseAll(); + } + DownloadManager.getInstance(getActivity()).add(entry); + entryMap.put(position, entry); + } + + private class GameUpdateListAdapter extends + RecyclerView.Adapter { + + @Override + public int getItemCount() { + + if (list.isEmpty()) { + return 0; + } + return list.size() + 1; + } + + private String getSize(float size) { + String unit = "MB"; + if (size >= 1000) { + size = size / 1024f; + unit = "GB"; + } + String str = size + ""; + int index = str.lastIndexOf("."); + if (index != -1 && str.length() >= index + 3) { + str = str.substring(0, index + 3); + size = Float.valueOf(str); + } + return size + unit; + } + + @Override + public void onBindViewHolder(GameUpdateViewHolder viewHolder, + int position) { + + if (position == 0) { + int count = 0; + float size = 0; + int done = 0; + for (int i = 0; i < list.size(); i++) { + String str = list.get(i).getSize(); + str = str.substring(0, str.lastIndexOf("M")); + size += Float.valueOf(str); + if (entryMap.get(i) != null) { + count++; + } + if (successMap.get(i)) { + done++; + } + } + viewHolder.gu_item_top_updateHint.setText("共" + list.size() + + "个游戏可更新,需" + getSize(size)); + if (done == list.size()) { + viewHolder.gu_item_top_updateAll.setText("更新完成"); + } else { + if (count == list.size()) { + viewHolder.gu_item_top_updateAll.setText("更新中"); + } else { + viewHolder.gu_item_top_updateAll.setText("全部更新"); + } + } + } else { + GameUpdateEntity game = list.get(position - 1); + if (game.getName().contains("光环助手")) { + viewHolder.gu_item_iv_icon + .setImageResource(R.drawable.logo); + viewHolder.gu_item_tv_nameHint.setVisibility(View.GONE); + } else { + ImageUtils.getInstance(getActivity()).display( + game.getIcon(), viewHolder.gu_item_iv_icon); + viewHolder.gu_item_tv_nameHint.setVisibility(View.VISIBLE); + } + String platform = PlatformUtils.getInstance(getActivity()) + .getPlatformName(game.getPlatform()); + if (platform == null || "官方版".equals(platform)) { + viewHolder.gu_item_tv_name.setText(game.getName()); + } else { + viewHolder.gu_item_tv_name.setText(game.getName() + " - " + + platform); + } + String currentVersion = PackageUtils.getVersionByPackage( + getActivity(), game.getPackageName()); + if (TextUtils.isEmpty(currentVersion)) { + viewHolder.gu_item_tv_current.setText("当前:无"); + } else { + viewHolder.gu_item_tv_current.setText("当前:V" + + currentVersion); + } + viewHolder.gu_item_tv_new.setText("新版:V" + game.getVersion() + + " | " + game.getSize()); + if (game.isPlugin()) { + viewHolder.gu_item_tv_nameHint.setText("将版本插件化可实现插件功能"); + } else { + viewHolder.gu_item_tv_nameHint.setText("不更新影响使用"); + } + + if (successMap.get(position - 1)) { + LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams( + DisplayUtils.dip2px(getActivity(), 48), + DisplayUtils.dip2px(getActivity(), 27)); + lparams.leftMargin = DisplayUtils.dip2px(getActivity(), 8); + viewHolder.gu_item_btv_update.setLayoutParams(lparams); + viewHolder.gu_item_btv_update.setText("启动"); + viewHolder.gu_item_btv_update.setTextColor(0xFFFFFFFF); + viewHolder.gu_item_btv_update + .setBackgroundResource(R.drawable.textview_orange_style); + } else { + DownloadEntry entry = entryMap.get(position - 1); + if (entry != null) { + if (game.isPlugin()) { + LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams( + LayoutParams.WRAP_CONTENT, + DisplayUtils.dip2px(getActivity(), 27)); + lparams.leftMargin = DisplayUtils.dip2px( + getActivity(), 8); + viewHolder.gu_item_btv_update.setPadding( + DisplayUtils.dip2px(getActivity(), 3), 0, + DisplayUtils.dip2px(getActivity(), 3), 0); + viewHolder.gu_item_btv_update + .setLayoutParams(lparams); + viewHolder.gu_item_btv_update.setText("插件化中"); + } else { + LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams( + LayoutParams.WRAP_CONTENT, + DisplayUtils.dip2px(getActivity(), 27)); + lparams.leftMargin = DisplayUtils.dip2px( + getActivity(), 8); + viewHolder.gu_item_btv_update.setPadding( + DisplayUtils.dip2px(getActivity(), 3), 0, + DisplayUtils.dip2px(getActivity(), 3), 0); + viewHolder.gu_item_btv_update + .setLayoutParams(lparams); + viewHolder.gu_item_btv_update.setText("更新中"); + } + viewHolder.gu_item_btv_update.setTextColor(0xFF2EC990); + viewHolder.gu_item_btv_update + .setBackgroundResource(R.drawable.border_update_bg); + } else { + if (game.isPlugin()) { + LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams( + LayoutParams.WRAP_CONTENT, + DisplayUtils.dip2px(getActivity(), 27)); + lparams.leftMargin = DisplayUtils.dip2px( + getActivity(), 8); + viewHolder.gu_item_btv_update.setPadding( + DisplayUtils.dip2px(getActivity(), 3), 0, + DisplayUtils.dip2px(getActivity(), 3), 0); + viewHolder.gu_item_btv_update + .setLayoutParams(lparams); + viewHolder.gu_item_btv_update.setText("插件化"); + } else { + LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams( + DisplayUtils.dip2px(getActivity(), 48), + DisplayUtils.dip2px(getActivity(), 27)); + lparams.leftMargin = DisplayUtils.dip2px( + getActivity(), 8); + viewHolder.gu_item_btv_update + .setLayoutParams(lparams); + viewHolder.gu_item_btv_update.setText("更新"); + } + viewHolder.gu_item_btv_update.setTextColor(0xFFFFFFFF); + viewHolder.gu_item_btv_update + .setBackgroundResource(R.drawable.textview_green_style); + } + } + if (packageName != null) { + viewHolder.gu_item_btv_update.performClick(); + packageName = null; + handler.postDelayed(runnable, 800); + } + } + } + + @Override + public GameUpdateViewHolder onCreateViewHolder(ViewGroup viewGroup, + int i) { + + View view; + if (i == 0) { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.gameupdate_item_top, viewGroup, false); + } else { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.gameupdate_item, viewGroup, false); + } + view.setTag(i); + return new GameUpdateViewHolder(view); + } + + @Override + public int getItemViewType(int position) { + + return position; + } + } + + Runnable runnable = new Runnable() { + @Override + public void run() { + gameupdate_rv_show.getAdapter().notifyItemChanged(0); + EventBus.getDefault().post(new EBPerformClick("update")); + } + }; + + public void onEventMainThread(EBDownloadDelete busThree) { + String packageName = packageNameMap.get(busThree.getUrl()); + if (packageName != null) { + Integer location = locationMap.get(packageName); + int position = location.intValue(); + entryMap.remove(position); + if (list.get(position).isPlugin()) { + if (list.size() == 1) { + list.remove(position); + gameupdate_rv_show.getAdapter().notifyDataSetChanged(); + EventBus.getDefault().post( + new EBDownloadChanged("update", View.GONE, list + .size())); + if (gameupdate_tv_none.getVisibility() == View.GONE) { + gameupdate_tv_none.setVisibility(View.VISIBLE); + } + } else { + list.remove(position); + gameupdate_rv_show.getAdapter().notifyItemRemoved( + position + 1); + EventBus.getDefault().post( + new EBDownloadChanged("update", View.VISIBLE, list + .size())); + } + } else { + gameupdate_rv_show.getAdapter().notifyItemChanged(position + 1); + gameupdate_rv_show.getAdapter().notifyItemChanged(0); + } + } + } + + public void onEventMainThread(EBPackage busFour) { + if ("安装".equals(busFour.getType())) { + Integer location = locationMap.get(busFour.getPackageName()); + if (location != null) { + int position = location.intValue(); + successMap.put(position, true); + EventBus.getDefault().post( + new EBDownloadChanged("update", View.VISIBLE, -1)); + gameupdate_rv_show.getAdapter().notifyItemChanged(position + 1); + gameupdate_rv_show.getAdapter().notifyItemChanged(0); + PackageManager.removeUpdateList(busFour.getPackageName()); + } + } else if ("卸载".equals(busFour.getType())) { + Integer location = locationMap.get(busFour.getPackageName()); + if (location != null) { + int position = location.intValue(); + if (!list.isEmpty()) { + if (list.get(position).isPlugin()) { + EventBus.getDefault().post( + new EBDownloadChanged("update", View.VISIBLE, + -1)); + if (list.size() == 1) { + list.remove(position); + gameupdate_rv_show.getAdapter() + .notifyDataSetChanged(); + // PackageManager.removeUpdateList(busFour + // .getPackageName()); + if (gameupdate_tv_none.getVisibility() == View.GONE) { + gameupdate_tv_none.setVisibility(View.VISIBLE); + } + } else { + list.remove(position); + gameupdate_rv_show.getAdapter().notifyItemRemoved( + position + 1); + gameupdate_rv_show.getAdapter() + .notifyItemChanged(0); + // PackageManager.removeUpdateList(busFour + // .getPackageName()); + } + } + } + } + } + } + + public void onEventMainThread(EBMiPush miPush) { + if ("mipush_plugin".equals(miPush.getFrom())) { + getUpdateListFromServer(); + } + } + + Runnable refresh = new Runnable() { + @Override + public void run() { + gameupdate_rv_show.getAdapter().notifyDataSetChanged(); + gameupdate_rv_show.setVisibility(View.VISIBLE); + gameupdate_ll_loading.setVisibility(View.GONE); + } + }; + + @Override + public void onDestroy() { + + super.onDestroy(); + EventBus.getDefault().unregister(this); + view = null; + gameupdate_rv_show = null; + gameupdate_ll_loading = null; + gameupdate_tv_none = null; + list = null; + locationMap = null; + packageNameMap = null; + entryMap = null; + successMap = null; + packageName = null; + handler = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/entity/AdEntity.java b/app/src/main/java/com/gh/gamecenter/entity/AdEntity.java new file mode 100644 index 0000000000..4ea0766d38 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/entity/AdEntity.java @@ -0,0 +1,76 @@ +package com.gh.gamecenter.entity; + +public class AdEntity { + + public static AdEntity str2AdEntity(String data) { + String[] ad = data.split(","); + AdEntity adEntity = new AdEntity(); + adEntity.setPicUrl(ad[0]); + if (ad[1] == null || "null".equals(ad[1])) { + adEntity.setPicPath(null); + } else { + adEntity.setPicPath(ad[1]); + } + adEntity.setGameId(ad[2]); + adEntity.setBgColor(ad[3]); + adEntity.setLastShowTime(Long.valueOf(ad[4])); + return adEntity; + } + + private String picUrl; + + private String picPath; + + private String gameId; + + private String bgColor; + + private long lastShowTime; + + public String getPicUrl() { + return picUrl; + } + + public void setPicUrl(String picUrl) { + this.picUrl = picUrl; + } + + public String getPicPath() { + return picPath; + } + + public void setPicPath(String picPath) { + this.picPath = picPath; + } + + public String getGameId() { + return gameId; + } + + public void setGameId(String gameId) { + this.gameId = gameId; + } + + public String getBgColor() { + return bgColor; + } + + public void setBgColor(String bgColor) { + this.bgColor = bgColor; + } + + public long getLastShowTime() { + return lastShowTime; + } + + public void setLastShowTime(long lastShowTime) { + this.lastShowTime = lastShowTime; + } + + @Override + public String toString() { + return picUrl + "," + picPath + "," + gameId + "," + bgColor + "," + + lastShowTime; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/entity/ApkEntity.java b/app/src/main/java/com/gh/gamecenter/entity/ApkEntity.java new file mode 100644 index 0000000000..22876493bc --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/entity/ApkEntity.java @@ -0,0 +1,84 @@ +package com.gh.gamecenter.entity; + +import android.text.TextUtils; + +import com.google.gson.annotations.SerializedName; + +public class ApkEntity { + + @SerializedName("package") + private String packageName; + + private String size; + + private String url; + + private String platform; + + private String version; + + @SerializedName("gh_version") + private String ghVersion; + + private String etag; + + public String getPackageName() { + return packageName; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + public String getSize() { + return size; + } + + public void setSize(String size) { + this.size = size; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getPlatform() { + if (TextUtils.isEmpty(platform)) { + return "官方版"; + } + return platform; + } + + public void setPlatform(String platform) { + this.platform = platform; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getGhVersion() { + return ghVersion; + } + + public void setGhVersion(String ghVersion) { + this.ghVersion = ghVersion; + } + + public String getEtag() { + return etag; + } + + public void setEtag(String etag) { + this.etag = etag; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/entity/AppEntity.java b/app/src/main/java/com/gh/gamecenter/entity/AppEntity.java new file mode 100644 index 0000000000..8d5f798e07 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/entity/AppEntity.java @@ -0,0 +1,81 @@ +package com.gh.gamecenter.entity; + +public class AppEntity { + + private String version; + private String url; + private String size; + private String content; + private boolean is_force; + private String alet_type; + + public AppEntity() { + + } + + public AppEntity(String version, String url, String size, String content, + boolean is_force, String alet_type) { + this.version = version; + this.url = url; + this.size = size; + this.content = content; + this.is_force = is_force; + this.alet_type = alet_type; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getSize() { + return size; + } + + public void setSize(String size) { + this.size = size; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public boolean isIs_force() { + return is_force; + } + + public void setIs_force(boolean is_force) { + this.is_force = is_force; + } + + public String getAlet_type() { + return alet_type; + } + + public void setAlet_type(String alet_type) { + this.alet_type = alet_type; + } + + @Override + public String toString() { + return "AppEntity [version=" + version + ", url=" + url + ", size=" + + size + ", content=" + content + ", is_force=" + is_force + + ", alet_type=" + alet_type + "]"; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/entity/CommentEntity.java b/app/src/main/java/com/gh/gamecenter/entity/CommentEntity.java new file mode 100644 index 0000000000..4bdc1bde31 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/entity/CommentEntity.java @@ -0,0 +1,64 @@ +package com.gh.gamecenter.entity; + +import com.google.gson.annotations.SerializedName; + +public class CommentEntity { + + @SerializedName("_id") + private String id; + + private String content; + private String news_id; + private UserEntity user; + private FeedbackEntity feedback; + private long time; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getNews_id() { + return news_id; + } + + public void setNews_id(String news_id) { + this.news_id = news_id; + } + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + public UserEntity getUser() { + return user; + } + + public void setUser(UserEntity user) { + this.user = user; + } + + public FeedbackEntity getFeedback() { + return feedback; + } + + public void setFeedback(FeedbackEntity feedback) { + this.feedback = feedback; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/entity/ConcernInstalledEntity.java b/app/src/main/java/com/gh/gamecenter/entity/ConcernInstalledEntity.java new file mode 100644 index 0000000000..8ba9f96161 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/entity/ConcernInstalledEntity.java @@ -0,0 +1,39 @@ +package com.gh.gamecenter.entity; + +public class ConcernInstalledEntity { + + private String gameId; + private boolean isConcern; + private boolean isInstalled; + + public String getGameId() { + return gameId; + } + + public void setGameId(String gameId) { + this.gameId = gameId; + } + + public boolean isConcern() { + return isConcern; + } + + public void setConcern(boolean isConcern) { + this.isConcern = isConcern; + } + + public boolean isInstalled() { + return isInstalled; + } + + public void setInstalled(boolean isInstalled) { + this.isInstalled = isInstalled; + } + + @Override + public String toString() { + return "ConcernInstalledEntity [gameId=" + gameId + ", isConcern=" + + isConcern + ", isInstalled=" + isInstalled + "]"; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/entity/DismissEntity.java b/app/src/main/java/com/gh/gamecenter/entity/DismissEntity.java new file mode 100644 index 0000000000..4022fb4d5e --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/entity/DismissEntity.java @@ -0,0 +1,19 @@ +package com.gh.gamecenter.entity; + +public class DismissEntity { + + private boolean isShow; + + public DismissEntity(boolean isShow) { + this.isShow = isShow; + } + + public boolean isShow() { + return isShow; + } + + public void setShow(boolean isShow) { + this.isShow = isShow; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/entity/FeedbackEntity.java b/app/src/main/java/com/gh/gamecenter/entity/FeedbackEntity.java new file mode 100644 index 0000000000..1ef64133d7 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/entity/FeedbackEntity.java @@ -0,0 +1,39 @@ +package com.gh.gamecenter.entity; + +public class FeedbackEntity { + + private long val; + private long up; + private long down; + + public long getVal() { + return val; + } + + public void setVal(long val) { + this.val = val; + } + + public long getUp() { + return up; + } + + public void setUp(long up) { + this.up = up; + } + + public long getDown() { + return down; + } + + public void setDown(long down) { + this.down = down; + } + + @Override + public String toString() { + return "FeedbackEntity [val=" + val + ", up=" + up + ", down=" + down + + "]"; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/entity/GameDetailsEntity.java b/app/src/main/java/com/gh/gamecenter/entity/GameDetailsEntity.java new file mode 100644 index 0000000000..8d5fee9681 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/entity/GameDetailsEntity.java @@ -0,0 +1,79 @@ +package com.gh.gamecenter.entity; + +import java.util.ArrayList; + +public class GameDetailsEntity { + + private ArrayList serverInfo; + private ArrayList tag; + private String remind; + private ArrayList news; + private ArrayList gallery; + private String des; + private String downloadAddWord; + + public ArrayList getServerInfo() { + return serverInfo; + } + + public void setServerInfo(ArrayList serverInfo) { + this.serverInfo = serverInfo; + } + + public ArrayList getTag() { + return tag; + } + + public void setTag(ArrayList tag) { + this.tag = tag; + } + + public String getRemind() { + return remind; + } + + public void setRemind(String remind) { + this.remind = remind; + } + + public ArrayList getNews() { + return news; + } + + public void setNews(ArrayList news) { + this.news = news; + } + + public ArrayList getGallery() { + return gallery; + } + + public void setGallery(ArrayList gallery) { + this.gallery = gallery; + } + + public String getDes() { + return des; + } + + public void setDes(String des) { + this.des = des; + } + + public String getDownloadAddWord() { + return downloadAddWord; + } + + public void setDownloadAddWord(String downloadAddWord) { + this.downloadAddWord = downloadAddWord; + } + + @Override + public String toString() { + return "GameDetailsEntity [serverInfo=" + serverInfo + ", tag=" + tag + + ", remind=" + remind + ", news=" + news + ", gallery=" + + gallery + ", des=" + des + ", downloadAddWord=" + + downloadAddWord + "]"; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/entity/GameDigestEntity.java b/app/src/main/java/com/gh/gamecenter/entity/GameDigestEntity.java new file mode 100644 index 0000000000..fd607fc408 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/entity/GameDigestEntity.java @@ -0,0 +1,58 @@ +package com.gh.gamecenter.entity; + +import com.google.gson.annotations.SerializedName; + +public class GameDigestEntity { + + @SerializedName("_id") + private String id; + + private String name; + + private String brief; + + private String icon; + + private String platform; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getBrief() { + return brief; + } + + public void setBrief(String brief) { + this.brief = brief; + } + + public String getIcon() { + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + + public String getPlatform() { + return platform; + } + + public void setPlatform(String platform) { + this.platform = platform; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/entity/GameEntity.java b/app/src/main/java/com/gh/gamecenter/entity/GameEntity.java new file mode 100644 index 0000000000..ec7e570a01 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/entity/GameEntity.java @@ -0,0 +1,117 @@ +package com.gh.gamecenter.entity; + +import java.util.ArrayList; + +import android.support.v4.util.ArrayMap; + +import com.gh.download.DownloadEntry; +import com.google.gson.annotations.SerializedName; + +public class GameEntity { + + @SerializedName("_id") + private String id; + + private String icon; + + private String name; + + private String brief; + + private ArrayList tag; + + private ArrayList apk; + + private String slide; + + private TestEntity test; + + @SerializedName("d_button_add_word") + private String downloadAddWord; + + private ArrayMap entryMap; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getIcon() { + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getBrief() { + return brief; + } + + public void setBrief(String brief) { + this.brief = brief; + } + + public ArrayList getTag() { + return tag; + } + + public void setTag(ArrayList tag) { + this.tag = tag; + } + + public ArrayList getApk() { + if (apk == null) { + apk = new ArrayList(); + } + return apk; + } + + public void setApk(ArrayList apk) { + this.apk = apk; + } + + public String getSlide() { + return slide; + } + + public void setSlide(String slide) { + this.slide = slide; + } + + public TestEntity getTest() { + return test; + } + + public void setTest(TestEntity test) { + this.test = test; + } + + public ArrayMap getEntryMap() { + return entryMap; + } + + public void setEntryMap(ArrayMap entryMap) { + this.entryMap = entryMap; + } + + public String getDownloadAddWord() { + return downloadAddWord; + } + + public void setDownloadAddWord(String downloadAddWord) { + this.downloadAddWord = downloadAddWord; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/entity/GameUpdateEntity.java b/app/src/main/java/com/gh/gamecenter/entity/GameUpdateEntity.java new file mode 100644 index 0000000000..84a2057c0c --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/entity/GameUpdateEntity.java @@ -0,0 +1,159 @@ +package com.gh.gamecenter.entity; + +import com.google.gson.annotations.SerializedName; + +public class GameUpdateEntity { + + @SerializedName("game_id") + private String id; + + private String name; + + private String icon; + + @SerializedName("package") + private String packageName; + + private String size; + + private String version; + + @SerializedName("gh_version") + private String ghVersion; + + private String url; + + private String platform; + + private boolean isPlugin; + + private ApkEntity apk; + + private String etag; + + public GameUpdateEntity() { + + } + + public GameUpdateEntity(String id, String name, String icon, + String packageName, String size, String version, String ghVersion, + String url, String platform, boolean isPlugin) { + this.id = id; + this.name = name; + this.icon = icon; + this.packageName = packageName; + this.size = size; + this.version = version; + this.ghVersion = ghVersion; + this.url = url; + this.platform = platform; + this.isPlugin = isPlugin; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getIcon() { + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + + public String getPackageName() { + return packageName; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + public String getSize() { + return size; + } + + public void setSize(String size) { + this.size = size; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getGhVersion() { + return ghVersion; + } + + public void setGhVersion(String ghVersion) { + this.ghVersion = ghVersion; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getPlatform() { + return platform; + } + + public void setPlatform(String platform) { + this.platform = platform; + } + + public boolean isPlugin() { + return isPlugin; + } + + public void setPlugin(boolean isPlugin) { + this.isPlugin = isPlugin; + } + + public String getEtag() { + return etag; + } + + public void setEtag(String etag) { + this.etag = etag; + } + + public ApkEntity getApk() { + if (apk == null) { + apk = new ApkEntity(); + apk.setGhVersion(ghVersion); + apk.setVersion(version); + apk.setPackageName(packageName); + apk.setPlatform(platform); + apk.setSize(size); + apk.setUrl(url); + apk.setEtag(etag); + } + return apk; + } + + public void setApk(ApkEntity apk) { + this.apk = apk; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/entity/MyGameInfo.java b/app/src/main/java/com/gh/gamecenter/entity/MyGameInfo.java new file mode 100644 index 0000000000..2cb3ccb191 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/entity/MyGameInfo.java @@ -0,0 +1,71 @@ +package com.gh.gamecenter.entity; + +import java.util.ArrayList; + +public class MyGameInfo { + + private String game_id; + private String package_name; + private long traffic; + private boolean isSignature; + private long installedTime; + + private ArrayList packageList; + + public String getGame_id() { + return game_id; + } + + public void setGame_id(String game_id) { + this.game_id = game_id; + } + + public String getPackage_name() { + return package_name; + } + + public void setPackage_name(String package_name) { + this.package_name = package_name; + } + + public long getTraffic() { + return traffic; + } + + public void setTraffic(long traffic) { + this.traffic = traffic; + } + + public boolean isSignature() { + return isSignature; + } + + public void setSignature(boolean isSignature) { + this.isSignature = isSignature; + } + + public long getInstalledTime() { + return installedTime; + } + + public void setInstalledTime(long installedTime) { + this.installedTime = installedTime; + } + + public ArrayList getPackageList() { + return packageList; + } + + public void setPackageList(ArrayList packageList) { + this.packageList = packageList; + } + + @Override + public String toString() { + return "MyGameInfo [game_id=" + game_id + ", package_name=" + + package_name + ", traffic=" + traffic + ", isSignature=" + + isSignature + ", installedTime=" + installedTime + + ", packageList=" + packageList + "]"; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/entity/NewsDetailsEntity.java b/app/src/main/java/com/gh/gamecenter/entity/NewsDetailsEntity.java new file mode 100644 index 0000000000..c9b9619498 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/entity/NewsDetailsEntity.java @@ -0,0 +1,121 @@ +package com.gh.gamecenter.entity; + +import java.io.Serializable; +import java.util.List; + +import com.google.gson.annotations.SerializedName; + +public class NewsDetailsEntity implements Serializable { + + private static final long serialVersionUID = 2608000952273704433L; + + @SerializedName("_id") + private String id; + private String title; + private String time; + private String author; + private String content; + private String type; + + @SerializedName("game_id") + private String game; + + //相关推荐 + private List more; + + //用户对新闻的反馈 + private String action; + + //新闻反馈 + private long up; + private long down; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getTime() { + return time; + } + + public void setTime(String time) { + this.time = time; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getGame() { + return game; + } + + public void setGame(String game) { + this.game = game; + } + + public List getMore() { + return more; + } + + public void setMore(List more) { + this.more = more; + } + + public String getAction() { + return action; + } + + public void setAction(String action) { + this.action = action; + } + + public long getUp() { + return up; + } + + public void setUp(long up) { + this.up = up; + } + + public long getDown() { + return down; + } + + public void setDown(long down) { + this.down = down; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/entity/NewsEntity.java b/app/src/main/java/com/gh/gamecenter/entity/NewsEntity.java new file mode 100644 index 0000000000..afabaa8f9b --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/entity/NewsEntity.java @@ -0,0 +1,67 @@ +package com.gh.gamecenter.entity; + +import com.google.gson.annotations.SerializedName; + +public class NewsEntity { + + @SerializedName("_id") + private String id; + + private String type; + private String title; + + @SerializedName("time") + private String publishOn; + + private String thumb; + + private String intro; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getPublishOn() { + return publishOn; + } + + public void setPublishOn(String publishOn) { + this.publishOn = publishOn; + } + + public String getThumb() { + return thumb; + } + + public void setThumb(String thumb) { + this.thumb = thumb; + } + + public String getIntro() { + return intro; + } + + public void setIntro(String intro) { + this.intro = intro; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/entity/ServerEntity.java b/app/src/main/java/com/gh/gamecenter/entity/ServerEntity.java new file mode 100644 index 0000000000..29d1d64f43 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/entity/ServerEntity.java @@ -0,0 +1,33 @@ +package com.gh.gamecenter.entity; + +public class ServerEntity { + + private String server; + private Long time; + private String tag; + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + public String getServer() { + return server; + } + + public void setServer(String server) { + this.server = server; + } + + public Long getTime() { + return time; + } + + public void setTime(Long time) { + this.time = time; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/entity/TagEntity.java b/app/src/main/java/com/gh/gamecenter/entity/TagEntity.java new file mode 100644 index 0000000000..83765d0d97 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/entity/TagEntity.java @@ -0,0 +1,40 @@ +package com.gh.gamecenter.entity; + + +public class TagEntity { + + private String name; + private String icon; + private String des; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getIcon() { + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + + public String getDes() { + return des; + } + + public void setDes(String des) { + this.des = des; + } + + @Override + public String toString() { + return "TagEntity [name=" + name + ", icon=" + icon + ", des=" + des + + "]"; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/entity/TestEntity.java b/app/src/main/java/com/gh/gamecenter/entity/TestEntity.java new file mode 100644 index 0000000000..3fa08ad450 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/entity/TestEntity.java @@ -0,0 +1,32 @@ +package com.gh.gamecenter.entity; + +public class TestEntity { + + private String type; + private long start; + private long end; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public long getStart() { + return start; + } + + public void setStart(long start) { + this.start = start; + } + + public long getEnd() { + return end; + } + + public void setEnd(long end) { + this.end = end; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/entity/UserEntity.java b/app/src/main/java/com/gh/gamecenter/entity/UserEntity.java new file mode 100644 index 0000000000..a39644356e --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/entity/UserEntity.java @@ -0,0 +1,67 @@ +package com.gh.gamecenter.entity; + +public class UserEntity { + + private String account; + private String name; + private String icon; + private String sign; + private String mobileNumber; + private boolean isActivation; + + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getIcon() { + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getMobileNumber() { + return mobileNumber; + } + + public void setMobileNumber(String mobileNumber) { + this.mobileNumber = mobileNumber; + } + + public boolean isActivation() { + return isActivation; + } + + public void setActivation(boolean isActivation) { + this.isActivation = isActivation; + } + + @Override + public String toString() { + return "UserEntity [account=" + account + ", name=" + name + ", icon=" + + icon + ", sign=" + sign + ", mobileNumber=" + mobileNumber + + ", isActivation=" + isActivation + "]"; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/eventbus/EBConcernChanged.java b/app/src/main/java/com/gh/gamecenter/eventbus/EBConcernChanged.java new file mode 100644 index 0000000000..3439af4151 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/eventbus/EBConcernChanged.java @@ -0,0 +1,20 @@ +package com.gh.gamecenter.eventbus; + +public class EBConcernChanged { + + private String id; + + public EBConcernChanged(String id) { + super(); + this.id = id; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/eventbus/EBDownloadChanged.java b/app/src/main/java/com/gh/gamecenter/eventbus/EBDownloadChanged.java new file mode 100644 index 0000000000..3bf348f720 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/eventbus/EBDownloadChanged.java @@ -0,0 +1,40 @@ +package com.gh.gamecenter.eventbus; + +public class EBDownloadChanged { + + private String type; + private int visibility; + private int size; + + public EBDownloadChanged(String type, int visibility, int size) { + super(); + this.type = type; + this.visibility = visibility; + this.size = size; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public int getVisibility() { + return visibility; + } + + public void setVisibility(int visibility) { + this.visibility = visibility; + } + + public int getSize() { + return size; + } + + public void setSize(int size) { + this.size = size; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/eventbus/EBDownloadDelete.java b/app/src/main/java/com/gh/gamecenter/eventbus/EBDownloadDelete.java new file mode 100644 index 0000000000..00257145c2 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/eventbus/EBDownloadDelete.java @@ -0,0 +1,40 @@ +package com.gh.gamecenter.eventbus; + +public class EBDownloadDelete { + + private String name; + private String platform; + private String url; + + public EBDownloadDelete(String name, String platform, String url) { + super(); + this.name = name; + this.platform = platform; + this.url = url; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPlatform() { + return platform; + } + + public void setPlatform(String platform) { + this.platform = platform; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/eventbus/EBLogout.java b/app/src/main/java/com/gh/gamecenter/eventbus/EBLogout.java new file mode 100644 index 0000000000..20d16e711b --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/eventbus/EBLogout.java @@ -0,0 +1,19 @@ +package com.gh.gamecenter.eventbus; + +public class EBLogout { + + private int type; + + public EBLogout(int type) { + this.type = type; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/eventbus/EBMiPush.java b/app/src/main/java/com/gh/gamecenter/eventbus/EBMiPush.java new file mode 100644 index 0000000000..e3aaedd33a --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/eventbus/EBMiPush.java @@ -0,0 +1,29 @@ +package com.gh.gamecenter.eventbus; + +public class EBMiPush { + + private String from; + private Object obj; + + public EBMiPush(String from, Object obj) { + this.from = from; + this.obj = obj; + } + + public String getFrom() { + return from; + } + + public void setFrom(String from) { + this.from = from; + } + + public Object getObj() { + return obj; + } + + public void setObj(Object obj) { + this.obj = obj; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/eventbus/EBMoveTop.java b/app/src/main/java/com/gh/gamecenter/eventbus/EBMoveTop.java new file mode 100644 index 0000000000..515bcfcd77 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/eventbus/EBMoveTop.java @@ -0,0 +1,40 @@ +package com.gh.gamecenter.eventbus; + +public class EBMoveTop { + + private String type; + private int visibility; + private int topMargin; + + public EBMoveTop(String type, int visibility, int topMargin) { + super(); + this.type = type; + this.visibility = visibility; + this.topMargin = topMargin; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public int getVisibility() { + return visibility; + } + + public void setVisibility(int visibility) { + this.visibility = visibility; + } + + public int getTopMargin() { + return topMargin; + } + + public void setTopMargin(int topMargin) { + this.topMargin = topMargin; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/eventbus/EBNetworkState.java b/app/src/main/java/com/gh/gamecenter/eventbus/EBNetworkState.java new file mode 100644 index 0000000000..2679ccc7d5 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/eventbus/EBNetworkState.java @@ -0,0 +1,18 @@ +package com.gh.gamecenter.eventbus; + +public class EBNetworkState { + + private boolean isNetworkConnected; + + public EBNetworkState(boolean isNetworkConnected) { + this.isNetworkConnected = isNetworkConnected; + } + + public boolean isNetworkConnected() { + return isNetworkConnected; + } + + public void setNetworkConnected(boolean isNetworkConnected) { + this.isNetworkConnected = isNetworkConnected; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/eventbus/EBNewsType.java b/app/src/main/java/com/gh/gamecenter/eventbus/EBNewsType.java new file mode 100644 index 0000000000..b79429ba08 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/eventbus/EBNewsType.java @@ -0,0 +1,31 @@ +package com.gh.gamecenter.eventbus; + +import java.util.List; + +public class EBNewsType { + + private String type; + private List list; + + public EBNewsType(String type, List list) { + this.type = type; + this.list = list; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/eventbus/EBPWDismiss.java b/app/src/main/java/com/gh/gamecenter/eventbus/EBPWDismiss.java new file mode 100644 index 0000000000..06b6cbeeed --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/eventbus/EBPWDismiss.java @@ -0,0 +1,5 @@ +package com.gh.gamecenter.eventbus; + +public class EBPWDismiss { + +} diff --git a/app/src/main/java/com/gh/gamecenter/eventbus/EBPackage.java b/app/src/main/java/com/gh/gamecenter/eventbus/EBPackage.java new file mode 100644 index 0000000000..27885d09a9 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/eventbus/EBPackage.java @@ -0,0 +1,30 @@ +package com.gh.gamecenter.eventbus; + +public class EBPackage { + + private String type; + private String packageName; + + public EBPackage(String type, String packageName) { + super(); + this.type = type; + this.packageName = packageName; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getPackageName() { + return packageName; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/eventbus/EBPerformClick.java b/app/src/main/java/com/gh/gamecenter/eventbus/EBPerformClick.java new file mode 100644 index 0000000000..6a117da8b4 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/eventbus/EBPerformClick.java @@ -0,0 +1,20 @@ +package com.gh.gamecenter.eventbus; + +public class EBPerformClick { + + private String from; + + public EBPerformClick(String from) { + super(); + this.from = from; + } + + public String getFrom() { + return from; + } + + public void setFrom(String from) { + this.from = from; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/eventbus/EBPlatformChanged.java b/app/src/main/java/com/gh/gamecenter/eventbus/EBPlatformChanged.java new file mode 100644 index 0000000000..fe9e06a264 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/eventbus/EBPlatformChanged.java @@ -0,0 +1,5 @@ +package com.gh.gamecenter.eventbus; + +public class EBPlatformChanged { + +} diff --git a/app/src/main/java/com/gh/gamecenter/eventbus/EBPutUrl.java b/app/src/main/java/com/gh/gamecenter/eventbus/EBPutUrl.java new file mode 100644 index 0000000000..91a9b1e01c --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/eventbus/EBPutUrl.java @@ -0,0 +1,30 @@ +package com.gh.gamecenter.eventbus; + +public class EBPutUrl { + + private String packageName; + private String url; + + public EBPutUrl(String packageName, String url) { + super(); + this.packageName = packageName; + this.url = url; + } + + public String getPackageName() { + return packageName; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/eventbus/EBRedDot.java b/app/src/main/java/com/gh/gamecenter/eventbus/EBRedDot.java new file mode 100644 index 0000000000..cb8e313351 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/eventbus/EBRedDot.java @@ -0,0 +1,19 @@ +package com.gh.gamecenter.eventbus; + +public class EBRedDot { + + private int type; + + public EBRedDot(int type) { + this.type = type; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/eventbus/EBShowDialog.java b/app/src/main/java/com/gh/gamecenter/eventbus/EBShowDialog.java new file mode 100644 index 0000000000..09ef620fc0 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/eventbus/EBShowDialog.java @@ -0,0 +1,33 @@ +package com.gh.gamecenter.eventbus; + +public class EBShowDialog { + + private String type; + private String path; + + public EBShowDialog(String type) { + this.type = type; + } + + public EBShowDialog(String type, String path) { + this.type = type; + this.path = path; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/eventbus/EBShowDone.java b/app/src/main/java/com/gh/gamecenter/eventbus/EBShowDone.java new file mode 100644 index 0000000000..2af7913294 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/eventbus/EBShowDone.java @@ -0,0 +1,22 @@ +package com.gh.gamecenter.eventbus; + +public class EBShowDone { + + private String from; + private int position; + + public EBShowDone(String from, int position) { + super(); + this.from = from; + this.position = position; + } + + public String getFrom() { + return from; + } + + public int getPosition() { + return position; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/eventbus/EBSkipNewPlugin.java b/app/src/main/java/com/gh/gamecenter/eventbus/EBSkipNewPlugin.java new file mode 100644 index 0000000000..35866c546b --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/eventbus/EBSkipNewPlugin.java @@ -0,0 +1,20 @@ +package com.gh.gamecenter.eventbus; + +public class EBSkipNewPlugin { + + private int type; + + public EBSkipNewPlugin(int type) { + super(); + this.type = type; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/eventbus/EBSlide.java b/app/src/main/java/com/gh/gamecenter/eventbus/EBSlide.java new file mode 100644 index 0000000000..65c8adb616 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/eventbus/EBSlide.java @@ -0,0 +1,39 @@ +package com.gh.gamecenter.eventbus; + +public class EBSlide { + private int distance; + private int position; + private boolean isReset; + + public EBSlide(int distance, int position, boolean isReset) { + super(); + this.distance = distance; + this.position = position; + this.isReset = isReset; + } + + public int getDistance() { + return distance; + } + + public void setDistance(int distance) { + this.distance = distance; + } + + public int getPosition() { + return position; + } + + public void setPosition(int position) { + this.position = position; + } + + public boolean isReset() { + return isReset; + } + + public void setReset(boolean isReset) { + this.isReset = isReset; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/eventbus/EBSms.java b/app/src/main/java/com/gh/gamecenter/eventbus/EBSms.java new file mode 100644 index 0000000000..5e4529415b --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/eventbus/EBSms.java @@ -0,0 +1,29 @@ +package com.gh.gamecenter.eventbus; + +public class EBSms { + + private String type; + private String code; + + public EBSms(String type, String code) { + this.type = type; + this.code = code; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/eventbus/EBTopState.java b/app/src/main/java/com/gh/gamecenter/eventbus/EBTopState.java new file mode 100644 index 0000000000..5c34996f2e --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/eventbus/EBTopState.java @@ -0,0 +1,30 @@ +package com.gh.gamecenter.eventbus; + +public class EBTopState { + + private String type; + private String searchHint; + + public EBTopState(String type, String searchHint) { + super(); + this.type = type; + this.searchHint = searchHint; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getSearchHint() { + return searchHint; + } + + public void setSearchHint(String searchHint) { + this.searchHint = searchHint; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/eventbus/EBUISwitch.java b/app/src/main/java/com/gh/gamecenter/eventbus/EBUISwitch.java new file mode 100644 index 0000000000..da634ef43a --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/eventbus/EBUISwitch.java @@ -0,0 +1,30 @@ +package com.gh.gamecenter.eventbus; + +public class EBUISwitch { + + private String from; + private int position; + + public EBUISwitch(String from, int position) { + super(); + this.position = position; + this.from = from; + } + + public int getPosition() { + return position; + } + + public void setPosition(int position) { + this.position = position; + } + + public String getFrom() { + return from; + } + + public void setFrom(String from) { + this.from = from; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/game/Game1Fragment.java b/app/src/main/java/com/gh/gamecenter/game/Game1Fragment.java new file mode 100644 index 0000000000..278327eed1 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/game/Game1Fragment.java @@ -0,0 +1,326 @@ +package com.gh.gamecenter.game; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; + +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.util.ArrayMap; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener; +import android.support.v7.widget.DefaultItemAnimator; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +import com.gh.base.AppController; +import com.gh.common.constant.Constants; +import com.gh.common.util.DownloadItemUtils; +import com.gh.common.util.Utils; +import com.gh.common.view.VerticalItemDecoration; +import com.gh.download.DataWatcher; +import com.gh.download.DownloadEntry; +import com.gh.download.DownloadManager; +import com.gh.gamecenter.R; +import com.gh.gamecenter.entity.ApkEntity; +import com.gh.gamecenter.entity.DismissEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.eventbus.EBNetworkState; +import com.gh.gamecenter.eventbus.EBPWDismiss; +import com.gh.gamecenter.eventbus.EBPackage; + +import de.greenrobot.event.EventBus; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-8-10 modified 2015-8-12 新游界面 + */ +public class Game1Fragment extends Fragment implements OnRefreshListener { + + private View view; + private RecyclerView recyclerview; + private SwipeRefreshLayout game_swipe_refresh; + private Game1FragmentAdapter adapter; + private LinearLayoutManager layoutManager; + private LinearLayout reuse_no_connection; + + // 黄壮华 添加 记录信息的map 修改2015/8/15 + private ArrayMap locationMap; + private ArrayMap> gameMap; + private ArrayMap> platformMap; + private ArrayMap nameMap; + + private boolean isEverpause = false; + private boolean isDestroy = false; + + private ArrayMap lastTimeMap; + private ArrayMap statusMap; + + private DismissEntity dismissEntity; + + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (!isDestroy) { + if (msg.what == Constants.DOWNLOAD_ROLL) { + String name = (String) msg.obj; + if (platformMap != null) { + LinkedBlockingQueue queue = platformMap + .get(name); + if (queue.size() > 1) { + queue.offer(queue.poll()); + Message msg2 = Message.obtain(); + msg2.obj = name; + msg2.what = Constants.DOWNLOAD_ROLL; + sendMessageDelayed(msg2, 3000); + } + } + } else if (msg.what == Constants.CONTINUE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + DownloadManager.getInstance(getActivity()).resume(url); + } + } else if (msg.what == Constants.PAUSE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + DownloadManager.getInstance(getActivity()).pause(url); + } + } + } + } + }; + + // 黄壮华 添加观察者 修改2015/8/15 + private DataWatcher dataWatcher = new DataWatcher() { + + @Override + public void onDataChanged( + HashMap downloadingEntries) { + if (!game_swipe_refresh.isRefreshing()) { + for (java.util.Map.Entry entry : downloadingEntries + .entrySet()) { + DownloadEntry downloadEntry = entry.getValue(); + String name = downloadEntry.getName(); + Utils.log("name = " + name); + Integer location = locationMap.get(name); + if (location != null) { + int index = location.intValue(); + + GameEntity detailedEntity = adapter.getList() + .get(index); + + if (detailedEntity != null) { + DownloadItemUtils.processDate(detailedEntity, + downloadEntry, platformMap, handler, + adapter, index, statusMap); + } + + } + } + } + } + }; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + view = View.inflate(getActivity(), R.layout.plugin1_fragment, null); + + dismissEntity = new DismissEntity(false); + + lastTimeMap = new ArrayMap(); + statusMap = new ArrayMap(); + locationMap = new ArrayMap(); + gameMap = new ArrayMap>(); + platformMap = new ArrayMap>(); + nameMap = new ArrayMap(); + + game_swipe_refresh = (SwipeRefreshLayout) view + .findViewById(R.id.game_swipe_refresh); + game_swipe_refresh.setColorSchemeResources(R.color.theme_colors); + game_swipe_refresh.setOnRefreshListener(this); + + recyclerview = (RecyclerView) view.findViewById(R.id.game_list); + recyclerview.setHasFixedSize(true); + layoutManager = new LinearLayoutManager(getActivity()); + recyclerview.setLayoutManager(layoutManager); + recyclerview.setItemAnimator(new DefaultItemAnimator()); + + // 黄壮华 添加 初始化游戏状态 修改2015/8/21 + DownloadItemUtils.initializeGameMap(getActivity(), gameMap); + + reuse_no_connection = (LinearLayout) view + .findViewById(R.id.reuse_no_connection); + reuse_no_connection.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + game_swipe_refresh.setRefreshing(true); + recyclerview.setVisibility(View.VISIBLE); + reuse_no_connection.setVisibility(View.GONE); + handler.postDelayed(runnable, 1000); + } + }); + + // 黄壮华 传递引用 修改2015/8/15 + adapter = new Game1FragmentAdapter(Game1Fragment.this, locationMap, + gameMap, platformMap, nameMap, recyclerview, + game_swipe_refresh, reuse_no_connection, handler, lastTimeMap, + statusMap, dismissEntity); + recyclerview.setAdapter(adapter); + recyclerview.setOnScrollListener(new RecyclerView.OnScrollListener() { + + @Override + public void onScrollStateChanged(RecyclerView recyclerView, + int newState) { + super.onScrollStateChanged(recyclerView, newState); + if (!isDestroy + && newState == RecyclerView.SCROLL_STATE_IDLE + && layoutManager.findLastVisibleItemPosition() == adapter + .getList().size()) { + if (!adapter.isRemove() && !adapter.isLoading()) { + adapter.addList(adapter.getList().size()); + } + } + } + }); + recyclerview.addItemDecoration(new VerticalItemDecoration( + getActivity(), 1)); + + EventBus.getDefault().register(this); + + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + if (container != null) { + container.removeView(view); + } + return view; + } + + public void onEventMainThread(EBPWDismiss dismiss) { + if (dismissEntity != null) { + dismissEntity.setShow(false); + } + } + + public void onEventMainThread(EBPackage busFour) { + String name = nameMap.get(busFour.getPackageName()); + if (name != null) { + int location = locationMap.get(name); + if ("安装".equals(busFour.getType())) { + GameEntity detailedEntity = adapter.getList().get(location); + for (ApkEntity apkEntity : detailedEntity.getApk()) { + if (apkEntity.getPackageName().equals( + busFour.getPackageName())) { + detailedEntity.getEntryMap().remove( + apkEntity.getPlatform()); + adapter.notifyItemChanged(location); + break; + } + } + } else if ("卸载".equals(busFour.getType())) { + adapter.notifyItemChanged(location); + } + } + } + + public void onEventMainThread(EBNetworkState busNetworkState) { + if (busNetworkState.isNetworkConnected()) { + if (reuse_no_connection.getVisibility() == View.VISIBLE) { + game_swipe_refresh.setRefreshing(true); + recyclerview.setVisibility(View.VISIBLE); + reuse_no_connection.setVisibility(View.GONE); + handler.postDelayed(runnable, 1000); + } else if (adapter.isNetworkError()) { + adapter.setNetworkError(false); + adapter.notifyItemChanged(adapter.getItemCount() - 1); + adapter.addList(adapter.getList().size()); + } + } + } + + @Override + public void onResume() { + super.onResume(); + if (isEverpause) { + // 黄壮华 添加 初始化游戏状态 修改2015/8/20 + DownloadItemUtils.initializeGameMap(getActivity(), gameMap); + List entities = new ArrayList(); + for (GameEntity entity : adapter.getList()) { + entity.setEntryMap(gameMap.get(entity.getName())); + entities.add(entity); + } + adapter.setList(entities); + } + isEverpause = false; + DownloadManager.getInstance(getActivity()).addObserver(dataWatcher); + } + + @Override + public void onPause() { + super.onPause(); + isEverpause = true; + statusMap.clear(); + DownloadManager.getInstance(getActivity()).removeObserver(dataWatcher); + } + + public boolean isEverpause() { + return isEverpause; + } + + Runnable runnable = new Runnable() { + @Override + public void run() { + if (!isDestroy) { + adapter = new Game1FragmentAdapter(Game1Fragment.this, + locationMap, gameMap, platformMap, nameMap, + recyclerview, game_swipe_refresh, reuse_no_connection, + handler, lastTimeMap, statusMap, dismissEntity); + recyclerview.setAdapter(adapter); + } + } + }; + + @Override + public void onRefresh() { + handler.postDelayed(runnable, 1000); + } + + @Override + public void onDestroy() { + super.onDestroy(); + isDestroy = true; + adapter.setDestroy(true); + AppController.canclePendingRequests(Game1Fragment.class); + EventBus.getDefault().unregister(this); + view = null; + recyclerview = null; + game_swipe_refresh = null; + adapter = null; + layoutManager = null; + reuse_no_connection = null; + locationMap = null; + gameMap = null; + platformMap = null; + nameMap = null; + lastTimeMap = null; + statusMap = null; + dismissEntity = null; + handler = null; + dataWatcher = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/game/Game1FragmentAdapter.java b/app/src/main/java/com/gh/gamecenter/game/Game1FragmentAdapter.java new file mode 100644 index 0000000000..17fa94e431 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/game/Game1FragmentAdapter.java @@ -0,0 +1,364 @@ +package com.gh.gamecenter.game; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.LinkedBlockingQueue; + +import org.json.JSONArray; + +import android.content.Context; +import android.content.Intent; +import android.os.Handler; +import android.support.v4.util.ArrayMap; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.Toast; + +import com.android.volley.NoConnectionError; +import com.android.volley.Response; +import com.android.volley.TimeoutError; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.common.util.DownloadItemUtils; +import com.gh.common.util.GameViewUtils; +import com.gh.common.util.ImageUtils; +import com.gh.common.util.TimestampUtils; +import com.gh.download.DownloadEntry; +import com.gh.gamecenter.GameDetailsActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.adapter.viewholder.FooterViewHolder; +import com.gh.gamecenter.adapter.viewholder.GameViewHolder; +import com.gh.gamecenter.db.info.GameInfo; +import com.gh.gamecenter.entity.ApkEntity; +import com.gh.gamecenter.entity.DismissEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.manager.GameManager; +import com.gh.gamecenter.volley.extended.JsonArrayExtendedRequest; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.tendcloud.tenddata.TCAgent; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-8-10 modified 2015-8-10 新游界面上新游推荐fragment适配器 + */ +public class Game1FragmentAdapter extends + RecyclerView.Adapter { + + private Game1Fragment fragment; + + private Context context; + + private RecyclerView recyclerView; + private SwipeRefreshLayout game_swipe_refresh; + private LinearLayout reuse_no_connection; + + private boolean isRemove; + private boolean isLoading; + private boolean isNetworkError; + private boolean isDestroy; + + private List list; + + // 黄壮华 获取引用 修改2015/8/15 + private ArrayMap locationMap; + private ArrayMap> gameMap; + private ArrayMap> platformMap; + private ArrayMap nameMap; + + private Handler handler; + private ArrayMap lastTimeMap; + private ArrayMap statusMap; + + private DismissEntity dismissEntity; + + // 黄壮华 获取引用 修改2015/8/15 + public Game1FragmentAdapter(Game1Fragment fment, + ArrayMap lMap, + ArrayMap> gMap, + ArrayMap> pMap, + ArrayMap nMap, RecyclerView rView, + SwipeRefreshLayout swipeRefreshLayout, LinearLayout linearLayout, + Handler hdler, ArrayMap ltMap, + ArrayMap sMap, DismissEntity dEntity) { + + // 黄壮华 获取引用 修改2015/8/15 + locationMap = lMap; + gameMap = gMap; + platformMap = pMap; + nameMap = nMap; + recyclerView = rView; + game_swipe_refresh = swipeRefreshLayout; + reuse_no_connection = linearLayout; + + handler = hdler; + lastTimeMap = ltMap; + statusMap = sMap; + + dismissEntity = dEntity; + + list = new ArrayList(); + + isRemove = false; + isLoading = false; + isNetworkError = false; + isDestroy = false; + + fragment = fment; + context = fment.getActivity(); + + addList(0); + } + + public void addList(final int offset) { + isLoading = true; + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + + "v1d45/game/youxituijian", Constants.GAME_CD), + new Response.Listener() { + + @Override + public void onResponse(JSONArray response) { + if (!isDestroy) { + processingData(response, offset); + } + isLoading = false; + } + + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + isLoading = false; + // 无网络连接 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + if (offset == 0) { + if (game_swipe_refresh.isRefreshing()) { + game_swipe_refresh.setRefreshing(false); + } + recyclerView.setVisibility(View.GONE); + reuse_no_connection.setVisibility(View.VISIBLE); + } else { + Toast.makeText(context, "网络错误", + Toast.LENGTH_SHORT).show(); + isNetworkError = true; + notifyItemChanged(getItemCount() - 1); + } + } + } + + }); + AppController.addToRequestQueue(request, Game1Fragment.class); + } + + public void processingData(JSONArray response, int offset) { + Type listType = new TypeToken>() { + }.getType(); + Gson gson = new Gson(); + List gameList = gson + .fromJson(response.toString(), listType); + GameManager manager = new GameManager(context); + if (gameList != null && !gameList.isEmpty()) { + for (GameEntity entity : gameList) { + // 黄壮华 初始化游戏状态 修改2015/8/15 + if (!TextUtils.isEmpty(entity.getName())) { + entity.setEntryMap(gameMap.get(entity.getName())); + list.add(entity); + if (!fragment.isEverpause()) { + notifyItemInserted(list.size() - 1); + } + for (ApkEntity apkEntity : entity.getApk()) { + manager.addOrUpdate(new GameInfo( + apkEntity.getPackageName(), entity.getId(), entity + .getName())); + } + } + } + } + + if (fragment.isEverpause()) { + notifyDataSetChanged(); + } + + if (offset == 0 && game_swipe_refresh.isRefreshing()) { + game_swipe_refresh.setRefreshing(false); + } + + if (gameList.isEmpty() || (offset == 0 && gameList.size() < 20)) { + isRemove = true; + notifyItemRemoved(list.size()); + } + + // 黄壮华 获取游戏位置信息 修改2015/8/15 + for (int i = 0, size = list.size(); i < size; i++) { + GameEntity entity = list.get(i); + locationMap.put(entity.getName(), i); + for (ApkEntity apkEntity : entity.getApk()) { + nameMap.put(apkEntity.getPackageName(), entity.getName()); + } + } + } + + @Override + public int getItemCount() { + if (list.size() == 0) { + return 0; + } + if (isRemove) { + return list.size(); + } + return list.size() + 1; + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, + final int position) { + if (viewHolder instanceof GameViewHolder) { + + final GameEntity detailedEntity = list.get(position); + + GameViewHolder holder = (GameViewHolder) viewHolder; + + holder.gameSeq.setText((position + 1) + ""); + holder.gameSeq.setVisibility(View.GONE); + ImageUtils.getInstance(context).display(detailedEntity.getIcon(), + holder.gameThumb); + if (detailedEntity.getApk() == null + || detailedEntity.getApk().isEmpty()) { + holder.gameNameAndSize.setText(detailedEntity.getName()); + } else { + holder.gameNameAndSize.setText(detailedEntity.getName() + + " | " + detailedEntity.getApk().get(0).getSize()); + } + holder.gameDes.setText(detailedEntity.getBrief()); + + GameViewUtils.setLabelList(context, holder.labelList, + detailedEntity.getTag()); + + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + Map kv = new HashMap(); + kv.put("入口", "新游-新游推荐"); + TCAgent.onEvent(context, "游戏详情", detailedEntity.getName(), + kv); + + Map map = new HashMap(); + map.put("location", "游戏推荐"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", detailedEntity.getName()); + map.put("page", "游戏"); + DataCollectionManager.onEvent(context, "click-item", map); + + AppController.put("GameEntity", detailedEntity); + Intent intent = new Intent(context, + GameDetailsActivity.class); + intent.putExtra("entrance", "游戏-新游推荐"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + }); + + DownloadItemUtils.setOnClickListener(context, holder.downloadBtn, + holder.downloadSpeed, holder.downloadPercentage, + detailedEntity, position, this, handler, lastTimeMap, + statusMap, platformMap, "游戏-游戏推荐", dismissEntity, "游戏:" + + detailedEntity.getName()); + + DownloadItemUtils.updateItem(context, holder.labelList, + holder.gameProgressbar, holder.gameInfo, + holder.downloadSpeed, holder.downloadPercentage, + holder.downloadBtn, detailedEntity, platformMap, statusMap); + } else if (viewHolder instanceof FooterViewHolder) { + FooterViewHolder holder = (FooterViewHolder) viewHolder; + if (isNetworkError) { + holder.footerview_progressbar.setVisibility(View.GONE); + holder.footerview_tv_loading.setText("加载失败,点击重试"); + holder.rootView.setClickable(true); + holder.rootView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + isNetworkError = false; + notifyItemChanged(getItemCount() - 1); + addList(list.size()); + } + }); + } else { + holder.footerview_progressbar.setVisibility(View.VISIBLE); + holder.footerview_tv_loading.setText("加载中..."); + holder.rootView.setClickable(false); + } + } + } + + @Override + public int getItemViewType(int position) { + return position; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { + if (i == list.size()) { + return new FooterViewHolder(LayoutInflater.from( + viewGroup.getContext()).inflate( + R.layout.refresh_footerview, viewGroup, false)); + } else { + return new GameViewHolder(LayoutInflater.from( + viewGroup.getContext()).inflate( + R.layout.home_list_item_gamenormal_type, viewGroup, false)); + } + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + notifyDataSetChanged(); + } + + public boolean isRemove() { + return isRemove; + } + + public void setRemove(boolean isRemove) { + this.isRemove = isRemove; + } + + public boolean isLoading() { + return isLoading; + } + + public void setLoading(boolean isLoading) { + this.isLoading = isLoading; + } + + public void setDestroy(boolean isDestroy) { + this.isDestroy = isDestroy; + } + + public boolean isNetworkError() { + return isNetworkError; + } + + public void setNetworkError(boolean isNetworkError) { + this.isNetworkError = isNetworkError; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/game/Game2Fragment.java b/app/src/main/java/com/gh/gamecenter/game/Game2Fragment.java new file mode 100644 index 0000000000..ceaccd9e83 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/game/Game2Fragment.java @@ -0,0 +1,514 @@ +package com.gh.gamecenter.game; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.concurrent.LinkedBlockingQueue; + +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.util.ArrayMap; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener; +import android.support.v7.widget.DefaultItemAnimator; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.gh.base.AppController; +import com.gh.common.constant.Constants; +import com.gh.common.util.DownloadItemUtils; +import com.gh.common.view.VerticalItemDecoration; +import com.gh.download.DataWatcher; +import com.gh.download.DownloadEntry; +import com.gh.download.DownloadManager; +import com.gh.gamecenter.GameActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.entity.ApkEntity; +import com.gh.gamecenter.entity.DismissEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.eventbus.EBNetworkState; +import com.gh.gamecenter.eventbus.EBPWDismiss; +import com.gh.gamecenter.eventbus.EBPackage; + +import de.greenrobot.event.EventBus; + +public class Game2Fragment extends Fragment implements OnRefreshListener { + + private View view; + private RecyclerView recyclerview; + private SwipeRefreshLayout game_swipe_refresh; + private Game2FragmentAdapter adapter; + private LinearLayoutManager layoutManager; + private TextView game_tv_label; + private RelativeLayout game_rl_label; + private RelativeLayout.LayoutParams rparams; + private LinearLayout reuse_no_connection; + + // 黄壮华 添加 记录信息的map 修改2015/8/18 + private ArrayMap locationMap; + private ArrayMap> gameMap; + private ArrayMap nameMap; + private ArrayMap> platformMap; + + private boolean isEverpause = false; + + private boolean isDestroy = false; + + private ArrayMap lastTimeMap; + private ArrayMap statusMap; + + private DismissEntity dismissEntity; + + // 黄壮华 添加观察者 修改2015/8/15 + private DataWatcher dataWatcher = new DataWatcher() { + @Override + public void onDataChanged( + HashMap downloadingEntries) { + if (!game_swipe_refresh.isRefreshing()) { + for (java.util.Map.Entry entry : downloadingEntries + .entrySet()) { + DownloadEntry downloadEntry = entry.getValue(); + Integer location = locationMap.get(downloadEntry.getName()); + if (location != null) { + int index = location.intValue(); + String platform = downloadEntry.getMeta().get( + "platform"); + + LinkedBlockingQueue queue = platformMap + .get(downloadEntry.getName()); + if (queue == null) { + queue = new LinkedBlockingQueue(); + queue.offer(platform); + platformMap.put(downloadEntry.getName(), queue); + } + + GameEntity detailedEntity = getEntityByLocation(index); + + if (detailedEntity != null) { + if (!"pause".equals(statusMap.get(entry.getValue() + .getUrl()))) { + ArrayMap entryMap = detailedEntity + .getEntryMap(); + if (entryMap == null) { + entryMap = new ArrayMap(); + detailedEntity.setEntryMap(entryMap); + } + entryMap.put(platform, downloadEntry); + adapter.notifyItemChanged(index); + } + } + } + } + } + } + }; + + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (!isDestroy) { + if (msg.what == Constants.CONTINUE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + DownloadManager.getInstance(getActivity()).resume(url); + } + } else if (msg.what == Constants.PAUSE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + DownloadManager.getInstance(getActivity()).pause(url); + } + } + } + } + }; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + view = View.inflate(getActivity(), R.layout.game_new_testgame_fragment, + null); + + dismissEntity = new DismissEntity(false); + + lastTimeMap = new ArrayMap(); + statusMap = new ArrayMap(); + locationMap = new ArrayMap(); + gameMap = new ArrayMap>(); + nameMap = new ArrayMap(); + platformMap = new ArrayMap>(); + + // 黄壮华 添加 初始化游戏状态 修改2015/8/21 + DownloadItemUtils.initializeGameMap(getActivity(), gameMap); + + game_rl_label = (RelativeLayout) view.findViewById(R.id.game_rl_label); + game_tv_label = (TextView) view.findViewById(R.id.game_tv_label); + + rparams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, + LayoutParams.WRAP_CONTENT); + + game_swipe_refresh = (SwipeRefreshLayout) view + .findViewById(R.id.game_swipe_refresh); + game_swipe_refresh.setColorSchemeResources(R.color.theme_colors); + game_swipe_refresh.setOnRefreshListener(this); + + reuse_no_connection = (LinearLayout) view + .findViewById(R.id.reuse_no_connection); + reuse_no_connection.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + game_swipe_refresh.setRefreshing(true); + recyclerview.setVisibility(View.VISIBLE); + reuse_no_connection.setVisibility(View.GONE); + handler.postDelayed(runnable, 1000); + } + }); + + recyclerview = (RecyclerView) view.findViewById(R.id.game_list); + recyclerview.setHasFixedSize(true); + layoutManager = new LinearLayoutManager(getActivity()); + recyclerview.setLayoutManager(layoutManager); + recyclerview.setItemAnimator(new DefaultItemAnimator()); + adapter = new Game2FragmentAdapter(getActivity(), locationMap, gameMap, + nameMap, platformMap, game_tv_label, recyclerview, + game_swipe_refresh, reuse_no_connection, handler, lastTimeMap, + statusMap, dismissEntity); + recyclerview.setAdapter(adapter); + recyclerview.setOnScrollListener(new RecyclerView.OnScrollListener() { + + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + + super.onScrolled(recyclerView, dx, dy); + + int position = layoutManager.findFirstVisibleItemPosition(); + + if (position == 0 + && layoutManager.findViewByPosition(position).getTop() == 0) { + game_rl_label.setVisibility(View.GONE); + } else { + if (!game_swipe_refresh.isRefreshing()) { + game_rl_label.setVisibility(View.VISIBLE); + } + } + + if (adapter.getPosition_tomorrow() != -1 + && position >= adapter.getPosition_tomorrow() + && position <= adapter.getTomorrowList().size() + + adapter.getPosition_tomorrow()) { + game_tv_label.setText("明天"); + game_tv_label.setBackgroundResource(R.drawable.title_red); + } else if (adapter.getPosition_aftertomorrow() != -1 + && position >= adapter.getPosition_aftertomorrow() + && position <= adapter.getTheDayAfterTomorrowList() + .size() + adapter.getPosition_aftertomorrow()) { + game_tv_label.setText("后天"); + game_tv_label + .setBackgroundResource(R.drawable.title_orange); + } else if (adapter.getPosition_before() != -1 + && position >= adapter.getPosition_before() + && position <= adapter.getBeforeList().size() + + adapter.getPosition_before()) { + game_tv_label.setText("昨天/以前"); + game_tv_label.setBackgroundResource(R.drawable.title_gray); + } else if (adapter.getPosition_today() != -1) { + game_tv_label.setText("今天"); + game_tv_label.setBackgroundResource(R.drawable.title_blue); + } + + if (position == adapter.getPosition_tomorrow() - 1 + || position == adapter.getPosition_aftertomorrow() - 1 + || position == adapter.getPosition_before() - 1) { + int buttom = layoutManager.findViewByPosition(position) + .getBottom(); + if (buttom <= game_rl_label.getHeight()) { + rparams.topMargin = buttom - game_rl_label.getHeight(); + game_rl_label.setLayoutParams(rparams); + } else { + rparams.topMargin = 0; + game_rl_label.setLayoutParams(rparams); + } + } else { + rparams.topMargin = 0; + game_rl_label.setLayoutParams(rparams); + } + } + + @Override + public void onScrollStateChanged(RecyclerView recyclerView, + int newState) { + super.onScrollStateChanged(recyclerView, newState); + if (!isDestroy + && newState == RecyclerView.SCROLL_STATE_IDLE + && layoutManager.findLastVisibleItemPosition() == adapter + .getItemCount() - 1) { + if (!adapter.isRemove() && !adapter.isLoading()) { + adapter.addList(adapter.getTotalSize()); + } + } + } + + }); + recyclerview.addItemDecoration(new VerticalItemDecoration( + getActivity(), 1)); + + EventBus.getDefault().register(this); + + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + if (container != null) { + container.removeView(view); + } + return view; + } + + public void onEventMainThread(EBPackage busFour) { + String name = nameMap.get(busFour.getPackageName()); + if (name != null) { + int location = locationMap.get(name); + if ("安装".equals(busFour.getType())) { + GameEntity detailedEntity = getEntityByLocation(location); + if (detailedEntity != null) { + for (ApkEntity apkEntity : detailedEntity.getApk()) { + if (apkEntity.getPackageName().equals( + busFour.getPackageName())) { + detailedEntity.getEntryMap().remove( + apkEntity.getPlatform()); + adapter.notifyItemChanged(location); + break; + } + } + } + } else if ("卸载".equals(busFour.getType())) { + adapter.notifyItemChanged(location); + } + } + } + + private GameEntity getEntityByLocation(int location) { + GameEntity entity = null; + int tdSize = adapter.getTodayList().size(); + int tmSize = adapter.getTomorrowList().size(); + int tdfSize = adapter.getTheDayAfterTomorrowList().size(); + int bfSize = adapter.getBeforeList().size(); + if (tdSize != 0 && tmSize == 0 && tdfSize == 0 && bfSize == 0) { + entity = adapter.getTodayList().get(location - 1); + } else if (tdSize == 0 && tmSize != 0 && tdfSize == 0 && bfSize == 0) { + entity = adapter.getTomorrowList().get(location - 1); + } else if (tdSize == 0 && tmSize == 0 && tdfSize != 0 && bfSize == 0) { + entity = adapter.getTheDayAfterTomorrowList().get(location - 1); + } else if (tdSize == 0 && tmSize == 0 && tdfSize == 0 && bfSize != 0) { + entity = adapter.getBeforeList().get(location - 1); + } else if (tdSize != 0 && tmSize != 0 && tdfSize == 0 && bfSize == 0) { + if (location <= tdSize) { + entity = adapter.getTodayList().get(location - 1); + } else { + entity = adapter.getTomorrowList().get(location - tdSize - 2); + } + } else if (tdSize != 0 && tmSize == 0 && tdfSize != 0 && bfSize == 0) { + if (location <= tdSize) { + entity = adapter.getTodayList().get(location - 1); + } else { + entity = adapter.getTheDayAfterTomorrowList().get( + location - tdSize - 2); + } + } else if (tdSize != 0 && tmSize == 0 && tdfSize == 0 && bfSize != 0) { + if (location <= tdSize) { + entity = adapter.getTodayList().get(location - 1); + } else { + entity = adapter.getBeforeList().get(location - tdSize - 2); + } + } else if (tdSize == 0 && tmSize != 0 && tdfSize != 0 && bfSize == 0) { + if (location <= tmSize) { + entity = adapter.getTomorrowList().get(location - 1); + } else { + entity = adapter.getTheDayAfterTomorrowList().get( + location - tmSize - 2); + } + } else if (tdSize == 0 && tmSize != 0 && tdfSize == 0 && bfSize != 0) { + if (location <= tmSize) { + entity = adapter.getTomorrowList().get(location - 1); + } else { + entity = adapter.getBeforeList().get(location - tmSize - 2); + } + } else if (tdSize == 0 && tmSize == 0 && tdfSize != 0 && bfSize != 0) { + if (location <= tdfSize) { + entity = adapter.getTheDayAfterTomorrowList().get(location - 1); + } else { + entity = adapter.getBeforeList().get(location - tdfSize - 2); + } + } else if (tdSize != 0 && tmSize != 0 && tdfSize != 0 && bfSize == 0) { + if (location <= tdSize) { + entity = adapter.getTodayList().get(location - 1); + } else if (location > tdSize + 1 && location <= tdSize + tmSize + 1) { + entity = adapter.getTomorrowList().get(location - tdSize - 2); + } else { + entity = adapter.getTheDayAfterTomorrowList().get( + location - tdSize - tmSize - 3); + } + } else if (tdSize != 0 && tmSize != 0 && tdfSize == 0 && bfSize != 0) { + if (location <= tdSize) { + entity = adapter.getTodayList().get(location - 1); + } else if (location > tdSize + 1 && location <= tdSize + tmSize + 1) { + entity = adapter.getTomorrowList().get(location - tdSize - 2); + } else { + entity = adapter.getBeforeList().get( + location - tdSize - tmSize - 3); + } + } else if (tdSize != 0 && tmSize == 0 && tdfSize != 0 && bfSize != 0) { + if (location <= tdSize) { + entity = adapter.getTodayList().get(location - 1); + } else if (location > tdSize + 1 + && location <= tdSize + tdfSize + 1) { + entity = adapter.getTomorrowList().get(location - tdSize - 2); + } else { + entity = adapter.getBeforeList().get( + location - tdSize - tdfSize - 3); + } + } else if (tdSize == 0 && tmSize != 0 && tdfSize != 0 && bfSize != 0) { + if (location <= tmSize) { + entity = adapter.getTomorrowList().get(location - 1); + } else if (location > tmSize + 1 + && location <= tmSize + tdfSize + 1) { + entity = adapter.getTheDayAfterTomorrowList().get( + location - tmSize - 2); + } else { + entity = adapter.getBeforeList().get( + location - tmSize - tdfSize - 3); + } + } else if (tdSize != 0 && tmSize != 0 && tdfSize != 0 && bfSize != 0) { + if (location <= tdSize) { + entity = adapter.getTodayList().get(location - 1); + } else if (location > tdSize + 1 && location <= tdSize + tmSize + 1) { + entity = adapter.getTomorrowList().get(location - tdSize - 2); + } else if (location > tdSize + tmSize + 2 + && location <= tdSize + tmSize + tdfSize + 2) { + entity = adapter.getTheDayAfterTomorrowList().get( + location - tdSize - tmSize - 3); + } else { + entity = adapter.getBeforeList().get( + location - tdSize - tmSize - tdfSize - 4); + } + } + return entity; + } + + public void onEventMainThread(EBPWDismiss dismiss) { + if (dismissEntity != null) { + dismissEntity.setShow(false); + } + } + + public void onEventMainThread(EBNetworkState busNetworkState) { + if (busNetworkState.isNetworkConnected()) { + if (reuse_no_connection.getVisibility() == View.VISIBLE) { + game_swipe_refresh.setRefreshing(true); + recyclerview.setVisibility(View.VISIBLE); + reuse_no_connection.setVisibility(View.GONE); + handler.postDelayed(runnable, 1000); + } else if (adapter.isNetworkError()) { + adapter.setNetworkError(false); + adapter.notifyItemChanged(adapter.getItemCount() - 1); + adapter.addList(adapter.getTotalSize()); + } + } + } + + Runnable runnable = new Runnable() { + @Override + public void run() { + if (!isDestroy) { + adapter = new Game2FragmentAdapter(getActivity(), locationMap, + gameMap, nameMap, platformMap, game_tv_label, + recyclerview, game_swipe_refresh, reuse_no_connection, + handler, lastTimeMap, statusMap, dismissEntity); + recyclerview.setAdapter(adapter); + } + } + }; + + @Override + public void onRefresh() { + handler.postDelayed(runnable, 1000); + } + + @Override + public void onResume() { + super.onResume(); + if (isEverpause) { + // 黄壮华 添加 初始化游戏状态 修改2015/8/21 + DownloadItemUtils.initializeGameMap(getActivity(), gameMap); + ArrayList tdList = new ArrayList(); + for (GameEntity entity : adapter.getTodayList()) { + entity.setEntryMap(gameMap.get(entity.getName())); + tdList.add(entity); + } + ArrayList tmList = new ArrayList(); + for (GameEntity entity : adapter.getTomorrowList()) { + entity.setEntryMap(gameMap.get(entity.getName())); + tmList.add(entity); + } + ArrayList dftList = new ArrayList(); + for (GameEntity entity : adapter.getTheDayAfterTomorrowList()) { + entity.setEntryMap(gameMap.get(entity.getName())); + dftList.add(entity); + } + ArrayList bftList = new ArrayList(); + for (GameEntity entity : adapter.getBeforeList()) { + entity.setEntryMap(gameMap.get(entity.getName())); + bftList.add(entity); + } + adapter.setGameList(tdList, tmList, dftList, bftList); + } + isEverpause = false; + DownloadManager.getInstance(getActivity()).addObserver(dataWatcher); + } + + @Override + public void onPause() { + super.onPause(); + isEverpause = true; + statusMap.clear(); + DownloadManager.getInstance(getActivity()).removeObserver(dataWatcher); + } + + @Override + public void onDestroy() { + super.onDestroy(); + isDestroy = true; + adapter.setDestory(true); + AppController.canclePendingRequests(GameActivity.class); + EventBus.getDefault().unregister(this); + view = null; + recyclerview = null; + game_swipe_refresh = null; + adapter = null; + layoutManager = null; + game_tv_label = null; + game_rl_label = null; + rparams = null; + reuse_no_connection = null; + locationMap = null; + gameMap = null; + nameMap = null; + platformMap = null; + lastTimeMap = null; + statusMap = null; + dismissEntity = null; + handler = null; + dataWatcher = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/game/Game2FragmentAdapter.java b/app/src/main/java/com/gh/gamecenter/game/Game2FragmentAdapter.java new file mode 100644 index 0000000000..32fb664f3e --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/game/Game2FragmentAdapter.java @@ -0,0 +1,771 @@ +package com.gh.gamecenter.game; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.LinkedBlockingQueue; + +import org.json.JSONArray; + +import android.content.Context; +import android.content.Intent; +import android.os.Handler; +import android.support.v4.util.ArrayMap; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.RecyclerView.ViewHolder; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.volley.NoConnectionError; +import com.android.volley.Response; +import com.android.volley.TimeoutError; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.common.util.DownloadItemUtils; +import com.gh.common.util.GameViewUtils; +import com.gh.common.util.ImageUtils; +import com.gh.common.util.TimestampUtils; +import com.gh.download.DownloadEntry; +import com.gh.gamecenter.GameDetailsActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.adapter.viewholder.FooterViewHolder; +import com.gh.gamecenter.db.info.GameInfo; +import com.gh.gamecenter.entity.ApkEntity; +import com.gh.gamecenter.entity.DismissEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.manager.GameManager; +import com.gh.gamecenter.volley.extended.JsonArrayExtendedRequest; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.tendcloud.tenddata.TCAgent; + +public class Game2FragmentAdapter extends + RecyclerView.Adapter { + + public class ITEM_TYPE { + public static final int head = 0; + public static final int game_layout = 1; + public static final int refresh_footer = 2; + } + + private int position_today = -1;// 今天的position + private int position_tomorrow = -1;// 明天的position + private int position_aftertomorrow = -1;// 后天的position + private int position_before = -1;// 昨天和以前的position + + private List todayGameList; + private List tomorrowGameList; + private List dayAfterTomorrowGameList; + private List beforeGameList; + + private Context context; + private LayoutInflater layoutInflater; + + private RecyclerView recyclerView; + private SwipeRefreshLayout game_swipe_refresh; + private LinearLayout reuse_no_connection; + private TextView game_tv_label; + + private boolean isRemove; + private boolean isLoading; + private boolean isNetworkError; + private boolean isDestory; + + // 黄壮华 添加 记录信息的map 修改2015/8/18 + private ArrayMap locationMap; + private ArrayMap> gameMap; + private ArrayMap nameMap; + private ArrayMap> platformMap; + + private Handler handler; + private ArrayMap lastTimeMap; + private ArrayMap statusMap; + + private DismissEntity dismissEntity; + + public Game2FragmentAdapter(Context con, ArrayMap lMap, + ArrayMap> gMap, + ArrayMap nMap, + ArrayMap> pMap, + TextView textView, RecyclerView rView, + SwipeRefreshLayout swipeRefreshLayout, LinearLayout linearLayout, + Handler hdler, ArrayMap ltMap, + ArrayMap sMap, DismissEntity dEntity) { + + locationMap = lMap; + gameMap = gMap; + nameMap = nMap; + platformMap = pMap; + game_tv_label = textView; + recyclerView = rView; + game_swipe_refresh = swipeRefreshLayout; + reuse_no_connection = linearLayout; + + handler = hdler; + lastTimeMap = ltMap; + statusMap = sMap; + + dismissEntity = dEntity; + + context = con; + layoutInflater = LayoutInflater.from(context); + + todayGameList = new ArrayList(); + tomorrowGameList = new ArrayList(); + dayAfterTomorrowGameList = new ArrayList(); + beforeGameList = new ArrayList(); + + isRemove = false; + isLoading = false; + isNetworkError = false; + isDestory = false; + + addList(0); + } + + public void addList(final int offset) { + isLoading = true; + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + + "v1d45/game/xincekapai?limit=10&offset=" + offset, + Constants.GAME_CD), new Response.Listener() { + + @Override + public void onResponse(JSONArray response) { + if (!isDestory) { + processingData(response, offset); + } + isLoading = false; + } + + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + isLoading = false; + // 无网络连接和访问超时 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + if (offset == 0) { + if (game_swipe_refresh.isRefreshing()) { + game_swipe_refresh.setRefreshing(false); + } + recyclerView.setVisibility(View.GONE); + reuse_no_connection.setVisibility(View.VISIBLE); + } else { + Toast.makeText(context, "网络错误", + Toast.LENGTH_SHORT).show(); + isNetworkError = true; + notifyItemChanged(getItemCount() - 1); + } + } + } + + }); + AppController.addToRequestQueue(request, Game2Fragment.class); + } + + private void processingData(JSONArray response, int offset) { + Type listType = new TypeToken>() { + }.getType(); + Gson gson = new Gson(); + GameManager manager = new GameManager(context); + // 黄壮华 初始化游戏状态 修改2015/8/15 + List list = gson.fromJson(response.toString(), listType); + if (list != null && !list.isEmpty()) { + for (GameEntity entity : list) { + entity.setEntryMap(gameMap.get(entity.getName())); + if (entity.getApk() != null) { + for (ApkEntity apkEntity : entity.getApk()) { + manager.addOrUpdate(new GameInfo( + apkEntity.getPackageName(), entity.getId(), entity + .getName())); + } + } + } + initDatas(list, offset); + } + + if (offset == 0 && game_swipe_refresh.isRefreshing()) { + game_swipe_refresh.setRefreshing(false); + } + + if (list.isEmpty() || (offset == 0 && list.size() < 10)) { + isRemove = true; + notifyItemRemoved(getItemCount()); + } + + // 黄壮华 获取游戏位置信息 修改2015/8/19 + for (int i = 0, size = list.size(); i < size; i++) { + GameEntity entity = list.get(i); + if (entity.getApk() != null) { + for (ApkEntity apkEntity : entity.getApk()) { + nameMap.put(apkEntity.getPackageName(), entity.getName()); + } + } + } + + } + + public void initDatas(List datas, int offset) { + // 去重 + for (int i = 0; i < datas.size(); i++) { + String id = datas.get(i).getId(); + int index = i; + + if (!todayGameList.isEmpty()) { + for (int j = 0; j < todayGameList.size(); j++) { + if (todayGameList.get(j).getId().equals(id)) { + datas.remove(i); + i--; + break; + } + } + if (i != index) { + continue; + } + } + + if (!tomorrowGameList.isEmpty()) { + for (int j = 0; j < tomorrowGameList.size(); j++) { + if (tomorrowGameList.get(j).getId().equals(id)) { + datas.remove(i); + i--; + break; + } + } + if (i != index) { + continue; + } + } + + if (!dayAfterTomorrowGameList.isEmpty()) { + for (int j = 0; j < dayAfterTomorrowGameList.size(); j++) { + if (dayAfterTomorrowGameList.get(j).getId().equals(id)) { + datas.remove(i); + i--; + break; + } + } + if (i != index) { + continue; + } + } + + if (!beforeGameList.isEmpty()) { + for (int j = 0; j < beforeGameList.size(); j++) { + if (beforeGameList.get(j).getId().equals(id)) { + datas.remove(i); + i--; + break; + } + } + if (i != index) { + continue; + } + } + } + + Calendar date = Calendar.getInstance(); + int today = date.get(Calendar.DAY_OF_MONTH); + for (int i = 0; i < datas.size(); i++) { + date.setTimeInMillis(Long.parseLong(datas.get(i).getTest() + .getStart() + + "000")); + + int currDay = date.get(Calendar.DAY_OF_MONTH); + + if (currDay == today) { + todayGameList.add(datas.get(i)); + } else if (currDay == today + 1) { + tomorrowGameList.add(datas.get(i)); + } else if (currDay == today + 2) { + dayAfterTomorrowGameList.add(datas.get(i)); + } else { + beforeGameList.add(datas.get(i)); + } + } + + // 黄壮华 2015/8/18 初始游戏位置状态 + int interval = 1; + for (int i = 0, size = todayGameList.size(); i < size; i++) { + locationMap.put(todayGameList.get(i).getName(), i + interval); + } + if (todayGameList.size() != 0) { + interval += (todayGameList.size() + 1); + } + for (int i = 0, size = tomorrowGameList.size(); i < size; i++) { + locationMap.put(tomorrowGameList.get(i).getName(), i + interval); + } + if (tomorrowGameList.size() != 0) { + interval += (tomorrowGameList.size() + 1); + } + for (int i = 0, size = dayAfterTomorrowGameList.size(); i < size; i++) { + locationMap.put(dayAfterTomorrowGameList.get(i).getName(), i + + interval); + } + if (dayAfterTomorrowGameList.size() != 0) { + interval += (dayAfterTomorrowGameList.size() + 1); + } + for (int i = 0, size = beforeGameList.size(); i < size; i++) { + locationMap.put(beforeGameList.get(i).getName(), i + interval); + } + + if (!todayGameList.isEmpty()) { + position_today = 0; + } + if (!tomorrowGameList.isEmpty()) { + if (position_today != -1) { + position_tomorrow = todayGameList.size() + 1; + } else { + position_tomorrow = 0; + } + } + if (!dayAfterTomorrowGameList.isEmpty()) { + if (position_today != -1 && position_tomorrow != -1) { + position_aftertomorrow = position_tomorrow + + tomorrowGameList.size() + 1; + } else if (position_today == -1 && position_tomorrow != -1) { + position_aftertomorrow = tomorrowGameList.size() + 1; + } else if (position_today != -1 && position_tomorrow == -1) { + position_aftertomorrow = todayGameList.size() + 1; + } else if (position_today == -1 && position_tomorrow == -1) { + position_aftertomorrow = 0; + } + } + if (!beforeGameList.isEmpty()) { + if (position_today != -1 && position_tomorrow != -1 + && position_aftertomorrow != -1) { + position_before = position_aftertomorrow + + dayAfterTomorrowGameList.size() + 1; + } else if (position_today != -1 && position_tomorrow != -1 + && position_aftertomorrow == -1) { + position_before = position_tomorrow + tomorrowGameList.size() + + 1; + } else if (position_today != -1 && position_tomorrow == -1 + && position_aftertomorrow != -1) { + position_before = position_aftertomorrow + + dayAfterTomorrowGameList.size() + 1; + } else if (position_today == -1 && position_tomorrow != -1 + && position_aftertomorrow != -1) { + position_before = position_aftertomorrow + + dayAfterTomorrowGameList.size() + 1; + } else if (position_today != -1 && position_tomorrow == -1 + && position_aftertomorrow == -1) { + position_before = todayGameList.size() + 1; + } else if (position_today == -1 && position_tomorrow == -1 + && position_aftertomorrow != -1) { + position_before = dayAfterTomorrowGameList.size() + 1; + } else if (position_today == -1 && position_tomorrow != -1 + && position_aftertomorrow == -1) { + position_before = tomorrowGameList.size() + 1; + } else if (position_today == -1 && position_tomorrow == -1 + && position_aftertomorrow == -1) { + position_before = 0; + } + } + if (offset == 0) { + if (position_today != -1) { + game_tv_label.setText("今天"); + game_tv_label.setBackgroundResource(R.drawable.title_blue); + } else if (position_tomorrow != -1) { + game_tv_label.setText("明天"); + game_tv_label.setBackgroundResource(R.drawable.title_red); + } else if (position_aftertomorrow != -1) { + game_tv_label.setText("后天"); + game_tv_label.setBackgroundResource(R.drawable.title_orange); + } else if (position_before != -1) { + game_tv_label.setText("昨天/以前"); + game_tv_label.setBackgroundResource(R.drawable.title_gray); + } + } + notifyDataSetChanged(); + } + + @Override + public int getItemViewType(int position) { + if (position_today != -1) { + if (position == position_today) { + return ITEM_TYPE.head; + } + if (position > position_today && position <= todayGameList.size()) { + return ITEM_TYPE.game_layout; + } + } + + if (position_tomorrow != -1) { + if (position == position_tomorrow) { + return ITEM_TYPE.head; + } + if (position > position_tomorrow + && position <= tomorrowGameList.size() + position_tomorrow) { + return ITEM_TYPE.game_layout; + } + } + + if (position_aftertomorrow != -1) { + if (position == position_aftertomorrow) { + return ITEM_TYPE.head; + } + if (position > position_aftertomorrow + && position <= dayAfterTomorrowGameList.size() + + position_aftertomorrow) { + return ITEM_TYPE.game_layout; + } + } + + if (position_before != -1) { + if (position == position_before) { + return ITEM_TYPE.head; + } + if (position > position_before + && position <= beforeGameList.size() + position_before) { + return ITEM_TYPE.game_layout; + } + } + + return ITEM_TYPE.refresh_footer; + } + + @Override + public int getItemCount() { + if (getTotalSize() == 0) { + return 0; + } + + int head = 0; + if (position_today != -1) { + head++; + } + if (position_tomorrow != -1) { + head++; + } + if (position_aftertomorrow != -1) { + head++; + } + if (position_before != -1) { + head++; + } + if (isRemove) { + return head + todayGameList.size() + tomorrowGameList.size() + + dayAfterTomorrowGameList.size() + beforeGameList.size(); + } else { + return head + todayGameList.size() + tomorrowGameList.size() + + dayAfterTomorrowGameList.size() + beforeGameList.size() + + 1; + } + } + + @Override + public void onBindViewHolder(ViewHolder viewHolder, int position) { + if (viewHolder instanceof HeadViewHolder) { + ((HeadViewHolder) viewHolder).initViewHolder(position); + } else if (viewHolder instanceof GameTestViewHolder) { + ((GameTestViewHolder) viewHolder).initViewHolder(position); + } else if (viewHolder instanceof FooterViewHolder) { + FooterViewHolder holder = (FooterViewHolder) viewHolder; + if (isNetworkError) { + holder.footerview_progressbar.setVisibility(View.GONE); + holder.footerview_tv_loading.setText("加载失败,点击重试"); + holder.rootView.setClickable(true); + holder.rootView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + isNetworkError = false; + notifyItemChanged(getItemCount() - 1); + addList(getTotalSize()); + } + }); + } else { + holder.footerview_progressbar.setVisibility(View.VISIBLE); + holder.footerview_tv_loading.setText("加载中..."); + holder.rootView.setClickable(false); + } + } + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + if (viewType == ITEM_TYPE.head) { + return new HeadViewHolder(layoutInflater.inflate( + R.layout.news_list_item_category, parent, false)); + } else if (viewType == ITEM_TYPE.game_layout) { + return new GameTestViewHolder(layoutInflater.inflate( + R.layout.home_list_item_gametest_type, parent, false)); + } + return new FooterViewHolder(layoutInflater.inflate( + R.layout.refresh_footerview, parent, false)); + } + + public class HeadViewHolder extends ViewHolder { + public TextView headType; + + public HeadViewHolder(View v) { + super(v); + headType = (TextView) v.findViewById(R.id.tv_label); + } + + public void initViewHolder(int position) { + if (position == position_today) { + headType.setText("今天"); + headType.setBackgroundResource(R.drawable.title_blue); + } + + if (position == position_tomorrow) { + headType.setText("明天"); + headType.setBackgroundResource(R.drawable.title_red); + } + + if (position == position_aftertomorrow) { + headType.setText("后天"); + headType.setBackgroundResource(R.drawable.title_orange); + } + + if (position == position_before) { + headType.setText("昨天/以前"); + headType.setBackgroundResource(R.drawable.title_gray); + } + } + } + + public class GameTestViewHolder extends ViewHolder { + public ImageView gameThumb; + public TextView gameNameAndSize; + public TextView downloadBtn; + public TextView gameDes; + public TextView gameTestType; + public TextView gameTestTime; + public LinearLayout labelList; + public ProgressBar game_progressbar; + public LinearLayout game_ll_info; + public TextView download_speed, download_percentage; + + private View rootItem; + + public GameTestViewHolder(View v) { + super(v); + this.rootItem = v; + gameThumb = (ImageView) v.findViewById(R.id.home2_game_thumb); + gameNameAndSize = (TextView) v + .findViewById(R.id.home2_game_nameAndsize); + downloadBtn = (TextView) v.findViewById(R.id.home2_download_btn); + gameDes = (TextView) v.findViewById(R.id.home2_game_des); + gameTestType = (TextView) v.findViewById(R.id.home2_test_type); + gameTestTime = (TextView) v.findViewById(R.id.home2_test_time); + labelList = (LinearLayout) v.findViewById(R.id.home2_label_list); + game_progressbar = (ProgressBar) v + .findViewById(R.id.home2_game_progressbar); + game_ll_info = (LinearLayout) v + .findViewById(R.id.home2_game_ll_info); + download_speed = (TextView) v + .findViewById(R.id.home2_download_speed); + download_percentage = (TextView) v + .findViewById(R.id.home2_download_percentage); + } + + public void initViewHolder(int position) { + + GameEntity entity = null; + + if (position > position_today + && position <= todayGameList.size() + position_today) { + entity = todayGameList.get(position - position_today - 1); + } else if (position > position_tomorrow + && position <= tomorrowGameList.size() + position_tomorrow) { + entity = tomorrowGameList.get(position - position_tomorrow - 1); + } else if (position > position_aftertomorrow + && position <= dayAfterTomorrowGameList.size() + + position_aftertomorrow) { + entity = dayAfterTomorrowGameList.get(position + - position_aftertomorrow - 1); + } else if (position > position_before + && position <= beforeGameList.size() + position_before) { + entity = beforeGameList.get(position - position_before - 1); + } + + if (entity != null) { + if (entity.getApk() == null || entity.getApk().isEmpty()) { + gameNameAndSize.setText(entity.getName()); + } else { + gameNameAndSize.setText(entity.getName() + " | " + + entity.getApk().get(0).getSize()); + } + ImageUtils.getInstance(context).display(entity.getIcon(), + gameThumb); + gameDes.setText(entity.getBrief()); + gameTestType.setText(entity.getTest().getType()); + if (entity.getTest().getStart() == 0) { + gameTestTime.setVisibility(View.GONE); + } else { + gameTestTime.setText(GameViewUtils.getGameTestDate(entity + .getTest().getStart())); + } + + final GameEntity gameEntity = entity; + + rootItem.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + Map kv = new HashMap(); + kv.put("入口", "新游-新测卡牌"); + TCAgent.onEvent(context, "游戏详情", gameEntity.getName(), + kv); + + Map map = new HashMap(); + map.put("location", "新测卡牌"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", gameEntity.getName()); + map.put("page", "游戏"); + DataCollectionManager.onEvent(context, "click-item", map); + + AppController.put("GameEntity", gameEntity); + Intent intent = new Intent(context, + GameDetailsActivity.class); + intent.putExtra("entrance", "游戏-新测卡牌"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + }); + + boolean isGone = false; + + if (entity.getApk() == null || entity.getApk().isEmpty()) { + downloadBtn.setVisibility(View.GONE); + isGone = true; + } else { + if (entity.getTest().getEnd() == 0) { + downloadBtn.setVisibility(View.VISIBLE); + DownloadItemUtils.setOnClickListener(context, + downloadBtn, download_speed, + download_percentage, entity, position, + Game2FragmentAdapter.this, handler, + lastTimeMap, statusMap, platformMap, "游戏-新测卡牌", + dismissEntity, "新游:" + entity.getName()); + } else { + long endTime = Long.valueOf(entity.getTest().getEnd() + + "000"); + long todayTime = new Date().getTime(); + if (todayTime > endTime) { + // 测试时间已过 + downloadBtn.setVisibility(View.GONE); + isGone = true; + } else { + // 测试时间未过 + downloadBtn.setVisibility(View.VISIBLE); + DownloadItemUtils.setOnClickListener(context, + downloadBtn, download_speed, + download_percentage, entity, position, + Game2FragmentAdapter.this, handler, + lastTimeMap, statusMap, platformMap, + "游戏-新测卡牌", dismissEntity, + "新游:" + entity.getName()); + } + } + } + + DownloadItemUtils.updateItem(context, labelList, + game_progressbar, game_ll_info, download_speed, + download_percentage, downloadBtn, entity, platformMap, + statusMap); + + if (Config.isShow && isGone) { + downloadBtn.setVisibility(View.GONE); + } + } + } + } + + public int getTotalSize() { + return todayGameList.size() + tomorrowGameList.size() + + dayAfterTomorrowGameList.size() + beforeGameList.size(); + } + + public List getTodayList() { + return todayGameList; + } + + public List getTomorrowList() { + return tomorrowGameList; + } + + public List getTheDayAfterTomorrowList() { + return dayAfterTomorrowGameList; + } + + public List getBeforeList() { + return beforeGameList; + } + + public int getPosition_today() { + return position_today; + } + + public int getPosition_tomorrow() { + return position_tomorrow; + } + + public int getPosition_aftertomorrow() { + return position_aftertomorrow; + } + + public int getPosition_before() { + return position_before; + } + + public void setGameList(List tdList, List tmList, + List dftList, List bftList) { + todayGameList = tdList; + tomorrowGameList = tmList; + dayAfterTomorrowGameList = dftList; + beforeGameList = bftList; + notifyDataSetChanged(); + } + + public boolean isRemove() { + return isRemove; + } + + public void setRemove(boolean isRemove) { + this.isRemove = isRemove; + } + + public boolean isLoading() { + return isLoading; + } + + public void setLoading(boolean isLoading) { + this.isLoading = isLoading; + } + + public boolean isDestory() { + return isDestory; + } + + public void setDestory(boolean isDestory) { + this.isDestory = isDestory; + } + + public boolean isNetworkError() { + return isNetworkError; + } + + public void setNetworkError(boolean isNetworkError) { + this.isNetworkError = isNetworkError; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/gamedetails/GameDatabaseFragment.java b/app/src/main/java/com/gh/gamecenter/gamedetails/GameDatabaseFragment.java new file mode 100644 index 0000000000..32a1612978 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/gamedetails/GameDatabaseFragment.java @@ -0,0 +1,30 @@ +package com.gh.gamecenter.gamedetails; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +/** + * 数据库 fragment + * @author 黄壮华 + * + */ +public class GameDatabaseFragment extends Fragment { + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + } + + @Override + @Nullable + public View onCreateView(LayoutInflater inflater, + @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + + return super.onCreateView(inflater, container, savedInstanceState); + } +} diff --git a/app/src/main/java/com/gh/gamecenter/gamedetails/GameDetailsFragment.java b/app/src/main/java/com/gh/gamecenter/gamedetails/GameDetailsFragment.java new file mode 100644 index 0000000000..af8b4b3992 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/gamedetails/GameDetailsFragment.java @@ -0,0 +1,1312 @@ +package com.gh.gamecenter.gamedetails; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.util.DisplayMetrics; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.widget.AbsListView.OnScrollListener; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.android.volley.NoConnectionError; +import com.android.volley.Response; +import com.android.volley.TimeoutError; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.common.constant.Config; +import com.gh.common.util.DisplayUtils; +import com.gh.common.util.ImageUtils; +import com.gh.common.util.NewsUtils; +import com.gh.common.util.Utils; +import com.gh.common.view.HorizontalItemDecoration; +import com.gh.common.view.MyRecyclerView; +import com.gh.common.view.MyViewPager; +import com.gh.gamecenter.R; +import com.gh.gamecenter.ViewImageActivity; +import com.gh.gamecenter.entity.GameDetailsEntity; +import com.gh.gamecenter.entity.NewsEntity; +import com.gh.gamecenter.entity.ServerEntity; +import com.gh.gamecenter.entity.TagEntity; +import com.gh.gamecenter.eventbus.EBMoveTop; +import com.gh.gamecenter.eventbus.EBNetworkState; +import com.gh.gamecenter.eventbus.EBNewsType; +import com.gh.gamecenter.eventbus.EBSlide; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.volley.extended.JsonArrayExtendedRequest; +import com.gh.gamecenter.volley.extended.JsonObjectExtendedRequest; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.tendcloud.tenddata.TCAgent; + +import de.greenrobot.event.EventBus; + +/** + * 游戏详情 fragment + * + * @author 黄壮华 + * + */ +public class GameDetailsFragment extends Fragment { + + public static class ITEM_TYPE { + public static final int blank_top1 = 1;// 空白顶部1 + public static final int blank_top2 = 2;// 空白顶部2 + public static final int newservice = 3;// 新服布局类型 + public static final int primatte = 4;// 插件介绍布局类型 + public static final int newsstrategy = 5;// 新闻攻略布局类型 + public static final int news_item = 6;// 新闻攻略item布局类型 + public static final int screenshot = 7;// 游戏截图布局类型 + public static final int intro = 8;// 游戏简介布局类型 + public static final int blank_bottom = 9;// 空白底部 + } + + private int count_newservice = 0; + private int count_plugin = 0; + private int count_news = 0; + private int count_gallery = 0; + private int count_intro = 0; + + private int position_news = -1; + + private View view; + private RecyclerView fm_gamedetails_rv_show; + private LinearLayoutManager linearLayoutManager; + private GameDetailsAdapter adapter; + private LinearLayout fm_gamedetails_ll_loading, reuse_no_connection; + private RelativeLayout.LayoutParams rparams; + + private GameDetailsEntity entity; + + private String id; + private String gameName; + private String entrance; + + private int dis = 0; + private int distance; + private int todayPosition = -1; + private int tomorrowPosition = -1; + private int count; + private int topbarVisibility = View.GONE; + + private boolean isDestroy; + + private Handler handler = new Handler(); + + public GameDetailsFragment() { + + } + + public GameDetailsFragment(String id, String gameName, String entrance) { + this.id = id; + this.entrance = entrance; + this.gameName = gameName; + } + + Runnable runnable = new Runnable() { + public void run() { + entity = new GameDetailsEntity(); + count = 3; + getServerInfo(); + getGameNews(); + getGameDetail(); + } + }; + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + Utils.log(this.getClass().getSimpleName() + " onSaveInstanceState"); + outState.putString("id", id); + outState.putString("entrance", entrance); + outState.putString("gameName", gameName); + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + if (savedInstanceState != null) { + id = savedInstanceState.getString("id"); + gameName = savedInstanceState.getString("gameName"); + entrance = savedInstanceState.getString("entrance"); + } + + isDestroy = false; + + view = View.inflate(getActivity(), R.layout.gamedetails, null); + + distance = DisplayUtils.dip2px(getActivity(), 66); + + fm_gamedetails_ll_loading = (LinearLayout) view + .findViewById(R.id.fm_gamedetails_ll_loading); + + reuse_no_connection = (LinearLayout) view + .findViewById(R.id.reuse_no_connection); + reuse_no_connection.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + fm_gamedetails_rv_show.setVisibility(View.GONE); + fm_gamedetails_ll_loading.setVisibility(View.VISIBLE); + reuse_no_connection.setVisibility(View.GONE); + handler.postDelayed(runnable, 1000); + } + }); + + rparams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, + LayoutParams.WRAP_CONTENT); + + linearLayoutManager = new LinearLayoutManager(getActivity()); + linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + adapter = new GameDetailsAdapter(); + fm_gamedetails_rv_show = (RecyclerView) view + .findViewById(R.id.fm_gamedetails_rv_show); + fm_gamedetails_rv_show.setHasFixedSize(true); + fm_gamedetails_rv_show + .setOnScrollListener(new GameDetailsOnScrollListener()); + fm_gamedetails_rv_show.setLayoutManager(linearLayoutManager); + fm_gamedetails_rv_show.setAdapter(adapter); + + EventBus.getDefault().register(this); + + MyRecyclerView.isCanMove = false; + MyViewPager.isCanMove = false; + + handler.postDelayed(runnable, 200); + } + + @Override + @Nullable + public View onCreateView(LayoutInflater inflater, + @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + + if (container != null) { + container.removeView(view); + } + return view; + } + + private class GameDetailsOnScrollListener extends + RecyclerView.OnScrollListener { + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + + super.onScrolled(recyclerView, dx, dy); + + int visibility; + if (linearLayoutManager.findFirstVisibleItemPosition() >= 1) { + visibility = View.VISIBLE; + } else { + visibility = View.GONE; + } + + dis += dy; + + rparams.topMargin -= dy; + + EventBus.getDefault().post( + new EBMoveTop("top", visibility, rparams.topMargin)); + } + + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + if (newState == OnScrollListener.SCROLL_STATE_IDLE) { + if (dis > distance) { + EventBus.getDefault().post(new EBSlide(distance, 1, false)); + EventBus.getDefault().post(new EBSlide(distance, 2, false)); + } else if (dis < -distance) { + EventBus.getDefault().post(new EBSlide(0, 1, false)); + EventBus.getDefault().post(new EBSlide(0, 2, false)); + } else { + EventBus.getDefault().post(new EBSlide(dis, 1, false)); + EventBus.getDefault().post(new EBSlide(dis, 2, false)); + } + } + } + } + + public void onEventMainThread(EBSlide busOne) { + if (busOne.getPosition() == 0) { + Utils.log("details:" + busOne.getDistance()); + if (busOne.isReset()) { + fm_gamedetails_rv_show.scrollBy(0, distance - dis); + } else { + if (busOne.getDistance() == 0) { + fm_gamedetails_rv_show.scrollToPosition(0); + rparams.topMargin = 0; + dis = 0; + } else { + fm_gamedetails_rv_show.scrollBy(0, busOne.getDistance() + - dis); + } + } + } + } + + public void onEventMainThread(EBNetworkState busNetworkState) { + if (busNetworkState.isNetworkConnected() + && reuse_no_connection.getVisibility() == View.VISIBLE) { + fm_gamedetails_rv_show.setVisibility(View.GONE); + fm_gamedetails_ll_loading.setVisibility(View.VISIBLE); + reuse_no_connection.setVisibility(View.GONE); + handler.postDelayed(runnable, 1000); + } + } + + public void onEventMainThread(EBMoveTop moveTop) { + if (moveTop.getType().equals("top")) { + topbarVisibility = moveTop.getVisibility(); + } + } + + private void getServerInfo() { + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest( + Config.HOST + "v2/game/" + id + "/serverInfo", + new Response.Listener() { + @Override + public void onResponse(JSONArray response) { + if (!isDestroy) { + try { + ArrayList serverInfo = new ArrayList(); + SimpleDateFormat format = new SimpleDateFormat( + "Mdd", Locale.getDefault()); + int today = Integer.valueOf(format + .format(new Date())); + for (int j = 0, sizej = response.length(); j < sizej; j++) { + ServerEntity entity = new ServerEntity(); + JSONObject jsonObject2; + jsonObject2 = response.getJSONObject(j); + String server = jsonObject2 + .getString("server"); + if (server.length() > 4) { + server = server.substring(0, 4); + } + entity.setServer(server); + entity.setTime(Long.valueOf(jsonObject2 + .getString("time") + "000")); + int day = Integer.valueOf(format + .format(new Date(entity.getTime()))); + if (day == today + 1) { + entity.setTag("明天"); + serverInfo.add(entity); + } else if (day == today - 1) { + entity.setTag("昨天"); + serverInfo.add(entity); + } else if (day == today) { + entity.setTag("今天"); + serverInfo.add(entity); + } + } + + Comparator comparator = new Comparator() { + @Override + public int compare(ServerEntity lhs, + ServerEntity rhs) { + + return (int) (lhs.getTime() - rhs + .getTime()); + } + }; + + Collections.sort(serverInfo, comparator); + + for (int j = 0, sizej = serverInfo.size(); j < sizej; j++) { + if ("今天".equals(serverInfo.get(j).getTag()) + && todayPosition == -1) { + todayPosition = j; + } else if ("明天".equals(serverInfo.get(j) + .getTag()) + && tomorrowPosition == -1) { + tomorrowPosition = j; + } + } + entity.setServerInfo(serverInfo); + refresh(); + } catch (JSONException e) { + + e.printStackTrace(); + } + } + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + // 无网络连接和访问超时 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + if (!isDestroy) { + fm_gamedetails_rv_show.setVisibility(View.GONE); + fm_gamedetails_ll_loading + .setVisibility(View.GONE); + reuse_no_connection.setVisibility(View.VISIBLE); + } + } + } + }); + AppController.addToRequestQueue(request, GameDetailsFragment.class); + } + + private void getGameNews() { + String url = Config.HOST + "v1d45/game/" + id + "/news?limit=3"; + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest(url, + new Response.Listener() { + @Override + public void onResponse(JSONArray response) { + Utils.log(response.toString()); + if (!isDestroy) { + Gson gson = new Gson(); + ArrayList news = gson.fromJson( + response.toString(), + new TypeToken>() { + }.getType()); + entity.setNews(news); + refresh(); + } + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + // 无网络连接和访问超时 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + if (!isDestroy) { + fm_gamedetails_rv_show.setVisibility(View.GONE); + fm_gamedetails_ll_loading + .setVisibility(View.GONE); + reuse_no_connection.setVisibility(View.VISIBLE); + } + } + } + }); + AppController.addToRequestQueue(request, GameDetailsFragment.class); + } + + private void getGameDetail() { + String url = Config.HOST + "v1d45/game/" + id + "/detail"; + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest(url, + new Response.Listener() { + @Override + public void onResponse(JSONObject response) { + + Utils.log(response.toString()); + if (!isDestroy) { + Gson gson = new Gson(); + GameDetailsEntity gameDetailsEntity = gson + .fromJson(response.toString(), + GameDetailsEntity.class); + if (entity.getNews() != null) { + gameDetailsEntity.setNews(entity.getNews()); + } + entity = gameDetailsEntity; + HashMap> map = new HashMap>(); + if (!response.isNull("news_type")) { + try { + JSONArray newsType = response + .getJSONArray("news_type"); + for (int i = 0, size = newsType.length(); i < size; i++) { + JSONObject jsonObject = newsType + .getJSONObject(i); + JSONArray subType = jsonObject + .getJSONArray("sub_type"); + ArrayList list = new ArrayList(); + for (int j = 0; j < subType.length(); j++) { + list.add(subType.getString(j)); + } + map.put(jsonObject.getString("type"), + list); + } + } catch (JSONException e) { + + e.printStackTrace(); + } + } + for (String type : map.keySet()) { + EventBus.getDefault().post( + new EBNewsType(type, map.get(type))); + } + refresh(); + } + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + // 无网络连接和访问超时 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + if (!isDestroy) { + fm_gamedetails_rv_show.setVisibility(View.GONE); + fm_gamedetails_ll_loading + .setVisibility(View.GONE); + reuse_no_connection.setVisibility(View.VISIBLE); + } + } + } + }); + AppController.addToRequestQueue(request, GameDetailsFragment.class); + } + + private void refresh() { + if (count == 1) { + fm_gamedetails_rv_show.setVisibility(View.VISIBLE); + fm_gamedetails_ll_loading.setVisibility(View.GONE); + adapter.notifyDataSetChanged(); + } else { + count--; + } + } + + private class GameDetailsViewHolder extends RecyclerView.ViewHolder + implements OnClickListener { + + private RecyclerView fm_gamedetails_newservice_show; + private ImageView fm_gamedetails_newservice_left, + fm_gamedetails_newservice_right; + + private LinearLayout fm_gamedetails_ll_primatte_details, + fm_gamedetails_ll_primatte_warmprompt, + fm_gamedetails_ll_primatte_details_show; + private TextView fm_gamedetails_primatte_content, + fm_gamedetails_tv_primatte_details; + private RecyclerView recyclerView; + private ImageView fm_gamedetails_iv_primatte_details; + + private LinearLayout fm_gamedetails_newsstrategy_more; + + private TextView news_type, news_title; + private View news_item; + + private RecyclerView fm_gamedetails_screenshot_show; + + private TextView fm_gamedetails_intro_content; + + private int type; + + public GameDetailsViewHolder(View convertView) { + super(convertView); + + type = (Integer) convertView.getTag(); + if (type == ITEM_TYPE.newservice) { + fm_gamedetails_newservice_left = (ImageView) convertView + .findViewById(R.id.fm_gamedetails_newservice_left); + fm_gamedetails_newservice_right = (ImageView) convertView + .findViewById(R.id.fm_gamedetails_newservice_right); + fm_gamedetails_newservice_show = (RecyclerView) convertView + .findViewById(R.id.fm_gamedetails_newservice_show); + fm_gamedetails_newservice_show.setHasFixedSize(true); + final LinearLayoutManager newServiceManager = new LinearLayoutManager( + getActivity()); + newServiceManager + .setOrientation(LinearLayoutManager.HORIZONTAL); + fm_gamedetails_newservice_show + .setLayoutManager(newServiceManager); + GameNewServiceAdapter gameNewServiceAdapter = new GameNewServiceAdapter(); + fm_gamedetails_newservice_show + .setAdapter(gameNewServiceAdapter); + fm_gamedetails_newservice_show + .setOnScrollListener(new RecyclerView.OnScrollListener() { + + @Override + public void onScrolled(RecyclerView recyclerView, + int dx, int dy) { + + super.onScrolled(recyclerView, dx, dy); + if (newServiceManager + .findFirstVisibleItemPosition() == 0 + && newServiceManager + .findViewByPosition(0) + .getLeft() == 0) { + fm_gamedetails_newservice_left + .setVisibility(View.INVISIBLE); + fm_gamedetails_newservice_right + .setVisibility(View.VISIBLE); + } else if (newServiceManager + .findLastVisibleItemPosition() == fm_gamedetails_newservice_show + .getAdapter().getItemCount() - 1 + && newServiceManager + .findViewByPosition( + fm_gamedetails_newservice_show + .getAdapter() + .getItemCount() - 1) + .getRight() == fm_gamedetails_newservice_show + .getWidth()) { + fm_gamedetails_newservice_left + .setVisibility(View.VISIBLE); + fm_gamedetails_newservice_right + .setVisibility(View.INVISIBLE); + } else { + fm_gamedetails_newservice_left + .setVisibility(View.VISIBLE); + fm_gamedetails_newservice_right + .setVisibility(View.VISIBLE); + } + } + + }); + } else if (type == ITEM_TYPE.primatte) { + fm_gamedetails_ll_primatte_details = (LinearLayout) convertView + .findViewById(R.id.fm_gamedetails_ll_primatte_details); + fm_gamedetails_ll_primatte_warmprompt = (LinearLayout) convertView + .findViewById(R.id.fm_gamedetails_ll_primatte_warmprompt); + fm_gamedetails_primatte_content = (TextView) convertView + .findViewById(R.id.fm_gamedetails_primatte_content); + fm_gamedetails_tv_primatte_details = (TextView) convertView + .findViewById(R.id.fm_gamedetails_tv_primatte_details); + fm_gamedetails_ll_primatte_details_show = (LinearLayout) convertView + .findViewById(R.id.fm_gamedetails_ll_primatte_details_show); + fm_gamedetails_ll_primatte_details_show + .setOnClickListener(this); + fm_gamedetails_iv_primatte_details = (ImageView) convertView + .findViewById(R.id.fm_gamedetails_iv_primatte_details); + } else if (type == ITEM_TYPE.newsstrategy) { + fm_gamedetails_newsstrategy_more = (LinearLayout) convertView + .findViewById(R.id.fm_gamedetails_newsstrategy_more); + fm_gamedetails_newsstrategy_more.setOnClickListener(this); + } else if (type == ITEM_TYPE.news_item) { + news_item = convertView; + news_type = (TextView) convertView.findViewById(R.id.news_type); + news_title = (TextView) convertView + .findViewById(R.id.news_title); + } else if (type == ITEM_TYPE.screenshot) { + fm_gamedetails_screenshot_show = (RecyclerView) convertView + .findViewById(R.id.fm_gamedetails_screenshot_show); + fm_gamedetails_screenshot_show.setHasFixedSize(true); + final LinearLayoutManager screenshotManager = new LinearLayoutManager( + getActivity()); + screenshotManager + .setOrientation(LinearLayoutManager.HORIZONTAL); + fm_gamedetails_screenshot_show + .setLayoutManager(screenshotManager); + GameScreenshotAdapter gameScreenshotAdapter = new GameScreenshotAdapter(); + fm_gamedetails_screenshot_show + .setAdapter(gameScreenshotAdapter); + fm_gamedetails_screenshot_show + .addItemDecoration(new HorizontalItemDecoration( + getActivity(), 6, entity.getGallery().size())); + fm_gamedetails_screenshot_show + .setOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(RecyclerView recyclerView, + int dx, int dy) { + + super.onScrolled(recyclerView, dx, dy); + if (screenshotManager + .findLastVisibleItemPosition() == recyclerView + .getAdapter().getItemCount() - 1) { + if (screenshotManager.findViewByPosition( + recyclerView.getAdapter() + .getItemCount() - 1) + .getRight() == fm_gamedetails_screenshot_show + .getWidth()) { + MyRecyclerView.isCanMove = true; + } + } + } + }); + } else if (type == ITEM_TYPE.intro) { + fm_gamedetails_intro_content = (TextView) convertView + .findViewById(R.id.fm_gamedetails_intro_content); + } + } + + @Override + public void onClick(View v) { + final int id = v.getId(); + if (id == R.id.fm_gamedetails_newsstrategy_more) { + Map kv = new HashMap(); + kv.put("点击", "新闻攻略-更多>"); + TCAgent.onEvent(getActivity(), "插件数据", gameName, kv); + + Map map = new HashMap(); + map.put("location", "新闻攻略-更多"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", gameName); + map.put("page", "游戏详情"); + DataCollectionManager.onEvent(getActivity(), "click-item", map); + + EventBus.getDefault().post(new EBMoveTop("topbar", 0, 0)); + } else if (id == R.id.fm_gamedetails_ll_primatte_details_show) { + int plugin_position = 0; + if (count_newservice == 0) { + plugin_position = 2; + } else { + plugin_position = 3; + } + if ("收回".equals(fm_gamedetails_tv_primatte_details.getText() + .toString())) { + + Map kv0 = new HashMap(); + kv0.put("点击", "插件介绍-收回^"); + TCAgent.onEvent(getActivity(), "插件数据", gameName, kv0); + + Map map = new HashMap(); + map.put("location", "插件介绍-收回"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", gameName); + map.put("page", "游戏详情"); + DataCollectionManager.onEvent(getActivity(), "click-item", + map); + + fm_gamedetails_tv_primatte_details.setText("详情"); + fm_gamedetails_iv_primatte_details + .setImageResource(R.drawable.down); + adapter.notifyItemChanged(plugin_position); + } else { + Map kv0 = new HashMap(); + kv0.put("点击", "插件介绍-详情v"); + TCAgent.onEvent(getActivity(), "插件数据", gameName, kv0); + + Map map = new HashMap(); + map.put("location", "插件介绍-详情"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", gameName); + map.put("page", "游戏详情"); + DataCollectionManager.onEvent(getActivity(), "click-item", + map); + + fm_gamedetails_tv_primatte_details.setText("收回"); + fm_gamedetails_iv_primatte_details + .setImageResource(R.drawable.up); + adapter.notifyItemChanged(plugin_position); + } + } + } + + } + + private class GameDetailsAdapter extends + RecyclerView.Adapter { + + @Override + public int getItemCount() { + + int count = 3; + if (entity.getServerInfo() != null + && !entity.getServerInfo().isEmpty()) { + count++; + count_newservice = 1; + } + if ((entity.getTag() != null && !entity.getTag().isEmpty()) + || !TextUtils.isEmpty(entity.getRemind())) { + count++; + count_plugin = 1; + } + if (entity.getNews() != null && !entity.getNews().isEmpty()) { + count += (entity.getNews().size() + 1); + count_news = 1; + } + if (entity.getGallery() != null && !entity.getGallery().isEmpty()) { + count++; + count_gallery = 1; + } + if (!TextUtils.isEmpty(entity.getDes())) { + count++; + count_intro = 1; + } + return count; + } + + @Override + public void onBindViewHolder(GameDetailsViewHolder viewHolder, + int position) { + + if (viewHolder.type == ITEM_TYPE.newservice) { + if (!(todayPosition == 0 || todayPosition == 1 || todayPosition == -1)) { + if (entity.getServerInfo().size() >= todayPosition + 2) { + viewHolder.fm_gamedetails_newservice_show + .scrollToPosition(todayPosition - 1); + } else { + viewHolder.fm_gamedetails_newservice_show + .scrollToPosition(todayPosition); + } + } else if (todayPosition == -1 + && !(tomorrowPosition == 0 || tomorrowPosition == 1 || tomorrowPosition == -1)) { + if (entity.getServerInfo().size() >= todayPosition + 2) { + viewHolder.fm_gamedetails_newservice_show + .scrollToPosition(tomorrowPosition - 1); + } else { + viewHolder.fm_gamedetails_newservice_show + .scrollToPosition(tomorrowPosition); + } + } else if (todayPosition == -1 && tomorrowPosition == -1) { + viewHolder.fm_gamedetails_newservice_show + .scrollToPosition(entity.getServerInfo().size() - 1); + viewHolder.fm_gamedetails_newservice_right + .setVisibility(View.GONE); + } else { + viewHolder.fm_gamedetails_newservice_left + .setVisibility(View.GONE); + } + if (todayPosition == entity.getServerInfo().size() - 1 + || todayPosition == entity.getServerInfo().size() - 2) { + viewHolder.fm_gamedetails_newservice_right + .setVisibility(View.GONE); + } + if (todayPosition == -1 + && (tomorrowPosition == entity.getServerInfo().size() - 1 || tomorrowPosition == entity + .getServerInfo().size() - 2)) { + viewHolder.fm_gamedetails_newservice_right + .setVisibility(View.GONE); + } + if (entity.getServerInfo().size() <= 3) { + viewHolder.fm_gamedetails_newservice_left + .setVisibility(View.GONE); + viewHolder.fm_gamedetails_newservice_right + .setVisibility(View.GONE); + } + } else if (viewHolder.type == ITEM_TYPE.primatte) { + if (!TextUtils.isEmpty(entity.getRemind())) { + viewHolder.fm_gamedetails_ll_primatte_warmprompt + .setVisibility(View.VISIBLE); + viewHolder.fm_gamedetails_primatte_content + .setVisibility(View.VISIBLE); + viewHolder.fm_gamedetails_primatte_content.setText(entity + .getRemind()); + } else { + viewHolder.fm_gamedetails_ll_primatte_warmprompt + .setVisibility(View.GONE); + viewHolder.fm_gamedetails_primatte_content + .setVisibility(View.GONE); + } + if (entity.getTag() == null || entity.getTag().isEmpty()) { + viewHolder.fm_gamedetails_tv_primatte_details + .setVisibility(View.GONE); + } else { + viewHolder.fm_gamedetails_ll_primatte_details + .removeAllViews(); + if (entity.getTag().size() >= 3) { + viewHolder.fm_gamedetails_tv_primatte_details + .setVisibility(View.VISIBLE); + if ("详情".equals(viewHolder.fm_gamedetails_tv_primatte_details + .getText().toString())) { + TagEntity tagEntity = entity.getTag().get(0); + View child = View.inflate(getActivity(), + R.layout.primatte_details_item, null); + ImageView primatte_item_icon = (ImageView) child + .findViewById(R.id.primatte_item_icon); + final TextView primatte_item_title = (TextView) child + .findViewById(R.id.primatte_item_title); + TextView primatte_item_intro = (TextView) child + .findViewById(R.id.primatte_item_intro); + ImageUtils.getInstance(getActivity()).display( + tagEntity.getIcon(), primatte_item_icon, + R.drawable.primatte_default_icon); + primatte_item_title.setText(tagEntity.getName()); + primatte_item_intro.setText(tagEntity.getDes()); + viewHolder.fm_gamedetails_ll_primatte_details + .addView(child); + + if (viewHolder.recyclerView == null) { + RecyclerView recyclerView = new RecyclerView( + getActivity()); + recyclerView.setHasFixedSize(true); + recyclerView + .setLayoutManager(new GridLayoutManager( + getActivity(), 3)); + recyclerView.setAdapter(new PrimatteAdapter( + entity.getTag())); + int height = (int) Math.ceil((entity.getTag() + .size() - 1) / 3d) + * DisplayUtils + .dip2px(getActivity(), 21); + LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams( + LayoutParams.MATCH_PARENT, height); + recyclerView.setLayoutParams(lparams); + viewHolder.recyclerView = recyclerView; + } + viewHolder.fm_gamedetails_ll_primatte_details + .addView(viewHolder.recyclerView); + return; + } + } else { + viewHolder.fm_gamedetails_tv_primatte_details + .setVisibility(View.GONE); + } + for (int i = 0, size = entity.getTag().size(); i < size; i++) { + TagEntity tagEntity = entity.getTag().get(i); + View child = View.inflate(getActivity(), + R.layout.primatte_details_item, null); + ImageView primatte_item_icon = (ImageView) child + .findViewById(R.id.primatte_item_icon); + TextView primatte_item_title = (TextView) child + .findViewById(R.id.primatte_item_title); + TextView primatte_item_intro = (TextView) child + .findViewById(R.id.primatte_item_intro); + ImageUtils.getInstance(getActivity()).display( + tagEntity.getIcon(), primatte_item_icon, + R.drawable.primatte_default_icon); + primatte_item_title.setText(tagEntity.getName()); + primatte_item_intro.setText(tagEntity.getDes()); + viewHolder.fm_gamedetails_ll_primatte_details + .addView(child); + } + } + } else if (viewHolder.type == ITEM_TYPE.news_item) { + final NewsEntity newsEntity = entity.getNews().get( + position - position_news - 1); + viewHolder.news_type.setBackgroundResource(NewsUtils + .getDrawableIdByType(newsEntity.getType())); + viewHolder.news_type.setText(newsEntity.getType()); + viewHolder.news_title.setText(newsEntity.getTitle()); + viewHolder.news_item.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Map kv = new HashMap(); + kv.put("点击", "新闻攻略"); + TCAgent.onEvent(getActivity(), "插件数据", gameName, kv); + + NewsUtils.startNewsActivity(getActivity(), newsEntity, + entrance + "-游戏详情-详情"); + } + }); + } else if (viewHolder.type == ITEM_TYPE.intro) { + viewHolder.fm_gamedetails_intro_content + .setText(entity.getDes()); + } + } + + @Override + public GameDetailsViewHolder onCreateViewHolder(ViewGroup viewGroup, + int type) { + + View view; + if (type == ITEM_TYPE.blank_top1) { + RelativeLayout relativeLayout = new RelativeLayout( + getActivity()); + LayoutParams params = new LayoutParams( + LayoutParams.MATCH_PARENT, DisplayUtils.dip2px( + getActivity(), 66)); + relativeLayout.setLayoutParams(params); + view = relativeLayout; + } else if (type == ITEM_TYPE.blank_top2) { + RelativeLayout relativeLayout = new RelativeLayout( + getActivity()); + LayoutParams params = new LayoutParams( + LayoutParams.MATCH_PARENT, DisplayUtils.dip2px( + getActivity(), 29)); + relativeLayout.setLayoutParams(params); + view = relativeLayout; + } else if (type == ITEM_TYPE.newservice) { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.gamedetails_item_newservice, viewGroup, false); + } else if (type == ITEM_TYPE.primatte) { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.gamedetails_item_primatte, viewGroup, false); + if (count_newservice == 1) { + view.findViewById(R.id.fm_gamedetails_primatte_cutting_line) + .setVisibility(View.VISIBLE); + } + } else if (type == ITEM_TYPE.newsstrategy) { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.gamedetails_item_newsstrategy, viewGroup, + false); + } else if (type == ITEM_TYPE.news_item) { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.gamedetails_item_news_item, viewGroup, false); + } else if (type == ITEM_TYPE.screenshot) { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.gamedetails_item_screenshot, viewGroup, false); + if (count_news == 1) { + view.findViewById( + R.id.fm_gamedetails_screenshot_cutting_line) + .setVisibility(View.VISIBLE); + } + } else if (type == ITEM_TYPE.intro) { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.gamedetails_item_intro, viewGroup, false); + } else { + int normalHeight = DisplayUtils.dip2px(getActivity(), 44); + + if (!Config.isShow) { + normalHeight = 0; + } + + if (topbarVisibility != View.VISIBLE) { + int height = 0; + for (int i = 0, size = fm_gamedetails_rv_show + .getChildCount(); i < size; i++) { + height += fm_gamedetails_rv_show.getChildAt(i) + .getMeasuredHeight(); + } + + int totalHeight = fm_gamedetails_rv_show.getHeight() + + DisplayUtils.dip2px(getActivity(), 66); + + int bottom = totalHeight - height; + + if (bottom > normalHeight) { + int count = 0; + if (count_newservice != 0) { + count++; + } + if (count_plugin != 0) { + count++; + } + if (count_news != 0) { + count++; + } + if (count_gallery != 0) { + count++; + } + normalHeight = bottom - count + * DisplayUtils.dip2px(getActivity(), 4); + } + } + + RelativeLayout relativeLayout = new RelativeLayout( + getActivity()); + relativeLayout.setBackgroundColor(0xffffffff); + LayoutParams params = new LayoutParams( + LayoutParams.MATCH_PARENT, normalHeight); + relativeLayout.setLayoutParams(params); + view = relativeLayout; + } + view.setTag(type); + return new GameDetailsViewHolder(view); + } + + @Override + public int getItemViewType(int position) { + + if (position == 0) { + return ITEM_TYPE.blank_top1; + } + if (position == 1) { + return ITEM_TYPE.blank_top2; + } + if (count_newservice != 0 && position == 2) { + return ITEM_TYPE.newservice; + } + if (count_plugin != 0) { + if ((count_newservice != 0 && position == 3) + || (count_newservice == 0 && position == 2)) { + return ITEM_TYPE.primatte; + } + } + if (count_news != 0) { + if ((count_newservice != 0 && count_plugin != 0 && position == 4) + || (count_newservice == 0 && count_plugin != 0 && position == 3) + || (count_newservice != 0 && count_plugin == 0 && position == 3) + || (count_newservice == 0 && count_plugin == 0 && position == 2)) { + position_news = position; + return ITEM_TYPE.newsstrategy; + } + } + if (position_news != -1 && position > position_news + && position <= position_news + entity.getNews().size()) { + return ITEM_TYPE.news_item; + } + if (count_gallery != 0) { + if ((count_newservice != 0 && count_plugin != 0 + && count_news != 0 && position == 5 + entity.getNews() + .size()) + || (count_newservice != 0 && count_plugin != 0 + && count_news == 0 && position == 4) + || (count_newservice != 0 && count_plugin == 0 + && count_news != 0 && position == 4 + entity + .getNews().size()) + || (count_newservice == 0 && count_plugin != 0 + && count_news != 0 && position == 4 + entity + .getNews().size()) + || (count_newservice == 0 && count_plugin == 0 + && count_news != 0 && position == 3 + entity + .getNews().size()) + || (count_newservice != 0 && count_plugin == 0 + && count_news == 0 && position == 3) + || (count_newservice == 0 && count_plugin != 0 + && count_news == 0 && position == 3) + || (count_newservice == 0 && count_plugin == 0 + && count_news == 0 && position == 2)) { + return ITEM_TYPE.screenshot; + } + } + if (count_intro != 0) { + if ((count_newservice != 0 && count_plugin != 0 + && count_news != 0 && count_gallery != 0 && position == 6 + entity + .getNews().size()) + || (count_newservice == 0 && count_plugin != 0 + && count_news != 0 && count_gallery != 0 && position == 5 + entity + .getNews().size()) + || (count_newservice != 0 && count_plugin == 0 + && count_news != 0 && count_gallery != 0 && position == 5 + entity + .getNews().size()) + || (count_newservice != 0 && count_plugin != 0 + && count_news == 0 && count_gallery != 0 && position == 5) + || (count_newservice != 0 && count_plugin != 0 + && count_news != 0 && count_gallery == 0 && position == 5 + entity + .getNews().size()) + || (count_newservice == 0 && count_plugin == 0 + && count_news != 0 && count_gallery != 0 && position == 4 + entity + .getNews().size()) + || (count_newservice == 0 && count_plugin != 0 + && count_news == 0 && count_gallery != 0 && position == 4) + || (count_newservice == 0 && count_plugin != 0 + && count_news != 0 && count_gallery == 0 && position == 4 + entity + .getNews().size()) + || (count_newservice != 0 && count_plugin == 0 + && count_news == 0 && count_gallery != 0 && position == 4) + || (count_newservice != 0 && count_plugin == 0 + && count_news != 0 && count_gallery == 0 && position == 4 + entity + .getNews().size()) + || (count_newservice != 0 && count_plugin != 0 + && count_news == 0 && count_gallery == 0 && position == 4) + || (count_newservice == 0 && count_plugin == 0 + && count_news == 0 && count_gallery != 0 && position == 3) + || (count_newservice == 0 && count_plugin == 0 + && count_news != 0 && count_gallery == 0 && position == 3 + entity + .getNews().size()) + || (count_newservice == 0 && count_plugin != 0 + && count_news == 0 && count_gallery == 0 && position == 3) + || (count_newservice != 0 && count_plugin == 0 + && count_news == 0 && count_gallery == 0 && position == 3) + || (count_newservice == 0 && count_plugin == 0 + && count_news == 0 && count_gallery == 0 && position == 2)) { + return ITEM_TYPE.intro; + } + } + return ITEM_TYPE.blank_bottom; + } + } + + private class PrimatteViewHolder extends RecyclerView.ViewHolder { + + private ImageView primatte_item_icon; + private TextView primatte_item_title; + + public PrimatteViewHolder(View view) { + super(view); + primatte_item_icon = (ImageView) view + .findViewById(R.id.primatte_item_icon); + primatte_item_title = (TextView) view + .findViewById(R.id.primatte_item_title); + view.findViewById(R.id.primatte_item_intro) + .setVisibility(View.GONE); + } + + } + + private class PrimatteAdapter extends + RecyclerView.Adapter { + + private List tags; + + public PrimatteAdapter(List tags) { + this.tags = tags; + } + + @Override + public int getItemCount() { + + return tags.size() - 1; + } + + @Override + public void onBindViewHolder(PrimatteViewHolder viewHodler, int position) { + + TagEntity tagEntity = tags.get(position + 1); + ImageUtils.getInstance(getActivity()).display(tagEntity.getIcon(), + viewHodler.primatte_item_icon, + R.drawable.primatte_default_icon); + viewHodler.primatte_item_title.setText(tagEntity.getName()); + } + + @Override + public PrimatteViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { + + View view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.primatte_details_item, viewGroup, false); + return new PrimatteViewHolder(view); + } + + } + + private class GameNewServiceViewHolder extends RecyclerView.ViewHolder { + + private TextView newservice_item_name, newservice_item_time; + private ImageView newservice_item_point; + + public GameNewServiceViewHolder(View convertView) { + super(convertView); + + newservice_item_name = (TextView) convertView + .findViewById(R.id.newservice_item_name); + newservice_item_time = (TextView) convertView + .findViewById(R.id.newservice_item_time); + newservice_item_point = (ImageView) convertView + .findViewById(R.id.newservice_item_point); + } + + } + + private class GameNewServiceAdapter extends + RecyclerView.Adapter { + + @Override + public int getItemCount() { + + return entity.getServerInfo().size(); + } + + @Override + public void onBindViewHolder(GameNewServiceViewHolder viewHolder, + int position) { + + ServerEntity serverEntity = entity.getServerInfo().get(position); + viewHolder.newservice_item_name.setText(serverEntity.getServer()); + String tag = serverEntity.getTag(); + if ("昨天".equals(tag)) { + viewHolder.newservice_item_name + .setBackgroundResource(R.drawable.newserver_gray); + viewHolder.newservice_item_point + .setBackgroundResource(R.drawable.oval_gray_bg); + } else if ("今天".equals(tag)) { + viewHolder.newservice_item_name + .setBackgroundResource(R.drawable.newserver_red); + viewHolder.newservice_item_point + .setBackgroundResource(R.drawable.oval_scarlet_bg); + } else { + viewHolder.newservice_item_name + .setBackgroundResource(R.drawable.newserver_orange); + viewHolder.newservice_item_point + .setBackgroundResource(R.drawable.oval_orange_bg); + } + SimpleDateFormat format = new SimpleDateFormat(tag + "kk:mm", + Locale.getDefault()); + viewHolder.newservice_item_time.setText(format.format(serverEntity + .getTime())); + } + + @Override + public GameNewServiceViewHolder onCreateViewHolder(ViewGroup viewGroup, + int i) { + + View view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.gamedetails_newservice_item, viewGroup, false); + DisplayMetrics outMetrics = new DisplayMetrics(); + getActivity().getWindowManager().getDefaultDisplay() + .getMetrics(outMetrics); + int width = outMetrics.widthPixels + - DisplayUtils.dip2px(getActivity(), 60); + RelativeLayout.LayoutParams rparams = new RelativeLayout.LayoutParams( + width / 3, DisplayUtils.dip2px(getActivity(), 1)); + rparams.addRule(RelativeLayout.CENTER_IN_PARENT); + view.findViewById(R.id.newservice_item_line).setLayoutParams( + rparams); + return new GameNewServiceViewHolder(view); + } + + } + + private class GameScreenshotViewHolder extends RecyclerView.ViewHolder + implements OnClickListener { + + private ImageView screenshot_item_iv; + + public GameScreenshotViewHolder(View convertView) { + super(convertView); + + screenshot_item_iv = (ImageView) convertView + .findViewById(R.id.screenshot_item_iv); + screenshot_item_iv.setOnClickListener(this); + } + + @Override + public void onClick(View v) { + Map kv = new HashMap(); + kv.put("点击", "游戏截图"); + TCAgent.onEvent(getActivity(), "插件数据", gameName, kv); + + Map map = new HashMap(); + map.put("location", "游戏截图"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", gameName); + map.put("page", "游戏详情"); + DataCollectionManager.onEvent(getActivity(), "click-item", map); + + Intent intent = new Intent(getActivity(), ViewImageActivity.class); + intent.putStringArrayListExtra("urls", entity.getGallery()); + intent.putExtra("current", getPosition()); + startActivity(intent); + } + + } + + private class GameScreenshotAdapter extends + RecyclerView.Adapter { + + @Override + public int getItemCount() { + if (entity.getGallery() == null) { + return 0; + } + return entity.getGallery().size(); + } + + @Override + public void onBindViewHolder(GameScreenshotViewHolder viewHolder, + int position) { + ImageUtils.getInstance(getActivity()).display( + entity.getGallery().get(position), + viewHolder.screenshot_item_iv); + } + + @Override + public GameScreenshotViewHolder onCreateViewHolder(ViewGroup viewGroup, + int i) { + View view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.gamedetails_screenshot_item, viewGroup, false); + return new GameScreenshotViewHolder(view); + } + + @Override + public int getItemViewType(int position) { + return position; + } + } + + @Override + public void onDestroy() { + + super.onDestroy(); + isDestroy = true; + EventBus.getDefault().unregister(this); + AppController.canclePendingRequests(GameDetailsFragment.class); + view = null; + fm_gamedetails_rv_show = null; + linearLayoutManager = null; + adapter = null; + fm_gamedetails_ll_loading = null; + reuse_no_connection = null; + rparams = null; + entity = null; + id = null; + entrance = null; + gameName = null; + handler = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/gamedetails/GameInformationFragment.java b/app/src/main/java/com/gh/gamecenter/gamedetails/GameInformationFragment.java new file mode 100644 index 0000000000..c5d9c43aea --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/gamedetails/GameInformationFragment.java @@ -0,0 +1,938 @@ +package com.gh.gamecenter.gamedetails; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import android.content.Context; +import android.content.SharedPreferences; +import android.net.Uri; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.util.ArrayMap; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.Editable; +import android.text.Html; +import android.text.Spanned; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.AbsListView.OnScrollListener; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.TextView.OnEditorActionListener; +import android.widget.Toast; + +import com.android.volley.NoConnectionError; +import com.android.volley.Response; +import com.android.volley.TimeoutError; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.common.constant.Config; +import com.gh.common.util.DisplayUtils; +import com.gh.common.util.NewsUtils; +import com.gh.common.util.Utils; +import com.gh.gamecenter.R; +import com.gh.gamecenter.entity.NewsEntity; +import com.gh.gamecenter.eventbus.EBMoveTop; +import com.gh.gamecenter.eventbus.EBNetworkState; +import com.gh.gamecenter.eventbus.EBNewsType; +import com.gh.gamecenter.eventbus.EBSlide; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.volley.extended.JsonArrayExtendedRequest; +import com.google.gson.Gson; +import com.tendcloud.tenddata.TCAgent; + +import de.greenrobot.event.EventBus; + +/** + * 游戏资讯 fragment + * + * @author 黄壮华 + * + */ +public class GameInformationFragment extends Fragment { + + private View view; + private RecyclerView fm_gameinformation_rv_show; + private LinearLayoutManager linearLayoutManager; + private GameInformationAdapter adapter; + private LinearLayout fm_gameinformation_ll_loading, reuse_no_connection; + private RelativeLayout.LayoutParams rparams; + + private ArrayMap adapterMap; + private List typeList; + + private String type = "全部"; + private String keyword; + private String id; + private String gameName; + private String entrance; + + private int dis = 0; + private int distance; + private int currentPosition = 0; + private int column; + + private boolean isNull = false; + private boolean isLoading = false; + private boolean isNetworkError = false; + private boolean isDestroy = false; + + public GameInformationFragment() { + + } + + public GameInformationFragment(String id, String gameName, String entrance) { + this.id = id; + this.gameName = gameName; + this.entrance = entrance; + } + + @Override + public void onSaveInstanceState(Bundle outState) { + + super.onSaveInstanceState(outState); + Utils.log(this.getClass().getSimpleName() + " onSaveInstanceState"); + outState.putString("id", id); + outState.putString("gameName", gameName); + outState.putString("entrance", entrance); + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + if (savedInstanceState != null) { + id = savedInstanceState.getString("id"); + gameName = savedInstanceState.getString("gameName"); + entrance = savedInstanceState.getString("entrance"); + } + + view = View.inflate(getActivity(), R.layout.gameinformation, null); + + distance = DisplayUtils.dip2px(getActivity(), 66); + typeList = new ArrayList(); + adapterMap = new ArrayMap(); + + SharedPreferences sp = getActivity().getSharedPreferences( + Config.PREFERENCE, Context.MODE_PRIVATE); + column = sp.getInt("game_detail_news_type_tab_column", 4); + + fm_gameinformation_ll_loading = (LinearLayout) view + .findViewById(R.id.fm_gameinformation_ll_loading); + + reuse_no_connection = (LinearLayout) view + .findViewById(R.id.reuse_no_connection); + reuse_no_connection.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + fm_gameinformation_rv_show.setVisibility(View.GONE); + fm_gameinformation_ll_loading.setVisibility(View.VISIBLE); + reuse_no_connection.setVisibility(View.GONE); + getGameInformation(0, true); + } + }); + + rparams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, + LayoutParams.WRAP_CONTENT); + + linearLayoutManager = new LinearLayoutManager(getActivity()); + linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + fm_gameinformation_rv_show = (RecyclerView) view + .findViewById(R.id.fm_gameinformation_rv_show); + fm_gameinformation_rv_show.setHasFixedSize(true); + fm_gameinformation_rv_show.setLayoutManager(linearLayoutManager); + fm_gameinformation_rv_show + .setOnScrollListener(new GameInformationOnScrollListener()); + + EventBus.getDefault().register(this); + + getGameInformation(0, true); + } + + @Override + @Nullable + public View onCreateView(LayoutInflater inflater, + @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + + if (container != null) { + container.removeView(view); + } + return view; + } + + private class GameInformationOnScrollListener extends + RecyclerView.OnScrollListener { + + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + + super.onScrolled(recyclerView, dx, dy); + int visibility; + if (linearLayoutManager.findFirstVisibleItemPosition() >= 1) { + visibility = View.VISIBLE; + } else { + visibility = View.GONE; + } + + dis += dy; + + rparams.topMargin -= dy; + + EventBus.getDefault().post( + new EBMoveTop("top", visibility, rparams.topMargin)); + } + + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + + super.onScrollStateChanged(recyclerView, newState); + if (newState == OnScrollListener.SCROLL_STATE_IDLE) { + int position = adapter.getNewsList().size() + 4; + if (!Config.isShow) { + position--; + } + if (linearLayoutManager.findLastVisibleItemPosition() == position + && !adapter.isRemove() && !isLoading) { + if (currentPosition == -1) { + searchFormServer(adapter.getNewsList().size()); + } else { + getGameInformation(adapter.getNewsList().size()); + } + } + + if (dis > distance) { + EventBus.getDefault().post(new EBSlide(distance, 0, false)); + EventBus.getDefault().post(new EBSlide(distance, 2, false)); + } else if (dis < -distance) { + EventBus.getDefault().post(new EBSlide(0, 0, false)); + EventBus.getDefault().post(new EBSlide(0, 2, false)); + } else { + EventBus.getDefault().post(new EBSlide(dis, 0, false)); + EventBus.getDefault().post(new EBSlide(dis, 2, false)); + } + } + } + } + + public void onEventMainThread(EBSlide busOne) { + if (busOne.getPosition() == 1) { + if (busOne.isReset()) { + fm_gameinformation_rv_show.scrollBy(0, distance - dis); + } else { + if (busOne.getDistance() == 0) { + fm_gameinformation_rv_show.scrollToPosition(0); + rparams.topMargin = 0; + dis = 0; + } else { + fm_gameinformation_rv_show.scrollBy(0, busOne.getDistance() + - dis); + } + } + } + } + + public void onEventMainThread(EBNetworkState busNetworkState) { + if (busNetworkState.isNetworkConnected()) { + if (reuse_no_connection.getVisibility() == View.VISIBLE) { + fm_gameinformation_rv_show.setVisibility(View.GONE); + fm_gameinformation_ll_loading.setVisibility(View.VISIBLE); + reuse_no_connection.setVisibility(View.GONE); + getGameInformation(0, true); + } else if (isNetworkError) { + isNetworkError = false; + adapter.notifyItemChanged(adapter.getItemCount() - 2); + if (currentPosition == -1) { + searchFormServer(adapter.getNewsList().size()); + } else { + getGameInformation(adapter.getNewsList().size()); + } + } + } + } + + public void onEventMainThread(EBNewsType type) { + if ("资讯".equals(type.getType())) { + typeList = type.getList(); + adapter.notifyItemChanged(2); + } + } + + private void getGameInformation(final int offset) { + getGameInformation(offset, false); + } + + private void getGameInformation(final int offset, final boolean isFirst) { + isLoading = true; + if (offset == 0) { + adapter = adapterMap.get(type); + if (adapter == null) { + adapter = new GameInformationAdapter( + new ArrayList()); + adapterMap.put(type, adapter); + } + fm_gameinformation_rv_show.setAdapter(adapter); + } + + final String url; + + if ("全部".equals(type)) { + url = Config.HOST + "v1d45/game/" + id + "/news?limit=20&offset=" + + offset + "&type_group=" + Uri.encode("资讯"); + } else { + url = Config.HOST + "v1d45/game/" + id + "/news?limit=20&offset=" + + offset + "&type=" + Uri.encode(type); + } + + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest(url, + new Response.Listener() { + + @Override + public void onResponse(JSONArray response) { + if (!isDestroy) { + try { + processingData(response, offset, isFirst); + isLoading = false; + } catch (JSONException e) { + e.printStackTrace(); + } + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + isLoading = false; + // 无网络连接和访问超时 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + if (!isDestroy) { + if (offset == 0 && isFirst) { + fm_gameinformation_rv_show + .setVisibility(View.GONE); + fm_gameinformation_ll_loading + .setVisibility(View.GONE); + reuse_no_connection + .setVisibility(View.VISIBLE); + } else { + Toast.makeText(getActivity(), "网络错误", + Toast.LENGTH_SHORT).show(); + isNetworkError = true; + adapter.notifyItemChanged(adapter + .getItemCount() - 2); + } + } + } + } + }); + if ((adapter.getNewsList().isEmpty() && !adapter.isRemove() && offset == 0) + || (offset != 0)) { + AppController.addToRequestQueue(request, + GameInformationFragment.class); + } + } + + private void processingData(JSONArray response, int offset, boolean isFirst) + throws JSONException { + Gson gson = new Gson(); + int size = response.length(); + if (offset == 0) { + fm_gameinformation_ll_loading.setVisibility(View.GONE); + fm_gameinformation_rv_show.setVisibility(View.VISIBLE); + } + for (int i = 0; i < size; i++) { + JSONObject jsonObject = response.getJSONObject(i); + adapter.getNewsList().add( + gson.fromJson(jsonObject.toString(), NewsEntity.class)); + adapter.notifyItemInserted(adapter.getNewsList().size() + 2); + } + if (size < 20) { + adapter.setRemove(true); + adapter.notifyItemRemoved(adapter.getNewsList().size() + 3); + adapter.notifyItemChanged(adapter.getNewsList().size() + 3); + if (isFirst && size == 0 && !isNull) { + isNull = true; + adapter.notifyItemRemoved(2); + } + } + } + + private class GameInformationViewHolder extends RecyclerView.ViewHolder + implements OnClickListener, TextWatcher, OnEditorActionListener { + + private EditText item_et_search; + private ImageView item_iv_delete; + private TextView item_tv_search; + private RecyclerView item_rv_select; + private LinearLayout item_ll_search_result; + private TextView item_tv_search_result; + private ImageView item_iv_search_result; + + private TextView information_type, information_title; + private View itemView; + + private ProgressBar item_pb_loading; + private TextView item_tv_loading; + + public GameInformationViewHolder(View convertView) { + super(convertView); + + itemView = convertView; + int position = (Integer) convertView.getTag(); + if (!isNull && position == 2) { + item_et_search = (EditText) convertView + .findViewById(R.id.item_et_search); + item_et_search.requestFocus(); + item_et_search.addTextChangedListener(this); + item_et_search.setOnEditorActionListener(this); + item_iv_delete = (ImageView) convertView + .findViewById(R.id.item_iv_delete); + item_iv_delete.setOnClickListener(this); + item_tv_search = (TextView) convertView + .findViewById(R.id.item_tv_search); + item_tv_search.setOnClickListener(this); + item_rv_select = (RecyclerView) convertView + .findViewById(R.id.item_rv_select); + item_rv_select.setLayoutManager(new GridLayoutManager( + getActivity(), column)); + item_rv_select.setAdapter(new SelectViewAdapter()); + item_ll_search_result = (LinearLayout) convertView + .findViewById(R.id.item_ll_search_result); + item_tv_search_result = (TextView) convertView + .findViewById(R.id.item_tv_search_result); + item_iv_search_result = (ImageView) convertView + .findViewById(R.id.item_iv_search_result); + item_iv_search_result.setOnClickListener(this); + } else if (position >= 3 + && position <= adapter.getNewsList().size() + 2) { + information_type = (TextView) convertView + .findViewById(R.id.information_type); + information_title = (TextView) convertView + .findViewById(R.id.information_title); + convertView.setOnClickListener(this); + } else if (!adapter.isRemove() + && position == adapter.getNewsList().size() + 3) { + item_pb_loading = (ProgressBar) convertView + .findViewById(R.id.item_pb_loading); + item_tv_loading = (TextView) convertView + .findViewById(R.id.item_tv_loading); + } + } + + @Override + public void onClick(View v) { + if (v == itemView) { + NewsEntity newsEntity = adapter.getNewsList().get( + getPosition() - 3); + + Map kv = new HashMap(); + kv.put("文章类型", newsEntity.getType()); + kv.put("入口", "游戏详情-资讯"); + TCAgent.onEvent(getActivity(), "文章阅读-资讯", + newsEntity.getTitle(), kv); + + Map map = new HashMap(); + map.put("location", "资讯"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", gameName); + map.put("news", newsEntity.getTitle()); + map.put("page", "游戏详情"); + DataCollectionManager.onEvent(getActivity(), "click-item", map); + + NewsUtils.startNewsActivity(getActivity(), newsEntity, entrance + + "-游戏详情-资讯"); + } + if (v == item_tv_search) { + InputMethodManager imm = (InputMethodManager) getActivity() + .getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); + if (!TextUtils.isEmpty(item_et_search.getText().toString())) { + keyword = item_et_search.getText().toString(); + + Map kv = new HashMap(); + kv.put("关键字", keyword); + TCAgent.onEvent(getActivity(), "搜索-游戏详情", gameName, kv); + + Map map = new HashMap(); + map.put("key", keyword); + map.put("from", "游戏详情-资讯"); + map.put("createdOn", System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent(getActivity(), "search", map); + + searchFormServer(0); + } else { + Toast.makeText(getActivity(), "请输入搜索关键字", + Toast.LENGTH_SHORT).show(); + } + } + if (v == item_iv_delete) { + item_et_search.setText(""); + } + if (v == item_iv_search_result) { + InputMethodManager imm = (InputMethodManager) getActivity() + .getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); + EventBus.getDefault().post(new EBSlide(0, 0, false)); + EventBus.getDefault().post(new EBSlide(0, 2, false)); + fm_gameinformation_rv_show.scrollBy(0, rparams.topMargin); + currentPosition = 0; + adapter = adapterMap.get("全部"); + fm_gameinformation_rv_show.setAdapter(adapter); + } + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, + int count) { + if (s.length() > 0) { + item_iv_delete.setVisibility(View.VISIBLE); + } else { + item_iv_delete.setVisibility(View.GONE); + } + } + + @Override + public void afterTextChanged(Editable s) { + + } + + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_SEARCH) { + InputMethodManager imm = (InputMethodManager) getActivity() + .getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); + if (!TextUtils.isEmpty(item_et_search.getText().toString())) { + keyword = item_et_search.getText().toString(); + + Map kv = new HashMap(); + kv.put("关键字", keyword); + TCAgent.onEvent(getActivity(), "搜索-游戏详情", gameName, kv); + + Map map = new HashMap(); + map.put("key", keyword); + map.put("from", "游戏详情-资讯"); + map.put("createdOn", System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent(getActivity(), "search", map); + + searchFormServer(0); + } else { + Toast.makeText(getActivity(), "请输入搜索关键字", + Toast.LENGTH_SHORT).show(); + } + } + return false; + } + + } + + private void searchFormServer(final int offset) { + isLoading = true; + if (offset == 0) { + EventBus.getDefault().post(new EBSlide(0, 0, false)); + EventBus.getDefault().post(new EBSlide(0, 2, false)); + fm_gameinformation_rv_show.scrollBy(0, rparams.topMargin); + + currentPosition = -1; + + adapter = new GameInformationAdapter(new ArrayList()); + fm_gameinformation_rv_show.setAdapter(adapter); + } + + final String url = Config.HOST + "v1d45/search/news?type_group=" + + Uri.encode("资讯") + "&game_id=" + id + "&keyword=" + + Uri.encode(keyword) + "&limit=20&offset=" + offset; + JsonArrayExtendedRequest searchRequest = new JsonArrayExtendedRequest( + url, new Response.Listener() { + + @Override + public void onResponse(JSONArray response) { + if (!isDestroy) { + try { + processingSearchData(response); + isLoading = false; + } catch (JSONException e) { + + e.printStackTrace(); + } + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + isLoading = false; + // 无网络连接和访问超时 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + if (!isDestroy) { + Toast.makeText(getActivity(), "网络错误", + Toast.LENGTH_SHORT).show(); + isNetworkError = true; + adapter.notifyItemChanged(adapter + .getItemCount() - 2); + } + } + } + }); + AppController.addToRequestQueue(searchRequest, + GameInformationFragment.class); + } + + private void processingSearchData(JSONArray response) throws JSONException { + Gson gson = new Gson(); + int size = response.length(); + for (int i = 0; i < size; i++) { + JSONObject jsonObject = response.getJSONObject(i); + adapter.getNewsList().add( + gson.fromJson(jsonObject.toString(), NewsEntity.class)); + adapter.notifyItemInserted(adapter.getNewsList().size() + 2); + } + if (size < 20) { + adapter.setRemove(true); + adapter.notifyItemRemoved(adapter.getNewsList().size() + 3); + adapter.notifyItemChanged(adapter.getNewsList().size() + 3); + } + adapter.notifyItemChanged(2); + } + + private class GameInformationAdapter extends + RecyclerView.Adapter { + + private ArrayList newsList; + private boolean isRemove; + + public GameInformationAdapter(ArrayList newsList) { + this.newsList = newsList; + isRemove = false; + } + + public ArrayList getNewsList() { + return newsList; + } + + public boolean isRemove() { + return isRemove; + } + + public void setRemove(boolean isRemove) { + this.isRemove = isRemove; + } + + @Override + public int getItemCount() { + if (isNull) { + return 3; + } + if (isRemove) { + return newsList.size() + 4; + } + return newsList.size() + 5; + } + + @Override + public void onBindViewHolder(GameInformationViewHolder viewHolder, + int position) { + if (!isNull && position == 2) { + if (currentPosition == -1) { + viewHolder.item_et_search.setText(keyword); + viewHolder.item_et_search.setSelection(keyword.length()); + viewHolder.item_et_search.requestFocus(); + Spanned content = Html.fromHtml("与“" + + keyword + "”相关的资讯共" + + adapter.getNewsList().size() + "条"); + viewHolder.item_tv_search_result.setText(content); + viewHolder.item_rv_select.setVisibility(View.GONE); + viewHolder.item_ll_search_result + .setVisibility(View.VISIBLE); + } else if (typeList.isEmpty()) { + viewHolder.item_rv_select.setVisibility(View.GONE); + viewHolder.item_ll_search_result.setVisibility(View.GONE); + } else { + viewHolder.item_rv_select.setVisibility(View.VISIBLE); + viewHolder.item_ll_search_result.setVisibility(View.GONE); + int height = DisplayUtils.dip2px( + getActivity(), + 50 * ((int) Math.ceil((typeList.size() + 1) + / (double) (column)))); + LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams( + LayoutParams.MATCH_PARENT, height); + viewHolder.item_rv_select.setLayoutParams(lparams); + } + } else if (position >= 3 && position <= newsList.size() + 2) { + viewHolder.information_type.setText((position - 2) + ""); + if (currentPosition == -1) { + String title = adapter + .getNewsList() + .get(position - 3) + .getTitle() + .replace(keyword, "" + keyword + ""); + Spanned content = Html.fromHtml(title); + viewHolder.information_title.setText(content); + } else { + viewHolder.information_title.setText(adapter.getNewsList() + .get(position - 3).getTitle()); + } + } else if (isRemove && position == newsList.size() + 3) { + LayoutParams params = new LayoutParams( + LayoutParams.MATCH_PARENT, 0); + + int itemHeight = DisplayUtils.dip2px(getActivity(), 38); + + int totalHeight = 0; + + if (currentPosition == -1) { + totalHeight = fm_gameinformation_rv_show.getHeight() + - DisplayUtils.dip2px(getActivity(), 29 + 51 + 35); + } else { + totalHeight = fm_gameinformation_rv_show.getHeight() + - DisplayUtils.dip2px( + getActivity(), + 29 + 51 + 50 * ((int) Math.ceil((typeList + .size() + 1) / (double) (column)))); + } + int bottomHeight = totalHeight - newsList.size() * itemHeight; + + int normalHeight = DisplayUtils.dip2px(getActivity(), 44); + + if (!Config.isShow) { + normalHeight = 0; + } + + if (bottomHeight > normalHeight) { + params.height = bottomHeight; + } else { + params.height = normalHeight; + } + + viewHolder.itemView.setLayoutParams(params); + } else if (!isRemove && position == newsList.size() + 3) { + if (isNetworkError) { + viewHolder.item_pb_loading.setVisibility(View.GONE); + viewHolder.item_tv_loading.setText("加载失败,点击重试"); + viewHolder.itemView.setClickable(true); + viewHolder.itemView + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + isNetworkError = false; + notifyItemChanged(getItemCount() - 2); + if (currentPosition == -1) { + searchFormServer(newsList.size()); + } else { + getGameInformation(newsList.size()); + } + } + }); + } else { + viewHolder.item_pb_loading.setVisibility(View.VISIBLE); + viewHolder.item_tv_loading.setText("加载中..."); + viewHolder.itemView.setClickable(false); + } + } + } + + @Override + public GameInformationViewHolder onCreateViewHolder( + ViewGroup viewGroup, int i) { + View view; + if (i == 0) { + RelativeLayout relativeLayout = new RelativeLayout( + getActivity()); + LayoutParams params = new LayoutParams( + LayoutParams.MATCH_PARENT, DisplayUtils.dip2px( + getActivity(), 66)); + relativeLayout.setLayoutParams(params); + view = relativeLayout; + } else if (i == 1) { + RelativeLayout relativeLayout = new RelativeLayout( + getActivity()); + LayoutParams params = new LayoutParams( + LayoutParams.MATCH_PARENT, DisplayUtils.dip2px( + getActivity(), 29)); + relativeLayout.setLayoutParams(params); + view = relativeLayout; + } else if (isNull && i == 2) { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.reuse_none_date, viewGroup, false); + TextView hint = (TextView) view + .findViewById(R.id.reuse_tv_none); + hint.setText("暂无数据"); + int height = fm_gameinformation_rv_show.getHeight() + - DisplayUtils.dip2px(getActivity(), 29); + LayoutParams params = new LayoutParams( + LayoutParams.MATCH_PARENT, height); + view.setLayoutParams(params); + } else if (i == 2) { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.gameinformaiton_item_search, viewGroup, false); + ((TextView) view.findViewById(R.id.item_tv_search)).setText("搜资讯"); + } else if (isRemove && (newsList == null || newsList.isEmpty()) + && i == 3) { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.reuse_none_date, viewGroup, false); + TextView hint = (TextView) view + .findViewById(R.id.reuse_tv_none); + int height = 0; + if (currentPosition == -1) { + hint.setText("搜索为空"); + height = fm_gameinformation_rv_show.getHeight() + - DisplayUtils.dip2px(getActivity(), 29 + 51 + 35); + } else { + hint.setText("暂无数据"); + height = fm_gameinformation_rv_show.getHeight() + - DisplayUtils.dip2px( + getActivity(), + 29 + 51 + 50 * ((int) Math.ceil((typeList + .size() + 1) / (double) (column)))); + } + LayoutParams params = new LayoutParams( + LayoutParams.MATCH_PARENT, height); + view.setLayoutParams(params); + } else if (!isRemove && i == newsList.size() + 3) { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.gamedetails_item_loading, viewGroup, false); + } else if ((!isRemove && i == newsList.size() + 4) + || (isRemove && i == newsList.size() + 3)) { + RelativeLayout relativeLayout = new RelativeLayout( + getActivity()); + LayoutParams params = new LayoutParams( + LayoutParams.MATCH_PARENT, DisplayUtils.dip2px( + getActivity(), 44)); + if (!Config.isShow) { + params.height = 0; + } + relativeLayout.setLayoutParams(params); + view = relativeLayout; + } else { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.gameinformation_item, viewGroup, false); + } + view.setTag(i); + return new GameInformationViewHolder(view); + } + + @Override + public int getItemViewType(int position) { + + return position; + } + } + + private class SelectViewHolder extends RecyclerView.ViewHolder implements + OnClickListener { + + private TextView select_tv_type; + + public SelectViewHolder(View covertView) { + super(covertView); + + select_tv_type = (TextView) covertView + .findViewById(R.id.select_tv_type); + select_tv_type.setOnClickListener(this); + } + + @Override + public void onClick(View v) { + EventBus.getDefault().post(new EBSlide(0, 0, false)); + EventBus.getDefault().post(new EBSlide(0, 2, false)); + fm_gameinformation_rv_show.scrollBy(0, rparams.topMargin); + type = select_tv_type.getText().toString(); + currentPosition = getPosition(); + + Map map = new HashMap(); + map.put("location", "资讯-" + type); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", gameName); + map.put("page", "游戏详情"); + DataCollectionManager.onEvent(getActivity(), "click-item", map); + + getGameInformation(0); + } + + } + + private class SelectViewAdapter extends + RecyclerView.Adapter { + + @Override + public int getItemCount() { + return 1 + typeList.size(); + } + + @Override + public void onBindViewHolder(SelectViewHolder viewHolder, int position) { + if (position == 0) { + viewHolder.select_tv_type.setText("全部"); + } else { + viewHolder.select_tv_type.setText(typeList.get(position - 1)); + } + if (currentPosition == position) { + viewHolder.select_tv_type + .setBackgroundResource(R.drawable.textview_search_dn); + viewHolder.select_tv_type.setClickable(false); + } else { + viewHolder.select_tv_type + .setBackgroundResource(R.drawable.textview_search_up); + viewHolder.select_tv_type.setClickable(true); + } + } + + @Override + public SelectViewHolder onCreateViewHolder(ViewGroup viewGroup, int type) { + View view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.gameinformation_select_item, viewGroup, false); + return new SelectViewHolder(view); + } + + } + + @Override + public void onDestroy() { + super.onDestroy(); + isDestroy = true; + EventBus.getDefault().unregister(this); + AppController.canclePendingRequests(GameInformationFragment.class); + view = null; + fm_gameinformation_rv_show = null; + linearLayoutManager = null; + adapter = null; + fm_gameinformation_ll_loading = null; + reuse_no_connection = null; + rparams = null; + adapterMap = null; + typeList = null; + type = null; + keyword = null; + id = null; + gameName = null; + entrance = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/gamedetails/GameStrategyFragment.java b/app/src/main/java/com/gh/gamecenter/gamedetails/GameStrategyFragment.java new file mode 100644 index 0000000000..cdd2413343 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/gamedetails/GameStrategyFragment.java @@ -0,0 +1,955 @@ +package com.gh.gamecenter.gamedetails; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import android.content.Context; +import android.content.SharedPreferences; +import android.net.Uri; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.util.ArrayMap; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.Editable; +import android.text.Html; +import android.text.Spanned; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.AbsListView.OnScrollListener; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.TextView.OnEditorActionListener; +import android.widget.Toast; + +import com.android.volley.NoConnectionError; +import com.android.volley.Response; +import com.android.volley.TimeoutError; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.common.constant.Config; +import com.gh.common.util.DisplayUtils; +import com.gh.common.util.NewsUtils; +import com.gh.common.util.Utils; +import com.gh.gamecenter.R; +import com.gh.gamecenter.entity.NewsEntity; +import com.gh.gamecenter.eventbus.EBMoveTop; +import com.gh.gamecenter.eventbus.EBNetworkState; +import com.gh.gamecenter.eventbus.EBNewsType; +import com.gh.gamecenter.eventbus.EBSlide; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.volley.extended.JsonArrayExtendedRequest; +import com.google.gson.Gson; +import com.tendcloud.tenddata.TCAgent; + +import de.greenrobot.event.EventBus; + +/** + * 游戏攻略fragment + * + * @author 黄壮华 + * + */ +public class GameStrategyFragment extends Fragment { + + private View view; + private RecyclerView fm_gamestrategy_rv_show; + private LinearLayoutManager linearLayoutManager; + private GameStrategyAdapter adapter; + private LinearLayout fm_gamestrategy_ll_loading, reuse_no_connection; + private RelativeLayout.LayoutParams rparams; + + private ArrayMap adapterMap; + private List typeList; + + private String id; + private String type = "全部"; + private String keyword; + private String gameName; + private String entrance; + + private int dis; + private int distance; + private int currentPosition = 0; + private int column; + + private boolean isNull = false; + private boolean isLoading = false; + private boolean isNetworkError = false; + private boolean isDestroy = false; + + public GameStrategyFragment() { + + } + + public GameStrategyFragment(String id, String gameName, String entrance) { + this.id = id; + this.gameName = gameName; + this.entrance = entrance; + } + + @Override + public void onSaveInstanceState(Bundle outState) { + + super.onSaveInstanceState(outState); + Utils.log(this.getClass().getSimpleName() + " onSaveInstanceState"); + outState.putString("id", id); + outState.putString("gameName", gameName); + outState.putString("entrance", entrance); + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + if (savedInstanceState != null) { + id = savedInstanceState.getString("id"); + gameName = savedInstanceState.getString("gameName"); + entrance = savedInstanceState.getString("entrance"); + } + + view = View.inflate(getActivity(), R.layout.gamestrategy, null); + + distance = DisplayUtils.dip2px(getActivity(), 66); + typeList = new ArrayList(); + adapterMap = new ArrayMap(); + + SharedPreferences sp = getActivity().getSharedPreferences( + Config.PREFERENCE, Context.MODE_PRIVATE); + column = sp.getInt("game_detail_news_type_tab_column", 4); + + fm_gamestrategy_ll_loading = (LinearLayout) view + .findViewById(R.id.fm_gamestrategy_ll_loading); + + reuse_no_connection = (LinearLayout) view + .findViewById(R.id.reuse_no_connection); + reuse_no_connection.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + fm_gamestrategy_rv_show.setVisibility(View.GONE); + fm_gamestrategy_ll_loading.setVisibility(View.VISIBLE); + reuse_no_connection.setVisibility(View.GONE); + getGameInformation(0, true); + } + }); + + rparams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, + LayoutParams.WRAP_CONTENT); + + fm_gamestrategy_rv_show = (RecyclerView) view + .findViewById(R.id.fm_gamestrategy_rv_show); + fm_gamestrategy_rv_show.setHasFixedSize(true); + linearLayoutManager = new LinearLayoutManager(getActivity()); + linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + fm_gamestrategy_rv_show.setLayoutManager(linearLayoutManager); + fm_gamestrategy_rv_show + .setOnScrollListener(new GameStrategyOnScrollListener()); + + EventBus.getDefault().register(this); + + getGameInformation(0, true); + } + + @Override + @Nullable + public View onCreateView(LayoutInflater inflater, + @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + + if (container != null) { + container.removeView(view); + } + return view; + } + + private class GameStrategyOnScrollListener extends + RecyclerView.OnScrollListener { + + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + + super.onScrolled(recyclerView, dx, dy); + + int visibility; + if (linearLayoutManager.findFirstVisibleItemPosition() >= 1) { + visibility = View.VISIBLE; + } else { + visibility = View.GONE; + } + + dis += dy; + + rparams.topMargin -= dy; + + EventBus.getDefault().post( + new EBMoveTop("top", visibility, rparams.topMargin)); + } + + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + + super.onScrollStateChanged(recyclerView, newState); + if (newState == OnScrollListener.SCROLL_STATE_IDLE) { + int position = adapter.getNewsList().size() + 4; + if (!Config.isShow) { + position--; + } + if (linearLayoutManager.findLastVisibleItemPosition() == position + && !adapter.isRemove() && !isLoading) { + if (currentPosition == -1) { + searchFormServer(adapter.getNewsList().size()); + } else { + getGameInformation(adapter.getNewsList().size()); + } + } + if (dis > distance) { + EventBus.getDefault().post(new EBSlide(distance, 0, false)); + EventBus.getDefault().post(new EBSlide(distance, 1, false)); + } else if (dis < -distance) { + EventBus.getDefault().post(new EBSlide(0, 0, false)); + EventBus.getDefault().post(new EBSlide(0, 1, false)); + } else { + EventBus.getDefault().post(new EBSlide(dis, 0, false)); + EventBus.getDefault().post(new EBSlide(dis, 1, false)); + } + } + } + } + + public void onEventMainThread(EBSlide busOne) { + if (busOne.getPosition() == 2) { + if (busOne.isReset()) { + fm_gamestrategy_rv_show.scrollBy(0, distance - dis); + } else { + if (busOne.getDistance() == 0) { + fm_gamestrategy_rv_show.scrollToPosition(0); + rparams.topMargin = 0; + dis = 0; + } else { + fm_gamestrategy_rv_show.scrollBy(0, busOne.getDistance() + - dis); + } + } + } + } + + public void onEventMainThread(EBNetworkState busNetworkState) { + if (busNetworkState.isNetworkConnected()) { + if (reuse_no_connection.getVisibility() == View.VISIBLE) { + fm_gamestrategy_rv_show.setVisibility(View.GONE); + fm_gamestrategy_ll_loading.setVisibility(View.VISIBLE); + reuse_no_connection.setVisibility(View.GONE); + getGameInformation(0, true); + } else if (isNetworkError) { + isNetworkError = false; + adapter.notifyItemChanged(adapter.getItemCount() - 2); + if (currentPosition == -1) { + searchFormServer(adapter.getNewsList().size()); + } else { + getGameInformation(adapter.getNewsList().size()); + } + } + } + } + + public void onEventMainThread(EBNewsType type) { + if ("攻略".equals(type.getType())) { + typeList = type.getList(); + adapter.notifyItemChanged(2); + } + } + + private void getGameInformation(final int offset) { + getGameInformation(offset, false); + } + + private void getGameInformation(final int offset, final boolean isFirst) { + isLoading = true; + if (offset == 0) { + adapter = adapterMap.get(type); + if (adapter == null) { + adapter = new GameStrategyAdapter(new ArrayList()); + adapterMap.put(type, adapter); + } + fm_gamestrategy_rv_show.setAdapter(adapter); + } + + final String url; + + if ("全部".equals(type)) { + url = Config.HOST + "v1d45/game/" + id + "/news?limit=20&offset=" + + offset + "&type_group=" + Uri.encode("攻略"); + } else { + url = Config.HOST + "v1d45/game/" + id + "/news?limit=20&offset=" + + offset + "&type=" + Uri.encode(type); + } + + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest(url, + new Response.Listener() { + + @Override + public void onResponse(JSONArray response) { + if (!isDestroy) { + try { + processingData(response, offset, isFirst); + isLoading = false; + } catch (JSONException e) { + e.printStackTrace(); + } + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + isLoading = false; + // 无网络连接和访问超时 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + if (!isDestroy) { + if (offset == 0 && isFirst) { + fm_gamestrategy_rv_show + .setVisibility(View.GONE); + fm_gamestrategy_ll_loading + .setVisibility(View.GONE); + reuse_no_connection + .setVisibility(View.VISIBLE); + } else { + Toast.makeText(getActivity(), "网络错误", + Toast.LENGTH_SHORT).show(); + isNetworkError = true; + adapter.notifyItemChanged(adapter + .getItemCount() - 2); + } + } + } + } + }); + if ((adapter.getNewsList().isEmpty() && !adapter.isRemove() && offset == 0) + || (offset != 0)) { + AppController + .addToRequestQueue(request, GameStrategyFragment.class); + } + } + + private void processingData(JSONArray response, int offset, boolean isFirst) + throws JSONException { + Gson gson = new Gson(); + int size = response.length(); + if (offset == 0) { + fm_gamestrategy_ll_loading.setVisibility(View.GONE); + fm_gamestrategy_rv_show.setVisibility(View.VISIBLE); + } + for (int i = 0; i < size; i++) { + JSONObject jsonObject = response.getJSONObject(i); + adapter.getNewsList().add( + gson.fromJson(jsonObject.toString(), NewsEntity.class)); + adapter.notifyItemInserted(adapter.getNewsList().size() + 2); + } + if (size < 20) { + adapter.setRemove(true); + adapter.notifyItemRemoved(adapter.getNewsList().size() + 3); + adapter.notifyItemChanged(adapter.getNewsList().size() + 3); + if (isFirst && size == 0 && !isNull) { + isNull = true; + adapter.notifyItemRemoved(2); + } + } + if (size == 0 && dis != 0) { + int dy = DisplayUtils.dip2px(getActivity(), 35); + dis -= dy; + rparams.topMargin += dy; + EventBus.getDefault().post( + new EBMoveTop("top", View.VISIBLE, rparams.topMargin)); + } + } + + private class GameStrategyViewHolder extends RecyclerView.ViewHolder + implements OnClickListener, TextWatcher, OnEditorActionListener { + + private EditText item_et_search; + private ImageView item_iv_delete; + private TextView item_tv_search; + private RecyclerView item_rv_select; + private LinearLayout item_ll_search_result; + private TextView item_tv_search_result; + private ImageView item_iv_search_result; + + private TextView information_type, information_title; + private View itemView; + + private ProgressBar item_pb_loading; + private TextView item_tv_loading; + + public GameStrategyViewHolder(View convertView) { + super(convertView); + + itemView = convertView; + int position = (Integer) convertView.getTag(); + if (!isNull && position == 2) { + item_et_search = (EditText) convertView + .findViewById(R.id.item_et_search); + item_et_search.addTextChangedListener(this); + item_et_search.setOnEditorActionListener(this); + item_iv_delete = (ImageView) convertView + .findViewById(R.id.item_iv_delete); + item_iv_delete.setOnClickListener(this); + item_tv_search = (TextView) convertView + .findViewById(R.id.item_tv_search); + item_tv_search.setOnClickListener(this); + item_rv_select = (RecyclerView) convertView + .findViewById(R.id.item_rv_select); + item_rv_select.setLayoutManager(new GridLayoutManager( + getActivity(), column)); + item_rv_select.setAdapter(new SelectViewAdapter()); + item_ll_search_result = (LinearLayout) convertView + .findViewById(R.id.item_ll_search_result); + item_tv_search_result = (TextView) convertView + .findViewById(R.id.item_tv_search_result); + item_iv_search_result = (ImageView) convertView + .findViewById(R.id.item_iv_search_result); + item_iv_search_result.setOnClickListener(this); + } else if (position >= 3 + && position <= adapter.getNewsList().size() + 2) { + information_type = (TextView) convertView + .findViewById(R.id.information_type); + information_title = (TextView) convertView + .findViewById(R.id.information_title); + convertView.setOnClickListener(this); + } else if (!adapter.isRemove() + && position == adapter.getNewsList().size() + 3) { + item_pb_loading = (ProgressBar) convertView + .findViewById(R.id.item_pb_loading); + item_tv_loading = (TextView) convertView + .findViewById(R.id.item_tv_loading); + } + } + + @Override + public void onClick(View v) { + if (v == itemView) { + NewsEntity newsEntity = adapter.getNewsList().get( + getPosition() - 3); + + Map kv = new HashMap(); + kv.put("文章类型", newsEntity.getType()); + kv.put("入口", "游戏详情-攻略"); + TCAgent.onEvent(getActivity(), "文章阅读-攻略", + newsEntity.getTitle(), kv); + + Map map = new HashMap(); + map.put("location", "攻略"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", gameName); + map.put("news", newsEntity.getTitle()); + map.put("page", "游戏详情"); + DataCollectionManager.onEvent(getActivity(), "click-item", map); + + NewsUtils.startNewsActivity(getActivity(), newsEntity, entrance + + "-游戏详情-攻略"); + } + if (v == item_tv_search) { + InputMethodManager imm = (InputMethodManager) getActivity() + .getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); + if (!TextUtils.isEmpty(item_et_search.getText().toString())) { + keyword = item_et_search.getText().toString(); + + Map kv = new HashMap(); + kv.put("关键字", keyword); + TCAgent.onEvent(getActivity(), "搜索-游戏详情", gameName, kv); + + Map map = new HashMap(); + map.put("key", keyword); + map.put("from", "游戏详情-攻略"); + map.put("createdOn", System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent(getActivity(), "search", map); + + searchFormServer(0); + } else { + Toast.makeText(getActivity(), "请输入搜索关键字", + Toast.LENGTH_SHORT).show(); + } + } + if (v == item_iv_delete) { + item_et_search.setText(""); + } + if (v == item_iv_search_result) { + InputMethodManager imm = (InputMethodManager) getActivity() + .getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); + EventBus.getDefault().post(new EBSlide(0, 0, false)); + EventBus.getDefault().post(new EBSlide(0, 1, false)); + fm_gamestrategy_rv_show.scrollBy(0, rparams.topMargin); + currentPosition = 0; + adapter = adapterMap.get("全部"); + fm_gamestrategy_rv_show.setAdapter(adapter); + } + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, + int count) { + if (s.length() > 0) { + item_iv_delete.setVisibility(View.VISIBLE); + } else { + item_iv_delete.setVisibility(View.GONE); + } + } + + @Override + public void afterTextChanged(Editable s) { + + } + + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_SEARCH) { + InputMethodManager imm = (InputMethodManager) getActivity() + .getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); + if (!TextUtils.isEmpty(item_et_search.getText().toString())) { + keyword = item_et_search.getText().toString(); + + Map kv = new HashMap(); + kv.put("关键字", keyword); + TCAgent.onEvent(getActivity(), "搜索-游戏详情", gameName, kv); + + Map map = new HashMap(); + map.put("key", keyword); + map.put("from", "游戏详情-攻略"); + map.put("createdOn", System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent(getActivity(), "search", map); + + searchFormServer(0); + } else { + Toast.makeText(getActivity(), "请输入搜索关键字", + Toast.LENGTH_SHORT).show(); + } + } + return false; + } + + } + + private void searchFormServer(int offset) { + isLoading = true; + if (offset == 0) { + EventBus.getDefault().post(new EBSlide(0, 0, false)); + EventBus.getDefault().post(new EBSlide(0, 1, false)); + fm_gamestrategy_rv_show.scrollBy(0, rparams.topMargin); + + currentPosition = -1; + + adapter = new GameStrategyAdapter(new ArrayList()); + fm_gamestrategy_rv_show.setAdapter(adapter); + } + + final String url = Config.HOST + "v1d45/search/news?type_group=" + + Uri.encode("攻略") + "&game_id=" + id + "&keyword=" + + Uri.encode(keyword) + "&limit=20&offset=" + offset; + JsonArrayExtendedRequest searchRequest = new JsonArrayExtendedRequest( + url, new Response.Listener() { + + @Override + public void onResponse(JSONArray response) { + if (!isDestroy) { + try { + processingSearchData(response); + isLoading = false; + } catch (JSONException e) { + + e.printStackTrace(); + } + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + isLoading = false; + // 无网络连接和访问超时 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + if (!isDestroy) { + Toast.makeText(getActivity(), "网络错误", + Toast.LENGTH_SHORT).show(); + isNetworkError = true; + adapter.notifyItemChanged(adapter + .getItemCount() - 2); + } + } + } + }); + AppController.addToRequestQueue(searchRequest, + GameStrategyFragment.class); + } + + private void processingSearchData(JSONArray response) throws JSONException { + Gson gson = new Gson(); + int size = response.length(); + for (int i = 0; i < size; i++) { + JSONObject jsonObject = response.getJSONObject(i); + adapter.getNewsList().add( + gson.fromJson(jsonObject.toString(), NewsEntity.class)); + adapter.notifyItemInserted(adapter.getNewsList().size() + 2); + } + if (size < 20) { + adapter.setRemove(true); + adapter.notifyItemRemoved(adapter.getNewsList().size() + 3); + adapter.notifyItemChanged(adapter.getNewsList().size() + 3); + } + adapter.notifyItemChanged(2); + } + + private class GameStrategyAdapter extends + RecyclerView.Adapter { + + private ArrayList newsList; + private boolean isRemove; + + public GameStrategyAdapter(ArrayList newsList) { + this.newsList = newsList; + isRemove = false; + } + + public ArrayList getNewsList() { + return newsList; + } + + public boolean isRemove() { + return isRemove; + } + + public void setRemove(boolean isRemove) { + this.isRemove = isRemove; + } + + @Override + public int getItemCount() { + + if (isNull) { + return 3; + } + if (isRemove) { + return newsList.size() + 4; + } + return newsList.size() + 5; + } + + @Override + public void onBindViewHolder(GameStrategyViewHolder viewHolder, + int position) { + + if (!isNull && position == 2) { + if (currentPosition == -1) { + viewHolder.item_et_search.setText(keyword); + viewHolder.item_et_search.setSelection(keyword.length()); + viewHolder.item_et_search.requestFocus(); + Spanned content = Html.fromHtml("与“" + + keyword + "”相关的资讯共" + + adapter.getNewsList().size() + "条"); + viewHolder.item_tv_search_result.setText(content); + viewHolder.item_rv_select.setVisibility(View.GONE); + viewHolder.item_ll_search_result + .setVisibility(View.VISIBLE); + } else if (typeList.isEmpty()) { + viewHolder.item_rv_select.setVisibility(View.GONE); + viewHolder.item_ll_search_result.setVisibility(View.GONE); + } else { + viewHolder.item_rv_select.setVisibility(View.VISIBLE); + viewHolder.item_ll_search_result.setVisibility(View.GONE); + int height = DisplayUtils.dip2px( + getActivity(), + 50 * ((int) Math.ceil((typeList.size() + 1) + / (double) (column)))); + LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams( + LayoutParams.MATCH_PARENT, height); + viewHolder.item_rv_select.setLayoutParams(lparams); + } + } else if (position >= 3 + && position <= adapter.getNewsList().size() + 2) { + viewHolder.information_type.setText((position - 2) + ""); + if (currentPosition == -1) { + String title = adapter + .getNewsList() + .get(position - 3) + .getTitle() + .replace( + keyword, + "" + keyword + + ""); + Spanned content = Html.fromHtml(title); + viewHolder.information_title.setText(content); + } else { + viewHolder.information_title.setText(adapter.getNewsList() + .get(position - 3).getTitle()); + } + } else if (isRemove && position == newsList.size() + 3) { + LayoutParams params = new LayoutParams( + LayoutParams.MATCH_PARENT, 0); + + int itemHeight = DisplayUtils.dip2px(getActivity(), 38); + + int totalHeight = 0; + + if (currentPosition == -1) { + totalHeight = fm_gamestrategy_rv_show.getHeight() + - DisplayUtils.dip2px(getActivity(), 29 + 51 + 35); + } else { + totalHeight = fm_gamestrategy_rv_show.getHeight() + - DisplayUtils.dip2px( + getActivity(), + 29 + 51 + 50 * ((int) Math.ceil((typeList + .size() + 1) / (double) (column)))); + } + int bottomHeight = totalHeight - newsList.size() * itemHeight; + + int normalHeight = DisplayUtils.dip2px(getActivity(), 44); + + if (!Config.isShow) { + normalHeight = 0; + } + + if (bottomHeight > normalHeight) { + params.height = bottomHeight; + } else { + params.height = normalHeight; + } + + viewHolder.itemView.setLayoutParams(params); + } else if (!isRemove && position == newsList.size() + 3) { + if (isNetworkError) { + viewHolder.item_pb_loading.setVisibility(View.GONE); + viewHolder.item_tv_loading.setText("加载失败,点击重试"); + viewHolder.itemView.setClickable(true); + viewHolder.itemView + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + isNetworkError = false; + notifyItemChanged(getItemCount() - 2); + if (currentPosition == -1) { + searchFormServer(newsList.size()); + } else { + getGameInformation(newsList.size()); + } + } + }); + } else { + viewHolder.item_pb_loading.setVisibility(View.VISIBLE); + viewHolder.item_tv_loading.setText("加载中..."); + viewHolder.itemView.setClickable(false); + } + } + } + + @Override + public GameStrategyViewHolder onCreateViewHolder(ViewGroup viewGroup, + int i) { + + View view; + if (i == 0) { + RelativeLayout relativeLayout = new RelativeLayout( + getActivity()); + LayoutParams params = new LayoutParams( + LayoutParams.MATCH_PARENT, DisplayUtils.dip2px( + getActivity(), 66)); + relativeLayout.setLayoutParams(params); + view = relativeLayout; + } else if (i == 1) { + RelativeLayout relativeLayout = new RelativeLayout( + getActivity()); + LayoutParams params = new LayoutParams( + LayoutParams.MATCH_PARENT, DisplayUtils.dip2px( + getActivity(), 29)); + relativeLayout.setLayoutParams(params); + view = relativeLayout; + } else if (isNull && i == 2) { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.reuse_none_date, viewGroup, false); + TextView hint = (TextView) view + .findViewById(R.id.reuse_tv_none); + hint.setText("暂无数据"); + int height = fm_gamestrategy_rv_show.getHeight() + - DisplayUtils.dip2px(getActivity(), 29); + LayoutParams params = new LayoutParams( + LayoutParams.MATCH_PARENT, height); + view.setLayoutParams(params); + } else if (i == 2) { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.gameinformaiton_item_search, viewGroup, false); + ((TextView) view.findViewById(R.id.item_tv_search)) + .setText("搜攻略"); + } else if (isRemove && (newsList == null || newsList.isEmpty()) + && i == 3) { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.reuse_none_date, viewGroup, false); + TextView hint = (TextView) view + .findViewById(R.id.reuse_tv_none); + int height = 0; + if (currentPosition == -1) { + hint.setText("搜索为空"); + height = fm_gamestrategy_rv_show.getHeight() + - DisplayUtils.dip2px(getActivity(), 29 + 51 + 35); + } else { + hint.setText("暂无数据"); + height = fm_gamestrategy_rv_show.getHeight() + - DisplayUtils.dip2px( + getActivity(), + 29 + 51 + 50 * ((int) Math.ceil((typeList + .size() + 1) / (double) (column)))); + } + LayoutParams params = new LayoutParams( + LayoutParams.MATCH_PARENT, height); + view.setLayoutParams(params); + } else if (!isRemove && i == adapter.getNewsList().size() + 3) { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.gamedetails_item_loading, viewGroup, false); + } else if ((!isRemove && i == newsList.size() + 4) + || (isRemove && i == newsList.size() + 3)) { + RelativeLayout relativeLayout = new RelativeLayout( + getActivity()); + LayoutParams params = new LayoutParams( + LayoutParams.MATCH_PARENT, DisplayUtils.dip2px( + getActivity(), 44)); + if (!Config.isShow) { + params.height = 0; + } + relativeLayout.setLayoutParams(params); + view = relativeLayout; + } else { + view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.gameinformation_item, viewGroup, false); + } + view.setTag(i); + return new GameStrategyViewHolder(view); + } + + @Override + public int getItemViewType(int position) { + + return position; + } + } + + private class SelectViewHolder extends RecyclerView.ViewHolder implements + OnClickListener { + + private TextView select_tv_type; + + public SelectViewHolder(View covertView) { + super(covertView); + + select_tv_type = (TextView) covertView + .findViewById(R.id.select_tv_type); + select_tv_type.setOnClickListener(this); + } + + @Override + public void onClick(View v) { + EventBus.getDefault().post(new EBSlide(0, 0, false)); + EventBus.getDefault().post(new EBSlide(0, 1, false)); + fm_gamestrategy_rv_show.scrollBy(0, rparams.topMargin); + type = select_tv_type.getText().toString(); + currentPosition = getPosition(); + + Map map = new HashMap(); + map.put("location", "攻略-" + type); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", gameName); + map.put("page", "游戏详情"); + DataCollectionManager.onEvent(getActivity(), "click-item", map); + + getGameInformation(0); + } + + } + + private class SelectViewAdapter extends + RecyclerView.Adapter { + + @Override + public int getItemCount() { + + return 1 + typeList.size(); + } + + @Override + public void onBindViewHolder(SelectViewHolder viewHolder, int position) { + + if (position == 0) { + viewHolder.select_tv_type.setText("全部"); + } else { + viewHolder.select_tv_type.setText(typeList.get(position - 1)); + } + if (currentPosition == position) { + viewHolder.select_tv_type + .setBackgroundResource(R.drawable.textview_search_dn); + viewHolder.select_tv_type.setClickable(false); + } else { + viewHolder.select_tv_type + .setBackgroundResource(R.drawable.textview_search_up); + viewHolder.select_tv_type.setClickable(true); + } + } + + @Override + public SelectViewHolder onCreateViewHolder(ViewGroup viewGroup, int type) { + + View view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.gameinformation_select_item, viewGroup, false); + return new SelectViewHolder(view); + } + + } + + @Override + public void onDestroy() { + + super.onDestroy(); + isDestroy = true; + EventBus.getDefault().unregister(this); + AppController.canclePendingRequests(GameStrategyFragment.class); + view = null; + fm_gamestrategy_rv_show = null; + linearLayoutManager = null; + adapter = null; + fm_gamestrategy_ll_loading = null; + reuse_no_connection = null; + rparams = null; + adapterMap = null; + typeList = null; + id = null; + type = null; + keyword = null; + gameName = null; + entrance = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/home/HomeFragment.java b/app/src/main/java/com/gh/gamecenter/home/HomeFragment.java new file mode 100644 index 0000000000..d933ee483c --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/home/HomeFragment.java @@ -0,0 +1,636 @@ +package com.gh.gamecenter.home; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.LinkedBlockingQueue; + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.graphics.Rect; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.util.ArrayMap; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.PopupWindow; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.gh.base.AppController; +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.common.util.DisplayUtils; +import com.gh.common.util.DownloadItemUtils; +import com.gh.common.view.VerticalItemDecoration; +import com.gh.download.DataWatcher; +import com.gh.download.DownloadEntry; +import com.gh.download.DownloadManager; +import com.gh.gamecenter.ConcernActivity; +import com.gh.gamecenter.DownloadManagerActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.SearchActivity; +import com.gh.gamecenter.SettingActivity; +import com.gh.gamecenter.entity.ApkEntity; +import com.gh.gamecenter.entity.DismissEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.eventbus.EBDownloadDelete; +import com.gh.gamecenter.eventbus.EBNetworkState; +import com.gh.gamecenter.eventbus.EBPWDismiss; +import com.gh.gamecenter.eventbus.EBPackage; +import com.gh.gamecenter.eventbus.EBRedDot; +import com.gh.gamecenter.eventbus.EBTopState; +import com.gh.gamecenter.eventbus.EBUISwitch; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.manager.PackageManager; +import com.tendcloud.tenddata.TCAgent; + +import de.greenrobot.event.EventBus; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-8-8 + * @update 2015-8-11 + * @des 主页fragment页面 + */ +public class HomeFragment extends Fragment implements OnClickListener { + + private View view; + private RecyclerView recyclerview; + private HomeFragmentAdapter adapter; + private TextView downloadHint, searchHint; + private LinearLayout reuse_no_connection; + + // 黄壮华 添加 记录信息的map 修改2015/8/19 + private ArrayMap locationMap; + private ArrayMap> gameMap; + private ArrayMap> platformMap; + private ArrayMap nameMap; + + private boolean isEverpause; + private boolean isDestroy = false; + + private int currentItem = 0; + + private String hint; + + private ArrayMap lastTimeMap; + private ArrayMap statusMap; + + private DismissEntity dismissEntity; + + private PopupWindow popWindow; + + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (!isDestroy) { + if (msg.what == Constants.DOWNLOAD_ROLL) { + String name = (String) msg.obj; + if (platformMap != null) { + LinkedBlockingQueue queue = platformMap + .get(name); + if (queue.size() > 1) { + queue.offer(queue.poll()); + Message msg2 = Message.obtain(); + msg2.obj = name; + msg2.what = Constants.DOWNLOAD_ROLL; + sendMessageDelayed(msg2, 3000); + } + } + } else if (msg.what == Constants.CONTINUE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + DownloadManager.getInstance(getActivity()).resume(url); + } + } else if (msg.what == Constants.PAUSE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + DownloadManager.getInstance(getActivity()).pause(url); + } + } + } + } + }; + + // 黄壮华 添加观察者 修改2015/8/19 + private DataWatcher dataWatcher = new DataWatcher() { + + @Override + public void onDataChanged( + HashMap downloadingEntries) { + for (Map.Entry entry : downloadingEntries + .entrySet()) { + DownloadEntry downloadEntry = entry.getValue(); + + Integer location = locationMap.get(downloadEntry.getName()); + if (location != null) { + int index = location.intValue(); + + GameEntity detailedEntity = getEntityByLocation(index); + + if (detailedEntity != null) { + DownloadItemUtils.processDate(detailedEntity, + downloadEntry, platformMap, handler, adapter, + index, statusMap); + } + } + } + } + }; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + view = View.inflate(getActivity(), R.layout.home1_fragment, null); + + SharedPreferences sp = getActivity().getSharedPreferences( + Config.PREFERENCE, Context.MODE_PRIVATE); + + LinearLayout home_actionbar = (LinearLayout) view + .findViewById(R.id.home_actionbar); + LayoutParams lparams = new LayoutParams( + LayoutParams.MATCH_PARENT, sp.getInt("actionbar_height", + DisplayUtils.dip2px(getActivity(), 48))); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + int top = DisplayUtils.getInternalDimensionSize(getResources(), + "status_bar_height"); + home_actionbar.setPadding(0, top, 0, 0); + lparams.height += top; + } + + home_actionbar.setLayoutParams(lparams); + + initActionBar(); + + lastTimeMap = new ArrayMap(); + statusMap = new ArrayMap(); + locationMap = new ArrayMap(); + gameMap = new ArrayMap>(); + platformMap = new ArrayMap>(); + nameMap = new ArrayMap(); + + dismissEntity = new DismissEntity(false); + + isEverpause = false; + + recyclerview = (RecyclerView) view.findViewById(R.id.home_list); + recyclerview.setHasFixedSize(true); + LinearLayoutManager llm = new LinearLayoutManager(getActivity()); + llm.setOrientation(LinearLayoutManager.VERTICAL); + recyclerview.setLayoutManager(llm); + + // 黄壮华 添加 初始化游戏状态 修改2015/8/21 + DownloadItemUtils.initializeGameMap(getActivity(), gameMap); + + reuse_no_connection = (LinearLayout) view + .findViewById(R.id.reuse_no_connection); + reuse_no_connection.setOnClickListener(this); + + adapter = new HomeFragmentAdapter(getActivity(), gameMap, locationMap, + nameMap, platformMap, reuse_no_connection, recyclerview, + handler, lastTimeMap, statusMap, dismissEntity); + recyclerview.setAdapter(adapter); + + recyclerview.addItemDecoration(new VerticalItemDecoration( + getActivity(), 1)); + + EventBus.getDefault().register(this); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + if (container != null) { + container.removeView(view); + } + return view; + } + + private void initActionBar() { + view.findViewById(R.id.actionbar_rl_download).setOnClickListener(this); + + view.findViewById(R.id.actionbar_iv_search).setOnClickListener(this); + + if (Config.isShow) { + view.findViewById(R.id.actionbar_rl_download).setVisibility( + View.VISIBLE); + } else { + view.findViewById(R.id.actionbar_rl_download).setVisibility( + View.GONE); + } + + downloadHint = (TextView) view.findViewById(R.id.action_tip); + int updateSize = PackageManager.getUpdateListSize(); + int downloadSize = DownloadManager.getInstance(getActivity()).getAll() + .size(); + if (downloadSize != 0) { + downloadHint.setVisibility(View.VISIBLE); + downloadHint.setText(downloadSize + ""); + int width = DisplayUtils.dip2px(getActivity(), 12); + RelativeLayout.LayoutParams rparams = new RelativeLayout.LayoutParams( + width, width); + rparams.topMargin = DisplayUtils.dip2px(getActivity(), 8); + rparams.rightMargin = DisplayUtils.dip2px(getActivity(), 2); + rparams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + downloadHint.setLayoutParams(rparams); + } else if (updateSize != 0) { + downloadHint.setText(""); + int width = DisplayUtils.dip2px(getActivity(), 10); + RelativeLayout.LayoutParams rparams = new RelativeLayout.LayoutParams( + width, width); + rparams.topMargin = DisplayUtils.dip2px(getActivity(), 8); + rparams.rightMargin = DisplayUtils.dip2px(getActivity(), 3); + rparams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + downloadHint.setLayoutParams(rparams); + } else { + downloadHint.setVisibility(View.GONE); + } + + searchHint = (TextView) view.findViewById(R.id.actionbar_search_input); + searchHint.setOnClickListener(this); + + view.findViewById(R.id.actionbar_notification).setOnClickListener(this); + + view.findViewById(R.id.actionbar_overflow).setOnClickListener(this); + } + + @Override + public void onClick(View v) { + final int id = v.getId(); + if (id == R.id.actionbar_notification) { + TCAgent.onEvent(getActivity(), "主页", "关注图标"); + + Map map = new HashMap(); + map.put("location", "关注图标"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "主页"); + DataCollectionManager.onEvent(getActivity(), "click-item", map); + + startActivity(new Intent(getActivity(), ConcernActivity.class)); + } else if (id == R.id.actionbar_rl_download) { + TCAgent.onEvent(getActivity(), "主页", "下载图标"); + + Map map = new HashMap(); + map.put("location", "下载图标"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "主页"); + DataCollectionManager.onEvent(getActivity(), "click-item", map); + + if (downloadHint != null + && downloadHint.getVisibility() == View.VISIBLE) { + downloadHint.setVisibility(View.GONE); + EventBus.getDefault().post(new EBTopState("隐藏", null)); + } + startActivity(new Intent(getActivity(), + DownloadManagerActivity.class)); + } else if (id == R.id.actionbar_search_input) { + TCAgent.onEvent(getActivity(), "主页", "搜索框"); + + Map map = new HashMap(); + map.put("location", "搜索框"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "主页"); + DataCollectionManager.onEvent(getActivity(), "click-item", map); + + Intent goSearch = new Intent(getActivity(), SearchActivity.class); + goSearch.putExtra("clicked", false); + goSearch.putExtra("hint", hint); + startActivity(goSearch); + } else if (id == R.id.actionbar_iv_search) { + TCAgent.onEvent(getActivity(), "主页", "搜索图标"); + + Map map = new HashMap(); + map.put("location", "搜索图标"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "主页"); + DataCollectionManager.onEvent(getActivity(), "click-item", map); + + Intent searchIntent = new Intent(getActivity(), + SearchActivity.class); + searchIntent.putExtra("clicked", true); + searchIntent.putExtra("hint", hint); + startActivity(searchIntent); + } else if (id == R.id.actionbar_overflow) { + TCAgent.onEvent(getActivity(), "主页", "更多图标"); + + Map map = new HashMap(); + map.put("location", "更多图标"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "主页"); + DataCollectionManager.onEvent(getActivity(), "click-item", map); + + popUpOverflow(v); + } else if (id == R.id.menu_rl_set) { + popWindow.dismiss(); + startActivity(new Intent(getActivity(), SettingActivity.class)); + } else if (id == R.id.reuse_no_connection) { + reuse_no_connection.setVisibility(View.GONE); + recyclerview.setVisibility(View.VISIBLE); + adapter = new HomeFragmentAdapter(getActivity(), gameMap, + locationMap, nameMap, platformMap, reuse_no_connection, + recyclerview, handler, lastTimeMap, statusMap, + dismissEntity); + recyclerview.setAdapter(adapter); + } + } + + public void updateRedDot(int type) { + int downloadSize = DownloadManager.getInstance(getActivity()).getAll() + .size(); + if (type == 1 && downloadSize == 0) { + downloadHint.setVisibility(View.VISIBLE); + downloadHint.setText((downloadSize + type) + ""); + int width = DisplayUtils.dip2px(getActivity(), 12); + RelativeLayout.LayoutParams rparams = new RelativeLayout.LayoutParams( + width, width); + rparams.topMargin = DisplayUtils.dip2px(getActivity(), 8); + rparams.rightMargin = DisplayUtils.dip2px(getActivity(), 2); + rparams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + downloadHint.setLayoutParams(rparams); + } else if (type == -1 && (downloadSize == 0 || downloadSize == 1)) { + int updateSize = PackageManager.getUpdateList().size(); + if (updateSize != 0) { + downloadHint.setVisibility(View.VISIBLE); + downloadHint.setText(""); + int width = DisplayUtils.dip2px(getActivity(), 10); + RelativeLayout.LayoutParams rparams = new RelativeLayout.LayoutParams( + width, width); + rparams.topMargin = DisplayUtils.dip2px(getActivity(), 8); + rparams.rightMargin = DisplayUtils.dip2px(getActivity(), 3); + rparams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + downloadHint.setLayoutParams(rparams); + } else { + downloadHint.setVisibility(View.GONE); + } + } else if (downloadSize != 0) { + downloadHint.setVisibility(View.VISIBLE); + downloadHint.setText((downloadSize + type) + ""); + } + } + + private void popUpOverflow(View view) { + + Rect frame = new Rect(); + getActivity().getWindow().getDecorView() + .getWindowVisibleDisplayFrame(frame); + + int xOffset = DisplayUtils.dip2px(getActivity(), 5); + int yOffset = frame.top + DisplayUtils.dip2px(getActivity(), 48) + + xOffset; + + View popView = View.inflate(getActivity(), R.layout.menu_popwindow, + null); + popView.findViewById(R.id.menu_rl_set).setOnClickListener(this); + popWindow = new PopupWindow(popView, LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT, true); + + popWindow.setOutsideTouchable(true); + popWindow.setAnimationStyle(android.R.style.Animation_Dialog); + popWindow.setBackgroundDrawable(getResources().getDrawable( + R.drawable.shape)); + + popWindow.showAtLocation(view, Gravity.TOP | Gravity.RIGHT, xOffset, + yOffset); + + } + + public void onEventMainThread(EBPWDismiss dismiss) { + if (dismissEntity != null) { + dismissEntity.setShow(false); + } + } + + public void onEventMainThread(EBDownloadDelete busThree) { + LinkedBlockingQueue queue = platformMap.get(busThree.getName()); + if (queue != null) { + queue.remove(busThree.getPlatform()); + platformMap.put(busThree.getName(), queue); + } + boolean isRemove = false; + for (GameEntity detailedEntity : adapter.getZuixinchajianList()) { + if (detailedEntity.getName().equals(busThree.getName())) { + if (TextUtils.isEmpty(busThree.getPlatform())) { + detailedEntity.getEntryMap().remove("官方版"); + } else { + detailedEntity.getEntryMap().remove(busThree.getPlatform()); + } + isRemove = true; + break; + } + } + if (!isRemove) { + for (GameEntity detailedEntity : adapter.getRemenkapaiList()) { + if (detailedEntity.getName().equals(busThree.getName())) { + if (TextUtils.isEmpty(busThree.getPlatform())) { + detailedEntity.getEntryMap().remove("官方版"); + } else { + detailedEntity.getEntryMap().remove( + busThree.getPlatform()); + } + isRemove = true; + break; + } + } + } + if (!isRemove) { + for (GameEntity detailedEntity : adapter.getXincekapaiList()) { + if (detailedEntity.getName().equals(busThree.getName())) { + if (TextUtils.isEmpty(busThree.getPlatform())) { + detailedEntity.getEntryMap().remove("官方版"); + } else { + detailedEntity.getEntryMap().remove( + busThree.getPlatform()); + } + isRemove = true; + break; + } + } + } + Integer location = locationMap.get(busThree.getName()); + if (location != null) { + adapter.notifyItemChanged(location.intValue()); + } + } + + public void onEventMainThread(EBTopState busTen) { + if ("搜索".equals(busTen.getType())) { + hint = busTen.getSearchHint(); + searchHint.setHint(busTen.getSearchHint()); + } else if ("显示".equals(busTen.getType())) { + if (downloadHint != null) { + downloadHint.setVisibility(View.VISIBLE); + } + } else { + if (downloadHint != null) { + downloadHint.setVisibility(View.GONE); + } + } + } + + public void onEventMainThread(EBRedDot busEight) { + updateRedDot(busEight.getType()); + } + + public void onEventMainThread(EBNetworkState busNetworkState) { + if (busNetworkState.isNetworkConnected() + && reuse_no_connection.getVisibility() == View.VISIBLE) { + reuse_no_connection.setVisibility(View.GONE); + recyclerview.setVisibility(View.VISIBLE); + adapter = new HomeFragmentAdapter(getActivity(), gameMap, + locationMap, nameMap, platformMap, reuse_no_connection, + recyclerview, handler, lastTimeMap, statusMap, + dismissEntity); + recyclerview.setAdapter(adapter); + } + } + + public void onEventMainThread(EBUISwitch busNine) { + if ("MainActivity".equals(busNine.getFrom())) { + currentItem = busNine.getPosition(); + if (busNine.getPosition() == 0) { + adapter.startAutoScroll(); + } else { + adapter.stopAutoScroll(); + statusMap.clear(); + } + } + } + + public void onEventMainThread(EBPackage busFour) { + String name = nameMap.get(busFour.getPackageName()); + if (name != null) { + int location = locationMap.get(name).intValue(); + if ("安装".equals(busFour.getType())) { + GameEntity detailedEntity = getEntityByLocation(location); + for (ApkEntity apkEntity : detailedEntity.getApk()) { + if (apkEntity.getPackageName().equals( + busFour.getPackageName())) { + if (detailedEntity.getEntryMap() != null) { + detailedEntity.getEntryMap().remove( + apkEntity.getPlatform()); + adapter.notifyItemChanged(location); + return; + } + } + } + } else if ("卸载".equals(busFour.getType())) { + adapter.notifyItemChanged(location); + } + } + } + + private GameEntity getEntityByLocation(int location) { + GameEntity entity = null; + if (location > adapter.getPosition_zuixinchajian() + && location <= adapter.getZuixinchajianListSize() + + adapter.getPosition_zuixinchajian()) { + entity = adapter.getZuixinchajianList().get( + location - adapter.getPosition_zuixinchajian() - 1); + } else if (location > adapter.getPosition_remenkapai() + && location <= adapter.getRemenkapaiListSize() + + adapter.getPosition_remenkapai()) { + entity = adapter.getRemenkapaiList().get( + location - adapter.getPosition_remenkapai() - 1); + } else if (location > adapter.getPosition_xincekapai() + && location <= adapter.getXincekapaiListSize() + + adapter.getPosition_xincekapai()) { + entity = adapter.getXincekapaiList().get( + location - adapter.getPosition_xincekapai() - 1); + } + return entity; + } + + @Override + public void onResume() { + + super.onResume(); + if (isEverpause) { + // 黄壮华 添加 初始化游戏状态 修改2015/8/20 + DownloadItemUtils.initializeGameMap(getActivity(), gameMap); + List zList = new ArrayList(); + if (adapter.getZuixinchajianList() != null) { + for (GameEntity entity : adapter.getZuixinchajianList()) { + entity.setEntryMap(gameMap.get(entity.getName())); + zList.add(entity); + } + } + List rList = new ArrayList(); + if (adapter.getRemenkapaiList() != null) { + for (GameEntity entity : adapter.getRemenkapaiList()) { + entity.setEntryMap(gameMap.get(entity.getName())); + rList.add(entity); + } + } + List xList = new ArrayList(); + if (adapter.getXincekapaiList() != null) { + for (GameEntity entity : adapter.getXincekapaiList()) { + entity.setEntryMap(gameMap.get(entity.getName())); + xList.add(entity); + } + } + adapter.setList(zList, rList, xList); + } + isEverpause = false; + DownloadManager.getInstance(getActivity()).addObserver(dataWatcher); + if (currentItem == 0) { + adapter.startAutoScroll(); + } + } + + @Override + public void onPause() { + super.onPause(); + isEverpause = true; + statusMap.clear(); + DownloadManager.getInstance(getActivity()).removeObserver(dataWatcher); + if (currentItem == 0) { + adapter.stopAutoScroll(); + } + } + + @Override + public void onDestroy() { + + super.onDestroy(); + isDestroy = true; + AppController.canclePendingRequests(HomeFragment.class); + EventBus.getDefault().unregister(this); + view = null; + recyclerview = null; + adapter = null; + downloadHint = null; + searchHint = null; + reuse_no_connection = null; + locationMap = null; + gameMap = null; + platformMap = null; + nameMap = null; + hint = null; + lastTimeMap = null; + statusMap = null; + dismissEntity = null; + popWindow = null; + handler = null; + dataWatcher = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/home/HomeFragmentAdapter.java b/app/src/main/java/com/gh/gamecenter/home/HomeFragmentAdapter.java new file mode 100644 index 0000000000..8d9cbacb8b --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/home/HomeFragmentAdapter.java @@ -0,0 +1,2391 @@ +package com.gh.gamecenter.home; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.concurrent.LinkedBlockingQueue; + +import org.json.JSONArray; + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Handler; +import android.support.v4.app.FragmentActivity; +import android.support.v4.util.ArrayMap; +import android.support.v4.view.ViewPager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.util.DisplayMetrics; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.ImageView.ScaleType; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.volley.NoConnectionError; +import com.android.volley.Response; +import com.android.volley.TimeoutError; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.common.util.DisplayUtils; +import com.gh.common.util.DownloadItemUtils; +import com.gh.common.util.GameViewUtils; +import com.gh.common.util.ImageUtils; +import com.gh.common.util.NewsUtils; +import com.gh.common.util.TimestampUtils; +import com.gh.common.view.AutoScrollViewPager; +import com.gh.download.DownloadEntry; +import com.gh.gamecenter.GameActivity; +import com.gh.gamecenter.GameDetailsActivity; +import com.gh.gamecenter.HotCardActivity; +import com.gh.gamecenter.NewsOrRaidersActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.adapter.RecyclingPagerAdapter; +import com.gh.gamecenter.adapter.viewholder.FooterViewHolder; +import com.gh.gamecenter.db.info.ConcernInfo; +import com.gh.gamecenter.db.info.GameInfo; +import com.gh.gamecenter.entity.ApkEntity; +import com.gh.gamecenter.entity.DismissEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.entity.NewsEntity; +import com.gh.gamecenter.eventbus.EBSkipNewPlugin; +import com.gh.gamecenter.manager.ConcernManager; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.manager.GameManager; +import com.gh.gamecenter.volley.extended.JsonArrayExtendedRequest; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.tendcloud.tenddata.TCAgent; + +import de.greenrobot.event.EventBus; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-8-8 + * @update 2015-8-20 + * @des 首页fragment适配器 + */ + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-8-8 + * @update 2015-8-20 + * @des 首页fragment适配器 + */ +public class HomeFragmentAdapter extends + RecyclerView.Adapter { + + private FragmentActivity activity; + private Context context; + private LayoutInflater layoutInflater; + + private class ITEM_TYPE { + public static final int navigation = 0;// 导航栏布局 + public static final int head = 1;// 首部简介布局 + public static final int news_image_type1 = 2;// 图片新闻类型 + public static final int news_image_type2 = 3;// 图片新闻类型 + public static final int news_text_type = 4;// 标题新闻类型 + public static final int game_type1 = 5; + public static final int game_type2 = 6; + public static final int loading = 7; + } + + private int position_kapaitoutiao = -1;// 卡牌头条版块的position + private int position_zuixinchajian = -1;// 最新插件版块的position + private int position_yuedujingxuan = -1;// 阅读精选版块的position + private int position_remenkapai = -1;// 热门卡牌版块的position + private int position_kapaigonglue = -1;// 卡牌攻略版块的position + private int position_xincekapai = -1;// 新测头条版块的position + + private int kapaitoutiaoSize = 0; + private List shoulanKapaitoutiaoList; + private List cilanKapaitoutiaoList; + private List zuixinchajianList; + private List yuedujingxuanList; + private List remenkapaiList; + private List kapaigonglueList; + private List xincekapaiList; + + private List allKapaigonglueList; + private List allNewsList; + private List concernList; + private ArrayMap> allKapaigonglueMap; + + // 黄壮华 获取引用 修改2015/8/19 + private ArrayMap> gameMap; + private ArrayMap locationMap; + private ArrayMap nameMap; + private ArrayMap> platformMap; + + private RecyclerView recyclerview; + private LinearLayout reuse_no_connection; + + private int flag; + private int width; + + private boolean isRemove; + + private Handler handler; + private ArrayMap lastTimeMap; + private ArrayMap statusMap; + + private DismissEntity dismissEntity; + + public HomeFragmentAdapter(FragmentActivity act, + ArrayMap> gMap, + ArrayMap lMap, ArrayMap nMap, + ArrayMap> pMap, + LinearLayout linearLayout, RecyclerView recyclerview, + Handler hdler, ArrayMap ltMap, + ArrayMap sMap, DismissEntity dEntity) { + + flag = 6; + isRemove = false; + + shoulanKapaitoutiaoList = new ArrayList(); + cilanKapaitoutiaoList = new ArrayList(); + zuixinchajianList = new ArrayList(); + yuedujingxuanList = new ArrayList(); + remenkapaiList = new ArrayList(); + kapaigonglueList = new ArrayList(); + xincekapaiList = new ArrayList(); + + // 黄壮华 获取引用 修改2015/8/19 + handler = hdler; + lastTimeMap = ltMap; + statusMap = sMap; + gameMap = gMap; + locationMap = lMap; + nameMap = nMap; + platformMap = pMap; + + dismissEntity = dEntity; + + reuse_no_connection = linearLayout; + this.recyclerview = recyclerview; + + activity = act; + context = act; + layoutInflater = LayoutInflater.from(act); + + DisplayMetrics outMetrics = new DisplayMetrics(); + activity.getWindowManager().getDefaultDisplay().getMetrics(outMetrics); + width = outMetrics.widthPixels; + + initKapaitoutiao(); + + initZuixinchajian(); + + initYuedujingxuan(); + + initRemenkapai(); + + initKapaigonglue(); + + initXincekapai(); + } + + public void initKapaitoutiao() { + JsonArrayExtendedRequest kapaitoutiaoRequest = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + + "v1d45/index/kapaitoutiao", Constants.NEWS_CD), + new Response.Listener() { + @Override + public void onResponse(JSONArray response) { + Type listType = new TypeToken>() { + }.getType(); + Gson gson = new Gson(); + List list = gson.fromJson( + response.toString(), listType); + for (int i = 0; i < list.size(); i++) { + if (list.get(i).getThumb() != null) { + shoulanKapaitoutiaoList.add(list.get(i)); + } else { + cilanKapaitoutiaoList.add(list.get(i)); + } + } + kapaitoutiaoSize = cilanKapaitoutiaoList.size() + + (shoulanKapaitoutiaoList.isEmpty() ? 0 : 1); + refreshCounts(); + + if (flag != 1) { + flag--; + } else { + isRemove = true; + notifyItemRemoved(getItemCount()); + initLocationMap(); + } + } + + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + // 无网络连接和访问超时 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + Toast.makeText(context, "网络错误", Toast.LENGTH_SHORT) + .show(); + reuse_no_connection.setVisibility(View.VISIBLE); + recyclerview.setVisibility(View.GONE); + } + } + }); + AppController + .addToRequestQueue(kapaitoutiaoRequest, HomeFragment.class); + } + + private void initZuixinchajian() { + JsonArrayExtendedRequest zuixinchajianRequest = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + + "v1d45/index/zuixinchajian", Constants.GAME_CD), + new Response.Listener() { + @Override + public void onResponse(JSONArray response) { + + GameManager manager = new GameManager(context); + initZuixinchajianList(response, manager); + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + + // 无网络连接和访问超时 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + Toast.makeText(context, "网络错误", Toast.LENGTH_SHORT) + .show(); + reuse_no_connection.setVisibility(View.VISIBLE); + recyclerview.setVisibility(View.GONE); + } + } + }); + AppController.addToRequestQueue(zuixinchajianRequest, + HomeFragment.class); + } + + private void initYuedujingxuan() { + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + + "v1d45/index/yuedujingxuan", Constants.NEWS_CD), + new Response.Listener() { + + @Override + public void onResponse(JSONArray response) { + Type listType = new TypeToken>() {}.getType(); + Gson gson = new Gson(); + yuedujingxuanList = gson.fromJson(response.toString(), listType); + + refreshCounts(); + + if (flag != 1) { + flag--; + } else { + isRemove = true; + notifyItemRemoved(getItemCount()); + initLocationMap(); + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + // 无网络连接和访问超时 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + Toast.makeText(context, "网络错误", Toast.LENGTH_SHORT) + .show(); + reuse_no_connection.setVisibility(View.VISIBLE); + recyclerview.setVisibility(View.GONE); + } + } + }); + AppController.addToRequestQueue(request, HomeFragment.class); + } + + private void initRemenkapai() { + JsonArrayExtendedRequest remenkapaiRequest = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + + "v1d45/index/remenkapai", Constants.GAME_CD), + new Response.Listener() { + @Override + public void onResponse(JSONArray response) { + + GameManager manager = new GameManager(context); + initRemenkapaiList(response, manager); + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + + // 无网络连接和访问超时 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + Toast.makeText(context, "网络错误", Toast.LENGTH_SHORT) + .show(); + reuse_no_connection.setVisibility(View.VISIBLE); + recyclerview.setVisibility(View.GONE); + } + } + }); + AppController.addToRequestQueue(remenkapaiRequest, HomeFragment.class); + } + + private void initXincekapai() { + JsonArrayExtendedRequest xincekapaiRequest = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + + "v1d45/index/xincekapai", Constants.GAME_CD), + new Response.Listener() { + @Override + public void onResponse(JSONArray response) { + + GameManager manager = new GameManager(context); + initXincekapaiList(response, manager); + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + + // 无网络连接和访问超时 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + Toast.makeText(context, "网络错误", Toast.LENGTH_SHORT) + .show(); + reuse_no_connection.setVisibility(View.VISIBLE); + recyclerview.setVisibility(View.GONE); + } + } + }); + AppController.addToRequestQueue(xincekapaiRequest, HomeFragment.class); + } + + private void initKapaigonglue() { + ConcernManager concernManager = new ConcernManager(context); + List list = concernManager.getAllConcernBySort(); + if (list.size() > 5) { + concernList = new ArrayList(); + for (int i = 0; i < 3; i++) { + concernList.add(list.remove(0)); + } + int[] index = new int[2]; + Random random = new Random(System.currentTimeMillis()); + for (int i = 0; i < 2; i++) { + if (i == 0) { + index[i] = random.nextInt(list.size()); + } else { + random(random, index, i, list.size()); + } + } + concernList.add(list.get(index[0])); + concernList.add(list.get(index[1])); + } else { + concernList = list; + } + + if (concernList.isEmpty()) { + getKaipaigonglueByUrl(); + } else { + getKaipaigonglueByList(); + } + + } + + private int count; + + private void getKaipaigonglueByList() { + allKapaigonglueList = new ArrayList(); + allKapaigonglueMap = new ArrayMap>(); + count = concernList.size(); + for (int i = 0, size = concernList.size(); i < size; i++) { + final int index = i; + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp( + Config.HOST + "v1d45/game/" + + concernList.get(i).getId() + + "/news?limit=5&offset=0&type_group=" + + Uri.encode("攻略"), Constants.NEWS_CD), + new Response.Listener() { + @Override + public void onResponse(JSONArray response) { + + Gson gson = new Gson(); + Type listType = new TypeToken>() { + }.getType(); + List newsList = gson.fromJson( + response.toString(), listType); + if (!newsList.isEmpty()) { + allKapaigonglueMap.put(concernList.get(index) + .getGameName(), newsList); + allKapaigonglueList.addAll(newsList); + } + refresh(); + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + + // 无网络连接和访问超时 + if (error.getClass() + .equals(NoConnectionError.class) + || error.getClass().equals( + TimeoutError.class)) { + Toast.makeText(context, "网络错误", + Toast.LENGTH_SHORT).show(); + reuse_no_connection.setVisibility(View.VISIBLE); + recyclerview.setVisibility(View.GONE); + } + } + }); + AppController.addToRequestQueue(request, HomeFragment.class); + } + } + + private void refresh() { + if (count != 1) { + count--; + } else { + if (allKapaigonglueList.isEmpty() || allKapaigonglueList.size() < 5) { + getKaipaigonglueByUrl(); + } else { + if (allKapaigonglueList.size() > 5) { + ArrayMap> kapaigonglueMap = new ArrayMap>(); + Random random = new Random(System.currentTimeMillis()); + ArrayMap> map = new ArrayMap>(); + for (String key : allKapaigonglueMap.keySet()) { + List list = new ArrayList(); + for (NewsEntity entity : allKapaigonglueMap.get(key)) { + list.add(entity); + } + map.put(key, list); + } + int number = 0; + while (number < 5) { + for (int i = 0; i < concernList.size(); i++) { + List list = map.get(concernList.get(i) + .getGameName()); + if (list != null && !list.isEmpty() && number < 5) { + List entities = kapaigonglueMap + .get(concernList.get(i).getGameName()); + if (entities == null) { + entities = new ArrayList(); + kapaigonglueMap.put(concernList.get(i) + .getGameName(), entities); + } + entities.add(list.remove(random.nextInt(list + .size()))); + number++; + if (number == 5) { + break; + } + } + } + } + for (int i = 0; i < concernList.size(); i++) { + List list = kapaigonglueMap.get(concernList + .get(i).getGameName()); + if (list != null && !list.isEmpty()) { + kapaigonglueList.addAll(list); + } + } + } else { + kapaigonglueList.addAll(allKapaigonglueList); + } + refreshCounts(); + if (flag != 1) { + flag--; + } else { + isRemove = true; + notifyItemRemoved(getItemCount()); + initLocationMap(); + } + } + } + } + + private void refreshCounts() { + + // 卡牌头条 + if (kapaitoutiaoSize != 0) { + position_kapaitoutiao = 1; + } + + // 最新插件 + if (zuixinchajianList != null && !zuixinchajianList.isEmpty()) { + if (position_kapaitoutiao != -1) { + position_zuixinchajian = position_kapaitoutiao + + kapaitoutiaoSize + 1; + } else { + position_zuixinchajian = 1; + } + } + + // 阅读精选 + if (yuedujingxuanList != null && !yuedujingxuanList.isEmpty()) { + if (position_kapaitoutiao != -1 && position_zuixinchajian != -1) { + position_yuedujingxuan = position_zuixinchajian + + zuixinchajianList.size() + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian == -1) { + position_yuedujingxuan = position_kapaitoutiao + + kapaitoutiaoSize + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian != -1) { + position_yuedujingxuan = position_zuixinchajian + + zuixinchajianList.size() + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian == -1) { + position_yuedujingxuan = 1; + } + } + + // 热门卡牌 + if (remenkapaiList != null && !remenkapaiList.isEmpty()) { + if (position_kapaitoutiao != -1 && position_zuixinchajian != -1 + && position_yuedujingxuan != -1) { + position_remenkapai = position_yuedujingxuan + 1 + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan == -1) { + position_remenkapai = position_kapaitoutiao + kapaitoutiaoSize + + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan == -1) { + position_remenkapai = position_zuixinchajian + + zuixinchajianList.size() + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan != -1) { + position_remenkapai = position_yuedujingxuan + 1 + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan != -1) { + position_remenkapai = position_yuedujingxuan + 1 + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan != -1) { + position_remenkapai = position_yuedujingxuan + 1 + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan == -1) { + position_remenkapai = position_zuixinchajian + + zuixinchajianList.size() + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan == -1) { + position_remenkapai = 1; + } + } + + // 卡牌攻略 + if (kapaigonglueList != null && !kapaigonglueList.isEmpty()) { + if (position_kapaitoutiao != -1 && position_zuixinchajian != -1 + && position_yuedujingxuan != -1 + && position_remenkapai != -1) { + position_kapaigonglue = position_remenkapai + + remenkapaiList.size() + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan == -1 + && position_remenkapai == -1) { + position_kapaigonglue = position_kapaitoutiao + + kapaitoutiaoSize + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan == -1 + && position_remenkapai == -1) { + position_kapaigonglue = position_zuixinchajian + + zuixinchajianList.size() + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan != -1 + && position_remenkapai == -1) { + position_kapaigonglue = position_yuedujingxuan + 1 + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan == -1 + && position_remenkapai != -1) { + position_kapaigonglue = position_remenkapai + + remenkapaiList.size() + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan == -1 + && position_remenkapai == -1) { + position_kapaigonglue = position_zuixinchajian + + zuixinchajianList.size() + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan != -1 + && position_remenkapai == -1) { + position_kapaigonglue = position_yuedujingxuan + 1 + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan == -1 + && position_remenkapai != -1) { + position_kapaigonglue = position_remenkapai + + remenkapaiList.size() + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan != -1 + && position_remenkapai == -1) { + position_kapaigonglue = position_yuedujingxuan + 1 + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan == -1 + && position_remenkapai != -1) { + position_kapaigonglue = position_remenkapai + + remenkapaiList.size() + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan != -1 + && position_remenkapai != -1) { + position_kapaigonglue = position_remenkapai + + remenkapaiList.size() + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan != -1 + && position_remenkapai == -1) { + position_kapaigonglue = position_yuedujingxuan + 1 + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan == -1 + && position_remenkapai != -1) { + position_kapaigonglue = position_remenkapai + + remenkapaiList.size() + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan != -1 + && position_remenkapai != -1) { + position_kapaigonglue = position_remenkapai + + remenkapaiList.size() + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan != -1 + && position_remenkapai != -1) { + position_kapaigonglue = position_remenkapai + + remenkapaiList.size() + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan == -1 + && position_remenkapai == -1) { + position_kapaigonglue = 1; + } + } + + // 新测卡牌 + if (xincekapaiList != null && !xincekapaiList.isEmpty()) { + if (position_kapaitoutiao != -1 && position_zuixinchajian != -1 + && position_yuedujingxuan != -1 + && position_remenkapai != -1 && position_kapaigonglue != -1) { + position_xincekapai = position_kapaigonglue + + kapaigonglueList.size() + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan == -1 + && position_remenkapai == -1 && position_kapaigonglue == -1) { + position_xincekapai = position_kapaitoutiao + kapaitoutiaoSize + + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan == -1 + && position_remenkapai == -1 && position_kapaigonglue == -1) { + position_xincekapai = position_zuixinchajian + + zuixinchajianList.size() + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan != -1 + && position_remenkapai == -1 && position_kapaigonglue == -1) { + position_xincekapai = position_yuedujingxuan + 1 + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan == -1 + && position_remenkapai != -1 && position_kapaigonglue == -1) { + position_xincekapai = position_remenkapai + + remenkapaiList.size() + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan == -1 + && position_remenkapai == -1 && position_kapaigonglue != -1) { + position_xincekapai = position_kapaigonglue + + kapaigonglueList.size() + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan == -1 + && position_remenkapai == -1 && position_kapaigonglue == -1) { + position_xincekapai = position_zuixinchajian + + zuixinchajianList.size() + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan != -1 + && position_remenkapai == -1 && position_kapaigonglue == -1) { + position_xincekapai = position_yuedujingxuan + 1 + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan == -1 + && position_remenkapai != -1 && position_kapaigonglue == -1) { + position_xincekapai = position_remenkapai + + remenkapaiList.size() + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan == -1 + && position_remenkapai == -1 && position_kapaigonglue != -1) { + position_xincekapai = position_kapaigonglue + + kapaigonglueList.size() + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan != -1 + && position_remenkapai == -1 && position_kapaigonglue == -1) { + position_xincekapai = position_yuedujingxuan + 1 + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan == -1 + && position_remenkapai != -1 && position_kapaigonglue == -1) { + position_xincekapai = position_remenkapai + + remenkapaiList.size() + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan == -1 + && position_remenkapai == -1 && position_kapaigonglue != -1) { + position_xincekapai = position_kapaigonglue + + kapaigonglueList.size() + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan != -1 + && position_remenkapai != -1 && position_kapaigonglue == -1) { + position_xincekapai = position_remenkapai + + remenkapaiList.size() + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan != -1 + && position_remenkapai == -1 && position_kapaigonglue != -1) { + position_xincekapai = position_kapaigonglue + + kapaigonglueList.size() + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan == -1 + && position_remenkapai != -1 && position_kapaigonglue != -1) { + position_xincekapai = position_kapaigonglue + + kapaigonglueList.size() + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan != -1 + && position_remenkapai == -1 && position_kapaigonglue == -1) { + position_xincekapai = position_yuedujingxuan + 1 + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan == -1 + && position_remenkapai != -1 && position_kapaigonglue == -1) { + position_xincekapai = position_remenkapai + + remenkapaiList.size() + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan != -1 + && position_remenkapai != -1 && position_kapaigonglue == -1) { + position_xincekapai = position_remenkapai + + remenkapaiList.size() + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan != -1 + && position_remenkapai != -1 && position_kapaigonglue == -1) { + position_xincekapai = position_remenkapai + + remenkapaiList.size() + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan == -1 + && position_remenkapai == -1 && position_kapaigonglue != -1) { + position_xincekapai = position_kapaigonglue + + kapaigonglueList.size() + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan != -1 + && position_remenkapai == -1 && position_kapaigonglue != -1) { + position_xincekapai = position_kapaigonglue + + kapaigonglueList.size() + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan != -1 + && position_remenkapai == -1 && position_kapaigonglue != -1) { + position_xincekapai = position_kapaigonglue + + kapaigonglueList.size() + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan == -1 + && position_remenkapai != -1 && position_kapaigonglue != -1) { + position_xincekapai = position_kapaigonglue + + kapaigonglueList.size() + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan == -1 + && position_remenkapai != -1 && position_kapaigonglue != -1) { + position_xincekapai = position_kapaigonglue + + kapaigonglueList.size() + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan != -1 + && position_remenkapai != -1 && position_kapaigonglue != -1) { + position_xincekapai = position_kapaigonglue + + kapaigonglueList.size() + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan != -1 + && position_remenkapai != -1 && position_kapaigonglue != -1) { + position_xincekapai = position_kapaigonglue + + kapaigonglueList.size() + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan != -1 + && position_remenkapai != -1 && position_kapaigonglue != -1) { + position_xincekapai = position_kapaigonglue + + kapaigonglueList.size() + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan == -1 + && position_remenkapai != -1 && position_kapaigonglue != -1) { + position_xincekapai = position_kapaigonglue + + kapaigonglueList.size() + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan != -1 + && position_remenkapai == -1 && position_kapaigonglue != -1) { + position_xincekapai = position_kapaigonglue + + kapaigonglueList.size() + 1; + } else if (position_kapaitoutiao != -1 + && position_zuixinchajian != -1 + && position_yuedujingxuan != -1 + && position_remenkapai != -1 && position_kapaigonglue == -1) { + position_xincekapai = position_remenkapai + + remenkapaiList.size() + 1; + } else if (position_kapaitoutiao == -1 + && position_zuixinchajian == -1 + && position_yuedujingxuan == -1 + && position_remenkapai == -1 && position_kapaigonglue == -1) { + position_xincekapai = 1; + } + } + + notifyDataSetChanged(); + } + + protected void initXincekapaiList(JSONArray response, GameManager manager) { + Type listType = new TypeToken>() { + }.getType(); + Gson gson = new Gson(); + + // 黄壮华 初始化游戏状态 修改2015/8/19 + xincekapaiList = new ArrayList(); + List list = gson.fromJson(response.toString(), listType); + for (GameEntity entity : list) { + entity.setEntryMap(gameMap.get(entity.getName())); + xincekapaiList.add(entity); + if (entity.getApk() != null) { + for (ApkEntity apkEntity : entity.getApk()) { + manager.addOrUpdate(new GameInfo( + apkEntity.getPackageName(), entity.getId(), entity + .getName())); + } + } + } + + // 去除重复游戏 + for (int i = 0; i < xincekapaiList.size(); i++) { + String name = xincekapaiList.get(i).getName(); + for (int j = 0; j < remenkapaiList.size(); j++) { + if (name.equals(remenkapaiList.get(j).getName())) { + remenkapaiList.remove(j); + break; + } + } + } + + refreshCounts(); + if (flag != 1) { + flag--; + } else { + isRemove = true; + notifyItemRemoved(getItemCount()); + initLocationMap(); + } + } + + private void getKaipaigonglueByUrl() { + JsonArrayExtendedRequest kapaigonglueRequest = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp( + Config.HOST + + "v1d45/news?limit=20&offset=0&type_group=" + + Uri.encode("攻略"), Constants.NEWS_CD), + new Response.Listener() { + + @Override + public void onResponse(JSONArray response) { + + Type listType = new TypeToken>() { + }.getType(); + Gson gson = new Gson(); + allNewsList = gson.fromJson(response.toString(), + listType); + if (allKapaigonglueList == null + || allKapaigonglueList.isEmpty()) { + if (allNewsList.size() > 5) { + Random random = new Random(System + .currentTimeMillis()); + int[] index = new int[5]; + for (int i = 0; i < index.length; i++) { + if (i == 0) { + index[i] = random.nextInt(allNewsList + .size()); + } else { + index[i] = random(random, index, i, + allNewsList.size()); + } + } + for (int i = 0; i < index.length; i++) { + kapaigonglueList.add(allNewsList + .get(index[i])); + } + } else { + kapaigonglueList.addAll(allNewsList); + } + } else { + kapaigonglueList.addAll(allKapaigonglueList); + for (int i = 0; i < allKapaigonglueList.size(); i++) { + for (int j = 0; j < allNewsList.size(); j++) { + if (allKapaigonglueList.get(i).getId() + .equals(allNewsList.get(j).getId())) { + allNewsList.remove(j); + j--; + break; + } + } + } + if (allNewsList.size() > 5 - allKapaigonglueList + .size()) { + Random random = new Random(System + .currentTimeMillis()); + int[] index = new int[5 - allKapaigonglueList + .size()]; + for (int i = 0; i < index.length; i++) { + if (i == 0) { + index[i] = random.nextInt(allNewsList + .size()); + } else { + index[i] = random(random, index, i, + allNewsList.size()); + } + } + for (int i = 0; i < index.length; i++) { + kapaigonglueList.add(allNewsList + .get(index[i])); + } + } else { + kapaigonglueList.addAll(allNewsList); + } + } + refreshCounts(); + if (flag != 1) { + flag--; + } else { + isRemove = true; + notifyItemRemoved(getItemCount()); + initLocationMap(); + } + } + + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + + } + }); + AppController + .addToRequestQueue(kapaigonglueRequest, HomeFragment.class); + } + + public List getKapaigonglueList() { + return kapaigonglueList; + } + + public void refreshKapaigonglueList() { + kapaigonglueList.clear(); + if (allKapaigonglueList == null || allKapaigonglueList.isEmpty()) { + if (allNewsList.size() > 5) { + Random random = new Random(System.currentTimeMillis()); + int[] index = new int[5]; + for (int i = 0; i < index.length; i++) { + if (i == 0) { + index[i] = random.nextInt(allNewsList.size()); + } else { + index[i] = random(random, index, i, allNewsList.size()); + } + } + for (int i = 0; i < index.length; i++) { + kapaigonglueList.add(allNewsList.get(index[i])); + } + refreshCounts(); + } + } else if (allKapaigonglueList.size() < 5) { + if (allNewsList.size() > 5 - allKapaigonglueList.size()) { + kapaigonglueList.addAll(allKapaigonglueList); + Random random = new Random(System.currentTimeMillis()); + int[] index = new int[5 - allKapaigonglueList.size()]; + for (int i = 0; i < index.length; i++) { + if (i == 0) { + index[i] = random.nextInt(allNewsList.size()); + } else { + index[i] = random(random, index, i, allNewsList.size()); + } + } + for (int i = 0; i < index.length; i++) { + kapaigonglueList.add(allNewsList.get(index[i])); + } + refreshCounts(); + } + } else { + ArrayMap> kapaigonglueMap = new ArrayMap>(); + Random random = new Random(System.currentTimeMillis()); + ArrayMap> map = new ArrayMap>(); + for (String key : allKapaigonglueMap.keySet()) { + List list = new ArrayList(); + for (NewsEntity entity : allKapaigonglueMap.get(key)) { + list.add(entity); + } + map.put(key, list); + } + int number = 0; + while (number < 5) { + for (int i = 0; i < concernList.size(); i++) { + List list = map.get(concernList.get(i) + .getGameName()); + if (list != null && !list.isEmpty() && number < 5) { + List entities = kapaigonglueMap + .get(concernList.get(i).getGameName()); + if (entities == null) { + entities = new ArrayList(); + kapaigonglueMap.put(concernList.get(i) + .getGameName(), entities); + } + entities.add(list.remove(random.nextInt(list.size()))); + number++; + if (number == 5) { + break; + } + } + } + } + for (int i = 0; i < concernList.size(); i++) { + List list = kapaigonglueMap.get(concernList.get(i) + .getGameName()); + if (list != null && !list.isEmpty()) { + kapaigonglueList.addAll(list); + } + } + refreshCounts(); + } + } + + private int random(Random random, int[] index, int i, int size) { + int seed = random.nextInt(size); + for (int j = 0; j < i; j++) { + if (index[j] == seed) { + return random(random, index, i, size); + } + } + return seed; + } + + protected void initRemenkapaiList(JSONArray response, GameManager manager) { + Type listType = new TypeToken>() {}.getType(); + Gson gson = new Gson(); + + // 黄壮华 初始化游戏状态 修改2015/8/19 + remenkapaiList = new ArrayList(); + List list = gson.fromJson(response.toString(), listType); + for (GameEntity entity : list) { + entity.setEntryMap(gameMap.get(entity.getName())); + remenkapaiList.add(entity); + for (ApkEntity apkEntity : entity.getApk()) { + manager.addOrUpdate(new GameInfo(apkEntity.getPackageName(), + entity.getId(), entity.getName())); + } + } + + // 去除重复游戏 + for (int i = 0; i < zuixinchajianList.size(); i++) { + String name = zuixinchajianList.get(i).getName(); + for (int j = 0; j < remenkapaiList.size(); j++) { + if (name.equals(remenkapaiList.get(j).getName())) { + remenkapaiList.remove(j); + break; + } + } + } + for (int i = 0; i < xincekapaiList.size(); i++) { + String name = xincekapaiList.get(i).getName(); + for (int j = 0; j < remenkapaiList.size(); j++) { + if (name.equals(remenkapaiList.get(j).getName())) { + remenkapaiList.remove(j); + break; + } + } + } + + refreshCounts(); + if (flag != 1) { + flag--; + } else { + isRemove = true; + notifyItemRemoved(getItemCount()); + initLocationMap(); + } + } + + protected void initZuixinchajianList(JSONArray response, GameManager manager) { + Type listType = new TypeToken>() { + }.getType(); + Gson gson = new Gson(); + + // 黄壮华 初始化游戏状态 修改2015/8/19 + zuixinchajianList = new ArrayList(); + List list = gson.fromJson(response.toString(), listType); + for (GameEntity entity : list) { + entity.setEntryMap(gameMap.get(entity.getName())); + zuixinchajianList.add(entity); + for (ApkEntity apkEntity : entity.getApk()) { + manager.addOrUpdate(new GameInfo(apkEntity.getPackageName(), + entity.getId(), entity.getName())); + } + } + + // 去除重复游戏 + for (int i = 0; i < zuixinchajianList.size(); i++) { + String name = zuixinchajianList.get(i).getName(); + for (int j = 0; j < remenkapaiList.size(); j++) { + if (name.equals(remenkapaiList.get(j).getName())) { + remenkapaiList.remove(j); + break; + } + } + } + + refreshCounts(); + if (flag != 1) { + flag--; + } else { + isRemove = true; + notifyItemRemoved(getItemCount()); + initLocationMap(); + } + } + + private void initLocationMap() { + locationMap.clear(); + GameEntity detailedEntity; + for (int i = 0, size = zuixinchajianList.size(); i < size; i++) { + detailedEntity = zuixinchajianList.get(i); + locationMap.put(detailedEntity.getName(), i + + position_zuixinchajian + 1); + for (ApkEntity apkEntity : detailedEntity.getApk()) { + nameMap.put(apkEntity.getPackageName(), + detailedEntity.getName()); + } + } + for (int i = 0, size = remenkapaiList.size(); i < size; i++) { + detailedEntity = remenkapaiList.get(i); + locationMap.put(detailedEntity.getName(), i + position_remenkapai + + 1); + for (ApkEntity apkEntity : detailedEntity.getApk()) { + nameMap.put(apkEntity.getPackageName(), + detailedEntity.getName()); + } + } + for (int i = 0, size = xincekapaiList.size(); i < size; i++) { + detailedEntity = xincekapaiList.get(i); + locationMap.put(detailedEntity.getName(), i + position_xincekapai + + 1); + for (ApkEntity apkEntity : detailedEntity.getApk()) { + nameMap.put(apkEntity.getPackageName(), + detailedEntity.getName()); + } + } + } + + @Override + public int getItemCount() { + int head = 0; + if (position_kapaitoutiao != -1) { + head++; + } + if (position_zuixinchajian != -1) { + head++; + } + if (position_yuedujingxuan != -1) { + head += 2; + } + if (position_remenkapai != -1) { + head++; + } + if (position_kapaigonglue != -1) { + head++; + } + if (position_xincekapai != -1) { + head++; + } + + if (isRemove) { + return 1 + head + kapaitoutiaoSize + zuixinchajianList.size() + + remenkapaiList.size() + kapaigonglueList.size() + + xincekapaiList.size(); + } else { + return 1 + head + kapaitoutiaoSize + zuixinchajianList.size() + + remenkapaiList.size() + kapaigonglueList.size() + + xincekapaiList.size() + 1; + } + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, + int viewType) { + if (viewType == ITEM_TYPE.navigation) { + return new NavigationViewHolder(layoutInflater.inflate( + R.layout.home_list_item_navigation, parent, false)); + } else if (viewType == ITEM_TYPE.head) { + return new HeadViewHolder(layoutInflater.inflate( + R.layout.home_list_item_head, parent, false)); + } else if (viewType == ITEM_TYPE.news_image_type1) { + return new ImageNewsTypeViewHolder(layoutInflater.inflate( + R.layout.home_autoscrollviewpager, parent, false)); + } else if (viewType == ITEM_TYPE.news_image_type2) { + View view = layoutInflater.inflate( + R.layout.home_autoscrollviewpager, parent, false); + ViewGroup.LayoutParams params = new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(context, 92)); + view.setLayoutParams(params); + return new GenuineNewsTypeViewHolder(view); + } else if (viewType == ITEM_TYPE.news_text_type) { + return new TextNewsTypeViewHolder(layoutInflater.inflate( + R.layout.home_list_item_newsnormal_type, parent, false)); + } else if (viewType == ITEM_TYPE.game_type1) { + return new GameNormalViewHolder(layoutInflater.inflate( + R.layout.home_list_item_gamenormal_type, parent, false)); + } else if (viewType == ITEM_TYPE.game_type2) { + return new GameTestViewHolder(layoutInflater.inflate( + R.layout.home_list_item_gametest_type, parent, false)); + } else { + return new FooterViewHolder(layoutInflater.inflate( + R.layout.refresh_footerview, parent, false)); + } + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, + int position) { + if (viewHolder instanceof HeadViewHolder) { + ((HeadViewHolder) viewHolder).initViewHolder(position); + } else if (viewHolder instanceof ImageNewsTypeViewHolder) { + ((ImageNewsTypeViewHolder) viewHolder).initViewHolder(position); + } else if (viewHolder instanceof GenuineNewsTypeViewHolder) { + ((GenuineNewsTypeViewHolder) viewHolder).initViewHolder(position); + } else if (viewHolder instanceof TextNewsTypeViewHolder) { + ((TextNewsTypeViewHolder) viewHolder).initViewHolder(position); + } else if (viewHolder instanceof GameNormalViewHolder) { + ((GameNormalViewHolder) viewHolder).initViewHolder(position); + } else if (viewHolder instanceof GameTestViewHolder) { + ((GameTestViewHolder) viewHolder).initViewHolder(position); + } + } + + @Override + public int getItemViewType(int position) { + if (position == 0) + return ITEM_TYPE.navigation; + + if (position_kapaitoutiao != -1) { + // 卡牌头条有数据 + if (position == position_kapaitoutiao) { + return ITEM_TYPE.head; + } + if (shoulanKapaitoutiaoList.isEmpty()) { + if (position > position_kapaitoutiao + && position <= position_kapaitoutiao + kapaitoutiaoSize) { + return ITEM_TYPE.news_text_type; + } + } else { + if (position == position_kapaitoutiao + 1) { + return ITEM_TYPE.news_image_type1; + } + if (position > position_kapaitoutiao + 1 + && position <= position_kapaitoutiao + kapaitoutiaoSize) { + return ITEM_TYPE.news_text_type; + } + } + } + + if (position_zuixinchajian != -1) { + // 最新插件有数量 + if (position == position_zuixinchajian) { + return ITEM_TYPE.head; + } + if (position > position_zuixinchajian + && position <= position_zuixinchajian + + zuixinchajianList.size()) { + return ITEM_TYPE.game_type1; + } + } + + if (position_yuedujingxuan != -1) { + // 阅读精选有数据 + if (position == position_yuedujingxuan) { + return ITEM_TYPE.head; + } + if (position == position_yuedujingxuan + 1) { + return ITEM_TYPE.news_image_type2; + } + } + + if (position_remenkapai != -1) { + // 热门卡牌有数据 + if (position == position_remenkapai) { + return ITEM_TYPE.head; + } + if (position > position_remenkapai + && position <= position_remenkapai + remenkapaiList.size()) { + return ITEM_TYPE.game_type1; + } + } + + if (position_kapaigonglue != -1) { + // 卡牌攻略有数据 + if (position == position_kapaigonglue) { + return ITEM_TYPE.head; + } + if (position > position_kapaigonglue + && position <= position_kapaigonglue + + kapaigonglueList.size()) { + return ITEM_TYPE.news_text_type; + } + } + + if (position_xincekapai != -1) { + // 新测卡牌有数据 + if (position == position_xincekapai) { + return ITEM_TYPE.head; + } + if (position > position_xincekapai + && position <= position_xincekapai + xincekapaiList.size()) { + return ITEM_TYPE.game_type2; + } + } + return ITEM_TYPE.loading; + } + + public class NavigationViewHolder extends RecyclerView.ViewHolder { + public ImageView gameImg; + public ImageView newsImg; + public ImageView gonglueImg; + public ImageView databaseImg; + + public NavigationViewHolder(View v) { + super(v); + gameImg = (ImageView) v.findViewById(R.id.game_img); + newsImg = (ImageView) v.findViewById(R.id.news_img); + gonglueImg = (ImageView) v.findViewById(R.id.gonglue_img); + databaseImg = (ImageView) v.findViewById(R.id.database_img); + + gameImg.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + TCAgent.onEvent(context, "主页", "游戏栏目"); + + Map map = new HashMap(); + map.put("location", "游戏"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "主页"); + DataCollectionManager.onEvent(context, "click-item", map); + + Intent intent = new Intent(context, GameActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + }); + newsImg.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + TCAgent.onEvent(context, "主页", "资讯栏目"); + + Map map = new HashMap(); + map.put("location", "资讯"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "主页"); + DataCollectionManager.onEvent(context, "click-item", map); + + Intent intent = new Intent(context, + NewsOrRaidersActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra("type", "资讯"); + context.startActivity(intent); + + } + }); + gonglueImg.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + TCAgent.onEvent(context, "主页", "攻略栏目"); + + Map map = new HashMap(); + map.put("location", "攻略"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "主页"); + DataCollectionManager.onEvent(context, "click-item", map); + + Intent intent = new Intent(context, + NewsOrRaidersActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra("type", "攻略"); + context.startActivity(intent); + } + }); + databaseImg.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + TCAgent.onEvent(context, "主页", "数据库栏目"); + + Map map = new HashMap(); + map.put("location", "数据库"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "主页"); + DataCollectionManager.onEvent(context, "click-item", map); + + Toast.makeText(context, "敬请期待", Toast.LENGTH_SHORT).show(); + // Intent intent = new Intent(context, + // DatabaseActivity.class); + // intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + // context.startActivity(intent); + + } + }); + } + } + + public class HeadViewHolder extends RecyclerView.ViewHolder { + public ImageView thumb; + public TextView title; + public LinearLayout link; + + public HeadViewHolder(View view) { + super(view); + this.thumb = (ImageView) view.findViewById(R.id.head_thumb); + this.title = (TextView) view.findViewById(R.id.head_title); + this.link = (LinearLayout) view.findViewById(R.id.head_link); + } + + public void initViewHolder(int position) { + if (position == position_kapaitoutiao) { + title.setText("卡牌头条"); + thumb.setBackgroundResource(R.drawable.home_kapaitoutiao); + link.setVisibility(View.VISIBLE); + link.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + TCAgent.onEvent(context, "更多>", "卡牌头条"); + + Map map = new HashMap(); + map.put("location", "卡牌头条-更多"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "主页"); + DataCollectionManager.onEvent(context, "click-item", + map); + + Intent intent = new Intent(context, + NewsOrRaidersActivity.class); + intent.putExtra("type", "资讯"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + }); + } else if (position == position_zuixinchajian) { + title.setText("最新插件"); + thumb.setBackgroundResource(R.drawable.home_zuixinchajian); + link.setVisibility(View.VISIBLE); + link.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + TCAgent.onEvent(context, "更多>", "最新插件"); + + Map map = new HashMap(); + map.put("location", "最新插件-更多"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "主页"); + DataCollectionManager.onEvent(context, "click-item", + map); + + EventBus.getDefault().post(new EBSkipNewPlugin(0)); + } + }); + } else if (position == position_yuedujingxuan) { + title.setText("阅读精选"); + thumb.setBackgroundResource(R.drawable.home_yuedujingxuan); + link.setVisibility(View.GONE); + } else if (position == position_remenkapai) { + title.setText("热门卡牌"); + thumb.setBackgroundResource(R.drawable.home_remenkapai); + link.setVisibility(View.VISIBLE); + link.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + TCAgent.onEvent(context, "更多>", "热门卡牌"); + + Map map = new HashMap(); + map.put("location", "热门卡牌-更多"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "主页"); + DataCollectionManager.onEvent(context, "click-item", + map); + + Intent intent = new Intent(context, + HotCardActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + }); + } else if (position == position_kapaigonglue) { + title.setText("卡牌攻略"); + thumb.setBackgroundResource(R.drawable.home_kapaigonglue); + link.setVisibility(View.VISIBLE); + link.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + TCAgent.onEvent(context, "更多>", "卡牌攻略"); + + Map map = new HashMap(); + map.put("location", "卡牌攻略-更多"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "主页"); + DataCollectionManager.onEvent(context, "click-item", + map); + + Intent intent = new Intent(context, + NewsOrRaidersActivity.class); + intent.putExtra("type", "攻略"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + }); + } else if (position == position_xincekapai) { + thumb.setBackgroundResource(R.drawable.home_xincekapai); + title.setText("新测卡牌"); + link.setVisibility(View.VISIBLE); + link.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + TCAgent.onEvent(context, "更多>", "新测卡牌"); + + Map map = new HashMap(); + map.put("location", "新测卡牌-更多"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "主页"); + DataCollectionManager.onEvent(context, "click-item", + map); + + Intent intent = new Intent(context, GameActivity.class); + intent.putExtra("tab", 1); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + }); + } + } + } + + public class ImageNewsTypeViewHolder extends RecyclerView.ViewHolder { + private AutoScrollViewPager home_viewpager; + private LinearLayout home_viewpager_ll_hint; + + public ImageNewsTypeViewHolder(View v) { + super(v); + home_viewpager = (AutoScrollViewPager) v + .findViewById(R.id.home_viewpager); + home_viewpager_ll_hint = (LinearLayout) v + .findViewById(R.id.home_viewpager_ll_hint); + + autoScrollViewPager = home_viewpager; + } + + public void initViewHolder(int position) { + if (!shoulanKapaitoutiaoList.isEmpty()) { + int currentItem = 0; + if (home_viewpager.getAdapter() != null) { + currentItem = home_viewpager.getCurrentItem(); + } + home_viewpager_ll_hint.removeAllViews(); + for (int i = 0; i < shoulanKapaitoutiaoList.size(); i++) { + TextView tv = new TextView(context); + LayoutParams lparams = new LayoutParams( + DisplayUtils.dip2px(context, 8), + DisplayUtils.dip2px(context, 8)); + if (i != currentItem) { + tv.setBackgroundResource(R.drawable.oval_hint_up); + } else { + tv.setBackgroundResource(R.drawable.oval_hint_dn); + } + if (i != 0) { + lparams.leftMargin = DisplayUtils.dip2px(context, 5); + } + tv.setLayoutParams(lparams); + home_viewpager_ll_hint.addView(tv); + } + + home_viewpager.setAdapter(new AutoScrollViewPagerAdapter()); + home_viewpager + .addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + + @Override + public void onPageSelected(int position) { + + for (int i = 0; i < home_viewpager_ll_hint + .getChildCount(); i++) { + TextView tv = (TextView) home_viewpager_ll_hint + .getChildAt(i); + if (i == position + % shoulanKapaitoutiaoList.size()) { + tv.setTextColor(0xffffffff); + tv.setBackgroundResource(R.drawable.oval_hint_dn); + } else { + tv.setTextColor(0xff333333); + tv.setBackgroundResource(R.drawable.oval_hint_up); + } + } + + } + + @Override + public void onPageScrolled(int position, + float positionOffset, + int positionOffsetPixels) { + + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + + home_viewpager.setCurrentItem(currentItem); + home_viewpager.setInterval(3000); + home_viewpager.startAutoScroll(); + } + } + + } + + public class AutoScrollViewPagerHolder { + + private ImageView news_thumb; + private TextView news_main_title, news_sub_title; + + public AutoScrollViewPagerHolder(View v) { + news_thumb = (ImageView) v.findViewById(R.id.news_thumb); + news_main_title = (TextView) v.findViewById(R.id.news_main_title); + news_sub_title = (TextView) v.findViewById(R.id.news_sub_title); + } + } + + public class AutoScrollViewPagerAdapter extends RecyclingPagerAdapter { + + @Override + public View getView(int position, View convertView, ViewGroup container) { + View view; + AutoScrollViewPagerHolder holder; + int i = position % shoulanKapaitoutiaoList.size(); + final NewsEntity newsEntity = shoulanKapaitoutiaoList.get(i); + + if (convertView != null) { + view = convertView; + holder = (AutoScrollViewPagerHolder) convertView.getTag(); + } else { + view = View.inflate(context, + R.layout.home_list_item_newsimage_type, null); + holder = new AutoScrollViewPagerHolder(view); + view.setTag(holder); + } + if (TextUtils.isEmpty(newsEntity.getThumb())) { + holder.news_thumb.setImageResource(R.drawable.preload); + holder.news_thumb.setScaleType(ScaleType.CENTER_INSIDE); + } else { + ImageUtils.getInstance(context).display(newsEntity.getThumb(), + holder.news_thumb); + } + String title = newsEntity.getTitle(); + String key = null; + if (title.contains("》")) { + key = "》"; + } else if (title.contains(" ")) { + key = " "; + } + if (key != null) { + int index = title.indexOf(key); + String mainTitle = title.substring(0, index + 1); + String subTitle = title.substring(index + 1); + + int left = (mainTitle.length() - 2) + * DisplayUtils.sp2px(context, 16) + + DisplayUtils.dip2px(context, 4); + int right = DisplayUtils.sp2px(context, + shoulanKapaitoutiaoList.size() * 13); + int length = subTitle.length() + * DisplayUtils.sp2px(context, 16); + int max = width - right - DisplayUtils.sp2px(context, 96); + if (left + length > max) { + holder.news_sub_title.setGravity(Gravity.RIGHT); + LayoutParams lparams = new LayoutParams( + LayoutParams.MATCH_PARENT, + LayoutParams.WRAP_CONTENT); + lparams.rightMargin = right; + holder.news_sub_title.setLayoutParams(lparams); + } else { + holder.news_sub_title.setGravity(Gravity.LEFT); + LayoutParams lparams = new LayoutParams( + LayoutParams.MATCH_PARENT, + LayoutParams.WRAP_CONTENT); + lparams.leftMargin = left; + holder.news_sub_title.setLayoutParams(lparams); + } + + holder.news_main_title.setText(mainTitle); + holder.news_sub_title.setVisibility(View.VISIBLE); + holder.news_sub_title.setText(subTitle); + } else { + holder.news_main_title.setText(title); + holder.news_sub_title.setVisibility(View.GONE); + } + view.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Map kv = new HashMap(); + kv.put("文章类型", newsEntity.getType()); + kv.put("入口", "主页-卡牌头条"); + TCAgent.onEvent(context, "文章阅读-资讯", newsEntity.getTitle(), + kv); + + Map kv2 = new HashMap(); + kv2.put(newsEntity.getTitle(), "点击量"); + TCAgent.onEvent(context, "主页数据", "卡牌头条", kv2); + + Map map = new HashMap(); + map.put("location", "卡牌头条-首栏"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("news", newsEntity.getTitle()); + map.put("page", "主页"); + DataCollectionManager.onEvent(context, "click-item", map); + + NewsUtils.startNewsActivity(context, newsEntity, "主页-卡牌头条"); + } + }); + return view; + } + + @Override + public int getCount() { + return Integer.MAX_VALUE; + } + + } + + public class GenuineNewsTypeViewHolder extends RecyclerView.ViewHolder { + private AutoScrollViewPager home_viewpager; + private LinearLayout home_viewpager_ll_hint; + + public GenuineNewsTypeViewHolder(View v) { + super(v); + home_viewpager = (AutoScrollViewPager) v + .findViewById(R.id.home_viewpager); + home_viewpager_ll_hint = (LinearLayout) v + .findViewById(R.id.home_viewpager_ll_hint); + + genuineNewsViewPager = home_viewpager; + } + + public void initViewHolder(int position) { + if (!yuedujingxuanList.isEmpty()) { + int currentItem = 0; + if (home_viewpager.getAdapter() != null) { + currentItem = home_viewpager.getCurrentItem(); + } + home_viewpager_ll_hint.removeAllViews(); + for (int i = 0; i < yuedujingxuanList.size(); i++) { + TextView tv = new TextView(context); + LayoutParams lparams = new LayoutParams( + DisplayUtils.dip2px(context, 8), + DisplayUtils.dip2px(context, 8)); + if (i != currentItem) { + tv.setBackgroundResource(R.drawable.oval_hint_up); + } else { + tv.setBackgroundResource(R.drawable.oval_hint_dn); + } + if (i != 0) { + lparams.leftMargin = DisplayUtils.dip2px(context, 5); + } + tv.setLayoutParams(lparams); + home_viewpager_ll_hint.addView(tv); + } + + home_viewpager.setAdapter(new GenuineNewsAdapter()); + home_viewpager + .addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + + @Override + public void onPageSelected(int position) { + + for (int i = 0; i < home_viewpager_ll_hint + .getChildCount(); i++) { + TextView tv = (TextView) home_viewpager_ll_hint + .getChildAt(i); + if (i == position + % yuedujingxuanList.size()) { + tv.setTextColor(0xffffffff); + tv.setBackgroundResource(R.drawable.oval_hint_dn); + } else { + tv.setTextColor(0xff333333); + tv.setBackgroundResource(R.drawable.oval_hint_up); + } + } + + } + + @Override + public void onPageScrolled(int position, + float positionOffset, + int positionOffsetPixels) { + + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + + home_viewpager.setCurrentItem(currentItem); + home_viewpager.setInterval(3000); + home_viewpager.startAutoScroll(); + } + } + + } + + public class GenuineNewsHolder { + private ImageView genuinenews_thumb; + private TextView genuinenews_title, genuinenews_intro; + + public GenuineNewsHolder(View v) { + genuinenews_thumb = (ImageView) v + .findViewById(R.id.genuinenews_thumb); + genuinenews_title = (TextView) v + .findViewById(R.id.genuinenews_title); + genuinenews_intro = (TextView) v + .findViewById(R.id.genuinenews_intro); + } + } + + public class GenuineNewsAdapter extends RecyclingPagerAdapter { + + @Override + public View getView(int position, View convertView, ViewGroup container) { + View view; + GenuineNewsHolder holder; + int i = position % yuedujingxuanList.size(); + final NewsEntity newsEntity = yuedujingxuanList.get(i); + + if (convertView != null) { + view = convertView; + holder = (GenuineNewsHolder) convertView.getTag(); + } else { + view = View.inflate(context, + R.layout.home_list_item_genuinenews_type, null); + holder = new GenuineNewsHolder(view); + view.setTag(holder); + } + + if (TextUtils.isEmpty(newsEntity.getThumb())) { + holder.genuinenews_thumb.setImageResource(R.drawable.preload); + holder.genuinenews_thumb.setScaleType(ScaleType.CENTER_INSIDE); + } else { + ImageUtils.getInstance(context).display(newsEntity.getThumb(), + holder.genuinenews_thumb); + } + + holder.genuinenews_title.setText(newsEntity.getTitle()); + + LayoutParams lparams = new LayoutParams( + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + lparams.leftMargin = DisplayUtils.sp2px(context, 8); + lparams.rightMargin = DisplayUtils.sp2px(context, + yuedujingxuanList.size() * 13 - 3); + holder.genuinenews_intro.setLayoutParams(lparams); + holder.genuinenews_intro.setText("\u3000\u3000" + + newsEntity.getIntro()); + + view.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + + Map kv2 = new HashMap(); + kv2.put(newsEntity.getTitle(), "点击量"); + TCAgent.onEvent(context, "主页数据", "阅读精品", kv2); + + Map map = new HashMap(); + map.put("location", "阅读精品"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("news", newsEntity.getTitle()); + map.put("page", "主页"); + DataCollectionManager.onEvent(context, "click-item", map); + + NewsUtils.startNewsActivity(context, newsEntity, "主页-阅读精品"); + } + }); + + return view; + } + + @Override + public int getCount() { + return Integer.MAX_VALUE; + } + + } + + public class TextNewsTypeViewHolder extends RecyclerView.ViewHolder { + public TextView newsType; + public TextView newsTitle; + public View rootItem; + + public TextNewsTypeViewHolder(View v) { + super(v); + rootItem = v; + newsType = (TextView) v.findViewById(R.id.news_type); + newsTitle = (TextView) v.findViewById(R.id.news_title); + } + + public void initViewHolder(final int position) { + if (position_kapaitoutiao != -1 + && position > position_kapaitoutiao + + (shoulanKapaitoutiaoList.isEmpty() ? 0 : 1) + && position <= position_kapaitoutiao + 1 + kapaitoutiaoSize) { + final NewsEntity newsEntity = cilanKapaitoutiaoList + .get(position + - (shoulanKapaitoutiaoList.isEmpty() ? 2 : 3)); + newsType.setBackgroundResource(NewsUtils + .getDrawableIdByType(newsEntity.getType())); + newsType.setText(newsEntity.getType()); + newsTitle.setText(newsEntity.getTitle()); + rootItem.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Map kv = new HashMap(); + kv.put("文章类型", newsEntity.getType()); + kv.put("入口", "主页-卡牌头条"); + TCAgent.onEvent(context, "文章阅读-资讯", + newsEntity.getTitle(), kv); + + Map kv2 = new HashMap(); + kv2.put(newsEntity.getTitle(), "点击量"); + TCAgent.onEvent(context, "主页数据", "卡牌头条", kv2); + + Map map = new HashMap(); + map.put("location", "卡牌头条-次栏"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("news", newsEntity.getTitle()); + map.put("page", "主页"); + DataCollectionManager.onEvent(context, "click-item", + map); + + NewsUtils.startNewsActivity(context, newsEntity, + "主页-卡牌头条"); + } + }); + } else if (position_kapaigonglue != -1 + && position > position_kapaigonglue + && position <= position_kapaigonglue + + kapaigonglueList.size()) { + final NewsEntity newsEntity = kapaigonglueList.get(position + - position_kapaigonglue - 1); + newsType.setBackgroundResource(NewsUtils + .getDrawableIdByType(newsEntity.getType())); + newsType.setText(newsEntity.getType()); + newsTitle.setText(newsEntity.getTitle()); + rootItem.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Map kv = new HashMap(); + kv.put("文章类型", newsEntity.getType()); + kv.put("入口", "主页-卡牌攻略"); + TCAgent.onEvent(context, "文章阅读-攻略", + newsEntity.getTitle(), kv); + + Map kv2 = new HashMap(); + kv2.put(newsEntity.getTitle(), "点击量"); + TCAgent.onEvent(context, "主页数据", "卡牌攻略", kv2); + + Map map = new HashMap(); + map.put("location", "卡牌攻略"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("news", newsEntity.getTitle()); + map.put("page", "主页"); + DataCollectionManager.onEvent(context, "click-item", + map); + + NewsUtils.startNewsActivity(context, newsEntity, + "主页-卡牌攻略"); + } + }); + } + } + + } + + public class GameNormalViewHolder extends RecyclerView.ViewHolder { + public ImageView gameThumb; + public TextView gameNameAndSize; + public TextView downloadBtn; + public TextView gameDes; + public LinearLayout labelList; + public ProgressBar game_progressbar; + public LinearLayout game_ll_info; + public TextView download_speed; + public TextView download_percentage; + + public View rootItem; + + /** + * + * @param v + * @param column + * column == zuixinchajian,表示是最新插件板块, column == + * remenkapai,表示热门版块 + */ + public GameNormalViewHolder(View v) { + super(v); + rootItem = v; + gameThumb = (ImageView) v.findViewById(R.id.home1_game_thumb); + gameNameAndSize = (TextView) v + .findViewById(R.id.home1_game_nameAndsize); + downloadBtn = (TextView) v.findViewById(R.id.home1_download_btn); + gameDes = (TextView) v.findViewById(R.id.home1_game_des); + labelList = (LinearLayout) v.findViewById(R.id.home1_label_list); + game_ll_info = (LinearLayout) v + .findViewById(R.id.home1_game_ll_info); + game_progressbar = (ProgressBar) v + .findViewById(R.id.home1_game_progressbar); + download_speed = (TextView) v + .findViewById(R.id.home1_download_speed); + download_percentage = (TextView) v + .findViewById(R.id.home1_download_percentage); + } + + public void initViewHolder(int position) { + + GameEntity entity = null; + String from = null; + if (position > position_zuixinchajian + && position <= position_zuixinchajian + + zuixinchajianList.size()) { + entity = zuixinchajianList.get(position + - position_zuixinchajian - 1); + from = "最新插件"; + } else if (position > position_remenkapai + && position <= position_remenkapai + remenkapaiList.size()) { + entity = remenkapaiList.get(position - position_remenkapai - 1); + from = "热门卡牌"; + } + if (entity != null) { + + ImageUtils.getInstance(context).display(entity.getIcon(), + gameThumb); + if (entity.getApk() == null || entity.getApk().isEmpty()) { + gameNameAndSize.setText(entity.getName()); + } else { + gameNameAndSize.setText(entity.getName() + " | " + + entity.getApk().get(0).getSize()); + } + gameDes.setText(entity.getBrief()); + GameViewUtils.setLabelList(context, labelList, entity.getTag()); + + final GameEntity gameInfoEntity = entity; + final String entrance = from; + + rootItem.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + + Map kv = new HashMap(); + kv.put("入口", "主页-" + entrance); + TCAgent.onEvent(context, "游戏详情", + gameInfoEntity.getName(), kv); + + Map kv2 = new HashMap(); + kv2.put(gameInfoEntity.getName(), "点击量"); + TCAgent.onEvent(context, "主页数据", entrance, kv2); + + Map map = new HashMap(); + map.put("location", entrance); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", gameInfoEntity.getName()); + map.put("page", "主页"); + DataCollectionManager.onEvent(context, "click-item", + map); + + AppController.put("GameEntity", gameInfoEntity); + Intent intent = new Intent(context, + GameDetailsActivity.class); + intent.putExtra("entrance", "主页-" + entrance); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + }); + + DownloadItemUtils.setOnClickListener(context, downloadBtn, + download_speed, download_percentage, entity, position, + HomeFragmentAdapter.this, handler, lastTimeMap, + statusMap, platformMap, "主页-" + entrance, + dismissEntity, "主页:" + entity.getName()); + + DownloadItemUtils.updateItem(context, labelList, + game_progressbar, game_ll_info, download_speed, + download_percentage, downloadBtn, entity, platformMap, + statusMap); + + } + } + } + + public class GameTestViewHolder extends RecyclerView.ViewHolder { + public ImageView gameThumb; + public TextView gameNameAndSize; + public TextView gameSize; + public TextView downloadBtn; + public TextView gameDes; + public TextView gameTestType; + public TextView gameTestTime; + public LinearLayout labelList; + public ProgressBar game_progressbar; + public LinearLayout game_ll_info; + public TextView download_speed; + public TextView download_percentage; + + private View rootItem; + + public GameTestViewHolder(View v) { + super(v); + this.rootItem = v; + gameThumb = (ImageView) v.findViewById(R.id.home2_game_thumb); + gameNameAndSize = (TextView) v + .findViewById(R.id.home2_game_nameAndsize); + downloadBtn = (TextView) v.findViewById(R.id.home2_download_btn); + gameDes = (TextView) v.findViewById(R.id.home2_game_des); + gameTestType = (TextView) v.findViewById(R.id.home2_test_type); + gameTestTime = (TextView) v.findViewById(R.id.home2_test_time); + labelList = (LinearLayout) v.findViewById(R.id.home2_label_list); + game_ll_info = (LinearLayout) v + .findViewById(R.id.home2_game_ll_info); + game_progressbar = (ProgressBar) v + .findViewById(R.id.home2_game_progressbar); + download_speed = (TextView) v + .findViewById(R.id.home2_download_speed); + download_percentage = (TextView) v + .findViewById(R.id.home2_download_percentage); + } + + public void initViewHolder(int position) { + if (position_xincekapai != -1) { + + final GameEntity entity = xincekapaiList.get(position + - position_xincekapai - 1); + + ImageUtils.getInstance(context).display(entity.getIcon(), + gameThumb); + if (entity.getApk() == null || entity.getApk().isEmpty()) { + gameNameAndSize.setText(entity.getName()); + } else { + gameNameAndSize.setText(entity.getName() + " | " + + entity.getApk().get(0).getSize()); + } + gameDes.setText(entity.getBrief()); + gameTestType.setText(xincekapaiList + .get(position - position_xincekapai - 1).getTest() + .getType()); + if (entity.getTest().getStart() == 0) { + gameTestTime.setVisibility(View.GONE); + } else { + gameTestTime.setText(GameViewUtils.getGameTestDate(entity + .getTest().getStart())); + } + + rootItem.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + + Map kv = new HashMap(); + kv.put("入口", "主页-新测卡牌"); + TCAgent.onEvent(context, "游戏详情", entity.getName(), kv); + + Map kv2 = new HashMap(); + kv2.put(entity.getName(), "点击量"); + TCAgent.onEvent(context, "主页数据", "新测卡牌", kv2); + + Map map = new HashMap(); + map.put("location", "新测卡牌"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", entity.getName()); + map.put("page", "主页"); + DataCollectionManager.onEvent(context, "click-item", + map); + + AppController.put("GameEntity", entity); + Intent intent = new Intent(context, + GameDetailsActivity.class); + intent.putExtra("entrance", "主页-新测卡牌"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + }); + + if (entity.getApk() == null || entity.getApk().isEmpty()) { + downloadBtn.setVisibility(View.GONE); + } else { + if (entity.getTest().getEnd() == 0) { + downloadBtn.setVisibility(View.VISIBLE); + DownloadItemUtils.setOnClickListener(context, + downloadBtn, download_speed, + download_percentage, entity, position, + HomeFragmentAdapter.this, handler, lastTimeMap, + statusMap, platformMap, "主页-新测卡牌", + dismissEntity, "主页:" + entity.getName()); + } else { + long endTime = Long.valueOf(entity.getTest().getEnd() + + "000"); + long todayTime = new Date().getTime(); + if (todayTime > endTime) { + // 测试时间已过 + downloadBtn.setVisibility(View.GONE); + } else { + // 测试时间未过 + downloadBtn.setVisibility(View.VISIBLE); + DownloadItemUtils.setOnClickListener(context, + downloadBtn, download_speed, + download_percentage, entity, position, + HomeFragmentAdapter.this, handler, + lastTimeMap, statusMap, platformMap, + "主页-新测卡牌", dismissEntity, + "主页:" + entity.getName()); + } + } + } + + DownloadItemUtils.updateItem(context, labelList, + game_progressbar, game_ll_info, download_speed, + download_percentage, downloadBtn, entity, platformMap, + statusMap); + } + } + + } + + private AutoScrollViewPager autoScrollViewPager; + private AutoScrollViewPager genuineNewsViewPager; + + public void startAutoScroll() { + if (autoScrollViewPager != null) { + autoScrollViewPager.startAutoScroll(); + } + if (genuineNewsViewPager != null) { + genuineNewsViewPager.startAutoScroll(); + } + } + + public void stopAutoScroll() { + if (autoScrollViewPager != null) { + autoScrollViewPager.stopAutoScroll(); + } + if (genuineNewsViewPager != null) { + genuineNewsViewPager.stopAutoScroll(); + } + } + + public void setList(List zList, List rList, + List xList) { + zuixinchajianList = zList; + remenkapaiList = rList; + xincekapaiList = xList; + notifyDataSetChanged(); + } + + public int getKapaitoutiaoListSize() { + return kapaitoutiaoSize; + } + + public int getKapaigonglueListSize() { + return kapaigonglueList.size(); + } + + public int getZuixinchajianListSize() { + return zuixinchajianList.size(); + } + + public int getRemenkapaiListSize() { + return remenkapaiList.size(); + } + + public int getXincekapaiListSize() { + return xincekapaiList.size(); + } + + public List getZuixinchajianList() { + return zuixinchajianList; + } + + public List getRemenkapaiList() { + return remenkapaiList; + } + + public List getXincekapaiList() { + return xincekapaiList; + } + + public int getPosition_kapaitoutiao() { + return position_kapaitoutiao; + } + + public int getPosition_zuixinchajian() { + return position_zuixinchajian; + } + + public int getPosition_remenkapai() { + return position_remenkapai; + } + + public int getPosition_kapaigonglue() { + return position_kapaigonglue; + } + + public int getPosition_xincekapai() { + return position_xincekapai; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/manager/ConcernManager.java b/app/src/main/java/com/gh/gamecenter/manager/ConcernManager.java new file mode 100644 index 0000000000..1478cab58c --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/manager/ConcernManager.java @@ -0,0 +1,309 @@ +package com.gh.gamecenter.manager; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import android.content.Context; +import android.support.v4.util.ArrayMap; + +import com.gh.common.util.PackageUtils; +import com.gh.common.util.TrafficUtils; +import com.gh.gamecenter.db.ConcernDao; +import com.gh.gamecenter.db.info.ConcernInfo; +import com.gh.gamecenter.entity.ApkEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.eventbus.EBConcernChanged; + +import de.greenrobot.event.EventBus; + +public class ConcernManager { + + private Context context; + private ConcernDao dao; + + public ConcernManager(Context context) { + this.context = context; + dao = new ConcernDao(context); + } + + /** + * 根据id判断是否已关注 + */ + public boolean isConcern(String id) { + ConcernInfo concernEntity = dao.find(id); + if (concernEntity != null) { + return concernEntity.isConcern(); + } + return false; + } + + /** + * 根据GameEntity添加一个关注 + */ + public void addByEntity(final GameEntity entity) { + new Thread() { + @Override + public void run() { + ConcernInfo concernEntity = findConcernById(entity.getId()); + if (concernEntity == null) { + concernEntity = new ConcernInfo(); + concernEntity.setId(entity.getId()); + concernEntity.setTime(System.currentTimeMillis()); + concernEntity.setIcon(entity.getIcon()); + concernEntity.setGameName(entity.getName()); + concernEntity.setConcern(true); + String tag = "已关注"; + HashMap packageNames = new HashMap(); + int weight = 1; + int quantity = 0; + for (ApkEntity apkEntity : entity.getApk()) { + if (PackageManager.isInstalled(apkEntity.getPackageName())) { + quantity++; + packageNames.put(apkEntity.getPackageName(), true); + } else { + packageNames.put(apkEntity.getPackageName(), false); + } + } + if (quantity > 0) { + weight++; + tag = "已关注,已安装"; + } + concernEntity.setInstalledQuantity(quantity); + concernEntity.setInstalled(weight == 1 ? false : true); + concernEntity.setTag(tag); + concernEntity.setPackageNames(packageNames); + long traffic = TrafficUtils + .getInstance(context) + .getTraffic( + new ArrayList(packageNames.keySet())); + concernEntity.setTraffic(traffic); + if (traffic > 0) { + weight++; + } + concernEntity.setWeight(weight); + addConcern(concernEntity); + } else { + concernEntity.setTime(System.currentTimeMillis()); + concernEntity.setIcon(entity.getIcon()); + concernEntity.setConcern(true); + HashMap packageNames = new HashMap(); + int quantity = 0; + for (ApkEntity apkEntity : entity.getApk()) { + if (PackageManager.isInstalled(apkEntity.getPackageName())) { + quantity++; + packageNames.put(apkEntity.getPackageName(), true); + } else { + packageNames.put(apkEntity.getPackageName(), false); + } + } + concernEntity.setInstalledQuantity(quantity); + concernEntity.setTag("已关注,已安装"); + concernEntity.setPackageNames(packageNames); + long traffic = TrafficUtils + .getInstance(context) + .getTraffic( + new ArrayList(packageNames.keySet())); + concernEntity.setTraffic(traffic); + int weight = 2; + if (traffic > 0) { + weight++; + } + concernEntity.setWeight(weight); + updateByConcern(concernEntity); + } + EventBus.getDefault() + .post(new EBConcernChanged(entity.getId())); + } + }.start(); + } + + /** + * 根据GameEntity更新关注 + */ + public void updateByEntity(com.gh.gamecenter.db.info.GameInfo gameEntity, + boolean flag) { + String packageName = gameEntity.getPackageName(); + ConcernInfo concernEntity = findConcernById(gameEntity.getId()); + if (concernEntity != null) { + concernEntity.setTime(System.currentTimeMillis()); + if ((concernEntity.isConcern() && concernEntity.isInstalled()) + || (!concernEntity.isConcern() && concernEntity + .isInstalled())) { + concernEntity.getPackageNames().put(packageName, true); + concernEntity.setInstalledQuantity(concernEntity + .getInstalledQuantity() + 1); + updateByConcern(concernEntity); + if (flag) { + EventBus.getDefault().post( + new EBConcernChanged(concernEntity.getId())); + } + } else if (concernEntity.isConcern() + && !concernEntity.isInstalled()) { + concernEntity.setTag("已关注,已安装"); + concernEntity.setInstalled(true); + concernEntity.setInstalledQuantity(1); + concernEntity.getPackageNames().put(packageName, true); + int weight = concernEntity.getWeight() + 1; + concernEntity.setWeight(weight); + updateByConcern(concernEntity); + if (flag) { + EventBus.getDefault().post( + new EBConcernChanged(concernEntity.getId())); + } + } + } else { + concernEntity = new ConcernInfo(); + concernEntity.setId(gameEntity.getId()); + concernEntity.setTime(System.currentTimeMillis()); + HashMap packageNames = new HashMap(); + packageNames.put(packageName, true); + concernEntity.setPackageNames(packageNames); + concernEntity.setInstalled(true); + concernEntity.setConcern(false); + concernEntity.setTag("已安装"); + concernEntity.setWeight(1); + concernEntity.setInstalledQuantity(1); + if (gameEntity.getGameName() != null) { + concernEntity.setGameName(gameEntity.getGameName()); + } else { + concernEntity.setGameName(PackageUtils.getNameByPackageName( + context, packageName)); + } + addConcern(concernEntity); + if (flag) { + EventBus.getDefault().post( + new EBConcernChanged(concernEntity.getId())); + } + } + } + + /** + * 获取已安装游戏的集合 + */ + public List getInstalledGame() { + return dao.getInstalled(); + } + + /** + * 获取已关注游戏的集合 + */ + public List getConcernGame() { + return dao.getConcern(0); + } + + public List getConcernGame(int number) { + return dao.getConcern(number); + } + + /** + * 根据包名 更新关注 + */ + public void updateByPackageName(String packageName) { + for (ConcernInfo concernEntity : getAllConcern()) { + Boolean isInstalled = concernEntity.getPackageNames().get( + packageName); + if (isInstalled != null && isInstalled) { + if (concernEntity.getInstalledQuantity() - 1 == 0) { + if (!concernEntity.isConcern() + && concernEntity.isInstalled()) { + deleteConcern(concernEntity.getId()); + } else { + concernEntity.setTime(System.currentTimeMillis()); + concernEntity.setTag("已关注"); + concernEntity.setInstalled(false); + concernEntity.setInstalledQuantity(0); + concernEntity.getPackageNames().put(packageName, false); + concernEntity.setWeight(concernEntity.getWeight() - 1); + updateByConcern(concernEntity); + } + EventBus.getDefault().post( + new EBConcernChanged(concernEntity.getId())); + } else if (concernEntity.getInstalledQuantity() - 1 > 0) { + concernEntity.setTime(System.currentTimeMillis()); + concernEntity.setInstalledQuantity(concernEntity + .getInstalledQuantity() - 1); + concernEntity.getPackageNames().put(packageName, false); + updateByConcern(concernEntity); + EventBus.getDefault().post( + new EBConcernChanged(concernEntity.getId())); + } + break; + } + } + } + + /** + * 获取所有的关注 按照权重和流量排序 + */ + public List getAllConcernBySort() { + return getConcern(0); + } + + /** + * 获取权重和流量排序靠前的关注 + * + * @param number + * 数量 + * @return + */ + public List getConcern(int number) { + return dao.get(number); + } + + /** + * 添加一个关注 + */ + public void addConcern(ConcernInfo entity) { + dao.add(entity); + } + + /** + * 删除一个关注 + */ + public void deleteConcern(String id) { + ConcernInfo concernEntity = findConcernById(id); + if (concernEntity.isConcern() && concernEntity.isInstalled()) { + concernEntity.setTime(System.currentTimeMillis()); + concernEntity.setConcern(false); + concernEntity.setWeight(concernEntity.getWeight() - 1); + concernEntity.setTag("已安装"); + updateByConcern(concernEntity); + } else { + dao.delete(id); + } + EventBus.getDefault().post(new EBConcernChanged(id)); + } + + /** + * 获取某一个关注 + */ + public ConcernInfo findConcernById(String id) { + return dao.find(id); + } + + /** + * 获取关注列表 + */ + public List getAllConcern() { + return dao.getAll(); + } + + /** + * 获取关注map + */ + public ArrayMap getConcernMap() { + ArrayMap map = new ArrayMap(); + for (ConcernInfo entity : dao.getAll()) { + map.put(entity.getId(), entity); + } + return map; + } + + /** + * 更新关注列表 + */ + public void updateByConcern(ConcernInfo entity) { + dao.update(entity); + } +} diff --git a/app/src/main/java/com/gh/gamecenter/manager/DataCollectionManager.java b/app/src/main/java/com/gh/gamecenter/manager/DataCollectionManager.java new file mode 100644 index 0000000000..de2ab66339 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/manager/DataCollectionManager.java @@ -0,0 +1,240 @@ +package com.gh.gamecenter.manager; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import android.content.Context; +import android.util.Log; + +import com.android.volley.Request.Method; +import com.android.volley.Response; +import com.android.volley.VolleyError; +import com.gh.common.util.DeviceUtils; +import com.gh.common.util.PackageUtils; +import com.gh.common.util.Utils; +import com.gh.gamecenter.db.DataCollectionDao; +import com.gh.gamecenter.db.info.DataCollectionInfo; +import com.gh.gamecenter.volley.extended.JsonObjectExtendedRequest; + +public class DataCollectionManager { + + private static DataCollectionManager mInstance; + + private Context mContext; + private DataCollectionDao dao; + + private DataCollectionManager(Context context) { + mContext = context; + dao = new DataCollectionDao(mContext); + } + + public static DataCollectionManager getInstance(Context context) { + if (mInstance == null) { + synchronized (DataCollectionManager.class) { + if (mInstance == null) { + mInstance = new DataCollectionManager( + context.getApplicationContext()); + } + } + } + return mInstance; + } + + // 添加事件 + public static void onEvent(Context context, DataCollectionInfo entity, + boolean isUpload) { + DataCollectionManager.getInstance(context).add(entity, isUpload); + } + + public static void onEvent(Context context, String type, String data, + boolean isUpload) { + String id = UUID.randomUUID().toString().replaceAll("-", ""); + DataCollectionInfo entity = new DataCollectionInfo(); + entity.setId(id); + entity.setType(type); + entity.setData(data); + onEvent(context, entity, isUpload); + } + + public static void onEvent(Context context, String type, + Map map) { + onEvent(context, type, new JSONObject(map).toString(), true); + } + + public static void onEvent(Context context, String type, + Map map, boolean isUpload) { + onEvent(context, type, new JSONObject(map).toString(), isUpload); + } + + public static void upsert(Context context, String type, + Map map) { + String id = UUID.randomUUID().toString().replaceAll("-", ""); + DataCollectionInfo entity = new DataCollectionInfo(); + entity.setId(id); + entity.setType(type); + entity.setData(new JSONObject(map).toString()); + DataCollectionManager.getInstance(context).upsert(entity, type); + } + + public void upsert(DataCollectionInfo entity, String type) { + List list = dao.findByType("user"); + if (list == null || list.isEmpty()) { + dao.add(entity); + } else { + entity.setId(list.get(0).getId()); + dao.update(entity); + if (list.size() > 1) { + List ids = new ArrayList(); + for (int i = 1, size = list.size(); i < size; i++) { + ids.add(list.get(i).getId()); + } + dao.delete(ids); + } + } + } + + // 把事件加入列表 + public void add(DataCollectionInfo entity, boolean isUpload) { + // 加入列表 + dao.add(entity); + + // 检查列表数目是否满足条件 + if (isUpload) { + // List list = dao.getAll(); + // if (list.size() >= 20) { + // try { + // upload(list, false); + // } catch (JSONException e) { + // e.printStackTrace(); + // } + // } + } + } + + /* + * 统计点击数据 + */ + public void statClickData() { + List list = dao.getClickData(); + if (!list.isEmpty()) { + List ids = new ArrayList(); + DataCollectionInfo dataCollectionEntity; + List data = new ArrayList(); + try { + for (int i = 0, size = list.size(); i < size; i++) { + dataCollectionEntity = list.get(i); + ids.add(dataCollectionEntity.getId()); + data.add(new JSONObject(dataCollectionEntity.getData())); + } + } catch (JSONException e) { + e.printStackTrace(); + } + Map map = new HashMap(); + map.put("data", data); + map.put("createOn", System.currentTimeMillis() / 100); + onEvent(mContext, "click", map); + dao.delete(ids); + } + } + + // 上传数据 + public void upload() { + statClickData(); + List list = dao.getAll(); + if (!list.isEmpty()) { + try { + upload(list); + } catch (JSONException e) { + e.printStackTrace(); + } + } + } + + // 上传数据 + private void upload(List list) + throws JSONException { + String url = "http://114.215.139.210/data/collection/upload"; + + final List ids = new ArrayList(); + + String version = PackageUtils.getVersion(mContext); + String user = DeviceUtils.getDeviceID(mContext); + String channel = (String) PackageUtils.getMetaData(mContext, + mContext.getPackageName(), "TD_CHANNEL_ID"); + + HashMap map = new HashMap(); + DataCollectionInfo dataCollectionEntity; + String type; + JSONArray jsonArray; + for (int i = 0, size = list.size(); i < size; i++) { + dataCollectionEntity = list.get(i); + type = dataCollectionEntity.getType(); + if (type.equals("click-item")) { + continue; + } + jsonArray = map.get(type); + if (jsonArray == null) { + jsonArray = new JSONArray(); + } + JSONObject jsonObject = new JSONObject( + dataCollectionEntity.getData()); + jsonObject.put("version", version); + jsonObject.put("user", user); + jsonObject.put("channel", channel); + jsonArray.put(jsonObject.toString()); + map.put(type, jsonArray); + + ids.add(dataCollectionEntity.getId()); + } + + ArrayList params = new ArrayList(); + for (String key : map.keySet()) { + HashMap hashMap = new HashMap(); + hashMap.put("type", key); + hashMap.put("data", map.get(key)); + JSONObject jsonObject = new JSONObject(hashMap); + params.add(jsonObject); + } + JSONArray body = new JSONArray(params); + + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Method.POST, url, body.toString(), + new Response.Listener() { + @Override + public void onResponse(JSONObject response) { + + Utils.log(response); + try { + if ("success".equals(response.getString("status"))) { + // 上传成功,删除本地数据 + dao.delete(ids); + } + } catch (JSONException e) { + + e.printStackTrace(); + } + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + + // 上传失败,检查网络状态,继续上传 + Utils.log(error); + if (error.networkResponse != null) { + Utils.log(new String(error.networkResponse.data)); + } + } + }); + Log.e("result", new String(request.getBody())); + // AppController.addToRequestQueue(request, + // DataCollectionManager.class); + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/manager/FilterManager.java b/app/src/main/java/com/gh/gamecenter/manager/FilterManager.java new file mode 100644 index 0000000000..512b8015ee --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/manager/FilterManager.java @@ -0,0 +1,87 @@ +package com.gh.gamecenter.manager; + +import java.util.ArrayList; +import java.util.List; + +import org.json.JSONArray; +import org.json.JSONException; + +import android.content.Context; +import android.content.SharedPreferences; + +import com.android.volley.Request; +import com.android.volley.Response; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.common.constant.Config; +import com.gh.common.util.Utils; +import com.gh.gamecenter.db.FilterDao; +import com.gh.gamecenter.db.info.FilterInfo; +import com.gh.gamecenter.volley.extended.JsonArrayExtendedRequest; + +public class FilterManager { + + private FilterDao dao; + private SharedPreferences sp; + + public FilterManager(Context context) { + dao = new FilterDao(context); + sp = context.getSharedPreferences(Config.PREFERENCE, + Context.MODE_PRIVATE); + } + + public void addFilter(String packageName) { + dao.add(new FilterInfo(packageName)); + } + + public void addAllFilter(List list) { + dao.addAll(list); + } + + public void deleteGame(String packageName) { + dao.delete(packageName); + } + + public List getAllGame() { + return dao.getAll(); + } + + public boolean isFilter(String packageName) { + return dao.isFilter(packageName); + } + + public void getFilterFromServer(final String today) { + long skip = dao.getCount(); + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest( + Request.Method.GET, Config.HOST + + "v1d45/support/package/unused?skip=" + skip, + new JSONArray(), new Response.Listener() { + + @Override + public void onResponse(JSONArray response) { + + Utils.log("getFilterFromServer=" + response.toString()); + + try { + List list = new ArrayList(); + for (int i = 0, size = response.length(); i < size; i++) { + list.add(new FilterInfo(response.getString(i))); + } + dao.addAll(list); + sp.edit().putString("filter_time", today).apply(); + } catch (JSONException e) { + + e.printStackTrace(); + } + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + + Utils.log("getFilterFromServer=" + error.toString()); + + } + }); + AppController.addToRequestQueue(request, FilterManager.class); + } +} diff --git a/app/src/main/java/com/gh/gamecenter/manager/GameManager.java b/app/src/main/java/com/gh/gamecenter/manager/GameManager.java new file mode 100644 index 0000000000..a1cebf976e --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/manager/GameManager.java @@ -0,0 +1,44 @@ +package com.gh.gamecenter.manager; + +import java.util.List; + +import android.content.Context; + +import com.gh.gamecenter.db.GameDao; +import com.gh.gamecenter.db.info.GameInfo; + +public class GameManager { + + private GameDao dao; + + public GameManager(Context context) { + dao = new GameDao(context); + } + + public void addOrUpdate(GameInfo entity) { + if (dao.find(entity.getPackageName()) == null) { + dao.add(entity); + } + } + + public void addGame(GameInfo entity) { + dao.add(entity); + } + + public GameInfo findGame(String packageName) { + return dao.find(packageName); + } + + public void deleteGame(String packageName) { + dao.delete(packageName); + } + + public List getAllGame() { + return dao.getAll(); + } + + public void updateGame(GameInfo entity) { + dao.update(entity); + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/manager/PackageManager.java b/app/src/main/java/com/gh/gamecenter/manager/PackageManager.java new file mode 100644 index 0000000000..0f01fc8e87 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/manager/PackageManager.java @@ -0,0 +1,279 @@ +package com.gh.gamecenter.manager; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.json.JSONArray; +import org.json.JSONObject; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager.NameNotFoundException; +import android.support.v4.util.ArrayMap; +import android.text.TextUtils; + +import com.gh.common.util.PackageUtils; +import com.gh.gamecenter.entity.GameUpdateEntity; + +public class PackageManager { + + private Context context; + private static ArrayList updateList; + private static ArrayMap installedMap; + private static ArrayList installedList; + + public PackageManager(Context context) { + this.context = context; + } + + /** + * 获取本地所有已安装的软件的包名的map + * + * @return 已安装游戏列表 + */ + public static ArrayMap getInstalledMap() { + return installedMap; + } + + public static ArrayList getInstalledList() { + return installedList; + } + + /** + * 根据包名 判断是否安装该游戏 + * + * @param packageName + * 包名 + * @return true 已安装 false 未安装 + */ + public static boolean isInstalled(String packageName) { + if (packageName == null) { + return false; + } + if (installedMap == null) { + return false; + } + Boolean b = installedMap.get(packageName); + if (b != null) { + return true; + } + return false; + } + + /** + * 移除一个已安装的游戏 + * + * @param game + */ + public static void removeInstalled(String packageName) { + installedMap.remove(packageName); + } + + /** + * 添加一个已安装的游戏 + * + * @param game + */ + public static void addInstalled(String packageName) { + installedMap.put(packageName, true); + } + + public void getInstalledMapFromLocal() { + installedMap = new ArrayMap(); + installedList = new ArrayList(); + ArrayList list = PackageUtils.getAllPackageName(context); + for (String str : list) { + installedMap.put(str, true); + installedList.add(str); + } + } + + /** + * 根据本地已安装的游戏列表,获取可更新游戏列表 + * + * @return 可更新游戏列表 + */ + public static ArrayList getUpdateList() { + if (updateList == null) { + updateList = new ArrayList(); + } + return updateList; + } + + public static boolean isContain(String packageName) { + if (getUpdateList().isEmpty()) { + return false; + } + for (int i = 0; i < getUpdateList().size(); i++) { + if (getUpdateList().get(i).getPackageName().equals(packageName)) { + return true; + } + } + return false; + } + + public static void addUpdate(GameUpdateEntity game) { + if (!isContain(game.getPackageName())) { + getUpdateList().add(game); + } + } + + public static void addUpdate(int index, GameUpdateEntity game) { + if (getUpdateList().isEmpty() || !getUpdateList().get(0).getName().equals(game.getName())) { + getUpdateList().add(index, game); + } + } + + public static void clearUpdateList() { + getUpdateList().clear(); + } + + public static void setUpdateList(ArrayList list) { + getUpdateList().clear(); + for (int i = 0; i < list.size(); i++) { + getUpdateList().add(list.get(i)); + } + } + + public static void addUpdateList(ArrayList list) { + for (int i = 0; i < list.size(); i++) { + getUpdateList().add(list.get(i)); + } + } + + public static void removeUpdateList(String packageName) { + for (int i = 0, size = getUpdateList().size(); i < size; i++) { + if (packageName.equals(getUpdateList().get(i).getPackageName())) { + getUpdateList().remove(i); + break; + } + } + } + + /** + * 获取所有已安装的软件的包名、版本(非系统应用) + * + * @param context + * 上下文 + * @return 已安装软件的包名的集合 + */ + public ArrayList getLocalPackageName() { + FilterManager filterManager = new FilterManager(context); + ArrayList list = new ArrayList(); + List packageInfos = context.getPackageManager() + .getInstalledPackages(0); + for (int i = 0, size = packageInfos.size(); i < size; i++) { + PackageInfo packageInfo = packageInfos.get(i); + if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { + if (!context.getPackageName().equals(packageInfo.packageName)) { + if (!filterManager.isFilter(packageInfo.packageName)) { + list.add(packageInfo.packageName); + } + } + } + } + return list; + } + + /** + * 获取所有已安装的软件的包名、版本(非系统应用) + * + * @param context + * 上下文 + * @return 已安装软件的包名的集合 + */ + public JSONArray getAllPackageName2JSON() { + FilterManager filterManager = new FilterManager(context); + JSONArray jsonArray = new JSONArray(); + List packageInfos = context.getPackageManager() + .getInstalledPackages(0); + for (int i = 0, size = packageInfos.size(); i < size; i++) { + PackageInfo packageInfo = packageInfos.get(i); + if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { + if (!context.getPackageName().equals(packageInfo.packageName)) { + if (!filterManager.isFilter(packageInfo.packageName)) { + HashMap params = new HashMap(); + params.put("package", packageInfo.packageName); + if (TextUtils.isEmpty(packageInfo.versionName)) { + params.put("version", ""); + } else { + params.put("version", packageInfo.versionName); + } + Object obj = PackageUtils.getMetaData(context, + packageInfo.packageName, "gh_version"); + String gh_version = null; + if (obj != null && obj.getClass().equals(String.class)) { + gh_version = (String) obj; + } + if (gh_version != null && gh_version.startsWith("gh")) { + params.put("gh_version", gh_version.substring(2)); + } else { + params.put("gh_version", ""); + } + JSONObject jsonObject = new JSONObject(params); + jsonArray.put(jsonObject); + } + } + } + } + return jsonArray; + } + + public long getInstalledTime(String packageName) { + try { + PackageInfo packageInfo = context.getPackageManager() + .getPackageInfo(packageName, 0); + return packageInfo.firstInstallTime; + } catch (NameNotFoundException e) { + + e.printStackTrace(); + } + return 0; + } + + public boolean isSignature(String packageName) { + String signature = PackageUtils.getApkSignatureByPackageName(context, + packageName); + if (PackageUtils.publicKey.equals(signature)) { + return true; + } + return false; + } + + /** + * 根据apk路径,获取apk包名、签名 根据包名 判断 是否已安装游戏 根据签名 判断 是否一致 + * + * @param path + * apk路径 + * @return true 可执行安装 false 要卸载已安装的,再执行安装 + */ + public boolean launchSetup(String path) { + + String packageName = PackageUtils.getPackageNameByPath(context, path); + + boolean isContain = PackageUtils.isContain(context, packageName); + if (!isContain) { + return true; + } + + boolean isInstalled = PackageUtils.isInstalled(context, packageName); + if (!isInstalled) { + return true; + } + + String signature = PackageUtils.getApkSignatureByPackageName(context, + packageName); + + if (PackageUtils.publicKey.equals(signature)) { + return true; + } + + return false; + } + + public static int getUpdateListSize() { + return getUpdateList().size(); + } +} diff --git a/app/src/main/java/com/gh/gamecenter/manager/SuspectedGameManager.java b/app/src/main/java/com/gh/gamecenter/manager/SuspectedGameManager.java new file mode 100644 index 0000000000..f99267c681 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/manager/SuspectedGameManager.java @@ -0,0 +1,42 @@ +package com.gh.gamecenter.manager; + +import java.util.List; + +import android.content.Context; + +import com.gh.gamecenter.db.SuspectedGameDao; +import com.gh.gamecenter.db.info.SuspectedGameInfo; + +public class SuspectedGameManager { + + private SuspectedGameDao dao; + + public SuspectedGameManager(Context context) { + dao = new SuspectedGameDao(context); + } + + public void addGame(SuspectedGameInfo entity) { + dao.add(entity); + } + + public SuspectedGameInfo findSuspectedGame(String packageName) { + return dao.find(packageName); + } + + public void deleteSuspectedGame(String packageName) { + dao.delete(packageName); + } + + public List getAllGame() { + return dao.getAll(); + } + + public void updateGame(SuspectedGameInfo entity) { + dao.update(entity); + } + + public void deleteAll() { + dao.deleteAll(); + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/manager/SystemBarTintManager.java b/app/src/main/java/com/gh/gamecenter/manager/SystemBarTintManager.java new file mode 100644 index 0000000000..e192dc5244 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/manager/SystemBarTintManager.java @@ -0,0 +1,608 @@ +/* + * Copyright (C) 2013 readyState Software Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.gh.gamecenter.manager; + +import java.lang.reflect.Method; + +import android.annotation.SuppressLint; +import android.annotation.TargetApi; +import android.app.Activity; +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.util.DisplayMetrics; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.FrameLayout.LayoutParams; + +/** + * Class to manage status and navigation bar tint effects when using KitKat + * translucent system UI modes. + * + */ +public class SystemBarTintManager { + + static { + // Android allows a system property to override the presence of the + // navigation bar. + // Used by the emulator. + // See + // https://github.com/android/platform_frameworks_base/blob/master/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java#L1076 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + try { + Class c = Class.forName("android.os.SystemProperties"); + Method m = c.getDeclaredMethod("get", String.class); + m.setAccessible(true); + sNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys"); + } catch (Throwable e) { + sNavBarOverride = null; + } + } + } + + /** + * The default system bar tint color value. + */ + public static final int DEFAULT_TINT_COLOR = 0x99000000; + + private static String sNavBarOverride; + + private final SystemBarConfig mConfig; + private boolean mStatusBarAvailable; + private boolean mNavBarAvailable; + private boolean mStatusBarTintEnabled; + private boolean mNavBarTintEnabled; + private View mStatusBarTintView; + private View mNavBarTintView; + + /** + * Constructor. Call this in the host activity onCreate method after its + * content view has been set. You should always create new instances when + * the host activity is recreated. + * + * @param activity + * The host activity. + */ + @TargetApi(19) + public SystemBarTintManager(Activity activity) { + + Window win = activity.getWindow(); + ViewGroup decorViewGroup = (ViewGroup) win.getDecorView(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + // check theme attrs + int[] attrs = { android.R.attr.windowTranslucentStatus, + android.R.attr.windowTranslucentNavigation }; + TypedArray a = activity.obtainStyledAttributes(attrs); + try { + mStatusBarAvailable = a.getBoolean(0, false); + mNavBarAvailable = a.getBoolean(1, false); + } finally { + a.recycle(); + } + + // check window flags + WindowManager.LayoutParams winParams = win.getAttributes(); + int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; + if ((winParams.flags & bits) != 0) { + mStatusBarAvailable = true; + } + bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; + if ((winParams.flags & bits) != 0) { + mNavBarAvailable = true; + } + } + + mConfig = new SystemBarConfig(activity, mStatusBarAvailable, + mNavBarAvailable); + // device might not have virtual navigation keys + if (!mConfig.hasNavigtionBar()) { + mNavBarAvailable = false; + } + + if (mStatusBarAvailable) { + setupStatusBarView(activity, decorViewGroup); + } + if (mNavBarAvailable) { + setupNavBarView(activity, decorViewGroup); + } + + } + + /** + * Enable tinting of the system status bar. + * + * If the platform is running Jelly Bean or earlier, or translucent system + * UI modes have not been enabled in either the theme or via window flags, + * then this method does nothing. + * + * @param enabled + * True to enable tinting, false to disable it (default). + */ + public void setStatusBarTintEnabled(boolean enabled) { + mStatusBarTintEnabled = enabled; + if (mStatusBarAvailable) { + mStatusBarTintView + .setVisibility(enabled ? View.VISIBLE : View.GONE); + } + } + + /** + * Enable tinting of the system navigation bar. + * + * If the platform does not have soft navigation keys, is running Jelly Bean + * or earlier, or translucent system UI modes have not been enabled in + * either the theme or via window flags, then this method does nothing. + * + * @param enabled + * True to enable tinting, false to disable it (default). + */ + public void setNavigationBarTintEnabled(boolean enabled) { + mNavBarTintEnabled = enabled; + if (mNavBarAvailable) { + mNavBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE); + } + } + + /** + * Apply the specified color tint to all system UI bars. + * + * @param color + * The color of the background tint. + */ + public void setTintColor(int color) { + setStatusBarTintColor(color); + setNavigationBarTintColor(color); + } + + /** + * Apply the specified drawable or color resource to all system UI bars. + * + * @param res + * The identifier of the resource. + */ + public void setTintResource(int res) { + setStatusBarTintResource(res); + setNavigationBarTintResource(res); + } + + /** + * Apply the specified drawable to all system UI bars. + * + * @param drawable + * The drawable to use as the background, or null to remove it. + */ + public void setTintDrawable(Drawable drawable) { + setStatusBarTintDrawable(drawable); + setNavigationBarTintDrawable(drawable); + } + + /** + * Apply the specified alpha to all system UI bars. + * + * @param alpha + * The alpha to use + */ + public void setTintAlpha(float alpha) { + setStatusBarAlpha(alpha); + setNavigationBarAlpha(alpha); + } + + /** + * Apply the specified color tint to the system status bar. + * + * @param color + * The color of the background tint. + */ + public void setStatusBarTintColor(int color) { + if (mStatusBarAvailable) { + mStatusBarTintView.setBackgroundColor(color); + } + } + + /** + * Apply the specified drawable or color resource to the system status bar. + * + * @param res + * The identifier of the resource. + */ + public void setStatusBarTintResource(int res) { + if (mStatusBarAvailable) { + mStatusBarTintView.setBackgroundResource(res); + } + } + + /** + * Apply the specified drawable to the system status bar. + * + * @param drawable + * The drawable to use as the background, or null to remove it. + */ + @SuppressWarnings("deprecation") + public void setStatusBarTintDrawable(Drawable drawable) { + if (mStatusBarAvailable) { + mStatusBarTintView.setBackgroundDrawable(drawable); + } + } + + /** + * Apply the specified alpha to the system status bar. + * + * @param alpha + * The alpha to use + */ + @TargetApi(11) + public void setStatusBarAlpha(float alpha) { + if (mStatusBarAvailable + && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + mStatusBarTintView.setAlpha(alpha); + } + } + + /** + * Apply the specified color tint to the system navigation bar. + * + * @param color + * The color of the background tint. + */ + public void setNavigationBarTintColor(int color) { + if (mNavBarAvailable) { + mNavBarTintView.setBackgroundColor(color); + } + } + + /** + * Apply the specified drawable or color resource to the system navigation + * bar. + * + * @param res + * The identifier of the resource. + */ + public void setNavigationBarTintResource(int res) { + if (mNavBarAvailable) { + mNavBarTintView.setBackgroundResource(res); + } + } + + /** + * Apply the specified drawable to the system navigation bar. + * + * @param drawable + * The drawable to use as the background, or null to remove it. + */ + @SuppressWarnings("deprecation") + public void setNavigationBarTintDrawable(Drawable drawable) { + if (mNavBarAvailable) { + mNavBarTintView.setBackgroundDrawable(drawable); + } + } + + /** + * Apply the specified alpha to the system navigation bar. + * + * @param alpha + * The alpha to use + */ + @TargetApi(11) + public void setNavigationBarAlpha(float alpha) { + if (mNavBarAvailable + && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + mNavBarTintView.setAlpha(alpha); + } + } + + /** + * Get the system bar configuration. + * + * @return The system bar configuration for the current device + * configuration. + */ + public SystemBarConfig getConfig() { + return mConfig; + } + + /** + * Is tinting enabled for the system status bar? + * + * @return True if enabled, False otherwise. + */ + public boolean isStatusBarTintEnabled() { + return mStatusBarTintEnabled; + } + + /** + * Is tinting enabled for the system navigation bar? + * + * @return True if enabled, False otherwise. + */ + public boolean isNavBarTintEnabled() { + return mNavBarTintEnabled; + } + + private void setupStatusBarView(Context context, ViewGroup decorViewGroup) { + mStatusBarTintView = new View(context); + LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, + mConfig.getStatusBarHeight()); + params.gravity = Gravity.TOP; + if (mNavBarAvailable && !mConfig.isNavigationAtBottom()) { + params.rightMargin = mConfig.getNavigationBarWidth(); + } + mStatusBarTintView.setLayoutParams(params); + mStatusBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR); + mStatusBarTintView.setVisibility(View.GONE); + decorViewGroup.addView(mStatusBarTintView); + } + + private void setupNavBarView(Context context, ViewGroup decorViewGroup) { + mNavBarTintView = new View(context); + LayoutParams params; + if (mConfig.isNavigationAtBottom()) { + params = new LayoutParams(LayoutParams.MATCH_PARENT, + mConfig.getNavigationBarHeight()); + params.gravity = Gravity.BOTTOM; + } else { + params = new LayoutParams(mConfig.getNavigationBarWidth(), + LayoutParams.MATCH_PARENT); + params.gravity = Gravity.RIGHT; + } + mNavBarTintView.setLayoutParams(params); + mNavBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR); + mNavBarTintView.setVisibility(View.GONE); + decorViewGroup.addView(mNavBarTintView); + } + + /** + * Class which describes system bar sizing and other characteristics for the + * current device configuration. + * + */ + public static class SystemBarConfig { + + private static final String STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height"; + private static final String NAV_BAR_HEIGHT_RES_NAME = "navigation_bar_height"; + private static final String NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME = "navigation_bar_height_landscape"; + private static final String NAV_BAR_WIDTH_RES_NAME = "navigation_bar_width"; + private static final String SHOW_NAV_BAR_RES_NAME = "config_showNavigationBar"; + + private final boolean mTranslucentStatusBar; + private final boolean mTranslucentNavBar; + private final int mStatusBarHeight; + private final int mActionBarHeight; + private final boolean mHasNavigationBar; + private final int mNavigationBarHeight; + private final int mNavigationBarWidth; + private final boolean mInPortrait; + private final float mSmallestWidthDp; + + private SystemBarConfig(Activity activity, + boolean translucentStatusBar, boolean traslucentNavBar) { + Resources res = activity.getResources(); + mInPortrait = (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT); + mSmallestWidthDp = getSmallestWidthDp(activity); + mStatusBarHeight = getInternalDimensionSize(res, + STATUS_BAR_HEIGHT_RES_NAME); + mActionBarHeight = getActionBarHeight(activity); + mNavigationBarHeight = getNavigationBarHeight(activity); + mNavigationBarWidth = getNavigationBarWidth(activity); + mHasNavigationBar = (mNavigationBarHeight > 0); + mTranslucentStatusBar = translucentStatusBar; + mTranslucentNavBar = traslucentNavBar; + } + + @TargetApi(14) + private int getActionBarHeight(Context context) { + int result = 0; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + TypedValue tv = new TypedValue(); + context.getTheme().resolveAttribute( + android.R.attr.actionBarSize, tv, true); + result = TypedValue.complexToDimensionPixelSize(tv.data, + context.getResources().getDisplayMetrics()); + } + return result; + } + + @TargetApi(14) + private int getNavigationBarHeight(Context context) { + Resources res = context.getResources(); + int result = 0; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + if (hasNavBar(context)) { + String key; + if (mInPortrait) { + key = NAV_BAR_HEIGHT_RES_NAME; + } else { + key = NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME; + } + return getInternalDimensionSize(res, key); + } + } + return result; + } + + @TargetApi(14) + private int getNavigationBarWidth(Context context) { + Resources res = context.getResources(); + int result = 0; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + if (hasNavBar(context)) { + return getInternalDimensionSize(res, NAV_BAR_WIDTH_RES_NAME); + } + } + return result; + } + + @TargetApi(14) + private boolean hasNavBar(Context context) { + Resources res = context.getResources(); + int resourceId = res.getIdentifier(SHOW_NAV_BAR_RES_NAME, "bool", + "android"); + if (resourceId != 0) { + boolean hasNav = res.getBoolean(resourceId); + // check override flag (see static block) + if ("1".equals(sNavBarOverride)) { + hasNav = false; + } else if ("0".equals(sNavBarOverride)) { + hasNav = true; + } + return hasNav; + } else { // fallback + return !ViewConfiguration.get(context).hasPermanentMenuKey(); + } + } + + private int getInternalDimensionSize(Resources res, String key) { + int result = 0; + int resourceId = res.getIdentifier(key, "dimen", "android"); + if (resourceId > 0) { + result = res.getDimensionPixelSize(resourceId); + } + return result; + } + + @SuppressLint("NewApi") + private float getSmallestWidthDp(Activity activity) { + DisplayMetrics metrics = new DisplayMetrics(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + activity.getWindowManager().getDefaultDisplay() + .getRealMetrics(metrics); + } else { + // TODO this is not correct, but we don't really care pre-kitkat + activity.getWindowManager().getDefaultDisplay() + .getMetrics(metrics); + } + float widthDp = metrics.widthPixels / metrics.density; + float heightDp = metrics.heightPixels / metrics.density; + return Math.min(widthDp, heightDp); + } + + /** + * Should a navigation bar appear at the bottom of the screen in the + * current device configuration? A navigation bar may appear on the + * right side of the screen in certain configurations. + * + * @return True if navigation should appear at the bottom of the screen, + * False otherwise. + */ + public boolean isNavigationAtBottom() { + return (mSmallestWidthDp >= 600 || mInPortrait); + } + + /** + * Get the height of the system status bar. + * + * @return The height of the status bar (in pixels). + */ + public int getStatusBarHeight() { + return mStatusBarHeight; + } + + /** + * Get the height of the action bar. + * + * @return The height of the action bar (in pixels). + */ + public int getActionBarHeight() { + return mActionBarHeight; + } + + /** + * Does this device have a system navigation bar? + * + * @return True if this device uses soft key navigation, False + * otherwise. + */ + public boolean hasNavigtionBar() { + return mHasNavigationBar; + } + + /** + * Get the height of the system navigation bar. + * + * @return The height of the navigation bar (in pixels). If the device + * does not have soft navigation keys, this will always return + * 0. + */ + public int getNavigationBarHeight() { + return mNavigationBarHeight; + } + + /** + * Get the width of the system navigation bar when it is placed + * vertically on the screen. + * + * @return The width of the navigation bar (in pixels). If the device + * does not have soft navigation keys, this will always return + * 0. + */ + public int getNavigationBarWidth() { + return mNavigationBarWidth; + } + + /** + * Get the layout inset for any system UI that appears at the top of the + * screen. + * + * @param withActionBar + * True to include the height of the action bar, False + * otherwise. + * @return The layout inset (in pixels). + */ + public int getPixelInsetTop(boolean withActionBar) { + return (mTranslucentStatusBar ? mStatusBarHeight : 0) + + (withActionBar ? mActionBarHeight : 0); + } + + /** + * Get the layout inset for any system UI that appears at the bottom of + * the screen. + * + * @return The layout inset (in pixels). + */ + public int getPixelInsetBottom() { + if (mTranslucentNavBar && isNavigationAtBottom()) { + return mNavigationBarHeight; + } else { + return 0; + } + } + + /** + * Get the layout inset for any system UI that appears at the right of + * the screen. + * + * @return The layout inset (in pixels). + */ + public int getPixelInsetRight() { + if (mTranslucentNavBar && !isNavigationAtBottom()) { + return mNavigationBarWidth; + } else { + return 0; + } + } + + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/personal/PersonalFragment.java b/app/src/main/java/com/gh/gamecenter/personal/PersonalFragment.java new file mode 100644 index 0000000000..7fc509b58d --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/personal/PersonalFragment.java @@ -0,0 +1,150 @@ +package com.gh.gamecenter.personal; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v7.widget.LinearLayoutManager; +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.Utils; +import com.gh.common.view.VerticalItemDecoration; +import com.gh.download.DownloadManager; +import com.gh.gamecenter.R; +import com.gh.gamecenter.eventbus.EBDownloadDelete; +import com.gh.gamecenter.eventbus.EBLogout; +import com.gh.gamecenter.eventbus.EBNetworkState; +import com.gh.gamecenter.eventbus.EBPackage; +import com.gh.gamecenter.eventbus.EBRedDot; +import com.gh.gamecenter.eventbus.EBShowDone; +import com.gh.gamecenter.eventbus.EBSms; +import com.gh.gamecenter.eventbus.EBUISwitch; + +import de.greenrobot.event.EventBus; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-8-8 主页fragment3页面 + */ +public class PersonalFragment extends Fragment { + + private View view; + private RecyclerView gameRecyclerView; + private PersonalFragmentAdapter adapter; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + view = View.inflate(getActivity(), R.layout.home3_fragment, null); + + gameRecyclerView = (RecyclerView) view.findViewById(R.id.me_gamelist); + + gameRecyclerView.setHasFixedSize(true); + adapter = new PersonalFragmentAdapter(getActivity(), gameRecyclerView); + LinearLayoutManager linearLayoutManager = new LinearLayoutManager( + getActivity()); + linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + gameRecyclerView.setLayoutManager(linearLayoutManager); + gameRecyclerView.setAdapter(adapter); + gameRecyclerView.addItemDecoration(new VerticalItemDecoration(getActivity(), 1)); + + EventBus.getDefault().register(this); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + if (container != null) { + container.removeView(view); + } + return view; + } + + public void onEventMainThread(EBPackage busFour) { + Utils.log(busFour.getType() + "=" + busFour.getPackageName()); + if ("安装".equals(busFour.getType())) { + adapter.install(busFour.getPackageName()); + } else if ("卸载".equals(busFour.getType())) { + adapter.delete(busFour.getPackageName()); + } + } + + public void onEventMainThread(EBNetworkState busNetworkState) { + if (busNetworkState.isNetworkConnected() && adapter.isNetworkError()) { + adapter.reload(); + } + } + + public void onEventMainThread(EBUISwitch busNine) { + if ("MainActivity".equals(busNine.getFrom())) { + if (busNine.getPosition() != 2) { + adapter.hidePlatformView(); + adapter.clearStatusMap(); + } + } + } + + public void onEventMainThread(EBRedDot busEight) { + adapter.notifyItemChanged(0); + } + + public void onEventMainThread(EBSms sms) { + if ("注册验证".equals(sms.getType())) { + adapter.setCode(sms.getCode()); + } + } + + public void onEventMainThread(EBLogout logout) { + if (logout.getType() == 0) { + adapter.logout(); + } else { + adapter.notifyItemChanged(0); + } + } + + public void onEventMainThread(EBShowDone showDone) { + if ("我的游戏".equals(showDone.getFrom()) && gameRecyclerView != null) { + gameRecyclerView.smoothScrollToPosition(showDone.getPosition()); + } + } + + public void onEventMainThread(EBDownloadDelete busThree) { + adapter.updateItem(busThree); + } + + @Override + public void onPause() { + super.onPause(); + adapter.hidePlatformView(); + adapter.clearStatusMap(); + DownloadManager.getInstance(getActivity()).removeObserver( + adapter.getDataWatcher()); + } + + @Override + public void onResume() { + super.onResume(); + DownloadManager.getInstance(getActivity()).addObserver( + adapter.getDataWatcher()); + } + + @Override + public void onDestroy() { + + super.onDestroy(); + EventBus.getDefault().unregister(this); + AppController.canclePendingRequests( + PersonalFragment.class); + view = null; + gameRecyclerView = null; + adapter = null; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/personal/PersonalFragmentAdapter.java b/app/src/main/java/com/gh/gamecenter/personal/PersonalFragmentAdapter.java new file mode 100644 index 0000000000..aaf998dcea --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/personal/PersonalFragmentAdapter.java @@ -0,0 +1,3190 @@ +package com.gh.gamecenter.personal; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.regex.Pattern; + +import org.json.JSONException; +import org.json.JSONObject; + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.graphics.Color; +import android.graphics.Rect; +import android.graphics.drawable.ClipDrawable; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.graphics.drawable.LayerDrawable; +import android.os.Build; +import android.os.Handler; +import android.os.Message; +import android.support.v4.app.FragmentActivity; +import android.support.v4.util.ArrayMap; +import android.support.v4.widget.ContentLoadingProgressBar; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.RecyclerView.ViewHolder; +import android.telephony.TelephonyManager; +import android.text.Editable; +import android.text.Html; +import android.text.InputType; +import android.text.Spanned; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.text.method.NumberKeyListener; +import android.util.DisplayMetrics; +import android.util.Log; +import android.util.SparseArray; +import android.util.SparseBooleanArray; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.RelativeLayout.LayoutParams; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.volley.NoConnectionError; +import com.android.volley.Request.Method; +import com.android.volley.Response; +import com.android.volley.TimeoutError; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.common.util.DeviceUtils; +import com.gh.common.util.DialogUtils; +import com.gh.common.util.DisplayUtils; +import com.gh.common.util.FileUtils; +import com.gh.common.util.ImageUtils; +import com.gh.common.util.MD5Utils; +import com.gh.common.util.PackageUtils; +import com.gh.common.util.PlatformUtils; +import com.gh.common.util.RSEUtils; +import com.gh.common.util.TimestampUtils; +import com.gh.common.util.TokenUtils; +import com.gh.common.util.TrafficUtils; +import com.gh.common.util.Utils; +import com.gh.common.view.HorizontalItemDecoration; +import com.gh.common.view.MyGame_LinearLayout; +import com.gh.download.DataWatcher; +import com.gh.download.DownloadEntry; +import com.gh.download.DownloadManager; +import com.gh.gamecenter.ConcernActivity; +import com.gh.gamecenter.DownloadManagerActivity; +import com.gh.gamecenter.GameDetailsActivity; +import com.gh.gamecenter.MainActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.RetrieveActivity; +import com.gh.gamecenter.SettingActivity; +import com.gh.gamecenter.UserInfoActivity; +import com.gh.gamecenter.db.info.ConcernInfo; +import com.gh.gamecenter.db.info.GameInfo; +import com.gh.gamecenter.entity.ApkEntity; +import com.gh.gamecenter.entity.GameDigestEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.entity.GameUpdateEntity; +import com.gh.gamecenter.entity.MyGameInfo; +import com.gh.gamecenter.entity.UserEntity; +import com.gh.gamecenter.eventbus.EBDownloadDelete; +import com.gh.gamecenter.eventbus.EBPutUrl; +import com.gh.gamecenter.eventbus.EBRedDot; +import com.gh.gamecenter.manager.ConcernManager; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.manager.GameManager; +import com.gh.gamecenter.manager.PackageManager; +import com.gh.gamecenter.manager.SuspectedGameManager; +import com.gh.gamecenter.volley.extended.JsonObjectExtendedRequest; +import com.google.gson.Gson; +import com.tendcloud.tenddata.TCAgent; + +import de.greenrobot.event.EventBus; + +public class PersonalFragmentAdapter extends + RecyclerView.Adapter { + + private FragmentActivity fragmentActivity; + private RecyclerView gameRecyclerView; + + private ArrayList gameDetailedList; + private ArrayList sortedList; + private SparseBooleanArray isShowMap; + + private UserEntity user; + + private ArrayMap locationMap; + private SparseArray recyclerViewMap; + + private int oldClickViewPosition = -1; + + private boolean isLoading; + private boolean isNetworkError; + + private ArrayMap lastTimeMap; + private ArrayMap statusMap; + + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (msg.what == 0) { + notifyDataSetChanged(); + sendEmptyMessageDelayed(2, 500); + } else if (msg.what == 1) { + if (countdown == 0) { + code_tv_send_again.setText("重新获取"); + code_tv_send_again.setClickable(true); + } else if (countdown > 0) { + code_tv_send_again.setText("重新获取(" + countdown-- + ")"); + sendEmptyMessageDelayed(1, 1000); + } + } else if (msg.what == 2) { + SharedPreferences sp = fragmentActivity.getSharedPreferences( + Config.PREFERENCE, Context.MODE_PRIVATE); + boolean isLogin = sp.getBoolean("isLogin", false); + if (isLogin) { + String username = sp.getString("username", null); + String password = sp.getString("password", null); + login(username, password); + } + } else if (msg.what == Constants.CONTINUE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + Log.e("result", "resume"); + DownloadManager.getInstance(fragmentActivity).resume(url); + } + } else if (msg.what == Constants.PAUSE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + Log.e("result", "pause"); + DownloadManager.getInstance(fragmentActivity).pause(url); + } + } + } + }; + + public PersonalFragmentAdapter(FragmentActivity activity, + RecyclerView gRecyclerView) { + fragmentActivity = activity; + gameRecyclerView = gRecyclerView; + gameDetailedList = new ArrayList(); + isShowMap = new SparseBooleanArray(); + + isLoading = true; + isNetworkError = false; + + locationMap = new ArrayMap(); + recyclerViewMap = new SparseArray(); + + lastTimeMap = new ArrayMap(); + statusMap = new ArrayMap(); + + new Thread(runnable).start(); + + } + + Runnable runnable = new Runnable() { + @Override + public void run() { + sortGameList(); + + if (sortedList.isEmpty()) { + isLoading = false; + handler.sendEmptyMessage(0); + } else { + List ids = new ArrayList(); + for (MyGameInfo info : sortedList) { + ids.add(info.getGame_id()); + } + initGameList(ids); + } + } + }; + + private void sortGameList() { + + sortedList = new ArrayList(); + + ArrayList signatureList = new ArrayList(); + ArrayList unsignatureList = new ArrayList(); + ArrayList noopenList = new ArrayList(); + ArrayList oftenuseList = new ArrayList(); + + PackageManager pManager = new PackageManager(fragmentActivity); + + TrafficUtils tUtils = TrafficUtils.getInstance(fragmentActivity); + + ConcernManager cManager = new ConcernManager(fragmentActivity); + List runnableGame = cManager.getInstalledGame(); + + for (ConcernInfo concernEntity : runnableGame) { + for (Entry entry : concernEntity.getPackageNames() + .entrySet()) { + if (entry.getValue()) { + MyGameInfo info = new MyGameInfo(); + info.setGame_id(concernEntity.getId()); + info.setPackage_name(entry.getKey()); + info.setTraffic(tUtils.getTraffice(entry.getKey())); + info.setSignature(pManager.isSignature(entry.getKey())); + info.setInstalledTime(pManager.getInstalledTime(entry + .getKey())); + if (info.isSignature()) { + signatureList.add(info); + } else { + unsignatureList.add(info); + } + } + } + } + + for (MyGameInfo info : signatureList) { + if (info.getTraffic() == 0) { + noopenList.add(info); + } else { + oftenuseList.add(info); + } + } + + Comparator comparator = new Comparator() { + @Override + public int compare(MyGameInfo lhs, MyGameInfo rhs) { + + if (rhs.getInstalledTime() > lhs.getInstalledTime()) { + return 1; + } else if (rhs.getInstalledTime() < lhs.getInstalledTime()) { + return -1; + } else { + return 0; + } + } + }; + + Collections.sort(noopenList, comparator); + + comparator = new Comparator() { + @Override + public int compare(MyGameInfo lhs, MyGameInfo rhs) { + + if (rhs.getTraffic() > lhs.getTraffic()) { + return 1; + } else if (isLoading) { + return -1; + } else { + return 0; + } + } + }; + + Collections.sort(oftenuseList, comparator); + + Collections.sort(unsignatureList, comparator); + + for (int i = 0, sizei = noopenList.size(); i < sizei; i++) { + boolean flag = true; + for (int j = 0, sizej = sortedList.size(); j < sizej; j++) { + if (sortedList.get(j).getGame_id() + .equals(noopenList.get(i).getGame_id())) { + flag = false; + MyGameInfo gameInfo = sortedList.get(j); + ArrayList list = gameInfo.getPackageList(); + if (list == null) { + list = new ArrayList(); + list.add(gameInfo.getPackage_name()); + } + list.add(noopenList.get(i).getPackage_name()); + gameInfo.setPackageList(list); + sortedList.set(j, gameInfo); + break; + } + } + if (flag) { + sortedList.add(noopenList.get(i)); + } + } + for (int i = 0, size = oftenuseList.size(); i < size; i++) { + boolean flag = true; + for (int j = 0, sizej = sortedList.size(); j < sizej; j++) { + if (sortedList.get(j).getGame_id() + .equals(oftenuseList.get(i).getGame_id())) { + flag = false; + MyGameInfo gameInfo = sortedList.get(j); + ArrayList list = gameInfo.getPackageList(); + if (list == null) { + list = new ArrayList(); + list.add(gameInfo.getPackage_name()); + } + list.add(oftenuseList.get(i).getPackage_name()); + gameInfo.setPackageList(list); + sortedList.set(j, gameInfo); + break; + } + } + if (flag) { + sortedList.add(oftenuseList.get(i)); + } + } + for (int i = 0, size = unsignatureList.size(); i < size; i++) { + boolean flag = true; + for (int j = 0, sizej = sortedList.size(); j < sizej; j++) { + if (sortedList.get(j).getGame_id() + .equals(unsignatureList.get(i).getGame_id())) { + flag = false; + MyGameInfo gameInfo = sortedList.get(j); + ArrayList list = gameInfo.getPackageList(); + if (list == null) { + list = new ArrayList(); + list.add(gameInfo.getPackage_name()); + } + list.add(unsignatureList.get(i).getPackage_name()); + gameInfo.setPackageList(list); + sortedList.set(j, gameInfo); + break; + } + } + if (flag) { + sortedList.add(unsignatureList.get(i)); + } + } + } + + private void initGameList(List ids) { + final List result = new ArrayList(); + final int count = ids.size(); + for (int i = 0, size = ids.size(); i < size; i++) { + JsonObjectExtendedRequest objectRequest = new JsonObjectExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + "v1d45/game/" + + ids.get(i) + "/digest", Constants.GAME_CD), + new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + result.add(response); + if (result.size() == count) { + processingData(result); + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + // 无网络连接和访问超时 + if (error.getClass() + .equals(NoConnectionError.class) + || error.getClass().equals( + TimeoutError.class)) { + Toast.makeText(fragmentActivity, "网络错误", + Toast.LENGTH_SHORT).show(); + isNetworkError = true; + notifyItemChanged(getItemCount() - 1); + } + } + }); + AppController.addToRequestQueue(objectRequest, + PersonalFragmentAdapter.class); + } + } + + private void processingData(List data) { + Gson gson = new Gson(); + List gameList = new ArrayList(); + for (int i = 0, size = data.size(); i < size; i++) { + gameList.add(gson + .fromJson(data.get(i).toString(), GameEntity.class)); + } + if (gameList != null && !gameList.isEmpty()) { + for (int i = 0, size = sortedList.size(); i < size; i++) { + String id = sortedList.get(i).getGame_id(); + for (GameEntity entity : gameList) { + if (entity.getId().equals(id)) { + gameDetailedList.add(entity); + } + } + } + GameManager manager = new GameManager(fragmentActivity); + for (GameEntity entity : gameDetailedList) { + for (ApkEntity apkEntity : entity.getApk()) { + manager.addOrUpdate(new GameInfo( + apkEntity.getPackageName(), entity.getId(), entity + .getName())); + } + } + } + + isLoading = false; + // notifyDataSetChanged(); + handler.sendEmptyMessage(0); + } + + @Override + public int getItemCount() { + return 1 + 1 + gameDetailedList.size(); + } + + @Override + public int getItemViewType(int position) { + return position; + } + + @Override + public void onBindViewHolder(ViewHolder viewHolder, final int position) { + if (viewHolder instanceof FunctionViewHolder) { + final FunctionViewHolder holder = (FunctionViewHolder) viewHolder; + DisplayMetrics outMetrics = new DisplayMetrics(); + fragmentActivity.getWindowManager().getDefaultDisplay() + .getMetrics(outMetrics); + LayoutParams rparams = new LayoutParams( + DisplayUtils.dip2px(fragmentActivity, 140), + DisplayUtils.dip2px(fragmentActivity, 140)); + rparams.addRule(RelativeLayout.CENTER_HORIZONTAL); + rparams.topMargin = outMetrics.widthPixels / 5; + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { + Rect frame = new Rect(); + fragmentActivity.getWindow().getDecorView() + .getWindowVisibleDisplayFrame(frame); + rparams.topMargin -= frame.top; + } + holder.me_iv_icon.setLayoutParams(rparams); + int downloadSize = DownloadManager.getInstance(fragmentActivity) + .getAll().size(); + int updateSize = PackageManager.getUpdateList().size(); + if (downloadSize == 0) { + holder.me_tv_download.setVisibility(View.GONE); + } else { + holder.me_tv_download.setVisibility(View.VISIBLE); + holder.me_tv_download.setText("" + downloadSize); + } + if (updateSize == 0) { + holder.me_tv_update.setVisibility(View.GONE); + } else { + holder.me_tv_update.setVisibility(View.VISIBLE); + holder.me_tv_update.setText("" + updateSize); + } + if (user == null) { + // holder.me_tv_login.setVisibility(View.VISIBLE); + // holder.me_tv_register.setVisibility(View.VISIBLE); + // holder.me_cutting_line.setVisibility(View.VISIBLE); + holder.me_tv_nickname.setVisibility(View.INVISIBLE); + holder.me_tv_sign.setVisibility(View.INVISIBLE); + holder.me_iv_icon.setImageResource(R.drawable.me_icon); + } else { + // holder.me_tv_login.setVisibility(View.GONE); + // holder.me_tv_register.setVisibility(View.GONE); + // holder.me_cutting_line.setVisibility(View.GONE); + holder.me_tv_nickname.setVisibility(View.VISIBLE); + holder.me_tv_sign.setVisibility(View.VISIBLE); + holder.me_tv_nickname.setText(user.getName()); + if (user.getSign() != null) { + holder.me_tv_sign.setText(user.getSign()); + } + ImageUtils.getInstance(fragmentActivity).display( + user.getIcon(), holder.me_iv_icon); + } + + } else if (viewHolder instanceof MultiFunctionViewHolder) { + MultiFunctionViewHolder holder = (MultiFunctionViewHolder) viewHolder; + if (isNetworkError) { + holder.personal_progressbar.setVisibility(View.GONE); + holder.personal_loading.setText("加载失败,点击重试"); + holder.rootView.setClickable(true); + holder.rootView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + reload(); + } + }); + } else { + holder.personal_progressbar.setVisibility(View.VISIBLE); + holder.personal_loading.setText("加载中..."); + holder.rootView.setClickable(false); + if (isLoading) { + holder.personal_ll_loading.setVisibility(View.VISIBLE); + holder.personal_tv_none.setVisibility(View.GONE); + holder.personal_rl_label.setVisibility(View.GONE); + } else if (gameDetailedList.isEmpty()) { + holder.personal_ll_loading.setVisibility(View.GONE); + holder.personal_tv_none.setVisibility(View.VISIBLE); + holder.personal_rl_label.setVisibility(View.GONE); + } else { + holder.personal_ll_loading.setVisibility(View.GONE); + holder.personal_tv_none.setVisibility(View.GONE); + holder.personal_rl_label.setVisibility(View.VISIBLE); + } + } + } else if (viewHolder instanceof MyGameViewHolder) { + final MyGameViewHolder holder = (MyGameViewHolder) viewHolder; + + final GameEntity entity = gameDetailedList.get(position - 2); + + holder.gameName.setText(entity.getName()); + ImageUtils.getInstance(fragmentActivity).display(entity.getIcon(), + holder.gameIco); + holder.gameDetail.setText(entity.getBrief()); + + Boolean isShow = isShowMap.get(position); + if (isShow != null && isShow.booleanValue()) { + LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams( + LayoutParams.MATCH_PARENT, DisplayUtils.dip2px( + fragmentActivity, 136)); + holder.mygame_ll.setLayoutParams(lparams); + holder.mygame_rv_show.setVisibility(View.VISIBLE); + holder.gameBtn.setText("收起"); + } else { + LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams( + LayoutParams.MATCH_PARENT, DisplayUtils.dip2px( + fragmentActivity, 66)); + holder.mygame_ll.setLayoutParams(lparams); + holder.mygame_rv_show.setVisibility(View.GONE); + holder.gameBtn.setText("打开"); + } + + ArrayList list = sortedList.get(position - 2) + .getPackageList(); + if (list != null) { + ArrayList platformList = new ArrayList(); + GameEntity gameInfoEntity = gameDetailedList.get(position - 2); + for (int i = 0, size = list.size(); i < size; i++) { + String packageName = list.get(i); + for (ApkEntity apkEntity : gameInfoEntity.getApk()) { + if (packageName.equals(apkEntity.getPackageName())) { + platformList.add(apkEntity); + break; + } + } + } + for (int i = 0; i < platformList.size(); i++) { + String platformName = PlatformUtils.getInstance( + fragmentActivity).getPlatformName( + platformList.get(i).getPlatform()); + if (platformName == null) { + platformList.remove(i); + i--; + } + } + ((PlatformViewAdapter) holder.mygame_rv_show.getAdapter()) + .setList(platformList, entity, position); + + if (platformList.size() == 1) { + PackageManager mPackageManager = new PackageManager( + fragmentActivity); + if (entity.getTag() != null + && entity.getTag().size() != 0 + && !mPackageManager.isSignature(platformList.get(0) + .getPackageName())) { + holder.gameBtn.setText("插件化"); + } else { + holder.gameBtn.setText("启动"); + } + } + + String url = null; + for (int i = 0, size = platformList.size(); i < size; i++) { + url = platformList.get(i).getUrl(); + if (DownloadManager.getInstance(fragmentActivity).get(url) != null) { + locationMap.put(url, position); + break; + } + } + } else { + ApkEntity mApkEntity = null; + GameEntity gameInfoEntity = gameDetailedList.get(position - 2); + String packageName = sortedList.get(position - 2) + .getPackage_name(); + for (ApkEntity apkEntity : gameInfoEntity.getApk()) { + if (packageName.equals(apkEntity.getPackageName())) { + mApkEntity = apkEntity; + break; + } + } + if (mApkEntity != null) { + PackageManager mPackageManager = new PackageManager( + fragmentActivity); + if (entity.getTag() != null + && entity.getTag().size() != 0 + && !mPackageManager.isSignature(mApkEntity + .getPackageName())) { + holder.gameBtn.setText("插件化"); + ArrayList platformList = new ArrayList(); + platformList.add(mApkEntity); + ((PlatformViewAdapter) holder.mygame_rv_show + .getAdapter()).setList(platformList, entity, + position); + + String url = null; + for (int i = 0, size = platformList.size(); i < size; i++) { + url = platformList.get(i).getUrl(); + if (DownloadManager.getInstance(fragmentActivity) + .get(url) != null) { + locationMap.put(url, position); + break; + } + } + } else { + holder.gameBtn.setText("启动"); + } + } + } + recyclerViewMap.put(position, holder.mygame_rv_show); + } + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { + if (i == 0) { + return new FunctionViewHolder(LayoutInflater.from( + viewGroup.getContext()).inflate( + R.layout.home3_fragment_function, viewGroup, false)); + } else if (i == 1) { + return new MultiFunctionViewHolder(LayoutInflater.from( + viewGroup.getContext()).inflate( + R.layout.personal_footer_none_head, viewGroup, false)); + } else { + View view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.mygame_item, viewGroup, false); + view.setTag(i); + return new MyGameViewHolder(view); + } + } + + public class FunctionViewHolder extends ViewHolder implements + OnClickListener { + + private TextView me_tv_download, me_tv_update, me_tv_nickname, + me_tv_sign; + // private TextView me_tv_login, me_tv_register; + // private View me_cutting_line; + private ImageView me_iv_icon; + + public FunctionViewHolder(View convertView) { + super(convertView); + + convertView.findViewById(R.id.me_ll_concern).setOnClickListener( + this); + convertView.findViewById(R.id.me_ll_download).setOnClickListener( + this); + convertView.findViewById(R.id.me_ll_setting).setOnClickListener( + this); + convertView.findViewById(R.id.me_ll_update) + .setOnClickListener(this); + me_tv_download = (TextView) convertView + .findViewById(R.id.me_tv_download); + me_tv_update = (TextView) convertView + .findViewById(R.id.me_tv_update); + me_iv_icon = (ImageView) convertView.findViewById(R.id.me_iv_icon); + me_iv_icon.setOnClickListener(this); + // me_tv_login = (TextView) + // convertView.findViewById(R.id.me_tv_login); + // me_tv_login.setOnClickListener(this); + // me_tv_register = (TextView) convertView + // .findViewById(R.id.me_tv_register); + // me_tv_register.setOnClickListener(this); + if (Config.isShow) { + convertView.findViewById(R.id.me_ll_download).setVisibility( + View.VISIBLE); + convertView.findViewById(R.id.me_ll_update).setVisibility( + View.VISIBLE); + } else { + convertView.findViewById(R.id.me_ll_download).setVisibility( + View.GONE); + convertView.findViewById(R.id.me_ll_update).setVisibility( + View.GONE); + } + me_tv_nickname = (TextView) convertView + .findViewById(R.id.me_tv_nickname); + me_tv_sign = (TextView) convertView.findViewById(R.id.me_tv_sign); + // me_cutting_line = convertView.findViewById(R.id.me_cutting_line); + } + + @Override + public void onClick(View v) { + final int id = v.getId(); + if (id == R.id.me_ll_concern) { + TCAgent.onEvent(fragmentActivity, "我的光环", "我的关注"); + + Map map = new HashMap(); + map.put("location", "我的关注"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "我的光环"); + DataCollectionManager.onEvent(fragmentActivity, "click-item", + map); + + fragmentActivity.startActivity(new Intent(fragmentActivity, + ConcernActivity.class)); + } else if (id == R.id.me_ll_download) { + TCAgent.onEvent(fragmentActivity, "我的光环", "下载管理"); + + Map map = new HashMap(); + map.put("location", "下载管理"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "我的光环"); + DataCollectionManager.onEvent(fragmentActivity, "click-item", + map); + + me_tv_download.setVisibility(View.GONE); + Intent downloadIntent = new Intent(fragmentActivity, + DownloadManagerActivity.class); + downloadIntent.putExtra("currentItem", 0); + fragmentActivity.startActivity(downloadIntent); + } else if (id == R.id.me_ll_setting) { + TCAgent.onEvent(fragmentActivity, "我的光环", "设置"); + + Map map = new HashMap(); + map.put("location", "设置"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "我的光环"); + DataCollectionManager.onEvent(fragmentActivity, "click-item", + map); + + fragmentActivity.startActivity(new Intent(fragmentActivity, + SettingActivity.class)); + } else if (id == R.id.me_ll_update) { + TCAgent.onEvent(fragmentActivity, "我的光环", "更新管理"); + + Map map = new HashMap(); + map.put("location", "更新管理"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "我的光环"); + DataCollectionManager.onEvent(fragmentActivity, "click-item", + map); + + me_tv_update.setVisibility(View.GONE); + Intent updateIntent = new Intent(fragmentActivity, + DownloadManagerActivity.class); + updateIntent.putExtra("currentItem", 1); + fragmentActivity.startActivity(updateIntent); + } + // else if (id == R.id.me_tv_login) { + // showMobileLoginDialog(); + // } else if (id == R.id.me_tv_register) { + // showOnekeyDialog(); + // } else if (id == R.id.me_iv_icon) { + // if (user != null) { + // Intent intent = new Intent(fragmentActivity, + // UserInfoActivity.class); + // fragmentActivity.startActivityForResult(intent, 0x123); + // } + // } + } + + } + + // 登录对话框 + private void showLoginDialog() { + final Dialog dialog = new Dialog(fragmentActivity); + View view = View.inflate(fragmentActivity, + R.layout.dialog_account_login, null); + + LinearLayout login_ll_dialog = (LinearLayout) view + .findViewById(R.id.account_login_ll_dialog); + DisplayMetrics outMetrics = new DisplayMetrics(); + fragmentActivity.getWindowManager().getDefaultDisplay() + .getMetrics(outMetrics); + LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams( + (int) (outMetrics.widthPixels * 0.8f), + LayoutParams.WRAP_CONTENT); + login_ll_dialog.setLayoutParams(lparams); + + view.findViewById(R.id.account_login_iv_close).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + + TextView forget = (TextView) view + .findViewById(R.id.account_login_tv_forget_password); + forget.setText(Html.fromHtml("忘记密码?")); + forget.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + Intent intent = new Intent(fragmentActivity, + RetrieveActivity.class); + fragmentActivity.startActivity(intent); + } + }); + final ImageView username_clean = (ImageView) view + .findViewById(R.id.account_login_iv_username_clean); + final ImageView password_clean = (ImageView) view + .findViewById(R.id.account_login_iv_password_clean); + final ImageView login_iv_username = (ImageView) view + .findViewById(R.id.account_login_iv_username); + final View login_username_cutting_line = view + .findViewById(R.id.account_login_username_cutting_line); + final ImageView login_iv_password = (ImageView) view + .findViewById(R.id.account_login_iv_password); + final View login_password_cutting_line = view + .findViewById(R.id.account_login_password_cutting_line); + final EditText username = (EditText) view + .findViewById(R.id.account_login_et_username); + final RelativeLayout login_rl_username = (RelativeLayout) view + .findViewById(R.id.account_login_rl_username); + username.setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (hasFocus) { + login_rl_username + .setBackgroundResource(R.drawable.border_input_dn); + login_iv_username + .setImageResource(R.drawable.login_username_dn); + login_username_cutting_line.setBackgroundColor(0xff1BA4FC); + if (username.getText().length() != 0) { + username_clean.setVisibility(View.VISIBLE); + } + } else { + login_rl_username + .setBackgroundResource(R.drawable.border_input_up); + login_iv_username + .setImageResource(R.drawable.login_username_up); + login_username_cutting_line.setBackgroundColor(0xffDBDBDB); + username_clean.setVisibility(View.GONE); + } + } + }); + username.addTextChangedListener(new TextWatcher() { + + @Override + public void onTextChanged(CharSequence s, int start, int before, + int count) { + + if (s.length() != 0) { + username_clean.setVisibility(View.VISIBLE); + } else { + username_clean.setVisibility(View.GONE); + } + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + username.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, + KeyEvent event) { + + if (actionId == EditorInfo.IME_ACTION_NEXT) { + String account = username.getText().toString().trim(); + if (TextUtils.isEmpty(account)) { + Toast.makeText(fragmentActivity, "请输入用户名", + Toast.LENGTH_SHORT).show(); + username.requestFocus(); + return true; + } else if (account.length() < 6 || account.length() > 18) { + Toast.makeText(fragmentActivity, "用户名长度错误", + Toast.LENGTH_SHORT).show(); + username.requestFocus(); + return true; + } else if (!Pattern.matches(Constants.REGEX_ACCOUNT, + account)) { + Toast.makeText(fragmentActivity, "用户名格式错误", + Toast.LENGTH_SHORT).show(); + username.requestFocus(); + return true; + } + } + return false; + } + }); + username.setKeyListener(new NumberKeyListener() { + @Override + public int getInputType() { + + return InputType.TYPE_CLASS_TEXT; + } + + @Override + protected char[] getAcceptedChars() { + return Constants.INPUT_RULE.toCharArray(); + } + }); + username_clean.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + username.setText(""); + } + }); + final EditText password = (EditText) view + .findViewById(R.id.account_login_et_password); + final RelativeLayout login_rl_password = (RelativeLayout) view + .findViewById(R.id.account_login_rl_password); + password.setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (hasFocus) { + login_rl_password + .setBackgroundResource(R.drawable.border_input_dn); + login_iv_password + .setImageResource(R.drawable.login_password_dn); + login_password_cutting_line.setBackgroundColor(0xff1BA4FC); + if (password.getText().length() != 0) { + password_clean.setVisibility(View.VISIBLE); + } + } else { + login_rl_password + .setBackgroundResource(R.drawable.border_input_up); + login_iv_password + .setImageResource(R.drawable.login_password_up); + login_password_cutting_line.setBackgroundColor(0xffDBDBDB); + password_clean.setVisibility(View.GONE); + } + } + }); + password.addTextChangedListener(new TextWatcher() { + + @Override + public void onTextChanged(CharSequence s, int start, int before, + int count) { + + if (s.length() != 0) { + password_clean.setVisibility(View.VISIBLE); + } else { + password_clean.setVisibility(View.GONE); + } + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + password.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, + KeyEvent event) { + + if (actionId == EditorInfo.IME_ACTION_DONE) { + String un = username.getText().toString(); + String pw = password.getText().toString(); + if (TextUtils.isEmpty(un)) { + Toast.makeText(fragmentActivity, "请输入用户名", + Toast.LENGTH_SHORT).show(); + username.requestFocus(); + return true; + } else if (un.length() < 6 || un.length() > 18) { + Toast.makeText(fragmentActivity, "用户名长度错误", + Toast.LENGTH_SHORT).show(); + username.requestFocus(); + return true; + } else if (!Pattern.matches(Constants.REGEX_ACCOUNT, un)) { + Toast.makeText(fragmentActivity, "用户名格式错误", + Toast.LENGTH_SHORT).show(); + username.requestFocus(); + return true; + } else if (TextUtils.isEmpty(pw)) { + Toast.makeText(fragmentActivity, "请输入密码", + Toast.LENGTH_SHORT).show(); + password.requestFocus(); + return true; + } else if (pw.length() < 6 || pw.length() > 32) { + Toast.makeText(fragmentActivity, "密码长度错误", + Toast.LENGTH_SHORT).show(); + password.requestFocus(); + return true; + } else if (!Pattern.matches(Constants.REGEX_PASSWORD, pw)) { + Toast.makeText(fragmentActivity, "密码格式错误", + Toast.LENGTH_SHORT).show(); + password.requestFocus(); + return true; + } else { + login(dialog, un, pw); + } + } + return false; + } + }); + password.setKeyListener(new NumberKeyListener() { + @Override + public int getInputType() { + + return InputType.TYPE_TEXT_VARIATION_PASSWORD; + } + + @Override + protected char[] getAcceptedChars() { + return Constants.INPUT_RULE.toCharArray(); + } + }); + password_clean.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + password.setText(""); + } + }); + TextView login = (TextView) view + .findViewById(R.id.account_login_tv_login); + login.requestFocus(); + login.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + String un = username.getText().toString(); + String pw = password.getText().toString(); + if (TextUtils.isEmpty(un)) { + Toast.makeText(fragmentActivity, "请输入用户名", + Toast.LENGTH_SHORT).show(); + username.requestFocus(); + } else if (un.length() < 6 || un.length() > 18) { + Toast.makeText(fragmentActivity, "用户名长度错误", + Toast.LENGTH_SHORT).show(); + username.requestFocus(); + } else if (!Pattern.matches(Constants.REGEX_ACCOUNT, un)) { + Toast.makeText(fragmentActivity, "用户名格式错误", + Toast.LENGTH_SHORT).show(); + username.requestFocus(); + } else if (TextUtils.isEmpty(pw)) { + Toast.makeText(fragmentActivity, "请输入密码", + Toast.LENGTH_SHORT).show(); + password.requestFocus(); + } else if (pw.length() < 6 || pw.length() > 32) { + Toast.makeText(fragmentActivity, "密码长度错误", + Toast.LENGTH_SHORT).show(); + password.requestFocus(); + } else if (!Pattern.matches(Constants.REGEX_PASSWORD, pw)) { + Toast.makeText(fragmentActivity, "密码格式错误", + Toast.LENGTH_SHORT).show(); + password.requestFocus(); + } else { + login(dialog, un, pw); + } + } + }); + view.findViewById(R.id.account_login_tv_mobile_login) + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + showMobileLoginDialog(); + } + }); + view.findViewById(R.id.account_login_tv_account_register) + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + showRegisterDialog(); + } + }); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.getWindow().setSoftInputMode( + WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE + | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); + dialog.setContentView(view); + dialog.show(); + } + + private void showMobileLoginDialog() { + final Dialog dialog = new Dialog(fragmentActivity); + View view = View.inflate(fragmentActivity, + R.layout.dialog_mobile_login, null); + + // 设置dialog宽度 + LinearLayout login_ll_dialog = (LinearLayout) view + .findViewById(R.id.mobile_login_ll_dialog); + DisplayMetrics outMetrics = new DisplayMetrics(); + fragmentActivity.getWindowManager().getDefaultDisplay() + .getMetrics(outMetrics); + LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams( + (int) (outMetrics.widthPixels * 0.8f), + LayoutParams.WRAP_CONTENT); + login_ll_dialog.setLayoutParams(lparams); + + view.findViewById(R.id.mobile_login_iv_close).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + + final EditText mobile = (EditText) view + .findViewById(R.id.mobile_login_et_mobile); + mobile.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, + KeyEvent event) { + + if (actionId == EditorInfo.IME_ACTION_DONE) { + String mobileNumber = mobile.getText().toString().trim(); + if (TextUtils.isEmpty(mobileNumber)) { + Toast.makeText(fragmentActivity, "请输入手机号码", + Toast.LENGTH_SHORT).show(); + return true; + } else if (mobileNumber.length() != 11) { + Toast.makeText(fragmentActivity, "手机号码长度错误", + Toast.LENGTH_SHORT).show(); + return true; + } else if (!Pattern.matches(Constants.REGEX_MOBILE, + mobileNumber)) { + Toast.makeText(fragmentActivity, "手机号码格式错误", + Toast.LENGTH_SHORT).show(); + return true; + } else { + login(dialog, mobileNumber); + } + } + return false; + } + }); + + final ImageView clean = (ImageView) view + .findViewById(R.id.mobile_login_iv_username_clean); + clean.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + mobile.setText(""); + } + }); + mobile.setKeyListener(new NumberKeyListener() { + @Override + public int getInputType() { + + return InputType.TYPE_CLASS_PHONE; + } + + @Override + protected char[] getAcceptedChars() { + return "1234567890".toCharArray(); + } + }); + mobile.addTextChangedListener(new TextWatcher() { + + @Override + public void onTextChanged(CharSequence s, int start, int before, + int count) { + + if (s.length() != 0) { + clean.setVisibility(View.VISIBLE); + } else { + clean.setVisibility(View.GONE); + } + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + + TextView login = (TextView) view + .findViewById(R.id.mobile_login_tv_login); + login.requestFocus(); + login.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + String mobileNumber = mobile.getText().toString().trim(); + if (TextUtils.isEmpty(mobileNumber)) { + Toast.makeText(fragmentActivity, "请输入手机号码", + Toast.LENGTH_SHORT).show(); + } else if (mobileNumber.length() != 11) { + Toast.makeText(fragmentActivity, "手机号码长度错误", + Toast.LENGTH_SHORT).show(); + } else if (!Pattern.matches(Constants.REGEX_MOBILE, + mobileNumber)) { + Toast.makeText(fragmentActivity, "手机号码格式错误", + Toast.LENGTH_SHORT).show(); + } else { + login(dialog, mobileNumber); + } + } + }); + + view.findViewById(R.id.mobile_login_tv_account_login) + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + showLoginDialog(); + } + }); + view.findViewById(R.id.mobile_login_tv_mobile_register) + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + showOnekeyDialog(); + } + }); + // 查看是否登录过,获取登录过的账号用以显示 + + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.getWindow().setSoftInputMode( + WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE + | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); + dialog.setContentView(view); + dialog.show(); + } + + // 手机号码登录 + private void login(final Dialog dialog, final String mobileNumber) { + final Dialog waitDialog = DialogUtils.showWaitDialog(fragmentActivity, + "登录中..."); + String url = Config.HOST + "v2/token/mobile?time=" + + System.currentTimeMillis(); + Map params = DeviceUtils + .getDeviceParams(fragmentActivity); + params.put("mobile_number", mobileNumber); + JSONObject body = new JSONObject(params); + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Method.POST, url, body.toString(), + new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + + Utils.log(response.toString()); + waitDialog.dismiss(); + try { + dialog.dismiss(); + + Toast.makeText(fragmentActivity, "登录成功", + Toast.LENGTH_SHORT).show(); + + SharedPreferences sp = fragmentActivity + .getSharedPreferences(Config.PREFERENCE, + Context.MODE_PRIVATE); + Editor editor = sp.edit(); + editor.putString("token", + response.getString("token")); + editor.putLong("token_expire", + response.getLong("expire")); + editor.putBoolean("isLogin", true); + editor.putString("mobile_number", mobileNumber); + editor.apply(); + + user = new UserEntity(); + user.setName(response.getJSONObject("user") + .getString("name")); + user.setSign(response.getJSONObject("user") + .getString("sign")); + user.setIcon(response.getJSONObject("user") + .getString("icon")); + user.setAccount(response.getJSONObject("user") + .getString("account")); + user.setMobileNumber(mobileNumber.substring(0, 3) + + "****" + mobileNumber.substring(7, 11)); + user.setActivation(response.getJSONObject("user") + .getBoolean("isActivation")); + AppController.put("user", user); + + notifyItemChanged(0); + } catch (JSONException e) { + + e.printStackTrace(); + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + + Utils.log(error.toString()); + waitDialog.dismiss(); + try { + if (error.networkResponse != null) { + JSONObject response = new JSONObject( + new String(error.networkResponse.data)); + if (!response.isNull("reason")) { + String reason = response + .getString("reason"); + if ("USER_NO_EXIST".equals(reason)) { + Toast.makeText(fragmentActivity, + "用户不存在", Toast.LENGTH_SHORT) + .show(); + return; + } else if ("DEVICE_ERROR".equals(reason)) { + Toast.makeText(fragmentActivity, + "设备错误", Toast.LENGTH_SHORT) + .show(); + return; + } + } + } + } catch (JSONException e) { + + e.printStackTrace(); + } + Toast.makeText(fragmentActivity, "登录失败", + Toast.LENGTH_SHORT).show(); + } + }); + AppController.addToRequestQueue(request, PersonalFragment.class); + } + + private void login(String username, String password) { + String url = Config.HOST + "v2/token/user?time=" + + System.currentTimeMillis(); + login(url, null, username, password); + } + + private void login(Dialog dialog, String username, String password) { + login(null, dialog, username, password); + } + + private void login(String url, final Dialog dialog, final String username, + String password) { + final Dialog waitDialog = DialogUtils.showWaitDialog(fragmentActivity, + "登录中..."); + if (url == null) { + url = Config.HOST + "v2/user/login?time=" + + System.currentTimeMillis(); + } + Map params = DeviceUtils + .getDeviceParams(fragmentActivity); + params.put("username", username); + try { + String s = RSEUtils.encryptByPublic(password + username + + System.currentTimeMillis() / 1000); + Utils.log("加密 = " + s); + params.put("password", s); + } catch (Exception e) { + + e.printStackTrace(); + } + JSONObject body = new JSONObject(params); + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Method.POST, url, body.toString(), + new Response.Listener() { + @Override + public void onResponse(JSONObject response) { + waitDialog.dismiss(); + try { + if (dialog != null) { + dialog.dismiss(); + } + + Toast.makeText(fragmentActivity, "登录成功", + Toast.LENGTH_SHORT).show(); + + SharedPreferences sp = fragmentActivity + .getSharedPreferences(Config.PREFERENCE, + Context.MODE_PRIVATE); + Editor editor = sp.edit(); + editor.putString("token", + response.getString("token")); + editor.putLong("token_expire", + response.getLong("expire")); + editor.putBoolean("isLogin", true); + if (!response.isNull("code")) { + String code = response.getString("code"); + String ciphertext = RSEUtils + .decryptByPublic(code); + editor.putString("username", username); + editor.putString( + "password", + ciphertext.substring(0, + ciphertext.indexOf(username))); + } + editor.apply(); + + JSONObject jsonObject = response + .getJSONObject("user"); + user = new UserEntity(); + user.setName(jsonObject.getString("name")); + user.setIcon(jsonObject.getString("icon")); + user.setSign(jsonObject.getString("sign")); + if (!jsonObject.isNull("mobile_number")) { + user.setMobileNumber(jsonObject + .getString("mobile_number")); + } + user.setAccount(username); + user.setActivation(true); + AppController.put("user", user); + + notifyItemChanged(0); + } catch (JSONException e) { + + e.printStackTrace(); + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + waitDialog.dismiss(); + Utils.log(error.toString()); + try { + if (error.networkResponse != null) { + JSONObject response = new JSONObject( + new String(error.networkResponse.data)); + if (!response.isNull("reason")) { + String reason = response + .getString("reason"); + if ("USERNAME_NOT_EXIST".equals(reason)) { + Toast.makeText(fragmentActivity, + "用户不存在", Toast.LENGTH_SHORT) + .show(); + return; + } else if ("PASSWORD_ERROR".equals(reason)) { + Toast.makeText(fragmentActivity, + "密码错误", Toast.LENGTH_SHORT) + .show(); + return; + } + } + } + } catch (JSONException e) { + + e.printStackTrace(); + } + Toast.makeText(fragmentActivity, "登录失败", + Toast.LENGTH_SHORT).show(); + } + }); + AppController.addToRequestQueue(request, PersonalFragment.class); + } + + private void showRegisterDialog() { + final Dialog dialog = new Dialog(fragmentActivity); + View view = View.inflate(fragmentActivity, + R.layout.dialog_account_register, null); + + LinearLayout register_ll_dialog = (LinearLayout) view + .findViewById(R.id.register_ll_dialog); + DisplayMetrics outMetrics = new DisplayMetrics(); + fragmentActivity.getWindowManager().getDefaultDisplay() + .getMetrics(outMetrics); + LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams( + (int) (outMetrics.widthPixels * 0.8f), + LayoutParams.WRAP_CONTENT); + register_ll_dialog.setLayoutParams(lparams); + + view.findViewById(R.id.register_iv_close).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + + final ImageView username_clean = (ImageView) view + .findViewById(R.id.register_iv_username_clean); + final ImageView password_clean = (ImageView) view + .findViewById(R.id.register_iv_password_clean); + final ImageView register_iv_username = (ImageView) view + .findViewById(R.id.register_iv_username); + final ImageView register_iv_password = (ImageView) view + .findViewById(R.id.register_iv_password); + final View register_username_cutting_line = view + .findViewById(R.id.register_username_cutting_line); + final View register_password_cutting_line = view + .findViewById(R.id.register_password_cutting_line); + final EditText username = (EditText) view + .findViewById(R.id.register_et_username); + final RelativeLayout register_rl_username = (RelativeLayout) view + .findViewById(R.id.register_rl_username); + username.setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (hasFocus) { + register_rl_username + .setBackgroundResource(R.drawable.border_input_dn); + register_iv_username + .setImageResource(R.drawable.login_username_dn); + register_username_cutting_line + .setBackgroundColor(0xff1BA4FC); + if (username.getText().length() != 0) { + username_clean.setVisibility(View.VISIBLE); + } + } else { + register_rl_username + .setBackgroundResource(R.drawable.border_input_up); + register_iv_username + .setImageResource(R.drawable.login_username_up); + register_username_cutting_line + .setBackgroundColor(0xffDBDBDB); + username_clean.setVisibility(View.GONE); + } + } + }); + username.addTextChangedListener(new TextWatcher() { + + @Override + public void onTextChanged(CharSequence s, int start, int before, + int count) { + + if (s.length() != 0) { + username_clean.setVisibility(View.VISIBLE); + } else { + username_clean.setVisibility(View.GONE); + } + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + username.setOnEditorActionListener(new TextView.OnEditorActionListener() { + + @Override + public boolean onEditorAction(TextView v, int actionId, + KeyEvent event) { + + if (actionId == EditorInfo.IME_ACTION_NEXT) { + String un = username.getText().toString(); + if (TextUtils.isEmpty(un)) { + Toast.makeText(fragmentActivity, "请输入用户名", + Toast.LENGTH_SHORT).show(); + username.requestFocus(); + return true; + } else if (un.length() < 6 || un.length() > 18) { + Toast.makeText(fragmentActivity, "用户名长度错误", + Toast.LENGTH_SHORT).show(); + username.requestFocus(); + return true; + } else if (!Pattern.matches(Constants.REGEX_ACCOUNT, un)) { + Toast.makeText(fragmentActivity, "用户名格式错误", + Toast.LENGTH_SHORT).show(); + username.requestFocus(); + return true; + } + } + return false; + } + }); + username.setKeyListener(new NumberKeyListener() { + @Override + public int getInputType() { + + return InputType.TYPE_CLASS_TEXT; + } + + @Override + protected char[] getAcceptedChars() { + return Constants.INPUT_RULE.toCharArray(); + } + }); + username_clean.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + username.setText(""); + } + }); + final EditText password = (EditText) view + .findViewById(R.id.register_et_password); + final RelativeLayout register_rl_password = (RelativeLayout) view + .findViewById(R.id.register_rl_password); + password.setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (hasFocus) { + register_rl_password + .setBackgroundResource(R.drawable.border_input_dn); + register_iv_password + .setImageResource(R.drawable.login_password_dn); + register_password_cutting_line + .setBackgroundColor(0xff1BA4FC); + if (password.getText().length() != 0) { + password_clean.setVisibility(View.VISIBLE); + } + } else { + register_rl_password + .setBackgroundResource(R.drawable.border_input_up); + register_iv_password + .setImageResource(R.drawable.login_password_up); + register_password_cutting_line + .setBackgroundColor(0xffDBDBDB); + password_clean.setVisibility(View.GONE); + } + } + }); + password.addTextChangedListener(new TextWatcher() { + + @Override + public void onTextChanged(CharSequence s, int start, int before, + int count) { + + if (s.length() != 0) { + password_clean.setVisibility(View.VISIBLE); + } else { + password_clean.setVisibility(View.GONE); + } + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + password.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, + KeyEvent event) { + + if (actionId == EditorInfo.IME_ACTION_DONE) { + String un = username.getText().toString(); + String pw = password.getText().toString(); + if (TextUtils.isEmpty(un)) { + Toast.makeText(fragmentActivity, "请输入用户名", + Toast.LENGTH_SHORT).show(); + username.requestFocus(); + return true; + } else if (un.length() < 6 || un.length() > 18) { + Toast.makeText(fragmentActivity, "用户名长度错误", + Toast.LENGTH_SHORT).show(); + username.requestFocus(); + return true; + } else if (!Pattern.matches(Constants.REGEX_ACCOUNT, un)) { + Toast.makeText(fragmentActivity, "用户名格式错误", + Toast.LENGTH_SHORT).show(); + username.requestFocus(); + return true; + } else if (TextUtils.isEmpty(pw)) { + Toast.makeText(fragmentActivity, "请输入密码", + Toast.LENGTH_SHORT).show(); + password.requestFocus(); + return true; + } else if (pw.length() < 6 || pw.length() > 32) { + Toast.makeText(fragmentActivity, "密码长度错误", + Toast.LENGTH_SHORT).show(); + password.requestFocus(); + return true; + } else if (!Pattern.matches(Constants.REGEX_PASSWORD, pw)) { + Toast.makeText(fragmentActivity, "密码格式错误", + Toast.LENGTH_SHORT).show(); + password.requestFocus(); + return true; + } else { + register(dialog, un, pw); + } + } + return false; + } + }); + password.setKeyListener(new NumberKeyListener() { + @Override + public int getInputType() { + + return InputType.TYPE_TEXT_VARIATION_PASSWORD; + } + + @Override + protected char[] getAcceptedChars() { + return Constants.INPUT_RULE.toCharArray(); + } + }); + password_clean.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + password.setText(""); + } + }); + TextView register = (TextView) view + .findViewById(R.id.register_tv_register); + register.requestFocus(); + register.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + String un = username.getText().toString(); + String pw = password.getText().toString(); + if (TextUtils.isEmpty(un)) { + Toast.makeText(fragmentActivity, "请输入用户名", + Toast.LENGTH_SHORT).show(); + username.requestFocus(); + } else if (un.length() < 6 || un.length() > 18) { + Toast.makeText(fragmentActivity, "用户名长度错误", + Toast.LENGTH_SHORT).show(); + username.requestFocus(); + } else if (!Pattern.matches(Constants.REGEX_ACCOUNT, un)) { + Toast.makeText(fragmentActivity, "用户名格式错误", + Toast.LENGTH_SHORT).show(); + username.requestFocus(); + } else if (TextUtils.isEmpty(pw)) { + Toast.makeText(fragmentActivity, "请输入密码", + Toast.LENGTH_SHORT).show(); + password.requestFocus(); + } else if (pw.length() < 6 || pw.length() > 32) { + Toast.makeText(fragmentActivity, "密码长度错误", + Toast.LENGTH_SHORT).show(); + password.requestFocus(); + } else if (!Pattern.matches(Constants.REGEX_PASSWORD, pw)) { + Toast.makeText(fragmentActivity, "密码格式错误", + Toast.LENGTH_SHORT).show(); + password.requestFocus(); + } else { + register(dialog, un, pw); + } + } + }); + view.findViewById(R.id.register_tv_login).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + showLoginDialog(); + } + }); + view.findViewById(R.id.register_tv_mobile).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + showOnekeyDialog(); + } + }); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.getWindow().setSoftInputMode( + WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE + | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); + dialog.setContentView(view); + dialog.show(); + } + + private void showNicknameDialog(final String token) { + final Dialog dialog = new Dialog(fragmentActivity); + View view = View.inflate(fragmentActivity, R.layout.dialog_nickname, + null); + + RelativeLayout nickname_rl_dialog = (RelativeLayout) view + .findViewById(R.id.nickname_rl_dialog); + DisplayMetrics outMetrics = new DisplayMetrics(); + fragmentActivity.getWindowManager().getDefaultDisplay() + .getMetrics(outMetrics); + LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams( + (int) (outMetrics.widthPixels * 0.8f), + LayoutParams.WRAP_CONTENT); + nickname_rl_dialog.setLayoutParams(lparams); + + final EditText nickname = (EditText) view + .findViewById(R.id.nickname_et_nickname); + nickname.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, + KeyEvent event) { + + if (actionId == EditorInfo.IME_ACTION_DONE) { + String name = nickname.getText().toString(); + if (TextUtils.isEmpty(name)) { + Toast.makeText(fragmentActivity, "请输入昵称", + Toast.LENGTH_SHORT).show(); + nickname.requestFocus(); + return true; + } else { + user.setName(name); + notifyItemChanged(0); + dialog.dismiss(); + updateUserInfo(name, null, token); + } + } + return false; + } + }); + + view.findViewById(R.id.nickname_tv_confirm).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + String name = nickname.getText().toString(); + if (TextUtils.isEmpty(name)) { + Toast.makeText(fragmentActivity, "请输入昵称", + Toast.LENGTH_SHORT).show(); + nickname.requestFocus(); + } else { + user.setName(name); + notifyItemChanged(0); + dialog.dismiss(); + updateUserInfo(name, null, token); + } + } + }); + + view.findViewById(R.id.nickname_tv_skip).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + notifyItemChanged(0); + dialog.dismiss(); + } + }); + + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.getWindow().setSoftInputMode( + WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE + | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); + dialog.setContentView(view); + dialog.show(); + } + + // 修改用户信息 + private void updateUserInfo(final String name, final String sign, + final String token) { + final Dialog dialog = DialogUtils.showWaitDialog(fragmentActivity, + "保存中..."); + new Thread() { + @Override + public void run() { + String url = Config.HOST + "v2/user/info?time=" + + System.currentTimeMillis(); + Map params = new HashMap(); + if (!TextUtils.isEmpty(name)) { + params.put("name", name); + } + if (!TextUtils.isEmpty(sign)) { + params.put("sign", sign); + } + JSONObject body = new JSONObject(params); + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Method.POST, url, body.toString(), + new Response.Listener() { + @Override + public void onResponse(JSONObject response) { + + Utils.log(response.toString()); + dialog.dismiss(); + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + + Utils.log(error.toString()); + dialog.dismiss(); + } + }); + request.addHeader("Auth", token); + AppController + .addToRequestQueue(request, UserInfoActivity.class); + } + }.start(); + } + + private void register(final Dialog dialog, final String username, + String password) { + final Dialog waitDialog = DialogUtils.showWaitDialog(fragmentActivity, + "注册中..."); + String url = Config.HOST + "v2/user/registerV1d0?time=" + + System.currentTimeMillis(); + Map params = DeviceUtils + .getDeviceParams(fragmentActivity); + params.put("username", username); + try { + String s = RSEUtils.encryptByPublic(password + username + + System.currentTimeMillis() / 1000); + Utils.log("加密 = " + s); + params.put("password", s); + } catch (Exception e) { + e.printStackTrace(); + } + JSONObject body = new JSONObject(params); + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Method.POST, url, body.toString(), + new Response.Listener() { + @Override + public void onResponse(JSONObject response) { + waitDialog.dismiss(); + Utils.log(response.toString()); + try { + dialog.dismiss(); + Toast.makeText(fragmentActivity, "注册成功", + Toast.LENGTH_SHORT).show(); + + String token = response.getString("token"); + long expire = response.getLong("expire"); + SharedPreferences sp = fragmentActivity + .getSharedPreferences(Config.PREFERENCE, + Context.MODE_PRIVATE); + Editor editor = sp.edit(); + editor.putString("token", token); + editor.putLong("token_expire", expire); + editor.putBoolean("isLogin", true); + String code = response.getString("code"); + String ciphertext = RSEUtils.decryptByPublic(code); + editor.putString("username", username); + editor.putString( + "password", + ciphertext.substring(0, + ciphertext.indexOf(username))); + editor.apply(); + + user = new UserEntity(); + user.setName(response.getJSONObject("user") + .getString("name")); + user.setIcon(response.getJSONObject("user") + .getString("icon")); + AppController.put("user", user); + + showNicknameDialog(token); + } catch (JSONException e) { + + e.printStackTrace(); + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + Utils.log(error); + waitDialog.dismiss(); + try { + if (error.networkResponse != null) { + JSONObject response = new JSONObject( + new String(error.networkResponse.data)); + Utils.log(response.toString()); + if (!response.isNull("reason")) { + String reason = response + .getString("reason"); + if ("USER_EXIST".equals(reason)) { + Toast.makeText(fragmentActivity, + "用户名已存在", Toast.LENGTH_SHORT) + .show(); + return; + } + } + } + } catch (JSONException e) { + + e.printStackTrace(); + } + Toast.makeText(fragmentActivity, "注册失败", + Toast.LENGTH_SHORT).show(); + } + }); + AppController.addToRequestQueue(request, PersonalFragment.class); + } + + private void showOnekeyDialog() { + final Dialog dialog = new Dialog(fragmentActivity); + + View view = View.inflate(fragmentActivity, + R.layout.dialog_onekey_register, null); + + LinearLayout onekey_ll_dialog = (LinearLayout) view + .findViewById(R.id.onekey_register_ll_dialog); + DisplayMetrics outMetrics = new DisplayMetrics(); + fragmentActivity.getWindowManager().getDefaultDisplay() + .getMetrics(outMetrics); + LayoutParams lparams = new LayoutParams( + (int) (outMetrics.widthPixels * 0.8f), + LayoutParams.WRAP_CONTENT); + onekey_ll_dialog.setLayoutParams(lparams); + + view.findViewById(R.id.onekey_register_iv_close).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + + final ImageView mobile_clean = (ImageView) view + .findViewById(R.id.onekey_register_iv_mobile_clean); + final EditText mobile = (EditText) view + .findViewById(R.id.onekey_register_et_mobile); + mobile.addTextChangedListener(new TextWatcher() { + + @Override + public void onTextChanged(CharSequence s, int start, int before, + int count) { + + if (s.length() != 0) { + mobile_clean.setVisibility(View.VISIBLE); + } else { + mobile_clean.setVisibility(View.GONE); + } + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + mobile.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, + KeyEvent event) { + + if (actionId == EditorInfo.IME_ACTION_DONE) { + String mobileNumber = mobile.getText().toString(); + if (TextUtils.isEmpty(mobileNumber)) { + Toast.makeText(fragmentActivity, "手机号码为空", + Toast.LENGTH_SHORT).show(); + return true; + } else if (mobileNumber.length() != 11) { + Toast.makeText(fragmentActivity, "手机号长度错误", + Toast.LENGTH_SHORT).show(); + return true; + } else if (!Pattern.matches(Constants.REGEX_MOBILE, + mobileNumber)) { + Toast.makeText(fragmentActivity, "手机号码格式错误", + Toast.LENGTH_SHORT).show(); + return true; + } else { + getCode(dialog, mobileNumber); + } + } + return false; + } + }); + mobile.setKeyListener(new NumberKeyListener() { + @Override + public int getInputType() { + + return InputType.TYPE_CLASS_PHONE; + } + + @Override + protected char[] getAcceptedChars() { + return "1234567890".toCharArray(); + } + }); + mobile_clean.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + mobile.setText(""); + } + }); + + TelephonyManager tm = (TelephonyManager) fragmentActivity + .getSystemService(Context.TELEPHONY_SERVICE); + String number = tm.getLine1Number();// 获取本机号码 + if (!TextUtils.isEmpty(number)) { + mobile.setText(number); + mobile.setSelection(number.length()); + } + + view.findViewById(R.id.onekey_register_tv_send).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + String mobileNumber = mobile.getText().toString(); + if (TextUtils.isEmpty(mobileNumber)) { + Toast.makeText(fragmentActivity, "手机号码为空", + Toast.LENGTH_SHORT).show(); + } else if (mobileNumber.length() != 11) { + Toast.makeText(fragmentActivity, "手机号长度错误", + Toast.LENGTH_SHORT).show(); + } else if (!Pattern.matches(Constants.REGEX_MOBILE, + mobileNumber)) { + Toast.makeText(fragmentActivity, "手机号码格式错误", + Toast.LENGTH_SHORT).show(); + } else { + getCode(dialog, mobileNumber); + } + } + }); + view.findViewById(R.id.onekey_register_tv_mobile_login) + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + showMobileLoginDialog(); + } + }); + view.findViewById(R.id.onekey_register_tv_account_register) + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + showRegisterDialog(); + } + }); + + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.getWindow().setSoftInputMode( + WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE + | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); + dialog.setContentView(view); + dialog.show(); + } + + private TextView code_tv_send_again; + private EditText code_et_code; + + private int countdown = 60; + + private void showCodeDialog(final String mobileNumber) { + final Dialog dialog = new Dialog(fragmentActivity); + View view = View.inflate(fragmentActivity, R.layout.dialog_code, null); + + LinearLayout code_ll_dialog = (LinearLayout) view + .findViewById(R.id.code_ll_dialog); + DisplayMetrics outMetrics = new DisplayMetrics(); + fragmentActivity.getWindowManager().getDefaultDisplay() + .getMetrics(outMetrics); + LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams( + (int) (outMetrics.widthPixels * 0.8f), + LayoutParams.WRAP_CONTENT); + code_ll_dialog.setLayoutParams(lparams); + + view.findViewById(R.id.code_iv_close).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + + TextView code_tv_hint = (TextView) view.findViewById(R.id.code_tv_hint); + code_tv_hint.setText("已向手机号" + mobileNumber + "发送验证码"); + + code_tv_send_again = (TextView) view + .findViewById(R.id.code_tv_send_again); + code_tv_send_again.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + getCode(null, mobileNumber); + } + }); + code_tv_send_again.setClickable(false); + + code_et_code = (EditText) view.findViewById(R.id.code_et_code); + code_et_code + .setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, + KeyEvent event) { + + if (actionId == EditorInfo.IME_ACTION_DONE) { + String code = code_et_code.getText().toString(); + if (TextUtils.isEmpty(code)) { + Toast.makeText(fragmentActivity, "验证码为空", + Toast.LENGTH_SHORT).show(); + return true; + } else if (code.length() != 6) { + Toast.makeText(fragmentActivity, "验证码长度错误", + Toast.LENGTH_SHORT).show(); + return true; + } else if (!Pattern.matches("^\\d{6}$", code)) { + Toast.makeText(fragmentActivity, "验证码格式错误", + Toast.LENGTH_SHORT).show(); + return true; + } else { + registerDone(dialog, mobileNumber, code); + } + } + return false; + } + }); + view.findViewById(R.id.code_tv_done).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + String code = code_et_code.getText().toString(); + if (TextUtils.isEmpty(code)) { + Toast.makeText(fragmentActivity, "验证码为空", + Toast.LENGTH_SHORT).show(); + } else if (code.length() != 6) { + Toast.makeText(fragmentActivity, "验证码长度错误", + Toast.LENGTH_SHORT).show(); + } else if (!Pattern.matches("^\\d{6}$", code)) { + Toast.makeText(fragmentActivity, "验证码格式错误", + Toast.LENGTH_SHORT).show(); + } else { + registerDone(dialog, mobileNumber, code); + } + } + }); + + view.findViewById(R.id.code_tv_mobile).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + showLoginDialog(); + } + }); + + view.findViewById(R.id.code_tv_register).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + showRegisterDialog(); + } + }); + + dialog.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + handler.removeMessages(1); + } + }); + + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.getWindow().setSoftInputMode( + WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE + | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); + dialog.setContentView(view); + dialog.show(); + } + + // 获取验证码 + private void getCode(final Dialog dialog, final String mobileNumber) { + final Dialog waitDialog = DialogUtils.showWaitDialog(fragmentActivity, + "发送中..."); + new Thread() { + @Override + public void run() { + String url = Config.HOST + "v2/user/register/code/" + + mobileNumber + "?time=" + System.currentTimeMillis(); + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + url, new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + + waitDialog.dismiss(); + try { + if ("success".equals(response + .getString("status"))) { + Toast.makeText(fragmentActivity, + "发送成功", Toast.LENGTH_SHORT) + .show(); + if (code_tv_send_again != null) { + code_tv_send_again + .setClickable(false); + } + if (dialog != null) { + dialog.dismiss(); + showCodeDialog(mobileNumber); + } + countdown = 60; + handler.removeMessages(1); + handler.sendEmptyMessage(1); + } + } catch (JSONException e) { + + e.printStackTrace(); + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + + waitDialog.dismiss(); + try { + if (error.networkResponse != null) { + JSONObject response = new JSONObject( + new String( + error.networkResponse.data)); + if (!response.isNull("reason")) { + String reason = response + .getString("reason"); + if ("MOBILE_NUMBER_ERROR" + .equals(reason)) { + Toast.makeText( + fragmentActivity, + "手机号码错误", + Toast.LENGTH_SHORT) + .show(); + return; + } else if ("USER_EXIST" + .equals(reason)) { + Toast.makeText( + fragmentActivity, + "用户已存在", + Toast.LENGTH_SHORT) + .show(); + return; + } else if ("TIME_IS_NOT" + .equals(reason)) { + Toast.makeText( + fragmentActivity, + "稍后再试", + Toast.LENGTH_SHORT) + .show(); + return; + } + } + } + } catch (JSONException e) { + + e.printStackTrace(); + } + Toast.makeText(fragmentActivity, "发送失败", + Toast.LENGTH_SHORT).show(); + } + }); + String token = TokenUtils.getToken(fragmentActivity); + request.addHeader("Auth", token); + AppController + .addToRequestQueue(request, PersonalFragment.class); + } + }.start(); + } + + // 完成注册 + private void registerDone(final Dialog dialog, String mobileNumber, + String code) { + final Dialog waitDialog = DialogUtils.showWaitDialog(fragmentActivity, + "发送中..."); + String url = Config.HOST + "v2/user/onekey?time=" + + System.currentTimeMillis(); + Map params = DeviceUtils + .getDeviceParams(fragmentActivity); + params.put("mobile_number", mobileNumber); + params.put("code", code); + JSONObject body = new JSONObject(params); + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + Method.POST, url, body.toString(), + new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + + Utils.log(response.toString()); + waitDialog.dismiss(); + try { + dialog.dismiss(); + Toast.makeText(fragmentActivity, "注册成功", + Toast.LENGTH_SHORT).show(); + + SharedPreferences sp = fragmentActivity + .getSharedPreferences(Config.PREFERENCE, + Context.MODE_PRIVATE); + Editor editor = sp.edit(); + String token = response.getString("token"); + editor.putString("token", token); + editor.putLong("token_expire", + response.getLong("expire")); + editor.putBoolean("isAutoLogin", true); + editor.apply(); + + user = new UserEntity(); + user.setName(response.getJSONObject("user") + .getString("name")); + user.setIcon(response.getJSONObject("user") + .getString("icon")); + AppController.put("user", user); + + showNicknameDialog(token); + } catch (JSONException e) { + + e.printStackTrace(); + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + + Utils.log(error.toString()); + waitDialog.dismiss(); + try { + if (error.networkResponse != null) { + JSONObject response = new JSONObject( + new String(error.networkResponse.data)); + if (!response.isNull("reason")) { + String reason = response + .getString("reason"); + if ("CODE_ERROR".equals(reason)) { + Toast.makeText(fragmentActivity, + "验证码错误", Toast.LENGTH_SHORT) + .show(); + return; + } else if ("CODE_EXPIRE".equals(reason)) { + Toast.makeText(fragmentActivity, + "验证码过期", Toast.LENGTH_SHORT) + .show(); + return; + } + } + } + } catch (JSONException e) { + + e.printStackTrace(); + } + Toast.makeText(fragmentActivity, "注册失败", + Toast.LENGTH_SHORT).show(); + } + }); + AppController.addToRequestQueue(request, PersonalFragment.class); + } + + // 设置获取到的验证码 + public void setCode(String code) { + if (code_et_code != null) { + code_et_code.setText(code); + code_et_code.setSelection(code.length()); + } + } + + private DataWatcher dataWatcher = new DataWatcher() { + @Override + public void onDataChanged( + HashMap downloadingEntries) { + for (Entry entry : downloadingEntries + .entrySet()) { + DownloadEntry downloadEntry = entry.getValue(); + Integer location = locationMap.get(downloadEntry.getUrl()); + if (location != null) { + int position = location.intValue(); + RecyclerView recyclerView = recyclerViewMap.get(position); + if (recyclerView != null) { + PlatformViewAdapter adapter = (PlatformViewAdapter) recyclerView + .getAdapter(); + ArrayList list = adapter.getList(); + if (list != null) { + String paltform = downloadEntry.getMeta().get( + "platform"); + for (int i = 0, size = list.size(); i < size; i++) { + if (list.get(i).getPlatform().equals(paltform)) { + String status = statusMap.get(downloadEntry + .getUrl()); + if (!"pause".equals(status)) { + adapter.notifyItemChanged(i); + } + break; + } + } + } + } + } + } + } + }; + + public DataWatcher getDataWatcher() { + return dataWatcher; + } + + public class MultiFunctionViewHolder extends ViewHolder { + + private LinearLayout personal_ll_loading; + private TextView personal_tv_none; + private RelativeLayout personal_rl_label; + private ContentLoadingProgressBar personal_progressbar; + private TextView personal_loading; + private View rootView; + + public MultiFunctionViewHolder(View convertView) { + super(convertView); + + rootView = convertView; + personal_ll_loading = (LinearLayout) convertView + .findViewById(R.id.personal_ll_loading); + personal_tv_none = (TextView) convertView + .findViewById(R.id.personal_tv_none); + personal_rl_label = (RelativeLayout) convertView + .findViewById(R.id.personal_rl_label); + personal_progressbar = (ContentLoadingProgressBar) convertView + .findViewById(R.id.personal_progressbar); + personal_loading = (TextView) convertView + .findViewById(R.id.personal_loading); + } + + } + + public class MyGameViewHolder extends ViewHolder implements + OnClickListener { + + public ImageView gameIco; + public TextView gameName; + public TextView gameDetail; + public TextView gameBtn; + public RecyclerView mygame_rv_show; + public LinearLayout mygame_rl_info; + + public MyGame_LinearLayout rootItem; + + public LinearLayout mygame_ll; + + public MyGameViewHolder(View v) { + super(v); + rootItem = (MyGame_LinearLayout) v; + gameIco = (ImageView) v.findViewById(R.id.mygame_game_thumb); + gameName = (TextView) v.findViewById(R.id.mygame_game_name); + gameDetail = (TextView) v.findViewById(R.id.mygame_game_detail); + gameBtn = (TextView) v.findViewById(R.id.mygame_game_btn); + gameBtn.setOnClickListener(this); + mygame_rl_info = (LinearLayout) v.findViewById(R.id.mygame_rl_info); + mygame_rl_info.setOnClickListener(this); + + mygame_ll = (LinearLayout) v.findViewById(R.id.mygame_ll); + + mygame_rv_show = (RecyclerView) v.findViewById(R.id.mygame_rv_show); + mygame_rv_show.setHasFixedSize(true); + LinearLayoutManager linearLayoutManager = new LinearLayoutManager( + fragmentActivity); + linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); + mygame_rv_show.setLayoutManager(linearLayoutManager); + + mygame_rv_show.setAdapter(new PlatformViewAdapter()); + mygame_rv_show.addItemDecoration(new HorizontalItemDecoration( + fragmentActivity, 6, mygame_rv_show.getAdapter() + .getItemCount())); + } + + @Override + public void onClick(View v) { + int position = getPosition(); + if (v == mygame_rl_info) { + GameEntity entity = gameDetailedList.get(position - 2); + Map kv = new HashMap(); + kv.put("入口", "我的光环-我的游戏"); + TCAgent.onEvent(fragmentActivity, "游戏详情", entity.getName(), kv); + + Map map = new HashMap(); + map.put("location", "我的游戏"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", entity.getName()); + map.put("page", "我的光环"); + DataCollectionManager.onEvent(fragmentActivity, "click-item", + map); + + AppController.put("GameEntity", entity); + Intent intent = new Intent(fragmentActivity, + GameDetailsActivity.class); + intent.putExtra("entrance", "我的光环-我的游戏"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + fragmentActivity.startActivity(intent); + } else if (v == gameBtn) { + String str = gameBtn.getText().toString(); + GameEntity entity = gameDetailedList.get(position - 2); + MyGameInfo gameInfo = sortedList.get(position - 2); + if ("启动".equals(str)) { + String packageName = null; + if (gameInfo.getPackageList() == null) { + packageName = gameInfo.getPackage_name(); + } else { + packageName = gameInfo.getPackageList().get(0); + } + Map kv = new HashMap(); + for (ApkEntity apkEntity : entity.getApk()) { + if (packageName.equals(apkEntity.getPackageName())) { + kv.put("版本", apkEntity.getPlatform()); + break; + } + } + TCAgent.onEvent(fragmentActivity, "游戏启动", entity.getName(), + kv); + + Map map = new HashMap(); + map.put("location", "我的游戏-游戏启动"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", entity.getName()); + map.put("page", "我的光环"); + DataCollectionManager.onEvent(fragmentActivity, + "click-item", map); + + PackageUtils.launchApplicationByPackageName( + fragmentActivity, packageName); + } else if ("打开".equals(str)) { + if (oldClickViewPosition != position + && oldClickViewPosition != -1) { + if (((LinearLayoutManager) gameRecyclerView + .getLayoutManager()) + .findViewByPosition(oldClickViewPosition) != null) { + ((MyGame_LinearLayout) ((LinearLayoutManager) gameRecyclerView + .getLayoutManager()) + .findViewByPosition(oldClickViewPosition)) + .hideRecyclerView(); + } + isShowMap.put(oldClickViewPosition, false); + } + rootItem.showRecyclerView(position); + isShowMap.put(position, true); + oldClickViewPosition = position; + gameBtn.setText("收起"); + } else if ("收起".equals(str)) { + rootItem.hideRecyclerView(); + isShowMap.put(position, false); + oldClickViewPosition = -1; + gameBtn.setText("打开"); + } else if ("插件化".equals(str)) { + if (mygame_rv_show.getVisibility() == View.VISIBLE) { + rootItem.hideRecyclerView(); + isShowMap.put(position, false); + oldClickViewPosition = -1; + } else { + if (oldClickViewPosition != position + && oldClickViewPosition != -1) { + View view = ((LinearLayoutManager) gameRecyclerView + .getLayoutManager()) + .findViewByPosition(oldClickViewPosition); + if (view != null) { + ((MyGame_LinearLayout) view).hideRecyclerView(); + ((TextView) view + .findViewById(R.id.mygame_game_btn)) + .setText("打开"); + } + isShowMap.put(oldClickViewPosition, false); + } + rootItem.showRecyclerView(position); + isShowMap.put(position, true); + oldClickViewPosition = position; + } + } + } + } + } + + private class PlatformViewHolder extends ViewHolder { + + private TextView platform_item_tv_hint, platform_item_tv_name, + platform_item_tv_status; + private ImageView platform_item_iv_pic; + private View view; + private ProgressBar platform_item_progressbar; + + public PlatformViewHolder(View convertView) { + super(convertView); + view = convertView; + platform_item_iv_pic = (ImageView) convertView + .findViewById(R.id.platform_item_iv_pic); + platform_item_tv_hint = (TextView) convertView + .findViewById(R.id.platform_item_tv_hint); + platform_item_tv_name = (TextView) convertView + .findViewById(R.id.platform_item_tv_name); + platform_item_tv_status = (TextView) convertView + .findViewById(R.id.platform_item_tv_status); + platform_item_progressbar = (ProgressBar) convertView + .findViewById(R.id.platform_item_progressbar); + } + + } + + private class PlatformViewAdapter extends + RecyclerView.Adapter { + + private ArrayList pList; + private GameEntity gEntity; + private int mLocation; + + public void setList(ArrayList list, GameEntity entity, + int position) { + pList = list; + gEntity = entity; + mLocation = position; + notifyDataSetChanged(); + } + + public ArrayList getList() { + return pList; + } + + @Override + public int getItemCount() { + if (pList == null) { + return 0; + } + return pList.size(); + } + + @Override + public void onBindViewHolder(final PlatformViewHolder viewHolder, + final int location) { + int id = PlatformUtils.getInstance(fragmentActivity) + .getPlatformPic(pList.get(location).getPlatform()); + if (id != 0) { + viewHolder.platform_item_iv_pic.setVisibility(View.VISIBLE); + viewHolder.platform_item_iv_pic.setImageResource(id); + viewHolder.platform_item_tv_hint.setVisibility(View.GONE); + } else { + String path = PlatformUtils.getInstance(fragmentActivity) + .getPlatformPicPath(pList.get(location).getPlatform()); + if (path != null) { + viewHolder.platform_item_iv_pic.setVisibility(View.VISIBLE); + ImageUtils.getInstance(fragmentActivity).display( + "file://" + path, viewHolder.platform_item_iv_pic); + viewHolder.platform_item_tv_hint.setVisibility(View.GONE); + } else { + viewHolder.platform_item_tv_hint + .setVisibility(View.VISIBLE); + viewHolder.platform_item_tv_hint.setText(PlatformUtils + .getInstance(fragmentActivity).getPlatformName( + pList.get(location).getPlatform())); + viewHolder.platform_item_iv_pic.setVisibility(View.GONE); + } + } + viewHolder.view.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (viewHolder.platform_item_iv_pic.getVisibility() == View.VISIBLE) { + Map kv = new HashMap(); + kv.put("版本", pList.get(location).getPlatform()); + TCAgent.onEvent(fragmentActivity, "游戏启动", + gEntity.getName(), kv); + + Map map = new HashMap(); + map.put("location", "我的游戏-游戏启动"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", gEntity.getName()); + map.put("page", "我的光环"); + DataCollectionManager.onEvent(fragmentActivity, + "click-item", map); + + PackageUtils.launchApplicationByPackageName( + fragmentActivity, pList.get(location) + .getPackageName()); + } else { + String str = viewHolder.platform_item_tv_status + .getText().toString(); + ApkEntity apkEntity = pList.get(location); + if ("插件化".equals(str)) { + // 下载插件版游戏 + String msg = FileUtils.isCanDownload(apkEntity + .getSize()); + if (TextUtils.isEmpty(msg)) { + Map kv = new HashMap(); + kv.put("版本", apkEntity.getPlatform()); + kv.put("状态", "下载开始"); + TCAgent.onEvent(fragmentActivity, "游戏下载", + gEntity.getName(), kv); + + Map kv2 = new HashMap(); + kv2.put("版本", apkEntity.getPlatform()); + kv2.put("状态", "下载开始"); + kv2.put("位置", "我的关注-开始"); + TCAgent.onEvent(fragmentActivity, "游戏下载位置", + gEntity.getName(), kv2); + + Map kv3 = new HashMap(); + kv3.put("我的关注", "下载数"); + kv3.put("我的关注", "下载开始"); + TCAgent.onEvent(fragmentActivity, "应用数据", + gEntity.getName(), kv3); + + Map kv6 = new HashMap(); + kv6.put("下载", "下载开始"); + kv6.put("版本", apkEntity.getPlatform()); + TCAgent.onEvent(fragmentActivity, "插件化", + gEntity.getName(), kv6); + + Map map = new HashMap(); + map.put("location", "我的游戏-插件化"); + map.put("createOn", + System.currentTimeMillis() / 1000); + map.put("game", gEntity.getName()); + map.put("page", "我的光环"); + DataCollectionManager.onEvent(fragmentActivity, + "click-item", map); + + DownloadEntry entry = new DownloadEntry(); + + entry.setUrl(apkEntity.getUrl()); + entry.setName(gEntity.getName()); + entry.setPath(FileUtils.getDownloadPath( + fragmentActivity, + MD5Utils.getContentMD5(gEntity + .getName() + + "_" + + System.currentTimeMillis()) + + ".apk")); + HashMap meta = new HashMap(); + meta.put("ETag", apkEntity.getEtag()); + meta.put("icon", gEntity.getIcon()); + meta.put( + "platform", apkEntity.getPlatform()); + meta.put("gameId", gEntity.getId()); + meta.put("entrance", "我的关注"); + meta.put("isPlugin", "true"); + meta.put("package_name", + apkEntity.getPackageName()); + meta.put("size", apkEntity.getSize()); + meta.put("version", apkEntity.getVersion()); + meta.put("gh_version", apkEntity.getGhVersion()); + entry.setMeta(meta); + + DownloadManager.getInstance(fragmentActivity) + .add(entry); + + EventBus.getDefault().post(new EBRedDot(1)); + + GameUpdateEntity game = new GameUpdateEntity( + gEntity.getId(), gEntity.getName(), + gEntity.getIcon(), apkEntity + .getPackageName(), apkEntity + .getSize(), apkEntity + .getVersion(), apkEntity + .getGhVersion(), apkEntity + .getUrl(), apkEntity + .getPlatform(), true); + PackageManager.addUpdate(game); + + locationMap.put(apkEntity.getUrl(), mLocation); + + statusMap.put(entry.getUrl(), "downloading"); + } else { + Toast.makeText(fragmentActivity, msg, + Toast.LENGTH_SHORT).show(); + } + } else if ("插件化中".equals(str)) { + // 暂停下载 + statusMap.put(apkEntity.getUrl(), "pause"); + + viewHolder.platform_item_tv_status.setText("继续"); + DownloadManager.getInstance(fragmentActivity) + .pause(apkEntity.getUrl()); + + Message msg = Message.obtain(); + msg.what = Constants.PAUSE_DOWNLOAD_TASK; + msg.obj = apkEntity.getUrl(); + lastTimeMap.put(apkEntity.getUrl(), + System.currentTimeMillis()); + handler.sendMessageDelayed(msg, 1000); + } else if ("插件化安装".equals(str)) { + // 安装插件 + showPluginDialog(apkEntity, gEntity.getName(), + PlatformViewAdapter.this, location); + } else if ("等待".equals(str)) { + Toast.makeText(fragmentActivity, "最多同时有3个下载任务", + Toast.LENGTH_SHORT).show(); + } else { + // 继续下载 + statusMap.put(apkEntity.getUrl(), "downloading"); + + viewHolder.platform_item_tv_status.setText("插件化中"); + DownloadManager.getInstance(fragmentActivity) + .resume(apkEntity.getUrl()); + + Message msg = Message.obtain(); + msg.what = Constants.CONTINUE_DOWNLOAD_TASK; + msg.obj = apkEntity.getUrl(); + lastTimeMap.put(apkEntity.getUrl(), + System.currentTimeMillis()); + handler.sendMessageDelayed(msg, 1000); + } + } + } + }); + viewHolder.view.setBackgroundDrawable(null); + viewHolder.view.setPadding(0, 0, 0, 0); + + PackageManager mPackageManager = new PackageManager( + fragmentActivity); + if (!mPackageManager.isSignature(pList.get(location) + .getPackageName())) { + viewHolder.platform_item_iv_pic.setVisibility(View.GONE); + viewHolder.platform_item_tv_hint.setVisibility(View.GONE); + + viewHolder.platform_item_tv_name.setVisibility(View.VISIBLE); + viewHolder.platform_item_tv_status.setVisibility(View.VISIBLE); + viewHolder.platform_item_progressbar + .setVisibility(View.VISIBLE); + viewHolder.platform_item_progressbar.setProgress(1000); + + int color = Color.parseColor(PlatformUtils.getInstance( + fragmentActivity).getPlatformColor( + pList.get(location).getPlatform())); + GradientDrawable gradientDrawable = new GradientDrawable(); + gradientDrawable.setColor(0xffffffff); + gradientDrawable.setStroke( + DisplayUtils.dip2px(fragmentActivity, 1), color); + int padding = DisplayUtils.dip2px(fragmentActivity, 1); + viewHolder.view.setPadding(padding, padding, padding, padding); + viewHolder.view.setBackgroundDrawable(gradientDrawable); + viewHolder.platform_item_tv_name.setTextColor(color); + String paltform = PlatformUtils.getInstance(fragmentActivity) + .getPlatformName(pList.get(location).getPlatform()); + viewHolder.platform_item_tv_name.setText(paltform); + viewHolder.platform_item_tv_status.setText("插件化"); + Drawable[] layers = new Drawable[2]; + GradientDrawable drawable = new GradientDrawable(); + drawable.setColor(0xFFDCDCDC); + layers[0] = drawable; + ClipDrawable clipDrawable = new ClipDrawable(new ColorDrawable( + color), Gravity.LEFT, ClipDrawable.HORIZONTAL); + layers[1] = clipDrawable; + LayerDrawable layerDrawable = new LayerDrawable(layers); + layerDrawable.setId(0, android.R.id.background); + layerDrawable.setId(1, android.R.id.progress); + viewHolder.platform_item_progressbar + .setProgressDrawable(layerDrawable); + } + + DownloadEntry downloadEntry = DownloadManager.getInstance( + fragmentActivity).get(pList.get(location).getUrl()); + if (downloadEntry != null) { + viewHolder.platform_item_progressbar + .setProgress((int) (downloadEntry.getPercent() * 10)); + switch (downloadEntry.getStatus()) { + case pause: + case neterror: + viewHolder.platform_item_tv_status.setText("继续"); + break; + case downloading: + if (!"pause".equals(statusMap.get(downloadEntry.getUrl()))) { + viewHolder.platform_item_tv_status.setText("插件化中"); + } + break; + case done: + EventBus.getDefault().post( + new EBPutUrl(PackageUtils.getPackageNameByPath( + fragmentActivity, downloadEntry.getPath()), + downloadEntry.getUrl())); + viewHolder.platform_item_tv_status.setText("插件化安装"); + break; + case waiting: + viewHolder.platform_item_tv_status.setText("等待"); + break; + default: + break; + } + } + } + + @Override + public int getItemViewType(int position) { + + return position; + } + + @Override + public PlatformViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { + View view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.mygame_platform_item, viewGroup, false); + DisplayMetrics outMetrics = new DisplayMetrics(); + fragmentActivity.getWindowManager().getDefaultDisplay() + .getMetrics(outMetrics); + int width = (outMetrics.widthPixels - DisplayUtils.dip2px( + fragmentActivity, 30)) / 3; + ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(width, + LayoutParams.WRAP_CONTENT); + view.setLayoutParams(params); + return new PlatformViewHolder(view); + } + } + + // 显示插件化 + private void showPluginDialog(final ApkEntity apkEntity, + final String gameName, final PlatformViewAdapter adapter, + final int location) { + final Dialog dialog = new Dialog(fragmentActivity); + View view = View.inflate(fragmentActivity, + R.layout.search_history_delete_dialog, null); + TextView title = (TextView) view.findViewById(R.id.delete_dialog_title); + title.setText("插件化安装"); + TextView content = (TextView) view + .findViewById(R.id.delete_dialog_message); + Spanned spanned = Html.fromHtml("您将进行插件化安装以实现插件功能,此过程将" + + "卸载" + "当前使用的版本并" + + "安装插件版本" + "。"); + content.setText(spanned); + + TextView cancel = (TextView) view + .findViewById(R.id.delete_dialog_cancel); + cancel.setText("取消"); + cancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + TextView confirm = (TextView) view + .findViewById(R.id.delete_dialog_confirm); + confirm.setText("确定"); + confirm.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + + Map kv6 = new HashMap(); + kv6.put("操作", "点击插件化安装完成"); + TCAgent.onEvent(fragmentActivity, "插件化", gameName, kv6); + + Map map = new HashMap(); + map.put("location", "我的游戏-插件化安装"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", gameName); + map.put("page", "我的光环"); + DataCollectionManager.onEvent(fragmentActivity, "click-item", + map); + + String path = DownloadManager.getInstance(fragmentActivity) + .get(apkEntity.getUrl()).getPath(); + if (FileUtils.isEmptyFile(path)) { + Toast.makeText(fragmentActivity, "解析包错误", + Toast.LENGTH_SHORT).show(); + DownloadManager.getInstance(fragmentActivity).cancel( + apkEntity.getUrl()); + adapter.notifyItemChanged(location); + } else { + PackageManager manager = new PackageManager( + fragmentActivity); + if (manager.launchSetup(path)) { + fragmentActivity.startActivity(PackageUtils + .getInstallIntent(path)); + } else { + MainActivity.uninstallMap.put(PackageUtils + .getPackageNameByPath(fragmentActivity, path), + path); + fragmentActivity.startActivity(PackageUtils + .getUninstallIntent(fragmentActivity, path)); + } + } + } + }); + + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.show(); + } + + public void updateItem(EBDownloadDelete busThree) { + notifyItemChanged(0); + Integer location = locationMap.get(busThree.getUrl()); + if (location != null) { + int position = location.intValue(); + RecyclerView recyclerView = recyclerViewMap.get(position); + if (recyclerView != null) { + notifyItemChanged(position); + } + } + } + + public void clearStatusMap() { + statusMap.clear(); + } + + public void logout() { + user = null; + notifyItemChanged(0); + } + + public boolean isNetworkError() { + return isNetworkError; + } + + public void setNetworkError(boolean isNetworkError) { + this.isNetworkError = isNetworkError; + } + + public void hidePlatformView() { + if (isShowMap.size() != 0) { + isShowMap.clear(); + notifyDataSetChanged(); + } + } + + public void reload() { + isNetworkError = false; + notifyItemChanged(getItemCount() - 1); + gameDetailedList.clear(); + isShowMap.clear(); + new Thread(runnable).start(); + } + + // 卸载则移除列表中数据 + public void delete(String packageName) { + hidePlatformView(); + for (int i = 0, size = sortedList.size(); i < size; i++) { + boolean flag = false; + List list = sortedList.get(i).getPackageList(); + if (list != null) { + for (int j = 0; j < list.size(); j++) { + if (packageName.equals(list.get(j))) { + flag = true; + list.remove(j); + if (list.size() == 1) { + sortedList.get(i).setPackage_name(list.get(0)); + sortedList.get(i).setPackageList(null); + } + break; + } + } + } else if (packageName.equals(sortedList.get(i).getPackage_name())) { + flag = true; + } + if (flag) { + if (list == null || list.isEmpty()) { + sortedList.remove(i); + gameDetailedList.remove(i); + notifyItemRemoved(i + 2); + break; + } else { + notifyItemChanged(i + 2); + } + + } + } + } + + // 安装则获取疑似表,更新游戏列表 + public void install(final String packageName) { + JsonObjectExtendedRequest request = new JsonObjectExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + + "v1d45/support/package/" + packageName + + "/game/digest", Constants.GAME_CD), + new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + if (response.length() != 0) { + Gson gson = new Gson(); + GameDigestEntity gameDigestEntity = gson.fromJson( + response.toString(), GameDigestEntity.class); + + ConcernManager manager = new ConcernManager( + fragmentActivity); + GameInfo gameEntity = new GameInfo(); + gameEntity.setId(gameDigestEntity.getId()); + gameEntity.setPackageName(packageName); + manager.updateByEntity(gameEntity, false); + // 移除疑似游戏数据库中所有数据 + SuspectedGameManager suspectedGameManager = new SuspectedGameManager( + fragmentActivity); + suspectedGameManager + .deleteSuspectedGame(packageName); + + gameDetailedList.clear(); + isShowMap.clear(); + new Thread(runnable).start(); + } + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + + } + }); + AppController.addToRequestQueue(request, PersonalFragment.class); + } +} diff --git a/app/src/main/java/com/gh/gamecenter/plugin/Plugin1Fragment.java b/app/src/main/java/com/gh/gamecenter/plugin/Plugin1Fragment.java new file mode 100644 index 0000000000..7b92fb5792 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/plugin/Plugin1Fragment.java @@ -0,0 +1,365 @@ +package com.gh.gamecenter.plugin; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; + +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.util.ArrayMap; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener; +import android.support.v7.widget.DefaultItemAnimator; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +import com.gh.base.AppController; +import com.gh.common.constant.Constants; +import com.gh.common.util.DownloadItemUtils; +import com.gh.common.view.VerticalItemDecoration; +import com.gh.download.DataWatcher; +import com.gh.download.DownloadEntry; +import com.gh.download.DownloadManager; +import com.gh.gamecenter.R; +import com.gh.gamecenter.entity.ApkEntity; +import com.gh.gamecenter.entity.DismissEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.eventbus.EBDownloadDelete; +import com.gh.gamecenter.eventbus.EBNetworkState; +import com.gh.gamecenter.eventbus.EBPWDismiss; +import com.gh.gamecenter.eventbus.EBPackage; +import com.gh.gamecenter.eventbus.EBUISwitch; + +import de.greenrobot.event.EventBus; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-8-10 modified 2015-8-13 插件界面下的精品fragment + */ +public class Plugin1Fragment extends Fragment implements OnRefreshListener { + + private View view; + private RecyclerView recyclerview; + private SwipeRefreshLayout game_swipe_refresh; + private Plugin1FragmentAdapter adapter; + private LinearLayoutManager layoutManager; + private LinearLayout reuse_no_connection; + + // 黄壮华 添加 记录信息的map 修改2015/8/15 + private ArrayMap locationMap; + private ArrayMap> gameMap; + private ArrayMap> platformMap; + private ArrayMap nameMap; + + private boolean isEverpause = false; + private boolean isDestroy = false; + + private int currentItem = 0; + + private ArrayMap lastTimeMap; + private ArrayMap statusMap; + + private DismissEntity dismissEntity; + + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (!isDestroy) { + if (msg.what == Constants.DOWNLOAD_ROLL) { + String name = (String) msg.obj; + if (platformMap != null) { + LinkedBlockingQueue queue = platformMap + .get(name); + if (queue.size() > 1) { + queue.offer(queue.poll()); + Message msg2 = Message.obtain(); + msg2.obj = name; + msg2.what = Constants.DOWNLOAD_ROLL; + sendMessageDelayed(msg2, 3000); + } + } + } else if (msg.what == Constants.CONTINUE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + DownloadManager.getInstance(getActivity()).resume(url); + } + } else if (msg.what == Constants.PAUSE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + DownloadManager.getInstance(getActivity()).pause(url); + } + } + } + } + }; + + // 黄壮华 添加观察者 修改2015/8/15 + private DataWatcher dataWatcher = new DataWatcher() { + @Override + public void onDataChanged( + HashMap downloadingEntries) { + if (!game_swipe_refresh.isRefreshing()) { + for (java.util.Map.Entry entry : downloadingEntries + .entrySet()) { + DownloadEntry downloadEntry = entry.getValue(); + + Integer location = locationMap.get(downloadEntry.getName()); + if (location != null) { + int index = location.intValue(); + + GameEntity detailedEntity = adapter.getList() + .get(index); + + if (detailedEntity != null) { + DownloadItemUtils.processDate(detailedEntity, + downloadEntry, platformMap, handler, + adapter, index + 1, statusMap); + } + + } + } + } + } + }; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + view = View.inflate(getActivity(), R.layout.plugin1_fragment, null); + + lastTimeMap = new ArrayMap(); + statusMap = new ArrayMap(); + locationMap = new ArrayMap(); + gameMap = new ArrayMap>(); + platformMap = new ArrayMap>(); + nameMap = new ArrayMap(); + + dismissEntity = new DismissEntity(false); + + game_swipe_refresh = (SwipeRefreshLayout) view + .findViewById(R.id.game_swipe_refresh); + game_swipe_refresh.setColorSchemeResources(R.color.theme_colors); + game_swipe_refresh.setOnRefreshListener(this); + + recyclerview = (RecyclerView) view.findViewById(R.id.game_list); + recyclerview.setHasFixedSize(true); + layoutManager = new LinearLayoutManager(getActivity()); + recyclerview.setLayoutManager(layoutManager); + recyclerview.setItemAnimator(new DefaultItemAnimator()); + + // 黄壮华 添加 初始化游戏状态 修改2015/8/21 + DownloadItemUtils.initializeGameMap(getActivity(), gameMap); + + reuse_no_connection = (LinearLayout) view + .findViewById(R.id.reuse_no_connection); + reuse_no_connection.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + game_swipe_refresh.setRefreshing(true); + recyclerview.setVisibility(View.VISIBLE); + reuse_no_connection.setVisibility(View.GONE); + handler.postDelayed(runnable, 1000); + } + }); + + // 黄壮华 传递引用 修改2015/8/15 + adapter = new Plugin1FragmentAdapter(Plugin1Fragment.this, locationMap, + gameMap, platformMap, nameMap, game_swipe_refresh, + reuse_no_connection, recyclerview, handler, lastTimeMap, + statusMap, dismissEntity); + recyclerview.setAdapter(adapter); + recyclerview.setOnScrollListener(new RecyclerView.OnScrollListener() { + + @Override + public void onScrollStateChanged(RecyclerView recyclerView, + int newState) { + super.onScrollStateChanged(recyclerView, newState); + if (newState == RecyclerView.SCROLL_STATE_IDLE + && layoutManager.findLastVisibleItemPosition() == 1 + adapter + .getList().size()) { + if (!adapter.isRemove() && !adapter.isLoading()) { + adapter.addList(adapter.getList().size()); + } + } + } + + }); + recyclerview.addItemDecoration(new VerticalItemDecoration( + getActivity(), 1)); + + EventBus.getDefault().register(this); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + if (container != null) { + container.removeView(view); + } + return view; + } + + public void onEventMainThread(EBDownloadDelete busThree) { + LinkedBlockingQueue queue = platformMap.get(busThree.getName()); + if (queue != null) { + queue.remove(busThree.getPlatform()); + platformMap.put(busThree.getName(), queue); + } + Integer location = locationMap.get(busThree.getName()); + if (location != null) { + int index = location.intValue(); + GameEntity detailedEntity = adapter.getList().get(index); + if (TextUtils.isEmpty(busThree.getPlatform())) { + detailedEntity.getEntryMap().remove("官方版"); + } else { + detailedEntity.getEntryMap().remove(busThree.getPlatform()); + } + adapter.notifyItemChanged(index + 1); + } + } + + public void onEventMainThread(EBNetworkState busNetworkState) { + if (busNetworkState.isNetworkConnected()) { + if (reuse_no_connection.getVisibility() == View.VISIBLE) { + game_swipe_refresh.setRefreshing(true); + recyclerview.setVisibility(View.VISIBLE); + reuse_no_connection.setVisibility(View.GONE); + handler.postDelayed(runnable, 1000); + } else if (adapter.isNetworkError()) { + adapter.setNetworkError(false); + adapter.notifyItemChanged(adapter.getItemCount() - 1); + adapter.addList(adapter.getList().size()); + } + } + } + + public void onEventMainThread(EBPWDismiss dismiss) { + if (dismissEntity != null) { + dismissEntity.setShow(false); + } + } + + public void onEventMainThread(EBUISwitch busNine) { + if ("PluginFragment".equals(busNine.getFrom())) { + currentItem = busNine.getPosition(); + if (busNine.getPosition() == 0) { + adapter.startAutoScroll(); + } else { + adapter.stopAutoScroll(); + } + } else if ("MainActivity".equals(busNine.getFrom())) { + if (busNine.getPosition() != 1) { + adapter.stopAutoScroll(); + statusMap.clear(); + } + } + } + + public void onEventMainThread(EBPackage busFour) { + String name = nameMap.get(busFour.getPackageName()); + if (name != null) { + int location = locationMap.get(name); + if ("安装".equals(busFour.getType())) { + GameEntity detailedEntity = adapter.getList().get(location); + for (ApkEntity apkEntity : detailedEntity.getApk()) { + if (apkEntity.getPackageName().equals( + busFour.getPackageName())) { + detailedEntity.getEntryMap().remove( + apkEntity.getPlatform()); + adapter.notifyItemChanged(location + 1); + break; + } + } + } else if ("卸载".equals(busFour.getType())) { + adapter.notifyItemChanged(location + 1); + } + } + } + + @Override + public void onResume() { + super.onResume(); + if (isEverpause) { + // 黄壮华 添加 初始化游戏状态 修改2015/8/21 + DownloadItemUtils.initializeGameMap(getActivity(), gameMap); + List entities = new ArrayList(); + for (GameEntity entity : adapter.getList()) { + entity.setEntryMap(gameMap.get(entity.getName())); + entities.add(entity); + } + adapter.setList(entities); + } + isEverpause = false; + DownloadManager.getInstance(getActivity()).addObserver(dataWatcher); + if (currentItem == 0) { + adapter.startAutoScroll(); + } + } + + public boolean isEverpause() { + return isEverpause; + } + + @Override + public void onPause() { + super.onPause(); + isEverpause = true; + statusMap.clear(); + DownloadManager.getInstance(getActivity()).removeObserver(dataWatcher); + if (currentItem == 0) { + adapter.stopAutoScroll(); + } + } + + Runnable runnable = new Runnable() { + @Override + public void run() { + adapter = new Plugin1FragmentAdapter(Plugin1Fragment.this, + locationMap, gameMap, platformMap, nameMap, + game_swipe_refresh, reuse_no_connection, recyclerview, + handler, lastTimeMap, statusMap, dismissEntity); + recyclerview.setAdapter(adapter); + } + }; + + @Override + public void onRefresh() { + handler.postDelayed(runnable, 1000); + } + + @Override + public void onDestroy() { + super.onDestroy(); + isDestroy = true; + AppController.canclePendingRequests(Plugin1Fragment.class); + EventBus.getDefault().unregister(this); + view = null; + recyclerview = null; + game_swipe_refresh = null; + adapter = null; + layoutManager = null; + reuse_no_connection = null; + locationMap = null; + gameMap = null; + platformMap = null; + nameMap = null; + lastTimeMap = null; + statusMap = null; + dismissEntity = null; + handler = null; + dataWatcher = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/plugin/Plugin1FragmentAdapter.java b/app/src/main/java/com/gh/gamecenter/plugin/Plugin1FragmentAdapter.java new file mode 100644 index 0000000000..335807cabe --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/plugin/Plugin1FragmentAdapter.java @@ -0,0 +1,587 @@ +package com.gh.gamecenter.plugin; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.LinkedBlockingQueue; + +import org.json.JSONArray; + +import android.content.Context; +import android.content.Intent; +import android.os.Handler; +import android.support.v4.util.ArrayMap; +import android.support.v4.view.ViewPager; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.RecyclerView; +import android.util.DisplayMetrics; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.volley.NoConnectionError; +import com.android.volley.Response; +import com.android.volley.TimeoutError; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.common.util.DisplayUtils; +import com.gh.common.util.DownloadItemUtils; +import com.gh.common.util.GameViewUtils; +import com.gh.common.util.ImageUtils; +import com.gh.common.util.TimestampUtils; +import com.gh.common.view.AutoScrollViewPager; +import com.gh.download.DownloadEntry; +import com.gh.gamecenter.GameDetailsActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.adapter.ImagePagerAdapter; +import com.gh.gamecenter.adapter.viewholder.FooterViewHolder; +import com.gh.gamecenter.adapter.viewholder.GameViewHolder; +import com.gh.gamecenter.db.info.GameInfo; +import com.gh.gamecenter.entity.ApkEntity; +import com.gh.gamecenter.entity.DismissEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.manager.GameManager; +import com.gh.gamecenter.volley.extended.JsonArrayExtendedRequest; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.tendcloud.tenddata.TCAgent; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-8-13 + * @update 2015-8-13 + * @des 插件板块下的精品栏目 + */ +public class Plugin1FragmentAdapter extends + RecyclerView.Adapter { + + private Context context; + + private Plugin1Fragment fragment; + + private RecyclerView recyclerview; + private SwipeRefreshLayout game_swipe_refresh; + private LinearLayout reuse_no_connection; + + private List slideList; + private List list; + + private boolean isRemove; + private boolean isLoading; + private boolean isNetworkError; + private boolean isSlideError; + private boolean isListError; + + // 黄壮华 获取引用 修改2015/8/15 + private ArrayMap locationMap; + private ArrayMap> gameMap; + private ArrayMap> platformMap; + private ArrayMap nameMap; + + private Handler handler; + private ArrayMap lastTimeMap; + private ArrayMap statusMap; + + private DismissEntity dismissEntity; + + // 黄壮华 获取引用 修改2015/8/15 + public Plugin1FragmentAdapter(Plugin1Fragment fment, + ArrayMap lMap, + ArrayMap> gMap, + ArrayMap> pMap, + ArrayMap nMap, + SwipeRefreshLayout swipeRefreshLayout, LinearLayout linearLayout, + RecyclerView rView, Handler hdler, ArrayMap ltMap, + ArrayMap sMap, DismissEntity dEntity) { + + fragment = fment; + context = fment.getActivity(); + locationMap = lMap; + gameMap = gMap; + platformMap = pMap; + nameMap = nMap; + game_swipe_refresh = swipeRefreshLayout; + reuse_no_connection = linearLayout; + recyclerview = rView; + + handler = hdler; + lastTimeMap = ltMap; + statusMap = sMap; + + dismissEntity = dEntity; + + list = new ArrayList(); + slideList = new ArrayList(); + + isRemove = false; + isLoading = false; + isNetworkError = false; + isSlideError = false; + isListError = false; + + new Thread(runnable) {}.start(); + } + + Runnable runnable = new Runnable() { + @Override + public void run() { + initSlide(true); + addList(0); + } + }; + + private void initSlide(final boolean isFirst) { + JsonArrayExtendedRequest slideRequest = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + "v1d45/plugin/slide", + Constants.GAME_CD), new Response.Listener() { + @Override + public void onResponse(JSONArray response) { + Type listType = new TypeToken>() { + }.getType(); + Gson gson = new Gson(); + slideList = gson.fromJson(response.toString(), listType); + if (slideList != null && !slideList.isEmpty()) { + GameManager manager = new GameManager(context); + for (GameEntity entity : slideList) { + for (ApkEntity apkEntity : entity.getApk()) { + manager.addOrUpdate(new GameInfo( + apkEntity.getPackageName(), entity + .getId(), entity.getName())); + } + } + notifyItemChanged(0); + } + } + + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + // 无网络连接 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + isSlideError = true; + if (!isFirst) { + Toast.makeText(context, "网络错误", + Toast.LENGTH_SHORT).show(); + notifyItemChanged(0); + } else { + showView(); + } + } + } + }); + AppController.addToRequestQueue(slideRequest, Plugin1Fragment.class); + } + + public void addList(final int offset) { + isLoading = true; + + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + + "v1d45/plugin/jingpin?limit=20&offset=" + offset, + Constants.GAME_CD), new Response.Listener() { + + @Override + public void onResponse(JSONArray response) { + processingData(response, offset); + isLoading = false; + } + + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + isLoading = false; + // 无网络连接和访问超时 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + if (offset == 0) { + if (game_swipe_refresh.isRefreshing()) { + game_swipe_refresh.setRefreshing(false); + } + isListError = true; + showView(); + } else { + Toast.makeText(context, "网络错误", + Toast.LENGTH_SHORT).show(); + isNetworkError = true; + notifyItemChanged(getItemCount() - 1); + } + } + } + + }); + AppController.addToRequestQueue(request, Plugin1Fragment.class); + } + + private void showView() { + if (isSlideError && isListError) { + Toast.makeText(context, "网络错误", Toast.LENGTH_SHORT).show(); + recyclerview.setVisibility(View.GONE); + reuse_no_connection.setVisibility(View.VISIBLE); + } else if (isSlideError && !isListError) { + Toast.makeText(context, "网络错误", Toast.LENGTH_SHORT).show(); + notifyItemChanged(0); + } else if (!isSlideError && isListError) { + Toast.makeText(context, "网络错误", Toast.LENGTH_SHORT).show(); + notifyItemChanged(getItemCount() - 1); + } + } + + private void processingData(JSONArray response, int offset) { + Type listType = new TypeToken>() { + }.getType(); + Gson gson = new Gson(); + GameManager manager = new GameManager(context); + List gameList = gson + .fromJson(response.toString(), listType); + if (gameList != null && !gameList.isEmpty()) { + if (!list.isEmpty()) { + for (int i = 0; i < gameList.size(); i++) { + GameEntity entity = gameList.get(i); + // 去重 + for (int j = 0; j < list.size(); j++) { + if (list.get(j).getId().equals(entity.getId())) { + gameList.remove(i); + i--; + break; + } + } + } + } + for (GameEntity entity : gameList) { + // 黄壮华 初始化游戏状态 修改2015/8/15 + entity.setEntryMap(gameMap.get(entity.getName())); + list.add(entity); + if (!fragment.isHidden() && !fragment.isEverpause()) { + final int size = list.size(); + notifyItemInserted(size); + } + for (ApkEntity apkEntity : entity.getApk()) { + manager.addOrUpdate(new GameInfo(apkEntity.getPackageName(), + entity.getId(), entity.getName())); + } + } + } + + if (fragment.isHidden() || fragment.isEverpause()) { + notifyDataSetChanged(); + } + + if (offset == 0 && game_swipe_refresh.isRefreshing()) { + game_swipe_refresh.setRefreshing(false); + } + + if (gameList.isEmpty() || (offset == 0 && gameList.size() < 20)) { + isRemove = true; + notifyItemRemoved(getItemCount()); + } + + // 黄壮华 获取游戏位置信息 修改2015/8/15 + for (int i = 0, size = list.size(); i < size; i++) { + GameEntity entity = list.get(i); + locationMap.put(entity.getName(), i); + for (ApkEntity apkEntity : entity.getApk()) { + nameMap.put(apkEntity.getPackageName(), entity.getName()); + } + } + } + + @Override + public int getItemCount() { + if (isRemove) { + return 1 + list.size(); + } else { + if (list.isEmpty()) { + if (isListError) { + return 1 + list.size() + 1; + } else { + return 1 + list.size(); + } + } else { + return 1 + list.size() + 1; + } + } + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, + int position) { + if (viewHolder instanceof AutoScrollViewpagerViewHolder) { + AutoScrollViewpagerViewHolder holder = (AutoScrollViewpagerViewHolder) viewHolder; + if (isSlideError) { + holder.viewpager_tv_failure.setVisibility(View.VISIBLE); + holder.viewPager.setVisibility(View.GONE); + holder.viewpager_ll_hint.setVisibility(View.GONE); + } else { + holder.viewpager_tv_failure.setVisibility(View.GONE); + holder.viewPager.setVisibility(View.VISIBLE); + holder.viewpager_ll_hint.setVisibility(View.VISIBLE); + } + if (slideList.size() > 0) { + int currentItem = 0; + if (holder.viewPager.getAdapter() != null) { + currentItem = holder.viewPager.getCurrentItem(); + } + holder.viewpager_ll_hint.removeAllViews(); + for (int i = 0, size = slideList.size(); i < size; i++) { + ImageView imageView = new ImageView(context); + LayoutParams lparams = new LayoutParams( + DisplayUtils.dip2px(context, 8), + DisplayUtils.dip2px(context, 8)); + lparams.bottomMargin = DisplayUtils.dip2px(context, 8); + if (i == currentItem) { + imageView.setImageResource(R.drawable.oval_hint_dn); + } else { + imageView.setImageResource(R.drawable.oval_hint_up); + } + if (i != 0) { + lparams.leftMargin = DisplayUtils.dip2px(context, 8); + } + imageView.setLayoutParams(lparams); + holder.viewpager_ll_hint.addView(imageView); + } + holder.viewPager.setAdapter(new ImagePagerAdapter(context, + slideList, true)); + holder.viewPager.setCurrentItem(currentItem); + holder.viewPager.setInterval(3000); + holder.viewPager.startAutoScroll(); + } + } else if (viewHolder instanceof GameViewHolder) { + + GameViewHolder holder = (GameViewHolder) viewHolder; + + final GameEntity detailedEntity = list.get(position - 1); + + holder.gameSeq.setText((position + 1) + ""); + holder.gameSeq.setVisibility(View.GONE); + ImageUtils.getInstance(context).display(detailedEntity.getIcon(), + holder.gameThumb); + if (detailedEntity.getApk() == null + || detailedEntity.getApk().isEmpty()) { + holder.gameNameAndSize.setText(detailedEntity.getName()); + } else { + holder.gameNameAndSize.setText(detailedEntity.getName() + + " | " + detailedEntity.getApk().get(0).getSize()); + } + holder.gameDes.setText(detailedEntity.getBrief()); + + // 添加tag标签 + GameViewUtils.setLabelList(context, holder.labelList, + detailedEntity.getTag()); + + // 添加点击事件 + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + Map kv = new HashMap(); + kv.put("入口", "插件-精品-列表"); + TCAgent.onEvent(context, "游戏详情", detailedEntity.getName(), + kv); + + Map map = new HashMap(); + map.put("location", "精品-列表"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", detailedEntity.getName()); + map.put("page", "插件"); + DataCollectionManager.onEvent(context, "click-item", map); + + AppController.put("GameEntity", detailedEntity); + Intent intent = new Intent(context, + GameDetailsActivity.class); + intent.putExtra("entrance", "插件-精品列表"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + }); + + DownloadItemUtils.setOnClickListener(context, holder.downloadBtn, + holder.downloadSpeed, holder.downloadPercentage, + detailedEntity, position, this, handler, lastTimeMap, + statusMap, platformMap, "插件-精品", dismissEntity, "精品:" + + detailedEntity.getName()); + + DownloadItemUtils.updateItem(context, holder.labelList, + holder.gameProgressbar, holder.gameInfo, + holder.downloadSpeed, holder.downloadPercentage, + holder.downloadBtn, detailedEntity, platformMap, statusMap); + } else if (viewHolder instanceof FooterViewHolder) { + FooterViewHolder holder = (FooterViewHolder) viewHolder; + if (isNetworkError || isListError) { + holder.footerview_progressbar.setVisibility(View.GONE); + holder.footerview_tv_loading.setText("加载失败,点击重试"); + holder.rootView.setClickable(true); + holder.rootView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + isNetworkError = false; + notifyItemChanged(getItemCount() - 1); + addList(list.size()); + } + }); + } else { + holder.footerview_progressbar.setVisibility(View.VISIBLE); + holder.footerview_tv_loading.setText("加载中..."); + holder.rootView.setClickable(false); + } + } + } + + @Override + public int getItemViewType(int position) { + return position; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { + if (i == 0) { + View view = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.plugin1_autoscrollviewpager_viewholder, viewGroup, + false); + DisplayMetrics outMetrics = new DisplayMetrics(); + fragment.getActivity().getWindowManager().getDefaultDisplay() + .getMetrics(outMetrics); + ViewGroup.LayoutParams params = new ViewGroup.LayoutParams( + LayoutParams.MATCH_PARENT, + (int) (outMetrics.widthPixels / 16f * 7f)); + view.setLayoutParams(params); + return new AutoScrollViewpagerViewHolder(view); + } else if (i > 0 && i <= list.size()) { + return new GameViewHolder(LayoutInflater.from( + viewGroup.getContext()).inflate( + R.layout.home_list_item_gamenormal_type, viewGroup, false)); + } else { + return new FooterViewHolder(LayoutInflater.from( + viewGroup.getContext()).inflate( + R.layout.refresh_footerview, viewGroup, false)); + } + } + + public class AutoScrollViewpagerViewHolder extends RecyclerView.ViewHolder { + private AutoScrollViewPager viewPager; + private LinearLayout viewpager_ll_hint; + private TextView viewpager_tv_failure; + + public AutoScrollViewpagerViewHolder(View v) { + super(v); + viewpager_tv_failure = (TextView) v + .findViewById(R.id.viewpager_tv_failure); + viewpager_tv_failure.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + isSlideError = false; + notifyItemChanged(0); + initSlide(false); + } + }); + viewpager_ll_hint = (LinearLayout) v + .findViewById(R.id.viewpager_ll_hint); + viewPager = (AutoScrollViewPager) v.findViewById(R.id.view_pager); + viewPager + .addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + + @Override + public void onPageSelected(int position) { + for (int i = 0, size = viewpager_ll_hint + .getChildCount(); i < size; i++) { + if (i == position % size) { + ((ImageView) viewpager_ll_hint + .getChildAt(i)) + .setImageResource(R.drawable.oval_hint_dn); + } else { + ((ImageView) viewpager_ll_hint + .getChildAt(i)) + .setImageResource(R.drawable.oval_hint_up); + } + } + } + + @Override + public void onPageScrolled(int position, + float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageScrollStateChanged(int state) { + // 解决viewpager和SwipeRefreshLayout滑动冲突 + if (state == ViewPager.SCROLL_STATE_DRAGGING) { + game_swipe_refresh.setEnabled(false); + } else { + game_swipe_refresh.setEnabled(true); + } + } + }); + autoScrollViewPager = viewPager; + } + + } + + private AutoScrollViewPager autoScrollViewPager; + + public void startAutoScroll() { + if (autoScrollViewPager != null) { + autoScrollViewPager.startAutoScroll(); + } + } + + public void stopAutoScroll() { + if (autoScrollViewPager != null) { + autoScrollViewPager.stopAutoScroll(); + } + } + + public List getSlideList() { + return slideList; + } + + public void setSlideList(List slideList) { + this.slideList = slideList; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + notifyItemRangeChanged(1, list.size()); + } + + public boolean isRemove() { + return isRemove; + } + + public void setRemove(boolean isRemove) { + this.isRemove = isRemove; + } + + public boolean isLoading() { + return isLoading; + } + + public void setLoading(boolean isLoading) { + this.isLoading = isLoading; + } + + public boolean isNetworkError() { + return isNetworkError; + } + + public void setNetworkError(boolean isNetworkError) { + this.isNetworkError = isNetworkError; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/plugin/Plugin2Fragment.java b/app/src/main/java/com/gh/gamecenter/plugin/Plugin2Fragment.java new file mode 100644 index 0000000000..dfe31b75ab --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/plugin/Plugin2Fragment.java @@ -0,0 +1,351 @@ +package com.gh.gamecenter.plugin; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; + +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.util.ArrayMap; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener; +import android.support.v7.widget.DefaultItemAnimator; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +import com.gh.base.AppController; +import com.gh.common.constant.Constants; +import com.gh.common.util.DownloadItemUtils; +import com.gh.common.view.VerticalItemDecoration; +import com.gh.download.DataWatcher; +import com.gh.download.DownloadEntry; +import com.gh.download.DownloadManager; +import com.gh.gamecenter.R; +import com.gh.gamecenter.entity.ApkEntity; +import com.gh.gamecenter.entity.DismissEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.eventbus.EBDownloadDelete; +import com.gh.gamecenter.eventbus.EBNetworkState; +import com.gh.gamecenter.eventbus.EBPWDismiss; +import com.gh.gamecenter.eventbus.EBPackage; +import com.gh.gamecenter.eventbus.EBUISwitch; + +import de.greenrobot.event.EventBus; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-8-8 + * @update 2015-8-11 + * @des 主页插件fragment + */ +public class Plugin2Fragment extends Fragment implements OnRefreshListener { + + private View view; + private RecyclerView recyclerview; + private SwipeRefreshLayout game_swipe_refresh; + private Plugin2FragmentAdapter adapter; + private LinearLayoutManager layoutManager; + private LinearLayout reuse_no_connection; + + // 黄壮华 添加 记录信息的map 修改2015/8/15 + private ArrayMap locationMap; + private ArrayMap> gameMap; + private ArrayMap> platformMap; + private ArrayMap nameMap; + + private boolean isEverpause = false; + private boolean isDestroy = false; + + private ArrayMap lastTimeMap; + private ArrayMap statusMap; + + private DismissEntity dismissEntity; + + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (!isDestroy) { + if (msg.what == Constants.DOWNLOAD_ROLL) { + String name = (String) msg.obj; + if (platformMap != null) { + LinkedBlockingQueue queue = platformMap + .get(name); + if (queue.size() > 1) { + queue.offer(queue.poll()); + Message msg2 = Message.obtain(); + msg2.obj = name; + msg2.what = Constants.DOWNLOAD_ROLL; + sendMessageDelayed(msg2, 3000); + } + } + } else if (msg.what == Constants.CONTINUE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + DownloadManager.getInstance(getActivity()).resume(url); + } + } else if (msg.what == Constants.PAUSE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + DownloadManager.getInstance(getActivity()).pause(url); + } + } + } + } + }; + + // 黄壮华 添加观察者 修改2015/8/15 + private DataWatcher dataWatcher = new DataWatcher() { + @Override + public void onDataChanged( + HashMap downloadingEntries) { + if (!game_swipe_refresh.isRefreshing()) { + for (java.util.Map.Entry entry : downloadingEntries + .entrySet()) { + DownloadEntry downloadEntry = entry.getValue(); + + Integer location = locationMap.get(downloadEntry.getName()); + if (location != null) { + int index = location.intValue(); + + GameEntity detailedEntity = adapter.getList() + .get(index); + + if (detailedEntity != null) { + DownloadItemUtils.processDate(detailedEntity, + downloadEntry, platformMap, handler, + adapter, index, statusMap); + } + + } + } + } + } + }; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + view = View.inflate(getActivity(), R.layout.plugin1_fragment, null); + + lastTimeMap = new ArrayMap(); + statusMap = new ArrayMap(); + locationMap = new ArrayMap(); + gameMap = new ArrayMap>(); + platformMap = new ArrayMap>(); + nameMap = new ArrayMap(); + + dismissEntity = new DismissEntity(false); + + game_swipe_refresh = (SwipeRefreshLayout) view + .findViewById(R.id.game_swipe_refresh); + game_swipe_refresh.setColorSchemeResources(R.color.theme_colors); + game_swipe_refresh.setOnRefreshListener(this); + + recyclerview = (RecyclerView) view.findViewById(R.id.game_list); + recyclerview.setHasFixedSize(true); + layoutManager = new LinearLayoutManager(getActivity()); + recyclerview.setLayoutManager(layoutManager); + recyclerview.setItemAnimator(new DefaultItemAnimator()); + + // 黄壮华 添加 初始化游戏状态 修改2015/8/21 + DownloadItemUtils.initializeGameMap(getActivity(), gameMap); + + reuse_no_connection = (LinearLayout) view + .findViewById(R.id.reuse_no_connection); + reuse_no_connection.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + game_swipe_refresh.setRefreshing(true); + recyclerview.setVisibility(View.VISIBLE); + reuse_no_connection.setVisibility(View.GONE); + handler.postDelayed(runnable, 1000); + } + }); + + // 黄壮华 传递引用 修改2015/8/15 + adapter = new Plugin2FragmentAdapter(Plugin2Fragment.this, locationMap, + gameMap, platformMap, nameMap, recyclerview, + game_swipe_refresh, reuse_no_connection, handler, lastTimeMap, + statusMap, dismissEntity); + recyclerview.setAdapter(adapter); + recyclerview.setOnScrollListener(new RecyclerView.OnScrollListener() { + + @Override + public void onScrollStateChanged(RecyclerView recyclerView, + int newState) { + super.onScrollStateChanged(recyclerView, newState); + if (newState == RecyclerView.SCROLL_STATE_IDLE + && layoutManager.findLastVisibleItemPosition() == adapter + .getList().size()) { + if (!adapter.isRemove() && !adapter.isLoading()) { + adapter.addList(adapter.getList().size()); + } + } + } + + }); + recyclerview.addItemDecoration(new VerticalItemDecoration( + getActivity(), 1)); + + EventBus.getDefault().register(this); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + if (container != null) { + container.removeView(view); + } + return view; + } + + public void onEventMainThread(EBDownloadDelete busThree) { + LinkedBlockingQueue queue = platformMap.get(busThree.getName()); + if (queue != null) { + queue.remove(busThree.getPlatform()); + platformMap.put(busThree.getName(), queue); + } + Integer location = locationMap.get(busThree.getName()); + if (location != null) { + int index = location.intValue(); + GameEntity detailedEntity = adapter.getList().get(index); + if (TextUtils.isEmpty(busThree.getPlatform())) { + detailedEntity.getEntryMap().remove("官方版"); + } else { + detailedEntity.getEntryMap().remove(busThree.getPlatform()); + } + adapter.notifyItemChanged(index); + } + } + + public void onEventMainThread(EBPWDismiss dismiss) { + if (dismissEntity != null) { + dismissEntity.setShow(false); + } + } + + public void onEventMainThread(EBPackage busFour) { + String name = nameMap.get(busFour.getPackageName()); + if (name != null) { + int location = locationMap.get(name); + if ("安装".equals(busFour.getType())) { + GameEntity detailedEntity = adapter.getList().get(location); + for (ApkEntity apkEntity : detailedEntity.getApk()) { + if (apkEntity.getPackageName().equals( + busFour.getPackageName())) { + detailedEntity.getEntryMap().remove( + apkEntity.getPlatform()); + adapter.notifyItemChanged(location); + break; + } + } + } else if ("卸载".equals(busFour.getType())) { + adapter.notifyItemChanged(location); + } + } + } + + public void onEventMainThread(EBNetworkState busNetworkState) { + if (busNetworkState.isNetworkConnected()) { + if (reuse_no_connection.getVisibility() == View.VISIBLE) { + game_swipe_refresh.setRefreshing(true); + recyclerview.setVisibility(View.VISIBLE); + reuse_no_connection.setVisibility(View.GONE); + handler.postDelayed(runnable, 1000); + } else if (adapter.isNetworkError()) { + adapter.setNetworkError(false); + adapter.notifyItemChanged(adapter.getItemCount() - 1); + adapter.addList(adapter.getList().size()); + } + } + } + + public void onEventMainThread(EBUISwitch busNine) { + if ("MainActivity".equals(busNine.getFrom())) { + if (busNine.getPosition() != 1) { + statusMap.clear(); + } + } + } + + @Override + public void onResume() { + super.onResume(); + if (isEverpause) { + // 黄壮华 添加 初始化游戏状态 修改2015/8/21 + DownloadItemUtils.initializeGameMap(getActivity(), gameMap); + List entities = new ArrayList(); + for (GameEntity entity : adapter.getList()) { + entity.setEntryMap(gameMap.get(entity.getName())); + entities.add(entity); + } + adapter.setList(entities); + } + isEverpause = false; + DownloadManager.getInstance(getActivity()).addObserver(dataWatcher); + } + + public boolean isEverpause() { + return isEverpause; + } + + @Override + public void onPause() { + super.onPause(); + isEverpause = true; + statusMap.clear(); + DownloadManager.getInstance(getActivity()).removeObserver(dataWatcher); + } + + Runnable runnable = new Runnable() { + @Override + public void run() { + adapter = new Plugin2FragmentAdapter(Plugin2Fragment.this, + locationMap, gameMap, platformMap, nameMap, recyclerview, + game_swipe_refresh, reuse_no_connection, handler, + lastTimeMap, statusMap, dismissEntity); + recyclerview.setAdapter(adapter); + } + }; + + @Override + public void onRefresh() { + handler.postDelayed(runnable, 1000); + } + + @Override + public void onDestroy() { + super.onDestroy(); + isDestroy = true; + AppController.canclePendingRequests(Plugin2Fragment.class); + EventBus.getDefault().unregister(this); + view = null; + recyclerview = null; + game_swipe_refresh = null; + adapter = null; + layoutManager = null; + reuse_no_connection = null; + locationMap = null; + gameMap = null; + platformMap = null; + nameMap = null; + lastTimeMap = null; + statusMap = null; + dismissEntity = null; + handler = null; + dataWatcher = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/plugin/Plugin2FragmentAdapter.java b/app/src/main/java/com/gh/gamecenter/plugin/Plugin2FragmentAdapter.java new file mode 100644 index 0000000000..bb4724d7fb --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/plugin/Plugin2FragmentAdapter.java @@ -0,0 +1,371 @@ +package com.gh.gamecenter.plugin; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.LinkedBlockingQueue; + +import org.json.JSONArray; + +import android.content.Context; +import android.content.Intent; +import android.os.Handler; +import android.support.v4.util.ArrayMap; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.Toast; + +import com.android.volley.NoConnectionError; +import com.android.volley.Response; +import com.android.volley.TimeoutError; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.common.util.DownloadItemUtils; +import com.gh.common.util.GameViewUtils; +import com.gh.common.util.ImageUtils; +import com.gh.common.util.TimestampUtils; +import com.gh.download.DownloadEntry; +import com.gh.gamecenter.GameDetailsActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.adapter.viewholder.FooterViewHolder; +import com.gh.gamecenter.adapter.viewholder.GameViewHolder; +import com.gh.gamecenter.db.info.GameInfo; +import com.gh.gamecenter.entity.ApkEntity; +import com.gh.gamecenter.entity.DismissEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.manager.GameManager; +import com.gh.gamecenter.volley.extended.JsonArrayExtendedRequest; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.tendcloud.tenddata.TCAgent; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-8-8 + * @update 2015-8-11 + * @des 首页插件fragment适配器 + */ +public class Plugin2FragmentAdapter extends + RecyclerView.Adapter { + + private Context context; + + private Plugin2Fragment fragment; + + private RecyclerView recyclerView; + private SwipeRefreshLayout game_swipe_refresh; + private LinearLayout reuse_no_connection; + + private boolean isRemove; + private boolean isLoading; + private boolean isNetworkError; + + private List list; + + // 黄壮华 获取引用 修改2015/8/15 + private ArrayMap locationMap; + private ArrayMap> gameMap; + private ArrayMap> platformMap; + private ArrayMap nameMap; + + private Handler handler; + private ArrayMap lastTimeMap; + private ArrayMap statusMap; + + private DismissEntity dismissEntity; + + // 黄壮华 获取引用 修改2015/8/15 + public Plugin2FragmentAdapter(Plugin2Fragment fment, + ArrayMap lMap, + ArrayMap> gMap, + ArrayMap> pMap, + ArrayMap nMap, RecyclerView rView, + SwipeRefreshLayout refreshLayout, LinearLayout linearLayout, + Handler hdler, ArrayMap ltMap, + ArrayMap sMap, DismissEntity dEntity) { + + // 黄壮华 获取引用 修改2015/8/15 + locationMap = lMap; + gameMap = gMap; + platformMap = pMap; + nameMap = nMap; + recyclerView = rView; + game_swipe_refresh = refreshLayout; + reuse_no_connection = linearLayout; + + handler = hdler; + lastTimeMap = ltMap; + statusMap = sMap; + + dismissEntity = dEntity; + + fragment = fment; + context = fment.getActivity(); + + isRemove = false; + isLoading = false; + isNetworkError = false; + + list = new ArrayList(); + + new Thread(runnable) {}.start(); + } + + Runnable runnable = new Runnable() { + @Override + public void run() { + addList(0); + } + }; + + public void addList(final int offset) { + isLoading = true; + + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + + "v1d45/plugin/zuixin?limit=20&offset=" + offset, + Constants.GAME_CD), new Response.Listener() { + + @Override + public void onResponse(JSONArray response) { + processingData(response, offset); + isLoading = false; + } + + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + isLoading = false; + // 无网络连接和访问超时 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + if (offset == 0) { + if (game_swipe_refresh.isRefreshing()) { + game_swipe_refresh.setRefreshing(false); + } + recyclerView.setVisibility(View.GONE); + reuse_no_connection.setVisibility(View.VISIBLE); + } else { + Toast.makeText(context, "网络错误", + Toast.LENGTH_SHORT).show(); + isNetworkError = true; + notifyItemChanged(getItemCount() - 1); + } + } + } + + }); + AppController.addToRequestQueue(request, Plugin2Fragment.class); + } + + private void processingData(JSONArray response, int offset) { + Type listType = new TypeToken>() { + }.getType(); + Gson gson = new Gson(); + GameManager manager = new GameManager(context); + List gameList = gson + .fromJson(response.toString(), listType); + if (gameList != null && !gameList.isEmpty()) { + if (!list.isEmpty()) { + for (int i = 0; i < gameList.size(); i++) { + GameEntity entity = gameList.get(i); + // 去重 + for (int j = 0; j < list.size(); j++) { + if (list.get(j).getId().equals(entity.getId())) { + gameList.remove(i); + i--; + break; + } + } + } + } + for (GameEntity entity : gameList) { + // 黄壮华 初始化游戏状态 修改2015/8/15 + entity.setEntryMap(gameMap.get(entity.getName())); + list.add(entity); + if (!fragment.isHidden() && !fragment.isEverpause()) { + notifyItemInserted(list.size() - 1); + } + for (ApkEntity apkEntity : entity.getApk()) { + manager.addOrUpdate(new GameInfo(apkEntity.getPackageName(), + entity.getId(), entity.getName())); + } + } + } + + if (fragment.isHidden() || fragment.isEverpause()) { + notifyDataSetChanged(); + } + + if (offset == 0 && game_swipe_refresh.isRefreshing()) { + game_swipe_refresh.setRefreshing(false); + } + + if (gameList.isEmpty() || (offset == 0 && gameList.size() < 20)) { + isRemove = true; + notifyItemRemoved(getItemCount()); + } + + // 黄壮华 获取游戏位置信息 修改2015/8/15 + for (int i = 0, size = list.size(); i < size; i++) { + GameEntity entity = list.get(i); + locationMap.put(entity.getName(), i); + for (ApkEntity apkEntity : entity.getApk()) { + nameMap.put(apkEntity.getPackageName(), entity.getName()); + } + } + } + + @Override + public int getItemCount() { + if (list.isEmpty()) { + return 0; + } + if (isRemove) { + return list.size(); + } else { + return list.size() + 1; + } + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, + int position) { + if (viewHolder instanceof GameViewHolder) { + GameViewHolder holder = (GameViewHolder) viewHolder; + final GameEntity detailedEntity = list.get(position); + ImageUtils.getInstance(context).display(detailedEntity.getIcon(), + holder.gameThumb); + if (detailedEntity.getApk() == null + || detailedEntity.getApk().isEmpty()) { + holder.gameNameAndSize.setText(detailedEntity.getName()); + } else { + holder.gameNameAndSize.setText(detailedEntity.getName() + + " | " + detailedEntity.getApk().get(0).getSize()); + } + holder.gameDes.setText(detailedEntity.getBrief()); + + GameViewUtils.setLabelList(context, holder.labelList, + detailedEntity.getTag()); + + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + Map kv = new HashMap(); + kv.put("入口", "插件-最新"); + TCAgent.onEvent(context, "游戏详情", detailedEntity.getName(), + kv); + + Map map = new HashMap(); + map.put("location", "最新"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", detailedEntity.getName()); + map.put("page", "插件"); + DataCollectionManager.onEvent(context, "click-item", map); + + AppController.put("GameEntity", detailedEntity); + Intent intent = new Intent(context, + GameDetailsActivity.class); + intent.putExtra("entrance", "插件-最新"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + }); + + DownloadItemUtils.setOnClickListener(context, holder.downloadBtn, + holder.downloadSpeed, holder.downloadPercentage, + detailedEntity, position, this, handler, lastTimeMap, + statusMap, platformMap, "插件-最新", dismissEntity, "最新:" + + detailedEntity.getName()); + + DownloadItemUtils.updateItem(context, holder.labelList, + holder.gameProgressbar, holder.gameInfo, + holder.downloadSpeed, holder.downloadPercentage, + holder.downloadBtn, detailedEntity, platformMap, statusMap); + } else if (viewHolder instanceof FooterViewHolder) { + FooterViewHolder holder = (FooterViewHolder) viewHolder; + if (isNetworkError) { + holder.footerview_progressbar.setVisibility(View.GONE); + holder.footerview_tv_loading.setText("加载失败,点击重试"); + holder.rootView.setClickable(true); + holder.rootView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + isNetworkError = false; + notifyItemChanged(getItemCount() - 1); + addList(list.size()); + } + }); + } else { + holder.footerview_progressbar.setVisibility(View.VISIBLE); + holder.footerview_tv_loading.setText("加载中..."); + holder.rootView.setClickable(false); + } + } + } + + @Override + public int getItemViewType(int position) { + return position; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { + if (i != list.size()) { + return new GameViewHolder(LayoutInflater.from( + viewGroup.getContext()).inflate( + R.layout.home_list_item_gamenormal_type, viewGroup, false)); + } else { + return new FooterViewHolder(LayoutInflater.from( + viewGroup.getContext()).inflate( + R.layout.refresh_footerview, viewGroup, false)); + } + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + notifyDataSetChanged(); + } + + public boolean isRemove() { + return isRemove; + } + + public void setRemove(boolean isRemove) { + this.isRemove = isRemove; + } + + public boolean isLoading() { + return isLoading; + } + + public void setLoading(boolean isLoading) { + this.isLoading = isLoading; + } + + public boolean isNetworkError() { + return isNetworkError; + } + + public void setNetworkError(boolean isNetworkError) { + this.isNetworkError = isNetworkError; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/plugin/Plugin3Fragment.java b/app/src/main/java/com/gh/gamecenter/plugin/Plugin3Fragment.java new file mode 100644 index 0000000000..7f43bb67f5 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/plugin/Plugin3Fragment.java @@ -0,0 +1,351 @@ +package com.gh.gamecenter.plugin; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; + +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.util.ArrayMap; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener; +import android.support.v7.widget.DefaultItemAnimator; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +import com.gh.base.AppController; +import com.gh.common.constant.Constants; +import com.gh.common.util.DownloadItemUtils; +import com.gh.common.view.VerticalItemDecoration; +import com.gh.download.DataWatcher; +import com.gh.download.DownloadEntry; +import com.gh.download.DownloadManager; +import com.gh.gamecenter.R; +import com.gh.gamecenter.entity.ApkEntity; +import com.gh.gamecenter.entity.DismissEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.eventbus.EBDownloadDelete; +import com.gh.gamecenter.eventbus.EBNetworkState; +import com.gh.gamecenter.eventbus.EBPWDismiss; +import com.gh.gamecenter.eventbus.EBPackage; +import com.gh.gamecenter.eventbus.EBUISwitch; + +import de.greenrobot.event.EventBus; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-8-8 + * @update 2015-8-11 + * @des 主页插件fragment + */ +public class Plugin3Fragment extends Fragment implements OnRefreshListener { + + private View view; + private RecyclerView recyclerview; + private SwipeRefreshLayout game_swipe_refresh; + private Plugin3FragmentAdapter adapter; + private LinearLayoutManager layoutManager; + private LinearLayout reuse_no_connection; + + // 黄壮华 添加 记录信息的map 修改2015/8/15 + private ArrayMap locationMap; + private ArrayMap> gameMap; + private ArrayMap> platformMap; + private ArrayMap nameMap; + + private boolean isEverpause = false; + private boolean isDestroy = false; + + private ArrayMap lastTimeMap; + private ArrayMap statusMap; + + private DismissEntity dismissEntity; + + private Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (!isDestroy) { + if (msg.what == Constants.DOWNLOAD_ROLL) { + String name = (String) msg.obj; + if (platformMap != null) { + LinkedBlockingQueue queue = platformMap + .get(name); + if (queue.size() > 1) { + queue.offer(queue.poll()); + Message msg2 = Message.obtain(); + msg2.obj = name; + msg2.what = Constants.DOWNLOAD_ROLL; + sendMessageDelayed(msg2, 3000); + } + } + } else if (msg.what == Constants.CONTINUE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + DownloadManager.getInstance(getActivity()).resume(url); + } + } else if (msg.what == Constants.PAUSE_DOWNLOAD_TASK) { + String url = (String) msg.obj; + if (System.currentTimeMillis() - lastTimeMap.get(url) >= 1000) { + DownloadManager.getInstance(getActivity()).pause(url); + } + } + } + } + }; + + // 黄壮华 添加观察者 修改2015/8/15 + private DataWatcher dataWatcher = new DataWatcher() { + @Override + public void onDataChanged( + HashMap downloadingEntries) { + if (!game_swipe_refresh.isRefreshing()) { + for (java.util.Map.Entry entry : downloadingEntries + .entrySet()) { + DownloadEntry downloadEntry = entry.getValue(); + + Integer location = locationMap.get(downloadEntry.getName()); + if (location != null) { + int index = location.intValue(); + + GameEntity detailedEntity = adapter.getList() + .get(index); + + if (detailedEntity != null) { + DownloadItemUtils.processDate(detailedEntity, + downloadEntry, platformMap, handler, + adapter, index, statusMap); + } + + } + } + } + } + }; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + view = View.inflate(getActivity(), R.layout.plugin1_fragment, null); + + lastTimeMap = new ArrayMap(); + statusMap = new ArrayMap(); + locationMap = new ArrayMap(); + gameMap = new ArrayMap>(); + platformMap = new ArrayMap>(); + nameMap = new ArrayMap(); + + dismissEntity = new DismissEntity(false); + + game_swipe_refresh = (SwipeRefreshLayout) view + .findViewById(R.id.game_swipe_refresh); + game_swipe_refresh.setColorSchemeResources(R.color.theme_colors); + game_swipe_refresh.setOnRefreshListener(this); + + recyclerview = (RecyclerView) view.findViewById(R.id.game_list); + recyclerview.setHasFixedSize(true); + layoutManager = new LinearLayoutManager(getActivity()); + recyclerview.setLayoutManager(layoutManager); + recyclerview.setItemAnimator(new DefaultItemAnimator()); + + // 黄壮华 添加 初始化游戏状态 修改2015/8/21 + DownloadItemUtils.initializeGameMap(getActivity(), gameMap); + + reuse_no_connection = (LinearLayout) view + .findViewById(R.id.reuse_no_connection); + reuse_no_connection.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + game_swipe_refresh.setRefreshing(true); + recyclerview.setVisibility(View.VISIBLE); + reuse_no_connection.setVisibility(View.GONE); + handler.postDelayed(runnable, 1000); + } + }); + + // 黄壮华 传递引用 修改2015/8/15 + adapter = new Plugin3FragmentAdapter(Plugin3Fragment.this, locationMap, + gameMap, platformMap, nameMap, recyclerview, + game_swipe_refresh, reuse_no_connection, handler, lastTimeMap, + statusMap, dismissEntity); + recyclerview.setAdapter(adapter); + recyclerview.setOnScrollListener(new RecyclerView.OnScrollListener() { + + @Override + public void onScrollStateChanged(RecyclerView recyclerView, + int newState) { + super.onScrollStateChanged(recyclerView, newState); + if (newState == RecyclerView.SCROLL_STATE_IDLE + && layoutManager.findLastVisibleItemPosition() == adapter + .getList().size()) { + if (!adapter.isRemove() && !adapter.isLoading()) { + adapter.addList(adapter.getList().size()); + } + } + } + + }); + recyclerview.addItemDecoration(new VerticalItemDecoration( + getActivity(), 1)); + + EventBus.getDefault().register(this); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + if (container != null) { + container.removeView(view); + } + return view; + } + + public void onEventMainThread(EBDownloadDelete busThree) { + LinkedBlockingQueue queue = platformMap.get(busThree.getName()); + if (queue != null) { + queue.remove(busThree.getPlatform()); + platformMap.put(busThree.getName(), queue); + } + Integer location = locationMap.get(busThree.getName()); + if (location != null) { + int index = location.intValue(); + GameEntity detailedEntity = adapter.getList().get(index); + if (TextUtils.isEmpty(busThree.getPlatform())) { + detailedEntity.getEntryMap().remove("官方版"); + } else { + detailedEntity.getEntryMap().remove(busThree.getPlatform()); + } + adapter.notifyItemChanged(index); + } + } + + public void onEventMainThread(EBPWDismiss dismiss) { + if (dismissEntity != null) { + dismissEntity.setShow(false); + } + } + + public void onEventMainThread(EBPackage busFour) { + String name = nameMap.get(busFour.getPackageName()); + if (name != null) { + int location = locationMap.get(name); + if ("安装".equals(busFour.getType())) { + GameEntity detailedEntity = adapter.getList().get(location); + for (ApkEntity apkEntity : detailedEntity.getApk()) { + if (apkEntity.getPackageName().equals( + busFour.getPackageName())) { + detailedEntity.getEntryMap().remove( + apkEntity.getPlatform()); + adapter.notifyItemChanged(location); + break; + } + } + } else if ("卸载".equals(busFour.getType())) { + adapter.notifyItemChanged(location); + } + } + } + + public void onEventMainThread(EBNetworkState busNetworkState) { + if (busNetworkState.isNetworkConnected()) { + if (reuse_no_connection.getVisibility() == View.VISIBLE) { + game_swipe_refresh.setRefreshing(true); + recyclerview.setVisibility(View.VISIBLE); + reuse_no_connection.setVisibility(View.GONE); + handler.postDelayed(runnable, 1000); + } else if (adapter.isNetworkError()) { + adapter.setNetworkError(false); + adapter.notifyItemChanged(adapter.getItemCount() - 1); + adapter.addList(adapter.getList().size()); + } + } + } + + public void onEventMainThread(EBUISwitch busNine) { + if ("MainActivity".equals(busNine.getFrom())) { + if (busNine.getPosition() != 1) { + statusMap.clear(); + } + } + } + + public boolean isEverpause() { + return isEverpause; + } + + @Override + public void onResume() { + super.onResume(); + if (isEverpause) { + // 黄壮华 添加 初始化游戏状态 修改2015/8/20 + DownloadItemUtils.initializeGameMap(getActivity(), gameMap); + List entities = new ArrayList(); + for (GameEntity entity : adapter.getList()) { + entity.setEntryMap(gameMap.get(entity.getName())); + entities.add(entity); + } + adapter.setList(entities); + } + isEverpause = false; + DownloadManager.getInstance(getActivity()).addObserver(dataWatcher); + } + + @Override + public void onPause() { + super.onPause(); + isEverpause = true; + statusMap.clear(); + DownloadManager.getInstance(getActivity()).removeObserver(dataWatcher); + } + + Runnable runnable = new Runnable() { + @Override + public void run() { + adapter = new Plugin3FragmentAdapter(Plugin3Fragment.this, + locationMap, gameMap, platformMap, nameMap, recyclerview, + game_swipe_refresh, reuse_no_connection, handler, + lastTimeMap, statusMap, dismissEntity); + recyclerview.setAdapter(adapter); + } + }; + + @Override + public void onRefresh() { + handler.postDelayed(runnable, 1000); + } + + @Override + public void onDestroy() { + super.onDestroy(); + AppController.canclePendingRequests(Plugin3Fragment.class); + EventBus.getDefault().unregister(this); + view = null; + recyclerview = null; + game_swipe_refresh = null; + adapter = null; + layoutManager = null; + reuse_no_connection = null; + locationMap = null; + gameMap = null; + platformMap = null; + nameMap = null; + lastTimeMap = null; + statusMap = null; + dismissEntity = null; + handler = null; + dataWatcher = null; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/plugin/Plugin3FragmentAdapter.java b/app/src/main/java/com/gh/gamecenter/plugin/Plugin3FragmentAdapter.java new file mode 100644 index 0000000000..15b73276b1 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/plugin/Plugin3FragmentAdapter.java @@ -0,0 +1,387 @@ +package com.gh.gamecenter.plugin; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.LinkedBlockingQueue; + +import org.json.JSONArray; + +import android.content.Context; +import android.content.Intent; +import android.os.Handler; +import android.support.v4.util.ArrayMap; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.Toast; + +import com.android.volley.NoConnectionError; +import com.android.volley.Response; +import com.android.volley.TimeoutError; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.common.util.DownloadItemUtils; +import com.gh.common.util.GameViewUtils; +import com.gh.common.util.ImageUtils; +import com.gh.common.util.TimestampUtils; +import com.gh.download.DownloadEntry; +import com.gh.gamecenter.GameDetailsActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.adapter.viewholder.FooterViewHolder; +import com.gh.gamecenter.adapter.viewholder.GameViewHolder; +import com.gh.gamecenter.db.info.GameInfo; +import com.gh.gamecenter.entity.ApkEntity; +import com.gh.gamecenter.entity.DismissEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.manager.GameManager; +import com.gh.gamecenter.volley.extended.JsonArrayExtendedRequest; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.tendcloud.tenddata.TCAgent; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-8-8 + * @update 2015-8-11 + * @des 首页插件fragment适配器 + */ + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-8-8 + * @update 2015-8-11 + * @des 首页插件fragment适配器 + */ +public class Plugin3FragmentAdapter extends + RecyclerView.Adapter { + + private Context context; + + private Plugin3Fragment fragment; + + private RecyclerView recyclerView; + private SwipeRefreshLayout game_swipe_refresh; + private LinearLayout reuse_no_connection; + + private boolean isRemove; + private boolean isLoading; + private boolean isNetworkError; + + private List list; + + // 黄壮华 获取引用 修改2015/8/15 + private ArrayMap locationMap; + private ArrayMap> gameMap; + private ArrayMap> platformMap; + private ArrayMap nameMap; + + private Handler handler; + private ArrayMap lastTimeMap; + private ArrayMap statusMap; + + private DismissEntity dismissEntity; + + // 黄壮华 获取引用 修改2015/8/15 + public Plugin3FragmentAdapter(Plugin3Fragment fment, + ArrayMap lMap, + ArrayMap> gMap, + ArrayMap> pMap, + ArrayMap nMap, RecyclerView rView, + SwipeRefreshLayout swipeRefreshLayout, LinearLayout linearLayout, + Handler hdler, ArrayMap ltMap, + ArrayMap sMap, DismissEntity dEntity) { + + // 黄壮华 获取引用 修改2015/8/15 + locationMap = lMap; + gameMap = gMap; + platformMap = pMap; + nameMap = nMap; + + handler = hdler; + lastTimeMap = ltMap; + statusMap = sMap; + + recyclerView = rView; + game_swipe_refresh = swipeRefreshLayout; + reuse_no_connection = linearLayout; + + dismissEntity = dEntity; + + fragment = fment; + context = fment.getActivity(); + + isRemove = false; + isLoading = false; + isNetworkError = false; + + list = new ArrayList(); + + new Thread(runnable) {}.start(); + } + + Runnable runnable = new Runnable() { + @Override + public void run() { + addList(0); + } + }; + + public void addList(final int offset) { + isLoading = true; + + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + + "v1d45/plugin/danji?limit=20&offset=" + offset, + Constants.GAME_CD), new Response.Listener() { + + @Override + public void onResponse(JSONArray response) { + processingData(response, offset); + isLoading = false; + } + + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + isLoading = false; + // 无网络连接 + if (error.getClass().equals(NoConnectionError.class) + || error.getClass().equals(TimeoutError.class)) { + if (offset == 0) { + if (game_swipe_refresh.isRefreshing()) { + game_swipe_refresh.setRefreshing(false); + } + recyclerView.setVisibility(View.GONE); + reuse_no_connection.setVisibility(View.VISIBLE); + } else { + Toast.makeText(context, "网络错误", + Toast.LENGTH_SHORT).show(); + isNetworkError = true; + notifyItemChanged(getItemCount() - 1); + } + } + } + + }); + AppController.addToRequestQueue(request, Plugin3Fragment.class); + } + + private void processingData(JSONArray response, int offset) { + Type listType = new TypeToken>() { + }.getType(); + Gson gson = new Gson(); + GameManager manager = new GameManager(context); + List gameList = gson + .fromJson(response.toString(), listType); + if (gameList != null && !gameList.isEmpty()) { + if (!list.isEmpty()) { + for (int i = 0; i < gameList.size(); i++) { + GameEntity entity = gameList.get(i); + // 去重 + for (int j = 0; j < list.size(); j++) { + if (list.get(j).getId().equals(entity.getId())) { + gameList.remove(i); + i--; + break; + } + } + } + } + for (GameEntity entity : gameList) { + // 黄壮华 初始化游戏状态 修改2015/8/15 + entity.setEntryMap(gameMap.get(entity.getName())); + list.add(entity); + if (!fragment.isHidden() && !fragment.isEverpause()) { + notifyItemInserted(list.size() - 1); + } + for (ApkEntity apkEntity : entity.getApk()) { + manager.addOrUpdate(new GameInfo(apkEntity.getPackageName(), + entity.getId(), entity.getName())); + } + } + } + + if (fragment.isHidden() || fragment.isEverpause()) { + notifyDataSetChanged(); + } + + if (offset == 0 && game_swipe_refresh.isRefreshing()) { + game_swipe_refresh.setRefreshing(false); + } + + if (gameList.isEmpty() || (offset == 0 && gameList.size() < 20)) { + isRemove = true; + notifyItemRemoved(getItemCount()); + } + + // 黄壮华 获取游戏位置信息 修改2015/8/15 + for (int i = 0, size = list.size(); i < size; i++) { + GameEntity entity = list.get(i); + locationMap.put(entity.getName(), i); + for (ApkEntity apkEntity : entity.getApk()) { + nameMap.put(apkEntity.getPackageName(), entity.getName()); + } + } + } + + @Override + public int getItemCount() { + if (list.size() == 0) { + return 0; + } + if (isRemove) { + return list.size(); + } else { + return list.size() + 1; + } + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, + final int position) { + if (viewHolder instanceof GameViewHolder) { + + GameViewHolder holder = (GameViewHolder) viewHolder; + + final GameEntity detailedEntity = list.get(position); + + detailedEntity.getApk().get(0).setPlatform("local_plugin"); + + ImageUtils.getInstance(context).display(detailedEntity.getIcon(), + holder.gameThumb); + if (detailedEntity.getApk() == null + || detailedEntity.getApk().isEmpty()) { + holder.gameNameAndSize.setText(detailedEntity.getName()); + } else { + holder.gameNameAndSize.setText(detailedEntity.getName() + + " | " + detailedEntity.getApk().get(0).getSize()); + } + holder.gameDes.setText(detailedEntity.getBrief()); + + GameViewUtils.setLabelList(context, holder.labelList, + detailedEntity.getTag()); + + holder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + Map kv = new HashMap(); + kv.put("入口", "插件-单机"); + TCAgent.onEvent(context, "游戏详情", detailedEntity.getName(), + kv); + + Map map = new HashMap(); + map.put("location", "单机"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", detailedEntity.getName()); + map.put("page", "插件"); + DataCollectionManager.onEvent(context, "click-item", map); + + AppController.put("GameEntity", detailedEntity); + Intent intent = new Intent(context, + GameDetailsActivity.class); + intent.putExtra("entrance", "插件-单机"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + }); + + DownloadItemUtils.setOnClickListener(context, holder.downloadBtn, + holder.downloadSpeed, holder.downloadPercentage, + detailedEntity, position, this, handler, lastTimeMap, + statusMap, platformMap, "插件-单机", false, dismissEntity, + "单机:" + detailedEntity.getName()); + + DownloadItemUtils.updateItem(context, holder.labelList, + holder.gameProgressbar, holder.gameInfo, + holder.downloadSpeed, holder.downloadPercentage, + holder.downloadBtn, detailedEntity, platformMap, statusMap, + false); + } else if (viewHolder instanceof FooterViewHolder) { + FooterViewHolder holder = (FooterViewHolder) viewHolder; + if (isNetworkError) { + holder.footerview_progressbar.setVisibility(View.GONE); + holder.footerview_tv_loading.setText("加载失败,点击重试"); + holder.rootView.setClickable(true); + holder.rootView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + isNetworkError = false; + notifyItemChanged(getItemCount() - 1); + addList(list.size()); + } + }); + } else { + holder.footerview_progressbar.setVisibility(View.VISIBLE); + holder.footerview_tv_loading.setText("加载中..."); + holder.rootView.setClickable(false); + } + } + } + + @Override + public int getItemViewType(int position) { + return position; + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { + if (i == list.size()) { + return new FooterViewHolder(LayoutInflater.from( + viewGroup.getContext()).inflate( + R.layout.refresh_footerview, viewGroup, false)); + } else { + return new GameViewHolder(LayoutInflater.from( + viewGroup.getContext()).inflate( + R.layout.home_list_item_gamenormal_type, viewGroup, false)); + } + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + notifyDataSetChanged(); + } + + public boolean isRemove() { + return isRemove; + } + + public void setRemove(boolean isRemove) { + this.isRemove = isRemove; + } + + public boolean isLoading() { + return isLoading; + } + + public void setLoading(boolean isLoading) { + this.isLoading = isLoading; + } + + public boolean isNetworkError() { + return isNetworkError; + } + + public void setNetworkError(boolean isNetworkError) { + this.isNetworkError = isNetworkError; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/plugin/PluginFragment.java b/app/src/main/java/com/gh/gamecenter/plugin/PluginFragment.java new file mode 100644 index 0000000000..054ed9ffad --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/plugin/PluginFragment.java @@ -0,0 +1,487 @@ +package com.gh.gamecenter.plugin; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.graphics.Rect; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.app.FragmentTransaction; +import android.support.v4.view.ViewPager; +import android.support.v4.view.ViewPager.OnPageChangeListener; +import android.text.TextUtils; +import android.util.DisplayMetrics; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.PopupWindow; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.gh.common.constant.Config; +import com.gh.common.util.DisplayUtils; +import com.gh.download.DownloadManager; +import com.gh.gamecenter.ConcernActivity; +import com.gh.gamecenter.DownloadManagerActivity; +import com.gh.gamecenter.MainActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.SearchActivity; +import com.gh.gamecenter.SettingActivity; +import com.gh.gamecenter.eventbus.EBRedDot; +import com.gh.gamecenter.eventbus.EBSkipNewPlugin; +import com.gh.gamecenter.eventbus.EBTopState; +import com.gh.gamecenter.eventbus.EBUISwitch; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.manager.PackageManager; +import com.tendcloud.tenddata.TCAgent; + +import de.greenrobot.event.EventBus; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-8-8 主页fragment3页面 + */ +public class PluginFragment extends Fragment implements OnClickListener, + OnPageChangeListener { + + private View view, slideLine; + private ViewPager viewPager; + private TextView jingpinText, zuixinText, danjiText, downloadHint, + searchHint; + private RelativeLayout.LayoutParams rparams; + + private int width; + + private String hint; + + public static boolean isFirst; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + view = View.inflate(getActivity(), R.layout.plugin_container_fragments, + null); + + SharedPreferences sp = getActivity().getSharedPreferences( + Config.PREFERENCE, Context.MODE_PRIVATE); + + LinearLayout home_actionbar = (LinearLayout) view + .findViewById(R.id.home_actionbar); + LayoutParams params = new LayoutParams( + LayoutParams.MATCH_PARENT, sp.getInt("actionbar_height", + DisplayUtils.dip2px(getActivity(), 48))); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + int top = DisplayUtils.getInternalDimensionSize(getResources(), + "status_bar_height"); + home_actionbar.setPadding(0, top, 0, 0); + params.height += top; + } + + home_actionbar.setLayoutParams(params); + + initActionBar(); + + viewPager = (ViewPager) view.findViewById(R.id.pager); + + slideLine = view.findViewById(R.id.slide_line); + jingpinText = (TextView) view.findViewById(R.id.jingpin_text); + zuixinText = (TextView) view.findViewById(R.id.zuixin_text); + danjiText = (TextView) view.findViewById(R.id.danji_text); + + jingpinText.setOnClickListener(this); + zuixinText.setOnClickListener(this); + danjiText.setOnClickListener(this); + + DisplayMetrics outMetrics = new DisplayMetrics(); + getActivity().getWindowManager().getDefaultDisplay() + .getMetrics(outMetrics); + width = outMetrics.widthPixels / 3; + rparams = new RelativeLayout.LayoutParams(width / 2, + DisplayUtils.dip2px(getActivity(), 2)); + rparams.addRule(RelativeLayout.BELOW, R.id.plugin_ll_top); + + viewPager.setAdapter(new FragmentAdapter(getChildFragmentManager())); + viewPager.setOffscreenPageLimit(3); + viewPager.addOnPageChangeListener(this); + + if (isFirst) { + rparams.leftMargin = width + width / 4; + slideLine.setLayoutParams(rparams); + viewPager.setCurrentItem(1); + isFirst = false; + jingpinText.setClickable(true); + zuixinText.setClickable(false); + danjiText.setClickable(true); + } else { + rparams.leftMargin = width / 4; + slideLine.setLayoutParams(rparams); + jingpinText.setClickable(false); + zuixinText.setClickable(true); + danjiText.setClickable(true); + } + + EventBus.getDefault().register(this); + + } + + private void initActionBar() { + view.findViewById(R.id.actionbar_rl_download).setOnClickListener(this); + + view.findViewById(R.id.actionbar_iv_search).setOnClickListener(this); + + if (Config.isShow) { + view.findViewById(R.id.actionbar_rl_download).setVisibility( + View.VISIBLE); + } else { + view.findViewById(R.id.actionbar_rl_download).setVisibility( + View.GONE); + } + + downloadHint = (TextView) view.findViewById(R.id.action_tip); + int updateSize = PackageManager.getUpdateListSize(); + int downloadSize = DownloadManager.getInstance(getActivity()).getAll() + .size(); + if (downloadSize != 0) { + downloadHint.setVisibility(View.VISIBLE); + downloadHint.setText(downloadSize + ""); + int width = DisplayUtils.dip2px(getActivity(), 12); + RelativeLayout.LayoutParams rparams = new RelativeLayout.LayoutParams( + width, width); + rparams.topMargin = DisplayUtils.dip2px(getActivity(), 8); + rparams.rightMargin = DisplayUtils.dip2px(getActivity(), 2); + rparams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + downloadHint.setLayoutParams(rparams); + } else if (updateSize != 0) { + downloadHint.setText(""); + int width = DisplayUtils.dip2px(getActivity(), 10); + RelativeLayout.LayoutParams rparams = new RelativeLayout.LayoutParams( + width, width); + rparams.topMargin = DisplayUtils.dip2px(getActivity(), 8); + rparams.rightMargin = DisplayUtils.dip2px(getActivity(), 3); + rparams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + downloadHint.setLayoutParams(rparams); + } else { + downloadHint.setVisibility(View.GONE); + } + + searchHint = (TextView) view.findViewById(R.id.actionbar_search_input); + searchHint.setOnClickListener(this); + if (!TextUtils.isEmpty(MainActivity.searchHint)) { + hint = MainActivity.searchHint; + searchHint.setHint(hint); + } + + view.findViewById(R.id.actionbar_notification).setOnClickListener(this); + + view.findViewById(R.id.actionbar_overflow).setOnClickListener(this); + + if (downloadSize != 0 || updateSize != 0) { + EventBus.getDefault().post(new EBTopState("显示", null)); + } + } + + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + if (container != null) { + container.removeView(view); + } + return view; + } + + private class FragmentAdapter extends FragmentPagerAdapter { + + public FragmentAdapter(FragmentManager fm) { + super(fm); + + } + + @Override + public Fragment getItem(int position) { + + if (position == 0) { + return new Plugin1Fragment(); + } else if (position == 1) { + return new Plugin2Fragment(); + } else { + return new Plugin3Fragment(); + } + } + + @Override + public int getCount() { + + return 3; + } + + } + + @Override + public void onClick(View v) { + final int id = v.getId(); + if (id == R.id.jingpin_text) { + viewPager.setCurrentItem(0); + } else if (id == R.id.zuixin_text) { + viewPager.setCurrentItem(1); + } else if (id == R.id.danji_text) { + viewPager.setCurrentItem(2); + } else if (id == R.id.actionbar_notification) { + TCAgent.onEvent(getActivity(), "主页", "关注图标"); + + Map map = new HashMap(); + map.put("location", "关注图标"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "主页"); + DataCollectionManager.onEvent(getActivity(), "click-item", map); + + startActivity(new Intent(getActivity(), ConcernActivity.class)); + } else if (id == R.id.actionbar_rl_download) { + TCAgent.onEvent(getActivity(), "主页", "下载图标"); + + Map map = new HashMap(); + map.put("location", "下载图标"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "主页"); + DataCollectionManager.onEvent(getActivity(), "click-item", map); + + if (downloadHint != null + && downloadHint.getVisibility() == View.VISIBLE) { + downloadHint.setVisibility(View.GONE); + EventBus.getDefault().post(new EBTopState("隐藏", null)); + } + startActivity(new Intent(getActivity(), + DownloadManagerActivity.class)); + } else if (id == R.id.actionbar_search_input) { + TCAgent.onEvent(getActivity(), "主页", "搜索框"); + + Map map = new HashMap(); + map.put("location", "搜索框"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "主页"); + DataCollectionManager.onEvent(getActivity(), "click-item", map); + + Intent goSearch = new Intent(getActivity(), SearchActivity.class); + goSearch.putExtra("clicked", false); + goSearch.putExtra("hint", hint); + startActivity(goSearch); + } else if (id == R.id.actionbar_iv_search) { + TCAgent.onEvent(getActivity(), "主页", "搜索图标"); + + Map map = new HashMap(); + map.put("location", "搜索图标"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "主页"); + DataCollectionManager.onEvent(getActivity(), "click-item", map); + + Intent searchIntent = new Intent(getActivity(), + SearchActivity.class); + searchIntent.putExtra("clicked", true); + searchIntent.putExtra("hint", hint); + startActivity(searchIntent); + } else if (id == R.id.actionbar_overflow) { + TCAgent.onEvent(getActivity(), "主页", "更多图标"); + + Map map = new HashMap(); + map.put("location", "更多图标"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("page", "主页"); + DataCollectionManager.onEvent(getActivity(), "click-item", map); + + popUpOverflow(v); + } else if (id == R.id.menu_rl_set) { + v.setVisibility(View.GONE); + startActivity(new Intent(getActivity(), SettingActivity.class)); + } + } + + public void updateRedDot(int type) { + int downloadSize = DownloadManager.getInstance(getActivity()).getAll() + .size(); + if (type == 1 && downloadSize == 0) { + downloadHint.setVisibility(View.VISIBLE); + downloadHint.setText((downloadSize + type) + ""); + int width = DisplayUtils.dip2px(getActivity(), 12); + RelativeLayout.LayoutParams rparams = new RelativeLayout.LayoutParams( + width, width); + rparams.topMargin = DisplayUtils.dip2px(getActivity(), 8); + rparams.rightMargin = DisplayUtils.dip2px(getActivity(), 2); + rparams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + downloadHint.setLayoutParams(rparams); + } else if (type == -1 && (downloadSize == 0 || downloadSize == 1)) { + int updateSize = PackageManager.getUpdateList().size(); + if (updateSize != 0) { + downloadHint.setVisibility(View.VISIBLE); + downloadHint.setText(""); + int width = DisplayUtils.dip2px(getActivity(), 10); + RelativeLayout.LayoutParams rparams = new RelativeLayout.LayoutParams( + width, width); + rparams.topMargin = DisplayUtils.dip2px(getActivity(), 8); + rparams.rightMargin = DisplayUtils.dip2px(getActivity(), 3); + rparams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + downloadHint.setLayoutParams(rparams); + } else { + downloadHint.setVisibility(View.GONE); + } + } else if (downloadSize != 0) { + downloadHint.setVisibility(View.VISIBLE); + downloadHint.setText((downloadSize + type) + ""); + } + } + + private void popUpOverflow(View view) { + + Rect frame = new Rect(); + getActivity().getWindow().getDecorView() + .getWindowVisibleDisplayFrame(frame); + + int xOffset = DisplayUtils.dip2px(getActivity(), 5); + int yOffset = frame.top + DisplayUtils.dip2px(getActivity(), 48) + + xOffset; + + View popView = View.inflate(getActivity(), R.layout.menu_popwindow, + null); + popView.findViewById(R.id.menu_rl_set).setOnClickListener(this); + PopupWindow popWindow = new PopupWindow(popView, + LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, true); + + popWindow.setOutsideTouchable(true); + popWindow.setAnimationStyle(android.R.style.Animation_Dialog); + popWindow.setBackgroundDrawable(getResources().getDrawable( + R.drawable.shape)); + + popWindow.showAtLocation(view, Gravity.TOP | Gravity.RIGHT, xOffset, + yOffset); + + } + + @Override + public void onPageSelected(int position) { + if (position == 0) { + jingpinText.setClickable(false); + zuixinText.setClickable(true); + danjiText.setClickable(true); + jingpinText.setTextColor(getResources().getColor(R.color.theme_colors)); + zuixinText.setTextColor(0xFF333333); + danjiText.setTextColor(0xFF333333); + EventBus.getDefault().post(new EBUISwitch("PluginFragment", 0)); + } else if (position == 1) { + jingpinText.setClickable(true); + zuixinText.setClickable(false); + danjiText.setClickable(true); + jingpinText.setTextColor(0xFF333333); + zuixinText.setTextColor(getResources().getColor(R.color.theme_colors)); + danjiText.setTextColor(0xFF333333); + EventBus.getDefault().post(new EBUISwitch("PluginFragment", 1)); + } else if (position == 2) { + jingpinText.setClickable(true); + zuixinText.setClickable(true); + danjiText.setClickable(false); + jingpinText.setTextColor(0xFF333333); + zuixinText.setTextColor(0xFF333333); + danjiText.setTextColor(getResources().getColor(R.color.theme_colors)); + EventBus.getDefault().post(new EBUISwitch("PluginFragment", 2)); + } + } + + @Override + public void onPageScrolled(int position, float positionOffset, + int positionOffsetPixels) { + if (positionOffset != 0) { + rparams.leftMargin = (int) (width * (position + positionOffset) + width / 4); + slideLine.setLayoutParams(rparams); + } + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + + public void onEventMainThread(EBUISwitch busNine) { + if ("MainActivity".equals(busNine.getFrom())) { + if (busNine.getPosition() == 1) { + EventBus.getDefault().post( + new EBUISwitch("PluginFragment", viewPager + .getCurrentItem())); + } + } + } + + public void onEventMainThread(EBTopState busTen) { + if ("搜索".equals(busTen.getType())) { + hint = busTen.getSearchHint(); + searchHint.setHint(busTen.getSearchHint()); + } else if ("隐藏".equals(busTen.getType())) { + if (downloadHint != null) { + downloadHint.setVisibility(View.GONE); + } + } + } + + public void onEventMainThread(EBRedDot busEight) { + updateRedDot(busEight.getType()); + } + + public void onEventMainThread(EBSkipNewPlugin busSix) { + if (busSix.getType() == 1) { + viewPager.setCurrentItem(1); + } + } + + @Override + public void onHiddenChanged(boolean hidden) { + + super.onHiddenChanged(hidden); + FragmentTransaction transaction = getChildFragmentManager() + .beginTransaction(); + List list = getChildFragmentManager().getFragments(); + if (list != null) { + if (hidden) { + for (Fragment fragment : getChildFragmentManager() + .getFragments()) { + transaction.hide(fragment); + } + } else { + for (Fragment fragment : getChildFragmentManager() + .getFragments()) { + transaction.show(fragment); + } + } + } + transaction.commit(); + } + + @Override + public void onDestroy() { + + super.onDestroy(); + EventBus.getDefault().unregister(this); + view = null; + slideLine = null; + viewPager = null; + jingpinText = null; + zuixinText = null; + danjiText = null; + downloadHint = null; + searchHint = null; + rparams = null; + hint = null; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/receiver/InstallAndUninstallReceiver.java b/app/src/main/java/com/gh/gamecenter/receiver/InstallAndUninstallReceiver.java new file mode 100644 index 0000000000..11650661c4 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/receiver/InstallAndUninstallReceiver.java @@ -0,0 +1,51 @@ +package com.gh.gamecenter.receiver; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import com.gh.common.util.Utils; +import com.gh.gamecenter.eventbus.EBPackage; +import com.tendcloud.tenddata.TCAgent; + +import de.greenrobot.event.EventBus; + +/** + * 监听应用安装和卸载的广播 + * @author LGT 黄壮华 + * + */ +public class InstallAndUninstallReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + + + // 接收安装广播 + if (intent.getAction().equals("android.intent.action.PACKAGE_ADDED")) { + String packageName = intent.getDataString(); + packageName = packageName.substring(packageName.indexOf(":") + 1); + Utils.log("安装了:" + packageName + "包名的程序"); + EventBus.getDefault().post(new EBPackage("安装", packageName)); + } + // 接收卸载广播 + if (intent.getAction().equals("android.intent.action.PACKAGE_REMOVED")) { + String packageName = intent.getDataString(); + packageName = packageName.substring(packageName.indexOf(":") + 1); + Utils.log("卸载了:" + packageName + "包名的程序"); + EventBus.getDefault().post(new EBPackage("卸载", packageName)); + } + + // 接收替换广播 + if (intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED)) { + String packageName = intent.getData().getSchemeSpecificPart(); + packageName = packageName.substring(packageName.indexOf(":") + 1); + Utils.log("替换了:" + packageName + "包名的程序"); + if (packageName.equals(context.getPackageName())) { + TCAgent.onEvent(context, "软件更新", "更新完成"); + } + EventBus.getDefault().post(new EBPackage("替换", packageName)); + } + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/receiver/NetworkStateReceiver.java b/app/src/main/java/com/gh/gamecenter/receiver/NetworkStateReceiver.java new file mode 100644 index 0000000000..e1c74fe8a1 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/receiver/NetworkStateReceiver.java @@ -0,0 +1,23 @@ +package com.gh.gamecenter.receiver; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import com.gh.common.util.NetworkUtils; +import com.gh.gamecenter.eventbus.EBNetworkState; + +import de.greenrobot.event.EventBus; + +public class NetworkStateReceiver extends BroadcastReceiver { + + // 监听网络状态的变化 + @Override + public void onReceive(Context context, Intent intent) { + + EventBus.getDefault().post( + new EBNetworkState(NetworkUtils + .isNetworkConnected(context))); + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/receiver/NotificationReceiver.java b/app/src/main/java/com/gh/gamecenter/receiver/NotificationReceiver.java new file mode 100644 index 0000000000..ac3c758d8e --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/receiver/NotificationReceiver.java @@ -0,0 +1,209 @@ +package com.gh.gamecenter.receiver; + +import java.util.ArrayList; +import java.util.List; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.support.v4.util.ArrayMap; + +import com.gh.base.AppController; +import com.gh.common.util.PackageUtils; +import com.gh.common.util.RunningUtils; +import com.gh.gamecenter.DownloadManagerActivity; +import com.gh.gamecenter.GameDetailsActivity; +import com.gh.gamecenter.NewsActivity; +import com.gh.gamecenter.SplashScreenActivity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.entity.NewsDetailsEntity; +import com.gh.gamecenter.eventbus.EBMiPush; +import com.google.gson.Gson; + +import de.greenrobot.event.EventBus; + +/** + * 用于接收点击小米推送的notification的广播 + * + * @author LGT + * + */ +public class NotificationReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + try { + JSONObject jsonObject = new JSONObject( + intent.getStringExtra("notifyData")); + int id = intent.getIntExtra("notifyId", 0); + switch (id) { + case 0: + if (RunningUtils.isRunning(context)) { + // 应用正在运行,前台或后台 + NewsDetailsEntity entity = new NewsDetailsEntity(); + entity.setTitle(jsonObject.get("title").toString());// 资讯标题 + entity.setId(jsonObject.get("_id").toString());// 资讯ID + entity.setTime(jsonObject.get("publishOn").toString());// 资讯时间 + // if (isEquals(context, + // EssayDetailsActivity.class.getName())) { + // // 当前topActivity为EssayDetailsActvity + // EventBus.getDefault().post( + // new EventBusMiPush("mipush_news", entity)); + // } else { + Intent intent1 = new Intent(context, NewsActivity.class); + intent1.putExtra("entity", entity); + intent1.putExtra("entrance", "小米推送"); + intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent1); + // } + } else { + // 应用未在运行 + Intent intent1 = new Intent(context, + SplashScreenActivity.class); + intent1.setAction(Intent.ACTION_MAIN); + intent1.addCategory(Intent.CATEGORY_LAUNCHER); + NewsDetailsEntity entity = new NewsDetailsEntity(); + entity.setTitle(jsonObject.get("title").toString());// 资讯标题 + entity.setId(jsonObject.get("_id").toString());// 资讯ID + entity.setTime(jsonObject.get("publishOn").toString());// 资讯时间 + intent1.putExtra("from", "mipush_news"); + intent1.putExtra("entity", entity); + intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent1); + } + break; + case 1: + if (RunningUtils.isRunning(context)) { + // 应用正在运行,前台或后台 + JSONArray jsonArray = jsonObject.getJSONArray("apk"); + ArrayMap map = getInstalledMapFromLocal(context); + ArrayList list = new ArrayList(); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject apk = jsonArray.getJSONObject(i); + String packageName = apk.getString("package"); + Boolean b = map.get(packageName); + if (b != null) { + // 判断是否gh_version是否相同 + String gh_version = (String) PackageUtils + .getMetaData(context, packageName, "gh_version"); + if (gh_version != null) { + gh_version = gh_version.substring(2); + // 判断gh_version是否相同 + if (gh_version.equals(apk + .getString("gh_version"))) { + // 判断version是否相同 + String version = PackageUtils + .getVersionByPackage(context, + packageName); + if (version + .equals(apk.getString("version"))) { + // 版本相同,无需显示插件更新,继续查看是否有可更新的游戏包 + continue; + } + } + } + list.add(packageName); + } + } + if (RunningUtils.isEqualsTop(context, + DownloadManagerActivity.class.getName())) { + // 当前topActivity为DownloadManagerActivity + EventBus.getDefault().post(new EBMiPush("mipush_plugin", list)); + } else { + Intent intent2 = new Intent(context, + DownloadManagerActivity.class); + intent2.putExtra("currentItem", 1); + intent2.putExtra("isPushIntent", true); + intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent2); + } + } else { + // 应用未在运行 + Intent intent2 = new Intent(context, + SplashScreenActivity.class); + intent2.setAction(Intent.ACTION_MAIN); + intent2.addCategory(Intent.CATEGORY_LAUNCHER); + intent2.putExtra("from", "mipush_plugin"); + intent2.putExtra("data", jsonObject.toString()); + intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent2); + } + break; + case 2: + String tag = jsonObject.getString("tag"); + String[] tags = tag.split(","); + JSONArray array = new JSONArray(); + for (int i = 0; i < tags.length; i++) { + array.put(tags[i]); + } + jsonObject.put("tag", array); + if (RunningUtils.isRunning(context)) { + // 应用正在运行,前台或后台 + Gson gson = new Gson(); + GameEntity infoEntity = gson.fromJson( + jsonObject.toString(), GameEntity.class); + // if (isEquals(context, GameEntity.class.getName())) { + // // 当前topActivity为GameEntity + // EventBus.getDefault().post( + // new EventBusMiPush("mipush_new_game", + // infoEntity)); + // } else { + AppController.put("GameEntity", infoEntity); + Intent intent3 = new Intent(context, + GameDetailsActivity.class); + intent3.putExtra("entrance", "小米推送"); + intent3.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent3); + // } + } else { + // 应用未在运行 + Intent intent3 = new Intent(context, + SplashScreenActivity.class); + intent3.setAction(Intent.ACTION_MAIN); + intent3.addCategory(Intent.CATEGORY_LAUNCHER); + Gson gson = new Gson(); + GameEntity infoEntity = gson.fromJson( + jsonObject.toString(), GameEntity.class); + intent3.putExtra("from", "mipush_new_game"); + AppController.put("GameEntity", infoEntity); + intent3.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent3); + } + break; + default: + break; + } + } catch (JSONException e) { + + e.printStackTrace(); + } + } + + private ArrayMap getInstalledMapFromLocal(Context context) { + ArrayMap map = new ArrayMap(); + ArrayList list = getAllPackageName(context); + for (String str : list) { + map.put(str, true); + } + return map; + } + + private ArrayList getAllPackageName(Context context) { + ArrayList list = new ArrayList(); + List packageInfos = context.getPackageManager() + .getInstalledPackages(0); + for (int i = 0, size = packageInfos.size(); i < size; i++) { + PackageInfo packageInfo = packageInfos.get(i); + if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { + list.add(packageInfo.packageName); + } + } + return list; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/receiver/SmsReceiver.java b/app/src/main/java/com/gh/gamecenter/receiver/SmsReceiver.java new file mode 100644 index 0000000000..b8e0594fc7 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/receiver/SmsReceiver.java @@ -0,0 +1,69 @@ +package com.gh.gamecenter.receiver; + +import java.util.regex.Pattern; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.telephony.SmsMessage; + +import com.gh.common.util.Utils; +import com.gh.gamecenter.eventbus.EBSms; + +import de.greenrobot.event.EventBus; + +public class SmsReceiver extends BroadcastReceiver { + + public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED"; + + @Override + public void onReceive(Context context, Intent intent) { + + if (intent.getAction().equals(SMS_RECEIVED_ACTION)) { + SmsMessage[] messages = getMessagesFromIntent(intent); + + for (SmsMessage message : messages) { + String msgBody = message.getDisplayMessageBody(); + Utils.log(msgBody); + if (Pattern.matches("^【注册验证】验证码:\\d{6},您正在注册成为光环助手用户,感谢您的支持!$", msgBody)) { + String code = msgBody.substring(10, 16); + Utils.log(code); + EventBus.getDefault().post(new EBSms("注册验证", code)); + } else if (Pattern.matches("^【身份验证】验证码:\\d{6},您正在进行手机号码:\\d{11}的身份验证,打死不要告诉别人哦!$", msgBody)) { + String code = msgBody.substring(10, 16); + Utils.log(code); + EventBus.getDefault().post(new EBSms("身份验证", code)); + } else if (Pattern.matches("^【变更验证】验证码:\\d{6},您正在尝试变更光环号:.{6,}的手机号码这一重要信息,请妥善保管账户信息。$", msgBody)) { + String code = msgBody.substring(10, 16); + Utils.log(code); + EventBus.getDefault().post(new EBSms("变更验证", code)); + } else if (Pattern.matches("^【变更验证】验证码:\\d{6},您正在尝试修改光环号:.{6,}的登录密码,请妥善保管账户信息。$", msgBody)) { + String code = msgBody.substring(10, 16); + Utils.log(code); + EventBus.getDefault().post(new EBSms("变更验证", code)); + } + } + //【注册验证】验证码:195306,您正在注册成为光环助手用户,感谢您的支持! + //【身份验证】验证码:716438,您正在进行手机号码:13829769945的身份验证,打死不要告诉别人哦! + //【变更验证】验证码:293785,您正在尝试变更光环号:qqqwww的手机号码这一重要信息,请妥善保管账户信息。 + //【变更验证】验证码:901874,您正在尝试修改光环号:qqqwww的登录密码,请妥善保管账户信息。 + } + } + + public SmsMessage[] getMessagesFromIntent(Intent intent) { + Object[] messages = (Object[]) intent.getSerializableExtra("pdus"); + byte[][] pduObjs = new byte[messages.length][]; + for (int i = 0; i < messages.length; i++) { + pduObjs[i] = (byte[]) messages[i]; + } + byte[][] pdus = new byte[pduObjs.length][]; + int pduCount = pdus.length; + SmsMessage[] msgs = new SmsMessage[pduCount]; + for (int i = 0; i < pduCount; i++) { + pdus[i] = pduObjs[i]; + msgs[i] = SmsMessage.createFromPdu(pdus[i]); + } + return msgs; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/receiver/UninstallReceiver.java b/app/src/main/java/com/gh/gamecenter/receiver/UninstallReceiver.java new file mode 100644 index 0000000000..cce04c5afe --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/receiver/UninstallReceiver.java @@ -0,0 +1,77 @@ +package com.gh.gamecenter.receiver; + +import java.util.List; + +import android.app.ActivityManager; +import android.app.ActivityManager.RunningTaskInfo; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; + +import com.gh.common.util.RunningUtils; +import com.gh.gamecenter.DownloadManagerActivity; +import com.gh.gamecenter.SplashScreenActivity; +import com.gh.gamecenter.eventbus.EBMiPush; + +import de.greenrobot.event.EventBus; + +public class UninstallReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + + String path = intent.getStringExtra("path"); + if (RunningUtils.isRunning(context)) { + if (RunningUtils.isEqualsTop(context, + DownloadManagerActivity.class.getName())) { + ActivityManager manager = (ActivityManager) context + .getSystemService(Context.ACTIVITY_SERVICE); + List task_info = manager.getRunningTasks(20); + String packageName = context.getPackageName(); + for (int i = 0; i < task_info.size(); i++) { + if (packageName.equals(task_info.get(i).topActivity + .getPackageName())) { + String className = task_info.get(i).topActivity + .getClassName(); + // 这里是指从后台返回到前台 前两个的是关键 + Intent intent2 = new Intent(); + intent2.setAction(Intent.ACTION_MAIN); + intent2.addCategory(Intent.CATEGORY_LAUNCHER); + try { + intent2.setComponent(new ComponentName(context, + Class.forName(className))); + } catch (ClassNotFoundException e) { + + e.printStackTrace(); + } + // intent2.setClass(context, Class.forName(className)); + intent2.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT + | Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); + context.startActivity(intent2); + } + } + EventBus.getDefault().post(new EBMiPush("plugin_install", path)); + } else { + Intent intent2 = new Intent(context, + DownloadManagerActivity.class); + intent2.putExtra("currentItem", 0); + intent2.putExtra("path", path); + intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent2); + } + + } else { + // 应用未在运行 + Intent intent2 = new Intent(context, SplashScreenActivity.class); + intent2.setAction(Intent.ACTION_MAIN); + intent2.addCategory(Intent.CATEGORY_LAUNCHER); + intent2.putExtra("from", "plugin_install"); + intent2.putExtra("path", path); + intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent2); + } + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/search/Search1DetailFragment.java b/app/src/main/java/com/gh/gamecenter/search/Search1DetailFragment.java new file mode 100644 index 0000000000..e4e2245790 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/search/Search1DetailFragment.java @@ -0,0 +1,78 @@ +package com.gh.gamecenter.search; + +import android.app.Fragment; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +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.view.VerticalItemDecoration; +import com.gh.gamecenter.R; +import com.gh.gamecenter.entity.DismissEntity; +import com.gh.gamecenter.eventbus.EBPWDismiss; + +import de.greenrobot.event.EventBus; + +public class Search1DetailFragment extends Fragment { + + private RecyclerView bodyView; + private Search1DetailFragmentAdapter adapter; + private String keys; + + private DismissEntity dismissEntity; + + public void SetKeys(String key) { + this.keys = key; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savadInstanceState) { + + View search1Layout = inflater.inflate(R.layout.search1_fragment, + container, false); + bodyView = (RecyclerView) search1Layout + .findViewById(R.id.search_detail); + bodyView.setHasFixedSize(true); + LinearLayoutManager llm = new LinearLayoutManager(getActivity()); + llm.setOrientation(LinearLayoutManager.VERTICAL); + + dismissEntity = new DismissEntity(false); + + bodyView.setLayoutManager(llm); + adapter = new Search1DetailFragmentAdapter(getActivity(), + search1Layout, keys, dismissEntity); + bodyView.setAdapter(adapter); + bodyView.addItemDecoration(new VerticalItemDecoration(getActivity(), 1)); + + EventBus.getDefault().register(this); + + return search1Layout; + } + + public void onEvent(EBPWDismiss dismiss) { + if (dismissEntity != null) { + dismissEntity.setShow(false); + } + } + + public void clearSearchResult() { + adapter.clearSearchResult(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + AppController.canclePendingRequests( + Search1DetailFragment.class); + bodyView = null; + adapter = null; + keys = null; + dismissEntity = null; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/search/Search1DetailFragmentAdapter.java b/app/src/main/java/com/gh/gamecenter/search/Search1DetailFragmentAdapter.java new file mode 100644 index 0000000000..bb20e0d25d --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/search/Search1DetailFragmentAdapter.java @@ -0,0 +1,220 @@ +package com.gh.gamecenter.search; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.json.JSONArray; + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; + +import com.android.volley.NoConnectionError; +import com.android.volley.Response; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.common.util.GameViewUtils; +import com.gh.common.util.ImageUtils; +import com.gh.common.util.TimestampUtils; +import com.gh.common.view.DownloadDialog; +import com.gh.gamecenter.GameDetailsActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.SearchActivity; +import com.gh.gamecenter.adapter.viewholder.GameViewHolder; +import com.gh.gamecenter.entity.DismissEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.volley.extended.JsonArrayExtendedRequest; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.tendcloud.tenddata.TCAgent; + +public class Search1DetailFragmentAdapter extends + RecyclerView.Adapter { + + private Context context; + + private View view; + + private List gameList = null; + + private DismissEntity dismissEntity; + + public Search1DetailFragmentAdapter(Context context, View view, + String keys, DismissEntity dEntity) { + + this.context = context; + this.view = view; + this.dismissEntity = dEntity; + showView(R.id.search_gamedetails_ll_loading); + + JsonArrayExtendedRequest request = new JsonArrayExtendedRequest( + TimestampUtils.addTimestamp(Config.HOST + + "v1d45/search/game?keyword=" + Uri.encode(keys), + Constants.SEARCH_CD), + new Response.Listener() { + + @Override + public void onResponse(JSONArray response) { + + SearchActivity.readyToSearch = true; + + Type listType = new TypeToken>() { + }.getType(); + Gson gson = new Gson(); + gameList = gson.fromJson(response.toString(), listType); + if (gameList != null && gameList.size() > 0) { + showView(R.id.search_detail); + notifyDataSetChanged(); + } else { + showView(R.id.search_gamedetails_tv_nogame); + } + + } + + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + + SearchActivity.readyToSearch = true; + if (error.getClass() + .isInstance(new NoConnectionError())) { + showView(R.id.search_gamedetails_ll_connection); + } else { + showView(R.id.search_gamedetails_tv_nogame); + } + } + + }); + AppController.addToRequestQueue(request, Search2GameListAdapter.class); + } + + private void showView(int id) { + view.findViewById(R.id.search_detail).setVisibility(View.GONE); + view.findViewById(R.id.search_gamedetails_ll_loading).setVisibility( + View.GONE); + view.findViewById(R.id.search_gamedetails_ll_connection).setVisibility( + View.GONE); + view.findViewById(R.id.search_gamedetails_tv_nogame).setVisibility( + View.GONE); + + view.findViewById(id).setVisibility(View.VISIBLE); + } + + public void clearSearchResult() { + if (gameList != null) { + gameList.clear(); + } + notifyDataSetChanged(); + } + + @Override + public int getItemCount() { + if (gameList == null) { + return 0; + } + return gameList.size(); + + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, + int viewType) { + View itemView = LayoutInflater.from(viewGroup.getContext()).inflate( + R.layout.home_list_item_gamenormal_type, viewGroup, false); + + return new GameViewHolder(itemView); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, + final int position) { + + if (gameList != null) { + GameViewHolder holder = (GameViewHolder) viewHolder; + holder.gameSeq.setText((position + 1) + ""); + + final GameEntity gameEntity = gameList.get(position); + + ImageUtils.getInstance(context).display(gameEntity.getIcon(), + holder.gameThumb); + if (gameEntity.getApk() == null || gameEntity.getApk().isEmpty()) { + holder.gameNameAndSize.setText(gameEntity.getName()); + } else { + holder.gameNameAndSize.setText(gameEntity.getName() + " | " + + gameEntity.getApk().get(0).getSize()); + } + holder.gameDes.setText(gameEntity.getBrief()); + + GameViewUtils.setLabelList(context, holder.labelList, + gameEntity.getTag()); + + holder.itemView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + + Map kv = new HashMap(); + kv.put("入口", "搜索"); + TCAgent.onEvent(context, "游戏详情", gameEntity.getName(), kv); + + Map map = new HashMap(); + map.put("location", "搜索"); + map.put("createOn", System.currentTimeMillis() / 1000); + map.put("game", gameEntity.getName()); + map.put("page", "搜索"); + DataCollectionManager.onEvent(context, "click-item", map); + + AppController.put("GameEntity", gameEntity); + Intent intent = new Intent(context, GameDetailsActivity.class); + intent.putExtra("entrance", "搜索"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + }); + + if (gameEntity.getApk() == null || gameEntity.getApk().isEmpty()) { + holder.downloadBtn.setVisibility(View.GONE); + } else { + holder.downloadBtn.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + InputMethodManager imm = (InputMethodManager) context + .getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(v.getWindowToken(), 0); + if (!dismissEntity.isShow()) { + dismissEntity.setShow(true); + DownloadDialog.getInstance(context) + .showPopupWindow(v, gameEntity, "搜索", "搜索:" + gameEntity.getName()); + } + } + }); + } + + if (Config.isShow) { + holder.downloadBtn.setVisibility(View.VISIBLE); + } else { + holder.downloadBtn.setVisibility(View.GONE); + } + } + } + + public GameEntity getGameByPosition(int position) { + if (gameList != null) { + return gameList.get(position); + } + return null; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/search/Search2GameListAdapter.java b/app/src/main/java/com/gh/gamecenter/search/Search2GameListAdapter.java new file mode 100644 index 0000000000..ab1f3a537f --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/search/Search2GameListAdapter.java @@ -0,0 +1,329 @@ +package com.gh.gamecenter.search; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.json.JSONArray; + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; +import android.widget.ImageView; +import android.widget.TextView; + +import com.android.volley.NoConnectionError; +import com.android.volley.Response; +import com.android.volley.VolleyError; +import com.gh.base.AppController; +import com.gh.common.constant.Config; +import com.gh.common.constant.Constants; +import com.gh.common.util.GameViewUtils; +import com.gh.common.util.ImageUtils; +import com.gh.common.util.TimestampUtils; +import com.gh.common.view.DownloadDialog; +import com.gh.gamecenter.GameDetailsActivity; +import com.gh.gamecenter.R; +import com.gh.gamecenter.SearchActivity; +import com.gh.gamecenter.adapter.viewholder.GameViewHolder; +import com.gh.gamecenter.entity.DismissEntity; +import com.gh.gamecenter.entity.GameEntity; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.gh.gamecenter.volley.extended.JsonArrayExtendedRequest; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.tendcloud.tenddata.TCAgent; + +public class Search2GameListAdapter extends + RecyclerView.Adapter { + + private Context context; + + private JsonArrayExtendedRequest request; + + private static List gameList = null; + + private final int LIST_ITEM = 0; + private final int DETAIL_ITEM = 1; + + private String key; + + private DismissEntity dismissEntity; + + public Search2GameListAdapter(Context context, String keys, + DismissEntity dEntity) { + this.context = context; + this.dismissEntity = dEntity; + searchGame(keys); + + key = keys; + } + + public void clearSearchResult() { + if (gameList != null) { + gameList.clear(); + } + notifyDataSetChanged(); + } + + public int getListSize() { + return gameList.size(); + } + + private void searchGame(String keys) { + + request = new JsonArrayExtendedRequest(TimestampUtils.addTimestamp( + Config.HOST + "v1d45/search/game?keyword=" + Uri.encode(keys), + Constants.SEARCH_CD), new Response.Listener() { + + @Override + public void onResponse(JSONArray response) { + + Type listType = new TypeToken>() { + }.getType(); + Gson gson = new Gson(); + gameList = gson.fromJson(response.toString(), listType); + if (gameList != null && gameList.size() > 0) { + notifyDataSetChanged(); + } + + } + + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + + // 无网络连接 + if (error.getClass().equals(NoConnectionError.class)) { + + } + } + + }); + AppController.addToRequestQueue(request, Search2GameListAdapter.class); + } + + @Override + public int getItemCount() { + if (gameList == null) { + return 0; + } else { + return gameList.size(); + } + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, + final int position) { + if (gameList != null) { + if (position == 0) { + + GameViewHolder holder = (GameViewHolder) viewHolder; + + holder.gameSeq.setText((position + 1) + ""); + + final GameEntity gameEntity = gameList.get(position); + + ImageUtils.getInstance(context).display(gameEntity.getIcon(), + holder.gameThumb); + if (gameEntity.getApk() == null + || gameEntity.getApk().isEmpty()) { + holder.gameNameAndSize.setText(gameEntity.getName()); + } else { + holder.gameNameAndSize.setText(gameEntity.getName() + + " | " + gameEntity.getApk().get(0).getSize()); + } + holder.gameDes.setText(gameEntity.getBrief()); + + GameViewUtils.setLabelList(context, holder.labelList, + gameEntity.getTag()); + + holder.itemView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + + TCAgent.onEvent(context, "搜索页面", key); + + Map map = new HashMap(); + map.put("key", key); + map.put("from", "搜索页面"); + map.put("createdOn", System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent(context, "search", map); + + Map kv = new HashMap(); + kv.put("入口", "搜索"); + TCAgent.onEvent(context, "游戏详情", gameEntity.getName(), + kv); + + Map map2 = new HashMap(); + map2.put("location", "搜索"); + map2.put("createOn", System.currentTimeMillis() / 1000); + map2.put("game", gameEntity.getName()); + map2.put("page", "搜索"); + DataCollectionManager.onEvent(context, "click-item", map2); + + AppController.put("GameEntity", gameEntity); + Intent intent = new Intent(context, + GameDetailsActivity.class); + intent.putExtra("entrance", "搜索"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + }); + + if (gameEntity.getApk() == null + || gameEntity.getApk().isEmpty()) { + holder.downloadBtn.setVisibility(View.GONE); + } else { + holder.downloadBtn + .setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + InputMethodManager imm = (InputMethodManager) context + .getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow( + v.getWindowToken(), 0); + if (!dismissEntity.isShow()) { + dismissEntity.setShow(true); + DownloadDialog + .getInstance(context) + .showPopupWindow( + v, + gameEntity, + "搜索", + "搜索:" + + gameEntity + .getName()); + } + } + }); + } + + if (Config.isShow) { + holder.downloadBtn.setVisibility(View.VISIBLE); + } else { + holder.downloadBtn.setVisibility(View.GONE); + } + } else { + GameListViewHolder holder = (GameListViewHolder) viewHolder; + + holder.initEntity(gameList.get(position)); + holder.tv_gameName.setText(gameList.get(position).getName()); + } + } + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, + int viewType) { + if (viewType == DETAIL_ITEM) { + + View itemView = LayoutInflater.from(viewGroup.getContext()) + .inflate(R.layout.home_list_item_gamenormal_type, + viewGroup, false); + + return new GameViewHolder(itemView); + + } else if (viewType == LIST_ITEM) { + + View itemView = LayoutInflater.from(viewGroup.getContext()) + .inflate(R.layout.search2_gamelist_fragment_item, + viewGroup, false); + + return new GameListViewHolder(itemView); + + } else { + // WRONG TYPE + return null; + } + + } + + @Override + public int getItemViewType(int position) { + if (position == 0) { + return DETAIL_ITEM; + } else { + return LIST_ITEM; + } + } + + public class GameListViewHolder extends RecyclerView.ViewHolder implements + OnClickListener { + + public TextView tv_gameName; + public ImageView iv_plus; + + private View rootItem; + private GameEntity game; + + public GameListViewHolder(View v) { + super(v); + + rootItem = v; + tv_gameName = (TextView) v.findViewById(R.id.search_gamelist_name); + iv_plus = (ImageView) v.findViewById(R.id.search_gamelist_ico); + + iv_plus.setOnClickListener(this); + rootItem.setOnClickListener(this); + } + + public void initEntity(GameEntity entity) { + this.game = entity; + } + + @Override + public void onClick(View v) { + if (v == rootItem) { + TCAgent.onEvent(context, "搜索页面", key); + + Map map = new HashMap(); + map.put("key", key); + map.put("from", "搜索页面"); + map.put("createdOn", System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent(context, "search", map); + + Map map2 = new HashMap(); + map2.put("location", "搜索"); + map2.put("createOn", System.currentTimeMillis() / 1000); + map2.put("game", game.getName()); + map2.put("page", "搜索"); + DataCollectionManager.onEvent(context, "click-item", map2); + + AppController.put("GameEntity", game); + Intent intent = new Intent(context, GameDetailsActivity.class); + intent.putExtra("entrance", "搜索"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + + return; + } + if (v.getId() == R.id.search_gamelist_ico) { + String str = game.getName(); + SearchActivity.searchInput.setText(str); + SearchActivity.searchInput.setFocusable(true); + SearchActivity.searchInput.requestFocus(); + SearchActivity.searchInput.setSelection(str.length()); + return; + } + } + + } + + public GameEntity getGameByPosition(int position) { + if (gameList != null) { + return gameList.get(position); + } + return null; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/search/Search2GameListFragment.java b/app/src/main/java/com/gh/gamecenter/search/Search2GameListFragment.java new file mode 100644 index 0000000000..b15ef77fc8 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/search/Search2GameListFragment.java @@ -0,0 +1,84 @@ +package com.gh.gamecenter.search; + +import android.app.Fragment; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +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.Utils; +import com.gh.gamecenter.R; +import com.gh.gamecenter.entity.DismissEntity; +import com.gh.gamecenter.eventbus.EBPWDismiss; + +import de.greenrobot.event.EventBus; + +public class Search2GameListFragment extends Fragment { + + private RecyclerView bodyView; + private Search2GameListAdapter adapter; + + private String keys; + + private DismissEntity dismissEntity; + + public int getListSize() { + return adapter.getListSize(); + } + + public void SetKeys(String keys) { + this.keys = keys; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savadInstanceState) { + + View search2_gamelist_Layout = inflater.inflate( + R.layout.search2_gamelist_fragment, container, false); + bodyView = (RecyclerView) search2_gamelist_Layout + .findViewById(R.id.search_gamelist); + bodyView.setHasFixedSize(true); + LinearLayoutManager llm = new LinearLayoutManager(getActivity()); + llm.setOrientation(LinearLayoutManager.VERTICAL); + + dismissEntity = new DismissEntity(false); + + bodyView.setLayoutManager(llm); + adapter = new Search2GameListAdapter(getActivity(), keys, dismissEntity); + bodyView.setAdapter(adapter); + + EventBus.getDefault().register(this); + + return search2_gamelist_Layout; + } + + public void onEvent(EBPWDismiss dismiss) { + if (dismissEntity != null) { + dismissEntity.setShow(false); + } + } + + public void clearSearchResult() { + if (adapter == null) { + Utils.log("adapter is null"); + } else { + adapter.clearSearchResult(); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + AppController.canclePendingRequests( + Search2GameListFragment.class); + bodyView = null; + adapter = null; + keys = null; + dismissEntity = null; + } +} diff --git a/app/src/main/java/com/gh/gamecenter/search/Search3HistoryAdapter.java b/app/src/main/java/com/gh/gamecenter/search/Search3HistoryAdapter.java new file mode 100644 index 0000000000..bb1a6aea55 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/search/Search3HistoryAdapter.java @@ -0,0 +1,212 @@ +package com.gh.gamecenter.search; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import android.app.Dialog; +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.RecyclerView.ViewHolder; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.View.OnLongClickListener; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.ImageView; +import android.widget.TextView; + +import com.gh.gamecenter.R; +import com.gh.gamecenter.SearchActivity; +import com.gh.gamecenter.db.SearchHistoryDao; +import com.gh.gamecenter.manager.DataCollectionManager; +import com.tendcloud.tenddata.TCAgent; + +public class Search3HistoryAdapter extends + RecyclerView.Adapter { + + private Context context; + + private final int LIST_ITEM = 0; + private final int DELETE_ITEM = 1; + + private SearchHistoryDao dao; + private List historyList = null; + + public Search3HistoryAdapter(Context context, SearchHistoryDao dao) { + + this.context = context; + this.dao = dao; + historyList = dao.getAll(); + notifyDataSetChanged(); + + } + + public void clearSearchResult() { + if (historyList != null) { + historyList.clear(); + } + notifyDataSetChanged(); + } + + @Override + public int getItemCount() { + if (historyList == null || historyList.size() == 0) { + return 0; + } + return historyList.size() + 1; + } + + @Override + public int getItemViewType(int position) { + if (position < historyList.size()) { + return LIST_ITEM; + } else { + return DELETE_ITEM; + } + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup viewGroup, + int viewType) { + if (viewType == LIST_ITEM) { + + View itemView = LayoutInflater.from(context).inflate( + R.layout.search3_history_fragment_item, viewGroup, false); + return new SearchHistoryViewHolder(itemView); + + } else if (viewType == DELETE_ITEM) { + + View itemView = LayoutInflater.from(context).inflate( + R.layout.search3_history_delete_item, viewGroup, false); + return new DeleteHistoryViewHolder(itemView, this); + + } else { + return null; + } + + } + + @Override + public void onBindViewHolder(ViewHolder viewHolder, final int position) { + if (historyList != null && position < historyList.size()) { + ((SearchHistoryViewHolder) viewHolder).tv_hisName + .setText(historyList.get(position)); + } + } + + private void showCancelDialog() { + + final Dialog dialog = new Dialog(context); + View view = View.inflate(context, + R.layout.search_history_delete_dialog, null); + + TextView cancel = (TextView) view + .findViewById(R.id.delete_dialog_cancel); + + cancel.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dialog.dismiss(); + } + }); + + view.findViewById(R.id.delete_dialog_confirm).setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View v) { + dao.deleteAll(); + clearSearchResult(); + dialog.dismiss(); + } + }); + dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + dialog.setContentView(view); + dialog.show(); + } + + public class SearchHistoryViewHolder extends ViewHolder + implements OnClickListener, OnLongClickListener { + + private TextView tv_hisName; + private ImageView iv_hisAdd; + + private View itemView; + + public SearchHistoryViewHolder(View view) { + super(view); + itemView = view; + + tv_hisName = (TextView) view.findViewById(R.id.search_history_name); + iv_hisAdd = (ImageView) view.findViewById(R.id.search_history_add); + + itemView.setOnClickListener(this); + itemView.setOnLongClickListener(this); + iv_hisAdd.setOnClickListener(this); + } + + @Override + public boolean onLongClick(View v) { + if (v == itemView) { + // TODO: alert a dialog and delete just one + } + return false; + } + + @Override + public void onClick(View v) { + if (v == itemView) { + String str = tv_hisName.getText().toString(); + + TCAgent.onEvent(context, "搜索页面", str); + + Map map = new HashMap(); + map.put("key", str); + map.put("from", "搜索页面"); + map.put("createdOn", System.currentTimeMillis() / 1000); + DataCollectionManager.onEvent(context, "search", map); + + SearchActivity.searchInput.setText(str); + SearchActivity.searchInput.setFocusable(true); + SearchActivity.searchInput.requestFocus(); + SearchActivity.searchInput.setSelection(str.length()); + SearchActivity.searchButton.performClick(); + dao.add(tv_hisName.getText().toString()); + return; + } + if (v.getId() == R.id.search_history_add) { + String str = tv_hisName.getText().toString(); + SearchActivity.searchInput.setText(str); + SearchActivity.searchInput.setFocusable(true); + SearchActivity.searchInput.requestFocus(); + SearchActivity.searchInput.setSelection(str.length()); + return; + } + } + + } + + public static class DeleteHistoryViewHolder extends ViewHolder + implements OnClickListener { + + private View itemView; + private Search3HistoryAdapter adapter; + + public DeleteHistoryViewHolder(View view, Search3HistoryAdapter adapter) { + super(view); + itemView = view; + this.adapter = adapter; + itemView.setOnClickListener(this); + } + + @Override + public void onClick(View v) { + if (v == itemView) { + adapter.showCancelDialog(); + } + } + + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/search/Search3HistoryFragment.java b/app/src/main/java/com/gh/gamecenter/search/Search3HistoryFragment.java new file mode 100644 index 0000000000..5c9ae2d3ea --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/search/Search3HistoryFragment.java @@ -0,0 +1,62 @@ +package com.gh.gamecenter.search; + +import android.app.Fragment; +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +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.gamecenter.R; +import com.gh.gamecenter.db.SearchHistoryDao; + +public class Search3HistoryFragment extends Fragment { + + private RecyclerView bodyView; + private Search3HistoryAdapter adapter; + private SearchHistoryDao dao; + + public Search3HistoryFragment() { + + } + + public Search3HistoryFragment(SearchHistoryDao dao) { + this.dao = dao; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savadInstanceState) { + + View search1Layout = inflater.inflate( + R.layout.search3_history_fragment, container, false); + bodyView = (RecyclerView) search1Layout + .findViewById(R.id.search_history); + bodyView.setHasFixedSize(true); + LinearLayoutManager llm = new LinearLayoutManager(getActivity()); + llm.setOrientation(LinearLayoutManager.VERTICAL); + + bodyView.setLayoutManager(llm); + adapter = new Search3HistoryAdapter(getActivity(), dao); + bodyView.setAdapter(adapter); + + return search1Layout; + } + + public void clearSearchResult() { + adapter.clearSearchResult(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + AppController.canclePendingRequests( + Search3HistoryFragment.class); + bodyView = null; + adapter = null; + dao = null; + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/volley/extended/ExtendedRequest.java b/app/src/main/java/com/gh/gamecenter/volley/extended/ExtendedRequest.java new file mode 100644 index 0000000000..7c959fff43 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/volley/extended/ExtendedRequest.java @@ -0,0 +1,182 @@ +package com.gh.gamecenter.volley.extended; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.http.HttpStatus; + +import android.text.TextUtils; + +import com.android.volley.AuthFailureError; +import com.android.volley.DefaultRetryPolicy; +import com.android.volley.NetworkResponse; +import com.android.volley.Request; +import com.android.volley.Response; +import com.android.volley.toolbox.HttpHeaderParser; +import com.gh.common.util.GzipUtils; +import com.gh.common.util.Trace; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-7-31 + * @param + */ +public abstract class ExtendedRequest extends Request { + private static final String HEADER_ENCODING = "Content-Encoding"; + private static final String HEADER_USER_AGENT = "User-Agent"; + private static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding"; + private static final String ENCODING_GZIP = "gzip"; + private static final int TIMEOUT = 5 * 1000; + + protected Map mParams; + protected Map mHeaders; + + private String mUserAgent; + private boolean mGzipEnabled = true; + + protected final Response.Listener mSuccessListener; + + public ExtendedRequest(int method, String url, + Response.Listener successListener, + Response.ErrorListener errorListener) { + super(method, url, errorListener); + setTimeout(TIMEOUT); + mSuccessListener = successListener; + } + + @Override + protected void deliverResponse(T response) { + if (mSuccessListener != null) { + mSuccessListener.onResponse(response); + } + } + + @Override + abstract protected Response parseNetworkResponse(NetworkResponse response); + + protected String getResponseString(NetworkResponse response) + throws UnsupportedEncodingException { + String responseString = null; + String charset = HttpHeaderParser.parseCharset(response.headers); + + if (HttpStatus.SC_NOT_MODIFIED == response.statusCode + || (mGzipEnabled && isGzipped(response.headers)) + || HttpStatus.SC_OK == response.statusCode) { + try { + byte[] data = GzipUtils.decompressBytes(response.data); + responseString = new String(data, charset); + } catch (IOException e) { + + e.printStackTrace(); + } + } + + if (responseString == null) { + responseString = new String(response.data, charset); + } + + return responseString; + } + + private boolean isGzipped(Map headers) { + return headers != null && !headers.isEmpty() + && headers.containsKey(HEADER_ENCODING) + && headers.get(HEADER_ENCODING).equalsIgnoreCase(ENCODING_GZIP); + } + + /** + * Sets parameters map + * + * @param params + * Parameters map + */ + public void setParams(Map params) { + mParams = params; + } + + /** + * Adds POST parameter + * + * @param key + * Parameter name + * @param value + * Parameter value + */ + public void addParam(String key, String value) { + if (mParams == null) { + mParams = new HashMap(); + } + mParams.put(key, value); + } + + public void addHeader(String key, String value) { + if (mHeaders == null) { + mHeaders = new HashMap(); + } + mHeaders.put(key, value); + } + + @Override + protected Map getParams() throws AuthFailureError { + return mParams; + } + + @Override + public Map getHeaders() throws AuthFailureError { + if (mHeaders == null) { + mHeaders = new HashMap(); + } + + // add user agent header + if (TextUtils.isEmpty(mUserAgent)) { + mHeaders.put(HEADER_USER_AGENT, mUserAgent); + } + + // add gzip header + if (mGzipEnabled) { + mHeaders.put(HEADER_ACCEPT_ENCODING, ENCODING_GZIP); + Trace.getInstance().debug(ExtendedRequest.class.getSimpleName(), + "using gzip-------------------"); + } else { + Trace.getInstance().debug(ExtendedRequest.class.getSimpleName(), + "not use gzip-------------------"); + } + + return mHeaders; + } + + /** + * Sets user agent to specify in request header + * + * @param userAgent + * User agent string + */ + public void setUserAgent(String userAgent) { + mUserAgent = userAgent; + } + + /** Disables GZIP compressing (enabled by default) */ + public void disableGzip() { + mGzipEnabled = false; + } + + public boolean isSetGzip() { + return mGzipEnabled; + } + + /** + * Sets request timeout + * + * @param timeoutSec + * Timeout in seconds + */ + public void setTimeout(int timeout) { + setRetryPolicy(new DefaultRetryPolicy(timeout, + DefaultRetryPolicy.DEFAULT_MAX_RETRIES, + DefaultRetryPolicy.DEFAULT_BACKOFF_MULT)); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/volley/extended/JsonArrayExtendedRequest.java b/app/src/main/java/com/gh/gamecenter/volley/extended/JsonArrayExtendedRequest.java new file mode 100644 index 0000000000..8ca80c43b3 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/volley/extended/JsonArrayExtendedRequest.java @@ -0,0 +1,54 @@ +package com.gh.gamecenter.volley.extended; + +import java.io.UnsupportedEncodingException; + +import org.json.JSONArray; +import org.json.JSONException; + +import com.android.volley.NetworkResponse; +import com.android.volley.ParseError; +import com.android.volley.Response; +import com.android.volley.Response.ErrorListener; +import com.android.volley.Response.Listener; +import com.android.volley.toolbox.HttpHeaderParser; +import com.gh.common.util.Utils; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-7-31 + */ +public class JsonArrayExtendedRequest extends JsonExtendedRequest { + + private String url; + + public JsonArrayExtendedRequest(String url, + Response.Listener listener, ErrorListener errorListener) { + super(Method.GET, url, null, listener, errorListener); + this.url = url; + } + + public JsonArrayExtendedRequest(int method, String url, + JSONArray jsonRequest, Listener listener, + ErrorListener errorListener) { + super(method, url, (jsonRequest == null) ? null : jsonRequest + .toString(), listener, errorListener); + this.url = url; + } + + @Override + protected Response parseNetworkResponse(NetworkResponse response) { + Utils.log(url + " = " + response.statusCode); + try { + String jsonString = getResponseString(response); + return Response.success(new JSONArray(jsonString), + HttpHeaderParser.parseCacheHeaders(response)); + } catch (UnsupportedEncodingException e) { + return Response.error(new ParseError(e)); + } catch (JSONException je) { + return Response.error(new ParseError(je)); + } + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/volley/extended/JsonExtendedRequest.java b/app/src/main/java/com/gh/gamecenter/volley/extended/JsonExtendedRequest.java new file mode 100644 index 0000000000..4d9c637c62 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/volley/extended/JsonExtendedRequest.java @@ -0,0 +1,63 @@ +package com.gh.gamecenter.volley.extended; + +import java.io.UnsupportedEncodingException; + +import com.android.volley.NetworkResponse; +import com.android.volley.Response; +import com.android.volley.Response.ErrorListener; +import com.android.volley.Response.Listener; +import com.android.volley.VolleyLog; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-7-31 + * @param + */ +public abstract class JsonExtendedRequest extends ExtendedRequest { + + /** Default charset for JSON request. */ + protected static final String PROTOCOL_CHARSET = "utf-8"; + + /** Content type for request. */ + private static final String PROTOCOL_CONTENT_TYPE = String.format( + "application/json; charset=%s", PROTOCOL_CHARSET); + + private final Listener mListener; + private final String mRequestBody; + + public JsonExtendedRequest(int method, String url, String requestBody, + Response.Listener listener, ErrorListener errorListener) { + super(method, url, listener, errorListener); + mListener = listener; + mRequestBody = requestBody; + } + + @Override + protected void deliverResponse(T response) { + mListener.onResponse(response); + } + + @Override + abstract protected Response parseNetworkResponse(NetworkResponse response); + + @Override + public String getBodyContentType() { + return PROTOCOL_CONTENT_TYPE; + } + + @Override + public byte[] getBody() { + try { + return mRequestBody == null ? null : mRequestBody + .getBytes(PROTOCOL_CHARSET); + } catch (UnsupportedEncodingException uee) { + VolleyLog + .wtf("Unsupported Encoding while trying to get the bytes of %s using %s", + mRequestBody, PROTOCOL_CHARSET); + return null; + } + } + +} diff --git a/app/src/main/java/com/gh/gamecenter/volley/extended/JsonObjectExtendedRequest.java b/app/src/main/java/com/gh/gamecenter/volley/extended/JsonObjectExtendedRequest.java new file mode 100644 index 0000000000..21386f23a3 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/volley/extended/JsonObjectExtendedRequest.java @@ -0,0 +1,57 @@ +package com.gh.gamecenter.volley.extended; + +import java.io.UnsupportedEncodingException; + +import org.json.JSONException; +import org.json.JSONObject; + +import com.android.volley.NetworkResponse; +import com.android.volley.ParseError; +import com.android.volley.Response; +import com.android.volley.Response.ErrorListener; +import com.android.volley.toolbox.HttpHeaderParser; +import com.gh.common.util.Utils; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-7-31 + */ +public class JsonObjectExtendedRequest extends JsonExtendedRequest { + + private String url; + + public JsonObjectExtendedRequest(String url, + Response.Listener listener, ErrorListener errorListener) { + super(Method.GET, url, null, listener, errorListener); + this.url = url; + } + + public JsonObjectExtendedRequest(int method, String url, + Response.Listener listener, ErrorListener errorListener) { + super(method, url, null, listener, errorListener); + this.url = url; + } + + public JsonObjectExtendedRequest(int method, String url, + String requestBody, Response.Listener listener, + ErrorListener errorListener) { + super(method, url, requestBody, listener, errorListener); + this.url = url; + } + + @Override + protected Response parseNetworkResponse(NetworkResponse response) { + Utils.log(url + " = " + response.statusCode); + try { + String jsonString = getResponseString(response); + return Response.success(new JSONObject(jsonString), + HttpHeaderParser.parseCacheHeaders(response)); + } catch (UnsupportedEncodingException e) { + return Response.error(new ParseError(e)); + } catch (JSONException je) { + return Response.error(new ParseError(je)); + } + } +} diff --git a/app/src/main/java/com/gh/gamecenter/volley/extended/StringExtendedRequest.java b/app/src/main/java/com/gh/gamecenter/volley/extended/StringExtendedRequest.java new file mode 100644 index 0000000000..65443c3a41 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/volley/extended/StringExtendedRequest.java @@ -0,0 +1,40 @@ +package com.gh.gamecenter.volley.extended; + +import java.io.UnsupportedEncodingException; + +import com.android.volley.NetworkResponse; +import com.android.volley.Response; +import com.android.volley.toolbox.HttpHeaderParser; +import com.gh.common.util.Utils; + +/** + * + * @author 温冠超 + * @email 294299195@qq.com + * @date 2015-7-31 + */ +public class StringExtendedRequest extends ExtendedRequest { + + private String url; + + public StringExtendedRequest(int method, String url, + Response.Listener successListener, + Response.ErrorListener errorListener) { + super(method, url, successListener, errorListener); + this.url = url; + } + + @Override + protected Response parseNetworkResponse(NetworkResponse response) { + Utils.log(url + " = " + response.statusCode); + String parsed; + try { + parsed = getResponseString(response); + } catch (UnsupportedEncodingException e) { + parsed = new String(response.data); + } + return Response.success(parsed, + HttpHeaderParser.parseCacheHeaders(response)); + } + +} diff --git a/app/src/main/java/com/kyleduo/switchbutton/AnimationController.java b/app/src/main/java/com/kyleduo/switchbutton/AnimationController.java new file mode 100644 index 0000000000..0a7c0cc2af --- /dev/null +++ b/app/src/main/java/com/kyleduo/switchbutton/AnimationController.java @@ -0,0 +1,164 @@ +package com.kyleduo.switchbutton; + +import android.os.Handler; +import android.os.Message; + +/** + * controller of view animation + * + * @author kyleduo + * @since 2014-09-25 + * + */ +class AnimationController { + + private static int ANI_WHAT = 0x100; + private static int DEFAULT_VELOCITY = 7; + private static int DEFAULT_FRAME_DURATION = 1000 / 60; + + private AnimationHandler mHandler; + private OnAnimateListener mOnAnimateListener; + + private boolean isAnimating = false; + + private int mFrame, mFrom, mTo; + private int mVelocity = DEFAULT_VELOCITY; + + private AnimationController() { + mHandler = new AnimationHandler(); + } + + /** + * get default AnimationController + * @return + */ + static AnimationController getDefault() { + AnimationController ac = new AnimationController(); + return ac; + } + + /** + * initial an AnimationController with a listener + * @param onAnimateListener NOT NULL + * @return + */ + AnimationController init(OnAnimateListener onAnimateListener) { + if (onAnimateListener == null) { + throw new IllegalArgumentException("onAnimateListener can not be null"); + } + this.mOnAnimateListener = onAnimateListener; + return this; + } + + private static class AnimationHandler extends Handler { + @Override + public void handleMessage(Message msg) { + if (msg.what == ANI_WHAT) { + if (msg.obj != null) { + ((Runnable) msg.obj).run(); + } + } + } + } + + void startAnimation(int from, int to) { + this.isAnimating = true; + this.mFrom = from; + this.mTo = to; + this.mFrame = mVelocity; + if (mTo > mFrom) { + this.mFrame = Math.abs(this.mVelocity); + } else if (mTo < mFrom) { + this.mFrame = -Math.abs(this.mVelocity); + } else { + this.isAnimating = false; + this.mOnAnimateListener.onAnimateComplete(); + return; + } + this.mOnAnimateListener.onAnimationStart(); + new RequireNextFrame().run(); + } + + void stopAnimation() { + isAnimating = false; + } + + /** + * configure the velocity of animation + * @param velocity a positive number + */ + public void setVelocity(int velocity) { + if (velocity <= 0) { + mVelocity = DEFAULT_VELOCITY; + return; + } + mVelocity = velocity; + } + + /** + * calculate next frame in child thread + * + * @author kyleduo + * + */ + class RequireNextFrame implements Runnable { + @Override + public void run() { + if (!isAnimating) { + return; + } + calcNextFrame(); + mOnAnimateListener.onFrameUpdate(mFrame); + if (mOnAnimateListener.continueAnimating()) { + requireNextFrame(); + } else { + stopAnimation(); + mOnAnimateListener.onAnimateComplete(); + return; + } + } + + private void calcNextFrame() { +// mFrame = mVelocity; + } + + private void requireNextFrame() { + Message msg = mHandler.obtainMessage(); + msg.what = ANI_WHAT; + msg.obj = this; + mHandler.sendMessageDelayed(msg, DEFAULT_FRAME_DURATION); + } + } + + /** + * interface for view animation + * + * @author kyle + * + */ + interface OnAnimateListener { + /** + * invoked when the animation start + */ + public void onAnimationStart(); + + /** + * ask view whether continue Animating + * + * @return boolean true for continueAnimating + */ + public boolean continueAnimating(); + + /** + * a new frame is ready. + * + * @param frame next step of the animation, for linear animation, it is equal to velocity + */ + public void onFrameUpdate(int frame); + + /** + * invoked when the animation complete + */ + public void onAnimateComplete(); + } +} diff --git a/app/src/main/java/com/kyleduo/switchbutton/Configuration.java b/app/src/main/java/com/kyleduo/switchbutton/Configuration.java new file mode 100644 index 0000000000..86414613f9 --- /dev/null +++ b/app/src/main/java/com/kyleduo/switchbutton/Configuration.java @@ -0,0 +1,407 @@ +package com.kyleduo.switchbutton; + +import java.lang.reflect.Field; + +import android.graphics.Color; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.graphics.drawable.StateListDrawable; +import android.view.View; + +/** + * class for configuring the Switchbutton + * used when you want to change the face of this view in code + * + * @author kyleduo + * @since 2014-09-24 + */ +public class Configuration implements Cloneable { + + static class Default { + static int DEFAULT_OFF_COLOR = Color.parseColor("#E3E3E3"); + static int DEFAULT_ON_COLOR = Color.parseColor("#02BFE7"); + static int DEFAULT_THUMB_COLOR = Color.parseColor("#FFFFFF"); + static int DEFAULT_THUMB_PRESSED_COLOR = Color.parseColor("#fafafa"); + static int DEFAULT_THUMB_MARGIN = 2; + static int DEFAULT_RADIUS = 999; + static float DEFAULT_MEASURE_FACTOR = 2f; + static int DEFAULT_INNER_BOUNDS = 0; + } + + static class Limit { + static int MIN_THUMB_SIZE = 24; + } + + /** + * drawable of background + */ + private Drawable mOnDrawable = null, mOffDrawable = null; + /** + * drawable of thumb + */ + private Drawable mThumbDrawable = null; + + private int mOnColor = Default.DEFAULT_ON_COLOR, mOffColor = Default.DEFAULT_OFF_COLOR, mThumbColor = Default.DEFAULT_THUMB_COLOR, mThumbPressedColor = Default.DEFAULT_THUMB_PRESSED_COLOR; + + /** + * space between View's border and thumb + */ + private int mThumbMarginTop = 0, mThumbMarginBottom = 0, mThumbMarginLeft = 0, mThumbMarginRight = 0; + + private int mThumbWidth = -1, mThumbHeight = -1; + + private float density; + + private int mVelocity = -1; + + private float mRadius = -1; + + /** + * factor limit the minimum width equals almost (the height of thumb * measureFactor) + */ + private float mMeasureFactor = 0; + + /** + * inner bounds + */ + private Rect mInsetBounds; + + private Configuration() { + }; + + public static Configuration getDefault(float density) { + Configuration defaultConfiguration = new Configuration(); + defaultConfiguration.density = density; + defaultConfiguration.setThumbMarginInPixel(defaultConfiguration.getDefaultThumbMarginInPixel()); + + defaultConfiguration.mInsetBounds = new Rect(Default.DEFAULT_INNER_BOUNDS, Default.DEFAULT_INNER_BOUNDS, Default.DEFAULT_INNER_BOUNDS, Default.DEFAULT_INNER_BOUNDS); + + return defaultConfiguration; + } + + public void setBackDrawable(Drawable offDrawable, Drawable onDrawable) { + if (onDrawable == null && offDrawable == null) { + throw new IllegalArgumentException("back drawable can not be null"); + } + + if (offDrawable != null) { + mOffDrawable = offDrawable; + + if (onDrawable != null) { + mOnDrawable = onDrawable; + } else { + mOnDrawable = mOffDrawable; + } + } + } + + void setOffDrawable(Drawable offDrawable) { + if (offDrawable == null) { + throw new IllegalArgumentException("off drawable can not be null"); + } + + mOffDrawable = offDrawable; + } + + void setOnDrawable(Drawable onDrawable) { + if (onDrawable == null) { + throw new IllegalArgumentException("on drawable can not be null"); + } + + mOnDrawable = onDrawable; + } + + public Drawable getOnDrawable() { + return mOnDrawable; + } + + public Drawable getOffDrawable() { + return mOffDrawable; + } + + public void setThumbDrawable(Drawable thumbDrawable) { + if (thumbDrawable == null) { + throw new IllegalArgumentException("thumb drawable can not be null"); + } + mThumbDrawable = thumbDrawable; + } + + public Drawable getThumbDrawable() { + return mThumbDrawable; + } + + public void setThumbMargin(int top, int bottom, int left, int right) { + mThumbMarginTop = (int) (top * density); + mThumbMarginBottom = (int) (bottom * density); + mThumbMarginLeft = (int) (left * density); + mThumbMarginRight = (int) (right * density); + } + + public void setThumbMarginInPixel(int top, int bottom, int left, int right) { + mThumbMarginTop = top; + mThumbMarginBottom = bottom; + mThumbMarginLeft = left; + mThumbMarginRight = right; + } + + public void setThumbMargin(int top, int bottom, int leftAndRight) { + setThumbMargin(top, bottom, leftAndRight, leftAndRight); + } + + public void setThumbMargin(int topAndBottom, int leftAndRight) { + setThumbMargin(topAndBottom, topAndBottom, leftAndRight, leftAndRight); + } + + public void setThumbMargin(int margin) { + setThumbMargin(margin, margin, margin, margin); + } + + public void setThumbMarginInPixel(int marginInPixel) { + setThumbMarginInPixel(marginInPixel, marginInPixel, marginInPixel, marginInPixel); + } + + public int getDefaultThumbMarginInPixel() { + return (int) (Default.DEFAULT_THUMB_MARGIN * density); + } + + public int getThumbMarginTop() { + return mThumbMarginTop; + } + + public int getThumbMarginBottom() { + return mThumbMarginBottom; + } + + public int getThumbMarginLeft() { + return mThumbMarginLeft; + } + + public int getThumbMarginRight() { + return mThumbMarginRight; + } + + public float getDensity() { + return density; + } + + public void setRadius(float radius) { + this.mRadius = radius; + } + + public float getRadius() { + if (this.mRadius < 0) { + return Default.DEFAULT_RADIUS; + } + return this.mRadius; + } + + /** + * set velocity of animation + * @param velocity pixel moved per frame (in linear) + */ + public void setVelocity(int velocity) { + this.mVelocity = velocity; + } + + public int getVelocity() { + return mVelocity; + } + + public void setOnColor(int onColor) { + this.mOnColor = onColor; + } + + public int getOnColor(int onColor) { + return mOnColor; + } + + public void setOffColor(int offColor) { + this.mOffColor = offColor; + } + + public int getOffColor() { + return mOffColor; + } + + public void setThumbColor(int thumbColor) { + this.mThumbColor = thumbColor; + } + + public int getThumbColor() { + return mThumbColor; + } + + public void setThumbWidthAndHeightInPixel(int width, int height) { + if (width > 0) { + mThumbWidth = width; + } + + if (height > 0) { + mThumbHeight = height; + } + } + + public void setThumbWidthAndHeight(int width, int height) { + setThumbWidthAndHeightInPixel((int) (width * density), (int) (height * density)); + } + + public Drawable getOffDrawableWithFix() { + if (mOffDrawable != null) { + return mOffDrawable; + } else { + return getDrawableFromColor(mOffColor); + } + } + + public Drawable getOnDrawableWithFix() { + if (mOnDrawable != null) { + return mOnDrawable; + } else { + return getDrawableFromColor(mOnColor); + } + } + + public Drawable getThumbDrawableWithFix() { + if (mThumbDrawable != null) { + return mThumbDrawable; + } else { + StateListDrawable drawable = new StateListDrawable(); + Drawable normalDrawable = getDrawableFromColor(this.mThumbColor); + Drawable pressedDrawable = getDrawableFromColor(this.mThumbPressedColor); + int[] stateSet = null; + try { + Field stateField = View.class.getDeclaredField("PRESSED_ENABLED_STATE_SET"); + stateField.setAccessible(true); + stateSet = (int[]) stateField.get(null); + } catch (Exception e) { + e.printStackTrace(); + } + if (stateSet != null) { + drawable.addState(stateSet, pressedDrawable); + } + drawable.addState(new int[] {}, normalDrawable); + return drawable; + } + } + + public float getMeasureFactor() { + if (mMeasureFactor <= 0) { + mMeasureFactor = Default.DEFAULT_MEASURE_FACTOR; + } + return mMeasureFactor; + } + + public void setMeasureFactor(float measureFactor) { + if (measureFactor <= 0) { + this.mMeasureFactor = Default.DEFAULT_MEASURE_FACTOR; + } + this.mMeasureFactor = measureFactor; + } + + public Rect getInsetBounds() { + return this.mInsetBounds; + } + + public void setInsetBounds(int left, int top, int right, int bottom) { + setInsetLeft(left); + setInsetTop(top); + setInsetRight(right); + setInsetBottom(bottom); + } + + public void setInsetLeft(int left) { + if (left > 0) { + left = -left; + } + this.mInsetBounds.left = left; + } + + public void setInsetTop(int top) { + if (top > 0) { + top = -top; + } + this.mInsetBounds.top = top; + } + + public void setInsetRight(int right) { + if (right > 0) { + right = -right; + } + this.mInsetBounds.right = right; + } + + public void setInsetBottom(int bottom) { + if (bottom > 0) { + bottom = -bottom; + } + this.mInsetBounds.bottom = bottom; + } + + public int getInsetX() { + return getShrinkX() / 2; + } + + public int getInsetY() { + return getShrinkY() / 2; + } + + public int getShrinkX() { + return this.mInsetBounds.left + this.mInsetBounds.right; + } + + public int getShrinkY() { + return this.mInsetBounds.top + this.mInsetBounds.bottom; + } + + public boolean needShrink() { + return this.mInsetBounds.left + this.mInsetBounds.right + this.mInsetBounds.top + this.mInsetBounds.bottom != 0; + } + + /** + * use for get drawable from color + * + * @param color + * @return + */ + private Drawable getDrawableFromColor(int color) { + GradientDrawable tempDrawable = new GradientDrawable(); + tempDrawable.setCornerRadius(this.getRadius()); + tempDrawable.setColor(color); + return tempDrawable; + } + + int getThumbWidth() { + int width = mThumbWidth; + if (width < 0) { + if (mThumbDrawable != null) { + width = mThumbDrawable.getIntrinsicWidth(); + if (width > 0) { + return width; + } + } + if (density <= 0) { + throw new IllegalArgumentException("density must be a positive number"); + } + width = (int) (Limit.MIN_THUMB_SIZE * density); + } + return width; + } + + int getThumbHeight() { + int height = mThumbHeight; + if (height < 0) { + if (mThumbDrawable != null) { + height = mThumbDrawable.getIntrinsicHeight(); + if (height > 0) { + return height; + } + } + if (density <= 0) { + throw new IllegalArgumentException("density must be a positive number"); + } + height = (int) (Limit.MIN_THUMB_SIZE * density); + } + return height; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kyleduo/switchbutton/SwitchButton.java b/app/src/main/java/com/kyleduo/switchbutton/SwitchButton.java new file mode 100644 index 0000000000..411efe9370 --- /dev/null +++ b/app/src/main/java/com/kyleduo/switchbutton/SwitchButton.java @@ -0,0 +1,695 @@ +package com.kyleduo.switchbutton; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Paint.Style; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Region; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.graphics.drawable.StateListDrawable; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.widget.CompoundButton; + +import com.gh.gamecenter.R; + +/** + * SwitchButton widget which is easy to use + * + * @version 1.2 + * @author kyleduo + * @since 2014-09-24 + */ + +public class SwitchButton extends CompoundButton { + private static boolean SHOW_RECT = false; + + private boolean mIsChecked = false; + + private Configuration mConf; + + /** + * zone for thumb to move inside + */ + private Rect mSafeZone; + /** + * zone for background + */ + private Rect mBackZone; + private Rect mThumbZone; + private RectF mSaveLayerZone; + + private AnimationController mAnimationController; + private SBAnimationListener mOnAnimateListener = new SBAnimationListener(); + private boolean isAnimating = false; + + private float mStartX, mStartY, mLastX; + private float mCenterPos; + + private int mTouchSlop; + private int mClickTimeout; + + private Paint mRectPaint; + + private Rect mBounds = null; + + private OnCheckedChangeListener mOnCheckedChangeListener; + + @SuppressLint("NewApi") + public SwitchButton(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initView(); + + TypedArray ta = context.obtainStyledAttributes(attrs, + R.styleable.SwitchButton); + + mConf.setThumbMarginInPixel(ta.getDimensionPixelSize( + R.styleable.SwitchButton_thumb_margin, + mConf.getDefaultThumbMarginInPixel())); + mConf.setThumbMarginInPixel(ta.getDimensionPixelSize( + R.styleable.SwitchButton_thumb_marginTop, + mConf.getThumbMarginTop()), ta.getDimensionPixelSize( + R.styleable.SwitchButton_thumb_marginBottom, + mConf.getThumbMarginBottom()), ta.getDimensionPixelSize( + R.styleable.SwitchButton_thumb_marginLeft, + mConf.getThumbMarginLeft()), ta.getDimensionPixelSize( + R.styleable.SwitchButton_thumb_marginRight, + mConf.getThumbMarginRight())); + mConf.setRadius(ta.getInt(R.styleable.SwitchButton_radius, + Configuration.Default.DEFAULT_RADIUS)); + + mConf.setThumbWidthAndHeightInPixel(ta.getDimensionPixelSize( + R.styleable.SwitchButton_thumb_width, -1), ta + .getDimensionPixelSize(R.styleable.SwitchButton_thumb_height, + -1)); + + mConf.setMeasureFactor(ta.getFloat( + R.styleable.SwitchButton_measureFactor, -1)); + + mConf.setInsetBounds( + ta.getDimensionPixelSize(R.styleable.SwitchButton_insetLeft, 0), + ta.getDimensionPixelSize(R.styleable.SwitchButton_insetTop, 0), + ta.getDimensionPixelSize(R.styleable.SwitchButton_insetRight, 0), + ta.getDimensionPixelSize(R.styleable.SwitchButton_insetBottom, + 0)); + + int velocity = ta.getInteger( + R.styleable.SwitchButton_animationVelocity, -1); + mAnimationController.setVelocity(velocity); + + fetchDrawableFromAttr(ta); + ta.recycle(); + + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { + this.setLayerType(View.LAYER_TYPE_SOFTWARE, null); + } + } + + public SwitchButton(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SwitchButton(Context context) { + this(context, null); + } + + private void initView() { + mConf = Configuration.getDefault(getContext().getResources() + .getDisplayMetrics().density); + mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); + mClickTimeout = ViewConfiguration.getPressedStateDuration() + + ViewConfiguration.getTapTimeout(); + mAnimationController = AnimationController.getDefault().init( + mOnAnimateListener); + mBounds = new Rect(); + if (SHOW_RECT) { + mRectPaint = new Paint(); + mRectPaint.setStyle(Style.STROKE); + } + } + + /** + * fetch drawable resources from attrs, drop them to conf, AFTER the size + * has been confirmed + * + * @param ta + */ + private void fetchDrawableFromAttr(TypedArray ta) { + if (mConf == null) { + return; + } + mConf.setOffDrawable(fetchDrawable(ta, + R.styleable.SwitchButton_offDrawable, + R.styleable.SwitchButton_offColor, + Configuration.Default.DEFAULT_OFF_COLOR)); + mConf.setOnDrawable(fetchDrawable(ta, + R.styleable.SwitchButton_onDrawable, + R.styleable.SwitchButton_onColor, + Configuration.Default.DEFAULT_ON_COLOR)); + mConf.setThumbDrawable(fetchThumbDrawable(ta)); + } + + private Drawable fetchDrawable(TypedArray ta, int attrId, int alterColorId, + int defaultColor) { + Drawable tempDrawable = ta.getDrawable(attrId); + if (tempDrawable == null) { + int tempColor = ta.getColor(alterColorId, defaultColor); + tempDrawable = new GradientDrawable(); + ((GradientDrawable) tempDrawable).setCornerRadius(this.mConf + .getRadius()); + ((GradientDrawable) tempDrawable).setColor(tempColor); + } + return tempDrawable; + } + + private Drawable fetchThumbDrawable(TypedArray ta) { + + Drawable tempDrawable = ta + .getDrawable(R.styleable.SwitchButton_thumbDrawable); + if (tempDrawable != null) { + return tempDrawable; + } + + int normalColor = ta.getColor(R.styleable.SwitchButton_thumbColor, + Configuration.Default.DEFAULT_THUMB_COLOR); + int pressedColor = ta.getColor( + R.styleable.SwitchButton_thumbPressedColor, + Configuration.Default.DEFAULT_THUMB_PRESSED_COLOR); + + StateListDrawable drawable = new StateListDrawable(); + GradientDrawable normalDrawable = new GradientDrawable(); + normalDrawable.setCornerRadius(this.mConf.getRadius()); + normalDrawable.setColor(normalColor); + GradientDrawable pressedDrawable = new GradientDrawable(); + pressedDrawable.setCornerRadius(this.mConf.getRadius()); + pressedDrawable.setColor(pressedColor); + drawable.addState(View.PRESSED_ENABLED_STATE_SET, pressedDrawable); + drawable.addState(new int[] {}, normalDrawable); + + return drawable; + } + + public void setConfiguration(Configuration conf) { + if (mConf == null) { + mConf = Configuration.getDefault(conf.getDensity()); + } + mConf.setOffDrawable(conf.getOffDrawableWithFix()); + mConf.setOnDrawable(conf.getOnDrawableWithFix()); + mConf.setThumbDrawable(conf.getThumbDrawableWithFix()); + mConf.setThumbMarginInPixel(conf.getThumbMarginTop(), + conf.getThumbMarginBottom(), conf.getThumbMarginLeft(), + conf.getThumbMarginRight()); + mConf.setThumbWidthAndHeightInPixel(conf.getThumbWidth(), + conf.getThumbHeight()); + mConf.setVelocity(conf.getVelocity()); + mConf.setMeasureFactor(conf.getMeasureFactor()); + mAnimationController.setVelocity(mConf.getVelocity()); + this.requestLayout(); + setup(); + setChecked(mIsChecked); + } + + /** + * return a REFERENCE of configuration, it is suggested that not to change + * that + * + * @return + */ + public Configuration getConfiguration() { + return mConf; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension(measureWidth(widthMeasureSpec), + measureHeight(heightMeasureSpec)); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + setup(); + } + + private void setup() { + setupBackZone(); + setupSafeZone(); + setupThumbZone(); + + setupDrawableBounds(); + if (this.getMeasuredWidth() > 0 && this.getMeasuredHeight() > 0) { + mSaveLayerZone = new RectF(0, 0, this.getMeasuredWidth(), + this.getMeasuredHeight()); + } + + ViewGroup parent = (ViewGroup) this.getParent(); + if (parent != null) { + parent.setClipChildren(false); + } + } + + /** + * setup zone for thumb to move + */ + private void setupSafeZone() { + int w = getMeasuredWidth(); + int h = getMeasuredHeight(); + if (w > 0 && h > 0) { + if (mSafeZone == null) { + mSafeZone = new Rect(); + } + int left, right, top, bottom; + left = getPaddingLeft() + + (mConf.getThumbMarginLeft() > 0 ? mConf + .getThumbMarginLeft() : 0); + right = w + - getPaddingRight() + - (mConf.getThumbMarginRight() > 0 ? mConf + .getThumbMarginRight() : 0) + (-mConf.getShrinkX()); + top = getPaddingTop() + + (mConf.getThumbMarginTop() > 0 ? mConf + .getThumbMarginTop() : 0); + bottom = h + - getPaddingBottom() + - (mConf.getThumbMarginBottom() > 0 ? mConf + .getThumbMarginBottom() : 0) + + (-mConf.getShrinkY()); + mSafeZone.set(left, top, right, bottom); + + mCenterPos = mSafeZone.left + + (mSafeZone.right - mSafeZone.left - mConf.getThumbWidth()) + / 2; + } else { + mSafeZone = null; + } + } + + private void setupBackZone() { + int w = getMeasuredWidth(); + int h = getMeasuredHeight(); + if (w > 0 && h > 0) { + if (mBackZone == null) { + mBackZone = new Rect(); + } + int left, right, top, bottom; + left = getPaddingLeft() + + (mConf.getThumbMarginLeft() > 0 ? 0 : -mConf + .getThumbMarginLeft()); + right = w + - getPaddingRight() + - (mConf.getThumbMarginRight() > 0 ? 0 : -mConf + .getThumbMarginRight()) + (-mConf.getShrinkX()); + top = getPaddingTop() + + (mConf.getThumbMarginTop() > 0 ? 0 : -mConf + .getThumbMarginTop()); + bottom = h + - getPaddingBottom() + - (mConf.getThumbMarginBottom() > 0 ? 0 : -mConf + .getThumbMarginBottom()) + (-mConf.getShrinkY()); + mBackZone.set(left, top, right, bottom); + } else { + mBackZone = null; + } + } + + private void setupThumbZone() { + int w = getMeasuredWidth(); + int h = getMeasuredHeight(); + if (w > 0 && h > 0) { + if (mThumbZone == null) { + mThumbZone = new Rect(); + } + int left, right, top, bottom; + left = mIsChecked ? (mSafeZone.right - mConf.getThumbWidth()) + : mSafeZone.left; + right = left + mConf.getThumbWidth(); + top = mSafeZone.top; + bottom = top + mConf.getThumbHeight(); + mThumbZone.set(left, top, right, bottom); + } else { + mThumbZone = null; + } + } + + private void setupDrawableBounds() { + if (mBackZone != null) { + mConf.getOnDrawable().setBounds(mBackZone); + mConf.getOffDrawable().setBounds(mBackZone); + } + if (mThumbZone != null) { + mConf.getThumbDrawable().setBounds(mThumbZone); + } + } + + private int measureWidth(int measureSpec) { + int measuredWidth = 0; + + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + int minWidth = (int) (mConf.getThumbWidth() * mConf.getMeasureFactor() + + getPaddingLeft() + getPaddingRight()); + int innerMarginWidth = mConf.getThumbMarginLeft() + + mConf.getThumbMarginRight(); + if (innerMarginWidth > 0) { + minWidth += innerMarginWidth; + } + + if (specMode == MeasureSpec.EXACTLY) { + measuredWidth = Math.max(specSize, minWidth); + } else { + measuredWidth = minWidth; + if (specMode == MeasureSpec.AT_MOST) { + measuredWidth = Math.min(specSize, minWidth); + } + } + + // bounds are negative numbers + measuredWidth += (mConf.getInsetBounds().left + mConf.getInsetBounds().right); + + return measuredWidth; + } + + private int measureHeight(int measureSpec) { + int measuredHeight = 0; + + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + int minHeight = mConf.getThumbHeight() + getPaddingTop() + + getPaddingBottom(); + int innerMarginHeight = mConf.getThumbMarginTop() + + mConf.getThumbMarginBottom(); + + if (innerMarginHeight > 0) { + minHeight += innerMarginHeight; + } + + if (specMode == MeasureSpec.EXACTLY) { + measuredHeight = Math.max(specSize, minHeight); + } else { + measuredHeight = minHeight; + if (specMode == MeasureSpec.AT_MOST) { + measuredHeight = Math.min(specSize, minHeight); + } + } + + measuredHeight += (mConf.getInsetBounds().top + mConf.getInsetBounds().bottom); + + return measuredHeight; + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + canvas.getClipBounds(mBounds); + if (mBounds != null && mConf.needShrink()) { + mBounds.inset(mConf.getInsetX(), mConf.getInsetY()); + canvas.clipRect(mBounds, Region.Op.REPLACE); + canvas.translate(mConf.getInsetBounds().left, + mConf.getInsetBounds().top); + } + + boolean useGeneralDisableEffect = !isEnabled() + && this.notStatableDrawable(); + if (useGeneralDisableEffect) { + canvas.saveLayerAlpha(mSaveLayerZone, 255 / 2, + Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG + | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG + | Canvas.FULL_COLOR_LAYER_SAVE_FLAG + | Canvas.CLIP_TO_LAYER_SAVE_FLAG); + } + + mConf.getOffDrawable().draw(canvas); + mConf.getOnDrawable().setAlpha(calcAlpha()); + mConf.getOnDrawable().draw(canvas); + mConf.getThumbDrawable().draw(canvas); + + if (useGeneralDisableEffect) { + canvas.restore(); + } + + if (SHOW_RECT) { + mRectPaint.setColor(Color.parseColor("#AA0000")); + canvas.drawRect(mBackZone, mRectPaint); + mRectPaint.setColor(Color.parseColor("#00FF00")); + canvas.drawRect(mSafeZone, mRectPaint); + mRectPaint.setColor(Color.parseColor("#0000FF")); + canvas.drawRect(mThumbZone, mRectPaint); + } + } + + private boolean notStatableDrawable() { + boolean thumbStatable = (mConf.getThumbDrawable() instanceof StateListDrawable); + boolean onStatable = (mConf.getOnDrawable() instanceof StateListDrawable); + boolean offStatable = (mConf.getOffDrawable() instanceof StateListDrawable); + return !thumbStatable || !onStatable || !offStatable; + } + + /** + * calculate the alpha value for on layer + * + * @return 0 ~ 255 + */ + private int calcAlpha() { + int alpha = 255; + if (mSafeZone == null || mSafeZone.right == mSafeZone.left) { + + } else { + int backWidth = mSafeZone.right - mConf.getThumbWidth() + - mSafeZone.left; + if (backWidth > 0) { + alpha = (mThumbZone.left - mSafeZone.left) * 255 / backWidth; + } + } + + return alpha; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + + if (isAnimating || !isEnabled()) { + return false; + } + int action = event.getAction(); + + float deltaX = event.getX() - mStartX; + float deltaY = event.getY() - mStartY; + + // status the view going to change to when finger released + boolean nextStatus = mIsChecked; + + switch (action) { + case MotionEvent.ACTION_DOWN: + catchView(); + mStartX = event.getX(); + mStartY = event.getY(); + mLastX = mStartX; + setPressed(true); + break; + + case MotionEvent.ACTION_MOVE: + float x = event.getX(); + moveThumb((int) (x - mLastX)); + mLastX = x; + break; + + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + setPressed(false); + + nextStatus = getStatusBasedOnPos(); + + float time = event.getEventTime() - event.getDownTime(); + + if (deltaX < mTouchSlop && deltaY < mTouchSlop + && time < mClickTimeout) { + performClick(); + } else { + slideToChecked(nextStatus); + } + + break; + + default: + break; + } + invalidate(); + return true; + } + + /** + * return the status based on position of thumb + * + * @return + */ + private boolean getStatusBasedOnPos() { + return mThumbZone.left > mCenterPos; + } + + @Override + public void invalidate() { + if (mBounds != null && mConf.needShrink()) { + invalidate(mBounds); + } else { + super.invalidate(); + } + } + + @Override + public boolean performClick() { + return super.performClick(); + } + + private void catchView() { + ViewParent parent = getParent(); + if (parent != null) { + parent.requestDisallowInterceptTouchEvent(true); + } + } + + @Override + public void setChecked(final boolean checked) { + setChecked(checked, true); + } + + public void setChecked(final boolean checked, boolean trigger) { + if (mThumbZone != null) { + moveThumb(checked ? getMeasuredWidth() : -getMeasuredWidth()); + } + setCheckedInClass(checked, trigger); + } + + @Override + public boolean isChecked() { + return mIsChecked; + } + + @Override + public void toggle() { + toggle(true); + } + + public void toggle(boolean animated) { + if (animated) { + slideToChecked(!mIsChecked); + } else { + setChecked(!mIsChecked); + } + } + + @Override + protected void drawableStateChanged() { + super.drawableStateChanged(); + if (mConf == null) { + return; + } + setDrawableState(mConf.getThumbDrawable()); + setDrawableState(mConf.getOnDrawable()); + setDrawableState(mConf.getOffDrawable()); + } + + private void setDrawableState(Drawable drawable) { + if (drawable != null) { + int[] myDrawableState = getDrawableState(); + drawable.setState(myDrawableState); + invalidate(); + } + } + + public void setOnCheckedChangeListener( + OnCheckedChangeListener onCheckedChangeListener) { + if (onCheckedChangeListener == null) { + throw new IllegalArgumentException( + "onCheckedChangeListener can not be null"); + } + mOnCheckedChangeListener = onCheckedChangeListener; + } + + private void setCheckedInClass(boolean checked) { + setCheckedInClass(checked, true); + } + + private void setCheckedInClass(boolean checked, boolean trigger) { + if (mIsChecked == checked) { + return; + } + mIsChecked = checked; + + refreshDrawableState(); + + if (mOnCheckedChangeListener != null && trigger) { + mOnCheckedChangeListener.onCheckedChanged(this, mIsChecked); + } + } + + public void slideToChecked(boolean checked) { + if (isAnimating) { + return; + } + int from = mThumbZone.left; + int to = checked ? mSafeZone.right - mConf.getThumbWidth() + : mSafeZone.left; + mAnimationController.startAnimation(from, to); + } + + private void moveThumb(int delta) { + + int newLeft = mThumbZone.left + delta; + int newRight = mThumbZone.right + delta; + if (newLeft < mSafeZone.left) { + newLeft = mSafeZone.left; + newRight = newLeft + mConf.getThumbWidth(); + } + if (newRight > mSafeZone.right) { + newRight = mSafeZone.right; + newLeft = newRight - mConf.getThumbWidth(); + } + + moveThumbTo(newLeft, newRight); + } + + private void moveThumbTo(int newLeft, int newRight) { + mThumbZone.set(newLeft, mThumbZone.top, newRight, mThumbZone.bottom); + mConf.getThumbDrawable().setBounds(mThumbZone); + } + + class SBAnimationListener implements AnimationController.OnAnimateListener { + + @Override + public void onAnimationStart() { + isAnimating = true; + } + + @Override + public boolean continueAnimating() { + return mThumbZone.right < mSafeZone.right + && mThumbZone.left > mSafeZone.left; + } + + @Override + public void onFrameUpdate(int frame) { + moveThumb(frame); + postInvalidate(); + } + + @Override + public void onAnimateComplete() { + setCheckedInClass(getStatusBasedOnPos()); + isAnimating = false; + } + + } +} diff --git a/app/src/main/res/anim/pophidden_anim.xml b/app/src/main/res/anim/pophidden_anim.xml new file mode 100644 index 0000000000..e42f14f1e8 --- /dev/null +++ b/app/src/main/res/anim/pophidden_anim.xml @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/popshow_anim.xml b/app/src/main/res/anim/popshow_anim.xml new file mode 100644 index 0000000000..7517901086 --- /dev/null +++ b/app/src/main/res/anim/popshow_anim.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-hdpi/account_warn.png b/app/src/main/res/drawable-hdpi/account_warn.png new file mode 100644 index 0000000000..d006150ca1 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/account_warn.png differ diff --git a/app/src/main/res/drawable-hdpi/btn_share.png b/app/src/main/res/drawable-hdpi/btn_share.png new file mode 100644 index 0000000000..953f77c5df Binary files /dev/null and b/app/src/main/res/drawable-hdpi/btn_share.png differ diff --git a/app/src/main/res/drawable-hdpi/concern_arrow.png b/app/src/main/res/drawable-hdpi/concern_arrow.png new file mode 100644 index 0000000000..9ac5b6e272 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/concern_arrow.png differ diff --git a/app/src/main/res/drawable-hdpi/concern_delete.png b/app/src/main/res/drawable-hdpi/concern_delete.png new file mode 100644 index 0000000000..20d1183169 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/concern_delete.png differ diff --git a/app/src/main/res/drawable-hdpi/default_user_icon.png b/app/src/main/res/drawable-hdpi/default_user_icon.png new file mode 100644 index 0000000000..6bdb193c73 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/default_user_icon.png differ diff --git a/app/src/main/res/drawable-hdpi/down.png b/app/src/main/res/drawable-hdpi/down.png new file mode 100644 index 0000000000..645e0a07bc Binary files /dev/null and b/app/src/main/res/drawable-hdpi/down.png differ diff --git a/app/src/main/res/drawable-hdpi/download_delete_icon.png b/app/src/main/res/drawable-hdpi/download_delete_icon.png new file mode 100644 index 0000000000..38e7e7e489 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/download_delete_icon.png differ diff --git a/app/src/main/res/drawable-hdpi/download_hint.9.png b/app/src/main/res/drawable-hdpi/download_hint.9.png new file mode 100644 index 0000000000..7a0063082b Binary files /dev/null and b/app/src/main/res/drawable-hdpi/download_hint.9.png differ diff --git a/app/src/main/res/drawable-hdpi/essay_comment.png b/app/src/main/res/drawable-hdpi/essay_comment.png new file mode 100644 index 0000000000..d716cd5000 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/essay_comment.png differ diff --git a/app/src/main/res/drawable-hdpi/essay_like_dn.png b/app/src/main/res/drawable-hdpi/essay_like_dn.png new file mode 100644 index 0000000000..9b7af06755 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/essay_like_dn.png differ diff --git a/app/src/main/res/drawable-hdpi/essay_like_up.png b/app/src/main/res/drawable-hdpi/essay_like_up.png new file mode 100644 index 0000000000..725ffa30ea Binary files /dev/null and b/app/src/main/res/drawable-hdpi/essay_like_up.png differ diff --git a/app/src/main/res/drawable-hdpi/essay_share.png b/app/src/main/res/drawable-hdpi/essay_share.png new file mode 100644 index 0000000000..0207c990bc Binary files /dev/null and b/app/src/main/res/drawable-hdpi/essay_share.png differ diff --git a/app/src/main/res/drawable-hdpi/essay_unlike_dn.png b/app/src/main/res/drawable-hdpi/essay_unlike_dn.png new file mode 100644 index 0000000000..d27edcab52 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/essay_unlike_dn.png differ diff --git a/app/src/main/res/drawable-hdpi/essay_unlike_up.png b/app/src/main/res/drawable-hdpi/essay_unlike_up.png new file mode 100644 index 0000000000..8ee67b040d Binary files /dev/null and b/app/src/main/res/drawable-hdpi/essay_unlike_up.png differ diff --git a/app/src/main/res/drawable-hdpi/essaydetails_comment_dn.9.png b/app/src/main/res/drawable-hdpi/essaydetails_comment_dn.9.png new file mode 100644 index 0000000000..0b6f497015 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/essaydetails_comment_dn.9.png differ diff --git a/app/src/main/res/drawable-hdpi/essaydetails_comment_up.9.png b/app/src/main/res/drawable-hdpi/essaydetails_comment_up.9.png new file mode 100644 index 0000000000..3524deafde Binary files /dev/null and b/app/src/main/res/drawable-hdpi/essaydetails_comment_up.9.png differ diff --git a/app/src/main/res/drawable-hdpi/home1_selected.png b/app/src/main/res/drawable-hdpi/home1_selected.png new file mode 100644 index 0000000000..73bfc450e0 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/home1_selected.png differ diff --git a/app/src/main/res/drawable-hdpi/home1_unselected.png b/app/src/main/res/drawable-hdpi/home1_unselected.png new file mode 100644 index 0000000000..36b6f9b74b Binary files /dev/null and b/app/src/main/res/drawable-hdpi/home1_unselected.png differ diff --git a/app/src/main/res/drawable-hdpi/home2_selected.png b/app/src/main/res/drawable-hdpi/home2_selected.png new file mode 100644 index 0000000000..6afac1a8dc Binary files /dev/null and b/app/src/main/res/drawable-hdpi/home2_selected.png differ diff --git a/app/src/main/res/drawable-hdpi/home2_unselected.png b/app/src/main/res/drawable-hdpi/home2_unselected.png new file mode 100644 index 0000000000..e5ebf992cb Binary files /dev/null and b/app/src/main/res/drawable-hdpi/home2_unselected.png differ diff --git a/app/src/main/res/drawable-hdpi/home3_selected.png b/app/src/main/res/drawable-hdpi/home3_selected.png new file mode 100644 index 0000000000..3481cd2f8b Binary files /dev/null and b/app/src/main/res/drawable-hdpi/home3_selected.png differ diff --git a/app/src/main/res/drawable-hdpi/home3_unselected.png b/app/src/main/res/drawable-hdpi/home3_unselected.png new file mode 100644 index 0000000000..ce5fe2cc37 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/home3_unselected.png differ diff --git a/app/src/main/res/drawable-hdpi/home_kapaigonglue.png b/app/src/main/res/drawable-hdpi/home_kapaigonglue.png new file mode 100644 index 0000000000..43f7d07291 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/home_kapaigonglue.png differ diff --git a/app/src/main/res/drawable-hdpi/home_kapaitoutiao.png b/app/src/main/res/drawable-hdpi/home_kapaitoutiao.png new file mode 100644 index 0000000000..a1ee445852 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/home_kapaitoutiao.png differ diff --git a/app/src/main/res/drawable-hdpi/home_remenkapai.png b/app/src/main/res/drawable-hdpi/home_remenkapai.png new file mode 100644 index 0000000000..b9c24b2654 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/home_remenkapai.png differ diff --git a/app/src/main/res/drawable-hdpi/home_xincekapai.png b/app/src/main/res/drawable-hdpi/home_xincekapai.png new file mode 100644 index 0000000000..a5e7a6fabc Binary files /dev/null and b/app/src/main/res/drawable-hdpi/home_xincekapai.png differ diff --git a/app/src/main/res/drawable-hdpi/home_yuedujingxuan.png b/app/src/main/res/drawable-hdpi/home_yuedujingxuan.png new file mode 100644 index 0000000000..474b4a6bcc Binary files /dev/null and b/app/src/main/res/drawable-hdpi/home_yuedujingxuan.png differ diff --git a/app/src/main/res/drawable-hdpi/home_zuixinchajian.png b/app/src/main/res/drawable-hdpi/home_zuixinchajian.png new file mode 100644 index 0000000000..d6e0cd5c8d Binary files /dev/null and b/app/src/main/res/drawable-hdpi/home_zuixinchajian.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_plus.png b/app/src/main/res/drawable-hdpi/ic_action_plus.png new file mode 100644 index 0000000000..b8703333f6 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_action_plus.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_actionbar_download.png b/app/src/main/res/drawable-hdpi/ic_actionbar_download.png new file mode 100644 index 0000000000..260300f745 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_actionbar_download.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_actionbar_notification.png b/app/src/main/res/drawable-hdpi/ic_actionbar_notification.png new file mode 100644 index 0000000000..ea63051b65 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_actionbar_notification.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_actionbar_overflow.png b/app/src/main/res/drawable-hdpi/ic_actionbar_overflow.png new file mode 100644 index 0000000000..5a1966a899 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_actionbar_overflow.png differ diff --git a/app/src/main/res/drawable-hdpi/img_cancel.png b/app/src/main/res/drawable-hdpi/img_cancel.png new file mode 100644 index 0000000000..d15c9726dd Binary files /dev/null and b/app/src/main/res/drawable-hdpi/img_cancel.png differ diff --git a/app/src/main/res/drawable-hdpi/login_auto_dn.png b/app/src/main/res/drawable-hdpi/login_auto_dn.png new file mode 100644 index 0000000000..0a44a6c7b0 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/login_auto_dn.png differ diff --git a/app/src/main/res/drawable-hdpi/login_auto_up.png b/app/src/main/res/drawable-hdpi/login_auto_up.png new file mode 100644 index 0000000000..35cacaee56 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/login_auto_up.png differ diff --git a/app/src/main/res/drawable-hdpi/login_close.png b/app/src/main/res/drawable-hdpi/login_close.png new file mode 100644 index 0000000000..ed01e6b481 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/login_close.png differ diff --git a/app/src/main/res/drawable-hdpi/login_mobile.png b/app/src/main/res/drawable-hdpi/login_mobile.png new file mode 100644 index 0000000000..3b57eefb29 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/login_mobile.png differ diff --git a/app/src/main/res/drawable-hdpi/login_password_dn.png b/app/src/main/res/drawable-hdpi/login_password_dn.png new file mode 100644 index 0000000000..45e3aa3240 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/login_password_dn.png differ diff --git a/app/src/main/res/drawable-hdpi/login_password_up.png b/app/src/main/res/drawable-hdpi/login_password_up.png new file mode 100644 index 0000000000..53d94b759a Binary files /dev/null and b/app/src/main/res/drawable-hdpi/login_password_up.png differ diff --git a/app/src/main/res/drawable-hdpi/login_user.png b/app/src/main/res/drawable-hdpi/login_user.png new file mode 100644 index 0000000000..39854aece9 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/login_user.png differ diff --git a/app/src/main/res/drawable-hdpi/login_username_dn.png b/app/src/main/res/drawable-hdpi/login_username_dn.png new file mode 100644 index 0000000000..2832faa0a3 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/login_username_dn.png differ diff --git a/app/src/main/res/drawable-hdpi/login_username_up.png b/app/src/main/res/drawable-hdpi/login_username_up.png new file mode 100644 index 0000000000..a555c45281 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/login_username_up.png differ diff --git a/app/src/main/res/drawable-hdpi/me_concern.png b/app/src/main/res/drawable-hdpi/me_concern.png new file mode 100644 index 0000000000..3bfb121601 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/me_concern.png differ diff --git a/app/src/main/res/drawable-hdpi/me_download.png b/app/src/main/res/drawable-hdpi/me_download.png new file mode 100644 index 0000000000..59ece3c104 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/me_download.png differ diff --git a/app/src/main/res/drawable-hdpi/me_setting.png b/app/src/main/res/drawable-hdpi/me_setting.png new file mode 100644 index 0000000000..1a75d797ff Binary files /dev/null and b/app/src/main/res/drawable-hdpi/me_setting.png differ diff --git a/app/src/main/res/drawable-hdpi/me_update.png b/app/src/main/res/drawable-hdpi/me_update.png new file mode 100644 index 0000000000..a8a76032f0 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/me_update.png differ diff --git a/app/src/main/res/drawable-hdpi/newserver_gray.9.png b/app/src/main/res/drawable-hdpi/newserver_gray.9.png new file mode 100644 index 0000000000..d5007a83bb Binary files /dev/null and b/app/src/main/res/drawable-hdpi/newserver_gray.9.png differ diff --git a/app/src/main/res/drawable-hdpi/newserver_orange.9.png b/app/src/main/res/drawable-hdpi/newserver_orange.9.png new file mode 100644 index 0000000000..c64baa34f0 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/newserver_orange.9.png differ diff --git a/app/src/main/res/drawable-hdpi/newserver_red.9.png b/app/src/main/res/drawable-hdpi/newserver_red.9.png new file mode 100644 index 0000000000..aa249c722f Binary files /dev/null and b/app/src/main/res/drawable-hdpi/newserver_red.9.png differ diff --git a/app/src/main/res/drawable-hdpi/newservice_left.png b/app/src/main/res/drawable-hdpi/newservice_left.png new file mode 100644 index 0000000000..77f82440ee Binary files /dev/null and b/app/src/main/res/drawable-hdpi/newservice_left.png differ diff --git a/app/src/main/res/drawable-hdpi/newservice_right.png b/app/src/main/res/drawable-hdpi/newservice_right.png new file mode 100644 index 0000000000..bb2c1ecbd3 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/newservice_right.png differ diff --git a/app/src/main/res/drawable-hdpi/ocupy.png b/app/src/main/res/drawable-hdpi/ocupy.png new file mode 100644 index 0000000000..c675816e29 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ocupy.png differ diff --git a/app/src/main/res/drawable-hdpi/primatte_default_icon.png b/app/src/main/res/drawable-hdpi/primatte_default_icon.png new file mode 100644 index 0000000000..e0890c7328 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/primatte_default_icon.png differ diff --git a/app/src/main/res/drawable-hdpi/primatte_line_left.png b/app/src/main/res/drawable-hdpi/primatte_line_left.png new file mode 100644 index 0000000000..5c4a4b334c Binary files /dev/null and b/app/src/main/res/drawable-hdpi/primatte_line_left.png differ diff --git a/app/src/main/res/drawable-hdpi/primatte_line_right.png b/app/src/main/res/drawable-hdpi/primatte_line_right.png new file mode 100644 index 0000000000..ca33570b63 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/primatte_line_right.png differ diff --git a/app/src/main/res/drawable-hdpi/register_mobile_dn.png b/app/src/main/res/drawable-hdpi/register_mobile_dn.png new file mode 100644 index 0000000000..66b6d7a1aa Binary files /dev/null and b/app/src/main/res/drawable-hdpi/register_mobile_dn.png differ diff --git a/app/src/main/res/drawable-hdpi/register_mobile_up.png b/app/src/main/res/drawable-hdpi/register_mobile_up.png new file mode 100644 index 0000000000..9f5703ebd6 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/register_mobile_up.png differ diff --git a/app/src/main/res/drawable-hdpi/reuse_btn_back.png b/app/src/main/res/drawable-hdpi/reuse_btn_back.png new file mode 100644 index 0000000000..9a5d9a2313 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/reuse_btn_back.png differ diff --git a/app/src/main/res/drawable-hdpi/reuse_btn_back_gray.png b/app/src/main/res/drawable-hdpi/reuse_btn_back_gray.png new file mode 100644 index 0000000000..e380faf2c1 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/reuse_btn_back_gray.png differ diff --git a/app/src/main/res/drawable-hdpi/reuse_search_black.png b/app/src/main/res/drawable-hdpi/reuse_search_black.png new file mode 100644 index 0000000000..4711fd8356 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/reuse_search_black.png differ diff --git a/app/src/main/res/drawable-hdpi/right.png b/app/src/main/res/drawable-hdpi/right.png new file mode 100644 index 0000000000..60c436a221 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/right.png differ diff --git a/app/src/main/res/drawable-hdpi/search_delete_gray.png b/app/src/main/res/drawable-hdpi/search_delete_gray.png new file mode 100644 index 0000000000..1ec6fb874e Binary files /dev/null and b/app/src/main/res/drawable-hdpi/search_delete_gray.png differ diff --git a/app/src/main/res/drawable-hdpi/search_history_ico.png b/app/src/main/res/drawable-hdpi/search_history_ico.png new file mode 100644 index 0000000000..190c575f2b Binary files /dev/null and b/app/src/main/res/drawable-hdpi/search_history_ico.png differ diff --git a/app/src/main/res/drawable-hdpi/search_input_delete.png b/app/src/main/res/drawable-hdpi/search_input_delete.png new file mode 100644 index 0000000000..56056e8415 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/search_input_delete.png differ diff --git a/app/src/main/res/drawable-hdpi/search_top_background.png b/app/src/main/res/drawable-hdpi/search_top_background.png new file mode 100644 index 0000000000..168f32fd9e Binary files /dev/null and b/app/src/main/res/drawable-hdpi/search_top_background.png differ diff --git a/app/src/main/res/drawable-hdpi/shadow_bg.9.png b/app/src/main/res/drawable-hdpi/shadow_bg.9.png new file mode 100644 index 0000000000..f6a2939d9c Binary files /dev/null and b/app/src/main/res/drawable-hdpi/shadow_bg.9.png differ diff --git a/app/src/main/res/drawable-hdpi/skyblue_editpage_image_remove.png b/app/src/main/res/drawable-hdpi/skyblue_editpage_image_remove.png new file mode 100644 index 0000000000..946546276b Binary files /dev/null and b/app/src/main/res/drawable-hdpi/skyblue_editpage_image_remove.png differ diff --git a/app/src/main/res/drawable-hdpi/skyblue_platform_checked.png b/app/src/main/res/drawable-hdpi/skyblue_platform_checked.png new file mode 100644 index 0000000000..91dcb67a5d Binary files /dev/null and b/app/src/main/res/drawable-hdpi/skyblue_platform_checked.png differ diff --git a/app/src/main/res/drawable-hdpi/skyblue_platform_checked_disabled.png b/app/src/main/res/drawable-hdpi/skyblue_platform_checked_disabled.png new file mode 100644 index 0000000000..69938b43ff Binary files /dev/null and b/app/src/main/res/drawable-hdpi/skyblue_platform_checked_disabled.png differ diff --git a/app/src/main/res/drawable-hdpi/tab_bg.9.png b/app/src/main/res/drawable-hdpi/tab_bg.9.png new file mode 100644 index 0000000000..07a69e46ac Binary files /dev/null and b/app/src/main/res/drawable-hdpi/tab_bg.9.png differ diff --git a/app/src/main/res/drawable-hdpi/title_blue.9.png b/app/src/main/res/drawable-hdpi/title_blue.9.png new file mode 100644 index 0000000000..854f7a5674 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/title_blue.9.png differ diff --git a/app/src/main/res/drawable-hdpi/title_gray.9.png b/app/src/main/res/drawable-hdpi/title_gray.9.png new file mode 100644 index 0000000000..2b32bc6b28 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/title_gray.9.png differ diff --git a/app/src/main/res/drawable-hdpi/title_orange.9.png b/app/src/main/res/drawable-hdpi/title_orange.9.png new file mode 100644 index 0000000000..4f3d0fc2c0 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/title_orange.9.png differ diff --git a/app/src/main/res/drawable-hdpi/title_red.9.png b/app/src/main/res/drawable-hdpi/title_red.9.png new file mode 100644 index 0000000000..8b158a5f92 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/title_red.9.png differ diff --git a/app/src/main/res/drawable-hdpi/up.png b/app/src/main/res/drawable-hdpi/up.png new file mode 100644 index 0000000000..739026183d Binary files /dev/null and b/app/src/main/res/drawable-hdpi/up.png differ diff --git a/app/src/main/res/drawable-hdpi/userinfo_more.png b/app/src/main/res/drawable-hdpi/userinfo_more.png new file mode 100644 index 0000000000..5f3d1d25c8 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/userinfo_more.png differ diff --git a/app/src/main/res/drawable-nodpi/splash_01.jpg b/app/src/main/res/drawable-nodpi/splash_01.jpg new file mode 100644 index 0000000000..5a83c49242 Binary files /dev/null and b/app/src/main/res/drawable-nodpi/splash_01.jpg differ diff --git a/app/src/main/res/drawable-nodpi/splash_02.jpg b/app/src/main/res/drawable-nodpi/splash_02.jpg new file mode 100644 index 0000000000..a025be4922 Binary files /dev/null and b/app/src/main/res/drawable-nodpi/splash_02.jpg differ diff --git a/app/src/main/res/drawable-nodpi/splash_03.jpg b/app/src/main/res/drawable-nodpi/splash_03.jpg new file mode 100644 index 0000000000..7cefe3f361 Binary files /dev/null and b/app/src/main/res/drawable-nodpi/splash_03.jpg differ diff --git a/app/src/main/res/drawable-nodpi/splash_04.jpg b/app/src/main/res/drawable-nodpi/splash_04.jpg new file mode 100644 index 0000000000..b4fd3841c2 Binary files /dev/null and b/app/src/main/res/drawable-nodpi/splash_04.jpg differ diff --git a/app/src/main/res/drawable-xhdpi/auth_follow_cb_chd.png b/app/src/main/res/drawable-xhdpi/auth_follow_cb_chd.png new file mode 100644 index 0000000000..44f13c06bd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/auth_follow_cb_chd.png differ diff --git a/app/src/main/res/drawable-xhdpi/auth_follow_cb_unc.png b/app/src/main/res/drawable-xhdpi/auth_follow_cb_unc.png new file mode 100644 index 0000000000..0bd2d702b2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/auth_follow_cb_unc.png differ diff --git a/app/src/main/res/drawable-xhdpi/auth_title_back.png b/app/src/main/res/drawable-xhdpi/auth_title_back.png new file mode 100644 index 0000000000..adf1824a9c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/auth_title_back.png differ diff --git a/app/src/main/res/drawable-xhdpi/blue_point.png b/app/src/main/res/drawable-xhdpi/blue_point.png new file mode 100644 index 0000000000..075bccac1a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/blue_point.png differ diff --git a/app/src/main/res/drawable-xhdpi/btn_back_nor.9.png b/app/src/main/res/drawable-xhdpi/btn_back_nor.9.png new file mode 100644 index 0000000000..73618b43ef Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/btn_back_nor.9.png differ diff --git a/app/src/main/res/drawable-xhdpi/download_delete.9.png b/app/src/main/res/drawable-xhdpi/download_delete.9.png new file mode 100644 index 0000000000..e093a55cbb Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/download_delete.9.png differ diff --git a/app/src/main/res/drawable-xhdpi/edittext_back.9.png b/app/src/main/res/drawable-xhdpi/edittext_back.9.png new file mode 100644 index 0000000000..0c83a76d42 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/edittext_back.9.png differ diff --git a/app/src/main/res/drawable-xhdpi/home_database_navigation.png b/app/src/main/res/drawable-xhdpi/home_database_navigation.png new file mode 100644 index 0000000000..972700ae7e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_database_navigation.png differ diff --git a/app/src/main/res/drawable-xhdpi/home_newgame_navigation.png b/app/src/main/res/drawable-xhdpi/home_newgame_navigation.png new file mode 100644 index 0000000000..f53c970fae Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_newgame_navigation.png differ diff --git a/app/src/main/res/drawable-xhdpi/home_news_navigation.png b/app/src/main/res/drawable-xhdpi/home_news_navigation.png new file mode 100644 index 0000000000..638158c9c6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_news_navigation.png differ diff --git a/app/src/main/res/drawable-xhdpi/home_raiders_navigation.png b/app/src/main/res/drawable-xhdpi/home_raiders_navigation.png new file mode 100644 index 0000000000..996f98f486 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_raiders_navigation.png differ diff --git a/app/src/main/res/drawable-xhdpi/light_blue_point.png b/app/src/main/res/drawable-xhdpi/light_blue_point.png new file mode 100644 index 0000000000..000213588e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/light_blue_point.png differ diff --git a/app/src/main/res/drawable-xhdpi/logo.png b/app/src/main/res/drawable-xhdpi/logo.png new file mode 100644 index 0000000000..25ffd8ce52 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/logo.png differ diff --git a/app/src/main/res/drawable-xhdpi/logo_black.png b/app/src/main/res/drawable-xhdpi/logo_black.png new file mode 100644 index 0000000000..d41c3f1446 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/logo_black.png differ diff --git a/app/src/main/res/drawable-xhdpi/logo_laiwangmoments.png b/app/src/main/res/drawable-xhdpi/logo_laiwangmoments.png new file mode 100644 index 0000000000..8a71a353ee Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/logo_laiwangmoments.png differ diff --git a/app/src/main/res/drawable-xhdpi/logo_line.png b/app/src/main/res/drawable-xhdpi/logo_line.png new file mode 100644 index 0000000000..f6e52398cc Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/logo_line.png differ diff --git a/app/src/main/res/drawable-xhdpi/logo_qq.png b/app/src/main/res/drawable-xhdpi/logo_qq.png new file mode 100644 index 0000000000..3d17d43e20 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/logo_qq.png differ diff --git a/app/src/main/res/drawable-xhdpi/logo_qzone.png b/app/src/main/res/drawable-xhdpi/logo_qzone.png new file mode 100644 index 0000000000..f8c97877ee Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/logo_qzone.png differ diff --git a/app/src/main/res/drawable-xhdpi/logo_sinaweibo.png b/app/src/main/res/drawable-xhdpi/logo_sinaweibo.png new file mode 100644 index 0000000000..2f8bf10f49 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/logo_sinaweibo.png differ diff --git a/app/src/main/res/drawable-xhdpi/md_switch_thumb_off_normal.png b/app/src/main/res/drawable-xhdpi/md_switch_thumb_off_normal.png new file mode 100644 index 0000000000..ad66765c6d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/md_switch_thumb_off_normal.png differ diff --git a/app/src/main/res/drawable-xhdpi/md_switch_thumb_on_normal.png b/app/src/main/res/drawable-xhdpi/md_switch_thumb_on_normal.png new file mode 100644 index 0000000000..002921662a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/md_switch_thumb_on_normal.png differ diff --git a/app/src/main/res/drawable-xhdpi/me_icon.png b/app/src/main/res/drawable-xhdpi/me_icon.png new file mode 100644 index 0000000000..af83145aaf Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/me_icon.png differ diff --git a/app/src/main/res/drawable-xhdpi/pin.png b/app/src/main/res/drawable-xhdpi/pin.png new file mode 100644 index 0000000000..2606e4a233 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/pin.png differ diff --git a/app/src/main/res/drawable-xhdpi/platform_360.png b/app/src/main/res/drawable-xhdpi/platform_360.png new file mode 100644 index 0000000000..a3a3fc7578 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/platform_360.png differ diff --git a/app/src/main/res/drawable-xhdpi/platform_37.jpg b/app/src/main/res/drawable-xhdpi/platform_37.jpg new file mode 100644 index 0000000000..24c271104e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/platform_37.jpg differ diff --git a/app/src/main/res/drawable-xhdpi/platform_91.jpg b/app/src/main/res/drawable-xhdpi/platform_91.jpg new file mode 100644 index 0000000000..f47e3e28d9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/platform_91.jpg differ diff --git a/app/src/main/res/drawable-xhdpi/platform_9u.png b/app/src/main/res/drawable-xhdpi/platform_9u.png new file mode 100644 index 0000000000..22dd4b7351 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/platform_9u.png differ diff --git a/app/src/main/res/drawable-xhdpi/platform_anzhi.jpg b/app/src/main/res/drawable-xhdpi/platform_anzhi.jpg new file mode 100644 index 0000000000..b847df383f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/platform_anzhi.jpg differ diff --git a/app/src/main/res/drawable-xhdpi/platform_baidu.png b/app/src/main/res/drawable-xhdpi/platform_baidu.png new file mode 100644 index 0000000000..3c3191b87c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/platform_baidu.png differ diff --git a/app/src/main/res/drawable-xhdpi/platform_dl.png b/app/src/main/res/drawable-xhdpi/platform_dl.png new file mode 100644 index 0000000000..5649b4b1dd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/platform_dl.png differ diff --git a/app/src/main/res/drawable-xhdpi/platform_ewan.jpg b/app/src/main/res/drawable-xhdpi/platform_ewan.jpg new file mode 100644 index 0000000000..0654c5b5a2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/platform_ewan.jpg differ diff --git a/app/src/main/res/drawable-xhdpi/platform_gf.png b/app/src/main/res/drawable-xhdpi/platform_gf.png new file mode 100644 index 0000000000..689bae94e9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/platform_gf.png differ diff --git a/app/src/main/res/drawable-xhdpi/platform_gfw.jpg b/app/src/main/res/drawable-xhdpi/platform_gfw.jpg new file mode 100644 index 0000000000..10c17c7012 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/platform_gfw.jpg differ diff --git a/app/src/main/res/drawable-xhdpi/platform_hw.jpg b/app/src/main/res/drawable-xhdpi/platform_hw.jpg new file mode 100644 index 0000000000..8a0983404f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/platform_hw.jpg differ diff --git a/app/src/main/res/drawable-xhdpi/platform_mi.png b/app/src/main/res/drawable-xhdpi/platform_mi.png new file mode 100644 index 0000000000..3232b63a3f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/platform_mi.png differ diff --git a/app/src/main/res/drawable-xhdpi/platform_oppo.png b/app/src/main/res/drawable-xhdpi/platform_oppo.png new file mode 100644 index 0000000000..56e0ffeac9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/platform_oppo.png differ diff --git a/app/src/main/res/drawable-xhdpi/platform_ouwan.png b/app/src/main/res/drawable-xhdpi/platform_ouwan.png new file mode 100644 index 0000000000..bb955d2ad1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/platform_ouwan.png differ diff --git a/app/src/main/res/drawable-xhdpi/platform_pps.jpg b/app/src/main/res/drawable-xhdpi/platform_pps.jpg new file mode 100644 index 0000000000..03be79bc64 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/platform_pps.jpg differ diff --git a/app/src/main/res/drawable-xhdpi/platform_vivo.jpg b/app/src/main/res/drawable-xhdpi/platform_vivo.jpg new file mode 100644 index 0000000000..81e8b9b2cf Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/platform_vivo.jpg differ diff --git a/app/src/main/res/drawable-xhdpi/platform_wdj.jpg b/app/src/main/res/drawable-xhdpi/platform_wdj.jpg new file mode 100644 index 0000000000..d8b01cbea3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/platform_wdj.jpg differ diff --git a/app/src/main/res/drawable-xhdpi/preload.png b/app/src/main/res/drawable-xhdpi/preload.png new file mode 100644 index 0000000000..b4bb7860d9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/preload.png differ diff --git a/app/src/main/res/drawable-xhdpi/reuse_none.9.png b/app/src/main/res/drawable-xhdpi/reuse_none.9.png new file mode 100644 index 0000000000..10ab9c6890 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/reuse_none.9.png differ diff --git a/app/src/main/res/drawable-xhdpi/skyblue_actionbar_back_btn.png b/app/src/main/res/drawable-xhdpi/skyblue_actionbar_back_btn.png new file mode 100644 index 0000000000..3a935e69ba Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/skyblue_actionbar_back_btn.png differ diff --git a/app/src/main/res/drawable-xhdpi/skyblue_actionbar_ok_btn.png b/app/src/main/res/drawable-xhdpi/skyblue_actionbar_ok_btn.png new file mode 100644 index 0000000000..c8e906f5aa Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/skyblue_actionbar_ok_btn.png differ diff --git a/app/src/main/res/drawable-xhdpi/skyblue_editpage_bg.9.png b/app/src/main/res/drawable-xhdpi/skyblue_editpage_bg.9.png new file mode 100644 index 0000000000..b55ac2f6ed Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/skyblue_editpage_bg.9.png differ diff --git a/app/src/main/res/drawable-xhdpi/skyblue_editpage_close.png b/app/src/main/res/drawable-xhdpi/skyblue_editpage_close.png new file mode 100644 index 0000000000..ba7bbb94f2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/skyblue_editpage_close.png differ diff --git a/app/src/main/res/drawable-xhdpi/skyblue_editpage_divider.9.png b/app/src/main/res/drawable-xhdpi/skyblue_editpage_divider.9.png new file mode 100644 index 0000000000..3abc218781 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/skyblue_editpage_divider.9.png differ diff --git a/app/src/main/res/drawable-xhdpi/skyblue_editpage_image_bg.9.png b/app/src/main/res/drawable-xhdpi/skyblue_editpage_image_bg.9.png new file mode 100644 index 0000000000..64dd0f31b0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/skyblue_editpage_image_bg.9.png differ diff --git a/app/src/main/res/drawable-xhdpi/skyblue_logo_qq.png b/app/src/main/res/drawable-xhdpi/skyblue_logo_qq.png new file mode 100644 index 0000000000..2fe158a761 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/skyblue_logo_qq.png differ diff --git a/app/src/main/res/drawable-xhdpi/skyblue_logo_qq_checked.png b/app/src/main/res/drawable-xhdpi/skyblue_logo_qq_checked.png new file mode 100644 index 0000000000..f00168b0d5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/skyblue_logo_qq_checked.png differ diff --git a/app/src/main/res/drawable-xhdpi/skyblue_logo_qzone.png b/app/src/main/res/drawable-xhdpi/skyblue_logo_qzone.png new file mode 100644 index 0000000000..7570f08345 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/skyblue_logo_qzone.png differ diff --git a/app/src/main/res/drawable-xhdpi/skyblue_logo_qzone_checked.png b/app/src/main/res/drawable-xhdpi/skyblue_logo_qzone_checked.png new file mode 100644 index 0000000000..2c25e4d8e1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/skyblue_logo_qzone_checked.png differ diff --git a/app/src/main/res/drawable-xhdpi/skyblue_logo_sinaweibo.png b/app/src/main/res/drawable-xhdpi/skyblue_logo_sinaweibo.png new file mode 100644 index 0000000000..53d006f8e2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/skyblue_logo_sinaweibo.png differ diff --git a/app/src/main/res/drawable-xhdpi/skyblue_logo_sinaweibo_checked.png b/app/src/main/res/drawable-xhdpi/skyblue_logo_sinaweibo_checked.png new file mode 100644 index 0000000000..73af57c586 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/skyblue_logo_sinaweibo_checked.png differ diff --git a/app/src/main/res/drawable-xhdpi/splash_logo.png b/app/src/main/res/drawable-xhdpi/splash_logo.png new file mode 100644 index 0000000000..f9e2e3ec26 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/splash_logo.png differ diff --git a/app/src/main/res/drawable-xhdpi/splash_name.png b/app/src/main/res/drawable-xhdpi/splash_name.png new file mode 100644 index 0000000000..f49785fd34 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/splash_name.png differ diff --git a/app/src/main/res/drawable-xhdpi/splash_slogan.png b/app/src/main/res/drawable-xhdpi/splash_slogan.png new file mode 100644 index 0000000000..04cf04fb69 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/splash_slogan.png differ diff --git a/app/src/main/res/drawable-xhdpi/ssdk_auth_title_back.png b/app/src/main/res/drawable-xhdpi/ssdk_auth_title_back.png new file mode 100644 index 0000000000..33d9b871a3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ssdk_auth_title_back.png differ diff --git a/app/src/main/res/drawable-xhdpi/ssdk_logo.png b/app/src/main/res/drawable-xhdpi/ssdk_logo.png new file mode 100644 index 0000000000..ed7e2351af Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ssdk_logo.png differ diff --git a/app/src/main/res/drawable-xhdpi/ssdk_oks_shake_to_share_back.xml b/app/src/main/res/drawable-xhdpi/ssdk_oks_shake_to_share_back.xml new file mode 100644 index 0000000000..87129aec3c --- /dev/null +++ b/app/src/main/res/drawable-xhdpi/ssdk_oks_shake_to_share_back.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/drawable-xhdpi/ssdk_oks_yaoyiyao.png b/app/src/main/res/drawable-xhdpi/ssdk_oks_yaoyiyao.png new file mode 100644 index 0000000000..4bbddc1a1d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ssdk_oks_yaoyiyao.png differ diff --git a/app/src/main/res/drawable-xhdpi/ssdk_title_div.png b/app/src/main/res/drawable-xhdpi/ssdk_title_div.png new file mode 100644 index 0000000000..7eed68679d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ssdk_title_div.png differ diff --git a/app/src/main/res/drawable-xhdpi/title_back.png b/app/src/main/res/drawable-xhdpi/title_back.png new file mode 100644 index 0000000000..adf1824a9c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/title_back.png differ diff --git a/app/src/main/res/drawable-xhdpi/title_shadow.png b/app/src/main/res/drawable-xhdpi/title_shadow.png new file mode 100644 index 0000000000..160be8a502 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/title_shadow.png differ diff --git a/app/src/main/res/drawable-xhdpi/wifi.png b/app/src/main/res/drawable-xhdpi/wifi.png new file mode 100644 index 0000000000..aa14b47385 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/wifi.png differ diff --git a/app/src/main/res/drawable/actionbar_search_bg.xml b/app/src/main/res/drawable/actionbar_search_bg.xml new file mode 100644 index 0000000000..4ed245ca25 --- /dev/null +++ b/app/src/main/res/drawable/actionbar_search_bg.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/background_tab.xml b/app/src/main/res/drawable/background_tab.xml new file mode 100644 index 0000000000..885cf036a7 --- /dev/null +++ b/app/src/main/res/drawable/background_tab.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/border.xml b/app/src/main/res/drawable/border.xml new file mode 100644 index 0000000000..ec3c835cff --- /dev/null +++ b/app/src/main/res/drawable/border.xml @@ -0,0 +1,15 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/border_blue_bg.xml b/app/src/main/res/drawable/border_blue_bg.xml new file mode 100644 index 0000000000..ec2402fbb8 --- /dev/null +++ b/app/src/main/res/drawable/border_blue_bg.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/border_dialog_bg.xml b/app/src/main/res/drawable/border_dialog_bg.xml new file mode 100644 index 0000000000..50a9df2417 --- /dev/null +++ b/app/src/main/res/drawable/border_dialog_bg.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/border_enter_bg.xml b/app/src/main/res/drawable/border_enter_bg.xml new file mode 100644 index 0000000000..e9eaa56330 --- /dev/null +++ b/app/src/main/res/drawable/border_enter_bg.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/border_gray_bg.xml b/app/src/main/res/drawable/border_gray_bg.xml new file mode 100644 index 0000000000..c2a5d7de08 --- /dev/null +++ b/app/src/main/res/drawable/border_gray_bg.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/border_green_bg.xml b/app/src/main/res/drawable/border_green_bg.xml new file mode 100644 index 0000000000..0b8ed0a216 --- /dev/null +++ b/app/src/main/res/drawable/border_green_bg.xml @@ -0,0 +1,12 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/border_input_dn.xml b/app/src/main/res/drawable/border_input_dn.xml new file mode 100644 index 0000000000..603dca4975 --- /dev/null +++ b/app/src/main/res/drawable/border_input_dn.xml @@ -0,0 +1,12 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/border_input_up.xml b/app/src/main/res/drawable/border_input_up.xml new file mode 100644 index 0000000000..156cd96d6e --- /dev/null +++ b/app/src/main/res/drawable/border_input_up.xml @@ -0,0 +1,12 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/border_login_bg.xml b/app/src/main/res/drawable/border_login_bg.xml new file mode 100644 index 0000000000..87eaf1267f --- /dev/null +++ b/app/src/main/res/drawable/border_login_bg.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/border_normal_bg.xml b/app/src/main/res/drawable/border_normal_bg.xml new file mode 100644 index 0000000000..89f099a193 --- /dev/null +++ b/app/src/main/res/drawable/border_normal_bg.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/border_orange_bg.xml b/app/src/main/res/drawable/border_orange_bg.xml new file mode 100644 index 0000000000..3f00e7e617 --- /dev/null +++ b/app/src/main/res/drawable/border_orange_bg.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/border_red_bg.xml b/app/src/main/res/drawable/border_red_bg.xml new file mode 100644 index 0000000000..963ab532dc --- /dev/null +++ b/app/src/main/res/drawable/border_red_bg.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/border_scarlet_bg.xml b/app/src/main/res/drawable/border_scarlet_bg.xml new file mode 100644 index 0000000000..2d117f0c49 --- /dev/null +++ b/app/src/main/res/drawable/border_scarlet_bg.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/border_update_bg.xml b/app/src/main/res/drawable/border_update_bg.xml new file mode 100644 index 0000000000..51b80ae9f0 --- /dev/null +++ b/app/src/main/res/drawable/border_update_bg.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/border_white_bg.xml b/app/src/main/res/drawable/border_white_bg.xml new file mode 100644 index 0000000000..5bb59bf654 --- /dev/null +++ b/app/src/main/res/drawable/border_white_bg.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/checkbox_style.xml b/app/src/main/res/drawable/checkbox_style.xml new file mode 100644 index 0000000000..68af81e015 --- /dev/null +++ b/app/src/main/res/drawable/checkbox_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/circle_mask.xml b/app/src/main/res/drawable/circle_mask.xml new file mode 100644 index 0000000000..b0f0dc8b13 --- /dev/null +++ b/app/src/main/res/drawable/circle_mask.xml @@ -0,0 +1,20 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/essay_comment_liked_dn.xml b/app/src/main/res/drawable/essay_comment_liked_dn.xml new file mode 100644 index 0000000000..941b24f0d0 --- /dev/null +++ b/app/src/main/res/drawable/essay_comment_liked_dn.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/essay_comment_liked_style.xml b/app/src/main/res/drawable/essay_comment_liked_style.xml new file mode 100644 index 0000000000..7788171023 --- /dev/null +++ b/app/src/main/res/drawable/essay_comment_liked_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/essay_comment_liked_up.xml b/app/src/main/res/drawable/essay_comment_liked_up.xml new file mode 100644 index 0000000000..638a2a9ebe --- /dev/null +++ b/app/src/main/res/drawable/essay_comment_liked_up.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/essay_comment_unliked_dn.xml b/app/src/main/res/drawable/essay_comment_unliked_dn.xml new file mode 100644 index 0000000000..c834427e2a --- /dev/null +++ b/app/src/main/res/drawable/essay_comment_unliked_dn.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/essay_comment_unliked_style.xml b/app/src/main/res/drawable/essay_comment_unliked_style.xml new file mode 100644 index 0000000000..1cf824b619 --- /dev/null +++ b/app/src/main/res/drawable/essay_comment_unliked_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/essay_comment_unliked_up.xml b/app/src/main/res/drawable/essay_comment_unliked_up.xml new file mode 100644 index 0000000000..5dc0e62a85 --- /dev/null +++ b/app/src/main/res/drawable/essay_comment_unliked_up.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/essay_like_style.xml b/app/src/main/res/drawable/essay_like_style.xml new file mode 100644 index 0000000000..3cdc684d7f --- /dev/null +++ b/app/src/main/res/drawable/essay_like_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/essay_liked_dn.xml b/app/src/main/res/drawable/essay_liked_dn.xml new file mode 100644 index 0000000000..101ecbfd26 --- /dev/null +++ b/app/src/main/res/drawable/essay_liked_dn.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/essay_liked_style.xml b/app/src/main/res/drawable/essay_liked_style.xml new file mode 100644 index 0000000000..fbee634616 --- /dev/null +++ b/app/src/main/res/drawable/essay_liked_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/essay_liked_up.xml b/app/src/main/res/drawable/essay_liked_up.xml new file mode 100644 index 0000000000..9b421949cd --- /dev/null +++ b/app/src/main/res/drawable/essay_liked_up.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/essay_text_style.xml b/app/src/main/res/drawable/essay_text_style.xml new file mode 100644 index 0000000000..698c49ef92 --- /dev/null +++ b/app/src/main/res/drawable/essay_text_style.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/essay_unlike_style.xml b/app/src/main/res/drawable/essay_unlike_style.xml new file mode 100644 index 0000000000..fdda7ba0d0 --- /dev/null +++ b/app/src/main/res/drawable/essay_unlike_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/essay_unliked_dn.xml b/app/src/main/res/drawable/essay_unliked_dn.xml new file mode 100644 index 0000000000..fc7d73f27f --- /dev/null +++ b/app/src/main/res/drawable/essay_unliked_dn.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/essay_unliked_style.xml b/app/src/main/res/drawable/essay_unliked_style.xml new file mode 100644 index 0000000000..c61641e29e --- /dev/null +++ b/app/src/main/res/drawable/essay_unliked_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/essay_unliked_up.xml b/app/src/main/res/drawable/essay_unliked_up.xml new file mode 100644 index 0000000000..5a1676017e --- /dev/null +++ b/app/src/main/res/drawable/essay_unliked_up.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/gridview_bg.xml b/app/src/main/res/drawable/gridview_bg.xml new file mode 100644 index 0000000000..c533e23bb2 --- /dev/null +++ b/app/src/main/res/drawable/gridview_bg.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/login_auto_style.xml b/app/src/main/res/drawable/login_auto_style.xml new file mode 100644 index 0000000000..c1e1578992 --- /dev/null +++ b/app/src/main/res/drawable/login_auto_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/md_back_off.xml b/app/src/main/res/drawable/md_back_off.xml new file mode 100644 index 0000000000..20d2fb1460 --- /dev/null +++ b/app/src/main/res/drawable/md_back_off.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/md_back_on.xml b/app/src/main/res/drawable/md_back_on.xml new file mode 100644 index 0000000000..b27326c1ea --- /dev/null +++ b/app/src/main/res/drawable/md_back_on.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/md_thumb.xml b/app/src/main/res/drawable/md_thumb.xml new file mode 100644 index 0000000000..7fde43d6e5 --- /dev/null +++ b/app/src/main/res/drawable/md_thumb.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/oval_gray_bg.xml b/app/src/main/res/drawable/oval_gray_bg.xml new file mode 100644 index 0000000000..34774f7b7a --- /dev/null +++ b/app/src/main/res/drawable/oval_gray_bg.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/oval_hint_dn.xml b/app/src/main/res/drawable/oval_hint_dn.xml new file mode 100644 index 0000000000..2a2ab04bbb --- /dev/null +++ b/app/src/main/res/drawable/oval_hint_dn.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/oval_hint_gray_bg.xml b/app/src/main/res/drawable/oval_hint_gray_bg.xml new file mode 100644 index 0000000000..bb16f3cfab --- /dev/null +++ b/app/src/main/res/drawable/oval_hint_gray_bg.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/oval_hint_red_bg.xml b/app/src/main/res/drawable/oval_hint_red_bg.xml new file mode 100644 index 0000000000..fc203d2815 --- /dev/null +++ b/app/src/main/res/drawable/oval_hint_red_bg.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/oval_hint_up.xml b/app/src/main/res/drawable/oval_hint_up.xml new file mode 100644 index 0000000000..e7a77aea5b --- /dev/null +++ b/app/src/main/res/drawable/oval_hint_up.xml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/oval_orange_bg.xml b/app/src/main/res/drawable/oval_orange_bg.xml new file mode 100644 index 0000000000..afe63fbd51 --- /dev/null +++ b/app/src/main/res/drawable/oval_orange_bg.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/oval_scarlet_bg.xml b/app/src/main/res/drawable/oval_scarlet_bg.xml new file mode 100644 index 0000000000..1e8a0b4675 --- /dev/null +++ b/app/src/main/res/drawable/oval_scarlet_bg.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/oval_search_bg.xml b/app/src/main/res/drawable/oval_search_bg.xml new file mode 100644 index 0000000000..6e7663beef --- /dev/null +++ b/app/src/main/res/drawable/oval_search_bg.xml @@ -0,0 +1,12 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/progressbar_bg_style.xml b/app/src/main/res/drawable/progressbar_bg_style.xml new file mode 100644 index 0000000000..96f9569aa0 --- /dev/null +++ b/app/src/main/res/drawable/progressbar_bg_style.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/progressbar_normal_radius_style.xml b/app/src/main/res/drawable/progressbar_normal_radius_style.xml new file mode 100644 index 0000000000..3eaa4af658 --- /dev/null +++ b/app/src/main/res/drawable/progressbar_normal_radius_style.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/progressbar_normal_style.xml b/app/src/main/res/drawable/progressbar_normal_style.xml new file mode 100644 index 0000000000..e5d009a356 --- /dev/null +++ b/app/src/main/res/drawable/progressbar_normal_style.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/reuse_listview_item_style.xml b/app/src/main/res/drawable/reuse_listview_item_style.xml new file mode 100644 index 0000000000..3819be1a69 --- /dev/null +++ b/app/src/main/res/drawable/reuse_listview_item_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/reuse_textview_normal_style.xml b/app/src/main/res/drawable/reuse_textview_normal_style.xml new file mode 100644 index 0000000000..3819be1a69 --- /dev/null +++ b/app/src/main/res/drawable/reuse_textview_normal_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/reuse_textview_style.xml b/app/src/main/res/drawable/reuse_textview_style.xml new file mode 100644 index 0000000000..b15ad8b9a2 --- /dev/null +++ b/app/src/main/res/drawable/reuse_textview_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape.xml b/app/src/main/res/drawable/shape.xml new file mode 100644 index 0000000000..9405f1297f --- /dev/null +++ b/app/src/main/res/drawable/shape.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/app/src/main/res/drawable/skyblue_platform_list_item.xml b/app/src/main/res/drawable/skyblue_platform_list_item.xml new file mode 100644 index 0000000000..03aa297d9d --- /dev/null +++ b/app/src/main/res/drawable/skyblue_platform_list_item.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/skyblue_platform_list_item_selected.xml b/app/src/main/res/drawable/skyblue_platform_list_item_selected.xml new file mode 100644 index 0000000000..7fad5d1dab --- /dev/null +++ b/app/src/main/res/drawable/skyblue_platform_list_item_selected.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/skyblue_platform_list_selector.xml b/app/src/main/res/drawable/skyblue_platform_list_selector.xml new file mode 100644 index 0000000000..b06e6995aa --- /dev/null +++ b/app/src/main/res/drawable/skyblue_platform_list_selector.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_again_dn.xml b/app/src/main/res/drawable/textview_again_dn.xml new file mode 100644 index 0000000000..e02b8abb40 --- /dev/null +++ b/app/src/main/res/drawable/textview_again_dn.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_again_style.xml b/app/src/main/res/drawable/textview_again_style.xml new file mode 100644 index 0000000000..6d6f8a7c01 --- /dev/null +++ b/app/src/main/res/drawable/textview_again_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_again_up.xml b/app/src/main/res/drawable/textview_again_up.xml new file mode 100644 index 0000000000..627f92f4f3 --- /dev/null +++ b/app/src/main/res/drawable/textview_again_up.xml @@ -0,0 +1,11 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_blue_dn.xml b/app/src/main/res/drawable/textview_blue_dn.xml new file mode 100644 index 0000000000..6ebdd1fabc --- /dev/null +++ b/app/src/main/res/drawable/textview_blue_dn.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_blue_style.xml b/app/src/main/res/drawable/textview_blue_style.xml new file mode 100644 index 0000000000..cbce625193 --- /dev/null +++ b/app/src/main/res/drawable/textview_blue_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_blue_up.xml b/app/src/main/res/drawable/textview_blue_up.xml new file mode 100644 index 0000000000..22326d4a15 --- /dev/null +++ b/app/src/main/res/drawable/textview_blue_up.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_cancel_dn.xml b/app/src/main/res/drawable/textview_cancel_dn.xml new file mode 100644 index 0000000000..5b32b83bf6 --- /dev/null +++ b/app/src/main/res/drawable/textview_cancel_dn.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_cancel_style.xml b/app/src/main/res/drawable/textview_cancel_style.xml new file mode 100644 index 0000000000..e7a36deaa5 --- /dev/null +++ b/app/src/main/res/drawable/textview_cancel_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_cancel_up.xml b/app/src/main/res/drawable/textview_cancel_up.xml new file mode 100644 index 0000000000..e3eb1d8910 --- /dev/null +++ b/app/src/main/res/drawable/textview_cancel_up.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_color_style.xml b/app/src/main/res/drawable/textview_color_style.xml new file mode 100644 index 0000000000..b51c055cad --- /dev/null +++ b/app/src/main/res/drawable/textview_color_style.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_gray_dn.xml b/app/src/main/res/drawable/textview_gray_dn.xml new file mode 100644 index 0000000000..4fdfe11d7e --- /dev/null +++ b/app/src/main/res/drawable/textview_gray_dn.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_gray_style.xml b/app/src/main/res/drawable/textview_gray_style.xml new file mode 100644 index 0000000000..7252804735 --- /dev/null +++ b/app/src/main/res/drawable/textview_gray_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_gray_up.xml b/app/src/main/res/drawable/textview_gray_up.xml new file mode 100644 index 0000000000..5dbdfd7ca6 --- /dev/null +++ b/app/src/main/res/drawable/textview_gray_up.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_green_dn.xml b/app/src/main/res/drawable/textview_green_dn.xml new file mode 100644 index 0000000000..fd763b282a --- /dev/null +++ b/app/src/main/res/drawable/textview_green_dn.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_green_style.xml b/app/src/main/res/drawable/textview_green_style.xml new file mode 100644 index 0000000000..d4fb65001c --- /dev/null +++ b/app/src/main/res/drawable/textview_green_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_green_up.xml b/app/src/main/res/drawable/textview_green_up.xml new file mode 100644 index 0000000000..632276c61b --- /dev/null +++ b/app/src/main/res/drawable/textview_green_up.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_login_dn.xml b/app/src/main/res/drawable/textview_login_dn.xml new file mode 100644 index 0000000000..1c03446c46 --- /dev/null +++ b/app/src/main/res/drawable/textview_login_dn.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_login_style.xml b/app/src/main/res/drawable/textview_login_style.xml new file mode 100644 index 0000000000..bc8e432339 --- /dev/null +++ b/app/src/main/res/drawable/textview_login_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_login_up.xml b/app/src/main/res/drawable/textview_login_up.xml new file mode 100644 index 0000000000..7fbe84f9bc --- /dev/null +++ b/app/src/main/res/drawable/textview_login_up.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_logout_dn.xml b/app/src/main/res/drawable/textview_logout_dn.xml new file mode 100644 index 0000000000..fbf4aedbbc --- /dev/null +++ b/app/src/main/res/drawable/textview_logout_dn.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_logout_style.xml b/app/src/main/res/drawable/textview_logout_style.xml new file mode 100644 index 0000000000..8760069a0a --- /dev/null +++ b/app/src/main/res/drawable/textview_logout_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_logout_up.xml b/app/src/main/res/drawable/textview_logout_up.xml new file mode 100644 index 0000000000..b967889047 --- /dev/null +++ b/app/src/main/res/drawable/textview_logout_up.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_onekey_register_dn.xml b/app/src/main/res/drawable/textview_onekey_register_dn.xml new file mode 100644 index 0000000000..b967889047 --- /dev/null +++ b/app/src/main/res/drawable/textview_onekey_register_dn.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_onekey_register_style.xml b/app/src/main/res/drawable/textview_onekey_register_style.xml new file mode 100644 index 0000000000..446db3919c --- /dev/null +++ b/app/src/main/res/drawable/textview_onekey_register_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_onekey_register_up.xml b/app/src/main/res/drawable/textview_onekey_register_up.xml new file mode 100644 index 0000000000..9b7bb0fcda --- /dev/null +++ b/app/src/main/res/drawable/textview_onekey_register_up.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_orange_dn.xml b/app/src/main/res/drawable/textview_orange_dn.xml new file mode 100644 index 0000000000..2062580199 --- /dev/null +++ b/app/src/main/res/drawable/textview_orange_dn.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_orange_style.xml b/app/src/main/res/drawable/textview_orange_style.xml new file mode 100644 index 0000000000..19f9d50b85 --- /dev/null +++ b/app/src/main/res/drawable/textview_orange_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_orange_up.xml b/app/src/main/res/drawable/textview_orange_up.xml new file mode 100644 index 0000000000..09ec5d8531 --- /dev/null +++ b/app/src/main/res/drawable/textview_orange_up.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_red_dn.xml b/app/src/main/res/drawable/textview_red_dn.xml new file mode 100644 index 0000000000..2e27ca8a3f --- /dev/null +++ b/app/src/main/res/drawable/textview_red_dn.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_red_style.xml b/app/src/main/res/drawable/textview_red_style.xml new file mode 100644 index 0000000000..5e1be27960 --- /dev/null +++ b/app/src/main/res/drawable/textview_red_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_red_up.xml b/app/src/main/res/drawable/textview_red_up.xml new file mode 100644 index 0000000000..14e1d3dc05 --- /dev/null +++ b/app/src/main/res/drawable/textview_red_up.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_register_bg.xml b/app/src/main/res/drawable/textview_register_bg.xml new file mode 100644 index 0000000000..b967889047 --- /dev/null +++ b/app/src/main/res/drawable/textview_register_bg.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_search_dn.xml b/app/src/main/res/drawable/textview_search_dn.xml new file mode 100644 index 0000000000..819d3afc41 --- /dev/null +++ b/app/src/main/res/drawable/textview_search_dn.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_search_style.xml b/app/src/main/res/drawable/textview_search_style.xml new file mode 100644 index 0000000000..0507583d02 --- /dev/null +++ b/app/src/main/res/drawable/textview_search_style.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_search_up.xml b/app/src/main/res/drawable/textview_search_up.xml new file mode 100644 index 0000000000..e342ab2430 --- /dev/null +++ b/app/src/main/res/drawable/textview_search_up.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_account.xml b/app/src/main/res/layout/activity_account.xml new file mode 100644 index 0000000000..b963e52ce3 --- /dev/null +++ b/app/src/main/res/layout/activity_account.xml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_concern.xml b/app/src/main/res/layout/activity_concern.xml new file mode 100644 index 0000000000..1d27453951 --- /dev/null +++ b/app/src/main/res/layout/activity_concern.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_cropimage.xml b/app/src/main/res/layout/activity_cropimage.xml new file mode 100644 index 0000000000..b4f53084bf --- /dev/null +++ b/app/src/main/res/layout/activity_cropimage.xml @@ -0,0 +1,15 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_database.xml b/app/src/main/res/layout/activity_database.xml new file mode 100644 index 0000000000..134ab6fe3b --- /dev/null +++ b/app/src/main/res/layout/activity_database.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + \ 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 new file mode 100644 index 0000000000..91df20e01b --- /dev/null +++ b/app/src/main/res/layout/activity_downloadmanager.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_essaydetails.xml b/app/src/main/res/layout/activity_essaydetails.xml new file mode 100644 index 0000000000..57fbc5a9ca --- /dev/null +++ b/app/src/main/res/layout/activity_essaydetails.xml @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_game.xml b/app/src/main/res/layout/activity_game.xml new file mode 100644 index 0000000000..ab6ed6a52f --- /dev/null +++ b/app/src/main/res/layout/activity_game.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_gamedetails.xml b/app/src/main/res/layout/activity_gamedetails.xml new file mode 100644 index 0000000000..ee54b4c1ee --- /dev/null +++ b/app/src/main/res/layout/activity_gamedetails.xml @@ -0,0 +1,297 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_hotcard.xml b/app/src/main/res/layout/activity_hotcard.xml new file mode 100644 index 0000000000..0b69bed99f --- /dev/null +++ b/app/src/main/res/layout/activity_hotcard.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000000..154bf47d40 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_mobile.xml b/app/src/main/res/layout/activity_mobile.xml new file mode 100644 index 0000000000..a94583ef26 --- /dev/null +++ b/app/src/main/res/layout/activity_mobile.xml @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_modifymobile.xml b/app/src/main/res/layout/activity_modifymobile.xml new file mode 100644 index 0000000000..e6a1d76eeb --- /dev/null +++ b/app/src/main/res/layout/activity_modifymobile.xml @@ -0,0 +1,242 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_news_or_raiders.xml b/app/src/main/res/layout/activity_news_or_raiders.xml new file mode 100644 index 0000000000..22cd5e395e --- /dev/null +++ b/app/src/main/res/layout/activity_news_or_raiders.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_password.xml b/app/src/main/res/layout/activity_password.xml new file mode 100644 index 0000000000..35cc662c30 --- /dev/null +++ b/app/src/main/res/layout/activity_password.xml @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_plugin.xml b/app/src/main/res/layout/activity_plugin.xml new file mode 100644 index 0000000000..9487030cd0 --- /dev/null +++ b/app/src/main/res/layout/activity_plugin.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_retrieve.xml b/app/src/main/res/layout/activity_retrieve.xml new file mode 100644 index 0000000000..d12135a73c --- /dev/null +++ b/app/src/main/res/layout/activity_retrieve.xml @@ -0,0 +1,275 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search.xml b/app/src/main/res/layout/activity_search.xml new file mode 100644 index 0000000000..8387bea411 --- /dev/null +++ b/app/src/main/res/layout/activity_search.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_setting.xml b/app/src/main/res/layout/activity_setting.xml new file mode 100644 index 0000000000..29a96f0c39 --- /dev/null +++ b/app/src/main/res/layout/activity_setting.xml @@ -0,0 +1,224 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml new file mode 100644 index 0000000000..80e487e098 --- /dev/null +++ b/app/src/main/res/layout/activity_splash.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_suggest.xml b/app/src/main/res/layout/activity_suggest.xml new file mode 100644 index 0000000000..257d2c53f1 --- /dev/null +++ b/app/src/main/res/layout/activity_suggest.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_userinfo.xml b/app/src/main/res/layout/activity_userinfo.xml new file mode 100644 index 0000000000..12657322b1 --- /dev/null +++ b/app/src/main/res/layout/activity_userinfo.xml @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_viewimage.xml b/app/src/main/res/layout/activity_viewimage.xml new file mode 100644 index 0000000000..e8fbcf66df --- /dev/null +++ b/app/src/main/res/layout/activity_viewimage.xml @@ -0,0 +1,22 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/app_updating_dialog.xml b/app/src/main/res/layout/app_updating_dialog.xml new file mode 100644 index 0000000000..300ac77005 --- /dev/null +++ b/app/src/main/res/layout/app_updating_dialog.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/concern_item.xml b/app/src/main/res/layout/concern_item.xml new file mode 100644 index 0000000000..32a5043960 --- /dev/null +++ b/app/src/main/res/layout/concern_item.xml @@ -0,0 +1,45 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/datebase_item.xml b/app/src/main/res/layout/datebase_item.xml new file mode 100644 index 0000000000..88cca0ac2b --- /dev/null +++ b/app/src/main/res/layout/datebase_item.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_account_login.xml b/app/src/main/res/layout/dialog_account_login.xml new file mode 100644 index 0000000000..cb94292c1e --- /dev/null +++ b/app/src/main/res/layout/dialog_account_login.xml @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_account_register.xml b/app/src/main/res/layout/dialog_account_register.xml new file mode 100644 index 0000000000..241380cfaf --- /dev/null +++ b/app/src/main/res/layout/dialog_account_register.xml @@ -0,0 +1,208 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_code.xml b/app/src/main/res/layout/dialog_code.xml new file mode 100644 index 0000000000..03d5c09a9a --- /dev/null +++ b/app/src/main/res/layout/dialog_code.xml @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_essay_comment.xml b/app/src/main/res/layout/dialog_essay_comment.xml new file mode 100644 index 0000000000..bc8814dc29 --- /dev/null +++ b/app/src/main/res/layout/dialog_essay_comment.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_mobile_login.xml b/app/src/main/res/layout/dialog_mobile_login.xml new file mode 100644 index 0000000000..db538cb43d --- /dev/null +++ b/app/src/main/res/layout/dialog_mobile_login.xml @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_modify_nickname.xml b/app/src/main/res/layout/dialog_modify_nickname.xml new file mode 100644 index 0000000000..3df0caa050 --- /dev/null +++ b/app/src/main/res/layout/dialog_modify_nickname.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_modify_select.xml b/app/src/main/res/layout/dialog_modify_select.xml new file mode 100644 index 0000000000..dd5b514618 --- /dev/null +++ b/app/src/main/res/layout/dialog_modify_select.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_modify_sign.xml b/app/src/main/res/layout/dialog_modify_sign.xml new file mode 100644 index 0000000000..a30f4f89ae --- /dev/null +++ b/app/src/main/res/layout/dialog_modify_sign.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_nickname.xml b/app/src/main/res/layout/dialog_nickname.xml new file mode 100644 index 0000000000..4ef5a4125d --- /dev/null +++ b/app/src/main/res/layout/dialog_nickname.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_onekey_register.xml b/app/src/main/res/layout/dialog_onekey_register.xml new file mode 100644 index 0000000000..fd5e5aeea1 --- /dev/null +++ b/app/src/main/res/layout/dialog_onekey_register.xml @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_update_download.xml b/app/src/main/res/layout/dialog_update_download.xml new file mode 100644 index 0000000000..fb10e1e122 --- /dev/null +++ b/app/src/main/res/layout/dialog_update_download.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_update_info.xml b/app/src/main/res/layout/dialog_update_info.xml new file mode 100644 index 0000000000..52cd56a391 --- /dev/null +++ b/app/src/main/res/layout/dialog_update_info.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/downloadmanager.xml b/app/src/main/res/layout/downloadmanager.xml new file mode 100644 index 0000000000..70526a315b --- /dev/null +++ b/app/src/main/res/layout/downloadmanager.xml @@ -0,0 +1,24 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/downloadmanager_item.xml b/app/src/main/res/layout/downloadmanager_item.xml new file mode 100644 index 0000000000..41b638eee7 --- /dev/null +++ b/app/src/main/res/layout/downloadmanager_item.xml @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/downloadmanager_item_top.xml b/app/src/main/res/layout/downloadmanager_item_top.xml new file mode 100644 index 0000000000..d9c07d0580 --- /dev/null +++ b/app/src/main/res/layout/downloadmanager_item_top.xml @@ -0,0 +1,29 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/essaydetails_comment_evaluate.xml b/app/src/main/res/layout/essaydetails_comment_evaluate.xml new file mode 100644 index 0000000000..922dc0f082 --- /dev/null +++ b/app/src/main/res/layout/essaydetails_comment_evaluate.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/essaydetails_comment_item.xml b/app/src/main/res/layout/essaydetails_comment_item.xml new file mode 100644 index 0000000000..c7703aacce --- /dev/null +++ b/app/src/main/res/layout/essaydetails_comment_item.xml @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/essaydetails_item_top.xml b/app/src/main/res/layout/essaydetails_item_top.xml new file mode 100644 index 0000000000..906a913259 --- /dev/null +++ b/app/src/main/res/layout/essaydetails_item_top.xml @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/essaydetails_more_news_item.xml b/app/src/main/res/layout/essaydetails_more_news_item.xml new file mode 100644 index 0000000000..35ded82626 --- /dev/null +++ b/app/src/main/res/layout/essaydetails_more_news_item.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/game_download_dialog.xml b/app/src/main/res/layout/game_download_dialog.xml new file mode 100644 index 0000000000..8e313dfbe4 --- /dev/null +++ b/app/src/main/res/layout/game_download_dialog.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/game_download_item.xml b/app/src/main/res/layout/game_download_item.xml new file mode 100644 index 0000000000..77ad664b9d --- /dev/null +++ b/app/src/main/res/layout/game_download_item.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/game_item.xml b/app/src/main/res/layout/game_item.xml new file mode 100644 index 0000000000..478d1af98a --- /dev/null +++ b/app/src/main/res/layout/game_item.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + +