Compare commits
157 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 62efcef486 | |||
| 0e10b3e50f | |||
| 1c05b322e4 | |||
| 9a6bbc7e43 | |||
| 3f0347c2a8 | |||
| 01cd24d2ba | |||
| dbbeff14ae | |||
| 2631d7136c | |||
| ee43e522f8 | |||
| 8c4967abc4 | |||
| 8dd069b38d | |||
| 1160fb999e | |||
| 948329f79e | |||
| a61ef37a22 | |||
| 66e8de06f0 | |||
| b5c3daea0c | |||
| ba70ecc063 | |||
| 3b1145133a | |||
| 3e0e4caa0c | |||
| a55a969588 | |||
| 8b46435808 | |||
| 1a6966e522 | |||
| 2fcee4cea0 | |||
| 223b7c6069 | |||
| 771946918a | |||
| d7e113108b | |||
| e3d9fac1b0 | |||
| 7c78109bf2 | |||
| b7ccf66418 | |||
| 8c5265f9b5 | |||
| e81bbf5195 | |||
| f219b62fcc | |||
| 6347260522 | |||
| 9fe80cfb66 | |||
| 62975e5e1b | |||
| 9b4e62149f | |||
| 8643a12744 | |||
| 9369218821 | |||
| 0c1b48cee2 | |||
| 5865fdbd23 | |||
| 6b5fe82d47 | |||
| 49624d5afd | |||
| a92de9ffa0 | |||
| d4133cc51d | |||
| 611068a9b0 | |||
| 7930ecaea9 | |||
| 3c72080802 | |||
| 4c762a1aa8 | |||
| 4f99477d83 | |||
| 6d4de6795e | |||
| 4f8b93cb6a | |||
| 48a4aefe96 | |||
| dc530be9be | |||
| bb5e9e739b | |||
| 7264249ef8 | |||
| 5eb5f6807e | |||
| 8bb50a6e2c | |||
| 7b7987b574 | |||
| a209edc181 | |||
| e744a475c3 | |||
| b280e1bf89 | |||
| decb763a5f | |||
| 28f685ae10 | |||
| 6270d59f3f | |||
| 11c6f33392 | |||
| a75b613744 | |||
| ccca070dd2 | |||
| bd2ce2e82d | |||
| a88c920ef0 | |||
| 6aee2ae6b9 | |||
| 0ec14da2ac | |||
| 375f538bc1 | |||
| 1c6907373b | |||
| 64fe9048f0 | |||
| c96193b3d0 | |||
| b1035c24bc | |||
| d69e75480e | |||
| 4da12055e9 | |||
| 7ca9272fe7 | |||
| 5f0bf827ae | |||
| 87cd020e94 | |||
| 4fd7095fbf | |||
| c1ebcf33e5 | |||
| d0f72a8d96 | |||
| 6e5ac76b52 | |||
| 8ae3b93307 | |||
| 7246e06973 | |||
| 0ae824b9f5 | |||
| deee22b6db | |||
| c8e01182f4 | |||
| dec6bd6779 | |||
| b00b791107 | |||
| 4db2b1cc29 | |||
| 471ebb3b6e | |||
| e057b6530b | |||
| b5328324f8 | |||
| 18aa853948 | |||
| c8559bd36a | |||
| b71e717da1 | |||
| 60677b36f6 | |||
| 339d32b1dd | |||
| 9432e34571 | |||
| 153f33f44b | |||
| fc2f20ee6e | |||
| cfa70feac5 | |||
| 6a851f7247 | |||
| a0cae1b7b8 | |||
| 5798ba9e89 | |||
| 919e3c386d | |||
| e85bb40904 | |||
| d23a2df809 | |||
| b9185cce15 | |||
| c14605b598 | |||
| 68c2f3c754 | |||
| 2725a59826 | |||
| 9ef8f5d1f2 | |||
| 39cd66032d | |||
| ee53e7218f | |||
| 72a1cded27 | |||
| 3295b6a7b7 | |||
| 4f64325f2b | |||
| de9c9cbdcb | |||
| 1fe9e259b4 | |||
| 6b4f68128b | |||
| 8b637fbeec | |||
| 7267535ccf | |||
| 8f99987696 | |||
| 515473e5dc | |||
| 8b83e939ce | |||
| c71bd36de2 | |||
| 9fdc8f0da3 | |||
| 8ba099024e | |||
| e656acec1d | |||
| 6fa4994e04 | |||
| a929706219 | |||
| 62effd1cc1 | |||
| 417b597d1d | |||
| 2fabb9013a | |||
| 835dcc6446 | |||
| fba0a6ec71 | |||
| 9a2f4c984c | |||
| d870e68001 | |||
| 8e7fcfb746 | |||
| a995e132f3 | |||
| 6b9921c5a7 | |||
| 75695812ee | |||
| eae0414cb4 | |||
| 7b203bedfc | |||
| da20b817d2 | |||
| ef1f2251b5 | |||
| c907835ce7 | |||
| 3be623dd63 | |||
| 045c1e0305 | |||
| c292e79d94 | |||
| cb54d87daf | |||
| a29c0bd466 | |||
| 575ba33e43 |
13
.gitignore
vendored
13
.gitignore
vendored
@ -1,9 +1,8 @@
|
||||
/.idea
|
||||
.idea/misc.xml
|
||||
.idea/
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
.gradle/
|
||||
local.properties
|
||||
# sign.properties
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
/PushSDK/build
|
||||
captures/
|
||||
build/
|
||||
@ -1,147 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.umeng.message.lib"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_ADDED" />
|
||||
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_CHANGED" />
|
||||
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_INSTALL" />
|
||||
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_REPLACED" />
|
||||
<uses-permission android:name="android.permission.RESTART_PACKAGES" />
|
||||
<uses-permission android:name="android.permission.GET_TASKS" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
||||
|
||||
<application>
|
||||
|
||||
<service
|
||||
android:name="com.taobao.accs.ChannelService"
|
||||
android:exported="true"
|
||||
android:process=":channel">
|
||||
<intent-filter>
|
||||
<action android:name="com.taobao.accs.intent.action.SERVICE" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.taobao.accs.intent.action.ELECTION" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name="com.taobao.accs.data.MsgDistributeService"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.taobao.accs.intent.action.RECEIVE" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<receiver
|
||||
android:name="com.taobao.accs.EventReceiver"
|
||||
android:process=":channel">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.PACKAGE_REMOVED" />
|
||||
<data android:scheme="package" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.USER_PRESENT" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name="com.taobao.accs.ServiceReceiver"
|
||||
android:exported="false"
|
||||
android:process=":channel">
|
||||
<intent-filter>
|
||||
<action android:name="com.taobao.accs.intent.action.COMMAND" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.taobao.accs.intent.action.START_FROM_AGOO" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service
|
||||
android:name="com.taobao.accs.ChannelService$KernelService"
|
||||
android:process=":channel">
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name="org.android.agoo.accs.AgooService"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.taobao.accs.intent.action.RECEIVE" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<service android:name="com.umeng.message.UmengIntentService"
|
||||
android:exported="true"
|
||||
android:process=":channel">
|
||||
<intent-filter>
|
||||
<action android:name="org.agoo.android.intent.action.RECEIVE" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<receiver
|
||||
android:name="com.taobao.agoo.AgooCommondReceiver"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.gh.gamecenter.intent.action.COMMAND" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.PACKAGE_REMOVED" />
|
||||
<data android:scheme="package" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name="com.umeng.message.NotificationProxyBroadcastReceiver"
|
||||
android:exported="false" />
|
||||
<service
|
||||
android:name="com.umeng.message.UmengMessageCallbackHandlerService"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.umeng.messge.registercallback.action" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.umeng.message.enablecallback.action" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.umeng.message.disablecallback.action" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.umeng.message.message.handler.action" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name="com.umeng.message.UmengDownloadResourceService"
|
||||
android:exported="false" />
|
||||
<service
|
||||
android:name="com.umeng.message.UmengMessageIntentReceiverService"
|
||||
android:exported="true"
|
||||
android:process=":channel" >
|
||||
<intent-filter>
|
||||
<action android:name="org.android.agoo.client.MessageReceiverService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
<provider
|
||||
android:name="com.umeng.message.provider.MessageProvider"
|
||||
android:authorities="com.gh.gamecenter.umeng.message"
|
||||
android:exported="false">
|
||||
<grant-uri-permission android:pathPattern=".*" />
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@ -1,51 +0,0 @@
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 22
|
||||
buildToolsVersion "23.0.2"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 11
|
||||
targetSdkVersion 22
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
||||
}
|
||||
debug {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
manifest.srcFile 'AndroidManifest.xml'
|
||||
java.srcDirs = ['src']
|
||||
resources.srcDirs = ['src']
|
||||
aidl.srcDirs = ['src']
|
||||
renderscript.srcDirs = ['src']
|
||||
res.srcDirs = ['res']
|
||||
assets.srcDirs = ['assets']
|
||||
jniLibs.srcDirs = ['libs']
|
||||
}
|
||||
|
||||
// Move the tests to tests/java, tests/res, etc...
|
||||
instrumentTest.setRoot('tests')
|
||||
|
||||
// Move the build types to build-types/<type>
|
||||
// For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
|
||||
// This moves them out of them default location under src/<type>/... which would
|
||||
// conflict with src/ being used by the main source set.
|
||||
// Adding new build types or product flavors should be accompanied
|
||||
// by a similar customization.
|
||||
debug.setRoot('build-types/debug')
|
||||
release.setRoot('build-types/release')
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
}
|
||||
@ -1,156 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.umeng.message.lib.test" >
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="11"
|
||||
android:targetSdkVersion="22" />
|
||||
|
||||
<instrumentation
|
||||
android:name="android.test.InstrumentationTestRunner"
|
||||
android:functionalTest="false"
|
||||
android:handleProfiling="false"
|
||||
android:label="Tests for com.umeng.message.lib.test"
|
||||
android:targetPackage="com.umeng.message.lib.test" />
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_ADDED" />
|
||||
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_CHANGED" />
|
||||
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_INSTALL" />
|
||||
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_REPLACED" />
|
||||
<uses-permission android:name="android.permission.RESTART_PACKAGES" />
|
||||
<uses-permission android:name="android.permission.GET_TASKS" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||
|
||||
<application>
|
||||
<uses-library android:name="android.test.runner" />
|
||||
|
||||
<service
|
||||
android:name="com.taobao.accs.ChannelService"
|
||||
android:exported="true"
|
||||
android:process=":channel" >
|
||||
<intent-filter>
|
||||
<action android:name="com.taobao.accs.intent.action.SERVICE" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.taobao.accs.intent.action.ELECTION" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
<service
|
||||
android:name="com.taobao.accs.data.MsgDistributeService"
|
||||
android:exported="true" >
|
||||
<intent-filter>
|
||||
<action android:name="com.taobao.accs.intent.action.RECEIVE" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<receiver
|
||||
android:name="com.taobao.accs.EventReceiver"
|
||||
android:process=":channel" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.PACKAGE_REMOVED" />
|
||||
|
||||
<data android:scheme="package" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.USER_PRESENT" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name="com.taobao.accs.ServiceReceiver"
|
||||
android:exported="false"
|
||||
android:process=":channel" >
|
||||
<intent-filter>
|
||||
<action android:name="com.taobao.accs.intent.action.COMMAND" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.taobao.accs.intent.action.START_FROM_AGOO" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service
|
||||
android:name="com.taobao.accs.ChannelService$KernelService"
|
||||
android:process=":channel" >
|
||||
</service>
|
||||
<service
|
||||
android:name="org.android.agoo.accs.AgooService"
|
||||
android:exported="true" >
|
||||
<intent-filter>
|
||||
<action android:name="com.taobao.accs.intent.action.RECEIVE" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
<service
|
||||
android:name="com.umeng.message.UmengIntentService"
|
||||
android:exported="true"
|
||||
android:process=":channel" >
|
||||
<intent-filter>
|
||||
<action android:name="org.agoo.android.intent.action.RECEIVE" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<receiver
|
||||
android:name="com.taobao.agoo.AgooCommondReceiver"
|
||||
android:exported="true" >
|
||||
<intent-filter>
|
||||
<action android:name="com.gh.gamecenter.intent.action.COMMAND" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.PACKAGE_REMOVED" />
|
||||
|
||||
<data android:scheme="package" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name="com.umeng.message.NotificationProxyBroadcastReceiver"
|
||||
android:exported="false" />
|
||||
|
||||
<service
|
||||
android:name="com.umeng.message.UmengMessageCallbackHandlerService"
|
||||
android:exported="false" >
|
||||
<intent-filter>
|
||||
<action android:name="com.umeng.messge.registercallback.action" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.umeng.message.enablecallback.action" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.umeng.message.disablecallback.action" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.umeng.message.message.handler.action" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
<service
|
||||
android:name="com.umeng.message.UmengDownloadResourceService"
|
||||
android:exported="false" />
|
||||
<service
|
||||
android:name="com.umeng.message.UmengMessageIntentReceiverService"
|
||||
android:exported="true"
|
||||
android:process=":channel" >
|
||||
<intent-filter>
|
||||
<action android:name="org.android.agoo.client.MessageReceiverService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<provider
|
||||
android:name="com.umeng.message.provider.MessageProvider"
|
||||
android:authorities="com.gh.gamecenter.umeng.message"
|
||||
android:exported="false" >
|
||||
<grant-uri-permission android:pathPattern=".*" />
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
Binary file not shown.
Binary file not shown.
@ -1,12 +0,0 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system use,
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
|
||||
# Project target.
|
||||
target=android-19
|
||||
android.library=true
|
||||
23
README.md
Normal file
23
README.md
Normal file
@ -0,0 +1,23 @@
|
||||
# 光环助手Android客户端
|
||||
|
||||
### 多渠道打包配置
|
||||
* 使用[ApkChannelPackage](https://github.com/ltlovezh/ApkChannelPackage)的方案
|
||||
|
||||
* 正式打包命令:请使用./gradlew channelPubRelease打包渠道包
|
||||
|
||||
### 混淆配置
|
||||
* 配置文件:Android默认配置+proguard-rules.txt等
|
||||
* 参考libraries下每个项目独立的配置文件``proguard-project.txt``
|
||||
|
||||
### apk大小优化
|
||||
* 限制resConfig资源集
|
||||
* 开启ShrinkResources
|
||||
* 开启混淆,使用minifyEnabled(仅在release开启)
|
||||
* pngquant对png压缩、png/jpg->webp(未尝试)
|
||||
|
||||
### 第三方appkey等配置
|
||||
* 修改``gradle.properties``文件将各种key填入其中,实现统一管理
|
||||
* 通过gradle文件内的resValue/buildConfigField/manifestPlaceHolder方式实现编译期间修改,具体情况请参考``./build.gradle``和``./app/build.gradle``配置
|
||||
|
||||
### Ver 2.5
|
||||
* 此处写本次更新所做的业务和代码修改
|
||||
1
app/.gitignore
vendored
1
app/.gitignore
vendored
@ -1 +0,0 @@
|
||||
/build
|
||||
336
app/build.gradle
336
app/build.gradle
@ -1,132 +1,264 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
apply plugin: 'com.neenbedankt.android-apt'
|
||||
|
||||
//tinker插件
|
||||
//apply plugin: 'com.tencent.tinker.patch'
|
||||
|
||||
// apkChannelPackage
|
||||
apply plugin: 'channel'
|
||||
|
||||
android {
|
||||
compileSdkVersion 21
|
||||
buildToolsVersion "23.0.3"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.gh.gamecenter"
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 21
|
||||
versionCode 18
|
||||
versionName "2.3"
|
||||
|
||||
// 默认的渠道
|
||||
// manifestPlaceholders = [CHANNEL_VALUE: "GH_TEST"]
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_7
|
||||
targetCompatibility JavaVersion.VERSION_1_7
|
||||
}
|
||||
|
||||
/**
|
||||
* 签名设置
|
||||
*/
|
||||
dexOptions {
|
||||
jumboMode = true
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
|
||||
javaCompileOptions {
|
||||
annotationProcessorOptions {
|
||||
arguments = [ eventBusIndex : 'com.bandeng.MyEventBusIndex' ]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 只支持两种架构,减少apk大小,有疑问请参考:
|
||||
* https://developer.android.com/ndk/guides/abis.html
|
||||
* http://allenfeng.com/2016/11/06/what-you-should-know-about-android-abi-and-so/
|
||||
* (为了性能考虑,armeabi可以考虑替换成armeabi-v7a[需要先收集用户设备情况])
|
||||
*/
|
||||
ndk {
|
||||
abiFilters "armeabi", "x86"
|
||||
}
|
||||
|
||||
// 由于app只针对中文用户,所以仅保留zh资源,其他删掉
|
||||
resConfigs "zh"
|
||||
|
||||
// jackOptions {
|
||||
// enabled true
|
||||
// }
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode rootProject.ext.versionCode
|
||||
versionName rootProject.ext.versionName
|
||||
applicationId rootProject.ext.applicationId
|
||||
|
||||
multiDexEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt', 'proguard-fresco.txt'
|
||||
|
||||
/**
|
||||
* All third-party appid/appkey
|
||||
*/
|
||||
buildConfigField "String", "WECHAT_APPID", "\"${WECHAT_APPID}\""
|
||||
buildConfigField "String", "WECHAT_SECRET", "\"${WECHAT_SECRET}\""
|
||||
buildConfigField "String", "TENCENT_APPID", "\"${TENCENT_APPID}\""
|
||||
buildConfigField "String", "WEIBO_APPKEY", "\"${WEIBO_APPKEY}\""
|
||||
buildConfigField "String", "MTA_APPKEY", "\"${MTA_APPKEY}\""
|
||||
buildConfigField "String", "TD_APPID", "\"${TD_APPID}\""
|
||||
|
||||
}
|
||||
|
||||
// gradle 2.2以上默认同时启用v1和v2(优先用于Android N)
|
||||
signingConfigs {
|
||||
debug {
|
||||
v1SigningEnabled true
|
||||
v2SigningEnabled true
|
||||
}
|
||||
release {
|
||||
storeFile file("gh.keystore")
|
||||
keyAlias "gh.keystore"
|
||||
keyPassword "20150318"
|
||||
storePassword "20150318"
|
||||
v1SigningEnabled true
|
||||
v2SigningEnabled true
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
debuggable true
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
zipAlignEnabled false
|
||||
versionNameSuffix "-debug"
|
||||
}
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
debuggable false
|
||||
minifyEnabled true
|
||||
zipAlignEnabled true
|
||||
shrinkResources true
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
debuggable true
|
||||
minifyEnabled false
|
||||
zipAlignEnabled false
|
||||
versionNameSuffix "-debug"
|
||||
|
||||
buildConfigField "String", "UMENG_APPKEY", "\"${DEBUG_UMENG_APPKEY}\""
|
||||
buildConfigField "String", "UMENG_MESSAGE_SECRET", "\"${DEBUG_UMENG_MESSAGE_SECRET}\""
|
||||
buildConfigField "String", "MIPUSH_APPID", "\"${DEBUG_MIPUSH_APPID}\""
|
||||
buildConfigField "String", "MIPUSH_APPKEY", "\"${DEBUG_MIPUSH_APPKEY}\""
|
||||
}
|
||||
release {
|
||||
debuggable false
|
||||
minifyEnabled true
|
||||
zipAlignEnabled true
|
||||
shrinkResources true
|
||||
signingConfig signingConfigs.release
|
||||
|
||||
buildConfigField "String", "UMENG_APPKEY", "\"${UMENG_APPKEY}\""
|
||||
buildConfigField "String", "UMENG_MESSAGE_SECRET", "\"${UMENG_MESSAGE_SECRET}\""
|
||||
buildConfigField "String", "MIPUSH_APPID", "\"${MIPUSH_APPID}\""
|
||||
buildConfigField "String", "MIPUSH_APPKEY", "\"${MIPUSH_APPKEY}\""
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 多渠道打包
|
||||
* 多渠道打包,渠道请参考"channel.txt"文件,所有渠道值均通过java code设置
|
||||
*/
|
||||
productFlavors {
|
||||
GH_100 {}
|
||||
GH_101 {}
|
||||
GH_102 {}
|
||||
GH_103 {}
|
||||
GH_104 {}
|
||||
GH_106 {}
|
||||
GH_107 {}
|
||||
GH_108 {}
|
||||
GH_109 {}
|
||||
GH_110 {}
|
||||
GH_111 {}
|
||||
GH_113 {}
|
||||
GH_114 {}
|
||||
GH_115 {}
|
||||
GH_116 {}
|
||||
GH_117 {}
|
||||
GH_118 {}
|
||||
GH_119 {}
|
||||
GH_120 {}
|
||||
GH_121 {}
|
||||
GH_123 {}
|
||||
GH_127 {}
|
||||
GH_200 {}
|
||||
GH_201 {}
|
||||
GH_202 {}
|
||||
GH_203 {}
|
||||
GH_204 {}
|
||||
GH_205 {}
|
||||
GH_222 {}
|
||||
GH_307 {}
|
||||
GH_TEST {}
|
||||
// public release host
|
||||
pub {
|
||||
buildConfigField "String", "API_HOST", "\"${API_HOST}\""
|
||||
buildConfigField "String", "USER_HOST", "\"${USER_HOST}\""
|
||||
buildConfigField "String", "COMMENT_HOST", "\"${COMMENT_HOST}\""
|
||||
buildConfigField "String", "LIBAO_HOST", "\"${LIBAO_HOST}\""
|
||||
buildConfigField "String", "MESSAGE_HOST", "\"${MESSAGE_HOST}\""
|
||||
buildConfigField "String", "DATA_HOST", "\"${DATA_HOST}\""
|
||||
}
|
||||
// internal dev host
|
||||
dev {
|
||||
buildConfigField "String", "API_HOST", "\"${DEV_API_HOST}\""
|
||||
buildConfigField "String", "USER_HOST", "\"${DEV_USER_HOST}\""
|
||||
buildConfigField "String", "COMMENT_HOST", "\"${DEV_COMMENT_HOST}\""
|
||||
buildConfigField "String", "LIBAO_HOST", "\"${DEV_LIBAO_HOST}\""
|
||||
buildConfigField "String", "MESSAGE_HOST", "\"${DEV_MESSAGE_HOST}\""
|
||||
buildConfigField "String", "DATA_HOST", "\"${DEV_DATA_HOST}\""
|
||||
}
|
||||
}
|
||||
productFlavors.all { flavor ->
|
||||
flavor.manifestPlaceholders = [CHANNEL_VALUE: name]//命令 gradlew assembleRelease
|
||||
|
||||
// productFlavors.all { flavor ->
|
||||
// flavor.manifestPlaceholders = [CHANNEL_VALUE: name]//命令 gradlew assembleRelease
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
// apkChannelPackage
|
||||
channel {
|
||||
//多渠道包的输出目录,默认为new File(project.buildDir,"channel")
|
||||
baseOutputDir = new File(project.buildDir, "channel")
|
||||
//多渠道包的命名规则,默认为:${appName}-${versionName}-${versionCode}-${flavorName}-${buildType}
|
||||
apkNameFormat = '${appName}-${versionName}-${versionCode}-${flavorName}-${buildType}'
|
||||
}
|
||||
|
||||
apt {
|
||||
arguments {
|
||||
eventBusIndex "com.bandeng.MyEventBusIndex"
|
||||
}
|
||||
}
|
||||
|
||||
//butterknife
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
|
||||
}
|
||||
rebuildChannel {
|
||||
// baseDebugApk = 已有Debug APK
|
||||
// baseReleaseApk = 已有Release APK
|
||||
// //默认为new File(project.buildDir, "rebuildChannel/debug")
|
||||
// debugOutputDir = Debug渠道包输出目录
|
||||
// //默认为new File(project.buildDir, "rebuildChannel/release")
|
||||
// releaseOutputDir = Release渠道包输出目录
|
||||
}
|
||||
apply plugin: 'com.neenbedankt.android-apt'
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
testCompile 'junit:junit:4.12'
|
||||
compile 'com.android.support:appcompat-v7:21.0.0'
|
||||
// compile 'com.android.support:cardview-v7:21.0.0'
|
||||
// fresco图片框架
|
||||
compile 'com.facebook.fresco:fresco:0.12.0'
|
||||
compile 'com.facebook.fresco:animated-gif:0.12.0'
|
||||
// Retrofit2所需要的包
|
||||
compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'
|
||||
// okhttp
|
||||
compile 'com.squareup.okhttp3:okhttp:3.2.0'
|
||||
// ConverterFactory的Gson依赖包
|
||||
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
|
||||
// ConverterFactory的String依赖包
|
||||
// compile 'com.squareup.retrofit2:converter-scalars:2.0.0-beta4'
|
||||
// ConverterFactory的RxJava依赖包
|
||||
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0-beta4'
|
||||
// gson
|
||||
compile 'com.google.code.gson:gson:2.8.0'
|
||||
// OrmLite数据库
|
||||
compile 'com.j256.ormlite:ormlite-android:5.0'
|
||||
compile 'com.j256.ormlite:ormlite-core:5.0'
|
||||
// butterknife
|
||||
compile 'com.jakewharton:butterknife:8.4.0'
|
||||
apt 'com.jakewharton:butterknife-compiler:8.4.0'
|
||||
// RxJava && RxAndroid
|
||||
compile 'io.reactivex:rxandroid:1.1.0'
|
||||
compile 'io.reactivex:rxjava:1.1.0'
|
||||
// RxBinding
|
||||
compile 'com.jakewharton.rxbinding:rxbinding:0.3.0'
|
||||
// compile 'com.jakewharton.rxbinding:rxbinding-appcompat-v7:0.3.0'
|
||||
// compile 'com.jakewharton.rxbinding:rxbinding-design:0.3.0'
|
||||
//添加友盟依赖工程
|
||||
compile project(':PushSDK')
|
||||
// zxing 二维码扫描以及生成
|
||||
compile 'com.google.zxing:core:3.2.1'
|
||||
compile 'com.google.zxing:android-core:3.2.1'
|
||||
}
|
||||
testCompile test.junit
|
||||
compile fileTree(include: '*.jar', dir: 'libs')
|
||||
compile libs.supportMultidex
|
||||
compile libs.supportDesign
|
||||
compile libs.supportAppCompat
|
||||
compile libs.supportAnnotation
|
||||
compile libs.supportPercent
|
||||
compile libs.supportDesign
|
||||
|
||||
compile libs.switchButton
|
||||
|
||||
compile libs.systemBarTint
|
||||
|
||||
compile libs.fresco
|
||||
compile libs.frescoAnimatedGif
|
||||
|
||||
compile libs.okHttp
|
||||
compile libs.okHttpLogInterceptor
|
||||
|
||||
compile libs.apkChannelPackage
|
||||
|
||||
// debugCompile libs.stetho
|
||||
// debugCompile libs.stethoWithOkHttp
|
||||
|
||||
compile libs.retrofit
|
||||
compile libs.retrofitWithGson // include gson 2.7
|
||||
compile libs.retrofitWithRxJava
|
||||
// compile libs.gson
|
||||
|
||||
compile libs.ormliteAndroid
|
||||
compile libs.ormliteCore
|
||||
|
||||
compile libs.butterKnife
|
||||
apt libs.butterKnifeApt
|
||||
|
||||
compile libs.rxJava
|
||||
compile libs.rxAndroid
|
||||
compile libs.rxBinding
|
||||
compile libs.zxing
|
||||
compile libs.zxingAndroid
|
||||
|
||||
compile libs.swipeLayout
|
||||
compile(libs.autoScrollViewPager) {
|
||||
exclude module: 'support-v4'
|
||||
}
|
||||
|
||||
// tinker
|
||||
// provided libs.tinker_anno
|
||||
// compile libs.tinker_lib
|
||||
|
||||
compile libs.eventbus
|
||||
apt libs.eventbusApt
|
||||
// compile project(':libraries:EventBus')
|
||||
compile project(':libraries:MiPush')
|
||||
compile project(':libraries:MTA')
|
||||
compile project(':libraries:QQShare')
|
||||
compile project(':libraries:TalkingData')
|
||||
compile project(':libraries:UmengPush')
|
||||
compile project(':libraries:WechatShare')
|
||||
compile project(':libraries:WeiboShare')
|
||||
compile project(':libraries:iosched')
|
||||
|
||||
}
|
||||
File propFile = file('sign.properties');
|
||||
if (propFile.exists()) {
|
||||
def Properties props = new Properties()
|
||||
props.load(new FileInputStream(propFile))
|
||||
|
||||
if (props.containsKey('keyAlias') && props.containsKey('keyPassword') &&
|
||||
props.containsKey('storeFile') && props.containsKey('storePassword')) {
|
||||
android.signingConfigs {
|
||||
debug {
|
||||
keyAlias props.get('keyAlias')
|
||||
keyPassword props.get('keyPassword')
|
||||
storeFile file(props.get('storeFile'))
|
||||
storePassword props.get('storePassword')
|
||||
}
|
||||
release {
|
||||
keyAlias props.get('keyAlias')
|
||||
keyPassword props.get('keyPassword')
|
||||
storeFile file(props.get('storeFile'))
|
||||
storePassword props.get('storePassword')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
android.buildTypes.release.signingConfig = null
|
||||
}
|
||||
} else {
|
||||
android.buildTypes.release.signingConfig = null
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
21
app/proguard-fresco.txt
Normal file
21
app/proguard-fresco.txt
Normal file
@ -0,0 +1,21 @@
|
||||
# Keep our interfaces so they can be used by other ProGuard rules.
|
||||
# See http://sourceforge.net/p/proguard/bugs/466/
|
||||
-keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip
|
||||
|
||||
# Do not strip any method/class that is annotated with @DoNotStrip
|
||||
-keep @com.facebook.common.internal.DoNotStrip class *
|
||||
-keepclassmembers class * {
|
||||
@com.facebook.common.internal.DoNotStrip *;
|
||||
}
|
||||
|
||||
# Keep native methods
|
||||
-keepclassmembers class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
-dontwarn okio.**
|
||||
-dontwarn com.squareup.okhttp.**
|
||||
-dontwarn okhttp3.**
|
||||
-dontwarn javax.annotation.**
|
||||
-dontwarn com.android.volley.toolbox.**
|
||||
-dontwarn com.facebook.infer.**
|
||||
160
app/proguard-rules.txt
Normal file
160
app/proguard-rules.txt
Normal file
@ -0,0 +1,160 @@
|
||||
# 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 *;
|
||||
#}
|
||||
|
||||
-keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod
|
||||
-dontwarn InnerClasses
|
||||
-dontoptimize
|
||||
|
||||
# OrmLite uses reflection
|
||||
-keep class com.j256.**
|
||||
-keepclassmembers class com.j256.** { *; }
|
||||
-keep enum com.j256.**
|
||||
-keepclassmembers enum com.j256.** { *; }
|
||||
-keep interface com.j256.**
|
||||
-keepclassmembers interface com.j256.** { *; }
|
||||
-dontwarn com.j256.**
|
||||
|
||||
#okhttp3
|
||||
-dontwarn com.squareup.okhttp3.**
|
||||
-dontwarn okio.**
|
||||
-keep class com.squareup.okhttp3.** { *;}
|
||||
|
||||
# stetho
|
||||
-keep class com.facebook.stetho.** { *; }
|
||||
-dontwarn com.facebook.stetho.**
|
||||
|
||||
# Retrofit 2.2
|
||||
# Platform calls Class.forName on types which do not exist on Android to determine platform.
|
||||
-dontnote retrofit2.Platform
|
||||
# Platform used when running on Java 8 VMs. Will not be used at runtime.
|
||||
-dontwarn retrofit2.Platform$Java8
|
||||
# Retain generic type information for use by reflection by converters and adapters.
|
||||
-keepattributes Signature
|
||||
# Retain declared checked exceptions for use by a Proxy instance.
|
||||
-keepattributes Exceptions
|
||||
|
||||
# Retrofit 2.X
|
||||
## https://square.github.io/retrofit/ ##
|
||||
|
||||
-dontwarn retrofit2.**
|
||||
-keep class retrofit2.** { *; }
|
||||
-keepattributes Signature
|
||||
-keepattributes Exceptions
|
||||
|
||||
-keepclasseswithmembers class * {
|
||||
@retrofit2.http.* <methods>;
|
||||
}
|
||||
|
||||
|
||||
# rxjava
|
||||
-keep class rx.schedulers.Schedulers {
|
||||
public static <methods>;
|
||||
}
|
||||
-keep class rx.schedulers.ImmediateScheduler {
|
||||
public <methods>;
|
||||
}
|
||||
-keep class rx.schedulers.TestScheduler {
|
||||
public <methods>;
|
||||
}
|
||||
-keep class rx.schedulers.Schedulers {
|
||||
public static ** test();
|
||||
}
|
||||
-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
|
||||
long producerIndex;
|
||||
long consumerIndex;
|
||||
}
|
||||
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
|
||||
long producerNode;
|
||||
long consumerNode;
|
||||
}
|
||||
-dontwarn rx.internal.util.**
|
||||
|
||||
## AutoScrollViewPager
|
||||
-keep class cn.trinea.android.** { *; }
|
||||
-keepclassmembers class cn.trinea.android.** { *; }
|
||||
-dontwarn cn.trinea.android.**
|
||||
|
||||
## butterknife
|
||||
# Retain generated class which implement Unbinder.
|
||||
#-keep public class * implements butterknife.Unbinder { public <init>(**, android.view.View); }
|
||||
#
|
||||
## Prevent obfuscation of types which use ButterKnife annotations since the simple name
|
||||
## is used to reflectively look up the generated ViewBinding.
|
||||
#-keep class butterknife.*
|
||||
#-keepclasseswithmembernames class * { @butterknife.* <methods>; }
|
||||
#-keepclasseswithmembernames class * { @butterknife.* <fields>; }
|
||||
|
||||
-dontwarn butterknife.internal.**
|
||||
-keep class **$$ViewInjector { *; }
|
||||
-keepnames class * { @butterknife.InjectView *;}
|
||||
-dontwarn butterknife.Views$InjectViewProcessor
|
||||
-dontwarn com.gc.materialdesign.views.**
|
||||
|
||||
# eventbus
|
||||
-keepattributes *Annotation*
|
||||
-keepclassmembers class ** {
|
||||
@org.greenrobot.eventbus.Subscribe <methods>;
|
||||
}
|
||||
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
|
||||
|
||||
# Only required if you use AsyncExecutor
|
||||
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
|
||||
<init>(java.lang.Throwable);
|
||||
}
|
||||
|
||||
|
||||
# app models
|
||||
-keep class com.gh.common.view.** {*;}
|
||||
-keep class com.gh.gamecenter.db.info.** {*;}
|
||||
-keep class com.gh.gamecenter.entity.** {*;}
|
||||
-keep class com.gh.gamecenter.retrofit.** {*;}
|
||||
-keep class com.gh.gamecenter.eventbus.** {*;}
|
||||
-keep class * extends rx.Subscriber
|
||||
|
||||
#---------------------------------webview------------------------------------
|
||||
-keepclassmembers class * extends android.webkit.WebViewClient {
|
||||
public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
|
||||
public boolean *(android.webkit.WebView, java.lang.String);
|
||||
}
|
||||
-keepclassmembers class * extends android.webkit.WebViewClient {
|
||||
public void *(android.webkit.WebView, java.lang.String);
|
||||
}
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
|
||||
##---------------Begin: proguard configuration for Gson ----------
|
||||
# Gson uses generic type information stored in a class file when working with fields. Proguard
|
||||
# removes such information by default, so configure it to keep all of it.
|
||||
-keepattributes Signature
|
||||
|
||||
# For using GSON @Expose annotation
|
||||
-keepattributes *Annotation*
|
||||
|
||||
# Gson specific classes
|
||||
-keep class sun.misc.Unsafe { *; }
|
||||
#-keep class com.google.gson.stream.** { *; }
|
||||
|
||||
# Prevent proguard from stripping interface information from TypeAdapterFactory,
|
||||
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
|
||||
-keep class * implements com.google.gson.TypeAdapterFactory
|
||||
-keep class * implements com.google.gson.JsonSerializer
|
||||
-keep class * implements com.google.gson.JsonDeserializer
|
||||
|
||||
-keepclassmembers enum * { *; }
|
||||
|
||||
##---------------End: proguard configuration for Gson ----------
|
||||
4
app/sign.properties
Normal file
4
app/sign.properties
Normal file
@ -0,0 +1,4 @@
|
||||
storeFile=gh.keystore
|
||||
storePassword=20150318
|
||||
keyAlias=gh.keystore
|
||||
keyPassword=20150318
|
||||
@ -1,324 +1,244 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.gh.gamecenter" >
|
||||
<manifest xmlns:android = "http://schemas.android.com/apk/res/android"
|
||||
package = "com.gh.gamecenter" >
|
||||
|
||||
<!-- 允许应用程序访问网络连接 -->
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name = "android.permission.INTERNET" />
|
||||
<!-- 允许应用程序写入外部存储,如SD卡上写文件 -->
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<!-- 允许应用程序读取扩展存储器 -->
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name = "android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<!-- 允许挂载和反挂载文件系统可移动存储 -->
|
||||
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
|
||||
<uses-permission android:name = "android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
|
||||
<!-- 允许应用程序访问Wi-Fi网络状态信息 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name = "android.permission.ACCESS_WIFI_STATE" />
|
||||
<!-- 允许应用程序获取网络信息状态 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name = "android.permission.ACCESS_NETWORK_STATE" />
|
||||
<!-- 允许应用程序读取电话状态 -->
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name = "android.permission.READ_PHONE_STATE" />
|
||||
<!-- 允许应用程序获取当前或最近运行的应用 -->
|
||||
<uses-permission android:name="android.permission.GET_TASKS" />
|
||||
<uses-permission android:name = "android.permission.GET_TASKS" />
|
||||
<!-- 允许访问振动设备 -->
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name = "android.permission.VIBRATE" />
|
||||
<!-- 允许应用程序通过WiFi或移动基站获取粗略的位置信息 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name = "android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<!-- 允许应用程序通过GPS获取精确的位置信息 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name = "android.permission.ACCESS_FINE_LOCATION" />
|
||||
<!-- 允许应用程序改变Wi-Fi连接状态 -->
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||
<uses-permission android:name = "android.permission.CHANGE_WIFI_STATE" />
|
||||
<!-- 允许应用程序管理AccountManager中的账户列表 -->
|
||||
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
|
||||
<uses-permission android:name = "android.permission.MANAGE_ACCOUNTS" />
|
||||
<!-- 允许应用程序访问GMail账户列表 -->
|
||||
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
||||
<uses-permission android:name = "android.permission.GET_ACCOUNTS" />
|
||||
<!-- 允许应用程序连接配对过的蓝牙设备 -->
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
<uses-permission android:name = "android.permission.BLUETOOTH" />
|
||||
<!-- 允许应用程序管理蓝牙,搜索和配对新的蓝牙设备 -->
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||
<uses-permission android:name = "android.permission.BLUETOOTH_ADMIN" />
|
||||
<!-- 允许应用程序打开系统窗口,显示其他应用程序 -->
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||
<!-- 小米推送需要的权限 -->
|
||||
<uses-permission android:name="com.gh.gamecenter.permission.MIPUSH_RECEIVE" />
|
||||
|
||||
<permission
|
||||
android:name="com.gh.gamecenter.permission.MIPUSH_RECEIVE"
|
||||
android:protectionLevel="signature" />
|
||||
<uses-permission android:name = "android.permission.SYSTEM_ALERT_WINDOW" />
|
||||
<!-- 修改系统设置的权限 -->
|
||||
<uses-permission android:name = "android.permission.WRITE_SETTINGS" />
|
||||
|
||||
<supports-screens
|
||||
android:anyDensity="true"
|
||||
android:largeScreens="true"
|
||||
android:normalScreens="true"
|
||||
android:resizeable="true"
|
||||
android:smallScreens="true" />
|
||||
android:anyDensity = "true"
|
||||
android:largeScreens = "true"
|
||||
android:normalScreens = "true"
|
||||
android:resizeable = "true"
|
||||
android:smallScreens = "true" />
|
||||
|
||||
<!--android:largeHeap = "true"-->
|
||||
<application
|
||||
android:name="com.gh.base.AppController"
|
||||
android:icon="@drawable/logo"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppNormalTheme" >
|
||||
<!-- TalkingData -->
|
||||
<meta-data
|
||||
android:name="TD_APP_ID"
|
||||
android:value="81DB144D555386A38A70B833537EC256" />
|
||||
<meta-data
|
||||
android:name="TD_CHANNEL_ID"
|
||||
android:value="GH_TEST"/>
|
||||
<!--android:value="${CHANNEL_VALUE}"-->
|
||||
|
||||
<!-- MTA -->
|
||||
<meta-data
|
||||
android:name="TA_APPKEY"
|
||||
android:value="APV567FTBS7J"/>
|
||||
<meta-data
|
||||
android:name="InstallChannel"
|
||||
android:value="GH_TEST"/>
|
||||
<!--android:value="${CHANNEL_VALUE}"-->
|
||||
|
||||
<!-- 友盟推送 -->
|
||||
<meta-data
|
||||
android:name="UMENG_APPKEY"
|
||||
android:value="585a29fa8f4a9d327600023e">
|
||||
</meta-data>
|
||||
<meta-data
|
||||
android:name="UMENG_MESSAGE_SECRET"
|
||||
android:value="8bcce6bed547ee624f5c2cc64d39a9e9">
|
||||
</meta-data>
|
||||
android:name = "com.gh.base.AppController"
|
||||
android:allowBackup = "true"
|
||||
android:icon = "@drawable/logo"
|
||||
android:label = "@string/app_name"
|
||||
android:theme = "@style/AppCompatTheme" >
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.SplashScreenActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppGuideTheme"
|
||||
android:uiOptions="splitActionBarWhenNarrow" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
android:name = "com.gh.gamecenter.SplashScreenActivity"
|
||||
android:configChanges = "keyboardHidden|orientation|screenSize"
|
||||
android:screenOrientation = "portrait"
|
||||
android:theme = "@style/AppGuideTheme"
|
||||
android:uiOptions = "splitActionBarWhenNarrow" >
|
||||
<intent-filter >
|
||||
<action android:name = "android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<category android:name = "android.intent.category.LAUNCHER" />
|
||||
</intent-filter >
|
||||
</activity >
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateAlwaysHidden|adjustResize"/>
|
||||
android:name = "com.gh.gamecenter.MainActivity"
|
||||
android:launchMode = "singleTop"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateAlwaysHidden|adjustResize" />
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.DownloadManagerActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
android:name = "com.gh.gamecenter.DownloadManagerActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.ViewImageActivity"
|
||||
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" />
|
||||
android:name = "com.gh.gamecenter.ViewImageActivity"
|
||||
android:theme = "@android:style/Theme.Black.NoTitleBar.Fullscreen" />
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.SearchActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateVisible" />
|
||||
android:name = "com.gh.gamecenter.SearchActivity"
|
||||
android:configChanges = "keyboardHidden"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.GameDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
android:name = "com.gh.gamecenter.NewsDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.NewsDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
android:name = "com.gh.gamecenter.SettingActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.SettingActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
android:name = "com.gh.gamecenter.ConcernActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.SuggestionActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="stateVisible" />
|
||||
android:name = "com.gh.gamecenter.SubjectActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.ConcernActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
android:name = "com.gh.gamecenter.PluginActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.SubjectActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
android:name = "com.gh.gamecenter.NewsSearchActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode="stateHidden"/>
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.PluginActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
android:name = "com.gh.gamecenter.GameNewsActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.NewsSearchActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
android:name = "com.gh.gamecenter.CropImageActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.GameNewsActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
android:name = "com.gh.gamecenter.WebActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.CropImageActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
android:name = "com.gh.gamecenter.ShareCardPicActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.WebActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
android:name = "com.gh.gamecenter.ShareCardActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.ShareCardPicActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
android:name = "com.gh.gamecenter.MessageDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.ShareCardActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
android:name = "com.gh.gamecenter.LibaoActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode="stateHidden"/>
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.MessageDetailActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
android:name = "com.gh.gamecenter.LibaoDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.StrategyActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
android:name = "com.gh.gamecenter.ShareGhWfifActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.LibaoActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
android:name = "com.gh.gamecenter.ShareGhActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.LibaoDetailActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
android:name = "com.gh.gamecenter.CleanApkActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.SkipActivity"
|
||||
android:theme="@android:style/Theme.Translucent">
|
||||
<intent-filter>
|
||||
<data android:scheme="ghzhushou"/>
|
||||
android:name = "com.gh.gamecenter.KcSelectGameActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.ChooseReceiverActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.ReceiverWaitingActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.FileSenderActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.FileReceiverActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.SelectUserIconActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.AboutActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.KaiFuActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.CommentDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.GameDetailActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.SuggestSelectActivity"
|
||||
android:screenOrientation = "portrait" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.SuggestionActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateHidden|adjustResize" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.VoteActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode = "stateAlwaysHidden|adjustResize" />
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.ToolBoxActivity"
|
||||
android:screenOrientation = "portrait"
|
||||
android:windowSoftInputMode="stateHidden"/>
|
||||
<activity
|
||||
android:name = "com.gh.gamecenter.SkipActivity"
|
||||
android:theme = "@style/Theme.AppCompat.Light.Fullscreen.Transparent" >
|
||||
<intent-filter >
|
||||
<data android:scheme = "ghzhushou" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.wxapi.WXEntryActivity"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTop"
|
||||
android:screenOrientation="portrait">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<data android:scheme="sdksample"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<!-- QQ 分享 -->
|
||||
<activity
|
||||
android:name="com.tencent.tauth.AuthActivity"
|
||||
android:launchMode="singleTask"
|
||||
android:noHistory="true" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="tencent1104659243" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name="com.tencent.connect.common.AssistActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:screenOrientation="behind"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
|
||||
<!--微博分享-->
|
||||
<activity
|
||||
android:name="com.sina.weibo.sdk.component.WeiboSdkBrowser"
|
||||
android:configChanges="keyboardHidden|orientation"
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
android:exported="false" >
|
||||
</activity>
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.WeiBoShareActivity"
|
||||
android:configChanges="keyboardHidden|orientation"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTop">
|
||||
<intent-filter>
|
||||
<action android:name="com.sina.weibo.sdk.action.ACTION_SDK_REQ_ACTIVITY" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<category android:name = "android.intent.category.DEFAULT" />
|
||||
<action android:name = "android.intent.action.VIEW" />
|
||||
<category android:name = "android.intent.category.BROWSABLE" />
|
||||
</intent-filter >
|
||||
</activity >
|
||||
|
||||
<receiver android:name="com.gh.gamecenter.receiver.InstallAndUninstallReceiver" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.PACKAGE_ADDED" />
|
||||
<action android:name="android.intent.action.PACKAGE_REMOVED" />
|
||||
<action android:name="android.intent.action.PACKAGE_REPLACED" />
|
||||
<receiver android:name = "com.gh.gamecenter.receiver.InstallAndUninstallReceiver" >
|
||||
<intent-filter >
|
||||
<action android:name = "android.intent.action.PACKAGE_ADDED" />
|
||||
<action android:name = "android.intent.action.PACKAGE_REMOVED" />
|
||||
<action android:name = "android.intent.action.PACKAGE_REPLACED" />
|
||||
|
||||
<data android:scheme="package" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<data android:scheme = "package" />
|
||||
</intent-filter >
|
||||
</receiver >
|
||||
<receiver
|
||||
android:name="com.gh.gamecenter.receiver.NotificationReceiver"
|
||||
android:exported="false" >
|
||||
<intent-filter>
|
||||
<action android:name="com.gh.gamecenter.NOTIFICATION" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
android:name = "com.gh.gamecenter.receiver.NotificationReceiver"
|
||||
android:exported = "false" >
|
||||
<intent-filter >
|
||||
<action android:name = "com.gh.gamecenter.NOTIFICATION" />
|
||||
</intent-filter >
|
||||
</receiver >
|
||||
<receiver
|
||||
android:name="com.gh.gamecenter.receiver.DownloadReceiver"
|
||||
android:exported="false" >
|
||||
<intent-filter>
|
||||
<action android:name="com.gh.gamecenter.DOWNLOAD" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
android:name = "com.gh.gamecenter.receiver.DownloadReceiver"
|
||||
android:exported = "false" >
|
||||
<intent-filter >
|
||||
<action android:name = "com.gh.gamecenter.DOWNLOAD" />
|
||||
</intent-filter >
|
||||
</receiver >
|
||||
<receiver
|
||||
android:name="com.gh.gamecenter.receiver.InstallReceiver"
|
||||
android:exported="false" >
|
||||
<intent-filter>
|
||||
<action android:name="com.gh.gamecenter.INSTALL" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver android:name="com.gh.gamecenter.receiver.NetworkStateReceiver" >
|
||||
<intent-filter>
|
||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name="com.xiaomi.push.service.receivers.PingReceiver"
|
||||
android:exported="false"
|
||||
android:process=":pushservice" >
|
||||
<intent-filter>
|
||||
<action android:name="com.xiaomi.push.PING_TIMER" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name="com.gh.base.GHPushMessageReceiver"
|
||||
android:exported="true" >
|
||||
<intent-filter>
|
||||
<action android:name="com.xiaomi.mipush.RECEIVE_MESSAGE" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.xiaomi.mipush.MESSAGE_ARRIVED" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.xiaomi.mipush.ERROR" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name="com.xiaomi.push.service.receivers.NetworkStatusReceiver"
|
||||
android:exported="true" >
|
||||
<intent-filter>
|
||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
|
||||
android:name = "com.gh.gamecenter.receiver.InstallReceiver"
|
||||
android:exported = "false" >
|
||||
<intent-filter >
|
||||
<action android:name = "com.gh.gamecenter.INSTALL" />
|
||||
</intent-filter >
|
||||
</receiver >
|
||||
<receiver android:name = "com.gh.gamecenter.receiver.NetworkStateReceiver" >
|
||||
<intent-filter >
|
||||
<action android:name = "android.net.conn.CONNECTIVITY_CHANGE" />
|
||||
</intent-filter >
|
||||
</receiver >
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name="com.gh.gamecenter.receiver.ActivitySkipReceiver"
|
||||
android:exported="true" >
|
||||
<intent-filter>
|
||||
<action android:name="com.gh.gamecenter.ACTIVITYSKIP" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
android:name = "com.gh.gamecenter.receiver.ActivitySkipReceiver"
|
||||
android:exported = "true" >
|
||||
<intent-filter >
|
||||
<action android:name = "com.gh.gamecenter.ACTIVITYSKIP" />
|
||||
</intent-filter >
|
||||
</receiver >
|
||||
|
||||
<service
|
||||
android:name="com.gh.download.DownloadService" />
|
||||
<service android:name = "com.gh.download.DownloadService" />
|
||||
|
||||
<service
|
||||
android:name=".statistics.AppStaticService" />
|
||||
<service android:name = "com.gh.gamecenter.statistics.AppStaticService" />
|
||||
|
||||
<service
|
||||
android:name="com.xiaomi.push.service.XMJobService"
|
||||
android:enabled="true"
|
||||
android:exported="false"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE"
|
||||
android:process=":pushservice" />
|
||||
<service
|
||||
android:name="com.xiaomi.push.service.XMPushService"
|
||||
android:enabled="true"
|
||||
android:process=":pushservice" />
|
||||
<service
|
||||
android:name="com.xiaomi.mipush.sdk.PushMessageHandler"
|
||||
android:enabled="true"
|
||||
android:exported="true" />
|
||||
<service
|
||||
android:name="com.xiaomi.mipush.sdk.MessageHandleService"
|
||||
android:enabled="true" />
|
||||
</application>
|
||||
</application >
|
||||
|
||||
</manifest>
|
||||
</manifest >
|
||||
69
app/src/main/assets/Home.html
Normal file
69
app/src/main/assets/Home.html
Normal file
@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/html">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>光环助手</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<style>
|
||||
body {
|
||||
font: 100%/1.0 'Microsoft YaHei','Helvetica Neue',Helvetica,Arial,sans-serif;
|
||||
background-color: #fff;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
header {
|
||||
}
|
||||
|
||||
article {
|
||||
width:100%;
|
||||
max-width:720px;
|
||||
clear: both;
|
||||
margin: 0 auto;
|
||||
margin-top: 20%;
|
||||
text-align: center;
|
||||
margin-bottom:20%;
|
||||
}
|
||||
.title{margin-top: 4%;font-size:1.7em;color:#191919;text-align:center;}
|
||||
.info{margin-top: 18%;font-size:1.0em;color:#191919;line-height:1.3em;}
|
||||
.download {text-align: center;}
|
||||
.download a{font-size:1.8em;padding:0.2em; text-align:center;color:#ffffff;margin: 0 auto;width:56%;background-color:#2999f9;border-radius:8px; text-decoration:none;display:block;line-height:1.8em;}
|
||||
|
||||
@media only screen and (min-width: 1080px) {
|
||||
article {
|
||||
width:100%;
|
||||
max-width:720px;
|
||||
clear: both;
|
||||
margin: 0 auto;
|
||||
margin-top: 5%;
|
||||
text-align: center;
|
||||
margin-bottom:20%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
</header>
|
||||
|
||||
<article>
|
||||
<img src="http://192.168.43.1:3100/image/gh_icon.png" width="28%">
|
||||
<p class="title">光环助手</p>
|
||||
<br class="info">乐于分享的人是最帅的^_^ </p>
|
||||
<div class="download">
|
||||
<a href="http://192.168.43.1:3100/download/ghzs.apk">免流量下载</a>
|
||||
</div>
|
||||
<p class="title"><font color="#9A9A9A" size="3em">仅限安卓系统 </font></p>
|
||||
</article>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
BIN
app/src/main/assets/scan_receiver.gif
Normal file
BIN
app/src/main/assets/scan_receiver.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 544 KiB |
@ -1,699 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 android.support.v7.widget;
|
||||
|
||||
import android.support.v4.util.Pools;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static android.support.v7.widget.RecyclerView.ViewHolder;
|
||||
|
||||
/**
|
||||
* Helper class that can enqueue and process adapter update operations.
|
||||
* <p>
|
||||
* To support animations, RecyclerView presents an older version the Adapter to best represent
|
||||
* previous state of the layout. Sometimes, this is not trivial when items are removed that were
|
||||
* not laid out, in which case, RecyclerView has no way of providing that item's view for
|
||||
* animations.
|
||||
* <p>
|
||||
* AdapterHelper creates an UpdateOp for each adapter data change then pre-processes them. During
|
||||
* pre processing, AdapterHelper finds out which UpdateOps can be deferred to second layout pass
|
||||
* and which cannot. For the UpdateOps that cannot be deferred, AdapterHelper will change them
|
||||
* according to previously deferred operation and dispatch them before the first layout pass. It
|
||||
* also takes care of updating deferred UpdateOps since order of operations is changed by this
|
||||
* process.
|
||||
* <p>
|
||||
* Although operations may be forwarded to LayoutManager in different orders, resulting data set
|
||||
* is guaranteed to be the consistent.
|
||||
*/
|
||||
class AdapterHelper implements OpReorderer.Callback {
|
||||
|
||||
final static int POSITION_TYPE_INVISIBLE = 0;
|
||||
|
||||
final static int POSITION_TYPE_NEW_OR_LAID_OUT = 1;
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final String TAG = "AHT";
|
||||
|
||||
private Pools.Pool<UpdateOp> mUpdateOpPool = new Pools.SimplePool<UpdateOp>(UpdateOp.POOL_SIZE);
|
||||
|
||||
final ArrayList<UpdateOp> mPendingUpdates = new ArrayList<UpdateOp>();
|
||||
|
||||
final ArrayList<UpdateOp> mPostponedList = new ArrayList<UpdateOp>();
|
||||
|
||||
final Callback mCallback;
|
||||
|
||||
Runnable mOnItemProcessedCallback;
|
||||
|
||||
final boolean mDisableRecycler;
|
||||
|
||||
final OpReorderer mOpReorderer;
|
||||
|
||||
AdapterHelper(Callback callback) {
|
||||
this(callback, false);
|
||||
}
|
||||
|
||||
AdapterHelper(Callback callback, boolean disableRecycler) {
|
||||
mCallback = callback;
|
||||
mDisableRecycler = disableRecycler;
|
||||
mOpReorderer = new OpReorderer(this);
|
||||
}
|
||||
|
||||
AdapterHelper addUpdateOp(UpdateOp... ops) {
|
||||
Collections.addAll(mPendingUpdates, ops);
|
||||
return this;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
recycleUpdateOpsAndClearList(mPendingUpdates);
|
||||
recycleUpdateOpsAndClearList(mPostponedList);
|
||||
}
|
||||
|
||||
void preProcess() {
|
||||
mOpReorderer.reorderOps(mPendingUpdates);
|
||||
final int count = mPendingUpdates.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
UpdateOp op = mPendingUpdates.get(i);
|
||||
switch (op.cmd) {
|
||||
case UpdateOp.ADD:
|
||||
applyAdd(op);
|
||||
break;
|
||||
case UpdateOp.REMOVE:
|
||||
applyRemove(op);
|
||||
break;
|
||||
case UpdateOp.UPDATE:
|
||||
applyUpdate(op);
|
||||
break;
|
||||
case UpdateOp.MOVE:
|
||||
applyMove(op);
|
||||
break;
|
||||
}
|
||||
if (mOnItemProcessedCallback != null) {
|
||||
mOnItemProcessedCallback.run();
|
||||
}
|
||||
}
|
||||
mPendingUpdates.clear();
|
||||
}
|
||||
|
||||
void consumePostponedUpdates() {
|
||||
final int count = mPostponedList.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
mCallback.onDispatchSecondPass(mPostponedList.get(i));
|
||||
}
|
||||
recycleUpdateOpsAndClearList(mPostponedList);
|
||||
}
|
||||
|
||||
private void applyMove(UpdateOp op) {
|
||||
// MOVE ops are pre-processed so at this point, we know that item is still in the adapter.
|
||||
// otherwise, it would be converted into a REMOVE operation
|
||||
postponeAndUpdateViewHolders(op);
|
||||
}
|
||||
|
||||
private void applyRemove(UpdateOp op) {
|
||||
int tmpStart = op.positionStart;
|
||||
int tmpCount = 0;
|
||||
int tmpEnd = op.positionStart + op.itemCount;
|
||||
int type = -1;
|
||||
for (int position = op.positionStart; position < tmpEnd; position++) {
|
||||
boolean typeChanged = false;
|
||||
ViewHolder vh = mCallback.findViewHolder(position);
|
||||
if (vh != null || canFindInPreLayout(position)) {
|
||||
// If a ViewHolder exists or this is a newly added item, we can defer this update
|
||||
// to post layout stage.
|
||||
// * For existing ViewHolders, we'll fake its existence in the pre-layout phase.
|
||||
// * For items that are added and removed in the same process cycle, they won't
|
||||
// have any effect in pre-layout since their add ops are already deferred to
|
||||
// post-layout pass.
|
||||
if (type == POSITION_TYPE_INVISIBLE) {
|
||||
// Looks like we have other updates that we cannot merge with this one.
|
||||
// Create an UpdateOp and dispatch it to LayoutManager.
|
||||
UpdateOp newOp = obtainUpdateOp(UpdateOp.REMOVE, tmpStart, tmpCount);
|
||||
dispatchAndUpdateViewHolders(newOp);
|
||||
typeChanged = true;
|
||||
}
|
||||
type = POSITION_TYPE_NEW_OR_LAID_OUT;
|
||||
} else {
|
||||
// This update cannot be recovered because we don't have a ViewHolder representing
|
||||
// this position. Instead, post it to LayoutManager immediately
|
||||
if (type == POSITION_TYPE_NEW_OR_LAID_OUT) {
|
||||
// Looks like we have other updates that we cannot merge with this one.
|
||||
// Create UpdateOp op and dispatch it to LayoutManager.
|
||||
UpdateOp newOp = obtainUpdateOp(UpdateOp.REMOVE, tmpStart, tmpCount);
|
||||
postponeAndUpdateViewHolders(newOp);
|
||||
typeChanged = true;
|
||||
}
|
||||
type = POSITION_TYPE_INVISIBLE;
|
||||
}
|
||||
if (typeChanged) {
|
||||
position -= tmpCount; // also equal to tmpStart
|
||||
tmpEnd -= tmpCount;
|
||||
tmpCount = 1;
|
||||
} else {
|
||||
tmpCount++;
|
||||
}
|
||||
}
|
||||
if (tmpCount != op.itemCount) { // all 1 effect
|
||||
recycleUpdateOp(op);
|
||||
op = obtainUpdateOp(UpdateOp.REMOVE, tmpStart, tmpCount);
|
||||
}
|
||||
if (type == POSITION_TYPE_INVISIBLE) {
|
||||
dispatchAndUpdateViewHolders(op);
|
||||
} else {
|
||||
postponeAndUpdateViewHolders(op);
|
||||
}
|
||||
}
|
||||
|
||||
private void applyUpdate(UpdateOp op) {
|
||||
int tmpStart = op.positionStart;
|
||||
int tmpCount = 0;
|
||||
int tmpEnd = op.positionStart + op.itemCount;
|
||||
int type = -1;
|
||||
for (int position = op.positionStart; position < tmpEnd; position++) {
|
||||
ViewHolder vh = mCallback.findViewHolder(position);
|
||||
if (vh != null || canFindInPreLayout(position)) { // deferred
|
||||
if (type == POSITION_TYPE_INVISIBLE) {
|
||||
UpdateOp newOp = obtainUpdateOp(UpdateOp.UPDATE, tmpStart, tmpCount);
|
||||
dispatchAndUpdateViewHolders(newOp);
|
||||
tmpCount = 0;
|
||||
tmpStart = position;
|
||||
}
|
||||
type = POSITION_TYPE_NEW_OR_LAID_OUT;
|
||||
} else { // applied
|
||||
if (type == POSITION_TYPE_NEW_OR_LAID_OUT) {
|
||||
UpdateOp newOp = obtainUpdateOp(UpdateOp.UPDATE, tmpStart, tmpCount);
|
||||
postponeAndUpdateViewHolders(newOp);
|
||||
tmpCount = 0;
|
||||
tmpStart = position;
|
||||
}
|
||||
type = POSITION_TYPE_INVISIBLE;
|
||||
}
|
||||
tmpCount++;
|
||||
}
|
||||
if (tmpCount != op.itemCount) { // all 1 effect
|
||||
recycleUpdateOp(op);
|
||||
op = obtainUpdateOp(UpdateOp.UPDATE, tmpStart, tmpCount);
|
||||
}
|
||||
if (type == POSITION_TYPE_INVISIBLE) {
|
||||
dispatchAndUpdateViewHolders(op);
|
||||
} else {
|
||||
postponeAndUpdateViewHolders(op);
|
||||
}
|
||||
}
|
||||
|
||||
private void dispatchAndUpdateViewHolders(UpdateOp op) {
|
||||
// tricky part.
|
||||
// traverse all postpones and revert their changes on this op if necessary, apply updated
|
||||
// dispatch to them since now they are after this op.
|
||||
if (op.cmd == UpdateOp.ADD || op.cmd == UpdateOp.MOVE) {
|
||||
throw new IllegalArgumentException("should not dispatch add or move for pre layout");
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "dispatch (pre)" + op);
|
||||
Log.d(TAG, "postponed state before:");
|
||||
for (UpdateOp updateOp : mPostponedList) {
|
||||
Log.d(TAG, updateOp.toString());
|
||||
}
|
||||
Log.d(TAG, "----");
|
||||
}
|
||||
|
||||
// handle each pos 1 by 1 to ensure continuity. If it breaks, dispatch partial
|
||||
// TODO Since move ops are pushed to end, we should not need this anymore
|
||||
int tmpStart = updatePositionWithPostponed(op.positionStart, op.cmd);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "pos:" + op.positionStart + ",updatedPos:" + tmpStart);
|
||||
}
|
||||
int tmpCnt = 1;
|
||||
int offsetPositionForPartial = op.positionStart;
|
||||
final int positionMultiplier;
|
||||
switch (op.cmd) {
|
||||
case UpdateOp.UPDATE:
|
||||
positionMultiplier = 1;
|
||||
break;
|
||||
case UpdateOp.REMOVE:
|
||||
positionMultiplier = 0;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("op should be remove or update." + op);
|
||||
}
|
||||
for (int p = 1; p < op.itemCount; p++) {
|
||||
final int pos = op.positionStart + (positionMultiplier * p);
|
||||
int updatedPos = updatePositionWithPostponed(pos, op.cmd);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "pos:" + pos + ",updatedPos:" + updatedPos);
|
||||
}
|
||||
boolean continuous = false;
|
||||
switch (op.cmd) {
|
||||
case UpdateOp.UPDATE:
|
||||
continuous = updatedPos == tmpStart + 1;
|
||||
break;
|
||||
case UpdateOp.REMOVE:
|
||||
continuous = updatedPos == tmpStart;
|
||||
break;
|
||||
}
|
||||
if (continuous) {
|
||||
tmpCnt++;
|
||||
} else {
|
||||
// need to dispatch this separately
|
||||
UpdateOp tmp = obtainUpdateOp(op.cmd, tmpStart, tmpCnt);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "need to dispatch separately " + tmp);
|
||||
}
|
||||
dispatchFirstPassAndUpdateViewHolders(tmp, offsetPositionForPartial);
|
||||
recycleUpdateOp(tmp);
|
||||
if (op.cmd == UpdateOp.UPDATE) {
|
||||
offsetPositionForPartial += tmpCnt;
|
||||
}
|
||||
tmpStart = updatedPos;// need to remove previously dispatched
|
||||
tmpCnt = 1;
|
||||
}
|
||||
}
|
||||
recycleUpdateOp(op);
|
||||
if (tmpCnt > 0) {
|
||||
UpdateOp tmp = obtainUpdateOp(op.cmd, tmpStart, tmpCnt);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "dispatching:" + tmp);
|
||||
}
|
||||
dispatchFirstPassAndUpdateViewHolders(tmp, offsetPositionForPartial);
|
||||
recycleUpdateOp(tmp);
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "post dispatch");
|
||||
Log.d(TAG, "postponed state after:");
|
||||
for (UpdateOp updateOp : mPostponedList) {
|
||||
Log.d(TAG, updateOp.toString());
|
||||
}
|
||||
Log.d(TAG, "----");
|
||||
}
|
||||
}
|
||||
|
||||
void dispatchFirstPassAndUpdateViewHolders(UpdateOp op, int offsetStart) {
|
||||
mCallback.onDispatchFirstPass(op);
|
||||
switch (op.cmd) {
|
||||
case UpdateOp.REMOVE:
|
||||
mCallback.offsetPositionsForRemovingInvisible(offsetStart, op.itemCount);
|
||||
break;
|
||||
case UpdateOp.UPDATE:
|
||||
mCallback.markViewHoldersUpdated(offsetStart, op.itemCount);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("only remove and update ops can be dispatched"
|
||||
+ " in first pass");
|
||||
}
|
||||
}
|
||||
|
||||
private int updatePositionWithPostponed(int pos, int cmd) {
|
||||
final int count = mPostponedList.size();
|
||||
for (int i = count - 1; i >= 0; i--) {
|
||||
UpdateOp postponed = mPostponedList.get(i);
|
||||
if (postponed.cmd == UpdateOp.MOVE) {
|
||||
int start, end;
|
||||
if (postponed.positionStart < postponed.itemCount) {
|
||||
start = postponed.positionStart;
|
||||
end = postponed.itemCount;
|
||||
} else {
|
||||
start = postponed.itemCount;
|
||||
end = postponed.positionStart;
|
||||
}
|
||||
if (pos >= start && pos <= end) {
|
||||
//i'm affected
|
||||
if (start == postponed.positionStart) {
|
||||
if (cmd == UpdateOp.ADD) {
|
||||
postponed.itemCount++;
|
||||
} else if (cmd == UpdateOp.REMOVE) {
|
||||
postponed.itemCount--;
|
||||
}
|
||||
// op moved to left, move it right to revert
|
||||
pos++;
|
||||
} else {
|
||||
if (cmd == UpdateOp.ADD) {
|
||||
postponed.positionStart++;
|
||||
} else if (cmd == UpdateOp.REMOVE) {
|
||||
postponed.positionStart--;
|
||||
}
|
||||
// op was moved right, move left to revert
|
||||
pos--;
|
||||
}
|
||||
} else if (pos < postponed.positionStart) {
|
||||
// postponed MV is outside the dispatched OP. if it is before, offset
|
||||
if (cmd == UpdateOp.ADD) {
|
||||
postponed.positionStart++;
|
||||
postponed.itemCount++;
|
||||
} else if (cmd == UpdateOp.REMOVE) {
|
||||
postponed.positionStart--;
|
||||
postponed.itemCount--;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (postponed.positionStart <= pos) {
|
||||
if (postponed.cmd == UpdateOp.ADD) {
|
||||
pos -= postponed.itemCount;
|
||||
} else if (postponed.cmd == UpdateOp.REMOVE) {
|
||||
pos += postponed.itemCount;
|
||||
}
|
||||
} else {
|
||||
if (cmd == UpdateOp.ADD) {
|
||||
postponed.positionStart++;
|
||||
} else if (cmd == UpdateOp.REMOVE) {
|
||||
postponed.positionStart--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "dispath (step" + i + ")");
|
||||
Log.d(TAG, "postponed state:" + i + ", pos:" + pos);
|
||||
for (UpdateOp updateOp : mPostponedList) {
|
||||
Log.d(TAG, updateOp.toString());
|
||||
}
|
||||
Log.d(TAG, "----");
|
||||
}
|
||||
}
|
||||
for (int i = mPostponedList.size() - 1; i >= 0; i--) {
|
||||
UpdateOp op = mPostponedList.get(i);
|
||||
if (op.cmd == UpdateOp.MOVE) {
|
||||
if (op.itemCount == op.positionStart || op.itemCount < 0) {
|
||||
mPostponedList.remove(i);
|
||||
recycleUpdateOp(op);
|
||||
}
|
||||
} else if (op.itemCount <= 0) {
|
||||
mPostponedList.remove(i);
|
||||
recycleUpdateOp(op);
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
private boolean canFindInPreLayout(int position) {
|
||||
final int count = mPostponedList.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
UpdateOp op = mPostponedList.get(i);
|
||||
if (op.cmd == UpdateOp.MOVE) {
|
||||
if (findPositionOffset(op.itemCount, i + 1) == position) {
|
||||
return true;
|
||||
}
|
||||
} else if (op.cmd == UpdateOp.ADD) {
|
||||
// TODO optimize.
|
||||
final int end = op.positionStart + op.itemCount;
|
||||
for (int pos = op.positionStart; pos < end; pos++) {
|
||||
if (findPositionOffset(pos, i + 1) == position) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void applyAdd(UpdateOp op) {
|
||||
postponeAndUpdateViewHolders(op);
|
||||
}
|
||||
|
||||
private void postponeAndUpdateViewHolders(UpdateOp op) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "postponing " + op);
|
||||
}
|
||||
// Utils.log("add UpdateOp to PostponedList");
|
||||
mPostponedList.add(op);
|
||||
// Utils.log("op" + op.positionStart + "=" + op.itemCount);
|
||||
switch (op.cmd) {
|
||||
case UpdateOp.ADD:
|
||||
mCallback.offsetPositionsForAdd(op.positionStart, op.itemCount);
|
||||
break;
|
||||
case UpdateOp.MOVE:
|
||||
mCallback.offsetPositionsForMove(op.positionStart, op.itemCount);
|
||||
break;
|
||||
case UpdateOp.REMOVE:
|
||||
mCallback.offsetPositionsForRemovingLaidOutOrNewView(op.positionStart,
|
||||
op.itemCount);
|
||||
break;
|
||||
case UpdateOp.UPDATE:
|
||||
mCallback.markViewHoldersUpdated(op.positionStart, op.itemCount);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown update op type for " + op);
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasPendingUpdates() {
|
||||
return mPendingUpdates.size() > 0;
|
||||
}
|
||||
|
||||
int findPositionOffset(int position) {
|
||||
return findPositionOffset(position, 0);
|
||||
}
|
||||
|
||||
int findPositionOffset(int position, int firstPostponedItem) {
|
||||
int count = mPostponedList.size();
|
||||
for (int i = firstPostponedItem; i < count; ++i) {
|
||||
UpdateOp op = mPostponedList.get(i);
|
||||
if (op.cmd == UpdateOp.MOVE) {
|
||||
if (op.positionStart == position) {
|
||||
position = op.itemCount;
|
||||
} else {
|
||||
if (op.positionStart < position) {
|
||||
position--; // like a remove
|
||||
}
|
||||
if (op.itemCount <= position) {
|
||||
position++; // like an add
|
||||
}
|
||||
}
|
||||
} else if (op.positionStart <= position) {
|
||||
if (op.cmd == UpdateOp.REMOVE) {
|
||||
if (position < op.positionStart + op.itemCount) {
|
||||
return -1;
|
||||
}
|
||||
position -= op.itemCount;
|
||||
} else if (op.cmd == UpdateOp.ADD) {
|
||||
position += op.itemCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if updates should be processed.
|
||||
*/
|
||||
boolean onItemRangeChanged(int positionStart, int itemCount) {
|
||||
mPendingUpdates.add(obtainUpdateOp(UpdateOp.UPDATE, positionStart, itemCount));
|
||||
return mPendingUpdates.size() == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if updates should be processed.
|
||||
*/
|
||||
boolean onItemRangeInserted(int positionStart, int itemCount) {
|
||||
mPendingUpdates.add(obtainUpdateOp(UpdateOp.ADD, positionStart, itemCount));
|
||||
return mPendingUpdates.size() == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if updates should be processed.
|
||||
*/
|
||||
boolean onItemRangeRemoved(int positionStart, int itemCount) {
|
||||
mPendingUpdates.add(obtainUpdateOp(UpdateOp.REMOVE, positionStart, itemCount));
|
||||
return mPendingUpdates.size() == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if updates should be processed.
|
||||
*/
|
||||
boolean onItemRangeMoved(int from, int to, int itemCount) {
|
||||
if (from == to) {
|
||||
return false;//no-op
|
||||
}
|
||||
if (itemCount != 1) {
|
||||
throw new IllegalArgumentException("Moving more than 1 item is not supported yet");
|
||||
}
|
||||
mPendingUpdates.add(obtainUpdateOp(UpdateOp.MOVE, from, to));
|
||||
return mPendingUpdates.size() == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips pre-processing and applies all updates in one pass.
|
||||
*/
|
||||
void consumeUpdatesInOnePass() {
|
||||
// we still consume postponed updates (if there is) in case there was a pre-process call
|
||||
// w/o a matching consumePostponedUpdates.
|
||||
consumePostponedUpdates();
|
||||
final int count = mPendingUpdates.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
UpdateOp op = mPendingUpdates.get(i);
|
||||
switch (op.cmd) {
|
||||
case UpdateOp.ADD:
|
||||
mCallback.onDispatchSecondPass(op);
|
||||
mCallback.offsetPositionsForAdd(op.positionStart, op.itemCount);
|
||||
break;
|
||||
case UpdateOp.REMOVE:
|
||||
mCallback.onDispatchSecondPass(op);
|
||||
mCallback.offsetPositionsForRemovingInvisible(op.positionStart, op.itemCount);
|
||||
break;
|
||||
case UpdateOp.UPDATE:
|
||||
mCallback.onDispatchSecondPass(op);
|
||||
mCallback.markViewHoldersUpdated(op.positionStart, op.itemCount);
|
||||
break;
|
||||
case UpdateOp.MOVE:
|
||||
mCallback.onDispatchSecondPass(op);
|
||||
mCallback.offsetPositionsForMove(op.positionStart, op.itemCount);
|
||||
break;
|
||||
}
|
||||
if (mOnItemProcessedCallback != null) {
|
||||
mOnItemProcessedCallback.run();
|
||||
}
|
||||
}
|
||||
recycleUpdateOpsAndClearList(mPendingUpdates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Queued operation to happen when child views are updated.
|
||||
*/
|
||||
static class UpdateOp {
|
||||
|
||||
static final int ADD = 0;
|
||||
|
||||
static final int REMOVE = 1;
|
||||
|
||||
static final int UPDATE = 2;
|
||||
|
||||
static final int MOVE = 3;
|
||||
|
||||
static final int POOL_SIZE = 30;
|
||||
|
||||
int cmd;
|
||||
|
||||
int positionStart;
|
||||
|
||||
// holds the target position if this is a MOVE
|
||||
int itemCount;
|
||||
|
||||
UpdateOp(int cmd, int positionStart, int itemCount) {
|
||||
this.cmd = cmd;
|
||||
this.positionStart = positionStart;
|
||||
this.itemCount = itemCount;
|
||||
}
|
||||
|
||||
String cmdToString() {
|
||||
switch (cmd) {
|
||||
case ADD:
|
||||
return "add";
|
||||
case REMOVE:
|
||||
return "rm";
|
||||
case UPDATE:
|
||||
return "up";
|
||||
case MOVE:
|
||||
return "mv";
|
||||
}
|
||||
return "??";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + cmdToString() + ",s:" + positionStart + "c:" + itemCount + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UpdateOp op = (UpdateOp) o;
|
||||
|
||||
if (cmd != op.cmd) {
|
||||
return false;
|
||||
}
|
||||
if (cmd == MOVE && Math.abs(itemCount - positionStart) == 1) {
|
||||
// reverse of this is also true
|
||||
if (itemCount == op.positionStart && positionStart == op.itemCount) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (itemCount != op.itemCount) {
|
||||
return false;
|
||||
}
|
||||
if (positionStart != op.positionStart) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = cmd;
|
||||
result = 31 * result + positionStart;
|
||||
result = 31 * result + itemCount;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateOp obtainUpdateOp(int cmd, int positionStart, int itemCount) {
|
||||
UpdateOp op = mUpdateOpPool.acquire();
|
||||
if (op == null) {
|
||||
op = new UpdateOp(cmd, positionStart, itemCount);
|
||||
} else {
|
||||
op.cmd = cmd;
|
||||
op.positionStart = positionStart;
|
||||
op.itemCount = itemCount;
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recycleUpdateOp(UpdateOp op) {
|
||||
if (!mDisableRecycler) {
|
||||
mUpdateOpPool.release(op);
|
||||
}
|
||||
}
|
||||
|
||||
void recycleUpdateOpsAndClearList(List<UpdateOp> ops) {
|
||||
final int count = ops.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
recycleUpdateOp(ops.get(i));
|
||||
}
|
||||
ops.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Contract between AdapterHelper and RecyclerView.
|
||||
*/
|
||||
static interface Callback {
|
||||
|
||||
ViewHolder findViewHolder(int position);
|
||||
|
||||
void offsetPositionsForRemovingInvisible(int positionStart, int itemCount);
|
||||
|
||||
void offsetPositionsForRemovingLaidOutOrNewView(int positionStart, int itemCount);
|
||||
|
||||
void markViewHoldersUpdated(int positionStart, int itemCount);
|
||||
|
||||
void onDispatchFirstPass(UpdateOp updateOp);
|
||||
|
||||
void onDispatchSecondPass(UpdateOp updateOp);
|
||||
|
||||
void offsetPositionsForAdd(int positionStart, int itemCount);
|
||||
|
||||
void offsetPositionsForMove(int from, int to);
|
||||
}
|
||||
}
|
||||
@ -1,484 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 android.support.v7.widget;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Helper class to manage children.
|
||||
* <p>
|
||||
* It wraps a RecyclerView and adds ability to hide some children. There are two sets of methods
|
||||
* provided by this class. <b>Regular</b> methods are the ones that replicate ViewGroup methods
|
||||
* like getChildAt, getChildCount etc. These methods ignore hidden children.
|
||||
* <p>
|
||||
* When RecyclerView needs direct access to the view group children, it can call unfiltered
|
||||
* methods like get getUnfilteredChildCount or getUnfilteredChildAt.
|
||||
*/
|
||||
class ChildHelper {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final String TAG = "ChildrenHelper";
|
||||
|
||||
final Callback mCallback;
|
||||
|
||||
final Bucket mBucket;
|
||||
|
||||
final List<View> mHiddenViews;
|
||||
|
||||
ChildHelper(Callback callback) {
|
||||
mCallback = callback;
|
||||
mBucket = new Bucket();
|
||||
mHiddenViews = new ArrayList<View>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a view to the ViewGroup
|
||||
*
|
||||
* @param child View to add.
|
||||
* @param hidden If set to true, this item will be invisible from regular methods.
|
||||
*/
|
||||
void addView(View child, boolean hidden) {
|
||||
addView(child, -1, hidden);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a view to the ViewGroup at an index
|
||||
*
|
||||
* @param child View to add.
|
||||
* @param index Index of the child from the regular perspective (excluding hidden views).
|
||||
* ChildHelper offsets this index to actual ViewGroup index.
|
||||
* @param hidden If set to true, this item will be invisible from regular methods.
|
||||
*/
|
||||
void addView(View child, int index, boolean hidden) {
|
||||
final int offset;
|
||||
if (index < 0) {
|
||||
offset = mCallback.getChildCount();
|
||||
} else {
|
||||
offset = getOffset(index);
|
||||
}
|
||||
mCallback.addView(child, offset);
|
||||
mBucket.insert(offset, hidden);
|
||||
if (hidden) {
|
||||
mHiddenViews.add(child);
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "addViewAt " + index + ",h:" + hidden + ", " + this);
|
||||
}
|
||||
}
|
||||
|
||||
private int getOffset(int index) {
|
||||
if (index < 0) {
|
||||
return -1; //anything below 0 won't work as diff will be undefined.
|
||||
}
|
||||
final int limit = mCallback.getChildCount();
|
||||
int offset = index;
|
||||
while (offset < limit) {
|
||||
final int removedBefore = mBucket.countOnesBefore(offset);
|
||||
final int diff = index - (offset - removedBefore);
|
||||
if (diff == 0) {
|
||||
while (mBucket.get(offset)) { // ensure this offset is not hidden
|
||||
offset ++;
|
||||
}
|
||||
return offset;
|
||||
} else {
|
||||
offset += diff;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the provided View from underlying RecyclerView.
|
||||
*
|
||||
* @param view The view to remove.
|
||||
*/
|
||||
void removeView(View view) {
|
||||
int index = mCallback.indexOfChild(view);
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
mCallback.removeViewAt(index);
|
||||
if (mBucket.remove(index)) {
|
||||
mHiddenViews.remove(view);
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "remove View off:" + index + "," + this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the view at the provided index from RecyclerView.
|
||||
*
|
||||
* @param index Index of the child from the regular perspective (excluding hidden views).
|
||||
* ChildHelper offsets this index to actual ViewGroup index.
|
||||
*/
|
||||
void removeViewAt(int index) {
|
||||
final int offset = getOffset(index);
|
||||
final View view = mCallback.getChildAt(offset);
|
||||
if (view == null) {
|
||||
return;
|
||||
}
|
||||
mCallback.removeViewAt(offset);
|
||||
if (mBucket.remove(offset)) {
|
||||
mHiddenViews.remove(view);
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "removeViewAt " + index + ", off:" + offset + ", " + this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the child at provided index.
|
||||
*
|
||||
* @param index Index of the child to return in regular perspective.
|
||||
*/
|
||||
View getChildAt(int index) {
|
||||
final int offset = getOffset(index);
|
||||
return mCallback.getChildAt(offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all views from the ViewGroup including the hidden ones.
|
||||
*/
|
||||
void removeAllViewsUnfiltered() {
|
||||
mCallback.removeAllViews();
|
||||
mBucket.reset();
|
||||
mHiddenViews.clear();
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "removeAllViewsUnfiltered");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This can be used to find a disappearing view by position.
|
||||
*
|
||||
* @param position The adapter position of the item.
|
||||
* @param type View type, can be {@link RecyclerView#INVALID_TYPE}.
|
||||
* @return A hidden view with a valid ViewHolder that matches the position and type.
|
||||
*/
|
||||
View findHiddenNonRemovedView(int position, int type) {
|
||||
final int count = mHiddenViews.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final View view = mHiddenViews.get(i);
|
||||
RecyclerView.ViewHolder holder = mCallback.getChildViewHolder(view);
|
||||
if (holder.getPosition() == position && !holder.isInvalid() &&
|
||||
(type == RecyclerView.INVALID_TYPE || holder.getItemViewType() == type)) {
|
||||
return view;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches the provided view to the underlying ViewGroup.
|
||||
*
|
||||
* @param child Child to attach.
|
||||
* @param index Index of the child to attach in regular perspective.
|
||||
* @param layoutParams LayoutParams for the child.
|
||||
* @param hidden If set to true, this item will be invisible to the regular methods.
|
||||
*/
|
||||
void attachViewToParent(View child, int index, ViewGroup.LayoutParams layoutParams,
|
||||
boolean hidden) {
|
||||
final int offset;
|
||||
if (index < 0) {
|
||||
offset = mCallback.getChildCount();
|
||||
} else {
|
||||
offset = getOffset(index);
|
||||
}
|
||||
mCallback.attachViewToParent(child, offset, layoutParams);
|
||||
mBucket.insert(offset, hidden);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "attach view to parent index:" + index + ",off:" + offset + "," +
|
||||
"h:" + hidden + ", " + this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of children that are not hidden.
|
||||
*
|
||||
* @return Number of children that are not hidden.
|
||||
* @see #getChildAt(int)
|
||||
*/
|
||||
int getChildCount() {
|
||||
return mCallback.getChildCount() - mHiddenViews.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total number of children.
|
||||
*
|
||||
* @return The total number of children including the hidden views.
|
||||
* @see #getUnfilteredChildAt(int)
|
||||
*/
|
||||
int getUnfilteredChildCount() {
|
||||
return mCallback.getChildCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a child by ViewGroup offset. ChildHelper won't offset this index.
|
||||
*
|
||||
* @param index ViewGroup index of the child to return.
|
||||
* @return The view in the provided index.
|
||||
*/
|
||||
View getUnfilteredChildAt(int index) {
|
||||
return mCallback.getChildAt(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detaches the view at the provided index.
|
||||
*
|
||||
* @param index Index of the child to return in regular perspective.
|
||||
*/
|
||||
void detachViewFromParent(int index) {
|
||||
final int offset = getOffset(index);
|
||||
mCallback.detachViewFromParent(offset);
|
||||
mBucket.remove(offset);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "detach view from parent " + index + ", off:" + offset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the child in regular perspective.
|
||||
*
|
||||
* @param child The child whose index will be returned.
|
||||
* @return The regular perspective index of the child or -1 if it does not exists.
|
||||
*/
|
||||
int indexOfChild(View child) {
|
||||
final int index = mCallback.indexOfChild(child);
|
||||
if (index == -1) {
|
||||
return -1;
|
||||
}
|
||||
if (mBucket.get(index)) {
|
||||
if (DEBUG) {
|
||||
throw new IllegalArgumentException("cannot get index of a hidden child");
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
// reverse the index
|
||||
return index - mBucket.countOnesBefore(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a View is visible to LayoutManager or not.
|
||||
*
|
||||
* @param view The child view to check. Should be a child of the Callback.
|
||||
* @return True if the View is not visible to LayoutManager
|
||||
*/
|
||||
boolean isHidden(View view) {
|
||||
return mHiddenViews.contains(view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks a child view as hidden.
|
||||
*
|
||||
* @param view The view to hide.
|
||||
*/
|
||||
void hide(View view) {
|
||||
final int offset = mCallback.indexOfChild(view);
|
||||
if (offset < 0) {
|
||||
throw new IllegalArgumentException("view is not a child, cannot hide " + view);
|
||||
}
|
||||
if (DEBUG && mBucket.get(offset)) {
|
||||
throw new RuntimeException("trying to hide same view twice, how come ? " + view);
|
||||
}
|
||||
mBucket.set(offset);
|
||||
mHiddenViews.add(view);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "hiding child " + view + " at offset " + offset+ ", " + this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return mBucket.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a view from the ViewGroup if it is hidden.
|
||||
*
|
||||
* @param view The view to remove.
|
||||
* @return True if the View is found and it is hidden. False otherwise.
|
||||
*/
|
||||
boolean removeViewIfHidden(View view) {
|
||||
final int index = mCallback.indexOfChild(view);
|
||||
if (index == -1) {
|
||||
if (mHiddenViews.remove(view) && DEBUG) {
|
||||
throw new IllegalStateException("view is in hidden list but not in view group");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (mBucket.get(index)) {
|
||||
mBucket.remove(index);
|
||||
mCallback.removeViewAt(index);
|
||||
if (!mHiddenViews.remove(view) && DEBUG) {
|
||||
throw new IllegalStateException(
|
||||
"removed a hidden view but it is not in hidden views list");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bitset implementation that provides methods to offset indices.
|
||||
*/
|
||||
static class Bucket {
|
||||
|
||||
final static int BITS_PER_WORD = Long.SIZE;
|
||||
|
||||
final static long LAST_BIT = 1L << (Long.SIZE - 1);
|
||||
|
||||
long mData = 0;
|
||||
|
||||
Bucket next;
|
||||
|
||||
void set(int index) {
|
||||
if (index >= BITS_PER_WORD) {
|
||||
ensureNext();
|
||||
next.set(index - BITS_PER_WORD);
|
||||
} else {
|
||||
mData |= 1L << index;
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureNext() {
|
||||
if (next == null) {
|
||||
next = new Bucket();
|
||||
}
|
||||
}
|
||||
|
||||
void clear(int index) {
|
||||
if (index >= BITS_PER_WORD) {
|
||||
if (next != null) {
|
||||
next.clear(index - BITS_PER_WORD);
|
||||
}
|
||||
} else {
|
||||
mData &= ~(1L << index);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
boolean get(int index) {
|
||||
if (index >= BITS_PER_WORD) {
|
||||
ensureNext();
|
||||
return next.get(index - BITS_PER_WORD);
|
||||
} else {
|
||||
return (mData & (1L << index)) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
mData = 0;
|
||||
if (next != null) {
|
||||
next.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void insert(int index, boolean value) {
|
||||
if (index >= BITS_PER_WORD) {
|
||||
ensureNext();
|
||||
next.insert(index - BITS_PER_WORD, value);
|
||||
} else {
|
||||
final boolean lastBit = (mData & LAST_BIT) != 0;
|
||||
long mask = (1L << index) - 1;
|
||||
final long before = mData & mask;
|
||||
final long after = ((mData & ~mask)) << 1;
|
||||
mData = before | after;
|
||||
if (value) {
|
||||
set(index);
|
||||
} else {
|
||||
clear(index);
|
||||
}
|
||||
if (lastBit || next != null) {
|
||||
ensureNext();
|
||||
next.insert(0, lastBit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean remove(int index) {
|
||||
if (index >= BITS_PER_WORD) {
|
||||
ensureNext();
|
||||
return next.remove(index - BITS_PER_WORD);
|
||||
} else {
|
||||
long mask = (1L << index);
|
||||
final boolean value = (mData & mask) != 0;
|
||||
mData &= ~mask;
|
||||
mask = mask - 1;
|
||||
final long before = mData & mask;
|
||||
// cannot use >> because it adds one.
|
||||
final long after = Long.rotateRight(mData & ~mask, 1);
|
||||
mData = before | after;
|
||||
if (next != null) {
|
||||
if (next.get(0)) {
|
||||
set(BITS_PER_WORD - 1);
|
||||
}
|
||||
next.remove(0);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
int countOnesBefore(int index) {
|
||||
if (next == null) {
|
||||
if (index >= BITS_PER_WORD) {
|
||||
return Long.bitCount(mData);
|
||||
}
|
||||
return Long.bitCount(mData & ((1L << index) - 1));
|
||||
}
|
||||
if (index < BITS_PER_WORD) {
|
||||
return Long.bitCount(mData & ((1L << index) - 1));
|
||||
} else {
|
||||
return next.countOnesBefore(index - BITS_PER_WORD) + Long.bitCount(mData);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return next == null ? Long.toBinaryString(mData)
|
||||
: next.toString() + "xx" + Long.toBinaryString(mData);
|
||||
}
|
||||
}
|
||||
|
||||
static interface Callback {
|
||||
|
||||
int getChildCount();
|
||||
|
||||
void addView(View child, int index);
|
||||
|
||||
int indexOfChild(View view);
|
||||
|
||||
void removeViewAt(int index);
|
||||
|
||||
View getChildAt(int offset);
|
||||
|
||||
void removeAllViews();
|
||||
|
||||
RecyclerView.ViewHolder getChildViewHolder(View view);
|
||||
|
||||
void attachViewToParent(View child, int index, ViewGroup.LayoutParams layoutParams);
|
||||
|
||||
void detachViewFromParent(int offset);
|
||||
}
|
||||
}
|
||||
@ -1,628 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 android.support.v7.widget;
|
||||
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.support.v4.view.ViewPropertyAnimatorCompat;
|
||||
import android.support.v4.view.ViewPropertyAnimatorListener;
|
||||
import android.support.v7.widget.RecyclerView.ViewHolder;
|
||||
import android.view.View;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This implementation of {@link RecyclerView.ItemAnimator} provides basic
|
||||
* animations on remove, add, and move events that happen to the items in
|
||||
* a RecyclerView. RecyclerView uses a DefaultItemAnimator by default.
|
||||
*
|
||||
* @see RecyclerView#setItemAnimator(RecyclerView.ItemAnimator)
|
||||
*/
|
||||
public class DefaultItemAnimator extends RecyclerView.ItemAnimator {
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private ArrayList<ViewHolder> mPendingRemovals = new ArrayList<ViewHolder>();
|
||||
private ArrayList<ViewHolder> mPendingAdditions = new ArrayList<ViewHolder>();
|
||||
private ArrayList<MoveInfo> mPendingMoves = new ArrayList<MoveInfo>();
|
||||
private ArrayList<ChangeInfo> mPendingChanges = new ArrayList<ChangeInfo>();
|
||||
|
||||
private ArrayList<ArrayList<ViewHolder>> mAdditionsList =
|
||||
new ArrayList<ArrayList<ViewHolder>>();
|
||||
private ArrayList<ArrayList<MoveInfo>> mMovesList = new ArrayList<ArrayList<MoveInfo>>();
|
||||
private ArrayList<ArrayList<ChangeInfo>> mChangesList = new ArrayList<ArrayList<ChangeInfo>>();
|
||||
|
||||
private ArrayList<ViewHolder> mAddAnimations = new ArrayList<ViewHolder>();
|
||||
private ArrayList<ViewHolder> mMoveAnimations = new ArrayList<ViewHolder>();
|
||||
private ArrayList<ViewHolder> mRemoveAnimations = new ArrayList<ViewHolder>();
|
||||
private ArrayList<ViewHolder> mChangeAnimations = new ArrayList<ViewHolder>();
|
||||
|
||||
private static class MoveInfo {
|
||||
public ViewHolder holder;
|
||||
public int fromX, fromY, toX, toY;
|
||||
|
||||
private MoveInfo(ViewHolder holder, int fromX, int fromY, int toX, int toY) {
|
||||
this.holder = holder;
|
||||
this.fromX = fromX;
|
||||
this.fromY = fromY;
|
||||
this.toX = toX;
|
||||
this.toY = toY;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ChangeInfo {
|
||||
public ViewHolder oldHolder, newHolder;
|
||||
public int fromX, fromY, toX, toY;
|
||||
private ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder) {
|
||||
this.oldHolder = oldHolder;
|
||||
this.newHolder = newHolder;
|
||||
}
|
||||
|
||||
private ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder,
|
||||
int fromX, int fromY, int toX, int toY) {
|
||||
this(oldHolder, newHolder);
|
||||
this.fromX = fromX;
|
||||
this.fromY = fromY;
|
||||
this.toX = toX;
|
||||
this.toY = toY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ChangeInfo{" +
|
||||
"oldHolder=" + oldHolder +
|
||||
", newHolder=" + newHolder +
|
||||
", fromX=" + fromX +
|
||||
", fromY=" + fromY +
|
||||
", toX=" + toX +
|
||||
", toY=" + toY +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runPendingAnimations() {
|
||||
boolean removalsPending = !mPendingRemovals.isEmpty();
|
||||
boolean movesPending = !mPendingMoves.isEmpty();
|
||||
boolean changesPending = !mPendingChanges.isEmpty();
|
||||
boolean additionsPending = !mPendingAdditions.isEmpty();
|
||||
if (!removalsPending && !movesPending && !additionsPending && !changesPending) {
|
||||
// nothing to animate
|
||||
return;
|
||||
}
|
||||
// First, remove stuff
|
||||
for (ViewHolder holder : mPendingRemovals) {
|
||||
animateRemoveImpl(holder);
|
||||
}
|
||||
mPendingRemovals.clear();
|
||||
// Next, move stuff
|
||||
if (movesPending) {
|
||||
final ArrayList<MoveInfo> moves = new ArrayList<MoveInfo>();
|
||||
moves.addAll(mPendingMoves);
|
||||
mMovesList.add(moves);
|
||||
mPendingMoves.clear();
|
||||
Runnable mover = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (MoveInfo moveInfo : moves) {
|
||||
animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY,
|
||||
moveInfo.toX, moveInfo.toY);
|
||||
}
|
||||
moves.clear();
|
||||
mMovesList.remove(moves);
|
||||
}
|
||||
};
|
||||
if (removalsPending) {
|
||||
View view = moves.get(0).holder.itemView;
|
||||
ViewCompat.postOnAnimationDelayed(view, mover, getRemoveDuration());
|
||||
} else {
|
||||
mover.run();
|
||||
}
|
||||
}
|
||||
// Next, change stuff, to run in parallel with move animations
|
||||
if (changesPending) {
|
||||
final ArrayList<ChangeInfo> changes = new ArrayList<ChangeInfo>();
|
||||
changes.addAll(mPendingChanges);
|
||||
mChangesList.add(changes);
|
||||
mPendingChanges.clear();
|
||||
Runnable changer = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (ChangeInfo change : changes) {
|
||||
animateChangeImpl(change);
|
||||
}
|
||||
changes.clear();
|
||||
mChangesList.remove(changes);
|
||||
}
|
||||
};
|
||||
if (removalsPending) {
|
||||
ViewHolder holder = changes.get(0).oldHolder;
|
||||
ViewCompat.postOnAnimationDelayed(holder.itemView, changer, getRemoveDuration());
|
||||
} else {
|
||||
changer.run();
|
||||
}
|
||||
}
|
||||
// Next, add stuff
|
||||
if (additionsPending) {
|
||||
final ArrayList<ViewHolder> additions = new ArrayList<ViewHolder>();
|
||||
additions.addAll(mPendingAdditions);
|
||||
mAdditionsList.add(additions);
|
||||
mPendingAdditions.clear();
|
||||
Runnable adder = new Runnable() {
|
||||
public void run() {
|
||||
for (ViewHolder holder : additions) {
|
||||
animateAddImpl(holder);
|
||||
}
|
||||
additions.clear();
|
||||
mAdditionsList.remove(additions);
|
||||
}
|
||||
};
|
||||
if (removalsPending || movesPending || changesPending) {
|
||||
long removeDuration = removalsPending ? getRemoveDuration() : 0;
|
||||
long moveDuration = movesPending ? getMoveDuration() : 0;
|
||||
long changeDuration = changesPending ? getChangeDuration() : 0;
|
||||
long totalDelay = removeDuration + Math.max(moveDuration, changeDuration);
|
||||
View view = additions.get(0).itemView;
|
||||
ViewCompat.postOnAnimationDelayed(view, adder, totalDelay);
|
||||
} else {
|
||||
adder.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean animateRemove(final ViewHolder holder) {
|
||||
endAnimation(holder);
|
||||
mPendingRemovals.add(holder);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void animateRemoveImpl(final ViewHolder holder) {
|
||||
final View view = holder.itemView;
|
||||
final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view);
|
||||
animation.setDuration(getRemoveDuration())
|
||||
.alpha(0).setListener(new VpaListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(View view) {
|
||||
dispatchRemoveStarting(holder);
|
||||
}
|
||||
@Override
|
||||
public void onAnimationEnd(View view) {
|
||||
animation.setListener(null);
|
||||
ViewCompat.setAlpha(view, 1);
|
||||
dispatchRemoveFinished(holder);
|
||||
mRemoveAnimations.remove(holder);
|
||||
dispatchFinishedWhenDone();
|
||||
}
|
||||
}).start();
|
||||
mRemoveAnimations.add(holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean animateAdd(final ViewHolder holder) {
|
||||
endAnimation(holder);
|
||||
ViewCompat.setAlpha(holder.itemView, 0);
|
||||
mPendingAdditions.add(holder);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void animateAddImpl(final ViewHolder holder) {
|
||||
final View view = holder.itemView;
|
||||
mAddAnimations.add(holder);
|
||||
final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view);
|
||||
animation.alpha(1).setDuration(getAddDuration()).
|
||||
setListener(new VpaListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(View view) {
|
||||
dispatchAddStarting(holder);
|
||||
}
|
||||
@Override
|
||||
public void onAnimationCancel(View view) {
|
||||
ViewCompat.setAlpha(view, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(View view) {
|
||||
animation.setListener(null);
|
||||
dispatchAddFinished(holder);
|
||||
mAddAnimations.remove(holder);
|
||||
dispatchFinishedWhenDone();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean animateMove(final ViewHolder holder, int fromX, int fromY,
|
||||
int toX, int toY) {
|
||||
final View view = holder.itemView;
|
||||
fromX += ViewCompat.getTranslationX(holder.itemView);
|
||||
fromY += ViewCompat.getTranslationY(holder.itemView);
|
||||
endAnimation(holder);
|
||||
int deltaX = toX - fromX;
|
||||
int deltaY = toY - fromY;
|
||||
if (deltaX == 0 && deltaY == 0) {
|
||||
dispatchMoveFinished(holder);
|
||||
return false;
|
||||
}
|
||||
if (deltaX != 0) {
|
||||
ViewCompat.setTranslationX(view, -deltaX);
|
||||
}
|
||||
if (deltaY != 0) {
|
||||
ViewCompat.setTranslationY(view, -deltaY);
|
||||
}
|
||||
mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY));
|
||||
return true;
|
||||
}
|
||||
|
||||
private void animateMoveImpl(final ViewHolder holder, int fromX, int fromY, int toX, int toY) {
|
||||
final View view = holder.itemView;
|
||||
final int deltaX = toX - fromX;
|
||||
final int deltaY = toY - fromY;
|
||||
if (deltaX != 0) {
|
||||
ViewCompat.animate(view).translationX(0);
|
||||
}
|
||||
if (deltaY != 0) {
|
||||
ViewCompat.animate(view).translationY(0);
|
||||
}
|
||||
// TODO: make EndActions end listeners instead, since end actions aren't called when
|
||||
// vpas are canceled (and can't end them. why?)
|
||||
// need listener functionality in VPACompat for this. Ick.
|
||||
mMoveAnimations.add(holder);
|
||||
final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view);
|
||||
animation.setDuration(getMoveDuration()).setListener(new VpaListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(View view) {
|
||||
dispatchMoveStarting(holder);
|
||||
}
|
||||
@Override
|
||||
public void onAnimationCancel(View view) {
|
||||
if (deltaX != 0) {
|
||||
ViewCompat.setTranslationX(view, 0);
|
||||
}
|
||||
if (deltaY != 0) {
|
||||
ViewCompat.setTranslationY(view, 0);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onAnimationEnd(View view) {
|
||||
animation.setListener(null);
|
||||
dispatchMoveFinished(holder);
|
||||
mMoveAnimations.remove(holder);
|
||||
dispatchFinishedWhenDone();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder,
|
||||
int fromX, int fromY, int toX, int toY) {
|
||||
final float prevTranslationX = ViewCompat.getTranslationX(oldHolder.itemView);
|
||||
final float prevTranslationY = ViewCompat.getTranslationY(oldHolder.itemView);
|
||||
final float prevAlpha = ViewCompat.getAlpha(oldHolder.itemView);
|
||||
endAnimation(oldHolder);
|
||||
int deltaX = (int) (toX - fromX - prevTranslationX);
|
||||
int deltaY = (int) (toY - fromY - prevTranslationY);
|
||||
// recover prev translation state after ending animation
|
||||
ViewCompat.setTranslationX(oldHolder.itemView, prevTranslationX);
|
||||
ViewCompat.setTranslationY(oldHolder.itemView, prevTranslationY);
|
||||
ViewCompat.setAlpha(oldHolder.itemView, prevAlpha);
|
||||
if (newHolder != null && newHolder.itemView != null) {
|
||||
// carry over translation values
|
||||
endAnimation(newHolder);
|
||||
ViewCompat.setTranslationX(newHolder.itemView, -deltaX);
|
||||
ViewCompat.setTranslationY(newHolder.itemView, -deltaY);
|
||||
ViewCompat.setAlpha(newHolder.itemView, 0);
|
||||
}
|
||||
mPendingChanges.add(new ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY));
|
||||
return true;
|
||||
}
|
||||
|
||||
private void animateChangeImpl(final ChangeInfo changeInfo) {
|
||||
final ViewHolder holder = changeInfo.oldHolder;
|
||||
final View view = holder.itemView;
|
||||
final ViewHolder newHolder = changeInfo.newHolder;
|
||||
final View newView = newHolder != null ? newHolder.itemView : null;
|
||||
mChangeAnimations.add(changeInfo.oldHolder);
|
||||
|
||||
final ViewPropertyAnimatorCompat oldViewAnim = ViewCompat.animate(view).setDuration(
|
||||
getChangeDuration());
|
||||
oldViewAnim.translationX(changeInfo.toX - changeInfo.fromX);
|
||||
oldViewAnim.translationY(changeInfo.toY - changeInfo.fromY);
|
||||
oldViewAnim.alpha(0).setListener(new VpaListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(View view) {
|
||||
dispatchChangeStarting(changeInfo.oldHolder, true);
|
||||
}
|
||||
@Override
|
||||
public void onAnimationEnd(View view) {
|
||||
oldViewAnim.setListener(null);
|
||||
ViewCompat.setAlpha(view, 1);
|
||||
ViewCompat.setTranslationX(view, 0);
|
||||
ViewCompat.setTranslationY(view, 0);
|
||||
dispatchChangeFinished(changeInfo.oldHolder, true);
|
||||
mChangeAnimations.remove(changeInfo.oldHolder);
|
||||
dispatchFinishedWhenDone();
|
||||
}
|
||||
}).start();
|
||||
if (newView != null) {
|
||||
mChangeAnimations.add(changeInfo.newHolder);
|
||||
final ViewPropertyAnimatorCompat newViewAnimation = ViewCompat.animate(newView);
|
||||
newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()).
|
||||
alpha(1).setListener(new VpaListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(View view) {
|
||||
dispatchChangeStarting(changeInfo.newHolder, false);
|
||||
}
|
||||
@Override
|
||||
public void onAnimationEnd(View view) {
|
||||
newViewAnimation.setListener(null);
|
||||
ViewCompat.setAlpha(newView, 1);
|
||||
ViewCompat.setTranslationX(newView, 0);
|
||||
ViewCompat.setTranslationY(newView, 0);
|
||||
dispatchChangeFinished(changeInfo.newHolder, false);
|
||||
mChangeAnimations.remove(changeInfo.newHolder);
|
||||
dispatchFinishedWhenDone();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
private void endChangeAnimation(List<ChangeInfo> infoList, ViewHolder item) {
|
||||
for (int i = infoList.size() - 1; i >= 0; i--) {
|
||||
ChangeInfo changeInfo = infoList.get(i);
|
||||
if (endChangeAnimationIfNecessary(changeInfo, item)) {
|
||||
if (changeInfo.oldHolder == null && changeInfo.newHolder == null) {
|
||||
infoList.remove(changeInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void endChangeAnimationIfNecessary(ChangeInfo changeInfo) {
|
||||
if (changeInfo.oldHolder != null) {
|
||||
endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder);
|
||||
}
|
||||
if (changeInfo.newHolder != null) {
|
||||
endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder);
|
||||
}
|
||||
}
|
||||
private boolean endChangeAnimationIfNecessary(ChangeInfo changeInfo, ViewHolder item) {
|
||||
boolean oldItem = false;
|
||||
if (changeInfo.newHolder == item) {
|
||||
changeInfo.newHolder = null;
|
||||
} else if (changeInfo.oldHolder == item) {
|
||||
changeInfo.oldHolder = null;
|
||||
oldItem = true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
ViewCompat.setAlpha(item.itemView, 1);
|
||||
ViewCompat.setTranslationX(item.itemView, 0);
|
||||
ViewCompat.setTranslationY(item.itemView, 0);
|
||||
dispatchChangeFinished(item, oldItem);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endAnimation(ViewHolder item) {
|
||||
final View view = item.itemView;
|
||||
// this will trigger end callback which should set properties to their target values.
|
||||
ViewCompat.animate(view).cancel();
|
||||
// TODO if some other animations are chained to end, how do we cancel them as well?
|
||||
for (int i = mPendingMoves.size() - 1; i >= 0; i--) {
|
||||
MoveInfo moveInfo = mPendingMoves.get(i);
|
||||
if (moveInfo.holder == item) {
|
||||
ViewCompat.setTranslationY(view, 0);
|
||||
ViewCompat.setTranslationX(view, 0);
|
||||
dispatchMoveFinished(item);
|
||||
mPendingMoves.remove(item);
|
||||
}
|
||||
}
|
||||
endChangeAnimation(mPendingChanges, item);
|
||||
if (mPendingRemovals.remove(item)) {
|
||||
ViewCompat.setAlpha(view, 1);
|
||||
dispatchRemoveFinished(item);
|
||||
}
|
||||
if (mPendingAdditions.remove(item)) {
|
||||
ViewCompat.setAlpha(view, 1);
|
||||
dispatchAddFinished(item);
|
||||
}
|
||||
|
||||
for (int i = mChangesList.size() - 1; i >= 0; i--) {
|
||||
ArrayList<ChangeInfo> changes = mChangesList.get(i);
|
||||
endChangeAnimation(changes, item);
|
||||
if (changes.isEmpty()) {
|
||||
mChangesList.remove(changes);
|
||||
}
|
||||
}
|
||||
for (int i = mMovesList.size() - 1; i >= 0; i--) {
|
||||
ArrayList<MoveInfo> moves = mMovesList.get(i);
|
||||
for (int j = moves.size() - 1; j >= 0; j--) {
|
||||
MoveInfo moveInfo = moves.get(j);
|
||||
if (moveInfo.holder == item) {
|
||||
ViewCompat.setTranslationY(view, 0);
|
||||
ViewCompat.setTranslationX(view, 0);
|
||||
dispatchMoveFinished(item);
|
||||
moves.remove(j);
|
||||
if (moves.isEmpty()) {
|
||||
mMovesList.remove(moves);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = mAdditionsList.size() - 1; i >= 0; i--) {
|
||||
ArrayList<ViewHolder> additions = mAdditionsList.get(i);
|
||||
if (additions.remove(item)) {
|
||||
ViewCompat.setAlpha(view, 1);
|
||||
dispatchAddFinished(item);
|
||||
if (additions.isEmpty()) {
|
||||
mAdditionsList.remove(additions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// animations should be ended by the cancel above.
|
||||
if (mRemoveAnimations.remove(item) && DEBUG) {
|
||||
throw new IllegalStateException("after animation is cancelled, item should not be in "
|
||||
+ "mRemoveAnimations list");
|
||||
}
|
||||
|
||||
if (mAddAnimations.remove(item) && DEBUG) {
|
||||
throw new IllegalStateException("after animation is cancelled, item should not be in "
|
||||
+ "mAddAnimations list");
|
||||
}
|
||||
|
||||
if (mChangeAnimations.remove(item) && DEBUG) {
|
||||
throw new IllegalStateException("after animation is cancelled, item should not be in "
|
||||
+ "mChangeAnimations list");
|
||||
}
|
||||
|
||||
if (mMoveAnimations.remove(item) && DEBUG) {
|
||||
throw new IllegalStateException("after animation is cancelled, item should not be in "
|
||||
+ "mMoveAnimations list");
|
||||
}
|
||||
dispatchFinishedWhenDone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return (!mPendingAdditions.isEmpty() ||
|
||||
!mPendingChanges.isEmpty() ||
|
||||
!mPendingMoves.isEmpty() ||
|
||||
!mPendingRemovals.isEmpty() ||
|
||||
!mMoveAnimations.isEmpty() ||
|
||||
!mRemoveAnimations.isEmpty() ||
|
||||
!mAddAnimations.isEmpty() ||
|
||||
!mChangeAnimations.isEmpty() ||
|
||||
!mMovesList.isEmpty() ||
|
||||
!mAdditionsList.isEmpty() ||
|
||||
!mChangesList.isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the state of currently pending and running animations. If there are none
|
||||
* pending/running, call {@link #dispatchAnimationsFinished()} to notify any
|
||||
* listeners.
|
||||
*/
|
||||
private void dispatchFinishedWhenDone() {
|
||||
if (!isRunning()) {
|
||||
dispatchAnimationsFinished();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endAnimations() {
|
||||
int count = mPendingMoves.size();
|
||||
for (int i = count - 1; i >= 0; i--) {
|
||||
MoveInfo item = mPendingMoves.get(i);
|
||||
View view = item.holder.itemView;
|
||||
ViewCompat.setTranslationY(view, 0);
|
||||
ViewCompat.setTranslationX(view, 0);
|
||||
dispatchMoveFinished(item.holder);
|
||||
mPendingMoves.remove(i);
|
||||
}
|
||||
count = mPendingRemovals.size();
|
||||
for (int i = count - 1; i >= 0; i--) {
|
||||
ViewHolder item = mPendingRemovals.get(i);
|
||||
dispatchRemoveFinished(item);
|
||||
mPendingRemovals.remove(i);
|
||||
}
|
||||
count = mPendingAdditions.size();
|
||||
for (int i = count - 1; i >= 0; i--) {
|
||||
ViewHolder item = mPendingAdditions.get(i);
|
||||
View view = item.itemView;
|
||||
ViewCompat.setAlpha(view, 1);
|
||||
dispatchAddFinished(item);
|
||||
mPendingAdditions.remove(i);
|
||||
}
|
||||
count = mPendingChanges.size();
|
||||
for (int i = count - 1; i >= 0; i--) {
|
||||
endChangeAnimationIfNecessary(mPendingChanges.get(i));
|
||||
}
|
||||
mPendingChanges.clear();
|
||||
if (!isRunning()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int listCount = mMovesList.size();
|
||||
for (int i = listCount - 1; i >= 0; i--) {
|
||||
ArrayList<MoveInfo> moves = mMovesList.get(i);
|
||||
count = moves.size();
|
||||
for (int j = count - 1; j >= 0; j--) {
|
||||
MoveInfo moveInfo = moves.get(j);
|
||||
ViewHolder item = moveInfo.holder;
|
||||
View view = item.itemView;
|
||||
ViewCompat.setTranslationY(view, 0);
|
||||
ViewCompat.setTranslationX(view, 0);
|
||||
dispatchMoveFinished(moveInfo.holder);
|
||||
moves.remove(j);
|
||||
if (moves.isEmpty()) {
|
||||
mMovesList.remove(moves);
|
||||
}
|
||||
}
|
||||
}
|
||||
listCount = mAdditionsList.size();
|
||||
for (int i = listCount - 1; i >= 0; i--) {
|
||||
ArrayList<ViewHolder> additions = mAdditionsList.get(i);
|
||||
count = additions.size();
|
||||
for (int j = count - 1; j >= 0; j--) {
|
||||
ViewHolder item = additions.get(j);
|
||||
View view = item.itemView;
|
||||
ViewCompat.setAlpha(view, 1);
|
||||
dispatchAddFinished(item);
|
||||
additions.remove(j);
|
||||
if (additions.isEmpty()) {
|
||||
mAdditionsList.remove(additions);
|
||||
}
|
||||
}
|
||||
}
|
||||
listCount = mChangesList.size();
|
||||
for (int i = listCount - 1; i >= 0; i--) {
|
||||
ArrayList<ChangeInfo> changes = mChangesList.get(i);
|
||||
count = changes.size();
|
||||
for (int j = count - 1; j >= 0; j--) {
|
||||
endChangeAnimationIfNecessary(changes.get(j));
|
||||
if (changes.isEmpty()) {
|
||||
mChangesList.remove(changes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cancelAll(mRemoveAnimations);
|
||||
cancelAll(mMoveAnimations);
|
||||
cancelAll(mAddAnimations);
|
||||
cancelAll(mChangeAnimations);
|
||||
|
||||
dispatchAnimationsFinished();
|
||||
}
|
||||
|
||||
void cancelAll(List<ViewHolder> viewHolders) {
|
||||
for (int i = viewHolders.size() - 1; i >= 0; i--) {
|
||||
ViewCompat.animate(viewHolders.get(i).itemView).cancel();
|
||||
}
|
||||
}
|
||||
|
||||
private static class VpaListenerAdapter implements ViewPropertyAnimatorListener {
|
||||
@Override
|
||||
public void onAnimationStart(View view) {}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(View view) {}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(View view) {}
|
||||
};
|
||||
}
|
||||
@ -1,816 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 languag`e governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.support.v7.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.SparseIntArray;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* A {@link RecyclerView.LayoutManager} implementations that lays out items in a grid.
|
||||
* <p>
|
||||
* By default, each item occupies 1 span. You can change it by providing a custom
|
||||
* {@link SpanSizeLookup} instance via {@link #setSpanSizeLookup(SpanSizeLookup)}.
|
||||
*/
|
||||
public class GridLayoutManager extends LinearLayoutManager {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
private static final String TAG = "GridLayoutManager";
|
||||
public static final int DEFAULT_SPAN_COUNT = -1;
|
||||
/**
|
||||
* The measure spec for the scroll direction.
|
||||
*/
|
||||
static final int MAIN_DIR_SPEC =
|
||||
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
|
||||
|
||||
int mSpanCount = DEFAULT_SPAN_COUNT;
|
||||
/**
|
||||
* The size of each span
|
||||
*/
|
||||
int mSizePerSpan;
|
||||
/**
|
||||
* Temporary array to keep views in layoutChunk method
|
||||
*/
|
||||
View[] mSet;
|
||||
final SparseIntArray mPreLayoutSpanSizeCache = new SparseIntArray();
|
||||
final SparseIntArray mPreLayoutSpanIndexCache = new SparseIntArray();
|
||||
SpanSizeLookup mSpanSizeLookup = new DefaultSpanSizeLookup();
|
||||
// re-used variable to acquire decor insets from RecyclerView
|
||||
final Rect mDecorInsets = new Rect();
|
||||
|
||||
/**
|
||||
* Creates a vertical GridLayoutManager
|
||||
*
|
||||
* @param context Current context, will be used to access resources.
|
||||
* @param spanCount The number of columns in the grid
|
||||
*/
|
||||
public GridLayoutManager(Context context, int spanCount) {
|
||||
super(context);
|
||||
setSpanCount(spanCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context Current context, will be used to access resources.
|
||||
* @param spanCount The number of columns or rows in the grid
|
||||
* @param orientation Layout orientation. Should be {@link #HORIZONTAL} or {@link
|
||||
* #VERTICAL}.
|
||||
* @param reverseLayout When set to true, layouts from end to start.
|
||||
*/
|
||||
public GridLayoutManager(Context context, int spanCount, int orientation,
|
||||
boolean reverseLayout) {
|
||||
super(context, orientation, reverseLayout);
|
||||
setSpanCount(spanCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* stackFromEnd is not supported by GridLayoutManager. Consider using
|
||||
* {@link #setReverseLayout(boolean)}.
|
||||
*/
|
||||
@Override
|
||||
public void setStackFromEnd(boolean stackFromEnd) {
|
||||
if (stackFromEnd) {
|
||||
throw new UnsupportedOperationException(
|
||||
"GridLayoutManager does not support stack from end."
|
||||
+ " Consider using reverse layout");
|
||||
}
|
||||
super.setStackFromEnd(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowCountForAccessibility(RecyclerView.Recycler recycler,
|
||||
RecyclerView.State state) {
|
||||
if (mOrientation == HORIZONTAL) {
|
||||
return mSpanCount;
|
||||
}
|
||||
if (state.getItemCount() < 1) {
|
||||
return 0;
|
||||
}
|
||||
return getSpanGroupIndex(recycler, state, state.getItemCount() - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCountForAccessibility(RecyclerView.Recycler recycler,
|
||||
RecyclerView.State state) {
|
||||
if (mOrientation == VERTICAL) {
|
||||
return mSpanCount;
|
||||
}
|
||||
if (state.getItemCount() < 1) {
|
||||
return 0;
|
||||
}
|
||||
return getSpanGroupIndex(recycler, state, state.getItemCount() - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitializeAccessibilityNodeInfoForItem(RecyclerView.Recycler recycler,
|
||||
RecyclerView.State state, View host, AccessibilityNodeInfoCompat info) {
|
||||
ViewGroup.LayoutParams lp = host.getLayoutParams();
|
||||
if (!(lp instanceof LayoutParams)) {
|
||||
super.onInitializeAccessibilityNodeInfoForItem(host, info);
|
||||
return;
|
||||
}
|
||||
LayoutParams glp = (LayoutParams) lp;
|
||||
int spanGroupIndex = getSpanGroupIndex(recycler, state, glp.getViewPosition());
|
||||
if (mOrientation == HORIZONTAL) {
|
||||
info.setCollectionItemInfo(AccessibilityNodeInfoCompat.CollectionItemInfoCompat.obtain(
|
||||
glp.getSpanIndex(), glp.getSpanSize(),
|
||||
spanGroupIndex, 1,
|
||||
mSpanCount > 1 && glp.getSpanSize() == mSpanCount, false));
|
||||
} else { // VERTICAL
|
||||
info.setCollectionItemInfo(AccessibilityNodeInfoCompat.CollectionItemInfoCompat.obtain(
|
||||
spanGroupIndex , 1,
|
||||
glp.getSpanIndex(), glp.getSpanSize(),
|
||||
mSpanCount > 1 && glp.getSpanSize() == mSpanCount, false));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||
if (state.isPreLayout()) {
|
||||
cachePreLayoutSpanMapping();
|
||||
}
|
||||
super.onLayoutChildren(recycler, state);
|
||||
if (DEBUG) {
|
||||
validateChildOrder();
|
||||
}
|
||||
clearPreLayoutSpanMappingCache();
|
||||
}
|
||||
|
||||
private void clearPreLayoutSpanMappingCache() {
|
||||
mPreLayoutSpanSizeCache.clear();
|
||||
mPreLayoutSpanIndexCache.clear();
|
||||
}
|
||||
|
||||
private void cachePreLayoutSpanMapping() {
|
||||
final int childCount = getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
final LayoutParams lp = (LayoutParams) getChildAt(i).getLayoutParams();
|
||||
final int viewPosition = lp.getViewPosition();
|
||||
mPreLayoutSpanSizeCache.put(viewPosition, lp.getSpanSize());
|
||||
mPreLayoutSpanIndexCache.put(viewPosition, lp.getSpanIndex());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemsAdded(RecyclerView recyclerView, int positionStart, int itemCount) {
|
||||
mSpanSizeLookup.invalidateSpanIndexCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemsChanged(RecyclerView recyclerView) {
|
||||
mSpanSizeLookup.invalidateSpanIndexCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemsRemoved(RecyclerView recyclerView, int positionStart, int itemCount) {
|
||||
mSpanSizeLookup.invalidateSpanIndexCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemsUpdated(RecyclerView recyclerView, int positionStart, int itemCount) {
|
||||
mSpanSizeLookup.invalidateSpanIndexCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemsMoved(RecyclerView recyclerView, int from, int to, int itemCount) {
|
||||
mSpanSizeLookup.invalidateSpanIndexCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
|
||||
return new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecyclerView.LayoutParams generateLayoutParams(Context c, AttributeSet attrs) {
|
||||
return new LayoutParams(c, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecyclerView.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
|
||||
if (lp instanceof ViewGroup.MarginLayoutParams) {
|
||||
return new LayoutParams((ViewGroup.MarginLayoutParams) lp);
|
||||
} else {
|
||||
return new LayoutParams(lp);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkLayoutParams(RecyclerView.LayoutParams lp) {
|
||||
return lp instanceof LayoutParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the source to get the number of spans occupied by each item in the adapter.
|
||||
*
|
||||
* @param spanSizeLookup {@link SpanSizeLookup} instance to be used to query number of spans
|
||||
* occupied by each item
|
||||
*/
|
||||
public void setSpanSizeLookup(SpanSizeLookup spanSizeLookup) {
|
||||
mSpanSizeLookup = spanSizeLookup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current {@link SpanSizeLookup} used by the GridLayoutManager.
|
||||
*
|
||||
* @return The current {@link SpanSizeLookup} used by the GridLayoutManager.
|
||||
*/
|
||||
public SpanSizeLookup getSpanSizeLookup() {
|
||||
return mSpanSizeLookup;
|
||||
}
|
||||
|
||||
private void updateMeasurements() {
|
||||
int totalSpace;
|
||||
if (getOrientation() == VERTICAL) {
|
||||
totalSpace = getWidth() - getPaddingRight() - getPaddingLeft();
|
||||
} else {
|
||||
totalSpace = getHeight() - getPaddingBottom() - getPaddingTop();
|
||||
}
|
||||
mSizePerSpan = totalSpace / mSpanCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
void onAnchorReady(RecyclerView.State state, AnchorInfo anchorInfo) {
|
||||
super.onAnchorReady(state, anchorInfo);
|
||||
updateMeasurements();
|
||||
if (state.getItemCount() > 0 && !state.isPreLayout()) {
|
||||
ensureAnchorIsInFirstSpan(anchorInfo);
|
||||
}
|
||||
if (mSet == null || mSet.length != mSpanCount) {
|
||||
mSet = new View[mSpanCount];
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureAnchorIsInFirstSpan(AnchorInfo anchorInfo) {
|
||||
int span = mSpanSizeLookup.getCachedSpanIndex(anchorInfo.mPosition, mSpanCount);
|
||||
while (span > 0 && anchorInfo.mPosition > 0) {
|
||||
anchorInfo.mPosition--;
|
||||
span = mSpanSizeLookup.getCachedSpanIndex(anchorInfo.mPosition, mSpanCount);
|
||||
}
|
||||
}
|
||||
|
||||
private int getSpanGroupIndex(RecyclerView.Recycler recycler, RecyclerView.State state,
|
||||
int viewPosition) {
|
||||
if (!state.isPreLayout()) {
|
||||
return mSpanSizeLookup.getSpanGroupIndex(viewPosition, mSpanCount);
|
||||
}
|
||||
final int adapterPosition = recycler.convertPreLayoutPositionToPostLayout(viewPosition);
|
||||
if (adapterPosition == -1) {
|
||||
if (DEBUG) {
|
||||
throw new RuntimeException("Cannot find span group index for position "
|
||||
+ viewPosition);
|
||||
}
|
||||
Log.w(TAG, "Cannot find span size for pre layout position. " + viewPosition);
|
||||
return 0;
|
||||
}
|
||||
return mSpanSizeLookup.getSpanGroupIndex(adapterPosition, mSpanCount);
|
||||
}
|
||||
|
||||
private int getSpanIndex(RecyclerView.Recycler recycler, RecyclerView.State state, int pos) {
|
||||
if (!state.isPreLayout()) {
|
||||
return mSpanSizeLookup.getCachedSpanIndex(pos, mSpanCount);
|
||||
}
|
||||
final int cached = mPreLayoutSpanIndexCache.get(pos, -1);
|
||||
if (cached != -1) {
|
||||
return cached;
|
||||
}
|
||||
final int adapterPosition = recycler.convertPreLayoutPositionToPostLayout(pos);
|
||||
if (adapterPosition == -1) {
|
||||
if (DEBUG) {
|
||||
throw new RuntimeException("Cannot find span index for pre layout position. It is"
|
||||
+ " not cached, not in the adapter. Pos:" + pos);
|
||||
}
|
||||
Log.w(TAG, "Cannot find span size for pre layout position. It is"
|
||||
+ " not cached, not in the adapter. Pos:" + pos);
|
||||
return 0;
|
||||
}
|
||||
return mSpanSizeLookup.getCachedSpanIndex(adapterPosition, mSpanCount);
|
||||
}
|
||||
|
||||
private int getSpanSize(RecyclerView.Recycler recycler, RecyclerView.State state, int pos) {
|
||||
if (!state.isPreLayout()) {
|
||||
return mSpanSizeLookup.getSpanSize(pos);
|
||||
}
|
||||
final int cached = mPreLayoutSpanSizeCache.get(pos, -1);
|
||||
if (cached != -1) {
|
||||
return cached;
|
||||
}
|
||||
final int adapterPosition = recycler.convertPreLayoutPositionToPostLayout(pos);
|
||||
if (adapterPosition == -1) {
|
||||
if (DEBUG) {
|
||||
throw new RuntimeException("Cannot find span size for pre layout position. It is"
|
||||
+ " not cached, not in the adapter. Pos:" + pos);
|
||||
}
|
||||
Log.w(TAG, "Cannot find span size for pre layout position. It is"
|
||||
+ " not cached, not in the adapter. Pos:" + pos);
|
||||
return 1;
|
||||
}
|
||||
return mSpanSizeLookup.getSpanSize(adapterPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
void layoutChunk(RecyclerView.Recycler recycler, RecyclerView.State state,
|
||||
LayoutState layoutState, LayoutChunkResult result) {
|
||||
final boolean layingOutInPrimaryDirection =
|
||||
layoutState.mItemDirection == LayoutState.ITEM_DIRECTION_TAIL;
|
||||
int count = 0;
|
||||
int consumedSpanCount = 0;
|
||||
int remainingSpan = mSpanCount;
|
||||
if (!layingOutInPrimaryDirection) {
|
||||
int itemSpanIndex = getSpanIndex(recycler, state, layoutState.mCurrentPosition);
|
||||
int itemSpanSize = getSpanSize(recycler, state, layoutState.mCurrentPosition);
|
||||
remainingSpan = itemSpanIndex + itemSpanSize;
|
||||
}
|
||||
while (count < mSpanCount && layoutState.hasMore(state) && remainingSpan > 0) {
|
||||
int pos = layoutState.mCurrentPosition;
|
||||
final int spanSize = getSpanSize(recycler, state, pos);
|
||||
if (spanSize > mSpanCount) {
|
||||
throw new IllegalArgumentException("Item at position " + pos + " requires " +
|
||||
spanSize + " spans but GridLayoutManager has only " + mSpanCount
|
||||
+ " spans.");
|
||||
}
|
||||
remainingSpan -= spanSize;
|
||||
if (remainingSpan < 0) {
|
||||
break; // item did not fit into this row or column
|
||||
}
|
||||
View view = layoutState.next(recycler);
|
||||
if (view == null) {
|
||||
break;
|
||||
}
|
||||
consumedSpanCount += spanSize;
|
||||
mSet[count] = view;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
result.mFinished = true;
|
||||
return;
|
||||
}
|
||||
|
||||
int maxSize = 0;
|
||||
|
||||
// we should assign spans before item decor offsets are calculated
|
||||
assignSpans(recycler, state, count, consumedSpanCount, layingOutInPrimaryDirection);
|
||||
for (int i = 0; i < count; i++) {
|
||||
View view = mSet[i];
|
||||
if (layoutState.mScrapList == null) {
|
||||
if (layingOutInPrimaryDirection) {
|
||||
addView(view);
|
||||
} else {
|
||||
addView(view, 0);
|
||||
}
|
||||
} else {
|
||||
if (layingOutInPrimaryDirection) {
|
||||
addDisappearingView(view);
|
||||
} else {
|
||||
addDisappearingView(view, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int spanSize = getSpanSize(recycler, state, getPosition(view));
|
||||
final int spec = View.MeasureSpec.makeMeasureSpec(mSizePerSpan * spanSize,
|
||||
View.MeasureSpec.EXACTLY);
|
||||
final LayoutParams lp = (LayoutParams) view.getLayoutParams();
|
||||
if (mOrientation == VERTICAL) {
|
||||
measureChildWithDecorationsAndMargin(view, spec, getMainDirSpec(lp.height));
|
||||
} else {
|
||||
measureChildWithDecorationsAndMargin(view, getMainDirSpec(lp.width), spec);
|
||||
}
|
||||
final int size = mOrientationHelper.getDecoratedMeasurement(view);
|
||||
if (size > maxSize) {
|
||||
maxSize = size;
|
||||
}
|
||||
}
|
||||
|
||||
// views that did not measure the maxSize has to be re-measured
|
||||
final int maxMeasureSpec = getMainDirSpec(maxSize);
|
||||
for (int i = 0; i < count; i ++) {
|
||||
final View view = mSet[i];
|
||||
if (mOrientationHelper.getDecoratedMeasurement(view) != maxSize) {
|
||||
int spanSize = getSpanSize(recycler, state, getPosition(view));
|
||||
final int spec = View.MeasureSpec.makeMeasureSpec(mSizePerSpan * spanSize,
|
||||
View.MeasureSpec.EXACTLY);
|
||||
if (mOrientation == VERTICAL) {
|
||||
measureChildWithDecorationsAndMargin(view, spec, maxMeasureSpec);
|
||||
} else {
|
||||
measureChildWithDecorationsAndMargin(view, maxMeasureSpec, spec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.mConsumed = maxSize;
|
||||
|
||||
int left = 0, right = 0, top = 0, bottom = 0;
|
||||
if (mOrientation == VERTICAL) {
|
||||
if (layoutState.mLayoutDirection == LayoutState.LAYOUT_START) {
|
||||
bottom = layoutState.mOffset;
|
||||
top = bottom - maxSize;
|
||||
} else {
|
||||
top = layoutState.mOffset;
|
||||
bottom = top + maxSize;
|
||||
}
|
||||
} else {
|
||||
if (layoutState.mLayoutDirection == LayoutState.LAYOUT_START) {
|
||||
right = layoutState.mOffset;
|
||||
left = right - maxSize;
|
||||
} else {
|
||||
left = layoutState.mOffset;
|
||||
right = left + maxSize;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < count; i++) {
|
||||
View view = mSet[i];
|
||||
LayoutParams params = (LayoutParams) view.getLayoutParams();
|
||||
if (mOrientation == VERTICAL) {
|
||||
left = getPaddingLeft() + mSizePerSpan * params.mSpanIndex;
|
||||
right = left + mOrientationHelper.getDecoratedMeasurementInOther(view);
|
||||
} else {
|
||||
top = getPaddingTop() + mSizePerSpan * params.mSpanIndex;
|
||||
bottom = top + mOrientationHelper.getDecoratedMeasurementInOther(view);
|
||||
}
|
||||
// We calculate everything with View's bounding box (which includes decor and margins)
|
||||
// To calculate correct layout position, we subtract margins.
|
||||
layoutDecorated(view, left + params.leftMargin, top + params.topMargin,
|
||||
right - params.rightMargin, bottom - params.bottomMargin);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "laid out child at position " + getPosition(view) + ", with l:"
|
||||
+ (left + params.leftMargin) + ", t:" + (top + params.topMargin) + ", r:"
|
||||
+ (right - params.rightMargin) + ", b:" + (bottom - params.bottomMargin)
|
||||
+ ", span:" + params.mSpanIndex + ", spanSize:" + params.mSpanSize);
|
||||
}
|
||||
// Consume the available space if the view is not removed OR changed
|
||||
if (params.isItemRemoved() || params.isItemChanged()) {
|
||||
result.mIgnoreConsumed = true;
|
||||
}
|
||||
result.mFocusable |= view.isFocusable();
|
||||
}
|
||||
Arrays.fill(mSet, null);
|
||||
}
|
||||
|
||||
private int getMainDirSpec(int dim) {
|
||||
if (dim < 0) {
|
||||
return MAIN_DIR_SPEC;
|
||||
} else {
|
||||
return View.MeasureSpec.makeMeasureSpec(dim, View.MeasureSpec.EXACTLY);
|
||||
}
|
||||
}
|
||||
|
||||
private void measureChildWithDecorationsAndMargin(View child, int widthSpec, int heightSpec) {
|
||||
calculateItemDecorationsForChild(child, mDecorInsets);
|
||||
RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) child.getLayoutParams();
|
||||
widthSpec = updateSpecWithExtra(widthSpec, lp.leftMargin + mDecorInsets.left,
|
||||
lp.rightMargin + mDecorInsets.right);
|
||||
heightSpec = updateSpecWithExtra(heightSpec, lp.topMargin + mDecorInsets.top,
|
||||
lp.bottomMargin + mDecorInsets.bottom);
|
||||
child.measure(widthSpec, heightSpec);
|
||||
}
|
||||
|
||||
private int updateSpecWithExtra(int spec, int startInset, int endInset) {
|
||||
if (startInset == 0 && endInset == 0) {
|
||||
return spec;
|
||||
}
|
||||
final int mode = View.MeasureSpec.getMode(spec);
|
||||
if (mode == View.MeasureSpec.AT_MOST || mode == View.MeasureSpec.EXACTLY) {
|
||||
return View.MeasureSpec.makeMeasureSpec(
|
||||
View.MeasureSpec.getSize(spec) - startInset - endInset, mode);
|
||||
}
|
||||
return spec;
|
||||
}
|
||||
|
||||
private void assignSpans(RecyclerView.Recycler recycler, RecyclerView.State state, int count,
|
||||
int consumedSpanCount, boolean layingOutInPrimaryDirection) {
|
||||
int span, spanDiff, start, end, diff;
|
||||
// make sure we traverse from min position to max position
|
||||
if (layingOutInPrimaryDirection) {
|
||||
start = 0;
|
||||
end = count;
|
||||
diff = 1;
|
||||
} else {
|
||||
start = count - 1;
|
||||
end = -1;
|
||||
diff = -1;
|
||||
}
|
||||
if (mOrientation == VERTICAL && isLayoutRTL()) { // start from last span
|
||||
span = consumedSpanCount - 1;
|
||||
spanDiff = -1;
|
||||
} else {
|
||||
span = 0;
|
||||
spanDiff = 1;
|
||||
}
|
||||
for (int i = start; i != end; i += diff) {
|
||||
View view = mSet[i];
|
||||
LayoutParams params = (LayoutParams) view.getLayoutParams();
|
||||
params.mSpanSize = getSpanSize(recycler, state, getPosition(view));
|
||||
if (spanDiff == -1 && params.mSpanSize > 1) {
|
||||
params.mSpanIndex = span - (params.mSpanSize - 1);
|
||||
} else {
|
||||
params.mSpanIndex = span;
|
||||
}
|
||||
span += spanDiff * params.mSpanSize;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of spans laid out by this grid.
|
||||
*
|
||||
* @return The number of spans
|
||||
* @see #setSpanCount(int)
|
||||
*/
|
||||
public int getSpanCount() {
|
||||
return mSpanCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of spans to be laid out.
|
||||
* <p>
|
||||
* If {@link #getOrientation()} is {@link #VERTICAL}, this is the number of columns.
|
||||
* If {@link #getOrientation()} is {@link #HORIZONTAL}, this is the number of rows.
|
||||
*
|
||||
* @param spanCount The total number of spans in the grid
|
||||
* @see #getSpanCount()
|
||||
*/
|
||||
public void setSpanCount(int spanCount) {
|
||||
if (spanCount == mSpanCount) {
|
||||
return;
|
||||
}
|
||||
if (spanCount < 1) {
|
||||
throw new IllegalArgumentException("Span count should be at least 1. Provided "
|
||||
+ spanCount);
|
||||
}
|
||||
mSpanCount = spanCount;
|
||||
mSpanSizeLookup.invalidateSpanIndexCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper class to provide the number of spans each item occupies.
|
||||
* <p>
|
||||
* Default implementation sets each item to occupy exactly 1 span.
|
||||
*
|
||||
* @see GridLayoutManager#setSpanSizeLookup(SpanSizeLookup)
|
||||
*/
|
||||
public static abstract class SpanSizeLookup {
|
||||
|
||||
final SparseIntArray mSpanIndexCache = new SparseIntArray();
|
||||
|
||||
private boolean mCacheSpanIndices = false;
|
||||
|
||||
/**
|
||||
* Returns the number of span occupied by the item at <code>position</code>.
|
||||
*
|
||||
* @param position The adapter position of the item
|
||||
* @return The number of spans occupied by the item at the provided position
|
||||
*/
|
||||
abstract public int getSpanSize(int position);
|
||||
|
||||
/**
|
||||
* Sets whether the results of {@link #getSpanIndex(int, int)} method should be cached or
|
||||
* not. By default these values are not cached. If you are not overriding
|
||||
* {@link #getSpanIndex(int, int)}, you should set this to true for better performance.
|
||||
*
|
||||
* @param cacheSpanIndices Whether results of getSpanIndex should be cached or not.
|
||||
*/
|
||||
public void setSpanIndexCacheEnabled(boolean cacheSpanIndices) {
|
||||
mCacheSpanIndices = cacheSpanIndices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the span index cache. GridLayoutManager automatically calls this method when
|
||||
* adapter changes occur.
|
||||
*/
|
||||
public void invalidateSpanIndexCache() {
|
||||
mSpanIndexCache.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether results of {@link #getSpanIndex(int, int)} method are cached or not.
|
||||
*
|
||||
* @return True if results of {@link #getSpanIndex(int, int)} are cached.
|
||||
*/
|
||||
public boolean isSpanIndexCacheEnabled() {
|
||||
return mCacheSpanIndices;
|
||||
}
|
||||
|
||||
int getCachedSpanIndex(int position, int spanCount) {
|
||||
if (!mCacheSpanIndices) {
|
||||
return getSpanIndex(position, spanCount);
|
||||
}
|
||||
final int existing = mSpanIndexCache.get(position, -1);
|
||||
if (existing != -1) {
|
||||
return existing;
|
||||
}
|
||||
final int value = getSpanIndex(position, spanCount);
|
||||
mSpanIndexCache.put(position, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the final span index of the provided position.
|
||||
* <p>
|
||||
* If you have a faster way to calculate span index for your items, you should override
|
||||
* this method. Otherwise, you should enable span index cache
|
||||
* ({@link #setSpanIndexCacheEnabled(boolean)}) for better performance. When caching is
|
||||
* disabled, default implementation traverses all items from 0 to
|
||||
* <code>position</code>. When caching is enabled, it calculates from the closest cached
|
||||
* value before the <code>position</code>.
|
||||
* <p>
|
||||
* If you override this method, you need to make sure it is consistent with
|
||||
* {@link #getSpanSize(int)}. GridLayoutManager does not call this method for
|
||||
* each item. It is called only for the reference item and rest of the items
|
||||
* are assigned to spans based on the reference item. For example, you cannot assign a
|
||||
* position to span 2 while span 1 is empty.
|
||||
* <p>
|
||||
* Note that span offsets always start with 0 and are not affected by RTL.
|
||||
*
|
||||
* @param position The position of the item
|
||||
* @param spanCount The total number of spans in the grid
|
||||
* @return The final span position of the item. Should be between 0 (inclusive) and
|
||||
* <code>spanCount</code>(exclusive)
|
||||
*/
|
||||
public int getSpanIndex(int position, int spanCount) {
|
||||
int positionSpanSize = getSpanSize(position);
|
||||
if (positionSpanSize == spanCount) {
|
||||
return 0; // quick return for full-span items
|
||||
}
|
||||
int span = 0;
|
||||
int startPos = 0;
|
||||
// If caching is enabled, try to jump
|
||||
if (mCacheSpanIndices && mSpanIndexCache.size() > 0) {
|
||||
int prevKey = findReferenceIndexFromCache(position);
|
||||
if (prevKey >= 0) {
|
||||
span = mSpanIndexCache.get(prevKey) + getSpanSize(prevKey);
|
||||
startPos = prevKey + 1;
|
||||
}
|
||||
}
|
||||
for (int i = startPos; i < position; i++) {
|
||||
int size = getSpanSize(i);
|
||||
span += size;
|
||||
if (span == spanCount) {
|
||||
span = 0;
|
||||
} else if (span > spanCount) {
|
||||
// did not fit, moving to next row / column
|
||||
span = size;
|
||||
}
|
||||
}
|
||||
if (span + positionSpanSize <= spanCount) {
|
||||
return span;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int findReferenceIndexFromCache(int position) {
|
||||
int lo = 0;
|
||||
int hi = mSpanIndexCache.size() - 1;
|
||||
|
||||
while (lo <= hi) {
|
||||
final int mid = (lo + hi) >>> 1;
|
||||
final int midVal = mSpanIndexCache.keyAt(mid);
|
||||
if (midVal < position) {
|
||||
lo = mid + 1;
|
||||
} else {
|
||||
hi = mid - 1;
|
||||
}
|
||||
}
|
||||
int index = lo - 1;
|
||||
if (index >= 0 && index < mSpanIndexCache.size()) {
|
||||
return mSpanIndexCache.keyAt(index);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the group this position belongs.
|
||||
* <p>
|
||||
* For example, if grid has 3 columns and each item occupies 1 span, span group index
|
||||
* for item 1 will be 0, item 5 will be 1.
|
||||
*
|
||||
* @param adapterPosition The position in adapter
|
||||
* @param spanCount The total number of spans in the grid
|
||||
* @return The index of the span group including the item at the given adapter position
|
||||
*/
|
||||
public int getSpanGroupIndex(int adapterPosition, int spanCount) {
|
||||
int span = 0;
|
||||
int group = 0;
|
||||
int positionSpanSize = getSpanSize(adapterPosition);
|
||||
for (int i = 0; i < adapterPosition; i++) {
|
||||
int size = getSpanSize(i);
|
||||
span += size;
|
||||
if (span == spanCount) {
|
||||
span = 0;
|
||||
group++;
|
||||
} else if (span > spanCount) {
|
||||
// did not fit, moving to next row / column
|
||||
span = size;
|
||||
group++;
|
||||
}
|
||||
}
|
||||
if (span + positionSpanSize > spanCount) {
|
||||
group++;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsPredictiveItemAnimations() {
|
||||
return mPendingSavedState == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation for {@link SpanSizeLookup}. Each item occupies 1 span.
|
||||
*/
|
||||
public static final class DefaultSpanSizeLookup extends SpanSizeLookup {
|
||||
|
||||
@Override
|
||||
public int getSpanSize(int position) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSpanIndex(int position, int spanCount) {
|
||||
return position % spanCount;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* LayoutParams used by GridLayoutManager.
|
||||
*/
|
||||
public static class LayoutParams extends RecyclerView.LayoutParams {
|
||||
|
||||
/**
|
||||
* Span Id for Views that are not laid out yet.
|
||||
*/
|
||||
public static final int INVALID_SPAN_ID = -1;
|
||||
|
||||
private int mSpanIndex = INVALID_SPAN_ID;
|
||||
|
||||
private int mSpanSize = 0;
|
||||
|
||||
public LayoutParams(Context c, AttributeSet attrs) {
|
||||
super(c, attrs);
|
||||
}
|
||||
|
||||
public LayoutParams(int width, int height) {
|
||||
super(width, height);
|
||||
}
|
||||
|
||||
public LayoutParams(ViewGroup.MarginLayoutParams source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
public LayoutParams(ViewGroup.LayoutParams source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
public LayoutParams(RecyclerView.LayoutParams source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current span index of this View. If the View is not laid out yet, the return
|
||||
* value is <code>undefined</code>.
|
||||
* <p>
|
||||
* Note that span index may change by whether the RecyclerView is RTL or not. For
|
||||
* example, if the number of spans is 3 and layout is RTL, the rightmost item will have
|
||||
* span index of 2. If the layout changes back to LTR, span index for this view will be 0.
|
||||
* If the item was occupying 2 spans, span indices would be 1 and 0 respectively.
|
||||
* <p>
|
||||
* If the View occupies multiple spans, span with the minimum index is returned.
|
||||
*
|
||||
* @return The span index of the View.
|
||||
*/
|
||||
public int getSpanIndex() {
|
||||
return mSpanIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of spans occupied by this View. If the View not laid out yet, the
|
||||
* return value is <code>undefined</code>.
|
||||
*
|
||||
* @return The number of spans occupied by this View.
|
||||
*/
|
||||
public int getSpanSize() {
|
||||
return mSpanSize;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 languag`e governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.support.v7.widget;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* Helper class that keeps temporary state while {LayoutManager} is filling out the empty
|
||||
* space.
|
||||
*/
|
||||
class LayoutState {
|
||||
|
||||
final static String TAG = "LayoutState";
|
||||
|
||||
final static int LAYOUT_START = -1;
|
||||
|
||||
final static int LAYOUT_END = 1;
|
||||
|
||||
final static int INVALID_LAYOUT = Integer.MIN_VALUE;
|
||||
|
||||
final static int ITEM_DIRECTION_HEAD = -1;
|
||||
|
||||
final static int ITEM_DIRECTION_TAIL = 1;
|
||||
|
||||
final static int SCOLLING_OFFSET_NaN = Integer.MIN_VALUE;
|
||||
|
||||
/**
|
||||
* Number of pixels that we should fill, in the layout direction.
|
||||
*/
|
||||
int mAvailable;
|
||||
|
||||
/**
|
||||
* Current position on the adapter to get the next item.
|
||||
*/
|
||||
int mCurrentPosition;
|
||||
|
||||
/**
|
||||
* Defines the direction in which the data adapter is traversed.
|
||||
* Should be {@link #ITEM_DIRECTION_HEAD} or {@link #ITEM_DIRECTION_TAIL}
|
||||
*/
|
||||
int mItemDirection;
|
||||
|
||||
/**
|
||||
* Defines the direction in which the layout is filled.
|
||||
* Should be {@link #LAYOUT_START} or {@link #LAYOUT_END}
|
||||
*/
|
||||
int mLayoutDirection;
|
||||
|
||||
/**
|
||||
* Used if you want to pre-layout items that are not yet visible.
|
||||
* The difference with {@link #mAvailable} is that, when recycling, distance rendered for
|
||||
* {@link #mExtra} is not considered not to recycle visible children.
|
||||
*/
|
||||
int mExtra = 0;
|
||||
|
||||
/**
|
||||
* @return true if there are more items in the data adapter
|
||||
*/
|
||||
boolean hasMore(RecyclerView.State state) {
|
||||
return mCurrentPosition >= 0 && mCurrentPosition < state.getItemCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the view for the next element that we should render.
|
||||
* Also updates current item index to the next item, based on {@link #mItemDirection}
|
||||
*
|
||||
* @return The next element that we should render.
|
||||
*/
|
||||
View next(RecyclerView.Recycler recycler) {
|
||||
final View view = recycler.getViewForPosition(mCurrentPosition);
|
||||
mCurrentPosition += mItemDirection;
|
||||
return view;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,338 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 android.support.v7.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.PointF;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
|
||||
/**
|
||||
* {@link RecyclerView.SmoothScroller} implementation which uses
|
||||
* {@link LinearInterpolator} until the target position becames a child of
|
||||
* the RecyclerView and then uses
|
||||
* {@link DecelerateInterpolator} to slowly approach to target position.
|
||||
*/
|
||||
abstract public class LinearSmoothScroller extends RecyclerView.SmoothScroller {
|
||||
|
||||
private static final String TAG = "LinearSmoothScroller";
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final float MILLISECONDS_PER_INCH = 25f;
|
||||
|
||||
private static final int TARGET_SEEK_SCROLL_DISTANCE_PX = 10000;
|
||||
|
||||
/**
|
||||
* Align child view's left or top with parent view's left or top
|
||||
*
|
||||
* @see #calculateDtToFit(int, int, int, int, int)
|
||||
* @see #calculateDxToMakeVisible(View, int)
|
||||
* @see #calculateDyToMakeVisible(View, int)
|
||||
*/
|
||||
public static final int SNAP_TO_START = -1;
|
||||
|
||||
/**
|
||||
* Align child view's right or bottom with parent view's right or bottom
|
||||
*
|
||||
* @see #calculateDtToFit(int, int, int, int, int)
|
||||
* @see #calculateDxToMakeVisible(View, int)
|
||||
* @see #calculateDyToMakeVisible(View, int)
|
||||
*/
|
||||
public static final int SNAP_TO_END = 1;
|
||||
|
||||
/**
|
||||
* <p>Decides if the child should be snapped from start or end, depending on where it
|
||||
* currently is in relation to its parent.</p>
|
||||
* <p>For instance, if the view is virtually on the left of RecyclerView, using
|
||||
* {@code SNAP_TO_ANY} is the same as using {@code SNAP_TO_START}</p>
|
||||
*
|
||||
* @see #calculateDtToFit(int, int, int, int, int)
|
||||
* @see #calculateDxToMakeVisible(View, int)
|
||||
* @see #calculateDyToMakeVisible(View, int)
|
||||
*/
|
||||
public static final int SNAP_TO_ANY = 0;
|
||||
|
||||
// Trigger a scroll to a further distance than TARGET_SEEK_SCROLL_DISTANCE_PX so that if target
|
||||
// view is not laid out until interim target position is reached, we can detect the case before
|
||||
// scrolling slows down and reschedule another interim target scroll
|
||||
private static final float TARGET_SEEK_EXTRA_SCROLL_RATIO = 1.2f;
|
||||
|
||||
protected final LinearInterpolator mLinearInterpolator = new LinearInterpolator();
|
||||
|
||||
protected final DecelerateInterpolator mDecelerateInterpolator = new DecelerateInterpolator();
|
||||
|
||||
protected PointF mTargetVector;
|
||||
|
||||
private final float MILLISECONDS_PER_PX;
|
||||
|
||||
// Temporary variables to keep track of the interim scroll target. These values do not
|
||||
// point to a real item position, rather point to an estimated location pixels.
|
||||
protected int mInterimTargetDx = 0, mInterimTargetDy = 0;
|
||||
|
||||
public LinearSmoothScroller(Context context) {
|
||||
MILLISECONDS_PER_PX = calculateSpeedPerPixel(context.getResources().getDisplayMetrics());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void onStart() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void onTargetFound(View targetView, RecyclerView.State state, Action action) {
|
||||
final int dx = calculateDxToMakeVisible(targetView, getHorizontalSnapPreference());
|
||||
final int dy = calculateDyToMakeVisible(targetView, getVerticalSnapPreference());
|
||||
final int distance = (int) Math.sqrt(dx * dx + dy * dy);
|
||||
final int time = calculateTimeForDeceleration(distance);
|
||||
if (time > 0) {
|
||||
action.update(-dx, -dy, time, mDecelerateInterpolator);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void onSeekTargetStep(int dx, int dy, RecyclerView.State state, Action action) {
|
||||
if (getChildCount() == 0) {
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
if (DEBUG && mTargetVector != null
|
||||
&& ((mTargetVector.x * dx < 0 || mTargetVector.y * dy < 0))) {
|
||||
throw new IllegalStateException("Scroll happened in the opposite direction"
|
||||
+ " of the target. Some calculations are wrong");
|
||||
}
|
||||
mInterimTargetDx = clampApplyScroll(mInterimTargetDx, dx);
|
||||
mInterimTargetDy = clampApplyScroll(mInterimTargetDy, dy);
|
||||
|
||||
if (mInterimTargetDx == 0 && mInterimTargetDy == 0) {
|
||||
updateActionForInterimTarget(action);
|
||||
} // everything is valid, keep going
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void onStop() {
|
||||
mInterimTargetDx = mInterimTargetDy = 0;
|
||||
mTargetVector = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the scroll speed.
|
||||
*
|
||||
* @param displayMetrics DisplayMetrics to be used for real dimension calculations
|
||||
* @return The time (in ms) it should take for each pixel. For instance, if returned value is
|
||||
* 2 ms, it means scrolling 1000 pixels with LinearInterpolation should take 2 seconds.
|
||||
*/
|
||||
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
|
||||
return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Calculates the time for deceleration so that transition from LinearInterpolator to
|
||||
* DecelerateInterpolator looks smooth.</p>
|
||||
*
|
||||
* @param dx Distance to scroll
|
||||
* @return Time for DecelerateInterpolator to smoothly traverse the distance when transitioning
|
||||
* from LinearInterpolation
|
||||
*/
|
||||
protected int calculateTimeForDeceleration(int dx) {
|
||||
// we want to cover same area with the linear interpolator for the first 10% of the
|
||||
// interpolation. After that, deceleration will take control.
|
||||
// area under curve (1-(1-x)^2) can be calculated as (1 - x/3) * x * x
|
||||
// which gives 0.100028 when x = .3356
|
||||
// this is why we divide linear scrolling time with .3356
|
||||
return (int) Math.ceil(calculateTimeForScrolling(dx) / .3356);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the time it should take to scroll the given distance (in pixels)
|
||||
*
|
||||
* @param dx Distance in pixels that we want to scroll
|
||||
* @return Time in milliseconds
|
||||
* @see #calculateSpeedPerPixel(DisplayMetrics)
|
||||
*/
|
||||
protected int calculateTimeForScrolling(int dx) {
|
||||
// In a case where dx is very small, rounding may return 0 although dx > 0.
|
||||
// To avoid that issue, ceil the result so that if dx > 0, we'll always return positive
|
||||
// time.
|
||||
return (int) Math.ceil(Math.abs(dx) * MILLISECONDS_PER_PX);
|
||||
}
|
||||
|
||||
/**
|
||||
* When scrolling towards a child view, this method defines whether we should align the left
|
||||
* or the right edge of the child with the parent RecyclerView.
|
||||
*
|
||||
* @return SNAP_TO_START, SNAP_TO_END or SNAP_TO_ANY; depending on the current target vector
|
||||
* @see #SNAP_TO_START
|
||||
* @see #SNAP_TO_END
|
||||
* @see #SNAP_TO_ANY
|
||||
*/
|
||||
protected int getHorizontalSnapPreference() {
|
||||
return mTargetVector == null || mTargetVector.x == 0 ? SNAP_TO_ANY :
|
||||
mTargetVector.x > 0 ? SNAP_TO_END : SNAP_TO_START;
|
||||
}
|
||||
|
||||
/**
|
||||
* When scrolling towards a child view, this method defines whether we should align the top
|
||||
* or the bottom edge of the child with the parent RecyclerView.
|
||||
*
|
||||
* @return SNAP_TO_START, SNAP_TO_END or SNAP_TO_ANY; depending on the current target vector
|
||||
* @see #SNAP_TO_START
|
||||
* @see #SNAP_TO_END
|
||||
* @see #SNAP_TO_ANY
|
||||
*/
|
||||
protected int getVerticalSnapPreference() {
|
||||
return mTargetVector == null || mTargetVector.y == 0 ? SNAP_TO_ANY :
|
||||
mTargetVector.y > 0 ? SNAP_TO_END : SNAP_TO_START;
|
||||
}
|
||||
|
||||
/**
|
||||
* When the target scroll position is not a child of the RecyclerView, this method calculates
|
||||
* a direction vector towards that child and triggers a smooth scroll.
|
||||
*
|
||||
* @see #computeScrollVectorForPosition(int)
|
||||
*/
|
||||
protected void updateActionForInterimTarget(Action action) {
|
||||
// find an interim target position
|
||||
PointF scrollVector = computeScrollVectorForPosition(getTargetPosition());
|
||||
if (scrollVector == null || (scrollVector.x == 0 && scrollVector.y == 0)) {
|
||||
Log.e(TAG, "To support smooth scrolling, you should override \n"
|
||||
+ "LayoutManager#computeScrollVectorForPosition.\n"
|
||||
+ "Falling back to instant scroll");
|
||||
final int target = getTargetPosition();
|
||||
stop();
|
||||
instantScrollToPosition(target);
|
||||
return;
|
||||
}
|
||||
normalize(scrollVector);
|
||||
mTargetVector = scrollVector;
|
||||
|
||||
mInterimTargetDx = (int) (TARGET_SEEK_SCROLL_DISTANCE_PX * scrollVector.x);
|
||||
mInterimTargetDy = (int) (TARGET_SEEK_SCROLL_DISTANCE_PX * scrollVector.y);
|
||||
final int time = calculateTimeForScrolling(TARGET_SEEK_SCROLL_DISTANCE_PX);
|
||||
// To avoid UI hiccups, trigger a smooth scroll to a distance little further than the
|
||||
// interim target. Since we track the distance travelled in onSeekTargetStep callback, it
|
||||
// won't actually scroll more than what we need.
|
||||
action.update((int) (mInterimTargetDx * TARGET_SEEK_EXTRA_SCROLL_RATIO)
|
||||
, (int) (mInterimTargetDy * TARGET_SEEK_EXTRA_SCROLL_RATIO)
|
||||
, (int) (time * TARGET_SEEK_EXTRA_SCROLL_RATIO), mLinearInterpolator);
|
||||
}
|
||||
|
||||
private int clampApplyScroll(int tmpDt, int dt) {
|
||||
final int before = tmpDt;
|
||||
tmpDt -= dt;
|
||||
if (before * tmpDt <= 0) { // changed sign, reached 0 or was 0, reset
|
||||
return 0;
|
||||
}
|
||||
return tmpDt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for {@link #calculateDxToMakeVisible(View, int)} and
|
||||
* {@link #calculateDyToMakeVisible(View, int)}
|
||||
*/
|
||||
public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int
|
||||
snapPreference) {
|
||||
switch (snapPreference) {
|
||||
case SNAP_TO_START:
|
||||
return boxStart - viewStart;
|
||||
case SNAP_TO_END:
|
||||
return boxEnd - viewEnd;
|
||||
case SNAP_TO_ANY:
|
||||
final int dtStart = boxStart - viewStart;
|
||||
if (dtStart > 0) {
|
||||
return dtStart;
|
||||
}
|
||||
final int dtEnd = boxEnd - viewEnd;
|
||||
if (dtEnd < 0) {
|
||||
return dtEnd;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("snap preference should be one of the"
|
||||
+ " constants defined in SmoothScroller, starting with SNAP_");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the vertical scroll amount necessary to make the given view fully visible
|
||||
* inside the RecyclerView.
|
||||
*
|
||||
* @param view The view which we want to make fully visible
|
||||
* @param snapPreference The edge which the view should snap to when entering the visible
|
||||
* area. One of {@link #SNAP_TO_START}, {@link #SNAP_TO_END} or
|
||||
* {@link #SNAP_TO_END}.
|
||||
* @return The vertical scroll amount necessary to make the view visible with the given
|
||||
* snap preference.
|
||||
*/
|
||||
public int calculateDyToMakeVisible(View view, int snapPreference) {
|
||||
final RecyclerView.LayoutManager layoutManager = getLayoutManager();
|
||||
if (!layoutManager.canScrollVertically()) {
|
||||
return 0;
|
||||
}
|
||||
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
|
||||
view.getLayoutParams();
|
||||
final int top = layoutManager.getDecoratedTop(view) - params.topMargin;
|
||||
final int bottom = layoutManager.getDecoratedBottom(view) + params.bottomMargin;
|
||||
final int start = layoutManager.getPaddingTop();
|
||||
final int end = layoutManager.getHeight() - layoutManager.getPaddingBottom();
|
||||
return calculateDtToFit(top, bottom, start, end, snapPreference);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the horizontal scroll amount necessary to make the given view fully visible
|
||||
* inside the RecyclerView.
|
||||
*
|
||||
* @param view The view which we want to make fully visible
|
||||
* @param snapPreference The edge which the view should snap to when entering the visible
|
||||
* area. One of {@link #SNAP_TO_START}, {@link #SNAP_TO_END} or
|
||||
* {@link #SNAP_TO_END}
|
||||
* @return The vertical scroll amount necessary to make the view visible with the given
|
||||
* snap preference.
|
||||
*/
|
||||
public int calculateDxToMakeVisible(View view, int snapPreference) {
|
||||
final RecyclerView.LayoutManager layoutManager = getLayoutManager();
|
||||
if (!layoutManager.canScrollHorizontally()) {
|
||||
return 0;
|
||||
}
|
||||
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
|
||||
view.getLayoutParams();
|
||||
final int left = layoutManager.getDecoratedLeft(view) - params.leftMargin;
|
||||
final int right = layoutManager.getDecoratedRight(view) + params.rightMargin;
|
||||
final int start = layoutManager.getPaddingLeft();
|
||||
final int end = layoutManager.getWidth() - layoutManager.getPaddingRight();
|
||||
return calculateDtToFit(left, right, start, end, snapPreference);
|
||||
}
|
||||
|
||||
abstract public PointF computeScrollVectorForPosition(int targetPosition);
|
||||
}
|
||||
@ -1,238 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 android.support.v7.widget;
|
||||
|
||||
import android.support.v7.widget.AdapterHelper.UpdateOp;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static android.support.v7.widget.AdapterHelper.UpdateOp.ADD;
|
||||
import static android.support.v7.widget.AdapterHelper.UpdateOp.MOVE;
|
||||
import static android.support.v7.widget.AdapterHelper.UpdateOp.REMOVE;
|
||||
import static android.support.v7.widget.AdapterHelper.UpdateOp.UPDATE;
|
||||
|
||||
class OpReorderer {
|
||||
|
||||
final Callback mCallback;
|
||||
|
||||
public OpReorderer(Callback callback) {
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
void reorderOps(List<UpdateOp> ops) {
|
||||
// since move operations breaks continuity, their effects on ADD/RM are hard to handle.
|
||||
// we push them to the end of the list so that they can be handled easily.
|
||||
int badMove;
|
||||
while ((badMove = getLastMoveOutOfOrder(ops)) != -1) {
|
||||
swapMoveOp(ops, badMove, badMove + 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void swapMoveOp(List<UpdateOp> list, int badMove, int next) {
|
||||
final UpdateOp moveOp = list.get(badMove);
|
||||
final UpdateOp nextOp = list.get(next);
|
||||
switch (nextOp.cmd) {
|
||||
case REMOVE:
|
||||
swapMoveRemove(list, badMove, moveOp, next, nextOp);
|
||||
break;
|
||||
case ADD:
|
||||
swapMoveAdd(list, badMove, moveOp, next, nextOp);
|
||||
break;
|
||||
case UPDATE:
|
||||
swapMoveUpdate(list, badMove, moveOp, next, nextOp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void swapMoveRemove(List<UpdateOp> list, int movePos, UpdateOp moveOp,
|
||||
int removePos, UpdateOp removeOp) {
|
||||
UpdateOp extraRm = null;
|
||||
// check if move is nulled out by remove
|
||||
boolean revertedMove = false;
|
||||
final boolean moveIsBackwards;
|
||||
|
||||
if (moveOp.positionStart < moveOp.itemCount) {
|
||||
moveIsBackwards = false;
|
||||
if (removeOp.positionStart == moveOp.positionStart
|
||||
&& removeOp.itemCount == moveOp.itemCount - moveOp.positionStart) {
|
||||
revertedMove = true;
|
||||
}
|
||||
} else {
|
||||
moveIsBackwards = true;
|
||||
if (removeOp.positionStart == moveOp.itemCount + 1 &&
|
||||
removeOp.itemCount == moveOp.positionStart - moveOp.itemCount) {
|
||||
revertedMove = true;
|
||||
}
|
||||
}
|
||||
|
||||
// going in reverse, first revert the effect of add
|
||||
if (moveOp.itemCount < removeOp.positionStart) {
|
||||
removeOp.positionStart--;
|
||||
} else if (moveOp.itemCount < removeOp.positionStart + removeOp.itemCount) {
|
||||
// move is removed.
|
||||
removeOp.itemCount --;
|
||||
moveOp.cmd = REMOVE;
|
||||
moveOp.itemCount = 1;
|
||||
if (removeOp.itemCount == 0) {
|
||||
list.remove(removePos);
|
||||
mCallback.recycleUpdateOp(removeOp);
|
||||
}
|
||||
// no need to swap, it is already a remove
|
||||
return;
|
||||
}
|
||||
|
||||
// now affect of add is consumed. now apply effect of first remove
|
||||
if (moveOp.positionStart <= removeOp.positionStart) {
|
||||
removeOp.positionStart++;
|
||||
} else if (moveOp.positionStart < removeOp.positionStart + removeOp.itemCount) {
|
||||
final int remaining = removeOp.positionStart + removeOp.itemCount
|
||||
- moveOp.positionStart;
|
||||
extraRm = mCallback.obtainUpdateOp(REMOVE, moveOp.positionStart + 1, remaining);
|
||||
removeOp.itemCount = moveOp.positionStart - removeOp.positionStart;
|
||||
}
|
||||
|
||||
// if effects of move is reverted by remove, we are done.
|
||||
if (revertedMove) {
|
||||
list.set(movePos, removeOp);
|
||||
list.remove(removePos);
|
||||
mCallback.recycleUpdateOp(moveOp);
|
||||
return;
|
||||
}
|
||||
|
||||
// now find out the new locations for move actions
|
||||
if (moveIsBackwards) {
|
||||
if (extraRm != null) {
|
||||
if (moveOp.positionStart > extraRm.positionStart) {
|
||||
moveOp.positionStart -= extraRm.itemCount;
|
||||
}
|
||||
if (moveOp.itemCount > extraRm.positionStart) {
|
||||
moveOp.itemCount -= extraRm.itemCount;
|
||||
}
|
||||
}
|
||||
if (moveOp.positionStart > removeOp.positionStart) {
|
||||
moveOp.positionStart -= removeOp.itemCount;
|
||||
}
|
||||
if (moveOp.itemCount > removeOp.positionStart) {
|
||||
moveOp.itemCount -= removeOp.itemCount;
|
||||
}
|
||||
} else {
|
||||
if (extraRm != null) {
|
||||
if (moveOp.positionStart >= extraRm.positionStart) {
|
||||
moveOp.positionStart -= extraRm.itemCount;
|
||||
}
|
||||
if (moveOp.itemCount >= extraRm.positionStart) {
|
||||
moveOp.itemCount -= extraRm.itemCount;
|
||||
}
|
||||
}
|
||||
if (moveOp.positionStart >= removeOp.positionStart) {
|
||||
moveOp.positionStart -= removeOp.itemCount;
|
||||
}
|
||||
if (moveOp.itemCount >= removeOp.positionStart) {
|
||||
moveOp.itemCount -= removeOp.itemCount;
|
||||
}
|
||||
}
|
||||
|
||||
list.set(movePos, removeOp);
|
||||
if (moveOp.positionStart != moveOp.itemCount) {
|
||||
list.set(removePos, moveOp);
|
||||
} else {
|
||||
list.remove(removePos);
|
||||
}
|
||||
if (extraRm != null) {
|
||||
list.add(movePos, extraRm);
|
||||
}
|
||||
}
|
||||
|
||||
private void swapMoveAdd(List<UpdateOp> list, int move, UpdateOp moveOp, int add,
|
||||
UpdateOp addOp) {
|
||||
int offset = 0;
|
||||
// going in reverse, first revert the effect of add
|
||||
if (moveOp.itemCount < addOp.positionStart) {
|
||||
offset--;
|
||||
}
|
||||
if (moveOp.positionStart < addOp.positionStart) {
|
||||
offset++;
|
||||
}
|
||||
if (addOp.positionStart <= moveOp.positionStart) {
|
||||
moveOp.positionStart += addOp.itemCount;
|
||||
}
|
||||
if (addOp.positionStart <= moveOp.itemCount) {
|
||||
moveOp.itemCount += addOp.itemCount;
|
||||
}
|
||||
addOp.positionStart += offset;
|
||||
list.set(move, addOp);
|
||||
list.set(add, moveOp);
|
||||
}
|
||||
|
||||
void swapMoveUpdate(List<UpdateOp> list, int move, UpdateOp moveOp, int update,
|
||||
UpdateOp updateOp) {
|
||||
UpdateOp extraUp1 = null;
|
||||
UpdateOp extraUp2 = null;
|
||||
// going in reverse, first revert the effect of add
|
||||
if (moveOp.itemCount < updateOp.positionStart) {
|
||||
updateOp.positionStart--;
|
||||
} else if (moveOp.itemCount < updateOp.positionStart + updateOp.itemCount) {
|
||||
// moved item is updated. add an update for it
|
||||
updateOp.itemCount--;
|
||||
extraUp1 = mCallback.obtainUpdateOp(UPDATE, moveOp.positionStart, 1);
|
||||
}
|
||||
// now affect of add is consumed. now apply effect of first remove
|
||||
if (moveOp.positionStart <= updateOp.positionStart) {
|
||||
updateOp.positionStart++;
|
||||
} else if (moveOp.positionStart < updateOp.positionStart + updateOp.itemCount) {
|
||||
final int remaining = updateOp.positionStart + updateOp.itemCount
|
||||
- moveOp.positionStart;
|
||||
extraUp2 = mCallback.obtainUpdateOp(UPDATE, moveOp.positionStart + 1, remaining);
|
||||
updateOp.itemCount -= remaining;
|
||||
}
|
||||
list.set(update, moveOp);
|
||||
if (updateOp.itemCount > 0) {
|
||||
list.set(move, updateOp);
|
||||
} else {
|
||||
list.remove(move);
|
||||
mCallback.recycleUpdateOp(updateOp);
|
||||
}
|
||||
if (extraUp1 != null) {
|
||||
list.add(move, extraUp1);
|
||||
}
|
||||
if (extraUp2 != null) {
|
||||
list.add(move, extraUp2);
|
||||
}
|
||||
}
|
||||
|
||||
private int getLastMoveOutOfOrder(List<UpdateOp> list) {
|
||||
boolean foundNonMove = false;
|
||||
for (int i = list.size() - 1; i >= 0; i--) {
|
||||
final UpdateOp op1 = list.get(i);
|
||||
if (op1.cmd == MOVE) {
|
||||
if (foundNonMove) {
|
||||
return i;
|
||||
}
|
||||
} else {
|
||||
foundNonMove = true;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static interface Callback {
|
||||
|
||||
UpdateOp obtainUpdateOp(int cmd, int startPosition, int itemCount);
|
||||
|
||||
void recycleUpdateOp(UpdateOp op);
|
||||
}
|
||||
}
|
||||
@ -1,338 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 android.support.v7.widget;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
/**
|
||||
* Helper class for LayoutManagers to abstract measurements depending on the View's orientation.
|
||||
* <p>
|
||||
* It is developed to easily support vertical and horizontal orientations in a LayoutManager but
|
||||
* can also be used to abstract calls around view bounds and child measurements with margins and
|
||||
* decorations.
|
||||
*
|
||||
* @see #createHorizontalHelper(RecyclerView.LayoutManager)
|
||||
* @see #createVerticalHelper(RecyclerView.LayoutManager)
|
||||
*/
|
||||
public abstract class OrientationHelper {
|
||||
|
||||
private static final int INVALID_SIZE = Integer.MIN_VALUE;
|
||||
|
||||
protected final RecyclerView.LayoutManager mLayoutManager;
|
||||
|
||||
public static final int HORIZONTAL = LinearLayout.HORIZONTAL;
|
||||
|
||||
public static final int VERTICAL = LinearLayout.VERTICAL;
|
||||
|
||||
private int mLastTotalSpace = INVALID_SIZE;
|
||||
|
||||
private OrientationHelper(RecyclerView.LayoutManager layoutManager) {
|
||||
mLayoutManager = layoutManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method after onLayout method is complete if state is NOT pre-layout.
|
||||
* This method records information like layout bounds that might be useful in the next layout
|
||||
* calculations.
|
||||
*/
|
||||
public void onLayoutComplete() {
|
||||
mLastTotalSpace = getTotalSpace();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the layout space change between the previous layout pass and current layout pass.
|
||||
* <p>
|
||||
* Make sure you call {@link #onLayoutComplete()} at the end of your LayoutManager's
|
||||
* {@link RecyclerView.LayoutManager#onLayoutChildren(RecyclerView.Recycler,
|
||||
* RecyclerView.State)} method.
|
||||
*
|
||||
* @return The difference between the current total space and previous layout's total space.
|
||||
* @see #onLayoutComplete()
|
||||
*/
|
||||
public int getTotalSpaceChange() {
|
||||
return INVALID_SIZE == mLastTotalSpace ? 0 : getTotalSpace() - mLastTotalSpace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the start of the view including its decoration and margin.
|
||||
* <p>
|
||||
* For example, for the horizontal helper, if a View's left is at pixel 20, has 2px left
|
||||
* decoration and 3px left margin, returned value will be 15px.
|
||||
*
|
||||
* @param view The view element to check
|
||||
* @return The first pixel of the element
|
||||
* @see #getDecoratedEnd(View)
|
||||
*/
|
||||
public abstract int getDecoratedStart(View view);
|
||||
|
||||
/**
|
||||
* Returns the end of the view including its decoration and margin.
|
||||
* <p>
|
||||
* For example, for the horizontal helper, if a View's right is at pixel 200, has 2px right
|
||||
* decoration and 3px right margin, returned value will be 205.
|
||||
*
|
||||
* @param view The view element to check
|
||||
* @return The last pixel of the element
|
||||
* @see #getDecoratedStart(View)
|
||||
*/
|
||||
public abstract int getDecoratedEnd(View view);
|
||||
|
||||
/**
|
||||
* Returns the space occupied by this View in the current orientation including decorations and
|
||||
* margins.
|
||||
*
|
||||
* @param view The view element to check
|
||||
* @return Total space occupied by this view
|
||||
* @see #getDecoratedMeasurementInOther(View)
|
||||
*/
|
||||
public abstract int getDecoratedMeasurement(View view);
|
||||
|
||||
/**
|
||||
* Returns the space occupied by this View in the perpendicular orientation including
|
||||
* decorations and margins.
|
||||
*
|
||||
* @param view The view element to check
|
||||
* @return Total space occupied by this view in the perpendicular orientation to current one
|
||||
* @see #getDecoratedMeasurement(View)
|
||||
*/
|
||||
public abstract int getDecoratedMeasurementInOther(View view);
|
||||
|
||||
/**
|
||||
* Returns the start position of the layout after the start padding is added.
|
||||
*
|
||||
* @return The very first pixel we can draw.
|
||||
*/
|
||||
public abstract int getStartAfterPadding();
|
||||
|
||||
/**
|
||||
* Returns the end position of the layout after the end padding is removed.
|
||||
*
|
||||
* @return The end boundary for this layout.
|
||||
*/
|
||||
public abstract int getEndAfterPadding();
|
||||
|
||||
/**
|
||||
* Returns the end position of the layout without taking padding into account.
|
||||
*
|
||||
* @return The end boundary for this layout without considering padding.
|
||||
*/
|
||||
public abstract int getEnd();
|
||||
|
||||
/**
|
||||
* Offsets all children's positions by the given amount.
|
||||
*
|
||||
* @param amount Value to add to each child's layout parameters
|
||||
*/
|
||||
public abstract void offsetChildren(int amount);
|
||||
|
||||
/**
|
||||
* Returns the total space to layout. This number is the difference between
|
||||
* {@link #getEndAfterPadding()} and {@link #getStartAfterPadding()}.
|
||||
*
|
||||
* @return Total space to layout children
|
||||
*/
|
||||
public abstract int getTotalSpace();
|
||||
|
||||
/**
|
||||
* Offsets the child in this orientation.
|
||||
*
|
||||
* @param view View to offset
|
||||
* @param offset offset amount
|
||||
*/
|
||||
public abstract void offsetChild(View view, int offset);
|
||||
|
||||
/**
|
||||
* Returns the padding at the end of the layout. For horizontal helper, this is the right
|
||||
* padding and for vertical helper, this is the bottom padding. This method does not check
|
||||
* whether the layout is RTL or not.
|
||||
*
|
||||
* @return The padding at the end of the layout.
|
||||
*/
|
||||
public abstract int getEndPadding();
|
||||
|
||||
/**
|
||||
* Creates an OrientationHelper for the given LayoutManager and orientation.
|
||||
*
|
||||
* @param layoutManager LayoutManager to attach to
|
||||
* @param orientation Desired orientation. Should be {@link #HORIZONTAL} or {@link #VERTICAL}
|
||||
* @return A new OrientationHelper
|
||||
*/
|
||||
public static OrientationHelper createOrientationHelper(
|
||||
RecyclerView.LayoutManager layoutManager, int orientation) {
|
||||
switch (orientation) {
|
||||
case HORIZONTAL:
|
||||
return createHorizontalHelper(layoutManager);
|
||||
case VERTICAL:
|
||||
return createVerticalHelper(layoutManager);
|
||||
}
|
||||
throw new IllegalArgumentException("invalid orientation");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a horizontal OrientationHelper for the given LayoutManager.
|
||||
*
|
||||
* @param layoutManager The LayoutManager to attach to.
|
||||
* @return A new OrientationHelper
|
||||
*/
|
||||
public static OrientationHelper createHorizontalHelper(
|
||||
RecyclerView.LayoutManager layoutManager) {
|
||||
return new OrientationHelper(layoutManager) {
|
||||
@Override
|
||||
public int getEndAfterPadding() {
|
||||
return mLayoutManager.getWidth() - mLayoutManager.getPaddingRight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEnd() {
|
||||
return mLayoutManager.getWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void offsetChildren(int amount) {
|
||||
mLayoutManager.offsetChildrenHorizontal(amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStartAfterPadding() {
|
||||
return mLayoutManager.getPaddingLeft();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDecoratedMeasurement(View view) {
|
||||
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
|
||||
view.getLayoutParams();
|
||||
return mLayoutManager.getDecoratedMeasuredWidth(view) + params.leftMargin
|
||||
+ params.rightMargin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDecoratedMeasurementInOther(View view) {
|
||||
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
|
||||
view.getLayoutParams();
|
||||
return mLayoutManager.getDecoratedMeasuredHeight(view) + params.topMargin
|
||||
+ params.bottomMargin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDecoratedEnd(View view) {
|
||||
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
|
||||
view.getLayoutParams();
|
||||
return mLayoutManager.getDecoratedRight(view) + params.rightMargin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDecoratedStart(View view) {
|
||||
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
|
||||
view.getLayoutParams();
|
||||
return mLayoutManager.getDecoratedLeft(view) - params.leftMargin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalSpace() {
|
||||
return mLayoutManager.getWidth() - mLayoutManager.getPaddingLeft()
|
||||
- mLayoutManager.getPaddingRight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void offsetChild(View view, int offset) {
|
||||
view.offsetLeftAndRight(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEndPadding() {
|
||||
return mLayoutManager.getPaddingRight();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a vertical OrientationHelper for the given LayoutManager.
|
||||
*
|
||||
* @param layoutManager The LayoutManager to attach to.
|
||||
* @return A new OrientationHelper
|
||||
*/
|
||||
public static OrientationHelper createVerticalHelper(RecyclerView.LayoutManager layoutManager) {
|
||||
return new OrientationHelper(layoutManager) {
|
||||
@Override
|
||||
public int getEndAfterPadding() {
|
||||
return mLayoutManager.getHeight() - mLayoutManager.getPaddingBottom();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEnd() {
|
||||
return mLayoutManager.getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void offsetChildren(int amount) {
|
||||
mLayoutManager.offsetChildrenVertical(amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStartAfterPadding() {
|
||||
return mLayoutManager.getPaddingTop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDecoratedMeasurement(View view) {
|
||||
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
|
||||
view.getLayoutParams();
|
||||
return mLayoutManager.getDecoratedMeasuredHeight(view) + params.topMargin
|
||||
+ params.bottomMargin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDecoratedMeasurementInOther(View view) {
|
||||
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
|
||||
view.getLayoutParams();
|
||||
return mLayoutManager.getDecoratedMeasuredWidth(view) + params.leftMargin
|
||||
+ params.rightMargin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDecoratedEnd(View view) {
|
||||
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
|
||||
view.getLayoutParams();
|
||||
return mLayoutManager.getDecoratedBottom(view) + params.bottomMargin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDecoratedStart(View view) {
|
||||
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
|
||||
view.getLayoutParams();
|
||||
return mLayoutManager.getDecoratedTop(view) - params.topMargin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalSpace() {
|
||||
return mLayoutManager.getHeight() - mLayoutManager.getPaddingTop()
|
||||
- mLayoutManager.getPaddingBottom();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void offsetChild(View view, int offset) {
|
||||
view.offsetTopAndBottom(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEndPadding() {
|
||||
return mLayoutManager.getPaddingBottom();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1,460 +0,0 @@
|
||||
/*
|
||||
* 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 android.support.v7.widget;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Like a SparseArray, but with the ability to offset key ranges for bulk insertions/deletions.
|
||||
*/
|
||||
class PositionMap<E> implements Cloneable {
|
||||
private static final Object DELETED = new Object();
|
||||
private boolean mGarbage = false;
|
||||
|
||||
private int[] mKeys;
|
||||
private Object[] mValues;
|
||||
private int mSize;
|
||||
|
||||
/**
|
||||
* Creates a new SparseArray containing no mappings.
|
||||
*/
|
||||
public PositionMap() {
|
||||
this(10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new PositionMap containing no mappings that will not
|
||||
* require any additional memory allocation to store the specified
|
||||
* number of mappings. If you supply an initial capacity of 0, the
|
||||
* sparse array will be initialized with a light-weight representation
|
||||
* not requiring any additional array allocations.
|
||||
*/
|
||||
public PositionMap(int initialCapacity) {
|
||||
if (initialCapacity == 0) {
|
||||
mKeys = ContainerHelpers.EMPTY_INTS;
|
||||
mValues = ContainerHelpers.EMPTY_OBJECTS;
|
||||
} else {
|
||||
initialCapacity = idealIntArraySize(initialCapacity);
|
||||
mKeys = new int[initialCapacity];
|
||||
mValues = new Object[initialCapacity];
|
||||
}
|
||||
mSize = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public PositionMap<E> clone() {
|
||||
PositionMap<E> clone = null;
|
||||
try {
|
||||
clone = (PositionMap<E>) super.clone();
|
||||
clone.mKeys = mKeys.clone();
|
||||
clone.mValues = mValues.clone();
|
||||
} catch (CloneNotSupportedException cnse) {
|
||||
/* ignore */
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Object mapped from the specified key, or <code>null</code>
|
||||
* if no such mapping has been made.
|
||||
*/
|
||||
public E get(int key) {
|
||||
return get(key, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Object mapped from the specified key, or the specified Object
|
||||
* if no such mapping has been made.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public E get(int key, E valueIfKeyNotFound) {
|
||||
int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
|
||||
|
||||
if (i < 0 || mValues[i] == DELETED) {
|
||||
return valueIfKeyNotFound;
|
||||
} else {
|
||||
return (E) mValues[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the mapping from the specified key, if there was any.
|
||||
*/
|
||||
public void delete(int key) {
|
||||
int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
|
||||
|
||||
if (i >= 0) {
|
||||
if (mValues[i] != DELETED) {
|
||||
mValues[i] = DELETED;
|
||||
mGarbage = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for {@link #delete(int)}.
|
||||
*/
|
||||
public void remove(int key) {
|
||||
delete(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the mapping at the specified index.
|
||||
*/
|
||||
public void removeAt(int index) {
|
||||
if (mValues[index] != DELETED) {
|
||||
mValues[index] = DELETED;
|
||||
mGarbage = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a range of mappings as a batch.
|
||||
*
|
||||
* @param index Index to begin at
|
||||
* @param size Number of mappings to remove
|
||||
*/
|
||||
public void removeAtRange(int index, int size) {
|
||||
final int end = Math.min(mSize, index + size);
|
||||
for (int i = index; i < end; i++) {
|
||||
removeAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void insertKeyRange(int keyStart, int count) {
|
||||
|
||||
}
|
||||
|
||||
public void removeKeyRange(ArrayList<E> removedItems, int keyStart, int count) {
|
||||
|
||||
}
|
||||
|
||||
private void gc() {
|
||||
// Log.e("SparseArray", "gc start with " + mSize);
|
||||
|
||||
int n = mSize;
|
||||
int o = 0;
|
||||
int[] keys = mKeys;
|
||||
Object[] values = mValues;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
Object val = values[i];
|
||||
|
||||
if (val != DELETED) {
|
||||
if (i != o) {
|
||||
keys[o] = keys[i];
|
||||
values[o] = val;
|
||||
values[i] = null;
|
||||
}
|
||||
|
||||
o++;
|
||||
}
|
||||
}
|
||||
|
||||
mGarbage = false;
|
||||
mSize = o;
|
||||
|
||||
// Log.e("SparseArray", "gc end with " + mSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a mapping from the specified key to the specified value,
|
||||
* replacing the previous mapping from the specified key if there
|
||||
* was one.
|
||||
*/
|
||||
public void put(int key, E value) {
|
||||
int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
|
||||
|
||||
if (i >= 0) {
|
||||
mValues[i] = value;
|
||||
} else {
|
||||
i = ~i;
|
||||
|
||||
if (i < mSize && mValues[i] == DELETED) {
|
||||
mKeys[i] = key;
|
||||
mValues[i] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mGarbage && mSize >= mKeys.length) {
|
||||
gc();
|
||||
|
||||
// Search again because indices may have changed.
|
||||
i = ~ContainerHelpers.binarySearch(mKeys, mSize, key);
|
||||
}
|
||||
|
||||
if (mSize >= mKeys.length) {
|
||||
int n = idealIntArraySize(mSize + 1);
|
||||
|
||||
int[] nkeys = new int[n];
|
||||
Object[] nvalues = new Object[n];
|
||||
|
||||
// Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
|
||||
System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
|
||||
System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
|
||||
|
||||
mKeys = nkeys;
|
||||
mValues = nvalues;
|
||||
}
|
||||
|
||||
if (mSize - i != 0) {
|
||||
// Log.e("SparseArray", "move " + (mSize - i));
|
||||
System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
|
||||
System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
|
||||
}
|
||||
|
||||
mKeys[i] = key;
|
||||
mValues[i] = value;
|
||||
mSize++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of key-value mappings that this SparseArray
|
||||
* currently stores.
|
||||
*/
|
||||
public int size() {
|
||||
if (mGarbage) {
|
||||
gc();
|
||||
}
|
||||
|
||||
return mSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an index in the range <code>0...size()-1</code>, returns
|
||||
* the key from the <code>index</code>th key-value mapping that this
|
||||
* SparseArray stores.
|
||||
*/
|
||||
public int keyAt(int index) {
|
||||
if (mGarbage) {
|
||||
gc();
|
||||
}
|
||||
|
||||
return mKeys[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an index in the range <code>0...size()-1</code>, returns
|
||||
* the value from the <code>index</code>th key-value mapping that this
|
||||
* SparseArray stores.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public E valueAt(int index) {
|
||||
if (mGarbage) {
|
||||
gc();
|
||||
}
|
||||
|
||||
return (E) mValues[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an index in the range <code>0...size()-1</code>, sets a new
|
||||
* value for the <code>index</code>th key-value mapping that this
|
||||
* SparseArray stores.
|
||||
*/
|
||||
public void setValueAt(int index, E value) {
|
||||
if (mGarbage) {
|
||||
gc();
|
||||
}
|
||||
|
||||
mValues[index] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index for which {@link #keyAt} would return the
|
||||
* specified key, or a negative number if the specified
|
||||
* key is not mapped.
|
||||
*/
|
||||
public int indexOfKey(int key) {
|
||||
if (mGarbage) {
|
||||
gc();
|
||||
}
|
||||
|
||||
return ContainerHelpers.binarySearch(mKeys, mSize, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an index for which {@link #valueAt} would return the
|
||||
* specified key, or a negative number if no keys map to the
|
||||
* specified value.
|
||||
* <p>Beware that this is a linear search, unlike lookups by key,
|
||||
* and that multiple keys can map to the same value and this will
|
||||
* find only one of them.
|
||||
* <p>Note also that unlike most collections' {@code indexOf} methods,
|
||||
* this method compares values using {@code ==} rather than {@code equals}.
|
||||
*/
|
||||
public int indexOfValue(E value) {
|
||||
if (mGarbage) {
|
||||
gc();
|
||||
}
|
||||
|
||||
for (int i = 0; i < mSize; i++)
|
||||
if (mValues[i] == value)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all key-value mappings from this SparseArray.
|
||||
*/
|
||||
public void clear() {
|
||||
int n = mSize;
|
||||
Object[] values = mValues;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
values[i] = null;
|
||||
}
|
||||
|
||||
mSize = 0;
|
||||
mGarbage = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a key/value pair into the array, optimizing for the case where
|
||||
* the key is greater than all existing keys in the array.
|
||||
*/
|
||||
public void append(int key, E value) {
|
||||
if (mSize != 0 && key <= mKeys[mSize - 1]) {
|
||||
put(key, value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mGarbage && mSize >= mKeys.length) {
|
||||
gc();
|
||||
}
|
||||
|
||||
int pos = mSize;
|
||||
if (pos >= mKeys.length) {
|
||||
int n = idealIntArraySize(pos + 1);
|
||||
|
||||
int[] nkeys = new int[n];
|
||||
Object[] nvalues = new Object[n];
|
||||
|
||||
// Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
|
||||
System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
|
||||
System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
|
||||
|
||||
mKeys = nkeys;
|
||||
mValues = nvalues;
|
||||
}
|
||||
|
||||
mKeys[pos] = key;
|
||||
mValues[pos] = value;
|
||||
mSize = pos + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>This implementation composes a string by iterating over its mappings. If
|
||||
* this map contains itself as a value, the string "(this Map)"
|
||||
* will appear in its place.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
if (size() <= 0) {
|
||||
return "{}";
|
||||
}
|
||||
|
||||
StringBuilder buffer = new StringBuilder(mSize * 28);
|
||||
buffer.append('{');
|
||||
for (int i=0; i<mSize; i++) {
|
||||
if (i > 0) {
|
||||
buffer.append(", ");
|
||||
}
|
||||
int key = keyAt(i);
|
||||
buffer.append(key);
|
||||
buffer.append('=');
|
||||
Object value = valueAt(i);
|
||||
if (value != this) {
|
||||
buffer.append(value);
|
||||
} else {
|
||||
buffer.append("(this Map)");
|
||||
}
|
||||
}
|
||||
buffer.append('}');
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
static int idealByteArraySize(int need) {
|
||||
for (int i = 4; i < 32; i++)
|
||||
if (need <= (1 << i) - 12)
|
||||
return (1 << i) - 12;
|
||||
|
||||
return need;
|
||||
}
|
||||
|
||||
static int idealBooleanArraySize(int need) {
|
||||
return idealByteArraySize(need);
|
||||
}
|
||||
|
||||
static int idealShortArraySize(int need) {
|
||||
return idealByteArraySize(need * 2) / 2;
|
||||
}
|
||||
|
||||
static int idealCharArraySize(int need) {
|
||||
return idealByteArraySize(need * 2) / 2;
|
||||
}
|
||||
|
||||
static int idealIntArraySize(int need) {
|
||||
return idealByteArraySize(need * 4) / 4;
|
||||
}
|
||||
|
||||
static int idealFloatArraySize(int need) {
|
||||
return idealByteArraySize(need * 4) / 4;
|
||||
}
|
||||
|
||||
static int idealObjectArraySize(int need) {
|
||||
return idealByteArraySize(need * 4) / 4;
|
||||
}
|
||||
|
||||
static int idealLongArraySize(int need) {
|
||||
return idealByteArraySize(need * 8) / 8;
|
||||
}
|
||||
|
||||
static class ContainerHelpers {
|
||||
static final boolean[] EMPTY_BOOLEANS = new boolean[0];
|
||||
static final int[] EMPTY_INTS = new int[0];
|
||||
static final long[] EMPTY_LONGS = new long[0];
|
||||
static final Object[] EMPTY_OBJECTS = new Object[0];
|
||||
|
||||
// This is Arrays.binarySearch(), but doesn't do any argument validation.
|
||||
static int binarySearch(int[] array, int size, int value) {
|
||||
int lo = 0;
|
||||
int hi = size - 1;
|
||||
|
||||
while (lo <= hi) {
|
||||
final int mid = (lo + hi) >>> 1;
|
||||
final int midVal = array[mid];
|
||||
|
||||
if (midVal < value) {
|
||||
lo = mid + 1;
|
||||
} else if (midVal > value) {
|
||||
hi = mid - 1;
|
||||
} else {
|
||||
return mid; // value found
|
||||
}
|
||||
}
|
||||
return ~lo; // value not present
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 android.support.v7.widget;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.view.AccessibilityDelegateCompat;
|
||||
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
|
||||
/**
|
||||
* The AccessibilityDelegate used by RecyclerView.
|
||||
* <p>
|
||||
* This class handles basic accessibility actions and delegates them to LayoutManager.
|
||||
*/
|
||||
public class RecyclerViewAccessibilityDelegate extends AccessibilityDelegateCompat {
|
||||
final RecyclerView mRecyclerView;
|
||||
|
||||
|
||||
public RecyclerViewAccessibilityDelegate(RecyclerView recyclerView) {
|
||||
mRecyclerView = recyclerView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean performAccessibilityAction(View host, int action, Bundle args) {
|
||||
if (super.performAccessibilityAction(host, action, args)) {
|
||||
return true;
|
||||
}
|
||||
if (mRecyclerView.getLayoutManager() != null) {
|
||||
return mRecyclerView.getLayoutManager().performAccessibilityAction(action, args);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
|
||||
super.onInitializeAccessibilityNodeInfo(host, info);
|
||||
info.setClassName(RecyclerView.class.getName());
|
||||
if (mRecyclerView.getLayoutManager() != null) {
|
||||
mRecyclerView.getLayoutManager().onInitializeAccessibilityNodeInfo(info);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
|
||||
super.onInitializeAccessibilityEvent(host, event);
|
||||
event.setClassName(RecyclerView.class.getName());
|
||||
if (host instanceof RecyclerView) {
|
||||
RecyclerView rv = (RecyclerView) host;
|
||||
if (rv.getLayoutManager() != null) {
|
||||
rv.getLayoutManager().onInitializeAccessibilityEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AccessibilityDelegateCompat getItemDelegate() {
|
||||
return mItemDelegate;
|
||||
}
|
||||
|
||||
final AccessibilityDelegateCompat mItemDelegate = new AccessibilityDelegateCompat() {
|
||||
@Override
|
||||
public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
|
||||
super.onInitializeAccessibilityNodeInfo(host, info);
|
||||
if (mRecyclerView.getLayoutManager() != null) {
|
||||
mRecyclerView.getLayoutManager().
|
||||
onInitializeAccessibilityNodeInfoForItem(host, info);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean performAccessibilityAction(View host, int action, Bundle args) {
|
||||
if (super.performAccessibilityAction(host, action, args)) {
|
||||
return true;
|
||||
}
|
||||
if (mRecyclerView.getLayoutManager() != null) {
|
||||
return mRecyclerView.getLayoutManager().
|
||||
performAccessibilityActionForItem(host, action, args);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 android.support.v7.widget;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* A helper class to do scroll offset calculations.
|
||||
*/
|
||||
class ScrollbarHelper {
|
||||
|
||||
/**
|
||||
* @param startChild View closest to start of the list. (top or left)
|
||||
* @param endChild View closest to end of the list (bottom or right)
|
||||
*/
|
||||
static int computeScrollOffset(RecyclerView.State state, OrientationHelper orientation,
|
||||
View startChild, View endChild, RecyclerView.LayoutManager lm,
|
||||
boolean smoothScrollbarEnabled, boolean reverseLayout) {
|
||||
if (lm.getChildCount() == 0 || state.getItemCount() == 0 || startChild == null ||
|
||||
endChild == null) {
|
||||
return 0;
|
||||
}
|
||||
final int minPosition = Math.min(lm.getPosition(startChild), lm.getPosition(endChild));
|
||||
final int maxPosition = Math.max(lm.getPosition(startChild), lm.getPosition(endChild));
|
||||
final int itemsBefore = reverseLayout
|
||||
? Math.max(0, state.getItemCount() - maxPosition - 1)
|
||||
: Math.max(0, minPosition - 1);
|
||||
if (!smoothScrollbarEnabled) {
|
||||
return itemsBefore;
|
||||
}
|
||||
final int laidOutArea = Math.abs(orientation.getDecoratedEnd(endChild) -
|
||||
orientation.getDecoratedStart(startChild));
|
||||
final int itemRange = Math.abs(lm.getPosition(startChild) - lm.getPosition(endChild)) + 1;
|
||||
final float avgSizePerRow = (float) laidOutArea / itemRange;
|
||||
|
||||
return Math.round(itemsBefore * avgSizePerRow + (orientation.getStartAfterPadding()
|
||||
- orientation.getDecoratedStart(startChild)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param startChild View closest to start of the list. (top or left)
|
||||
* @param endChild View closest to end of the list (bottom or right)
|
||||
*/
|
||||
static int computeScrollExtent(RecyclerView.State state, OrientationHelper orientation,
|
||||
View startChild, View endChild, RecyclerView.LayoutManager lm,
|
||||
boolean smoothScrollbarEnabled) {
|
||||
if (lm.getChildCount() == 0 || state.getItemCount() == 0 || startChild == null ||
|
||||
endChild == null) {
|
||||
return 0;
|
||||
}
|
||||
if (!smoothScrollbarEnabled) {
|
||||
return Math.abs(lm.getPosition(startChild) - lm.getPosition(endChild)) + 1;
|
||||
}
|
||||
final int extend = orientation.getDecoratedEnd(endChild)
|
||||
- orientation.getDecoratedStart(startChild);
|
||||
return Math.min(orientation.getTotalSpace(), extend);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param startChild View closest to start of the list. (top or left)
|
||||
* @param endChild View closest to end of the list (bottom or right)
|
||||
*/
|
||||
static int computeScrollRange(RecyclerView.State state, OrientationHelper orientation,
|
||||
View startChild, View endChild, RecyclerView.LayoutManager lm,
|
||||
boolean smoothScrollbarEnabled) {
|
||||
if (lm.getChildCount() == 0 || state.getItemCount() == 0 || startChild == null ||
|
||||
endChild == null) {
|
||||
return 0;
|
||||
}
|
||||
if (!smoothScrollbarEnabled) {
|
||||
return state.getItemCount();
|
||||
}
|
||||
// smooth scrollbar enabled. try to estimate better.
|
||||
final int laidOutArea = orientation.getDecoratedEnd(endChild) -
|
||||
orientation.getDecoratedStart(startChild);
|
||||
final int laidOutRange = Math.abs(lm.getPosition(startChild) - lm.getPosition(endChild))
|
||||
+ 1;
|
||||
// estimate a size for full list.
|
||||
return (int) ((float) laidOutArea / laidOutRange * state.getItemCount());
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -6,50 +6,48 @@ 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 class CustomView extends RelativeLayout {
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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");
|
||||
// Indicate if user touched this view the last time
|
||||
public boolean isLastTouch = false;
|
||||
int beforeBackground;
|
||||
boolean animation = 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();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
if (animation)
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAnimationStart() {
|
||||
super.onAnimationStart();
|
||||
animation = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAnimationEnd() {
|
||||
super.onAnimationEnd();
|
||||
animation = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,176 +8,167 @@ import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.RectF;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
public class ProgressBarCircularIndeterminate extends CustomView {
|
||||
|
||||
final static String ANDROIDXML = "http://schemas.android.com/apk/res/android";
|
||||
final static String ANDROIDXML = "http://schemas.android.com/apk/res/android";
|
||||
|
||||
int backgroundColor = Color.parseColor("#1E88E5");
|
||||
int backgroundColor = Color.parseColor("#1E88E5");
|
||||
float radius1 = 0;
|
||||
float radius2 = 0;
|
||||
int cont = 0;
|
||||
boolean firstAnimationOver = false;
|
||||
int arcD = 1;
|
||||
int arcO = 0;
|
||||
float rotateAngle = 0;
|
||||
int limite = 0;
|
||||
|
||||
public ProgressBarCircularIndeterminate(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setAttributes(attrs);
|
||||
public ProgressBarCircularIndeterminate(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setAttributes(attrs);
|
||||
}
|
||||
|
||||
}
|
||||
// Set atributtes of XML to View
|
||||
protected void setAttributes(AttributeSet attrs) {
|
||||
|
||||
// Set atributtes of XML to View
|
||||
protected void setAttributes(AttributeSet attrs) {
|
||||
setMinimumHeight(Utils.dpToPx(32, getResources()));
|
||||
setMinimumWidth(Utils.dpToPx(32, getResources()));
|
||||
|
||||
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(ContextCompat.getColor(getContext(), bacgroundColor));
|
||||
} else {
|
||||
// Color by hexadecimal
|
||||
int background = attrs.getAttributeIntValue(ANDROIDXML, "background", -1);
|
||||
if (background != -1) {
|
||||
setBackgroundColor(background);
|
||||
} else {
|
||||
setBackgroundColor(Color.parseColor("#1E88E5"));
|
||||
}
|
||||
}
|
||||
|
||||
// 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()));
|
||||
|
||||
setMinimumHeight(Utils.dpToPx(3, getResources()));
|
||||
}
|
||||
|
||||
}
|
||||
// Set color of background
|
||||
public void setBackgroundColor(int color) {
|
||||
super.setBackgroundColor(ContextCompat.getColor(getContext(), android.R.color.transparent));
|
||||
if (isEnabled()) {
|
||||
beforeBackground = backgroundColor;
|
||||
}
|
||||
this.backgroundColor = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
drawFirstAnimation(canvas);
|
||||
}
|
||||
if (cont > 0) {
|
||||
drawSecondAnimation(canvas);
|
||||
}
|
||||
invalidate();
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
if (firstAnimationOver == false)
|
||||
drawFirstAnimation(canvas);
|
||||
if (cont > 0)
|
||||
drawSecondAnimation(canvas);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* 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(ContextCompat.getColor(getContext(), 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float radius1 = 0;
|
||||
float radius2 = 0;
|
||||
int cont = 0;
|
||||
boolean firstAnimationOver = false;
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
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(ContextCompat.getColor(getContext(), android.R.color.transparent));
|
||||
transparentPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
|
||||
temp.drawCircle(getWidth() / 2, getHeight() / 2, (getWidth() / 2)
|
||||
- Utils.dpToPx(4, getResources()), transparentPaint);
|
||||
|
||||
int arcD = 1;
|
||||
int arcO = 0;
|
||||
float rotateAngle = 0;
|
||||
int limite = 0;
|
||||
canvas.drawBitmap(bitmap, 0, 0, new Paint());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -5,30 +5,30 @@ 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) {
|
||||
|
||||
|
||||
/**
|
||||
* 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.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());
|
||||
}
|
||||
|
||||
if (myView.getId() == android.R.id.content)
|
||||
return myView.getLeft();
|
||||
else
|
||||
return myView.getLeft() + getRelativeLeft((View) myView.getParent());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,114 +1,200 @@
|
||||
package com.gh.base;
|
||||
|
||||
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.multidex.MultiDex;
|
||||
import android.support.v4.util.ArrayMap;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.bandeng.MyEventBusIndex;
|
||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.util.DataUtils;
|
||||
import com.gh.common.util.HttpsUtils;
|
||||
import com.gh.common.util.StringUtils;
|
||||
import com.gh.common.util.TokenUtils;
|
||||
import com.gh.common.util.Utils;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.leon.channel.helper.ChannelReaderUtil;
|
||||
import com.umeng.message.IUmengRegisterCallback;
|
||||
import com.umeng.message.PushAgent;
|
||||
import com.umeng.message.UTrack;
|
||||
import com.xiaomi.channel.commonutils.logger.LoggerInterface;
|
||||
import com.xiaomi.mipush.sdk.Logger;
|
||||
import com.xiaomi.mipush.sdk.MiPushClient;
|
||||
import com.xiaomi.mipush.sdk.MiPushCommandMessage;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class AppController extends Application {
|
||||
|
||||
public static final String TAG = AppController.class.getSimpleName();
|
||||
// xiaomi push appid
|
||||
public static final String APP_ID = "2882303761517352993";
|
||||
// xiaomi push appkey
|
||||
public static final String APP_KEY = "5451735292993";
|
||||
public static final String TAG = AppController.class.getSimpleName();
|
||||
public static final String KEY_FILE_INFO = "FileInfo";
|
||||
//快传文件发送单线程
|
||||
public static Executor FILE_SENDER_EXECUTOR = Executors.newSingleThreadExecutor();
|
||||
//快传文件发送主要的线程池
|
||||
public static Executor MAIN_EXECUTOR = Executors.newCachedThreadPool();
|
||||
private static AppController mInstance;
|
||||
private static ArrayMap<String, Object> objectMap = new ArrayMap<>();
|
||||
|
||||
private static AppController mInstance;
|
||||
private static ArrayMap<String, Object> objectMap = new ArrayMap<>();
|
||||
private String mChannel;
|
||||
|
||||
private ArrayList<Activity> list = new ArrayList<>();
|
||||
public static void put(String key, Object object) {
|
||||
if (objectMap == null) {
|
||||
objectMap = new ArrayMap<>();
|
||||
}
|
||||
objectMap.put(key, object);
|
||||
}
|
||||
|
||||
private boolean isFinish = false;
|
||||
public static Object get(String key, boolean isRemove) {
|
||||
if (objectMap == null) {
|
||||
return null;
|
||||
}
|
||||
if (isRemove) {
|
||||
return objectMap.remove(key);
|
||||
} else {
|
||||
return objectMap.get(key);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
//初始化Fresco
|
||||
Fresco.initialize(this);
|
||||
public static void remove(String key) {
|
||||
if (objectMap == null) {
|
||||
return;
|
||||
}
|
||||
objectMap.remove(key);
|
||||
}
|
||||
|
||||
DataUtils.init(this);
|
||||
public static String getProcessName(Context cxt, int pid) {
|
||||
ActivityManager am = (ActivityManager) cxt.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
List<RunningAppProcessInfo> runningApps = am.getRunningAppProcesses();
|
||||
if (runningApps == null) {
|
||||
return null;
|
||||
}
|
||||
for (RunningAppProcessInfo procInfo : runningApps) {
|
||||
if (procInfo.pid == pid) {
|
||||
return procInfo.processName;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
HttpsUtils.initHttpsUrlConnection(this);
|
||||
public static synchronized AppController getInstance() {
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
AppUncaHandler uncaHandler = new AppUncaHandler(this);
|
||||
Thread.setDefaultUncaughtExceptionHandler(uncaHandler);
|
||||
mInstance = this;
|
||||
public String getChannel() {
|
||||
return mChannel;
|
||||
}
|
||||
|
||||
// 注册push服务,注册成功后会向GHPushMessageReceiver发送广播
|
||||
// 可以从GHPushMessageReceiver的onCommandResult方法中MiPushCommandMessage对象参数中获取注册信息
|
||||
if (shouldInit()) {
|
||||
MiPushClient.registerPush(this, APP_ID, APP_KEY);
|
||||
}
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
LoggerInterface newLogger = new LoggerInterface() {
|
||||
MultiDex.install(this);
|
||||
mInstance = this;
|
||||
|
||||
@Override
|
||||
public void setTag(String tag) {
|
||||
// ignore
|
||||
}
|
||||
//TODO 强烈不建议开发阶段开启这个Handler,必须处理错误
|
||||
if (!BuildConfig.DEBUG) {
|
||||
AppUncaughtHandler appUncaughtHandler = new AppUncaughtHandler(this);
|
||||
Thread.setDefaultUncaughtExceptionHandler(appUncaughtHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String content, Throwable t) {
|
||||
Log.d(TAG, content, t);
|
||||
}
|
||||
mChannel = ChannelReaderUtil.getChannel(this);
|
||||
if (TextUtils.isEmpty(mChannel)) {
|
||||
//默认用Android Studio run时并没有写入channel magic number到apk包里面,所以需要fallback
|
||||
mChannel = "GH_TEST";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String content) {
|
||||
Log.d(TAG, content);
|
||||
}
|
||||
};
|
||||
Logger.setLogger(this, newLogger);
|
||||
Log.e("CHANNEL_ID", mChannel);
|
||||
|
||||
//友盟推送
|
||||
final PushAgent mPushAgent = PushAgent.getInstance(this);
|
||||
//初始化Fresco
|
||||
Fresco.initialize(this);
|
||||
|
||||
DataUtils.init(this, BuildConfig.DEBUG, mChannel);
|
||||
|
||||
//注册推送服务,每次调用register方法都会回调该接口
|
||||
mPushAgent.register(new IUmengRegisterCallback() {
|
||||
//测试MTA崩溃的,坑爹
|
||||
// if (BuildConfig.DEBUG) {
|
||||
// StatConfig.setDebugEnable(true);
|
||||
// StatConfig.setStatSendStrategy(StatReportStrategy.DEVELOPER);
|
||||
// throw new RuntimeException("test again");
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void onSuccess(String deviceToken) {
|
||||
//注册成功会返回device token
|
||||
Utils.log("deviceToken::" + deviceToken);
|
||||
HttpsUtils.initHttpsUrlConnection(this);
|
||||
|
||||
//设置别名
|
||||
mPushAgent.addExclusiveAlias(TokenUtils.getDeviceId(getApplicationContext())
|
||||
, "GHDID", new UTrack.ICallBack() {
|
||||
@Override
|
||||
public void onMessage(boolean b, String s) {
|
||||
Utils.log("ExclusiveAlias::" + b + "==" + s);
|
||||
// if (BuildConfig.DEBUG) {
|
||||
// Stetho.initializeWithDefaults(this);
|
||||
// }
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 注册push服务,注册成功后会向{@link GHPushMessageReceiver}发送广播
|
||||
* 可以从{@link GHPushMessageReceiver#onCommandResult(Context, MiPushCommandMessage)}
|
||||
* 的{@link MiPushCommandMessage} 对象参数中获取注册信息
|
||||
*/
|
||||
if (shouldInit()) {
|
||||
MiPushClient.registerPush(this, Config.MIPUSH_APPID, Config.MIPUSH_APPKEY);
|
||||
|
||||
@Override
|
||||
public void onFailure(String s, String s1) {
|
||||
Utils.log("deviceToken::" + "注册失败");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 友盟推送数据处理
|
||||
mPushAgent.setNotificationClickHandler(new GHUmengNotificationClickHandler());
|
||||
if (BuildConfig.DEBUG) {
|
||||
LoggerInterface newLogger = new LoggerInterface() {
|
||||
|
||||
@Override
|
||||
public void setTag(String tag) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String content) {
|
||||
Log.d(TAG, content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String content, Throwable t) {
|
||||
Log.d(TAG, content, t);
|
||||
}
|
||||
};
|
||||
Logger.setLogger(this, newLogger);
|
||||
}
|
||||
|
||||
//友盟推送
|
||||
final PushAgent pushAgent = PushAgent.getInstance(this);
|
||||
pushAgent.setAppkeyAndSecret(Config.UMENG_APPKEY, Config.UMENG_MESSAGE_SECRET);
|
||||
|
||||
//注册推送服务,每次调用register方法都会回调该接口
|
||||
pushAgent.register(new IUmengRegisterCallback() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(String deviceToken) {
|
||||
//注册成功会返回device token
|
||||
Utils.log("deviceToken::" + deviceToken);
|
||||
|
||||
//设置别名
|
||||
pushAgent.addExclusiveAlias(TokenUtils.getDeviceId(getApplicationContext()),
|
||||
"GHDID", new UTrack.ICallBack() {
|
||||
@Override
|
||||
public void onMessage(boolean b, String s) {
|
||||
Utils.log(StringUtils.buildString("ExclusiveAlias::", String.valueOf(b), "==", s));
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(String s, String s1) {
|
||||
Utils.log("deviceToken::" + "注册失败");
|
||||
}
|
||||
});
|
||||
|
||||
// 友盟推送数据处理
|
||||
pushAgent.setNotificationClickHandler(new GHUmengNotificationClickHandler());
|
||||
|
||||
// // 监听屏幕状态广播
|
||||
// if (shouldInit()) {
|
||||
@ -127,98 +213,23 @@ public class AppController extends Application {
|
||||
// Utils.log(appRunTimeInfo.getPackageName() + "====1111=====" + appRunTimeInfo.getRunTime());
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
public static void put(String key, Object object) {
|
||||
if (objectMap == null) {
|
||||
objectMap = new ArrayMap<>();
|
||||
}
|
||||
objectMap.put(key, object);
|
||||
}
|
||||
// 启用EventBus3.0加速功能
|
||||
EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
|
||||
}
|
||||
|
||||
public static Object get(String key, boolean isRemove) {
|
||||
if (objectMap == null) {
|
||||
return null;
|
||||
}
|
||||
if (isRemove) {
|
||||
return objectMap.remove(key);
|
||||
} else {
|
||||
return objectMap.get(key);
|
||||
}
|
||||
}
|
||||
|
||||
public static void remove(String key) {
|
||||
if (objectMap == null) {
|
||||
return;
|
||||
}
|
||||
objectMap.remove(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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());
|
||||
}
|
||||
|
||||
public static String getProcessName(Context cxt, int pid) {
|
||||
ActivityManager am = (ActivityManager) cxt
|
||||
.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
List<RunningAppProcessInfo> 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;
|
||||
}
|
||||
|
||||
private boolean shouldInit() {
|
||||
ActivityManager am = ((ActivityManager) getSystemService(Context.ACTIVITY_SERVICE));
|
||||
List<RunningAppProcessInfo> 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;
|
||||
}
|
||||
private boolean shouldInit() {
|
||||
ActivityManager am = ((ActivityManager) getSystemService(Context.ACTIVITY_SERVICE));
|
||||
List<RunningAppProcessInfo> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
51
app/src/main/java/com/gh/base/AppControllerLike.java
Normal file
51
app/src/main/java/com/gh/base/AppControllerLike.java
Normal file
@ -0,0 +1,51 @@
|
||||
//package com.gh.base;
|
||||
//
|
||||
//
|
||||
//import android.annotation.TargetApi;
|
||||
//import android.app.Application;
|
||||
//import android.content.Context;
|
||||
//import android.content.Intent;
|
||||
//import android.os.Build;
|
||||
//import android.support.multidex.MultiDex;
|
||||
//
|
||||
//import com.tencent.tinker.lib.listener.DefaultPatchListener;
|
||||
//import com.tencent.tinker.lib.listener.PatchListener;
|
||||
//import com.tencent.tinker.lib.patch.AbstractPatch;
|
||||
//import com.tencent.tinker.lib.patch.UpgradePatch;
|
||||
//import com.tencent.tinker.lib.reporter.DefaultLoadReporter;
|
||||
//import com.tencent.tinker.lib.reporter.DefaultPatchReporter;
|
||||
//import com.tencent.tinker.lib.reporter.LoadReporter;
|
||||
//import com.tencent.tinker.lib.reporter.PatchReporter;
|
||||
//import com.tencent.tinker.lib.tinker.TinkerInstaller;
|
||||
//import com.tencent.tinker.loader.app.DefaultApplicationLike;
|
||||
//
|
||||
//public class AppControllerLike extends DefaultApplicationLike {
|
||||
//
|
||||
// public AppControllerLike(Application application, int tinkerFlags, boolean tinkerLoadVerifyFlag,
|
||||
// long applicationStartElapsedTime, long applicationStartMillisTime,
|
||||
// Intent tinkerResultIntent) {
|
||||
// super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime,
|
||||
// applicationStartMillisTime, tinkerResultIntent);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onBaseContextAttached(Context base) {
|
||||
// super.onBaseContextAttached(base);
|
||||
// MultiDex.install(base);
|
||||
//
|
||||
// LoadReporter loadReporter = new DefaultLoadReporter(getApplication());
|
||||
// PatchReporter patchReporter = new DefaultPatchReporter(getApplication());
|
||||
// PatchListener patchListener = new DefaultPatchListener(getApplication());
|
||||
// AbstractPatch upgradePatchProcessor = new UpgradePatch();
|
||||
//
|
||||
// TinkerInstaller.install(this, loadReporter, patchReporter, patchListener,
|
||||
// AppTinkerResultService.class, upgradePatchProcessor);
|
||||
//// TinkerInstaller.install(this);
|
||||
// }
|
||||
//
|
||||
// @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
|
||||
// public void registerActivityLifecycleCallbacks(Application.ActivityLifecycleCallbacks callback) {
|
||||
// getApplication().registerActivityLifecycleCallbacks(callback);
|
||||
// }
|
||||
//
|
||||
//}
|
||||
29
app/src/main/java/com/gh/base/AppTinkerResultService.java
Normal file
29
app/src/main/java/com/gh/base/AppTinkerResultService.java
Normal file
@ -0,0 +1,29 @@
|
||||
//package com.gh.base;
|
||||
//
|
||||
//import com.gh.common.util.Utils;
|
||||
//import com.tencent.tinker.lib.service.DefaultTinkerResultService;
|
||||
//import com.tencent.tinker.lib.service.PatchResult;
|
||||
//import com.tencent.tinker.lib.util.TinkerServiceInternals;
|
||||
//
|
||||
//import java.io.File;
|
||||
//
|
||||
//
|
||||
//public class AppTinkerResultService extends DefaultTinkerResultService {
|
||||
//
|
||||
// @Override
|
||||
// public void onPatchResult(PatchResult result) {
|
||||
// if (result == null) {
|
||||
// return;
|
||||
// }
|
||||
// Utils.log(result);
|
||||
//
|
||||
// //first, we want to kill the recover process
|
||||
// TinkerServiceInternals.killTinkerPatchServiceProcess(getApplicationContext());
|
||||
//
|
||||
// if (result.isSuccess) {
|
||||
// Utils.log("Tinkder Success");
|
||||
// deleteRawPatchFile(new File(result.rawPatchFilePath));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//}
|
||||
@ -1,128 +0,0 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.util.DataCollectionUtils;
|
||||
import com.gh.common.util.FileUtils;
|
||||
import com.gh.gamecenter.SplashScreenActivity;
|
||||
import com.tencent.stat.StatService;
|
||||
|
||||
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.Locale;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
// 防止重复奔溃,导致助手一直重启,20秒内不做处理
|
||||
SharedPreferences sp = appController.getApplicationContext().getSharedPreferences(
|
||||
Config.PREFERENCE, Context.MODE_PRIVATE);
|
||||
long time = sp.getLong("last_restart_time", 0);
|
||||
if (System.currentTimeMillis() - time > 20 * 1000) {
|
||||
sp.edit().putLong("last_restart_time", System.currentTimeMillis()).apply();
|
||||
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,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
// 退出程序并重启
|
||||
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);
|
||||
|
||||
// MTA主动上传错误
|
||||
StatService.reportError(appController.getApplicationContext(), errorMsg);
|
||||
|
||||
// 上传错误数据
|
||||
DataCollectionUtils.uploadError(appController.getApplicationContext(), errorMsg);
|
||||
|
||||
// 保存到本地
|
||||
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;
|
||||
}
|
||||
}
|
||||
127
app/src/main/java/com/gh/base/AppUncaughtHandler.java
Normal file
127
app/src/main/java/com/gh/base/AppUncaughtHandler.java
Normal file
@ -0,0 +1,127 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.util.AppManager;
|
||||
import com.gh.common.util.DataCollectionUtils;
|
||||
import com.gh.common.util.FileUtils;
|
||||
import com.gh.gamecenter.SplashScreenActivity;
|
||||
import com.tencent.stat.StatService;
|
||||
|
||||
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.Locale;
|
||||
|
||||
public class AppUncaughtHandler implements UncaughtExceptionHandler {
|
||||
|
||||
private UncaughtExceptionHandler mDefaultHandler;
|
||||
private AppController mAppController;
|
||||
|
||||
public AppUncaughtHandler(AppController appController) {
|
||||
// 获取系统默认的UncaughtException处理器
|
||||
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
|
||||
mAppController = appController;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uncaughtException(Thread thread, Throwable ex) {
|
||||
if (!handleException(ex) && mDefaultHandler != null) {
|
||||
// 如果用户没有处理则让系统默认的异常处理器来处理
|
||||
mDefaultHandler.uncaughtException(thread, ex);
|
||||
} else {
|
||||
AppController.MAIN_EXECUTOR.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Looper.prepare();
|
||||
Toast.makeText(mAppController.getApplicationContext(),
|
||||
"\"光环助手\"发生错误", Toast.LENGTH_SHORT).show();
|
||||
Looper.loop();
|
||||
}
|
||||
});
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// 防止重复奔溃,导致助手一直重启,20秒内不做处理
|
||||
SharedPreferences sp = mAppController.getApplicationContext().getSharedPreferences(
|
||||
Config.PREFERENCE, Context.MODE_PRIVATE);
|
||||
long time = sp.getLong("last_restart_time", 0);
|
||||
if (System.currentTimeMillis() - time > 20 * 1000) {
|
||||
sp.edit().putLong("last_restart_time", System.currentTimeMillis()).apply();
|
||||
Intent intent = new Intent(mAppController.getApplicationContext(), SplashScreenActivity.class);
|
||||
intent.setAction(Intent.ACTION_MAIN);
|
||||
intent.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||
PendingIntent restartIntent = PendingIntent.getActivity(
|
||||
mAppController.getApplicationContext(), 0, intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
// 退出程序并重启
|
||||
AlarmManager mgr = (AlarmManager) mAppController.getSystemService(Context.ALARM_SERVICE);
|
||||
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent); // 1秒钟后重启应用
|
||||
}
|
||||
AppManager.getInstance().finishAllActivity();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
|
||||
*
|
||||
* @param ex
|
||||
* @return true:如果处理了该异常信息;否则返回false.
|
||||
*/
|
||||
private boolean handleException(Throwable ex) {
|
||||
if (ex == null) {
|
||||
return false;
|
||||
}
|
||||
saveLog(ex);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 保存log到本地
|
||||
private void saveLog(Throwable ex) {
|
||||
String errorMsg = Log.getStackTraceString(ex);
|
||||
|
||||
// MTA主动上传错误
|
||||
// StatService.reportError(mAppController.getApplicationContext(), errorMsg);
|
||||
StatService.reportException(mAppController, ex);
|
||||
|
||||
// 上传错误数据
|
||||
DataCollectionUtils.uploadError(mAppController, errorMsg);
|
||||
|
||||
// 保存到本地
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.getDefault());
|
||||
File file = new File(FileUtils.getLogPath(mAppController.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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,21 +1,17 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
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 com.gh.common.constant.Config;
|
||||
import com.gh.common.util.AppManager;
|
||||
import com.gh.common.util.DataUtils;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
@ -23,191 +19,168 @@ import com.gh.common.util.FileUtils;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.RunningUtils;
|
||||
import com.gh.common.util.ShareUtils;
|
||||
import com.gh.common.util.Utils;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.eventbus.EBShowDialog;
|
||||
import com.gh.gamecenter.listener.OnCallBackListener;
|
||||
import com.gh.gamecenter.manager.SystemBarTintManager;
|
||||
import com.gh.gamecenter.manager.SystemBarTintManager.SystemBarConfig;
|
||||
import com.readystatesoftware.systembartint.SystemBarTintManager.SystemBarConfig;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
import de.greenrobot.event.EventBus;
|
||||
|
||||
public class BaseActivity extends Activity implements OnCallBackListener {
|
||||
import static com.gh.common.util.EntranceUtils.KEY_DATA;
|
||||
import static com.gh.common.util.EntranceUtils.KEY_ENTRANCE;
|
||||
|
||||
private SystemBarTintManager tintManager;
|
||||
public abstract class BaseActivity extends BaseAppCompatToolBarActivity implements OnCallBackListener {
|
||||
|
||||
protected String entrance;
|
||||
protected String mEntrance;
|
||||
private boolean mIsPause;
|
||||
|
||||
private boolean isPause;
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
init(mContentView);
|
||||
AppManager.getInstance().addActivity(this);
|
||||
EventBus.getDefault().register(this);
|
||||
mEntrance = getIntent().getStringExtra(KEY_ENTRANCE);
|
||||
if (getIntent().getBundleExtra(KEY_DATA) != null) {
|
||||
mEntrance = getIntent().getBundleExtra(KEY_DATA).getString(KEY_ENTRANCE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
Utils.log(this.getClass().getSimpleName());
|
||||
AppController.getInstance().addActivity(this);
|
||||
EventBus.getDefault().register(this);
|
||||
entrance = getIntent().getStringExtra("entrance");
|
||||
if (getIntent().getBundleExtra("data") != null) {
|
||||
entrance = getIntent().getBundleExtra("data").getString("entrance");
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected boolean onNavigationIconClicked() {
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
private void init(View contentView) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
SystemBarConfig config = getTintManager().getConfig();
|
||||
contentView.setPadding(0, config.getPixelInsetTop(false), 0, config.getPixelInsetBottom());
|
||||
}
|
||||
setContentView(contentView);
|
||||
|
||||
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);
|
||||
SystemBarConfig config = tintManager.getConfig();
|
||||
contentView.setPadding(0, config.getPixelInsetTop(false), 0,
|
||||
config.getPixelInsetBottom());
|
||||
}
|
||||
ButterKnife.bind(this);
|
||||
|
||||
setContentView(contentView);
|
||||
View reuse_actionbar = findViewById(R.id.reuse_actionbar);
|
||||
if (reuse_actionbar != null) {
|
||||
int actionbar_height = getSharedPreferences(Config.PREFERENCE, Context.MODE_PRIVATE)
|
||||
.getInt("actionbar_height", DisplayUtils.dip2px(getApplicationContext(), 55));
|
||||
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, actionbar_height);
|
||||
reuse_actionbar.setLayoutParams(lparams);
|
||||
|
||||
ButterKnife.bind(this);
|
||||
findViewById(R.id.actionbar_rl_back).setOnClickListener(
|
||||
new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
int actionbar_height = getSharedPreferences(Config.PREFERENCE,
|
||||
Context.MODE_PRIVATE).getInt("actionbar_height",
|
||||
DisplayUtils.dip2px(getApplicationContext(), 48));
|
||||
protected void init(String title) {
|
||||
TextView actionbar_tv_title = (TextView) findViewById(R.id.actionbar_tv_title);
|
||||
actionbar_tv_title.setText(title);
|
||||
// setNavigationTitle(title);
|
||||
}
|
||||
|
||||
RelativeLayout reuse_actionbar = (RelativeLayout) findViewById(R.id.reuse_actionbar);
|
||||
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(
|
||||
LayoutParams.MATCH_PARENT, actionbar_height);
|
||||
reuse_actionbar.setLayoutParams(lparams);
|
||||
public void toast(String msg) {
|
||||
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
findViewById(R.id.actionbar_rl_back).setOnClickListener(
|
||||
new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
public void toast(int msg) {
|
||||
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
protected SystemBarTintManager getTintManager() {
|
||||
return tintManager;
|
||||
}
|
||||
//如果是游戏分享,newsTitle默认为空
|
||||
public void showShare(String url, String gameName, String icon, String newsTitle, ArrayList<String> tag, boolean isToolsBox) {
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
super.finish();
|
||||
AppController.getInstance().removeActivity(this);
|
||||
}
|
||||
//判断是否是官方版
|
||||
boolean isPlugin = false;
|
||||
if (tag != null) {
|
||||
for (String s : tag) {
|
||||
if (!"官方版".equals(s)) {
|
||||
isPlugin = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void toast(String msg) {
|
||||
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
ShareUtils.getInstance(this).showShareWindows(getWindow().getDecorView(), url, gameName, icon, newsTitle, isPlugin, true, isToolsBox);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
//如果是游戏分享,newsTitle默认为空
|
||||
public void showShare(String url, String gameName, String icon, String newsTitle, ArrayList<String> tag) {
|
||||
|
||||
//判断是否是官方版
|
||||
boolean isPlugin = false;
|
||||
if (tag != null){
|
||||
for (String s : tag) {
|
||||
if (!"官方版".equals(s)){
|
||||
isPlugin = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ShareUtils.getInstance(this).showShareWindows(new View(this), url, gameName, icon, newsTitle, isPlugin);
|
||||
|
||||
if (newsTitle == null) {
|
||||
DataUtils.onEvent(this, "内容分享", gameName);
|
||||
} else {
|
||||
DataUtils.onEvent(this, "内容分享", newsTitle);
|
||||
}
|
||||
}
|
||||
if (newsTitle == null) {
|
||||
DataUtils.onEvent(this, "内容分享", gameName);
|
||||
} else {
|
||||
DataUtils.onEvent(this, "内容分享", newsTitle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void onEventMainThread(final EBShowDialog showDialog) {
|
||||
if (!isPause && this.getClass().getName().equals(RunningUtils.getTopActivity(this))) {
|
||||
if ("hijack".equals(showDialog.getType())) {
|
||||
DialogUtils.showQqSessionDialog(this, null);// 建议用户联系客服
|
||||
} else if ("plugin".equals(showDialog.getType())) {
|
||||
DialogUtils.showPluginDialog(this, new DialogUtils.ConfiremListener(){
|
||||
@Override
|
||||
public void onConfirem() {
|
||||
if (FileUtils.isEmptyFile(showDialog.getPath())) {
|
||||
Toast.makeText(BaseActivity.this, "解析包出错(可能被误删了),请重新下载", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
startActivity(PackageUtils.getUninstallIntent(BaseActivity.this, showDialog.getPath()));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
DataUtils.onPause(this);
|
||||
isPause = true;
|
||||
}
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEventMainThread(final EBShowDialog showDialog) {
|
||||
if (!mIsPause && this.getClass().getName().equals(RunningUtils.getTopActivity(this))) {
|
||||
if ("hijack".equals(showDialog.getType())) {
|
||||
DialogUtils.showQqSessionDialog(this, "2586716223");// 建议用户联系客服
|
||||
} else if ("plugin".equals(showDialog.getType())) {
|
||||
DialogUtils.showPluginDialog(this, new DialogUtils.ConfirmListener() {
|
||||
@Override
|
||||
public void onConfirm() {
|
||||
if (FileUtils.isEmptyFile(showDialog.getPath())) {
|
||||
Toast.makeText(BaseActivity.this, "解析包出错(可能被误删了),请重新下载", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
startActivity(PackageUtils.getUninstallIntent(BaseActivity.this, showDialog.getPath()));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
DataUtils.onResume(this);
|
||||
isPause = false;
|
||||
DownloadManager.getInstance(this).initGameMap();
|
||||
}
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
EventBus.getDefault().unregister(this);
|
||||
AppManager.getInstance().finishActivity(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDone() {
|
||||
|
||||
}
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
DataUtils.onPause(this);
|
||||
mIsPause = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDone(Object obj) {
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
DataUtils.onResume(this);
|
||||
mIsPause = false;
|
||||
DownloadManager.getInstance(this).initGameMap();
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public void loadDone() {
|
||||
|
||||
@Override
|
||||
public void loadError() {
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public void loadDone(Object obj) {
|
||||
|
||||
@Override
|
||||
public void loadEmpty() {
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public void loadError() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadEmpty() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
325
app/src/main/java/com/gh/base/BaseAppCompatActivity.java
Normal file
325
app/src/main/java/com/gh/base/BaseAppCompatActivity.java
Normal file
@ -0,0 +1,325 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.view.View;
|
||||
|
||||
import com.gh.common.util.AppDebugConfig;
|
||||
import com.gh.common.util.AppManager;
|
||||
import com.gh.common.util.Util_System_Keyboard;
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
|
||||
/**
|
||||
* @author CsHeng
|
||||
*/
|
||||
public abstract class BaseAppCompatActivity extends BaseAppCompatActivityLog implements FragmentNavigationDelegate,
|
||||
OnBackPressedListener {
|
||||
|
||||
protected static final String ARGS_FRAGMENT_NAME = "frgName";
|
||||
protected static final String ARGS_FRAGMENT_BUNDLE = "frgBundle";
|
||||
protected View mContentView;
|
||||
|
||||
protected static Intent clearTop(Context context, Class<? extends Activity> cls) {
|
||||
final Intent intent = getReorderToFrontIntent(context, cls);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
return intent;
|
||||
}
|
||||
|
||||
protected static Intent getReorderToFrontIntent(Context context, Class<? extends Activity> cls) {
|
||||
final Intent intent = new Intent(context, cls);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
return intent;
|
||||
}
|
||||
|
||||
protected static void showActivity(Context context, Class<? extends Activity> cls) {
|
||||
final Intent intent = getReorderToFrontIntent(context, cls);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
protected static void startFragmentForResult(Context context, Class<? extends Activity> activity,
|
||||
Class<? extends Fragment> fragment, Bundle bundle, int requestCode) {
|
||||
if (context instanceof Activity) {
|
||||
((Activity) context).startActivityForResult(getFragmentIntent(context, activity, fragment, bundle),
|
||||
requestCode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据传进来的fragment class和bundle extra来决定跳转到哪一个fragment
|
||||
*
|
||||
* @param context
|
||||
* @param fragment fragment.getCanonicalName()
|
||||
* @param bundle fragment的构造参数
|
||||
* @return
|
||||
*/
|
||||
protected static Intent getFragmentIntent(Context context, Class<? extends Activity> activity,
|
||||
Class<? extends Fragment> fragment, Bundle bundle) {
|
||||
final Intent intent = getReorderToFrontIntent(context, activity);
|
||||
intent.putExtra(ARGS_FRAGMENT_NAME, fragment.getCanonicalName());
|
||||
intent.putExtra(ARGS_FRAGMENT_BUNDLE, bundle);
|
||||
return intent;
|
||||
}
|
||||
|
||||
protected static void startFragment(Context context, Class<? extends Activity> activity,
|
||||
Class<? extends Fragment> fragment) {
|
||||
startFragment(context, activity, fragment, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动Fragment
|
||||
*
|
||||
* @param context
|
||||
* @param fragment
|
||||
* @param bundle
|
||||
*/
|
||||
protected static void startFragment(Context context, Class<? extends Activity> activity,
|
||||
Class<? extends Fragment> fragment, Bundle bundle) {
|
||||
context.startActivity(getFragmentIntent(context, activity, fragment, bundle));
|
||||
}
|
||||
|
||||
private void handleRedirectFromUri(Uri uri) {
|
||||
try {
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(this, uri, uri.getHost(), uri.getPath(), uri.getEncodedQuery());
|
||||
}
|
||||
// switch (uri.getPath()) {
|
||||
// case SchemeConstants.PATH_OPEN_GAME: {
|
||||
// /**
|
||||
// * 对于联运游戏:传入的game_id为0,game_url为对应的游戏链接,aid传联运游戏的aid
|
||||
// * 对于非联运游戏:传入非联运游戏的game_id,game_url不传,aid传0
|
||||
// */
|
||||
// GameModel game = new GameModel();
|
||||
// int gameId = Integer.parseInt(uri.getQueryParameter(SchemeConstants.PARAMS_GAMEID));
|
||||
// game.setId(gameId);
|
||||
//// if (AppDebugConfig.IS_DEBUG) {
|
||||
//// int debugId = 1049;
|
||||
//// game.setId(debugId);
|
||||
//// }
|
||||
// if (gameId == 0) {
|
||||
// // cooperate
|
||||
// int aid = Integer.parseInt(uri.getQueryParameter(SchemeConstants.PARAMS_AID));
|
||||
// game.setAid(aid);
|
||||
// String gameUrl = uri.getQueryParameter(SchemeConstants.PARAMS_GAMEURL);
|
||||
// game.setUrl(gameUrl);
|
||||
// }
|
||||
// ApiRequester.requestGameDetail(this, game);
|
||||
//
|
||||
// break;
|
||||
// }
|
||||
// case SchemeConstants.PATH_OPEN_ARTICLE: {
|
||||
//
|
||||
// String url = uri.getQueryParameter(SchemeConstants.PARAMS_ARTICLE_URL);
|
||||
// String title = uri.getQueryParameter(SchemeConstants.PARAMS_ARTICLE_TITLE);
|
||||
//
|
||||
// if (!TextUtils.isEmpty(url) && !TextUtils.isEmpty(title)) {
|
||||
// Bundle args = new Bundle();
|
||||
// args.putString(Fragment_Browser_Web.ARGS_URL, url);
|
||||
// args.putString(Fragment_Browser_Web.ARGS_TITLE, getString(R.string.title_article_detail));
|
||||
// CommonActivity.startFragment(this, Fragment_Browser_Web.class, args);
|
||||
// }
|
||||
//
|
||||
// break;
|
||||
// }
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
} catch (Exception e) {
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
// Debug_SDK.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onHandleBackPressed() {
|
||||
onBackPressed();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean handleBackPressed() {
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(this);
|
||||
}
|
||||
final Fragment curFragment = getTopFragment();
|
||||
if (curFragment instanceof OnBackPressedListener &&
|
||||
((OnBackPressedListener) curFragment).onHandleBackPressed()) {
|
||||
return true;
|
||||
}
|
||||
if (popFragment()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Fragment getTopFragment() {
|
||||
return getSupportFragmentManager().findFragmentById(R.id.layout_activity_content);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
final int layoutId = getLayoutId();
|
||||
if (layoutId != 0) {
|
||||
mContentView = getLayoutInflater().inflate(layoutId, null);
|
||||
setContentView(mContentView);
|
||||
}
|
||||
if (savedInstanceState == null) {
|
||||
handleRedirectIntent(getIntent());
|
||||
}
|
||||
AppManager.getInstance().addActivity(this);
|
||||
}
|
||||
|
||||
protected abstract int getLayoutId();
|
||||
|
||||
/**
|
||||
* 1、判断当前是否存在某Fragment,例如下载管理器已经在栈中,则不重新启动,而将其带到最上层 (FindFragmentWithTag)
|
||||
* 2、支持URI调用?
|
||||
* 是否需要重新导向到其他Activity
|
||||
*/
|
||||
protected void handleRedirectIntent(Intent intent) {
|
||||
try {
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(this, intent.toUri(Intent.URI_INTENT_SCHEME));
|
||||
}
|
||||
|
||||
// 1、根据从网页抓取到的Intent跳转进来,处理custom uri
|
||||
// final Uri uri = intent.getData();
|
||||
// if (uri != null && SchemeConstants.SCHEME_FFSS.equals(uri.getScheme())) {
|
||||
// handleRedirectFromUri(uri);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // 2、根据序列化的数据来重新构建Fragment实例,若没有,则是旧的形式来决定传参
|
||||
// final String fragmentName = intent.getStringExtra(ARGS_FRAGMENT_NAME);
|
||||
// if (AppDebugConfig.IS_DEBUG) {
|
||||
// AppDebugConfig.logMethodWithParams(this, fragmentName);
|
||||
// }
|
||||
// if (!TextUtils.isEmpty(fragmentName)) {
|
||||
// final Bundle args = intent.getBundleExtra(ARGS_FRAGMENT_BUNDLE);
|
||||
// final Fragment fragment = Fragment.instantiate(this, fragmentName, args);
|
||||
// if (fragment instanceof DialogFragment) {
|
||||
// ((DialogFragment) fragment).show(getSupportFragmentManager(), fragmentName);
|
||||
// } else {
|
||||
// getSupportFragmentManager().beginTransaction().replace(R.id.layout_activity_content, fragment)
|
||||
// .commitAllowingStateLoss();
|
||||
// }
|
||||
// }
|
||||
} catch (Throwable e) {
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(this, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
AppManager.getInstance().finishActivity(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFragment(Fragment fragment) {
|
||||
getSupportFragmentManager().beginTransaction().add(R.id.layout_activity_content, fragment)
|
||||
.addToBackStack(fragment.toString()).commitAllowingStateLoss();
|
||||
Util_System_Keyboard.hideSoftKeyboard(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceFragment(Fragment toReplace) {
|
||||
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
|
||||
ft.replace(R.id.layout_activity_content, toReplace).addToBackStack(toReplace.toString());
|
||||
ft.commitAllowingStateLoss();
|
||||
Util_System_Keyboard.hideSoftKeyboard(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFragment(Fragment toRemove) {
|
||||
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
|
||||
ft.replace(R.id.layout_activity_content, toRemove).addToBackStack(toRemove.toString());
|
||||
ft.commitAllowingStateLoss();
|
||||
Util_System_Keyboard.hideSoftKeyboard(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showFragment(Fragment toShow) {
|
||||
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
|
||||
ft.show(toShow).addToBackStack(toShow.toString());
|
||||
ft.commitAllowingStateLoss();
|
||||
Util_System_Keyboard.hideSoftKeyboard(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideFragment(Fragment toHide) {
|
||||
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
|
||||
ft.show(toHide).addToBackStack(toHide.toString());
|
||||
ft.commitAllowingStateLoss();
|
||||
Util_System_Keyboard.hideSoftKeyboard(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean popFragment() {
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(this, getSupportFragmentManager().getBackStackEntryCount());
|
||||
}
|
||||
final int backStackCount = getSupportFragmentManager().getBackStackEntryCount();
|
||||
if (backStackCount > 0) {
|
||||
Util_System_Keyboard.hideSoftKeyboard(this);
|
||||
getSupportFragmentManager().popBackStack();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void popFragmentToBase() {
|
||||
getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
* forward ActivityResultListener to fragments this activity hosts
|
||||
*
|
||||
* @param requestCode
|
||||
* @param resultCode
|
||||
* @param data
|
||||
*/
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(this, requestCode, resultCode, data);
|
||||
}
|
||||
final Fragment fragment = getTopFragment();
|
||||
if (fragment != null) {
|
||||
fragment.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(this);
|
||||
}
|
||||
if (handleBackPressed()) {
|
||||
return;
|
||||
}
|
||||
// default finish activity
|
||||
Util_System_Keyboard.hideSoftKeyboard(this);
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
setIntent(intent);
|
||||
handleRedirectIntent(intent);
|
||||
}
|
||||
|
||||
}
|
||||
94
app/src/main/java/com/gh/base/BaseAppCompatActivityLog.java
Normal file
94
app/src/main/java/com/gh/base/BaseAppCompatActivityLog.java
Normal file
@ -0,0 +1,94 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
||||
import com.gh.common.util.AppDebugConfig;
|
||||
|
||||
|
||||
/**
|
||||
* @author: CsHeng (csheng1204[at]gmail[dot]com)
|
||||
* Date: 13-7-25
|
||||
* Time: 下午8:42
|
||||
*/
|
||||
public class BaseAppCompatActivityLog extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodName(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodName(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodName(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodName(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodName(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
try {
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodName(this);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
try {
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodName(this);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodName(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
if (AppDebugConfig.IS_DEBUG) {
|
||||
AppDebugConfig.logMethodName(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
138
app/src/main/java/com/gh/base/BaseAppCompatToolBarActivity.java
Normal file
138
app/src/main/java/com/gh/base/BaseAppCompatToolBarActivity.java
Normal file
@ -0,0 +1,138 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.MenuItem;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.gh.gamecenter.R;
|
||||
import com.readystatesoftware.systembartint.SystemBarTintManager;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Created by csheng on 15-10-12.
|
||||
*/
|
||||
public abstract class BaseAppCompatToolBarActivity extends BaseAppCompatActivity implements ToolbarController {
|
||||
|
||||
private Toolbar mToolbar;
|
||||
private SystemBarTintManager mTintManager;
|
||||
|
||||
// TODO 获取沉浸栏管理,要进行版本判断或者判断是否为空
|
||||
protected SystemBarTintManager getTintManager() {
|
||||
return mTintManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
initToolbar();
|
||||
// Util_Window.initStatusBarColor(getWindow(), ContextCompat.getColor(this, R.color.theme));
|
||||
initStatusBar();
|
||||
}
|
||||
|
||||
private void initToolbar() {
|
||||
mToolbar = (Toolbar) findViewById(R.id.toolbar_navigation);
|
||||
if (mToolbar != null) {
|
||||
mToolbar.setTitle("");
|
||||
setSupportActionBar(mToolbar);
|
||||
}
|
||||
}
|
||||
|
||||
private void initStatusBar() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
setTranslucentStatus(true);
|
||||
mTintManager = new SystemBarTintManager(this);
|
||||
mTintManager.setStatusBarTintEnabled(true);
|
||||
// mTintManager.setNavigationBarTintEnabled(true);
|
||||
if (Build.MANUFACTURER.equals("Meizu") || Build.MANUFACTURER.equals("Xiaomi")) {
|
||||
mTintManager.setStatusBarTintColor(Color.WHITE);
|
||||
} else {
|
||||
mTintManager.setStatusBarTintColor(Color.BLACK);
|
||||
}
|
||||
|
||||
switch (Build.MANUFACTURER) {
|
||||
case "Meizu":
|
||||
try {
|
||||
Window window = getWindow();
|
||||
if (window != null) {
|
||||
WindowManager.LayoutParams lp = window.getAttributes();
|
||||
Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
|
||||
Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags");
|
||||
darkFlag.setAccessible(true);
|
||||
meizuFlags.setAccessible(true);
|
||||
int bit = darkFlag.getInt(null);
|
||||
int value = meizuFlags.getInt(lp);
|
||||
value |= bit;
|
||||
meizuFlags.setInt(lp, value);
|
||||
window.setAttributes(lp);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
break;
|
||||
case "Xiaomi":
|
||||
try {
|
||||
Window window = getWindow();
|
||||
if (window != null) {
|
||||
Class<?> clazz = window.getClass();
|
||||
Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
|
||||
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
|
||||
int darkModeFlag = field.getInt(layoutParams);
|
||||
Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
|
||||
extraFlagField.invoke(window, darkModeFlag, darkModeFlag);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
return onNavigationIconClicked();
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
protected abstract boolean onNavigationIconClicked();
|
||||
|
||||
@Override
|
||||
public void setNavigationTitle(int res) {
|
||||
mToolbar.setTitle(res);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNavigationTitle(CharSequence res) {
|
||||
mToolbar.setTitle(res);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Toolbar getToolBar() {
|
||||
return mToolbar;
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,7 +2,6 @@ package com.gh.base;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
@ -13,6 +12,7 @@ import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.util.ApkActiveUtils;
|
||||
import com.gh.common.util.DataUtils;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
@ -34,6 +34,9 @@ import com.gh.gamecenter.eventbus.EBPackage;
|
||||
import com.gh.gamecenter.manager.PackageManager;
|
||||
import com.tencent.tauth.Tencent;
|
||||
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2016/9/19.
|
||||
* 游戏详情、新闻详情基类(控制底部下载栏)
|
||||
@ -55,14 +58,11 @@ public abstract class BaseDetailActivity extends BaseActivity implements View.On
|
||||
protected GameEntity gameEntity;
|
||||
protected DownloadEntity mDownloadEntity;
|
||||
|
||||
protected String entrance;
|
||||
protected String name;
|
||||
protected String title;
|
||||
protected String downloadAddWord;
|
||||
protected String downloadOffText;
|
||||
|
||||
protected Handler handler = new Handler();
|
||||
|
||||
private DataWatcher dataWatcher = new DataWatcher() {
|
||||
@Override
|
||||
public void onDataChanged(DownloadEntity downloadEntity) {
|
||||
@ -79,33 +79,45 @@ public abstract class BaseDetailActivity extends BaseActivity implements View.On
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_detail;
|
||||
}
|
||||
|
||||
//接收QQ或者QQ空间分享回调
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (requestCode == com.tencent.connect.common.Constants.REQUEST_QQ_SHARE
|
||||
|| requestCode == com.tencent.connect.common.Constants.REQUEST_QZONE_SHARE) {
|
||||
Tencent.onActivityResultData(requestCode, resultCode, data, ShareUtils.getInstance(this).QqShareListener);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
entrance = getIntent().getStringExtra("entrance");
|
||||
if (getIntent().getBundleExtra("data") != null) {
|
||||
entrance = getIntent().getBundleExtra("data").getString("entrance");
|
||||
}
|
||||
|
||||
View contentView = View.inflate(this, R.layout.activity_detail, null);
|
||||
// View contentView = View.inflate(this, R.layout.activity_detail, null);
|
||||
|
||||
// 添加分享图标
|
||||
iv_share = new ImageView(this);
|
||||
iv_share.setImageResource(R.drawable.ic_share);
|
||||
iv_share.setOnClickListener(this);
|
||||
iv_share.setVisibility(View.GONE);
|
||||
iv_share.setPadding(DisplayUtils.dip2px(this, 13),DisplayUtils.dip2px(this, 11)
|
||||
,DisplayUtils.dip2px(this, 11),DisplayUtils.dip2px(this, 13));
|
||||
iv_share.setPadding(DisplayUtils.dip2px(this, 13), DisplayUtils.dip2px(this, 11)
|
||||
, DisplayUtils.dip2px(this, 11), DisplayUtils.dip2px(this, 13));
|
||||
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
|
||||
DisplayUtils.dip2px(this, 48), DisplayUtils.dip2px(this, 48));
|
||||
params.addRule( RelativeLayout.CENTER_VERTICAL);
|
||||
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT );
|
||||
RelativeLayout reuse_actionbar = (RelativeLayout) contentView.findViewById(
|
||||
params.addRule(RelativeLayout.CENTER_VERTICAL);
|
||||
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
|
||||
RelativeLayout reuse_actionbar = (RelativeLayout) mContentView.findViewById(
|
||||
R.id.reuse_actionbar);
|
||||
reuse_actionbar.addView(iv_share, params);
|
||||
|
||||
init(contentView);
|
||||
// init(contentView);
|
||||
|
||||
actionbar_tv_title = (TextView) findViewById(R.id.actionbar_tv_title);
|
||||
detail_rv_show = (RecyclerView) findViewById(R.id.detail_rv_show);
|
||||
@ -126,16 +138,10 @@ public abstract class BaseDetailActivity extends BaseActivity implements View.On
|
||||
|
||||
}
|
||||
|
||||
//接收QQ或者QQ空间分享回调
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (requestCode == com.tencent.connect.common.Constants.REQUEST_QQ_SHARE
|
||||
|| requestCode == com.tencent.connect.common.Constants.REQUEST_QZONE_SHARE) {
|
||||
Tencent.onActivityResultData(requestCode, resultCode, data, ShareUtils.getInstance(this).QqShareListener);
|
||||
}
|
||||
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
DownloadManager.getInstance(this).removeObserver(dataWatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -149,12 +155,6 @@ public abstract class BaseDetailActivity extends BaseActivity implements View.On
|
||||
DownloadManager.getInstance(this).addObserver(dataWatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
DownloadManager.getInstance(this).removeObserver(dataWatcher);
|
||||
}
|
||||
|
||||
protected void initDownload(boolean isCheck) {
|
||||
if (Config.isShow(this)) {
|
||||
detail_ll_bottom.setVisibility(View.VISIBLE);
|
||||
@ -295,6 +295,7 @@ public abstract class BaseDetailActivity extends BaseActivity implements View.On
|
||||
}
|
||||
|
||||
// 接收下载被删除消息
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEvent(EBDownloadStatus status) {
|
||||
if ("delete".equals(status.getStatus())
|
||||
&& gameEntity != null
|
||||
@ -308,13 +309,17 @@ public abstract class BaseDetailActivity extends BaseActivity implements View.On
|
||||
}
|
||||
|
||||
// 接受安装、卸载消息
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEventMainThread(EBPackage busFour) {
|
||||
if (gameEntity != null
|
||||
&& gameEntity.getApk() != null
|
||||
&& gameEntity.getApk().size() == 1) {
|
||||
String packageName = gameEntity.getApk().get(0).getPackageName();
|
||||
if (packageName.equals(busFour.getPackageName())) {
|
||||
initDownload(false);
|
||||
&& gameEntity.getApk().size() > 0) {
|
||||
for (ApkEntity apkEntity : gameEntity.getApk()) {
|
||||
String packageName = apkEntity.getPackageName();
|
||||
if (packageName.equals(busFour.getPackageName())) {
|
||||
ApkActiveUtils.filterHideApk(gameEntity);
|
||||
initDownload(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -327,15 +332,15 @@ public abstract class BaseDetailActivity extends BaseActivity implements View.On
|
||||
if (NetworkUtils.isWifiConnected(this)) {
|
||||
download();
|
||||
} else {
|
||||
DialogUtils.showDownloadDialog(this, new DialogUtils.ConfiremListener() {
|
||||
DialogUtils.showDownloadDialog(this, new DialogUtils.ConfirmListener() {
|
||||
@Override
|
||||
public void onConfirem() {
|
||||
public void onConfirm() {
|
||||
download();
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
DownloadDialog.getInstance(this).showPopupWindow(v, gameEntity, entrance, name + ":" + title);
|
||||
DownloadDialog.getInstance(this).showPopupWindow(v, gameEntity, mEntrance, name + ":" + title);
|
||||
}
|
||||
} else {
|
||||
toast("稍等片刻~!游戏正在上传中...");
|
||||
@ -343,10 +348,8 @@ public abstract class BaseDetailActivity extends BaseActivity implements View.On
|
||||
} else if (v == detail_pb_progressbar || v == detail_tv_per) {
|
||||
String str = detail_tv_per.getText().toString();
|
||||
if ("下载中".equals(str)) {
|
||||
Intent intent = new Intent(this, DownloadManagerActivity.class);
|
||||
intent.putExtra("url", gameEntity.getApk().get(0).getUrl());
|
||||
intent.putExtra("entrance", entrance + "+(" + name + "[" + title + "])");
|
||||
startActivity(intent);
|
||||
DownloadManagerActivity.startDownloadManagerActivity(this, gameEntity.getApk().get(0).getUrl()
|
||||
, mEntrance + "+(" + name + "[" + title + "])");
|
||||
} else if ("安装".equals(str)) {
|
||||
PackageUtils.launchSetup(this, mDownloadEntity.getPath());
|
||||
}
|
||||
@ -371,9 +374,9 @@ public abstract class BaseDetailActivity extends BaseActivity implements View.On
|
||||
ApkEntity apkEntity = gameEntity.getApk().get(0);
|
||||
String msg = FileUtils.isCanDownload(this, apkEntity.getSize());
|
||||
if (TextUtils.isEmpty(msg)) {
|
||||
DataUtils.onGameDownloadEvent(this, gameEntity.getName(), apkEntity.getPlatform(), entrance, "下载开始");
|
||||
DataUtils.onGameDownloadEvent(this, gameEntity.getName(), apkEntity.getPlatform(), mEntrance, "下载开始");
|
||||
|
||||
DownloadManager.createDownload(this, apkEntity, gameEntity, method, entrance, name + ":" + title);
|
||||
DownloadManager.createDownload(this, apkEntity, gameEntity, method, mEntrance, name + ":" + title);
|
||||
|
||||
detail_tv_download.setVisibility(View.GONE);
|
||||
detail_pb_progressbar.setVisibility(View.VISIBLE);
|
||||
|
||||
@ -1,17 +1,19 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.gamecenter.listener.OnCallBackListener;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
import de.greenrobot.event.EventBus;
|
||||
|
||||
/**
|
||||
* Created by LGT on 2016/9/4.
|
||||
@ -19,75 +21,80 @@ import de.greenrobot.event.EventBus;
|
||||
*/
|
||||
public class BaseFragment extends Fragment implements OnCallBackListener {
|
||||
|
||||
protected View view;
|
||||
protected View view;
|
||||
|
||||
protected Handler handler = new Handler();
|
||||
protected boolean isEverpause;
|
||||
|
||||
protected boolean isEverpause;
|
||||
protected String mEntrance;
|
||||
|
||||
protected void init(int layout) {
|
||||
view = View.inflate(getActivity(), layout, null);
|
||||
protected void init(int layout) {
|
||||
view = View.inflate(getActivity(), layout, null);
|
||||
|
||||
ButterKnife.bind(this, view);
|
||||
}
|
||||
ButterKnife.bind(this, view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
isEverpause = false;
|
||||
EventBus.getDefault().register(this);
|
||||
}
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mEntrance = getActivity().getIntent().getStringExtra(EntranceUtils.KEY_ENTRANCE);
|
||||
isEverpause = false;
|
||||
EventBus.getDefault().register(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
if(container != null){
|
||||
container.removeView(view);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
if (container != null) {
|
||||
container.removeView(view);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
public boolean isEverpause() {
|
||||
return isEverpause;
|
||||
}
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
isEverpause = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
isEverpause = true;
|
||||
}
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
isEverpause = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
isEverpause = false;
|
||||
}
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
public void toast(String msg) {
|
||||
Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDone() {
|
||||
public boolean isEverpause() {
|
||||
return isEverpause;
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public void loadDone() {
|
||||
|
||||
@Override
|
||||
public void loadDone(Object obj) {
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public void loadDone(Object obj) {
|
||||
|
||||
@Override
|
||||
public void loadError() {
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public void loadError() {
|
||||
|
||||
@Override
|
||||
public void loadEmpty() {
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public void loadEmpty() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,185 +1,206 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
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 com.gh.common.constant.Config;
|
||||
import com.gh.common.util.DataUtils;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.FileUtils;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.RunningUtils;
|
||||
import com.gh.common.util.ShareUtils;
|
||||
import com.gh.common.util.Utils;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.eventbus.EBShowDialog;
|
||||
import com.gh.gamecenter.manager.SystemBarTintManager;
|
||||
import com.gh.gamecenter.manager.SystemBarTintManager.SystemBarConfig;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
import de.greenrobot.event.EventBus;
|
||||
|
||||
public class BaseFragmentActivity extends FragmentActivity {
|
||||
|
||||
protected String entrance;
|
||||
|
||||
private boolean isPause;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
Utils.log(this.getClass().getSimpleName());
|
||||
AppController.getInstance().addActivity(this);
|
||||
EventBus.getDefault().register(this);
|
||||
entrance = getIntent().getStringExtra("entrance");
|
||||
if (getIntent().getBundleExtra("data") != null) {
|
||||
entrance = getIntent().getBundleExtra("data").getString("entrance");
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
SystemBarConfig config = tintManager.getConfig();
|
||||
contentView.setPadding(0, config.getPixelInsetTop(false), 0,
|
||||
config.getPixelInsetBottom());
|
||||
}
|
||||
|
||||
setContentView(contentView);
|
||||
|
||||
ButterKnife.bind(this);
|
||||
|
||||
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();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
super.finish();
|
||||
AppController.getInstance().removeActivity(this);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
//如果是游戏分享,newsTitle默认为空
|
||||
public void showShare(String url, String gameName, String icon, String newsTitle, ArrayList<String> tag) {
|
||||
|
||||
//判断是否是官方版
|
||||
boolean isPlugin = false;
|
||||
if (tag != null){
|
||||
for (String s : tag) {
|
||||
if (!"官方版".equals(s)){
|
||||
isPlugin = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ShareUtils.getInstance(this).showShareWindows(new View(this), url, gameName, icon, newsTitle, isPlugin);
|
||||
|
||||
if (newsTitle == null){
|
||||
DataUtils.onEvent(this, "内容分享", gameName);
|
||||
}else {
|
||||
DataUtils.onEvent(this, "内容分享", newsTitle);
|
||||
}
|
||||
}
|
||||
|
||||
public void onEventMainThread(final EBShowDialog showDialog) {
|
||||
if (!isPause && this.getClass().getName().equals(RunningUtils.getTopActivity(this))) {
|
||||
if ("hijack".equals(showDialog.getType())) {
|
||||
DialogUtils.showQqSessionDialog(this, null);// 建议用户联系客服
|
||||
} else if ("plugin".equals(showDialog.getType())) {
|
||||
DialogUtils.showPluginDialog(this, new DialogUtils.ConfiremListener(){
|
||||
@Override
|
||||
public void onConfirem() {
|
||||
if (FileUtils.isEmptyFile(showDialog.getPath())) {
|
||||
Toast.makeText(BaseFragmentActivity.this, "解析包出错(可能被误删了),请重新下载", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
startActivity(PackageUtils.getUninstallIntent(BaseFragmentActivity.this, showDialog.getPath()));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
DataUtils.onPause(this);
|
||||
isPause = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
DataUtils.onResume(this);
|
||||
isPause = false;
|
||||
DownloadManager.getInstance(this).initGameMap();
|
||||
}
|
||||
|
||||
}
|
||||
//package com.gh.base;
|
||||
//
|
||||
//import android.annotation.TargetApi;
|
||||
//import android.content.Context;
|
||||
//import android.graphics.Color;
|
||||
//import android.os.Build;
|
||||
//import android.os.Bundle;
|
||||
//import android.support.v4.app.FragmentActivity;
|
||||
//import android.view.*;
|
||||
//import android.view.View.OnClickListener;
|
||||
//import android.view.ViewGroup.LayoutParams;
|
||||
//import android.widget.*;
|
||||
//import butterknife.ButterKnife;
|
||||
//import com.gh.common.constant.Config;
|
||||
//import com.gh.common.util.*;
|
||||
//import com.gh.download.DownloadManager;
|
||||
//import com.gh.gamecenter.R;
|
||||
//import com.gh.gamecenter.eventbus.EBShowDialog;
|
||||
//import com.readystatesoftware.systembartint.SystemBarTintManager;
|
||||
//import com.readystatesoftware.systembartint.SystemBarTintManager.SystemBarConfig;
|
||||
//import de.greenrobot.event.EventBus;
|
||||
//
|
||||
//import java.lang.reflect.Field;
|
||||
//import java.lang.reflect.Method;
|
||||
//import java.util.ArrayList;
|
||||
//
|
||||
//public class BaseFragmentActivity extends FragmentActivity {
|
||||
//
|
||||
// protected String mEntrance;
|
||||
//
|
||||
// private boolean isPause;
|
||||
//
|
||||
// @Override
|
||||
// protected void onCreate(Bundle savedInstanceState) {
|
||||
// super.onCreate(savedInstanceState);
|
||||
// AppManager.getInstance().addActivity(this);
|
||||
// EventBus.getDefault().register(this);
|
||||
// mEntrance = getIntent().getStringExtra("mEntrance");
|
||||
// if (getIntent().getBundleExtra("data") != null) {
|
||||
// mEntrance = getIntent().getBundleExtra("data").getString("mEntrance");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// 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);
|
||||
// if (Build.MANUFACTURER.equals("Meizu") || Build.MANUFACTURER.equals("Xiaomi")) {
|
||||
// tintManager.setStatusBarTintColor(Color.WHITE);
|
||||
// } else {
|
||||
// tintManager.setStatusBarTintColor(Color.BLACK);
|
||||
// }
|
||||
// SystemBarConfig config = tintManager.getConfig();
|
||||
// contentView.setPadding(0, config.getPixelInsetTop(false), 0,
|
||||
// config.getPixelInsetBottom());
|
||||
//
|
||||
// if (Build.MANUFACTURER.equals("Meizu")) {
|
||||
// try {
|
||||
// Window window = getWindow();
|
||||
// if (window != null) {
|
||||
// WindowManager.LayoutParams lp = window.getAttributes();
|
||||
// Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
|
||||
// Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags");
|
||||
// darkFlag.setAccessible(true);
|
||||
// meizuFlags.setAccessible(true);
|
||||
// int bit = darkFlag.getInt(null);
|
||||
// int value = meizuFlags.getInt(lp);
|
||||
// value |= bit;
|
||||
// meizuFlags.setInt(lp, value);
|
||||
// window.setAttributes(lp);
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// } else if (Build.MANUFACTURER.equals("Xiaomi")) {
|
||||
// try {
|
||||
// Window window = getWindow();
|
||||
// if (window != null) {
|
||||
// Class<?> clazz = window.getClass();
|
||||
// Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
|
||||
// Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
|
||||
// int darkModeFlag = field.getInt(layoutParams);
|
||||
// Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
|
||||
// extraFlagField.invoke(window, darkModeFlag, darkModeFlag);
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// setContentView(contentView);
|
||||
//
|
||||
// ButterKnife.bind(this);
|
||||
//
|
||||
// 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();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// 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);
|
||||
// }
|
||||
//
|
||||
// //如果是游戏分享,newsTitle默认为空
|
||||
// public void showShare(String url, String gameName, String icon, String newsTitle, ArrayList<String> tag) {
|
||||
//
|
||||
// //判断是否是官方版
|
||||
// boolean isPlugin = false;
|
||||
// if (tag != null) {
|
||||
// for (String s : tag) {
|
||||
// if (!"官方版".equals(s)) {
|
||||
// isPlugin = true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// ShareUtils.getInstance(this).showShareWindows(new View(this), url, gameName, icon, newsTitle, isPlugin, true);
|
||||
//
|
||||
// if (newsTitle == null) {
|
||||
// DataUtils.onEvent(this, "内容分享", gameName);
|
||||
// } else {
|
||||
// DataUtils.onEvent(this, "内容分享", newsTitle);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public void onEventMainThread(final EBShowDialog showDialog) {
|
||||
// if (!isPause && this.getClass().getName().equals(RunningUtils.getTopActivity(this))) {
|
||||
// if ("hijack".equals(showDialog.getType())) {
|
||||
// DialogUtils.showQqSessionDialog(this, null);// 建议用户联系客服
|
||||
// } else if ("plugin".equals(showDialog.getType())) {
|
||||
// DialogUtils.showPluginDialog(this, new DialogUtils.ConfirmListener() {
|
||||
// @Override
|
||||
// public void onConfirm() {
|
||||
// if (FileUtils.isEmptyFile(showDialog.getPath())) {
|
||||
// Toast.makeText(BaseFragmentActivity.this, "解析包出错(可能被误删了),请重新下载", Toast.LENGTH_SHORT).show();
|
||||
// } else {
|
||||
// startActivity(PackageUtils.getUninstallIntent(BaseFragmentActivity.this, showDialog.getPath()));
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void onDestroy() {
|
||||
// super.onDestroy();
|
||||
// EventBus.getDefault().unregister(this);
|
||||
// AppManager.getInstance().finishActivity(this);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void onPause() {
|
||||
// super.onPause();
|
||||
// DataUtils.onPause(this);
|
||||
// isPause = true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void onResume() {
|
||||
// super.onResume();
|
||||
// DataUtils.onResume(this);
|
||||
// isPause = false;
|
||||
// DownloadManager.getInstance(this).initGameMap();
|
||||
// }
|
||||
//
|
||||
//}
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
|
||||
/**
|
||||
* @author CsHeng
|
||||
* @Date 15-9-29
|
||||
* @Time 上午10:24
|
||||
*/
|
||||
public interface FragmentNavigationDelegate {
|
||||
|
||||
void addFragment(Fragment toAdd);
|
||||
|
||||
void replaceFragment(Fragment toReplace);
|
||||
|
||||
void removeFragment(Fragment toRemove);
|
||||
|
||||
void showFragment(Fragment toShow);
|
||||
|
||||
void hideFragment(Fragment toHide);
|
||||
|
||||
boolean popFragment();
|
||||
|
||||
void popFragmentToBase();
|
||||
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application.ActivityLifecycleCallbacks;
|
||||
import android.os.Bundle;
|
||||
|
||||
/**
|
||||
* 1、写点针对生命周期的统计代码
|
||||
* 2、写点通用的逻辑
|
||||
* 3、接口解耦
|
||||
*
|
||||
* @author CsHeng
|
||||
* @Date 09/05/2017
|
||||
* @Time 6:22 PM
|
||||
*/
|
||||
public class GHActivityLifecycleCallbacksImpl implements ActivityLifecycleCallbacks {
|
||||
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStarted(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResumed(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityPaused(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStopped(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityDestroyed(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -13,17 +13,16 @@ import android.os.Bundle;
|
||||
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.ClassUtils;
|
||||
import com.gh.common.util.AppDebugConfig;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.common.util.FileUtils;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.RunningUtils;
|
||||
import com.gh.common.util.TokenUtils;
|
||||
import com.gh.common.util.Utils;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.SplashScreenActivity;
|
||||
import com.xiaomi.mipush.sdk.ErrorCode;
|
||||
import com.xiaomi.mipush.sdk.MiPushClient;
|
||||
import com.xiaomi.mipush.sdk.MiPushCommandMessage;
|
||||
@ -41,6 +40,20 @@ import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static com.gh.common.util.EntranceUtils.ENTRANCE_MIPUSH;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_ARTICLE;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_GAME;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_WEB;
|
||||
import static com.gh.common.util.EntranceUtils.HOSt_COLUMN;
|
||||
import static com.gh.common.util.EntranceUtils.KEY_ENTRANCE;
|
||||
import static com.gh.common.util.EntranceUtils.KEY_GAMEID;
|
||||
import static com.gh.common.util.EntranceUtils.KEY_ID;
|
||||
import static com.gh.common.util.EntranceUtils.KEY_NEWSID;
|
||||
import static com.gh.common.util.EntranceUtils.KEY_TARGET;
|
||||
import static com.gh.common.util.EntranceUtils.KEY_TO;
|
||||
import static com.gh.common.util.EntranceUtils.KEY_TYPE;
|
||||
import static com.gh.common.util.EntranceUtils.KEY_URL;
|
||||
|
||||
/**
|
||||
* 1、PushMessageReceiver是个抽象类,该类继承了BroadcastReceiver。
|
||||
* 2、需要将自定义的DemoMessageReceiver注册在AndroidManifest.xml文件中 <receiver
|
||||
@ -59,265 +72,241 @@ import java.util.Locale;
|
||||
* 6、DemoMessageReceiver的onCommandResult方法用来接收客户端向服务器发送命令后的响应结果
|
||||
* 7、DemoMessageReceiver的onReceiveRegisterResult方法用来接收客户端向服务器发送注册命令后的响应结果
|
||||
* 8、以上这些方法运行在非UI线程中
|
||||
*
|
||||
*
|
||||
* @author mayixiang
|
||||
* //TODO 请勿更改此类路径,若需更改时请注意更改./libraries/MiPush/proguard-library.txt混淆对应配置
|
||||
*/
|
||||
public class GHPushMessageReceiver extends PushMessageReceiver {
|
||||
private String mAlias;
|
||||
|
||||
@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) || channel.equalsIgnoreCase(TD_CHANNEL_ID)) {
|
||||
String type = jsonObject.getString("type");
|
||||
Utils.log("type = " + type);
|
||||
if ("NEWS".equals(type)) {
|
||||
// 新闻推送
|
||||
JSONArray jsonArray = jsonObject.getJSONArray("package");
|
||||
ArrayMap<String, Boolean> 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<String, Boolean> 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 (apk.getString("version").equals(version)) {
|
||||
// 版本相同,无需显示插件更新,继续查看是否有可更新的游戏包
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 显示推送的消息
|
||||
showNotification(context, jsonObject, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if ("NEW_GAME".equals(type)) {
|
||||
// 新游推送
|
||||
showNotification(context, jsonObject, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
private String mAlias;
|
||||
|
||||
Log.v(AppController.TAG, "onReceivePassThroughMessage is called. " + message.toString());
|
||||
}
|
||||
@Override
|
||||
public void onReceivePassThroughMessage(Context context, MiPushMessage message) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(this, message);
|
||||
}
|
||||
// 1判断notifyid是否为4
|
||||
try {
|
||||
//TODO what is magic number 4?
|
||||
if (message.getNotifyId() == 4) {
|
||||
JSONObject jsonObject = new JSONObject(message.getContent());
|
||||
Utils.log(jsonObject.toString());
|
||||
String channel = jsonObject.getString("channel");
|
||||
Utils.log("channel = " + channel);
|
||||
|
||||
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);
|
||||
// 1判断渠道号是否一致或是否为ALL
|
||||
String packageChannel = AppController.getInstance().getChannel();
|
||||
if ("ALL".equals(channel) || channel.equalsIgnoreCase(packageChannel)) {
|
||||
String type = jsonObject.getString(KEY_TYPE);
|
||||
Utils.log("type = " + type);
|
||||
if ("NEWS".equals(type)) {
|
||||
// 新闻推送
|
||||
JSONArray jsonArray = jsonObject.getJSONArray("package");
|
||||
ArrayMap<String, Boolean> 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<String, Boolean> 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 (apk.getString("version").equals(version)) {
|
||||
// 版本相同,无需显示插件更新,继续查看是否有可更新的游戏包
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 显示推送的消息
|
||||
showNotification(context, jsonObject, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if ("NEW_GAME".equals(type)) {
|
||||
// 新游推送
|
||||
showNotification(context, jsonObject, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
NotificationManager nManager = (NotificationManager) context
|
||||
.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
private ArrayMap<String, Boolean> getInstalledMapFromLocal(Context context) {
|
||||
ArrayMap<String, Boolean> map = new ArrayMap<>();
|
||||
ArrayList<String> list = getAllPackageName(context);
|
||||
for (String str : list) {
|
||||
map.put(str, true);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
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();
|
||||
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);
|
||||
|
||||
RemoteViews remoteViews = null;
|
||||
NotificationManager nManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
||||
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);
|
||||
}
|
||||
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();
|
||||
|
||||
String url = jsonObject.getString("icon");
|
||||
String path = context.getCacheDir() + File.separator + url.substring(url.lastIndexOf("/") + 1);
|
||||
int result = FileUtils.downloadFile(url, path);
|
||||
if (result != 200) {
|
||||
// 下载出错,使用光环logo
|
||||
path = null;
|
||||
}
|
||||
RemoteViews remoteViews = null;
|
||||
|
||||
if (remoteViews != null) {
|
||||
if (path == null) {
|
||||
remoteViews.setImageViewBitmap(R.id.icon, BitmapFactory.decodeResource(context.getResources(), R.drawable.logo));
|
||||
} else {
|
||||
remoteViews.setImageViewBitmap(R.id.icon, BitmapFactory.decodeFile(path));
|
||||
}
|
||||
remoteViews.setTextViewText(R.id.title, jsonObject.getString("pushTitle"));
|
||||
remoteViews.setTextViewText(R.id.intro, jsonObject.getString("pushDesc"));
|
||||
notification.contentView = remoteViews;
|
||||
} else {
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
|
||||
.setSmallIcon(R.drawable.logo_black)
|
||||
.setTicker(jsonObject.getString("pushTitle"))
|
||||
.setContentTitle(jsonObject.getString("pushTitle"))
|
||||
.setContentText(jsonObject.getString("pushDesc"))
|
||||
.setContentIntent(pendingIntent);
|
||||
if (path == null) {
|
||||
builder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.logo));
|
||||
} else {
|
||||
builder.setLargeIcon(BitmapFactory.decodeFile(path));
|
||||
}
|
||||
notification = builder.build();
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
notification.defaults = Notification.DEFAULT_SOUND;// 添加系统默认声音
|
||||
notification.flags |= Notification.FLAG_AUTO_CANCEL; // FLAG_AUTO_CANCEL表明当通知被用户点击时,通知将被清除。
|
||||
nManager.notify(((int) System.currentTimeMillis() / 1000), notification);// 通过通知管理器来发起通知。如果id不同,则每click,在status哪里增加一个提示
|
||||
}
|
||||
String url = jsonObject.getString("icon");
|
||||
String path = context.getCacheDir() + File.separator + url.substring(url.lastIndexOf("/") + 1);
|
||||
int result = FileUtils.downloadFile(url, path);
|
||||
if (result != 200) {
|
||||
// 下载出错,使用光环logo
|
||||
path = null;
|
||||
}
|
||||
|
||||
private ArrayMap<String, Boolean> getInstalledMapFromLocal(Context context) {
|
||||
ArrayMap<String, Boolean> map = new ArrayMap<>();
|
||||
ArrayList<String> list = getAllPackageName(context);
|
||||
for (String str : list) {
|
||||
map.put(str, true);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
if (remoteViews != null) {
|
||||
if (path == null) {
|
||||
remoteViews.setImageViewBitmap(R.id.icon, BitmapFactory.decodeResource(context.getResources(), R.drawable.logo));
|
||||
} else {
|
||||
remoteViews.setImageViewBitmap(R.id.icon, BitmapFactory.decodeFile(path));
|
||||
}
|
||||
remoteViews.setTextViewText(R.id.title, jsonObject.getString("pushTitle"));
|
||||
remoteViews.setTextViewText(R.id.intro, jsonObject.getString("pushDesc"));
|
||||
notification.contentView = remoteViews;
|
||||
} else {
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
|
||||
.setSmallIcon(R.drawable.logo_black)
|
||||
.setTicker(jsonObject.getString("pushTitle"))
|
||||
.setContentTitle(jsonObject.getString("pushTitle"))
|
||||
.setContentText(jsonObject.getString("pushDesc"))
|
||||
.setContentIntent(pendingIntent);
|
||||
if (path == null) {
|
||||
builder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.logo));
|
||||
} else {
|
||||
builder.setLargeIcon(BitmapFactory.decodeFile(path));
|
||||
}
|
||||
notification = builder.build();
|
||||
}
|
||||
|
||||
private ArrayList<String> getAllPackageName(Context context) {
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
List<PackageInfo> packageInfos = context.getPackageManager()
|
||||
.getInstalledPackages(0);
|
||||
for (PackageInfo packageInfo : packageInfos) {
|
||||
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
|
||||
list.add(packageInfo.packageName);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
notification.defaults = Notification.DEFAULT_SOUND;// 添加系统默认声音
|
||||
notification.flags |= Notification.FLAG_AUTO_CANCEL; // FLAG_AUTO_CANCEL表明当通知被用户点击时,通知将被清除。
|
||||
nManager.notify(((int) System.currentTimeMillis() / 1000), notification);// 通过通知管理器来发起通知。如果id不同,则每click,在status哪里增加一个提示
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotificationMessageClicked(Context context, MiPushMessage message) {
|
||||
Log.v(AppController.TAG, "onNotificationMessageClicked is called. " + message.toString());
|
||||
private ArrayList<String> getAllPackageName(Context context) {
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
List<PackageInfo> packageInfos = context.getPackageManager().getInstalledPackages(0);
|
||||
for (PackageInfo packageInfo : packageInfos) {
|
||||
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
|
||||
list.add(packageInfo.packageName);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
try {
|
||||
String content = message.getContent();
|
||||
JSONObject response = new JSONObject(content);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("entrance", "(小米推送)");
|
||||
String type = response.getString("type");
|
||||
if ("article".equals(type)) {
|
||||
bundle.putString("to", "NewsDetailActivity");
|
||||
bundle.putString("newsId", response.getString("target"));
|
||||
} else if ("game".equals(type)) {
|
||||
bundle.putString("to", "GameDetailActivity");
|
||||
bundle.putString("gameId", response.getString("target"));
|
||||
} else if ("column".equals(type)) {
|
||||
bundle.putString("to", "SubjectActivity");
|
||||
bundle.putString("id", response.getString("target"));
|
||||
} else if ("web".equals(type)) {
|
||||
bundle.putString("to", "WebActivity");
|
||||
bundle.putString("url", response.getString("target"));
|
||||
}
|
||||
if (RunningUtils.isRunning(context)) {
|
||||
// 应用正在运行,前台或后台
|
||||
String to = bundle.getString("to");
|
||||
if (!TextUtils.isEmpty(to)) {
|
||||
Class<?> clazz = ClassUtils.forName(to);
|
||||
if (clazz != null) {
|
||||
Intent intent1 = new Intent(context, clazz);
|
||||
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent1.putExtra("data", bundle);
|
||||
context.startActivity(intent1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 应用未在运行
|
||||
Intent intent1 = new Intent(context, SplashScreenActivity.class);
|
||||
intent1.setAction(Intent.ACTION_MAIN);
|
||||
intent1.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent1.putExtra("data", bundle);
|
||||
context.startActivity(intent1);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onNotificationMessageClicked(Context context, MiPushMessage message) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(this, message);
|
||||
}
|
||||
try {
|
||||
String content = message.getContent();
|
||||
JSONObject response = new JSONObject(content);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(KEY_ENTRANCE, ENTRANCE_MIPUSH);
|
||||
String type = response.getString(KEY_TYPE);
|
||||
String target = response.getString(KEY_TARGET);
|
||||
if (HOST_ARTICLE.equals(type)) {
|
||||
bundle.putString(KEY_TO, "NewsDetailActivity");
|
||||
bundle.putString(KEY_NEWSID, target);
|
||||
} else if (HOST_GAME.equals(type)) {
|
||||
bundle.putString(KEY_TO, "GameDetailActivity");
|
||||
bundle.putString(KEY_GAMEID, target);
|
||||
} else if (HOSt_COLUMN.equals(type)) {
|
||||
bundle.putString(KEY_TO, "SubjectActivity");
|
||||
bundle.putString(KEY_ID, target);
|
||||
} else if (HOST_WEB.equals(type)) {
|
||||
bundle.putString(KEY_TO, "WebActivity");
|
||||
bundle.putString(KEY_URL, target);
|
||||
}
|
||||
EntranceUtils.jumpActivity(context, bundle);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotificationMessageArrived(Context context,
|
||||
MiPushMessage message) {
|
||||
Log.v(AppController.TAG, "onNotificationMessageArrived is called. "
|
||||
+ message.toString());
|
||||
}
|
||||
@Override
|
||||
public void onNotificationMessageArrived(Context context,
|
||||
MiPushMessage message) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(this, message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommandResult(Context context, MiPushCommandMessage message) {
|
||||
Log.v(AppController.TAG, "onCommandResult is called. "
|
||||
+ message.toString());
|
||||
@Override
|
||||
public void onReceiveRegisterResult(Context context, MiPushCommandMessage message) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(this, message);
|
||||
}
|
||||
}
|
||||
|
||||
String command = message.getCommand();
|
||||
List<String> arguments = message.getCommandArguments();
|
||||
@Override
|
||||
public void onCommandResult(Context context, MiPushCommandMessage message) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
AppDebugConfig.logMethodWithParams(this, message);
|
||||
}
|
||||
|
||||
if (MiPushClient.COMMAND_SET_ALIAS.equals(command)) {
|
||||
if (message.getResultCode() == ErrorCode.SUCCESS) {
|
||||
mAlias = arguments.get(0);
|
||||
}
|
||||
}
|
||||
String command = message.getCommand();
|
||||
List<String> arguments = message.getCommandArguments();
|
||||
|
||||
if (TextUtils.isEmpty(mAlias)) {
|
||||
//添加别名
|
||||
MiPushClient.setAlias(context, TokenUtils.getDeviceId(context), null);
|
||||
}
|
||||
}
|
||||
if (MiPushClient.COMMAND_SET_ALIAS.equals(command)) {
|
||||
if (message.getResultCode() == ErrorCode.SUCCESS) {
|
||||
mAlias = arguments.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceiveRegisterResult(Context context,
|
||||
MiPushCommandMessage message) {
|
||||
Log.v(AppController.TAG, "onReceiveRegisterResult is called. "
|
||||
+ message.toString());
|
||||
}
|
||||
if (TextUtils.isEmpty(mAlias)) {
|
||||
//添加别名
|
||||
MiPushClient.setAlias(context, TokenUtils.getDeviceId(context), null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,14 +1,9 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.gh.common.util.ClassUtils;
|
||||
import com.gh.common.util.RunningUtils;
|
||||
import com.gh.gamecenter.MainActivity;
|
||||
import com.gh.gamecenter.SplashScreenActivity;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.umeng.message.UmengNotificationClickHandler;
|
||||
import com.umeng.message.entity.UMessage;
|
||||
|
||||
@ -18,54 +13,34 @@ import org.json.JSONObject;
|
||||
|
||||
public class GHUmengNotificationClickHandler extends UmengNotificationClickHandler {
|
||||
|
||||
@Override
|
||||
public void launchApp(Context context, UMessage uMessage) {
|
||||
@Override
|
||||
public void launchApp(Context context, UMessage uMessage) {
|
||||
// super.launchApp(context, uMessage);
|
||||
|
||||
try {
|
||||
String content = uMessage.extra.get("data");
|
||||
JSONObject response = new JSONObject(content);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("entrance", "(友盟推送)");
|
||||
String type = response.getString("type");
|
||||
if ("article".equals(type)) {
|
||||
bundle.putString("to", "NewsDetailActivity");
|
||||
bundle.putString("newsId", response.getString("target"));
|
||||
} else if ("game".equals(type)) {
|
||||
bundle.putString("to", "GameDetailActivity");
|
||||
bundle.putString("gameId", response.getString("target"));
|
||||
} else if ("column".equals(type)) {
|
||||
bundle.putString("to", "SubjectActivity");
|
||||
bundle.putString("id", response.getString("target"));
|
||||
} else if ("web".equals(type)) {
|
||||
bundle.putString("to", "WebActivity");
|
||||
bundle.putString("url", response.getString("target"));
|
||||
}
|
||||
if (RunningUtils.isRunning(context)
|
||||
&& MainActivity.class.getName().equals(RunningUtils.getBaseActivity(context))) {
|
||||
// 应用正在运行,前台或后台
|
||||
String to = bundle.getString("to");
|
||||
if (!TextUtils.isEmpty(to)) {
|
||||
Class<?> clazz = ClassUtils.forName(to);
|
||||
if (clazz != null) {
|
||||
Intent intent1 = new Intent(context, clazz);
|
||||
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent1.putExtra("data", bundle);
|
||||
context.startActivity(intent1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 应用未在运行
|
||||
Intent intent1 = new Intent(context, SplashScreenActivity.class);
|
||||
intent1.setAction(Intent.ACTION_MAIN);
|
||||
intent1.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent1.putExtra("data", bundle);
|
||||
context.startActivity(intent1);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
try {
|
||||
String content = uMessage.extra.get(EntranceUtils.KEY_DATA);
|
||||
JSONObject response = new JSONObject(content);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(EntranceUtils.KEY_ENTRANCE, EntranceUtils.ENTRANCE_UMENG);
|
||||
String type = response.getString(EntranceUtils.KEY_TYPE);
|
||||
String target = response.getString(EntranceUtils.KEY_TARGET);
|
||||
if (EntranceUtils.HOST_ARTICLE.equals(type)) {
|
||||
bundle.putString(EntranceUtils.KEY_TO, "NewsDetailActivity");
|
||||
bundle.putString(EntranceUtils.KEY_NEWSID, target);
|
||||
} else if (EntranceUtils.HOST_GAME.equals(type)) {
|
||||
bundle.putString(EntranceUtils.KEY_TO, "GameDetailActivity");
|
||||
bundle.putString(EntranceUtils.KEY_GAMEID, target);
|
||||
} else if (EntranceUtils.HOSt_COLUMN.equals(type)) {
|
||||
bundle.putString(EntranceUtils.KEY_TO, "SubjectActivity");
|
||||
bundle.putString(EntranceUtils.KEY_ID, target);
|
||||
} else if (EntranceUtils.HOST_WEB.equals(type)) {
|
||||
bundle.putString(EntranceUtils.KEY_TO, "WebActivity");
|
||||
bundle.putString(EntranceUtils.KEY_URL, target);
|
||||
}
|
||||
EntranceUtils.jumpActivity(context, bundle);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,17 +1,15 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.AlphaAnimation;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.ScaleAnimation;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
@ -19,6 +17,7 @@ import com.gh.common.constant.Config;
|
||||
import com.gh.common.util.DataCollectionUtils;
|
||||
import com.gh.common.util.DataUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.ConcernActivity;
|
||||
import com.gh.gamecenter.DownloadManagerActivity;
|
||||
@ -28,177 +27,249 @@ import com.gh.gamecenter.eventbus.EBDownloadStatus;
|
||||
import com.gh.gamecenter.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.manager.PackageManager;
|
||||
|
||||
import de.greenrobot.event.EventBus;
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
/**
|
||||
* Created by LGT on 2016/9/9.
|
||||
* 工具栏 搜索控制
|
||||
*/
|
||||
public class HomeFragment extends Fragment implements View.OnClickListener {
|
||||
public class HomeFragment extends Fragment implements View.OnClickListener, SearchBarHint {
|
||||
|
||||
protected View view;
|
||||
protected View view;
|
||||
|
||||
protected Handler handler = new Handler();
|
||||
private TextView downloadHint;
|
||||
private TextView searchHint;
|
||||
|
||||
private TextView downloadHint;
|
||||
private TextView searchHint;
|
||||
private AlphaAnimation mAlphaAnimation;
|
||||
|
||||
private String hint;
|
||||
private ArrayList<String> hintList;
|
||||
private int hintIndex;
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
if (!TextUtils.isEmpty(hint)) {
|
||||
outState.putString("hint", hint);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (savedInstanceState != null) {
|
||||
hintList = savedInstanceState.getStringArrayList("hint");
|
||||
}
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
hint = savedInstanceState.getString("hint");
|
||||
}
|
||||
hintIndex = 0;
|
||||
|
||||
view = View.inflate(getActivity(), R.layout.fragment_home, null);
|
||||
view = View.inflate(getActivity(), R.layout.fragment_home, null);
|
||||
|
||||
SharedPreferences sp = getActivity().getSharedPreferences(
|
||||
Config.PREFERENCE, Context.MODE_PRIVATE);
|
||||
LinearLayout home_actionbar = (LinearLayout) view.findViewById(R.id.home_actionbar);
|
||||
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT, sp.getInt("actionbar_height",
|
||||
DisplayUtils.dip2px(getActivity(), 48)));
|
||||
// SharedPreferences sp = getActivity().getSharedPreferences(
|
||||
// Config.PREFERENCE, Context.MODE_PRIVATE);
|
||||
LinearLayout home_actionbar = (LinearLayout) view.findViewById(R.id.home_actionbar);
|
||||
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(getActivity(), 55));
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
int top = DisplayUtils.getStatusBarHeight(getResources());
|
||||
home_actionbar.setPadding(0, top, 0, 0);
|
||||
lparams.height += top;
|
||||
}
|
||||
home_actionbar.setLayoutParams(lparams);
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
// int top = DisplayUtils.getStatusBarHeight(getResources());
|
||||
// home_actionbar.setPadding(0, top, 0, 0);
|
||||
// lparams.height += top;
|
||||
// }
|
||||
home_actionbar.setLayoutParams(lparams);
|
||||
|
||||
initActionBar();
|
||||
initActionBar();
|
||||
|
||||
EventBus.getDefault().register(this);
|
||||
}
|
||||
final ScaleAnimation scaleAnimation = new ScaleAnimation(0.4f, 1.0f, 0.4f, 1.0f
|
||||
, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
|
||||
scaleAnimation.setDuration(500);
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
if (container != null) {
|
||||
container.removeView(view);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
mAlphaAnimation = new AlphaAnimation(1f, 0.2f);
|
||||
mAlphaAnimation.setDuration(300);
|
||||
mAlphaAnimation.setStartOffset(5000);
|
||||
|
||||
private void initActionBar() {
|
||||
view.findViewById(R.id.actionbar_rl_download).setOnClickListener(this);
|
||||
view.findViewById(R.id.actionbar_iv_search).setOnClickListener(this);
|
||||
view.findViewById(R.id.actionbar_notification).setOnClickListener(this);
|
||||
scaleAnimation.setAnimationListener(new Animation.AnimationListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) {
|
||||
|
||||
if (Config.isShow(getActivity())) {
|
||||
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(String.valueOf(downloadSize));
|
||||
} else if (updateSize != 0) {
|
||||
downloadHint.setVisibility(View.VISIBLE);
|
||||
downloadHint.setText(String.valueOf(updateSize));
|
||||
} else {
|
||||
downloadHint.setVisibility(View.GONE);
|
||||
}
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
if (mAlphaAnimation != null) {
|
||||
searchHint.setAnimation(mAlphaAnimation);
|
||||
mAlphaAnimation.start();
|
||||
}
|
||||
}
|
||||
|
||||
searchHint = (TextView) view.findViewById(R.id.actionbar_search_input);
|
||||
searchHint.setOnClickListener(this);
|
||||
if (!TextUtils.isEmpty(hint)) {
|
||||
searchHint.setHint(hint);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onAnimationRepeat(Animation animation) {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final int id = v.getId();
|
||||
if (id == R.id.actionbar_rl_download) {
|
||||
DataUtils.onEvent(getActivity(), "主页", "下载图标");
|
||||
DataCollectionUtils.uploadClick(getActivity(), "下载图标", "主页");
|
||||
}
|
||||
});
|
||||
|
||||
Intent intent = new Intent(getActivity(), DownloadManagerActivity.class);
|
||||
intent.putExtra("entrance", "(工具栏)");
|
||||
startActivity(intent);
|
||||
} else if (id == R.id.actionbar_iv_search) {
|
||||
DataUtils.onEvent(getActivity(), "主页", "搜索图标");
|
||||
DataCollectionUtils.uploadClick(getActivity(), "搜索图标", "主页");
|
||||
mAlphaAnimation.setAnimationListener(new Animation.AnimationListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) {
|
||||
|
||||
Intent intent = new Intent(getActivity(), SearchActivity.class);
|
||||
intent.putExtra("clicked", true);
|
||||
intent.putExtra("hint", hint);
|
||||
intent.putExtra("entrance", "(工具栏)");
|
||||
startActivity(intent);
|
||||
} else if (id == R.id.actionbar_search_input) {
|
||||
DataUtils.onEvent(getActivity(), "主页", "搜索框");
|
||||
DataCollectionUtils.uploadClick(getActivity(), "搜索框", "主页");
|
||||
}
|
||||
|
||||
Intent intent = new Intent(getActivity(), SearchActivity.class);
|
||||
intent.putExtra("clicked", false);
|
||||
intent.putExtra("hint", hint);
|
||||
intent.putExtra("entrance", "(工具栏)");
|
||||
startActivity(intent);
|
||||
} else if (id == R.id.actionbar_notification) {
|
||||
DataUtils.onEvent(getActivity(), "主页", "关注图标");
|
||||
DataCollectionUtils.uploadClick(getActivity(), "关注图标", "主页");
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
// 切换数据
|
||||
if (hintIndex > hintList.size() - 1) {
|
||||
hintIndex = 0;
|
||||
}
|
||||
searchHint.setHint(hintList.get(hintIndex));
|
||||
hintIndex++;
|
||||
|
||||
Intent intent = new Intent(getActivity(), ConcernActivity.class);
|
||||
intent.putExtra("entrance", "(工具栏)");
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
if (scaleAnimation != null) {
|
||||
searchHint.setAnimation(scaleAnimation);
|
||||
scaleAnimation.start();
|
||||
}
|
||||
}
|
||||
|
||||
// 打开下载按钮事件
|
||||
public void onEventMainThread(EBReuse reuse) {
|
||||
if ("Refresh".equals(reuse.getType())) {
|
||||
if (Config.isShow(getActivity())) {
|
||||
view.findViewById(R.id.actionbar_rl_download).setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
view.findViewById(R.id.actionbar_rl_download).setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onAnimationRepeat(Animation animation) {
|
||||
|
||||
public void setHint(String hint) {
|
||||
if (!TextUtils.isEmpty(hint)) {
|
||||
this.hint = hint;
|
||||
if (searchHint != null) {
|
||||
searchHint.setHint(hint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
public void onEventMainThread(EBDownloadStatus status) {
|
||||
int updateSize = PackageManager.getUpdateListSize();
|
||||
int downloadSize = DownloadManager.getInstance(getActivity()).getAll().size();
|
||||
if (downloadSize != 0) {
|
||||
downloadHint.setVisibility(View.VISIBLE);
|
||||
downloadHint.setText(String.valueOf(downloadSize));
|
||||
} else if (updateSize != 0) {
|
||||
downloadHint.setVisibility(View.VISIBLE);
|
||||
downloadHint.setText(String.valueOf(updateSize));
|
||||
} else {
|
||||
downloadHint.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
if (hintList != null && hintList.size() > 0) {
|
||||
if (hintList.size() > 1) {
|
||||
searchHint.setAnimation(mAlphaAnimation);
|
||||
} else {
|
||||
String hint = hintList.get(0);
|
||||
searchHint.setHint(hint);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
EventBus.getDefault().register(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
if (container != null) {
|
||||
container.removeView(view);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
if (hintList != null && !hintList.isEmpty()) {
|
||||
outState.putStringArrayList("hint", hintList);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
|
||||
private void initActionBar() {
|
||||
view.findViewById(R.id.actionbar_rl_download).setOnClickListener(this);
|
||||
view.findViewById(R.id.actionbar_iv_search).setOnClickListener(this);
|
||||
view.findViewById(R.id.actionbar_notification).setOnClickListener(this);
|
||||
view.findViewById(R.id.actionbar_search_rl).setOnClickListener(this);
|
||||
|
||||
if (Config.isShow(getActivity())) {
|
||||
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(String.valueOf(downloadSize));
|
||||
} else if (updateSize != 0) {
|
||||
downloadHint.setVisibility(View.VISIBLE);
|
||||
downloadHint.setText(String.valueOf(updateSize));
|
||||
} else {
|
||||
downloadHint.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
searchHint = (TextView) view.findViewById(R.id.actionbar_search_input);
|
||||
searchHint.setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final int id = v.getId();
|
||||
if (id == R.id.actionbar_rl_download) {
|
||||
DataUtils.onEvent(getActivity(), "主页", "下载图标");
|
||||
DataCollectionUtils.uploadClick(getActivity(), "下载图标", "主页");
|
||||
|
||||
DownloadManagerActivity.startDownloadManagerActivity(getContext(), null, "(工具栏)");
|
||||
} else if (id == R.id.actionbar_iv_search) {
|
||||
DataUtils.onEvent(getActivity(), "主页", "搜索图标");
|
||||
DataCollectionUtils.uploadClick(getActivity(), "搜索图标", "主页");
|
||||
|
||||
Intent intent = new Intent(getActivity(), SearchActivity.class);
|
||||
intent.putExtra("clicked", true);
|
||||
intent.putExtra("hint", searchHint.getHint().toString());
|
||||
intent.putExtra(EntranceUtils.KEY_ENTRANCE, "(工具栏)");
|
||||
startActivity(intent);
|
||||
} else if (id == R.id.actionbar_search_input || id == R.id.actionbar_search_rl) {
|
||||
DataUtils.onEvent(getActivity(), "主页", "搜索框");
|
||||
DataCollectionUtils.uploadClick(getActivity(), "搜索框", "主页");
|
||||
|
||||
Intent intent = new Intent(getActivity(), SearchActivity.class);
|
||||
intent.putExtra("clicked", false);
|
||||
intent.putExtra("hint", searchHint.getHint().toString());
|
||||
intent.putExtra(EntranceUtils.KEY_ENTRANCE, "(工具栏)");
|
||||
startActivity(intent);
|
||||
} else if (id == R.id.actionbar_notification) {
|
||||
DataUtils.onEvent(getActivity(), "主页", "关注图标");
|
||||
DataCollectionUtils.uploadClick(getActivity(), "关注图标", "主页");
|
||||
|
||||
Intent intent = new Intent(getActivity(), ConcernActivity.class);
|
||||
intent.putExtra(EntranceUtils.KEY_ENTRANCE, "(工具栏)");
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
// 打开下载按钮事件
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEventMainThread(EBReuse reuse) {
|
||||
if ("Refresh".equals(reuse.getType())) {
|
||||
if (Config.isShow(getActivity())) {
|
||||
view.findViewById(R.id.actionbar_rl_download).setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
view.findViewById(R.id.actionbar_rl_download).setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEventMainThread(EBDownloadStatus status) {
|
||||
int updateSize = PackageManager.getUpdateListSize();
|
||||
int downloadSize = DownloadManager.getInstance(getActivity()).getAll().size();
|
||||
if (downloadSize != 0) {
|
||||
downloadHint.setVisibility(View.VISIBLE);
|
||||
downloadHint.setText(String.valueOf(downloadSize));
|
||||
} else if (updateSize != 0) {
|
||||
downloadHint.setVisibility(View.VISIBLE);
|
||||
downloadHint.setText(String.valueOf(updateSize));
|
||||
} else {
|
||||
downloadHint.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHint(ArrayList<String> hint) {
|
||||
if (hint != null && hint.size() > 0) {
|
||||
hintList = hint;
|
||||
if (hint.size() == 1 && searchHint != null) {
|
||||
searchHint.setHint(hintList.get(0));
|
||||
} else if (mAlphaAnimation != null && searchHint != null) {
|
||||
searchHint.setAnimation(mAlphaAnimation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
9
app/src/main/java/com/gh/base/OnBackPressedListener.java
Normal file
9
app/src/main/java/com/gh/base/OnBackPressedListener.java
Normal file
@ -0,0 +1,9 @@
|
||||
package com.gh.base;
|
||||
|
||||
/**
|
||||
* Forward activity onBackPressed() events to fragment
|
||||
* (If nested fragments need this, just forward again)
|
||||
*/
|
||||
public interface OnBackPressedListener {
|
||||
public boolean onHandleBackPressed();
|
||||
}
|
||||
13
app/src/main/java/com/gh/base/SearchBarHint.java
Normal file
13
app/src/main/java/com/gh/base/SearchBarHint.java
Normal file
@ -0,0 +1,13 @@
|
||||
package com.gh.base;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @author CsHeng
|
||||
* @Date 05/05/2017
|
||||
* @Time 4:52 PM
|
||||
*/
|
||||
|
||||
public interface SearchBarHint {
|
||||
void setHint(ArrayList<String> hintList);
|
||||
}
|
||||
48
app/src/main/java/com/gh/base/SuggestionType.java
Normal file
48
app/src/main/java/com/gh/base/SuggestionType.java
Normal file
@ -0,0 +1,48 @@
|
||||
package com.gh.base;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public enum SuggestionType implements Serializable {
|
||||
|
||||
FEEDBACK("普通反馈", 1),
|
||||
SUGGESTION("功能建议", 2),
|
||||
CRASH("发生闪退", 3),
|
||||
GAME("游戏问题", 4),
|
||||
COLLECT("游戏收录", 5),
|
||||
POST("文章投稿", 6);
|
||||
|
||||
private String mName;
|
||||
private int mIndex;
|
||||
|
||||
private SuggestionType(String name, int index) {
|
||||
mName = name;
|
||||
mIndex = index;
|
||||
}
|
||||
|
||||
public static String getName(int index) {
|
||||
for (SuggestionType c : SuggestionType.values()) {
|
||||
if (c.mIndex == index) {
|
||||
return c.mName;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static int getIndex(String name) {
|
||||
for (SuggestionType c : SuggestionType.values()) {
|
||||
if (c.mName == name) {
|
||||
return c.mIndex;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return mIndex;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
}
|
||||
17
app/src/main/java/com/gh/base/ToolbarController.java
Normal file
17
app/src/main/java/com/gh/base/ToolbarController.java
Normal file
@ -0,0 +1,17 @@
|
||||
package com.gh.base;
|
||||
|
||||
import android.support.annotation.StringRes;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
|
||||
/**
|
||||
* Created by csheng on 15-10-12.
|
||||
*/
|
||||
public interface ToolbarController {
|
||||
|
||||
void setNavigationTitle(@StringRes int res);
|
||||
|
||||
void setNavigationTitle(CharSequence res);
|
||||
|
||||
Toolbar getToolBar();
|
||||
|
||||
}
|
||||
@ -4,18 +4,33 @@ package com.gh.common.constant;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
|
||||
public class Config {
|
||||
|
||||
public static final String HOST = "http://api.ghzhushou.com/v2d3/";
|
||||
public static final String USER_HOST = "http://user.ghzhushou.com/v1d1/";
|
||||
public static final String COMMENT_HOST = "http://comment.ghzhushou.com/v1d1/";
|
||||
public static final String DATA_HOST = "http://data.ghzhushou.com/";
|
||||
public static final String LIBAO_HOST = "http://libao.ghzhushou.com/v1d0/";
|
||||
public static final String PREFERENCE = "ghzhushou";
|
||||
public static final String API_HOST = BuildConfig.API_HOST;
|
||||
public static final String USER_HOST = BuildConfig.USER_HOST;
|
||||
public static final String COMMENT_HOST = BuildConfig.COMMENT_HOST;
|
||||
public static final String DATA_HOST = BuildConfig.DATA_HOST;
|
||||
public static final String LIBAO_HOST = BuildConfig.LIBAO_HOST;
|
||||
public static final String MESSAGE_HOST = BuildConfig.MESSAGE_HOST;
|
||||
|
||||
public static boolean isShow(Context context) {
|
||||
SharedPreferences sp = context.getSharedPreferences(Config.PREFERENCE, Context.MODE_PRIVATE);
|
||||
return sp.getBoolean("isShow", true);
|
||||
}
|
||||
public static final String PREFERENCE = "ghzhushou";
|
||||
|
||||
// Third-Party confs
|
||||
public static final String WECHAT_APPID = BuildConfig.WECHAT_APPID;
|
||||
public static final String TENCENT_APPID = BuildConfig.TENCENT_APPID;
|
||||
public static final String WEIBO_APPKEY = BuildConfig.WEIBO_APPKEY;
|
||||
public static final String MIPUSH_APPID = BuildConfig.MIPUSH_APPID;
|
||||
public static final String MIPUSH_APPKEY = BuildConfig.MIPUSH_APPKEY;
|
||||
public static final String MTA_APPKEY = BuildConfig.MTA_APPKEY;
|
||||
public static final String TD_APPID = BuildConfig.TD_APPID;// TalkingData
|
||||
public static final String UMENG_APPKEY = BuildConfig.UMENG_APPKEY;
|
||||
public static final String UMENG_MESSAGE_SECRET = BuildConfig.UMENG_MESSAGE_SECRET;
|
||||
|
||||
public static boolean isShow(Context context) {
|
||||
SharedPreferences sp = context.getSharedPreferences(Config.PREFERENCE, Context.MODE_PRIVATE);
|
||||
return sp.getBoolean("isShow", true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2,41 +2,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 = 60 * 1000;
|
||||
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 = 60 * 1000;
|
||||
|
||||
}
|
||||
|
||||
@ -5,22 +5,22 @@ package com.gh.common.constant;
|
||||
*/
|
||||
public class ItemViewType {
|
||||
|
||||
public static final int COLUMN_HEADER = 0; // 专题头部布局
|
||||
public static final int GAME_SLIDE = 1; // 滚动图布局
|
||||
public static final int GAME_NORMAL = 2; // 正常游戏布局
|
||||
public static final int GAME_TEST = 3; // 测试游戏布局
|
||||
public static final int GAME_IMAGE = 4; // 游戏大图布局
|
||||
public static final int NEWS_HEADER = 5; // 新闻头部布局
|
||||
public static final int NEWS_TEXT = 6; // 新闻文本布局
|
||||
public static final int NEWS_IMAGE = 7; // 新闻带图布局
|
||||
public static final int NEWS_IMAGE1 = 8; // 新闻带一张小图布局
|
||||
public static final int NEWS_IMAGE2 = 9; // 新闻带三张小图布局
|
||||
public static final int NEWS_IMAGE3 = 10; // 新闻带一张大图布局
|
||||
public static final int NEWS_DIGEST = 11; // 新闻摘要布局
|
||||
public static final int SEARCH_NORMAL = 12; // 搜索正常布局
|
||||
public static final int SEARCH_DELETE = 13; // 清空历史记录布局
|
||||
public static final int LOADING = 14; // 加载布局
|
||||
public static final int LIBAO_NORMAL = 15; // 礼包正常布局
|
||||
public static final int LIBAO_SKIP_CONCERN = 16; // 跳转关注管理页面布局
|
||||
public static final int COLUMN_HEADER = 0; // 专题头部布局
|
||||
public static final int GAME_SLIDE = 1; // 滚动图布局
|
||||
public static final int GAME_NORMAL = 2; // 正常游戏布局
|
||||
public static final int GAME_TEST = 3; // 测试游戏布局
|
||||
public static final int GAME_IMAGE = 4; // 游戏大图布局
|
||||
public static final int NEWS_HEADER = 5; // 新闻头部布局
|
||||
public static final int NEWS_TEXT = 6; // 新闻文本布局
|
||||
public static final int NEWS_IMAGE = 7; // 新闻带图布局
|
||||
public static final int NEWS_IMAGE1 = 8; // 新闻带一张小图布局
|
||||
public static final int NEWS_IMAGE2 = 9; // 新闻带三张小图布局
|
||||
public static final int NEWS_IMAGE3 = 10; // 新闻带一张大图布局
|
||||
public static final int NEWS_DIGEST = 11; // 新闻摘要布局
|
||||
public static final int SEARCH_NORMAL = 12; // 搜索正常布局
|
||||
public static final int LOADING = 14; // 加载布局
|
||||
public static final int LIBAO_NORMAL = 15; // 礼包正常布局
|
||||
public static final int LIBAO_SKIP_CONCERN = 16; // 跳转关注管理页面布局
|
||||
public static final int KC_HINT = 16;
|
||||
|
||||
}
|
||||
|
||||
@ -10,11 +10,11 @@ import com.sina.weibo.sdk.auth.Oauth2AccessToken;
|
||||
* 该类定义了微博授权时所需要的参数。
|
||||
*/
|
||||
public class AccessTokenKeeper {
|
||||
private static final String PREFERENCES_NAME = "com_weibo_sdk_android";
|
||||
private static final String PREFERENCES_NAME = "com_weibo_sdk_android";
|
||||
|
||||
private static final String KEY_UID = "uid";
|
||||
private static final String KEY_ACCESS_TOKEN = "access_token";
|
||||
private static final String KEY_EXPIRES_IN = "expires_in";
|
||||
private static final String KEY_UID = "uid";
|
||||
private static final String KEY_ACCESS_TOKEN = "access_token";
|
||||
private static final String KEY_EXPIRES_IN = "expires_in";
|
||||
private static final String KEY_REFRESH_TOKEN = "refresh_token";
|
||||
|
||||
/**
|
||||
@ -41,7 +41,6 @@ public class AccessTokenKeeper {
|
||||
* 从 SharedPreferences 读取 Token 信息。
|
||||
*
|
||||
* @param context 应用程序上下文环境
|
||||
*
|
||||
* @return 返回 Token 对象
|
||||
*/
|
||||
public static Oauth2AccessToken readAccessToken(Context context) {
|
||||
|
||||
31
app/src/main/java/com/gh/common/util/ApkActiveUtils.java
Normal file
31
app/src/main/java/com/gh/common/util/ApkActiveUtils.java
Normal file
@ -0,0 +1,31 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.manager.PackageManager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by khy on 10/05/17.
|
||||
*/
|
||||
|
||||
public class ApkActiveUtils {
|
||||
|
||||
// 过滤隐藏apk包
|
||||
public static void filterHideApk(GameEntity gameEntity) {
|
||||
if (gameEntity == null || gameEntity.getApk() == null
|
||||
|| gameEntity.getApk().size() == 0) return;
|
||||
|
||||
List<ApkEntity> apkList = gameEntity.getApk();
|
||||
for (int i = 0; i < apkList.size(); i++) {
|
||||
ApkEntity apkEntity = apkList.get(i);
|
||||
String packageName = apkEntity.getPackageName();
|
||||
String id = gameEntity.getId();
|
||||
if (!apkEntity.isActive() && !PackageManager.isCanPluggable(id, packageName)) {
|
||||
apkList.remove(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
116
app/src/main/java/com/gh/common/util/AppDebugConfig.java
Normal file
116
app/src/main/java/com/gh/common/util/AppDebugConfig.java
Normal file
@ -0,0 +1,116 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.os.Debug;
|
||||
import android.util.Log;
|
||||
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* App的测试配置项
|
||||
*/
|
||||
public class AppDebugConfig {
|
||||
|
||||
/**
|
||||
* debug模式,发布打包需要置为false,可以通过混淆让调试的log文本从代码文件中消除,避免被反编译时漏泄相关信息。
|
||||
*/
|
||||
public static final boolean IS_DEBUG = BuildConfig.DEBUG;
|
||||
|
||||
public static void logMethodName(Object object) {
|
||||
if (IS_DEBUG) {
|
||||
try {
|
||||
Log.v(getLogTag(object), getMethodName());
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String getLogTag(Object object) {
|
||||
return object.getClass().getSimpleName() + "[" + object.hashCode() + "]";
|
||||
}
|
||||
|
||||
private static String getMethodName() {
|
||||
final Thread current = Thread.currentThread();
|
||||
final StackTraceElement trace = current.getStackTrace()[4];
|
||||
return trace.getMethodName();
|
||||
}
|
||||
|
||||
public static void logMethodName(Class<?> cls) {
|
||||
if (IS_DEBUG) {
|
||||
try {
|
||||
Log.v(getLogTag(cls), getMethodName());
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void logParams(String tag, Object... params) {
|
||||
if (IS_DEBUG) {
|
||||
for (Object obj : params) {
|
||||
Log.i(tag, "" + obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void logNetworkRequest(Object object, String request, String response) {
|
||||
if (IS_DEBUG) {
|
||||
Log.i(getLogTag(object), String.format("【Request】:%s", request));
|
||||
Log.i(getLogTag(object), String.format("【Response】:%s", response));
|
||||
}
|
||||
}
|
||||
|
||||
public static void logFields(Class<?> classType) {
|
||||
if (IS_DEBUG) {
|
||||
try {
|
||||
final String name = classType.getSimpleName();
|
||||
final Field[] fs = classType.getDeclaredFields();
|
||||
for (Field f : fs) {
|
||||
Log.i(name, "Filed:" + f.getName());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void logMethodWithParams(Object object, Object... params) {
|
||||
if (IS_DEBUG) {
|
||||
try {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(getMethodName()).append(":");
|
||||
for (Object obj : params) {
|
||||
sb.append('[').append(obj).append("], ");
|
||||
}
|
||||
Log.v(getLogTag(object), sb.toString());
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void logMemoryInfo() {
|
||||
if (IS_DEBUG) {
|
||||
try {
|
||||
// final ActivityManager activityManager = (ActivityManager) getActivity().getSystemService(Context
|
||||
// .ACTIVITY_SERVICE);
|
||||
// activityManager.getMemoryClass();
|
||||
final String tag = "MM_INFO";
|
||||
// Log.i(tag, "Class " + activityManager.getMemoryClass());
|
||||
final long mb = 1024 * 1024;
|
||||
//Get VM Heap Size by calling:
|
||||
Log.i(tag, "VM Heap Size:" + Runtime.getRuntime().totalMemory() / mb);
|
||||
|
||||
// Get VM Heap Size Limit by calling:
|
||||
Log.i(tag, "VM Heap Size Limit:" + Runtime.getRuntime().maxMemory() / mb);
|
||||
|
||||
// Get Allocated VM Memory by calling:
|
||||
Log.i(tag, "Allocated VM Memory:" + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime()
|
||||
.freeMemory()) / mb);
|
||||
|
||||
//Get Native Allocated Memory by calling:
|
||||
Log.i(tag, "Native Allocated Memory:" + Debug.getNativeHeapAllocatedSize() / mb);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
143
app/src/main/java/com/gh/common/util/AppManager.java
Normal file
143
app/src/main/java/com/gh/common/util/AppManager.java
Normal file
@ -0,0 +1,143 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* 应用程序Activity管理类:用于Activity和Intent相关的管理
|
||||
*
|
||||
* @author CsHeng
|
||||
* @version 1.0
|
||||
*/
|
||||
public class AppManager {
|
||||
|
||||
private static AppManager mInstance;
|
||||
private Stack<Activity> mActivityStack;
|
||||
|
||||
private AppManager() {
|
||||
mActivityStack = new Stack<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 单一实例
|
||||
*/
|
||||
public static AppManager getInstance() {
|
||||
if (mInstance == null) {
|
||||
mInstance = new AppManager();
|
||||
}
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return mActivityStack.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加Activity到堆栈
|
||||
*/
|
||||
public void addActivity(Activity activity) {
|
||||
mActivityStack.add(activity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前Activity(堆栈中最后一个压入的)
|
||||
*/
|
||||
public Activity currentActivity() {
|
||||
return mActivityStack.lastElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束当前Activity(堆栈中最后一个压入的)
|
||||
*/
|
||||
public void finishActivity() {
|
||||
final Activity activity = mActivityStack.lastElement();
|
||||
finishActivity(activity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束指定的Activity
|
||||
*/
|
||||
public void finishActivity(Activity activity) {
|
||||
if (activity != null) {
|
||||
mActivityStack.remove(activity);
|
||||
activity.finish();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束指定类名的Activity
|
||||
*/
|
||||
public void finishActivity(Class<?> cls) {
|
||||
for (Activity activity : mActivityStack) {
|
||||
if (activity.getClass().equals(cls)) {
|
||||
finishActivity(activity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOnStack(Activity activity) {
|
||||
return mActivityStack.contains(activity);
|
||||
}
|
||||
|
||||
public Intent[] getStartIntents(Intent... intent) {
|
||||
List<Intent> intentList = getCurrentIntents();
|
||||
if (intentList != null) {
|
||||
Collections.addAll(intentList, intent);
|
||||
return intentList.toArray(new Intent[intentList.size()]);
|
||||
}
|
||||
return intent;
|
||||
}
|
||||
|
||||
public List<Intent> getCurrentIntents() {
|
||||
List<Intent> intentList = new ArrayList<>();
|
||||
for (Activity activity : mActivityStack) {
|
||||
intentList.add(activity.getIntent());
|
||||
}
|
||||
return intentList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出应用程序
|
||||
*/
|
||||
public void appExit(Context context) {
|
||||
try {
|
||||
finishAllActivity();
|
||||
/* Need Permission */
|
||||
// ActivityManager activityMgr= (ActivityManager)
|
||||
// context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
// activityMgr.restartPackage(context.getPackageName());
|
||||
// activityMgr.killBackgroundProcesses(context.getPackageName());
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束所有Activity
|
||||
*/
|
||||
public void finishAllActivity() {
|
||||
for (Activity activity : mActivityStack) {
|
||||
activity.finish();
|
||||
}
|
||||
mActivityStack.clear();
|
||||
try {
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
if (mActivityStack != null) {
|
||||
mActivityStack.clear();
|
||||
}
|
||||
mInstance = null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,9 +2,15 @@ package com.gh.common.util;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.media.ExifInterface;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
@ -12,76 +18,135 @@ import java.io.IOException;
|
||||
*/
|
||||
public class BitmapUtils {
|
||||
|
||||
/**
|
||||
* 根据文件路径返回bitmap
|
||||
* @param filepath 文件路径
|
||||
* @param w 宽
|
||||
* @param h 高
|
||||
* @return bitmap
|
||||
*/
|
||||
public static Bitmap getBitmapByFile(String filepath, int w, int h) {
|
||||
try {
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
// 设置为ture只获取图片大小
|
||||
options.inJustDecodeBounds = true;
|
||||
options.inPreferredConfig = Bitmap.Config.RGB_565;
|
||||
// 返回为空
|
||||
BitmapFactory.decodeFile(filepath, options);
|
||||
int width = options.outWidth;
|
||||
int height = options.outHeight;
|
||||
float scaleWidth = 0.f, scaleHeight = 0.f;
|
||||
if (width > w || height > h) {
|
||||
// 缩放
|
||||
scaleWidth = ((float) width) / w;
|
||||
scaleHeight = ((float) height) / h;
|
||||
}
|
||||
options.inJustDecodeBounds = false;
|
||||
int scale = (int) Math.ceil(Math.max(scaleWidth, scaleHeight));
|
||||
if (scale % 2 == 1) {
|
||||
scale += 1;
|
||||
}
|
||||
options.inSampleSize = scale;
|
||||
Bitmap bitmap = BitmapFactory.decodeFile(filepath, options);
|
||||
bitmap = rotatePicture(filepath, bitmap);
|
||||
if (bitmap != null) {
|
||||
return bitmap;
|
||||
}
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 保存图片
|
||||
*
|
||||
* @param newPath
|
||||
* @param filePath
|
||||
* @return
|
||||
*/
|
||||
public static boolean savePicture(String newPath, String filePath) {
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
// options.inSampleSize = 2;
|
||||
Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);
|
||||
|
||||
public static Bitmap rotatePicture(String path, Bitmap bitmap) {
|
||||
int rotate = 0;
|
||||
try {
|
||||
ExifInterface exifInterface = new ExifInterface(path);
|
||||
int orientation = exifInterface.getAttributeInt(
|
||||
ExifInterface.TAG_ORIENTATION,
|
||||
ExifInterface.ORIENTATION_NORMAL);
|
||||
switch (orientation) {
|
||||
case ExifInterface.ORIENTATION_ROTATE_90:
|
||||
rotate = 90;
|
||||
break;
|
||||
case ExifInterface.ORIENTATION_ROTATE_180:
|
||||
rotate = 180;
|
||||
break;
|
||||
case ExifInterface.ORIENTATION_ROTATE_270:
|
||||
rotate = 270;
|
||||
break;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (rotate != 0) {
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.setRotate(rotate);
|
||||
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
|
||||
bitmap.getHeight(), matrix, true);
|
||||
} else {
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
File file = new File(newPath);
|
||||
int quality = 80;
|
||||
do {
|
||||
try {
|
||||
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, bos);
|
||||
bos.flush();
|
||||
bos.close();
|
||||
} catch (IOException e) {
|
||||
file.delete();
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
quality -= 10;
|
||||
if (quality < 10) {
|
||||
quality = 10;
|
||||
}
|
||||
} while (file.length() > 81920 && quality > 10);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据文件路径返回bitmap
|
||||
*
|
||||
* @param filepath 文件路径
|
||||
* @param w 宽
|
||||
* @param h 高
|
||||
* @return bitmap
|
||||
*/
|
||||
public static Bitmap getBitmapByFile(String filepath, int w, int h) {
|
||||
try {
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
// 设置为ture只获取图片大小
|
||||
options.inJustDecodeBounds = true;
|
||||
options.inPreferredConfig = Bitmap.Config.RGB_565;
|
||||
// 返回为空
|
||||
BitmapFactory.decodeFile(filepath, options);
|
||||
int width = options.outWidth;
|
||||
int height = options.outHeight;
|
||||
float scaleWidth = 0.f, scaleHeight = 0.f;
|
||||
if (width > w || height > h) {
|
||||
// 缩放
|
||||
scaleWidth = ((float) width) / w;
|
||||
scaleHeight = ((float) height) / h;
|
||||
}
|
||||
options.inJustDecodeBounds = false;
|
||||
int scale = (int) Math.ceil(Math.max(scaleWidth, scaleHeight));
|
||||
if (scale % 2 == 1) {
|
||||
scale += 1;
|
||||
}
|
||||
options.inSampleSize = scale;
|
||||
Bitmap bitmap = BitmapFactory.decodeFile(filepath, options);
|
||||
bitmap = rotatePicture(filepath, bitmap);
|
||||
if (bitmap != null) {
|
||||
return bitmap;
|
||||
}
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Bitmap rotatePicture(String path, Bitmap bitmap) {
|
||||
int rotate = 0;
|
||||
try {
|
||||
ExifInterface exifInterface = new ExifInterface(path);
|
||||
int orientation = exifInterface.getAttributeInt(
|
||||
ExifInterface.TAG_ORIENTATION,
|
||||
ExifInterface.ORIENTATION_NORMAL);
|
||||
switch (orientation) {
|
||||
case ExifInterface.ORIENTATION_ROTATE_90:
|
||||
rotate = 90;
|
||||
break;
|
||||
case ExifInterface.ORIENTATION_ROTATE_180:
|
||||
rotate = 180;
|
||||
break;
|
||||
case ExifInterface.ORIENTATION_ROTATE_270:
|
||||
rotate = 270;
|
||||
break;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (rotate != 0) {
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.setRotate(rotate);
|
||||
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
|
||||
bitmap.getHeight(), matrix, true);
|
||||
} else {
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Drawable转Bitmap
|
||||
*/
|
||||
public static Bitmap drawableToBitmap(Drawable drawable) {
|
||||
if (drawable == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 取 drawable 的长宽
|
||||
int w = drawable.getIntrinsicWidth();
|
||||
int h = drawable.getIntrinsicHeight();
|
||||
// 取 drawable 的颜色格式
|
||||
Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
|
||||
: Bitmap.Config.RGB_565;
|
||||
//建立对应的Bitmap
|
||||
Bitmap bitmap = Bitmap.createBitmap(w, h, config);
|
||||
// 建立对应 bitmap 的画布
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
drawable.setBounds(0, 0, w, h);
|
||||
// 把 drawable 内容画到画布中
|
||||
drawable.draw(canvas);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -3,18 +3,18 @@ package com.gh.common.util;
|
||||
|
||||
public class ClassUtils {
|
||||
|
||||
public static Class<?> forName(String name) {
|
||||
if ("NewsActivity".equals(name)) {
|
||||
name = "NewsDetailActivity";
|
||||
} else if ("GameDetailsActivity".equals(name)) {
|
||||
name = "GameDetailActivity";
|
||||
}
|
||||
try {
|
||||
return Class.forName("com.gh.gamecenter." + name);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static Class<?> forName(String name) {
|
||||
if ("NewsActivity".equals(name)) {
|
||||
name = "NewsDetailActivity";
|
||||
} else if ("GameDetailsActivity".equals(name)) {
|
||||
name = "GameDetailActivity";
|
||||
}
|
||||
try {
|
||||
return Class.forName("com.gh.gamecenter." + name);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
198
app/src/main/java/com/gh/common/util/CommentUtils.java
Normal file
198
app/src/main/java/com/gh/common/util/CommentUtils.java
Normal file
@ -0,0 +1,198 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gh.gamecenter.CommentDetailActivity;
|
||||
import com.gh.gamecenter.MessageDetailActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.adapter.MessageDetailAdapter;
|
||||
import com.gh.gamecenter.db.CommentDao;
|
||||
import com.gh.gamecenter.entity.CommentEntity;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Created by khy on 2017/3/22.
|
||||
*/
|
||||
public class CommentUtils {
|
||||
|
||||
public static void setCommentTime(TextView textView, long time) {
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd", Locale.getDefault());
|
||||
try {
|
||||
long today = format.parse(format.format(new Date())).getTime();
|
||||
long day = time * 1000;
|
||||
if (day >= today && day < today + 86400 * 1000) {
|
||||
long min = new Date().getTime() / 1000 - day / 1000;
|
||||
int hour = (int) (min / (60 * 60));
|
||||
if (hour == 0) {
|
||||
if (min < 60) {
|
||||
textView.setText("刚刚");
|
||||
} else {
|
||||
textView.setText(String.format(Locale.getDefault(), "%d分钟前", (int) (min / 60)));
|
||||
}
|
||||
} else {
|
||||
textView.setText(String.format(Locale.getDefault(), "%d小时前", hour));
|
||||
}
|
||||
} else if (day >= today - 86400 * 1000 && day < today) {
|
||||
format.applyPattern("HH:mm");
|
||||
textView.setText("昨天 ");
|
||||
} else {
|
||||
format.applyPattern("yyyy-MM-dd");
|
||||
textView.setText(format.format(day));
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
format.applyPattern("yyyy-MM-dd");
|
||||
textView.setText(format.format(time * 1000));
|
||||
}
|
||||
}
|
||||
|
||||
public static void showReportDialog(final CommentEntity commentEntity, final Context mContext
|
||||
, final MessageDetailAdapter.OnCommentCallBackListener mCallBackListener, final String newsId) {
|
||||
|
||||
CommentDao commentDao = new CommentDao(mContext);
|
||||
|
||||
final Dialog dialog = new Dialog(mContext);
|
||||
|
||||
LinearLayout container = new LinearLayout(mContext);
|
||||
container.setOrientation(LinearLayout.VERTICAL);
|
||||
container.setBackgroundColor(Color.WHITE);
|
||||
container.setPadding(0, DisplayUtils.dip2px(mContext, 12), 0, DisplayUtils.dip2px(mContext, 12));
|
||||
|
||||
List<String> dialogType = new ArrayList<>();
|
||||
|
||||
if (!commentDao.isMyComment(commentEntity.getId())) {
|
||||
dialogType.add("回复");
|
||||
}
|
||||
|
||||
dialogType.add("复制");
|
||||
dialogType.add("举报");
|
||||
|
||||
if (commentEntity.getParent() != null) {
|
||||
dialogType.add("查看对话");
|
||||
}
|
||||
|
||||
for (String s : dialogType) {
|
||||
final TextView reportTv = new TextView(mContext);
|
||||
reportTv.setText(s);
|
||||
reportTv.setTextSize(17);
|
||||
reportTv.setTextColor(ContextCompat.getColor(mContext, R.color.title));
|
||||
reportTv.setBackgroundResource(R.drawable.textview_white_style);
|
||||
int widthPixels = mContext.getResources().getDisplayMetrics().widthPixels;
|
||||
reportTv.setLayoutParams(new LinearLayout.LayoutParams((widthPixels * 9) / 10,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT));
|
||||
reportTv.setPadding(DisplayUtils.dip2px(mContext, 20), DisplayUtils.dip2px(mContext, 12),
|
||||
0, DisplayUtils.dip2px(mContext, 12));
|
||||
container.addView(reportTv);
|
||||
|
||||
reportTv.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dialog.cancel();
|
||||
switch (reportTv.getText().toString()) {
|
||||
case "回复":
|
||||
if (mCallBackListener != null) {
|
||||
mCallBackListener.showSoftInput(commentEntity);
|
||||
} else if (!TextUtils.isEmpty(newsId)) {
|
||||
mContext.startActivity(MessageDetailActivity.getMessageDetailIntent(mContext, commentEntity, newsId));
|
||||
} else {
|
||||
Utils.toast(mContext, "缺少关键属性");
|
||||
}
|
||||
|
||||
break;
|
||||
case "复制":
|
||||
LibaoUtils.copyLink(commentEntity.getContent(), mContext);
|
||||
break;
|
||||
case "举报":
|
||||
showReportTypeDialog(commentEntity, mContext);
|
||||
break;
|
||||
case "查看对话":
|
||||
mContext.startActivity(CommentDetailActivity.getCommentDetailIntent(mContext, commentEntity.getId()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(container);
|
||||
dialog.show();
|
||||
|
||||
}
|
||||
|
||||
private static void showReportTypeDialog(final CommentEntity commentEntity, final Context mContext) {
|
||||
final String[] arrReportType = new String[]{"垃圾广告营销", "恶意攻击谩骂", "淫秽色情信息",
|
||||
"违法有害信息", "其它"};
|
||||
int widthPixels = mContext.getResources().getDisplayMetrics().widthPixels;
|
||||
|
||||
final Dialog reportTypeDialog = new Dialog(mContext);
|
||||
LinearLayout container = new LinearLayout(mContext);
|
||||
container.setOrientation(LinearLayout.VERTICAL);
|
||||
container.setPadding(0, DisplayUtils.dip2px(mContext, 12), 0, DisplayUtils.dip2px(mContext, 12));
|
||||
container.setBackgroundColor(Color.WHITE);
|
||||
|
||||
for (final String s : arrReportType) {
|
||||
TextView reportTypeTv = new TextView(mContext);
|
||||
reportTypeTv.setText(s);
|
||||
reportTypeTv.setTextSize(17);
|
||||
reportTypeTv.setTextColor(ContextCompat.getColor(mContext, R.color.title));
|
||||
reportTypeTv.setBackgroundResource(R.drawable.textview_white_style);
|
||||
reportTypeTv.setLayoutParams(new LinearLayout.LayoutParams((widthPixels * 9) / 10,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT));
|
||||
reportTypeTv.setPadding(DisplayUtils.dip2px(mContext, 20), DisplayUtils.dip2px(mContext, 12),
|
||||
0, DisplayUtils.dip2px(mContext, 12));
|
||||
container.addView(reportTypeTv);
|
||||
|
||||
reportTypeTv.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
try {
|
||||
jsonObject.put("comment_id", commentEntity.getId());
|
||||
jsonObject.put("reason", s);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
PostCommentUtils.addReportData(mContext, jsonObject.toString(), true,
|
||||
new PostCommentUtils.PostCommentListener() {
|
||||
@Override
|
||||
public void postSuccess(JSONObject response) {
|
||||
Utils.toast(mContext, "感谢您的举报");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postFailed(Throwable error) {
|
||||
Utils.toast(mContext, "举报失败,请检查网络设置");
|
||||
}
|
||||
});
|
||||
reportTypeDialog.cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
reportTypeDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
reportTypeDialog.setContentView(container);
|
||||
reportTypeDialog.show();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -14,9 +14,8 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by khy on 2016/11/8.
|
||||
*
|
||||
* <p>
|
||||
* 初始化资讯关注-内容图片
|
||||
*
|
||||
**/
|
||||
public class ConcernContentUtils {
|
||||
|
||||
@ -52,8 +51,8 @@ public class ConcernContentUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private static SimpleDraweeView getImageView(final Context context, final List<String> list, final String entrance,
|
||||
final int position, int width, int type) {
|
||||
private static SimpleDraweeView getImageView(final Context context, final List<String> list, final String entrance,
|
||||
final int position, int width, int type) {
|
||||
SimpleDraweeView imageView;
|
||||
if (type == 0) {
|
||||
imageView = new SimpleDraweeView(context);
|
||||
@ -87,14 +86,11 @@ public class ConcernContentUtils {
|
||||
imageView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent checkIntent = new Intent(context, ViewImageActivity.class);
|
||||
checkIntent.putExtra("urls", (ArrayList<String>) list);
|
||||
checkIntent.putExtra("current", position);
|
||||
checkIntent.putExtra("ScaleType", "FIT_CENTER");
|
||||
checkIntent.putExtra("entrance", entrance);
|
||||
Intent checkIntent = ViewImageActivity.getViewImageIntent(context, (ArrayList<String>) list, position, entrance);
|
||||
context.startActivity(checkIntent);
|
||||
}
|
||||
});
|
||||
return imageView;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2,14 +2,17 @@ package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.gh.gamecenter.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.json.JSONArray;
|
||||
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.ResponseBody;
|
||||
import retrofit2.HttpException;
|
||||
import rx.Observable;
|
||||
import rx.functions.Func1;
|
||||
import rx.schedulers.Schedulers;
|
||||
@ -59,7 +62,19 @@ public class ConcernUtils {
|
||||
})
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.io())
|
||||
.subscribe(new Response<ResponseBody>());
|
||||
.subscribe(new Response<ResponseBody>() {
|
||||
@Override
|
||||
public void onResponse(ResponseBody response) {
|
||||
super.onResponse(response);
|
||||
EventBus.getDefault().post(new EBReuse("UpdateConcernSuccess"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(HttpException e) {
|
||||
super.onFailure(e);
|
||||
EventBus.getDefault().post(new EBReuse("UpdateConcernFailure"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -11,150 +11,193 @@ import com.gh.gamecenter.manager.ConcernManager;
|
||||
import com.gh.gamecenter.manager.DataCollectionManager;
|
||||
import com.gh.gamecenter.manager.PackageManager;
|
||||
|
||||
import org.json.JSONArray;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by LGT on 2016/12/9.
|
||||
* 数据收集 工具类(data.ghzhushou.com)
|
||||
* 数据收集 工具类(data.ghzs666.com)
|
||||
*/
|
||||
public class DataCollectionUtils {
|
||||
|
||||
// 上传助手奔溃数据
|
||||
public static void uploadError(Context context, String msg) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("content", msg);
|
||||
map.put("type", android.os.Build.MODEL);
|
||||
map.put("system", android.os.Build.VERSION.SDK_INT + "=" + android.os.Build.VERSION.RELEASE);
|
||||
// WIFI实时
|
||||
DataCollectionManager.onEvent(context, "error", map, NetworkUtils.isWifiConnected(context));
|
||||
}
|
||||
// 上传助手奔溃数据
|
||||
public static void uploadError(Context context, String msg) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("content", msg);
|
||||
map.put("type", android.os.Build.MODEL);
|
||||
map.put("system", android.os.Build.VERSION.SDK_INT + "=" + android.os.Build.VERSION.RELEASE);
|
||||
// WIFI实时
|
||||
DataCollectionManager.onEvent(context, "error", map, NetworkUtils.isWifiConnected(context));
|
||||
}
|
||||
|
||||
// 上传下载数据(开始、完成)
|
||||
public static void uploadDownload(Context context, DownloadEntity downloadEntity, String status) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("game", downloadEntity.getName());
|
||||
map.put("game_id", downloadEntity.getGameId());
|
||||
if (downloadEntity.isPluggable()) {
|
||||
map.put("method", "插件化");
|
||||
map.put("btn_status", "插件化");
|
||||
} else if (downloadEntity.isUpdate()) {
|
||||
map.put("method", "更新");
|
||||
map.put("btn_status", "更新");
|
||||
} else {
|
||||
map.put("method", "正常");
|
||||
map.put("btn_status", "下载");
|
||||
}
|
||||
map.put("platform", PlatformUtils.getInstance(context).getPlatformName(downloadEntity.getPlatform()));
|
||||
map.put("status", status);
|
||||
map.put("location", downloadEntity.getLocation());
|
||||
map.put("entrance", downloadEntity.getEntrance());
|
||||
map.put("installed", downloadEntity.getInstalled());
|
||||
map.put("network", NetworkUtils.getConnectedType(context));
|
||||
DataCollectionManager.onEvent(context, "download", map);
|
||||
}
|
||||
// 上传下载数据(开始、完成)
|
||||
public static void uploadDownload(Context context, DownloadEntity downloadEntity, String status) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("game", downloadEntity.getName());
|
||||
map.put("game_id", downloadEntity.getGameId());
|
||||
if (downloadEntity.isPluggable()) {
|
||||
map.put("method", "插件化");
|
||||
map.put("btn_status", "插件化");
|
||||
} else if (downloadEntity.isUpdate()) {
|
||||
map.put("method", "更新");
|
||||
map.put("btn_status", "更新");
|
||||
} else {
|
||||
map.put("method", "正常");
|
||||
map.put("btn_status", "下载");
|
||||
}
|
||||
map.put("platform", PlatformUtils.getInstance(context).getPlatformName(downloadEntity.getPlatform()));
|
||||
map.put("status", status);
|
||||
map.put("location", downloadEntity.getLocation());
|
||||
map.put(EntranceUtils.KEY_ENTRANCE, downloadEntity.getEntrance());
|
||||
map.put("installed", downloadEntity.getInstalled());
|
||||
map.put("network", NetworkUtils.getConnectedType(context));
|
||||
DataCollectionManager.onEvent(context, "download", map);
|
||||
}
|
||||
|
||||
// 上传点击数据
|
||||
public static void uploadClick(Context context, String... args) {
|
||||
if (args.length < 2) {
|
||||
return;
|
||||
}
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("location", args[0]);
|
||||
map.put("page", args[1]);
|
||||
if (args.length == 3) {
|
||||
map.put("title", args[2]);
|
||||
}
|
||||
DataCollectionManager.onEvent(context, "click-item", map);
|
||||
}
|
||||
// 上传点击数据
|
||||
public static void uploadClick(Context context, String... args) {
|
||||
if (args.length < 2) {
|
||||
return;
|
||||
}
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("location", args[0]);
|
||||
map.put("page", args[1]);
|
||||
if (args.length == 3) {
|
||||
map.put("title", args[2]);
|
||||
}
|
||||
DataCollectionManager.onEvent(context, "click-item", map);
|
||||
}
|
||||
|
||||
// 上传游戏数据
|
||||
public static void uploadGame(Context context, GameEntity gameEntity, int seconds, String from) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("game", gameEntity.getName());
|
||||
map.put("game_id", gameEntity.getId());
|
||||
map.put("time", seconds);
|
||||
map.put("from", from);
|
||||
DataCollectionManager.onEvent(context, "game", map);
|
||||
}
|
||||
// 上传游戏数据
|
||||
public static void uploadGame(Context context, GameEntity gameEntity, int seconds, String from) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("game", gameEntity.getName());
|
||||
map.put("game_id", gameEntity.getId());
|
||||
map.put("time", seconds);
|
||||
map.put("from", from);
|
||||
DataCollectionManager.onEvent(context, "game", map);
|
||||
}
|
||||
|
||||
// 上传新闻数据
|
||||
public static void uploadNews(Context context, NewsDetailEntity newsDetailEntity,
|
||||
GameEntity gameEntity, int seconds, String from) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("title", newsDetailEntity.getTitle());
|
||||
map.put("type", newsDetailEntity.getType());
|
||||
map.put("author", newsDetailEntity.getAuthor());
|
||||
if (gameEntity != null) {
|
||||
map.put("game", gameEntity.getName());
|
||||
map.put("game_id", gameEntity.getId());
|
||||
}
|
||||
map.put("time", seconds);
|
||||
map.put("from", from);
|
||||
DataCollectionManager.onEvent(context, "news", map);
|
||||
}
|
||||
// 上传新闻数据
|
||||
public static void uploadNews(Context context, NewsDetailEntity newsDetailEntity,
|
||||
GameEntity gameEntity, int seconds, String from) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("title", newsDetailEntity.getTitle());
|
||||
map.put("type", newsDetailEntity.getType());
|
||||
map.put("author", newsDetailEntity.getAuthor());
|
||||
if (gameEntity != null) {
|
||||
map.put("game", gameEntity.getName());
|
||||
map.put("game_id", gameEntity.getId());
|
||||
}
|
||||
map.put("time", seconds);
|
||||
map.put("from", from);
|
||||
DataCollectionManager.onEvent(context, "news", map);
|
||||
}
|
||||
|
||||
// 上传安装或卸载数据
|
||||
public static void uploadInorunstall(Context context, String type, String packageName) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("type", type);
|
||||
map.put("packageName", packageName);
|
||||
DataCollectionManager.onEvent(context, "inorunstall", map);
|
||||
}
|
||||
// 上传安装或卸载数据
|
||||
public static void uploadInorunstall(Context context, String type, String packageName) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("type", type);
|
||||
map.put("packageName", packageName);
|
||||
DataCollectionManager.onEvent(context, "inorunstall", map);
|
||||
}
|
||||
|
||||
// 上传劫持数据
|
||||
public static void uploadHijack(Context context, DownloadEntity downloadEntity) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("url", downloadEntity.getUrl());
|
||||
map.put("game", downloadEntity.getName());
|
||||
map.put("game_id", downloadEntity.getGameId());
|
||||
map.put("platform", downloadEntity.getPlatform());
|
||||
map.put("hijack_url", downloadEntity.getError());
|
||||
DataCollectionManager.onEvent(context, "hijack", map);
|
||||
}
|
||||
// 上传劫持数据
|
||||
public static void uploadHijack(Context context, DownloadEntity downloadEntity) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("url", downloadEntity.getUrl());
|
||||
map.put("game", downloadEntity.getName());
|
||||
map.put("game_id", downloadEntity.getGameId());
|
||||
map.put("platform", downloadEntity.getPlatform());
|
||||
map.put("hijack_url", downloadEntity.getError());
|
||||
DataCollectionManager.onEvent(context, "hijack", map);
|
||||
}
|
||||
|
||||
// 上传用户数据
|
||||
public static void uploadUser(Context context) {
|
||||
ConcernManager concernManager = new ConcernManager(context);
|
||||
ArrayList<String> concernList = new ArrayList<>();
|
||||
for (ConcernInfo entity : concernManager.getAllConcern()) {
|
||||
if (entity.isConcern()) {
|
||||
concernList.add(entity.getGameName());
|
||||
}
|
||||
}
|
||||
Map<String, Object> 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);
|
||||
DataCollectionManager.upsert(context, "user", map);
|
||||
}
|
||||
// 上传用户数据
|
||||
public static void uploadUser(Context context) {
|
||||
ConcernManager concernManager = new ConcernManager(context);
|
||||
ArrayList<String> concernList = new ArrayList<>();
|
||||
for (ConcernInfo entity : concernManager.getAllConcern()) {
|
||||
if (entity.isConcern()) {
|
||||
concernList.add(entity.getGameName());
|
||||
}
|
||||
}
|
||||
Map<String, Object> 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);
|
||||
DataCollectionManager.upsert(context, "user", map);
|
||||
}
|
||||
|
||||
// 上传搜索数据
|
||||
public static void uploadSearch(Context context, String... args) {
|
||||
if (args.length < 2) {
|
||||
return;
|
||||
}
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("key", args[0]);
|
||||
map.put("from", args[1]);
|
||||
if (args.length == 3) {
|
||||
map.put("click", args[2]);
|
||||
}
|
||||
DataCollectionManager.onEvent(context, "search", map);
|
||||
}
|
||||
// 上传搜索数据
|
||||
public static void uploadSearch(Context context, String... args) {
|
||||
if (args.length != 5) {
|
||||
return;
|
||||
}
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("from", args[2]);
|
||||
map.put("search_type", args[1]);
|
||||
map.put("key", args[0]);
|
||||
map.put("game_id", args[3]);
|
||||
map.put("game_name", args[4]);
|
||||
map.put("netword", NetworkUtils.getConnectedType(context));
|
||||
map.put("type", "search");
|
||||
map.put("device_type", android.os.Build.MODEL);
|
||||
map.put("device_system", android.os.Build.VERSION.SDK_INT + "=" + android.os.Build.VERSION.RELEASE);
|
||||
DataCollectionManager.onEvent(context, "search", map);
|
||||
}
|
||||
|
||||
// 上传关注数据
|
||||
public static void uploadConcern(Context context, String... args) {
|
||||
if (args.length < 3) {
|
||||
return;
|
||||
}
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("game", args[0]);
|
||||
map.put("game_id", args[1]);
|
||||
map.put("type", args[2]);
|
||||
DataCollectionManager.onEvent(context, "concern", map);
|
||||
}
|
||||
// 上传搜索点击数据
|
||||
public static void uploadSearchClick(Context context, String... args) {
|
||||
if (args.length != 5) {
|
||||
return;
|
||||
}
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("from", args[2]);
|
||||
map.put("search_type", args[1]);
|
||||
map.put("key", args[0]);
|
||||
map.put("game_id", args[3]);
|
||||
map.put("game_name", args[4]);
|
||||
map.put("netword", NetworkUtils.getConnectedType(context));
|
||||
map.put("type", "click");
|
||||
map.put("device_type", android.os.Build.MODEL);
|
||||
map.put("device_system", android.os.Build.VERSION.SDK_INT + "=" + android.os.Build.VERSION.RELEASE);
|
||||
DataCollectionManager.onEvent(context, "search", map);
|
||||
}
|
||||
|
||||
// 上传关注数据
|
||||
public static void uploadConcern(Context context, String... args) {
|
||||
if (args.length < 3) {
|
||||
return;
|
||||
}
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("game", args[0]);
|
||||
map.put("game_id", args[1]);
|
||||
map.put("type", args[2]);
|
||||
DataCollectionManager.onEvent(context, "concern", map);
|
||||
}
|
||||
|
||||
//上传推荐位数据
|
||||
public static void uploadPosition(Context context, String... args) {
|
||||
if (args.length < 3) {
|
||||
return;
|
||||
}
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("page", args[0]);
|
||||
map.put("location", args[1]);
|
||||
map.put("name", args[2]);
|
||||
DataCollectionManager.onEvent(context, "position", map);
|
||||
}
|
||||
|
||||
//上传应用列表
|
||||
public static void uploadAppList(Context context, JSONArray applist) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("applist", applist);
|
||||
DataCollectionManager.onEvent(context, "applist", map);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.gh.base.AppController;
|
||||
import com.gh.download.DownloadEntity;
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
@ -23,67 +24,67 @@ import rx.schedulers.Schedulers;
|
||||
*/
|
||||
public class DataLogUtils {
|
||||
|
||||
// 上传日志
|
||||
public static void uploadLog(Context context, String topic, Map<String, Object> map) {
|
||||
String version = PackageUtils.getVersionName(context);
|
||||
String user = Installation.getUUID(context);
|
||||
String channel = (String) PackageUtils.getMetaData(context, context.getPackageName(), "TD_CHANNEL_ID");
|
||||
map.put("version", version);
|
||||
map.put("user", user);
|
||||
map.put("device_id", TokenUtils.getDeviceId(context));
|
||||
map.put("channel", channel);
|
||||
// 轮播图
|
||||
public static void uploadLunbotuLog(Context context, String type, String title, String location) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("location", location);
|
||||
map.put("type", type);
|
||||
map.put("title", title);
|
||||
map.put("form", "click");
|
||||
uploadLog(context, "lunbotu", map);
|
||||
}
|
||||
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("topic", topic);
|
||||
params.put("source", "GH-ASSIST-Client");
|
||||
params.put("time", String.valueOf(Utils.getTime(context)));
|
||||
params.put("content", new JSONObject(map).toString());
|
||||
// 上传日志
|
||||
public static void uploadLog(Context context, String topic, Map<String, Object> map) {
|
||||
String version = PackageUtils.getVersionName(context);
|
||||
String user = Installation.getUUID(context);
|
||||
String channel = AppController.getInstance().getChannel();
|
||||
map.put("version", version);
|
||||
map.put("user", user);
|
||||
map.put("device_id", TokenUtils.getDeviceId(context));
|
||||
map.put("channel", channel);
|
||||
|
||||
RequestBody body = RequestBody.create(MediaType.parse("application/json"),
|
||||
new JSONObject(params).toString());
|
||||
RetrofitManager.getData().postLog(body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<ResponseBody>());
|
||||
}
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("topic", topic);
|
||||
params.put("source", "GH-ASSIST-Client");
|
||||
params.put("time", String.valueOf(Utils.getTime(context)));
|
||||
params.put("content", new JSONObject(map).toString());
|
||||
|
||||
// 轮播图
|
||||
public static void uploadLunbotuLog(Context context, String type, String title, String location) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("location", location);
|
||||
map.put("type", type);
|
||||
map.put("title", title);
|
||||
map.put("form", "click");
|
||||
uploadLog(context, "lunbotu", map);
|
||||
}
|
||||
RequestBody body = RequestBody.create(MediaType.parse("application/json"),
|
||||
new JSONObject(params).toString());
|
||||
RetrofitManager.getData().postLog(body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<ResponseBody>());
|
||||
}
|
||||
|
||||
// 网络错误
|
||||
public static void uploadNeterrorLog(Context context, DownloadEntity downloadEntity) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("url", downloadEntity.getUrl());
|
||||
map.put("game", downloadEntity.getName());
|
||||
map.put("game_id", downloadEntity.getGameId());
|
||||
map.put("platform", downloadEntity.getPlatform());
|
||||
map.put("error", downloadEntity.getError());
|
||||
uploadLog(context, "neterror", map);
|
||||
}
|
||||
// 网络错误
|
||||
public static void uploadNeterrorLog(Context context, DownloadEntity downloadEntity) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("url", downloadEntity.getUrl());
|
||||
map.put("game", downloadEntity.getName());
|
||||
map.put("game_id", downloadEntity.getGameId());
|
||||
map.put("platform", downloadEntity.getPlatform());
|
||||
map.put("error", downloadEntity.getError());
|
||||
uploadLog(context, "neterror", map);
|
||||
}
|
||||
|
||||
// 助手更新
|
||||
public static void uploadUpgradeLog(Context context, String step) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("step", step);
|
||||
uploadLog(context, "upgrade", map);
|
||||
}
|
||||
// 助手更新
|
||||
public static void uploadUpgradeLog(Context context, String step) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("step", step);
|
||||
uploadLog(context, "upgrade", map);
|
||||
}
|
||||
|
||||
// 链接劫持
|
||||
public static void uploadHijack(Context context, DownloadEntity downloadEntity) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("url", downloadEntity.getUrl());
|
||||
map.put("game", downloadEntity.getName());
|
||||
map.put("game_id", downloadEntity.getGameId());
|
||||
map.put("platform", downloadEntity.getPlatform());
|
||||
map.put("hijack_url", downloadEntity.getError());
|
||||
uploadLog(context, "hijack", map);
|
||||
}
|
||||
// 链接劫持
|
||||
public static void uploadHijack(Context context, DownloadEntity downloadEntity) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("url", downloadEntity.getUrl());
|
||||
map.put("game", downloadEntity.getName());
|
||||
map.put("game_id", downloadEntity.getGameId());
|
||||
map.put("platform", downloadEntity.getPlatform());
|
||||
map.put("hijack_url", downloadEntity.getError());
|
||||
uploadLog(context, "hijack", map);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -4,8 +4,10 @@ import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.tencent.stat.MtaSDkException;
|
||||
import com.tencent.stat.StatConfig;
|
||||
import com.tencent.stat.StatCrashReporter;
|
||||
import com.tencent.stat.StatReportStrategy;
|
||||
import com.tencent.stat.StatService;
|
||||
import com.tendcloud.tenddata.TCAgent;
|
||||
@ -20,29 +22,61 @@ import java.util.Properties;
|
||||
*/
|
||||
public class DataUtils {
|
||||
|
||||
public static void init(Application application) {
|
||||
/**
|
||||
* 初始化各种统计工具,仅在release build(非debug)模式启用统计
|
||||
*
|
||||
* @param context
|
||||
* @param debug 是否debug模式
|
||||
* @param channel
|
||||
*/
|
||||
public static void init(Application context, final boolean debug, String channel) {
|
||||
|
||||
//TalkingData
|
||||
//dubug true release false
|
||||
TCAgent.LOG_ON = true;
|
||||
TCAgent.init(application);
|
||||
TCAgent.setReportUncaughtExceptions(true);
|
||||
TCAgent.LOG_ON = debug;
|
||||
if (!debug) {
|
||||
TCAgent.init(context, Config.TD_APPID, channel);
|
||||
//TODO 去除为了测试MTA的问题,这个版本不启用
|
||||
// TCAgent.setReportUncaughtExceptions(true);
|
||||
}
|
||||
|
||||
// 打开debug开关,可查看mta上报日志或错误
|
||||
// debug true release false
|
||||
StatConfig.setDebugEnable(debug);
|
||||
|
||||
//MTA
|
||||
// 打开debug开关,可查看mta上报日志或错误
|
||||
// dubug true release false
|
||||
StatConfig.setDebugEnable(true);
|
||||
// 收集未处理的异常
|
||||
StatConfig.setAutoExceptionCaught(true);
|
||||
// 设置数据上报策略
|
||||
StatConfig.setStatSendStrategy(StatReportStrategy.PERIOD);
|
||||
StatConfig.setSendPeriodMinutes(5);
|
||||
// 开启收集服务
|
||||
String TA_APPKEY = (String) PackageUtils.getMetaData(application, application.getPackageName(), "TA_APPKEY");
|
||||
try {
|
||||
StatService.startStatService(application, TA_APPKEY, com.tencent.stat.common.StatConstants.VERSION);
|
||||
} catch (MtaSDkException e) {
|
||||
e.printStackTrace();
|
||||
if (!debug) {
|
||||
|
||||
//TODO 加入账号之后设置用户
|
||||
// StatConfig.setCustomUserId(context, "userid");
|
||||
|
||||
// 收集未处理的异常
|
||||
StatConfig.setAutoExceptionCaught(true);
|
||||
|
||||
StatConfig.setAntoActivityLifecycleStat(true);
|
||||
|
||||
// 设置数据上报策略
|
||||
StatConfig.setStatSendStrategy(StatReportStrategy.PERIOD);
|
||||
StatConfig.setSendPeriodMinutes(5);
|
||||
|
||||
StatConfig.init(context);
|
||||
StatConfig.setInstallChannel(channel);
|
||||
StatService.setContext(context);
|
||||
StatService.registerActivityLifecycleCallbacks(context);
|
||||
|
||||
StatCrashReporter crashReporter = StatCrashReporter.getStatCrashReporter(context);
|
||||
// 开启异常时的实时上报
|
||||
crashReporter.setEnableInstantReporting(true);
|
||||
// 开启java异常捕获
|
||||
crashReporter.setJavaCrashHandlerStatus(true);
|
||||
|
||||
try {
|
||||
// 开启收集服务
|
||||
StatService.startStatService(context, Config.MTA_APPKEY, com.tencent.stat.common.StatConstants.VERSION);
|
||||
} catch (MtaSDkException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void onEvent(Context var0, String var1, String var2) {
|
||||
@ -50,16 +84,6 @@ public class DataUtils {
|
||||
StatService.trackCustomEvent(var0, var1, var2);
|
||||
}
|
||||
|
||||
public static void onEvent(Context var0, String var1, String var2, Map<String, Object> var3) {
|
||||
TCAgent.onEvent(var0, var1, var2, var3);
|
||||
Properties prop = new Properties();
|
||||
prop.setProperty("label", var2);
|
||||
for (String key : var3.keySet()) {
|
||||
prop.setProperty(key, var3.get(key) + "");
|
||||
}
|
||||
StatService.trackCustomKVEvent(var0, var1, prop);
|
||||
}
|
||||
|
||||
public static void onPause(Activity var0) {
|
||||
TCAgent.onPause(var0);
|
||||
StatService.onPause(var0);
|
||||
@ -78,23 +102,33 @@ public class DataUtils {
|
||||
onEvent(context, "游戏启动", gameName, kv);
|
||||
}
|
||||
|
||||
public static void onEvent(Context var0, String var1, String var2, Map<String, Object> var3) {
|
||||
TCAgent.onEvent(var0, var1, var2, var3);
|
||||
Properties prop = new Properties();
|
||||
prop.setProperty("label", var2);
|
||||
for (String key : var3.keySet()) {
|
||||
prop.setProperty(key, var3.get(key) + "");
|
||||
}
|
||||
StatService.trackCustomKVEvent(var0, var1, prop);
|
||||
}
|
||||
|
||||
// 游戏下载
|
||||
public static void onGameDownloadEvent(Context context, String gameName, String platform, String entrance, String status) {
|
||||
Map<String, Object> kv = new HashMap<>();
|
||||
kv.put("版本", platform);
|
||||
kv.put("状态", status);
|
||||
DataUtils.onEvent(context, "游戏下载", gameName, kv);
|
||||
onEvent(context, "游戏下载", gameName, kv);
|
||||
|
||||
Map<String, Object> kv2 = new HashMap<>();
|
||||
kv2.put("版本", platform);
|
||||
kv2.put("状态", status);
|
||||
kv2.put("位置", entrance);
|
||||
DataUtils.onEvent(context, "游戏下载位置", gameName, kv2);
|
||||
onEvent(context, "游戏下载位置", gameName, kv2);
|
||||
|
||||
Map<String, Object> kv3 = new HashMap<>();
|
||||
kv3.put(entrance, "下载数");
|
||||
kv3.put(entrance, status);
|
||||
DataUtils.onEvent(context, "应用数据", gameName, kv3);
|
||||
onEvent(context, "应用数据", gameName, kv3);
|
||||
}
|
||||
|
||||
// 游戏更新
|
||||
@ -102,7 +136,7 @@ public class DataUtils {
|
||||
Map<String, Object> kv = new HashMap<>();
|
||||
kv.put("版本", paltform);
|
||||
kv.put("状态", status);
|
||||
DataUtils.onEvent(context, "游戏更新", gameName, kv);
|
||||
onEvent(context, "游戏更新", gameName, kv);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,275 +1,445 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Handler;
|
||||
import android.text.Html;
|
||||
import android.text.Spanned;
|
||||
import android.view.Display;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gh.base.AppController;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.kuaichuan.WifiMgr;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
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;
|
||||
}
|
||||
private static boolean isShow = false;
|
||||
|
||||
private static boolean isShow = false;
|
||||
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 showWarningDialog(Context context, String title, CharSequence msg, String cancel, String confirm,
|
||||
final ConfiremListener cmListener, final CancelListener clListener) {
|
||||
// 快传成绩单
|
||||
public static void showKuaiChuanResult(final Activity activity, Handler handler, int requestCode, final String picName) {
|
||||
|
||||
if (isShow) {
|
||||
return;
|
||||
}
|
||||
isShow = true;
|
||||
AppController.remove("FileInfo");
|
||||
|
||||
final Dialog dialog = new Dialog(context);
|
||||
List<Map<String, String>> mapList = (List<Map<String, String>>) AppController.get("sendData", true);
|
||||
if (mapList == null || mapList.size() == 0) return;
|
||||
|
||||
View view = View.inflate(context, R.layout.common_alertdialog, null);
|
||||
WifiMgr.getInstance(activity).disconnectCurrentNetwork(); // 断开当前WiFi
|
||||
|
||||
// 标题
|
||||
TextView alertdialog_title = (TextView) view.findViewById(R.id.alertdialog_title);
|
||||
alertdialog_title.setText(title);
|
||||
// int heightPixels = getContext().getResources().getDisplayMetrics().heightPixels;
|
||||
// int widthPixels = getContext().getResources().getDisplayMetrics().widthPixels;
|
||||
|
||||
// 内容
|
||||
TextView alertdialog_content = (TextView) view.findViewById(R.id.alertdialog_content);
|
||||
alertdialog_content.setText(msg);
|
||||
int filesCount = mapList.size();
|
||||
int filesSize = 0;
|
||||
int sendTime = 0;
|
||||
|
||||
// 取消按钮
|
||||
TextView alertdialog_cannel = (TextView) view.findViewById(R.id.alertdialog_cannel);
|
||||
alertdialog_cannel.setText(cancel);
|
||||
alertdialog_cannel.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dialog.dismiss();
|
||||
if (clListener != null) {
|
||||
clListener.onCancel();
|
||||
}
|
||||
}
|
||||
});
|
||||
View view = View.inflate(activity
|
||||
, R.layout.dialog_kuaichuan, null);
|
||||
final LinearLayout mShareLl = (LinearLayout) view.findViewById(R.id.kuaichuan_dialog_ll);
|
||||
final LinearLayout mShareBottomLl = (LinearLayout) view.findViewById(R.id.kuaichuan_dialog_share_rl);
|
||||
LinearLayout shareIconLl = (LinearLayout) view.findViewById(R.id.kuaichuan_icon_ll);
|
||||
ImageView qrCode = (ImageView) view.findViewById(R.id.kuaichuan_qrcode);
|
||||
TextView dateTv = (TextView) view.findViewById(R.id.kuaichuan_dialog_date);
|
||||
TextView countTv = (TextView) view.findViewById(R.id.kuaichuan_send_count);
|
||||
TextView sizeTv = (TextView) view.findViewById(R.id.kuaichuan_send_size);
|
||||
TextView speedTv = (TextView) view.findViewById(R.id.kuaichuan_send_speed);
|
||||
TextView timeCount = (TextView) view.findViewById(R.id.kuaichuan_time_count);
|
||||
TextView timeTv = (TextView) view.findViewById(R.id.kuaichuan_time_tv);
|
||||
TextView sendCountTv = (TextView) view.findViewById(R.id.dialog_send_tv);
|
||||
ImageView closeIv = (ImageView) view.findViewById(R.id.kuaichuan_dialog_colse);
|
||||
// content.setLayoutParams(new LinearLayout.LayoutParams((int)(((float)heightPixels)*0.85), (int)((float)widthPixels*0.81)));
|
||||
|
||||
// 确定按钮
|
||||
TextView alertdialog_confirm = (TextView) view.findViewById(R.id.alertdialog_confirm);
|
||||
alertdialog_confirm.setText(confirm);
|
||||
alertdialog_confirm.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dialog.dismiss();
|
||||
if (cmListener != null) {
|
||||
cmListener.onConfirem();
|
||||
}
|
||||
}
|
||||
});
|
||||
final Dialog dialog = new Dialog(activity);
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setCanceledOnTouchOutside(false);
|
||||
dialog.setContentView(view);
|
||||
dialog.show();
|
||||
|
||||
dialog.setOnDismissListener(new Dialog.OnDismissListener() {
|
||||
@Override
|
||||
public void onDismiss(DialogInterface dialog) {
|
||||
isShow = false;
|
||||
}
|
||||
});
|
||||
Window dialogWindow = dialog.getWindow();
|
||||
WindowManager m = activity.getWindowManager();
|
||||
Display d = m.getDefaultDisplay();
|
||||
if (dialogWindow != null) {
|
||||
WindowManager.LayoutParams p = dialogWindow.getAttributes();
|
||||
p.height = (int) (d.getHeight() * 0.82);
|
||||
p.width = (int) (d.getWidth() * 0.80);
|
||||
dialogWindow.setAttributes(p);
|
||||
}
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(view);
|
||||
dialog.show();
|
||||
}
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日", Locale.getDefault());
|
||||
dateTv.setText(format.format(new Date().getTime()));
|
||||
|
||||
public static void showInstallHintDialog(Context context ,final ConfiremListener cmListener) {
|
||||
for (Map<String, String> map : mapList) {
|
||||
int size = Integer.parseInt(map.get("apkSize"));
|
||||
int time = 10;
|
||||
try {
|
||||
time = Integer.parseInt(map.get("sendTime"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
String apkPath = map.get("apkPath");
|
||||
filesSize = filesSize + size;
|
||||
sendTime = sendTime + time;
|
||||
|
||||
if (shareIconLl.getChildCount() >= 5) continue;
|
||||
|
||||
android.content.pm.PackageManager pm = activity.getPackageManager();
|
||||
PackageInfo info = pm.getPackageArchiveInfo(apkPath,
|
||||
android.content.pm.PackageManager.GET_ACTIVITIES);
|
||||
if (info != null) {
|
||||
ApplicationInfo appInfo = info.applicationInfo;
|
||||
appInfo.sourceDir = apkPath;
|
||||
appInfo.publicSourceDir = apkPath;
|
||||
Bitmap bitmap = BitmapUtils.drawableToBitmap(appInfo.loadIcon(pm));
|
||||
|
||||
ImageView imageView = new ImageView(activity);
|
||||
imageView.setLayoutParams(new LinearLayout.LayoutParams(DisplayUtils.dip2px(activity, 25)
|
||||
, DisplayUtils.dip2px(activity, 24)));
|
||||
imageView.setImageBitmap(bitmap);
|
||||
shareIconLl.addView(imageView);
|
||||
}
|
||||
}
|
||||
|
||||
if (requestCode == 0x170) { // 发送
|
||||
qrCode.setImageResource(R.drawable.kc_qrcode_120);
|
||||
sendCountTv.setText("成功传送游戏");
|
||||
} else {
|
||||
qrCode.setImageResource(R.drawable.kc_qrcode_110);
|
||||
sendCountTv.setText("成功接收游戏");
|
||||
}
|
||||
|
||||
double size = (((float) filesSize / 1024) / 1024);
|
||||
String sizeName;
|
||||
if (size > 1024) {
|
||||
DecimalFormat df = new DecimalFormat("#.0");
|
||||
sizeName = df.format(size / 1024) + "GB";
|
||||
} else {
|
||||
DecimalFormat df = new DecimalFormat("#.0");
|
||||
sizeName = df.format(size) + "MB";
|
||||
}
|
||||
|
||||
if (sendTime == 0) {
|
||||
sendTime = 1;
|
||||
}
|
||||
|
||||
int i = (filesSize / 1024) / (sendTime / 1000);
|
||||
String speed;
|
||||
if (i >= 1000) {
|
||||
float mSpeed = i / 1024f;
|
||||
DecimalFormat df = new DecimalFormat("#.0");
|
||||
String str = df.format(mSpeed);
|
||||
if (str.length() > 4) {
|
||||
str = str.substring(0, 4);
|
||||
}
|
||||
speed = str + "MB/s";
|
||||
} else {
|
||||
speed = i + "KB/s";
|
||||
}
|
||||
|
||||
if (sendTime > 60000) {
|
||||
timeCount.setText(String.valueOf(sendTime / 1000 / 60));
|
||||
timeTv.setText("分钟传送完成");
|
||||
} else {
|
||||
timeCount.setText(String.valueOf(sendTime / 1000));
|
||||
timeTv.setText("秒传送完成");
|
||||
}
|
||||
|
||||
sizeTv.setText(sizeName);
|
||||
speedTv.setText(speed);
|
||||
countTv.setText(filesCount + "个");
|
||||
|
||||
// 延迟操作,等待截图部分绘制完成
|
||||
handler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mShareLl.setDrawingCacheEnabled(true);
|
||||
mShareLl.buildDrawingCache();
|
||||
Bitmap drawingCache = mShareLl.getDrawingCache();
|
||||
saveBitmap(drawingCache, activity, picName);
|
||||
MessageShareUtils.getInstance(activity).showShareWindows(mShareBottomLl, drawingCache, picName, 2);
|
||||
mShareBottomLl.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}, 200);
|
||||
|
||||
closeIv.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dialog.cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void saveBitmap(Bitmap bm, Activity activity, String picName) {
|
||||
File externalCacheDir = activity.getExternalCacheDir();
|
||||
if (externalCacheDir == null) return;
|
||||
|
||||
File file = new File(externalCacheDir.getPath() + "/ShareImg");
|
||||
if (!file.isDirectory()) {
|
||||
file.delete();
|
||||
file.mkdirs();
|
||||
}
|
||||
if (!file.exists()) {
|
||||
file.mkdirs();
|
||||
}
|
||||
MessageShareUtils.getInstance(activity).writeBitmap(file.getPath(), picName, bm, false);
|
||||
|
||||
}
|
||||
|
||||
public static void showInstallHintDialog(Context context, final ConfirmListener cmListener) {
|
||||
|
||||
|
||||
final Dialog dialog = new Dialog(context);
|
||||
final Dialog dialog = new Dialog(context);
|
||||
|
||||
View view = View.inflate(context, R.layout.dialog_install_hint, null);
|
||||
View view = View.inflate(context, R.layout.dialog_install_hint, null);
|
||||
|
||||
// 标题
|
||||
TextView alertdialog_title = (TextView) view.findViewById(R.id.installhint_title);
|
||||
alertdialog_title.setText("重要提示");
|
||||
Spanned content = Html.fromHtml("如果您使用的是"+ "<font color=\"#ff0000\">华为</font>" +"或"+
|
||||
"<font color=\"#ff0000\">OPPO</font>" +"手机,安装游戏时请选择“" +
|
||||
"<font color=\"#ff0000\">继续安装</font>" +
|
||||
"”(记住不要选择“官方推荐”或“软件商店安装”)");
|
||||
// 内容
|
||||
TextView alertdialog_content = (TextView) view.findViewById(R.id.installhint_content);
|
||||
alertdialog_content.setText(content);
|
||||
// 标题
|
||||
TextView alertdialog_title = (TextView) view.findViewById(R.id.installhint_title);
|
||||
alertdialog_title.setText("重要提示");
|
||||
Spanned content = Html.fromHtml("如果您使用的是" + "<font color=\"#ff0000\">华为</font>" + "或" +
|
||||
"<font color=\"#ff0000\">OPPO</font>" + "手机,安装游戏时请选择“" +
|
||||
"<font color=\"#ff0000\">继续安装</font>" +
|
||||
"”(记住不要选择“官方推荐”或“软件商店安装”)");
|
||||
// 内容
|
||||
TextView alertdialog_content = (TextView) view.findViewById(R.id.installhint_content);
|
||||
alertdialog_content.setText(content);
|
||||
|
||||
// 确定按钮
|
||||
TextView installhint_confirm = (TextView) view.findViewById(R.id.installhint_confirm);
|
||||
installhint_confirm.setText("知道了");
|
||||
// 确定按钮
|
||||
TextView installhint_confirm = (TextView) view.findViewById(R.id.installhint_confirm);
|
||||
installhint_confirm.setText("知道了");
|
||||
|
||||
final ImageView installhint_unselect = (ImageView) view.findViewById(R.id.installhint_unselect);
|
||||
final ImageView installhint_select = (ImageView) view.findViewById(R.id.installhint_select);
|
||||
final ImageView installhint_unselect = (ImageView) view.findViewById(R.id.installhint_unselect);
|
||||
final ImageView installhint_select = (ImageView) view.findViewById(R.id.installhint_select);
|
||||
|
||||
TextView installhint_cancel = (TextView) view.findViewById(R.id.installhint_cancel);
|
||||
LinearLayout installhint_unselect_ll = (LinearLayout) view.findViewById(R.id.installhint_unselect_ll);
|
||||
LinearLayout installhint_unselect_ll = (LinearLayout) view.findViewById(R.id.installhint_unselect_ll);
|
||||
|
||||
installhint_unselect_ll.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (installhint_unselect.getVisibility() == View.GONE) {
|
||||
installhint_unselect.setVisibility(View.VISIBLE);
|
||||
installhint_select.setVisibility(View.GONE);
|
||||
} else {
|
||||
installhint_unselect.setVisibility(View.GONE);
|
||||
installhint_select.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
installhint_unselect_ll.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (installhint_unselect.getVisibility() == View.GONE) {
|
||||
installhint_unselect.setVisibility(View.VISIBLE);
|
||||
installhint_select.setVisibility(View.GONE);
|
||||
} else {
|
||||
installhint_unselect.setVisibility(View.GONE);
|
||||
installhint_select.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
installhint_confirm.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dialog.dismiss();
|
||||
if (installhint_select.getVisibility() == View.VISIBLE) {
|
||||
if (cmListener != null) {
|
||||
cmListener.onConfirem();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
installhint_confirm.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dialog.dismiss();
|
||||
if (installhint_select.getVisibility() == View.VISIBLE) {
|
||||
if (cmListener != null) {
|
||||
cmListener.onConfirm();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
dialog.setOnDismissListener(new Dialog.OnDismissListener() {
|
||||
@Override
|
||||
public void onDismiss(DialogInterface dialog) {
|
||||
isShow = false;
|
||||
}
|
||||
});
|
||||
dialog.setOnDismissListener(new Dialog.OnDismissListener() {
|
||||
@Override
|
||||
public void onDismiss(DialogInterface dialog) {
|
||||
isShow = false;
|
||||
}
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(view);
|
||||
dialog.show();
|
||||
}
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(view);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public static void showHintDialog(Context context, String title, CharSequence msg, String confirm) {
|
||||
final Dialog dialog = new Dialog(context);
|
||||
public static void showHintDialog(Context context, String title, CharSequence msg, String confirm) {
|
||||
final Dialog dialog = new Dialog(context);
|
||||
|
||||
View view = View.inflate(context, R.layout.common_hintdialog, null);
|
||||
View view = View.inflate(context, R.layout.common_hintdialog, null);
|
||||
|
||||
TextView hintdialog_title = (TextView) view.findViewById(R.id.hintdialog_title);
|
||||
hintdialog_title.setText(title);
|
||||
TextView hintdialog_title = (TextView) view.findViewById(R.id.tv_dialog_hint_title);
|
||||
hintdialog_title.setText(title);
|
||||
|
||||
// 内容
|
||||
TextView hintdialog_content = (TextView) view.findViewById(R.id.hintdialog_content);
|
||||
hintdialog_content.setText(msg);
|
||||
// 内容
|
||||
TextView hintdialog_content = (TextView) view.findViewById(R.id.tv_dialog_hint_content);
|
||||
hintdialog_content.setText(msg);
|
||||
|
||||
TextView hintdialog_confirm = (TextView) view.findViewById(R.id.hintdialog_confirm);
|
||||
TextView hintdialog_confirm = (TextView) view.findViewById(R.id.tv_dialog_hint_confirm);
|
||||
|
||||
hintdialog_confirm.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dialog.cancel();
|
||||
}
|
||||
});
|
||||
hintdialog_confirm.setText(confirm);
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(view);
|
||||
dialog.show();
|
||||
}
|
||||
hintdialog_confirm.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dialog.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
public static void showHijackDialog(final Context context) {
|
||||
showWarningDialog(context, "警告", "您当前网络环境异常,下载地址已被替换(网络劫持),请更换网络环境进行下载。",
|
||||
new ConfiremListener() {
|
||||
@Override
|
||||
public void onConfirem() {
|
||||
// 跳转wifi管理界面
|
||||
context.startActivity(new Intent("android.settings.WIFI_SETTINGS"));
|
||||
}
|
||||
});
|
||||
}
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(view);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
// 网络劫持时 打开QQ客户端,创建临时会话
|
||||
public static void showQqSessionDialog(final Context context, String qq) {
|
||||
if (qq == null) {
|
||||
qq = "2586716223";// 默认客服QQ
|
||||
}
|
||||
final String finalQq = qq;
|
||||
showWarningDialog(context, "警告", "您当前网络环境异常,下载地址可能被运营商恶意替换(网络劫持)" +
|
||||
",如多次下载失败,请联系客服获取正确的下载地址(客服QQ:" + qq + ")"
|
||||
, "取消", "前往QQ", new ConfiremListener() {
|
||||
@Override
|
||||
public void onConfirem() {
|
||||
if (ShareUtils.isQQClientAvailable(context)) {
|
||||
//安装了QQ会直接调用QQ,打开手机QQ进行会话 QQ号:2586716223
|
||||
String str = "mqqwpa://im/chat?chat_type=wpa&uin=" + finalQq + "&version=1&src_type=web&web_src=oicqzone.com";
|
||||
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(str)));
|
||||
} else {
|
||||
//没有安装QQ 复制账号
|
||||
ClipboardManager cmb = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
cmb.setText(finalQq);
|
||||
Utils.toast(context, "已复制" + finalQq);
|
||||
}
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
public static void showHijackDialog(final Context context) {
|
||||
showWarningDialog(context, "警告", "您当前网络环境异常,下载地址已被替换(网络劫持),请更换网络环境进行下载。",
|
||||
new ConfirmListener() {
|
||||
@Override
|
||||
public void onConfirm() {
|
||||
// 跳转wifi管理界面
|
||||
context.startActivity(IntentUtils.getWifiIntent());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void showWarningDialog(Context context, String title, CharSequence msg, final ConfirmListener listener) {
|
||||
showWarningDialog(context, title, msg, "取消", "确定", listener, null);
|
||||
}
|
||||
|
||||
public static void showWarningDialog(Context context, String title, CharSequence msg, final ConfiremListener listener) {
|
||||
showWarningDialog(context, title, msg, "取消", "确定", listener, null);
|
||||
}
|
||||
public static void showWarningDialog(Context context, String title, CharSequence msg, String cancel, String confirm,
|
||||
final ConfirmListener cmListener, final CancelListener clListener) {
|
||||
|
||||
public static void showDownloadDialog(Context context, ConfiremListener listener) {
|
||||
showWarningDialog(context, "下载提示", "您当前使用的网络为2G/3G/4G,开始下载将会消耗移动流量,确定下载?", listener);
|
||||
}
|
||||
if (isShow) {
|
||||
return;
|
||||
}
|
||||
isShow = true;
|
||||
|
||||
public static void showCancelDialog(Context context, final ConfiremListener listener) {
|
||||
Spanned content = Html.fromHtml("取消关注游戏后,您将无法及时收到游戏" +
|
||||
"<font color=\"#ff0000\">攻略</font>、" +
|
||||
"<font color=\"#ff0000\">资讯</font>等最新动态提醒。");
|
||||
showWarningDialog(context, "取消关注", content, "暂不取消", "确定取消", listener, null);
|
||||
}
|
||||
final Dialog dialog = new Dialog(context);
|
||||
|
||||
public static void showPluginDialog(Context context, final ConfiremListener listener) {
|
||||
Spanned spanned = Html.fromHtml("您将进行插件化安装以实现插件功能,此过程将"
|
||||
+ "<font color=\"#ff0000\">卸载</font>" + "当前使用的版本并"
|
||||
+ "<font color=\"#ff0000\">安装插件版本</font>");
|
||||
showWarningDialog(context, "插件化安装", spanned, listener);
|
||||
}
|
||||
View view = View.inflate(context, R.layout.common_alertdialog, null);
|
||||
|
||||
public static void showDisclaimerDialog(Context context, String content) {
|
||||
final Dialog disclaimerDialog = new Dialog(context);
|
||||
View view = View.inflate(context, R.layout.dialog_disclaimer, null);
|
||||
// 标题
|
||||
TextView alertdialog_title = (TextView) view.findViewById(R.id.alertdialog_title);
|
||||
alertdialog_title.setText(title);
|
||||
|
||||
// 内容
|
||||
TextView alertdialog_content = (TextView) view.findViewById(R.id.alertdialog_content);
|
||||
alertdialog_content.setText(msg);
|
||||
|
||||
// 取消按钮
|
||||
TextView alertdialog_cannel = (TextView) view.findViewById(R.id.alertdialog_cannel);
|
||||
alertdialog_cannel.setText(cancel);
|
||||
alertdialog_cannel.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dialog.dismiss();
|
||||
if (clListener != null) {
|
||||
clListener.onCancel();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 确定按钮
|
||||
TextView alertdialog_confirm = (TextView) view.findViewById(R.id.alertdialog_confirm);
|
||||
alertdialog_confirm.setText(confirm);
|
||||
alertdialog_confirm.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dialog.dismiss();
|
||||
if (cmListener != null) {
|
||||
cmListener.onConfirm();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
dialog.setOnDismissListener(new Dialog.OnDismissListener() {
|
||||
@Override
|
||||
public void onDismiss(DialogInterface dialog) {
|
||||
isShow = false;
|
||||
}
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(view);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
// 网络劫持时 打开QQ客户端,创建临时会话
|
||||
public static void showQqSessionDialog(final Context context, final String qq) {
|
||||
showWarningDialog(context, "警告", "您当前网络环境异常,下载地址可能被运营商恶意替换(网络劫持)" +
|
||||
",如多次下载失败,请联系客服获取正确的下载地址(客服QQ:" + qq + ")"
|
||||
, "取消", "前往QQ", new ConfirmListener() {
|
||||
@Override
|
||||
public void onConfirm() {
|
||||
QQUtils.startQQSession(context, qq);
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
|
||||
public static void showDownloadDialog(Context context, ConfirmListener listener) {
|
||||
showWarningDialog(context, "下载提示", "您当前使用的网络为2G/3G/4G,开始下载将会消耗移动流量,确定下载?", listener);
|
||||
}
|
||||
|
||||
public static void showCancelDialog(Context context, final ConfirmListener listener) {
|
||||
Spanned content = Html.fromHtml("取消关注游戏后,您将无法及时收到游戏" +
|
||||
"<font color=\"#ff0000\">攻略</font>、" +
|
||||
"<font color=\"#ff0000\">资讯</font>等最新动态提醒。");
|
||||
showWarningDialog(context, "取消关注", content, "暂不取消", "确定取消", listener, null);
|
||||
}
|
||||
|
||||
public static void showPluginDialog(Context context, final ConfirmListener listener) {
|
||||
Spanned spanned = Html.fromHtml("您将进行插件化安装以实现插件功能,此过程将"
|
||||
+ "<font color=\"#ff0000\">卸载</font>" + "当前使用的版本并"
|
||||
+ "<font color=\"#ff0000\">安装插件版本</font>");
|
||||
showWarningDialog(context, "插件化安装", spanned, listener);
|
||||
}
|
||||
|
||||
public static void showDisclaimerDialog(Context context, String content) {
|
||||
final Dialog disclaimerDialog = new Dialog(context);
|
||||
View view = View.inflate(context, R.layout.dialog_disclaimer, null);
|
||||
|
||||
// TextView title = (TextView) view.findViewById(R.id.disclaimer_title);
|
||||
// title.setText("免责声明");
|
||||
|
||||
TextView message = (TextView) view.findViewById(R.id.disclaimer_message);
|
||||
Spanned spanned = Html.fromHtml(content);
|
||||
message.setText(spanned);
|
||||
TextView message = (TextView) view.findViewById(R.id.disclaimer_message);
|
||||
Spanned spanned = Html.fromHtml(content);
|
||||
message.setText(spanned);
|
||||
|
||||
view.findViewById(R.id.disclaimer_confirm).setOnClickListener(
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
disclaimerDialog.dismiss();
|
||||
}
|
||||
});
|
||||
view.findViewById(R.id.disclaimer_confirm).setOnClickListener(
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
disclaimerDialog.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
disclaimerDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
disclaimerDialog.setContentView(view);
|
||||
disclaimerDialog.show();
|
||||
}
|
||||
disclaimerDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
disclaimerDialog.setContentView(view);
|
||||
disclaimerDialog.show();
|
||||
}
|
||||
|
||||
public interface ConfiremListener{
|
||||
void onConfirem();
|
||||
}
|
||||
public interface ConfirmListener {
|
||||
void onConfirm();
|
||||
}
|
||||
|
||||
public interface CancelListener{
|
||||
void onCancel();
|
||||
}
|
||||
public interface CancelListener {
|
||||
void onCancel();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -5,64 +5,63 @@ 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);
|
||||
}
|
||||
/**
|
||||
* 根据手机的分辨率从 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(像素) 的单位 转成为 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 pxValue
|
||||
* (DisplayMetrics类中属性scaledDensity)
|
||||
* @return
|
||||
*/
|
||||
public static int px2sp(Context context, float pxValue) {
|
||||
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
|
||||
return (int) (pxValue / fontScale + 0.5f);
|
||||
}
|
||||
/**
|
||||
* 将px值转换为sp值,保证文字大小不变
|
||||
*
|
||||
* @param pxValue
|
||||
* @param pxValue (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 spValue
|
||||
* (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 resources 资源
|
||||
* @return height
|
||||
*/
|
||||
public static int getStatusBarHeight(Resources resources) {
|
||||
return getInternalDimensionSize(resources, "status_bar_height");
|
||||
}
|
||||
/**
|
||||
* 将sp值转换为px值,保证文字大小不变
|
||||
*
|
||||
* @param spValue
|
||||
* @param spValue (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 resources 资源
|
||||
* @return height
|
||||
*/
|
||||
public static int getStatusBarHeight(Resources resources) {
|
||||
return getInternalDimensionSize(resources, "status_bar_height");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,16 +1,12 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
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.inputmethod.InputMethodManager;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
@ -22,6 +18,7 @@ import com.gh.download.DownloadManager;
|
||||
import com.gh.download.DownloadStatus;
|
||||
import com.gh.gamecenter.DownloadManagerActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.adapter.viewholder.GameViewHolder;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.manager.PackageManager;
|
||||
|
||||
@ -29,476 +26,427 @@ import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
public class DownloadItemUtils {
|
||||
|
||||
// 更新下载进度条
|
||||
public static void processDate(Context context,
|
||||
GameEntity gameEntity,
|
||||
DownloadEntity downloadEntity,
|
||||
RecyclerView.Adapter<RecyclerView.ViewHolder> adapter,
|
||||
int index) {
|
||||
// 更新下载进度条
|
||||
public static void processDate(Context context,
|
||||
GameEntity gameEntity,
|
||||
DownloadEntity downloadEntity,
|
||||
RecyclerView.Adapter<? extends RecyclerView.ViewHolder> adapter,
|
||||
int index) {
|
||||
|
||||
if (!gameEntity.getId().equals(downloadEntity.getGameId())) {
|
||||
adapter.notifyItemChanged(index);
|
||||
return;
|
||||
}
|
||||
if (!gameEntity.getId().equals(downloadEntity.getGameId())) {
|
||||
adapter.notifyItemChanged(index);
|
||||
return;
|
||||
}
|
||||
|
||||
LinkedBlockingQueue<String> queue = DownloadManager.getInstance(context).getQueue(downloadEntity.getName());
|
||||
if (queue == null) {
|
||||
queue = new LinkedBlockingQueue<>();
|
||||
DownloadManager.getInstance(context).putQueue(downloadEntity.getName(), queue);
|
||||
}
|
||||
LinkedBlockingQueue<String> queue = DownloadManager.getInstance(context).getQueue(downloadEntity.getName());
|
||||
if (queue == null) {
|
||||
queue = new LinkedBlockingQueue<>();
|
||||
DownloadManager.getInstance(context).putQueue(downloadEntity.getName(), queue);
|
||||
}
|
||||
|
||||
String platform = downloadEntity.getPlatform();
|
||||
ArrayMap<String, DownloadEntity> entryMap = gameEntity.getEntryMap();
|
||||
String platform = downloadEntity.getPlatform();
|
||||
ArrayMap<String, DownloadEntity> entryMap = gameEntity.getEntryMap();
|
||||
|
||||
DownloadStatus status = downloadEntity.getStatus();
|
||||
if (status.equals(DownloadStatus.pause)
|
||||
|| status.equals(DownloadStatus.cancel)
|
||||
|| status.equals(DownloadStatus.done)) {
|
||||
queue.remove(platform);
|
||||
if (entryMap == null) {
|
||||
entryMap = new ArrayMap<>();
|
||||
gameEntity.setEntryMap(entryMap);
|
||||
}
|
||||
entryMap.put(platform, downloadEntity);
|
||||
if (!"pause".equals(DownloadManager.getInstance(context).getStatus(downloadEntity.getUrl()))) {
|
||||
adapter.notifyItemChanged(index);
|
||||
}
|
||||
} else {
|
||||
if (!queue.contains(platform)) {
|
||||
queue.offer(platform);
|
||||
if (queue.size() == 2) {
|
||||
Message msg = Message.obtain();
|
||||
msg.obj = downloadEntity.getName();
|
||||
msg.what = Constants.DOWNLOAD_ROLL;
|
||||
DownloadManager.getInstance(context).sendMessageDelayed(msg, 3000);
|
||||
}
|
||||
}
|
||||
if (platform.equals(queue.peek())) {
|
||||
if (entryMap == null) {
|
||||
entryMap = new ArrayMap<>();
|
||||
gameEntity.setEntryMap(entryMap);
|
||||
}
|
||||
entryMap.put(platform, downloadEntity);
|
||||
if (!"pause".equals(DownloadManager.getInstance(context).getStatus(downloadEntity.getUrl()))) {
|
||||
adapter.notifyItemChanged(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DownloadStatus status = downloadEntity.getStatus();
|
||||
if (status.equals(DownloadStatus.pause)
|
||||
|| status.equals(DownloadStatus.cancel)
|
||||
|| status.equals(DownloadStatus.done)) {
|
||||
queue.remove(platform);
|
||||
if (entryMap == null) {
|
||||
entryMap = new ArrayMap<>();
|
||||
gameEntity.setEntryMap(entryMap);
|
||||
}
|
||||
entryMap.put(platform, downloadEntity);
|
||||
if (!"pause".equals(DownloadManager.getInstance(context).getStatus(downloadEntity.getUrl()))) {
|
||||
adapter.notifyItemChanged(index);
|
||||
}
|
||||
} else {
|
||||
if (!queue.contains(platform)) {
|
||||
queue.offer(platform);
|
||||
if (queue.size() == 2) {
|
||||
Message msg = Message.obtain();
|
||||
msg.obj = downloadEntity.getName();
|
||||
msg.what = Constants.DOWNLOAD_ROLL;
|
||||
DownloadManager.getInstance(context).sendMessageDelayed(msg, 3000);
|
||||
}
|
||||
}
|
||||
if (platform.equals(queue.peek())) {
|
||||
if (entryMap == null) {
|
||||
entryMap = new ArrayMap<>();
|
||||
gameEntity.setEntryMap(entryMap);
|
||||
}
|
||||
entryMap.put(platform, downloadEntity);
|
||||
if (!"pause".equals(DownloadManager.getInstance(context).getStatus(downloadEntity.getUrl()))) {
|
||||
adapter.notifyItemChanged(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新正常的条目,只有一个apk包
|
||||
public static void updateNormalItem(Context context,
|
||||
TextView textView,
|
||||
ProgressBar game_progressbar,
|
||||
LinearLayout game_ll_info,
|
||||
TextView download_speed,
|
||||
TextView download_percentage,
|
||||
TextView downloadBtn,
|
||||
GameEntity gameEntity,
|
||||
boolean isShowPlatform) {
|
||||
public static void updateItem(Context context, GameEntity gameEntity, GameViewHolder holder, boolean isShowPlatform) {
|
||||
|
||||
ArrayMap<String, DownloadEntity> entryMap = gameEntity.getEntryMap();
|
||||
if (entryMap != null && !entryMap.isEmpty()) {
|
||||
DownloadEntity downloadEntity = entryMap.get(gameEntity.getApk().get(0).getPlatform());
|
||||
if (downloadEntity != null) {
|
||||
// 更改进度条和提示文本的状态
|
||||
changeStatus(context, textView, game_progressbar, game_ll_info, download_speed, download_percentage, downloadBtn,
|
||||
downloadEntity, isShowPlatform, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 控制是否显示下载按钮
|
||||
if (!Config.isShow(context) || "光环助手".equals(gameEntity.getName())) {
|
||||
holder.gameDownloadBtn.setVisibility(View.GONE);
|
||||
} else {
|
||||
holder.gameDownloadBtn.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
textView.setVisibility(View.VISIBLE);
|
||||
game_progressbar.setVisibility(View.GONE);
|
||||
game_ll_info.setVisibility(View.GONE);
|
||||
if (gameEntity.isLibaoExists()) {
|
||||
holder.gameLibaoIcon.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.gameLibaoIcon.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
downloadBtn.setTextColor(Color.WHITE);
|
||||
if (gameEntity.isPluggable()) {
|
||||
downloadBtn.setText("插件化");
|
||||
DownloadEntity downloadEntity = DownloadManager.getInstance(context).getByPackage(
|
||||
gameEntity.getApk().get(0).getPackageName());
|
||||
if (downloadEntity == null
|
||||
|| downloadEntity.getUrl().equals(gameEntity.getApk().get(0).getUrl())) {
|
||||
downloadBtn.setClickable(true);
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_plugin_style);
|
||||
} else {
|
||||
downloadBtn.setClickable(false);
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_pause_up);
|
||||
}
|
||||
} else if (PackageManager.isInstalled(gameEntity.getApk().get(0).getPackageName())) {
|
||||
if (PackageManager.isCanUpdate(gameEntity.getId(), gameEntity.getApk().get(0).getPackageName())) {
|
||||
downloadBtn.setText("更新");
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_download_style);
|
||||
} else {
|
||||
if (gameEntity.getTag() != null && gameEntity.getTag().size() != 0
|
||||
&& !TextUtils.isEmpty(gameEntity.getApk().get(0).getGhVersion())
|
||||
&& !PackageUtils.isSignature(context, gameEntity.getApk().get(0).getPackageName())) {
|
||||
downloadBtn.setText("插件化");
|
||||
DownloadEntity downloadEntity = DownloadManager.getInstance(context).getByPackage(
|
||||
gameEntity.getApk().get(0).getPackageName());
|
||||
if (downloadEntity == null
|
||||
|| downloadEntity.getUrl().equals(gameEntity.getApk().get(0).getUrl())) {
|
||||
downloadBtn.setClickable(true);
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_plugin_style);
|
||||
} else {
|
||||
downloadBtn.setClickable(false);
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_pause_up);
|
||||
}
|
||||
} else {
|
||||
downloadBtn.setText("启动");
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_launch_style);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
downloadBtn.setText("下载");
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_download_style);
|
||||
}
|
||||
}
|
||||
// LibaoDao libaoDao = new LibaoDao(context);
|
||||
// if (libaoDao.isExist(gameEntity.getId())) {
|
||||
// holder.gameLibaoIcon.setVisibility(View.VISIBLE);
|
||||
// } else {
|
||||
//
|
||||
// }
|
||||
|
||||
// 更新插件的条目,有多个apk包
|
||||
public static void updatePluginItem(Context context,
|
||||
TextView textView,
|
||||
ProgressBar game_progressbar,
|
||||
LinearLayout game_ll_info,
|
||||
TextView download_speed,
|
||||
TextView download_percentage,
|
||||
TextView downloadBtn,
|
||||
GameEntity gameEntity,
|
||||
boolean isShowPlatform) {
|
||||
if (gameEntity.getApk() == null || gameEntity.getApk().isEmpty()) {
|
||||
holder.gameDes.setVisibility(View.VISIBLE);
|
||||
holder.gameProgressbar.setVisibility(View.GONE);
|
||||
holder.gameInfo.setVisibility(View.GONE);
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_pause_style);
|
||||
holder.gameDownloadBtn.setText("暂无");
|
||||
holder.gameDownloadBtn.setClickable(false);
|
||||
} else if (gameEntity.getApk().size() == 1) {
|
||||
updateNormalItem(context, holder, gameEntity, isShowPlatform);
|
||||
} else {
|
||||
updatePluginItem(context, holder, gameEntity, isShowPlatform);
|
||||
}
|
||||
|
||||
GameUtils.setDownloadBtnStatus(context, gameEntity, downloadBtn);
|
||||
}
|
||||
|
||||
ArrayMap<String, DownloadEntity> entryMap = gameEntity.getEntryMap();
|
||||
if (entryMap != null && !entryMap.isEmpty()) {
|
||||
// 更新正常的条目,只有一个apk包
|
||||
public static void updateNormalItem(Context context, GameViewHolder holder, GameEntity gameEntity,
|
||||
boolean isShowPlatform) {
|
||||
|
||||
DownloadEntity downloadEntity;
|
||||
ArrayMap<String, DownloadEntity> entryMap = gameEntity.getEntryMap();
|
||||
if (entryMap != null && !entryMap.isEmpty()) {
|
||||
DownloadEntity downloadEntity = entryMap.get(gameEntity.getApk().get(0).getPlatform());
|
||||
if (downloadEntity != null) {
|
||||
// 更改进度条和提示文本的状态
|
||||
changeStatus(context, holder, downloadEntity, isShowPlatform, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LinkedBlockingQueue<String> queue = DownloadManager.getInstance(context).getQueue(gameEntity.getName());
|
||||
if (queue != null && !queue.isEmpty()) {
|
||||
downloadEntity = entryMap.get(queue.peek());
|
||||
} else {
|
||||
downloadEntity = entryMap.get(entryMap.keyAt(0));
|
||||
}
|
||||
holder.gameDes.setVisibility(View.VISIBLE);
|
||||
holder.gameProgressbar.setVisibility(View.GONE);
|
||||
holder.gameInfo.setVisibility(View.GONE);
|
||||
|
||||
if (downloadEntity != null) {
|
||||
// 更改进度条和提示文本的状态
|
||||
changeStatus(context, textView, game_progressbar, game_ll_info, download_speed,
|
||||
download_percentage, downloadBtn, downloadEntity, isShowPlatform, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
holder.gameDownloadBtn.setTextColor(Color.WHITE);
|
||||
if (gameEntity.isPluggable()) {
|
||||
holder.gameDownloadBtn.setText("插件化");
|
||||
DownloadEntity downloadEntity = DownloadManager.getInstance(context).getByPackage(
|
||||
gameEntity.getApk().get(0).getPackageName());
|
||||
if (downloadEntity == null
|
||||
|| downloadEntity.getUrl().equals(gameEntity.getApk().get(0).getUrl())) {
|
||||
holder.gameDownloadBtn.setClickable(true);
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_plugin_style);
|
||||
} else {
|
||||
holder.gameDownloadBtn.setClickable(false);
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_pause_up);
|
||||
}
|
||||
} else if (PackageManager.isInstalled(gameEntity.getApk().get(0).getPackageName())) {
|
||||
if (PackageManager.isCanUpdate(gameEntity.getId(), gameEntity.getApk().get(0).getPackageName())) {
|
||||
holder.gameDownloadBtn.setText("更新");
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_download_style);
|
||||
} else {
|
||||
if (gameEntity.getTag() != null && gameEntity.getTag().size() != 0
|
||||
&& !TextUtils.isEmpty(gameEntity.getApk().get(0).getGhVersion())
|
||||
&& !PackageUtils.isSignature(context, gameEntity.getApk().get(0).getPackageName())) {
|
||||
holder.gameDownloadBtn.setText("插件化");
|
||||
DownloadEntity downloadEntity = DownloadManager.getInstance(context).getByPackage(
|
||||
gameEntity.getApk().get(0).getPackageName());
|
||||
if (downloadEntity == null
|
||||
|| downloadEntity.getUrl().equals(gameEntity.getApk().get(0).getUrl())) {
|
||||
holder.gameDownloadBtn.setClickable(true);
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_plugin_style);
|
||||
} else {
|
||||
holder.gameDownloadBtn.setClickable(false);
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_pause_up);
|
||||
}
|
||||
} else {
|
||||
holder.gameDownloadBtn.setText("启动");
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_launch_style);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
holder.gameDownloadBtn.setText("下载");
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_download_style);
|
||||
}
|
||||
}
|
||||
|
||||
textView.setVisibility(View.VISIBLE);
|
||||
game_progressbar.setVisibility(View.GONE);
|
||||
game_ll_info.setVisibility(View.GONE);
|
||||
}
|
||||
// 更新插件的条目,有多个apk包
|
||||
public static void updatePluginItem(Context context, GameViewHolder holder, GameEntity gameEntity,
|
||||
boolean isShowPlatform) {
|
||||
|
||||
// 更改进度条和提示文本的状态
|
||||
public static void changeStatus(Context context,
|
||||
TextView textView,
|
||||
ProgressBar game_progressbar,
|
||||
LinearLayout game_ll_info,
|
||||
TextView download_speed,
|
||||
TextView download_percentage,
|
||||
TextView downloadBtn,
|
||||
DownloadEntity downloadEntity,
|
||||
boolean isShowPlatform,
|
||||
boolean isNormal) {
|
||||
textView.setVisibility(View.GONE);
|
||||
game_progressbar.setVisibility(View.VISIBLE);
|
||||
game_ll_info.setVisibility(View.VISIBLE);
|
||||
GameUtils.setDownloadBtnStatus(context, gameEntity, holder.gameDownloadBtn);
|
||||
|
||||
String platform = PlatformUtils.getInstance(context)
|
||||
.getPlatformName(downloadEntity.getPlatform());
|
||||
ArrayMap<String, DownloadEntity> entryMap = gameEntity.getEntryMap();
|
||||
if (entryMap != null && !entryMap.isEmpty()) {
|
||||
|
||||
DownloadStatus status = downloadEntity.getStatus();
|
||||
if (status.equals(DownloadStatus.downloading)) {
|
||||
if (!"pause".equals(DownloadManager.getInstance(context).getStatus(downloadEntity.getUrl()))) {
|
||||
game_progressbar.setProgress((int) (downloadEntity.getPercent() * 10));
|
||||
if (isShowPlatform && platform != null) {
|
||||
download_speed.setText(String.format("%s - %s(剩%s)", platform,
|
||||
SpeedUtils.getSpeed(downloadEntity.getSpeed()),
|
||||
SpeedUtils.getRemainTime(downloadEntity.getSize(), downloadEntity.getProgress(), downloadEntity.getSpeed() * 1024)));
|
||||
} else {
|
||||
download_speed.setText(String.format("%s(剩%s)", SpeedUtils.getSpeed(downloadEntity.getSpeed()),
|
||||
SpeedUtils.getRemainTime(downloadEntity.getSize(), downloadEntity.getProgress(), downloadEntity.getSpeed() * 1024)));
|
||||
}
|
||||
download_percentage.setText(downloadEntity.getPercent() + "%");
|
||||
}
|
||||
DownloadEntity downloadEntity;
|
||||
|
||||
if (isNormal) {
|
||||
downloadBtn.setText("下载中");
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_downloading_style);
|
||||
downloadBtn.setTextColor(context.getResources().getColorStateList(R.color.text_downloading_style));
|
||||
}
|
||||
} else if (status.equals(DownloadStatus.waiting)) {
|
||||
game_progressbar.setProgress((int) (downloadEntity.getPercent() * 10));
|
||||
if (isShowPlatform && platform != null) {
|
||||
download_speed.setText(String.format("%s - 等待", platform));
|
||||
} else {
|
||||
download_speed.setText("等待");
|
||||
}
|
||||
download_percentage.setText(downloadEntity.getPercent() + "%");
|
||||
LinkedBlockingQueue<String> queue = DownloadManager.getInstance(context).getQueue(gameEntity.getName());
|
||||
if (queue != null && !queue.isEmpty()) {
|
||||
downloadEntity = entryMap.get(queue.peek());
|
||||
} else {
|
||||
downloadEntity = entryMap.get(entryMap.keyAt(0));
|
||||
}
|
||||
|
||||
if (isNormal) {
|
||||
downloadBtn.setText("下载中");
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_downloading_style);
|
||||
downloadBtn.setTextColor(context.getResources().getColorStateList(R.color.text_downloading_style));
|
||||
}
|
||||
} else if (status.equals(DownloadStatus.pause)
|
||||
|| status.equals(DownloadStatus.timeout)
|
||||
|| status.equals(DownloadStatus.neterror)) {
|
||||
game_progressbar.setProgress((int) (downloadEntity.getPercent() * 10));
|
||||
if (isShowPlatform && platform != null) {
|
||||
download_speed.setText(String.format("%s - 暂停", platform));
|
||||
} else {
|
||||
download_speed.setText("暂停");
|
||||
}
|
||||
download_percentage.setText(downloadEntity.getPercent() + "%");
|
||||
if (downloadEntity != null) {
|
||||
// 更改进度条和提示文本的状态
|
||||
changeStatus(context, holder, downloadEntity, isShowPlatform, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isNormal) {
|
||||
downloadBtn.setText("下载中");
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_downloading_style);
|
||||
downloadBtn.setTextColor(context.getResources().getColorStateList(R.color.text_downloading_style));
|
||||
}
|
||||
} else if (status.equals(DownloadStatus.done)) {
|
||||
game_progressbar.setProgress(1000);
|
||||
if (isShowPlatform && platform != null) {
|
||||
download_speed.setText(String.format("%s - 下载完成", platform));
|
||||
} else {
|
||||
download_speed.setText("下载完成");
|
||||
}
|
||||
download_percentage.setText(R.string.hundred_percent);
|
||||
holder.gameDes.setVisibility(View.VISIBLE);
|
||||
holder.gameProgressbar.setVisibility(View.GONE);
|
||||
holder.gameInfo.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (isNormal) {
|
||||
downloadBtn.setText("安装");
|
||||
downloadBtn.setTextColor(Color.WHITE);
|
||||
if (downloadEntity.isPluggable()
|
||||
&& PackageManager.isInstalled(downloadEntity.getPackageName())) {
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_plugin_style);
|
||||
} else {
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_download_style);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 更改进度条和提示文本的状态
|
||||
public static void changeStatus(Context context, GameViewHolder holder, DownloadEntity downloadEntity,
|
||||
boolean isShowPlatform, boolean isNormal) {
|
||||
holder.gameDes.setVisibility(View.GONE);
|
||||
holder.gameProgressbar.setVisibility(View.VISIBLE);
|
||||
holder.gameInfo.setVisibility(View.VISIBLE);
|
||||
|
||||
public static void updateItem(Context context,
|
||||
TextView textView,
|
||||
ProgressBar game_progressbar,
|
||||
LinearLayout game_ll_info,
|
||||
TextView download_speed,
|
||||
TextView download_percentage,
|
||||
TextView downloadBtn,
|
||||
GameEntity entity,
|
||||
boolean isShowPlatform) {
|
||||
String platform = PlatformUtils.getInstance(context)
|
||||
.getPlatformName(downloadEntity.getPlatform());
|
||||
|
||||
// 控制是否显示下载按钮
|
||||
if (!Config.isShow(context) || "光环助手".equals(entity.getName())) {
|
||||
downloadBtn.setVisibility(View.GONE);
|
||||
} else {
|
||||
downloadBtn.setVisibility(View.VISIBLE);
|
||||
}
|
||||
DownloadStatus status = downloadEntity.getStatus();
|
||||
if (status.equals(DownloadStatus.downloading)) {
|
||||
if (!"pause".equals(DownloadManager.getInstance(context).getStatus(downloadEntity.getUrl()))) {
|
||||
holder.gameProgressbar.setProgress((int) (downloadEntity.getPercent() * 10));
|
||||
if (isShowPlatform && platform != null) {
|
||||
holder.gameDownloadSpeed.setText(String.format("%s - %s(剩%s)", platform,
|
||||
SpeedUtils.getSpeed(downloadEntity.getSpeed()),
|
||||
SpeedUtils.getRemainTime(downloadEntity.getSize(), downloadEntity.getProgress(), downloadEntity.getSpeed() * 1024)));
|
||||
} else {
|
||||
holder.gameDownloadSpeed.setText(String.format("%s(剩%s)", SpeedUtils.getSpeed(downloadEntity.getSpeed()),
|
||||
SpeedUtils.getRemainTime(downloadEntity.getSize(), downloadEntity.getProgress(), downloadEntity.getSpeed() * 1024)));
|
||||
}
|
||||
holder.gameDownloadPercentage.setText(downloadEntity.getPercent() + "%");
|
||||
}
|
||||
|
||||
if (entity.getApk() == null || entity.getApk().isEmpty()) {
|
||||
textView.setVisibility(View.VISIBLE);
|
||||
game_progressbar.setVisibility(View.GONE);
|
||||
game_ll_info.setVisibility(View.GONE);
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_pause_style);
|
||||
downloadBtn.setText("暂无");
|
||||
downloadBtn.setClickable(false);
|
||||
} else if (entity.getApk().size() == 1) {
|
||||
updateNormalItem(context, textView, game_progressbar, game_ll_info, download_speed,
|
||||
download_percentage, downloadBtn, entity, isShowPlatform);
|
||||
} else {
|
||||
updatePluginItem(context, textView, game_progressbar, game_ll_info, download_speed,
|
||||
download_percentage, downloadBtn, entity, isShowPlatform);
|
||||
}
|
||||
if (isNormal) {
|
||||
holder.gameDownloadBtn.setText("下载中");
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_downloading_style);
|
||||
holder.gameDownloadBtn.setTextColor(context.getResources().getColorStateList(R.color.text_downloading_style));
|
||||
}
|
||||
} else if (status.equals(DownloadStatus.waiting)) {
|
||||
holder.gameProgressbar.setProgress((int) (downloadEntity.getPercent() * 10));
|
||||
if (isShowPlatform && platform != null) {
|
||||
holder.gameDownloadSpeed.setText(String.format("%s - 等待", platform));
|
||||
} else {
|
||||
holder.gameDownloadSpeed.setText("等待");
|
||||
}
|
||||
holder.gameDownloadPercentage.setText(downloadEntity.getPercent() + "%");
|
||||
|
||||
}
|
||||
if (isNormal) {
|
||||
holder.gameDownloadBtn.setText("下载中");
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_downloading_style);
|
||||
holder.gameDownloadBtn.setTextColor(context.getResources().getColorStateList(R.color.text_downloading_style));
|
||||
}
|
||||
} else if (status.equals(DownloadStatus.pause)
|
||||
|| status.equals(DownloadStatus.timeout)
|
||||
|| status.equals(DownloadStatus.neterror)) {
|
||||
holder.gameProgressbar.setProgress((int) (downloadEntity.getPercent() * 10));
|
||||
if (isShowPlatform && platform != null) {
|
||||
holder.gameDownloadSpeed.setText(String.format("%s - 暂停", platform));
|
||||
} else {
|
||||
holder.gameDownloadSpeed.setText("暂停");
|
||||
}
|
||||
holder.gameDownloadPercentage.setText(downloadEntity.getPercent() + "%");
|
||||
|
||||
public static void updateItem(Context context,
|
||||
TextView textView,
|
||||
ProgressBar game_progressbar,
|
||||
LinearLayout game_ll_info,
|
||||
TextView download_speed,
|
||||
TextView download_percentage,
|
||||
TextView downloadBtn,
|
||||
GameEntity entity) {
|
||||
updateItem(context, textView, game_progressbar, game_ll_info, download_speed,
|
||||
download_percentage, downloadBtn, entity, true);
|
||||
}
|
||||
if (isNormal) {
|
||||
holder.gameDownloadBtn.setText("下载中");
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_downloading_style);
|
||||
holder.gameDownloadBtn.setTextColor(context.getResources().getColorStateList(R.color.text_downloading_style));
|
||||
}
|
||||
} else if (status.equals(DownloadStatus.done)) {
|
||||
holder.gameProgressbar.setProgress(1000);
|
||||
if (isShowPlatform && platform != null) {
|
||||
holder.gameDownloadSpeed.setText(String.format("%s - 下载完成", platform));
|
||||
} else {
|
||||
holder.gameDownloadSpeed.setText("下载完成");
|
||||
}
|
||||
holder.gameDownloadPercentage.setText(R.string.hundred_percent);
|
||||
|
||||
private static void setNormalOnClickListener(final Context context,
|
||||
final TextView downloadBtn,
|
||||
final GameEntity gameEntity,
|
||||
final int position,
|
||||
final RecyclerView.Adapter<RecyclerView.ViewHolder> adapter,
|
||||
final String entrance,
|
||||
final String location) {
|
||||
downloadBtn.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
String str = downloadBtn.getText().toString();
|
||||
if ("下载".equals(str)) {
|
||||
if (NetworkUtils.isWifiConnected(context)) {
|
||||
download(context, gameEntity, downloadBtn, entrance, location);
|
||||
} else {
|
||||
DialogUtils.showDownloadDialog(context, new DialogUtils.ConfiremListener() {
|
||||
@Override
|
||||
public void onConfirem() {
|
||||
download(context, gameEntity, downloadBtn, entrance, location);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if ("插件化".equals(str)) {
|
||||
if (NetworkUtils.isWifiConnected(context)) {
|
||||
plugin(context, gameEntity, downloadBtn, entrance, location);
|
||||
} else {
|
||||
DialogUtils.showDownloadDialog(context, new DialogUtils.ConfiremListener() {
|
||||
@Override
|
||||
public void onConfirem() {
|
||||
plugin(context, gameEntity, downloadBtn, entrance, location);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if ("安装".equals(str)) {
|
||||
install(context, gameEntity, position, adapter);
|
||||
} else if ("启动".equals(str)) {
|
||||
DataUtils.onGameLaunchEvent(context, gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), location);
|
||||
if (isNormal) {
|
||||
holder.gameDownloadBtn.setText("安装");
|
||||
holder.gameDownloadBtn.setTextColor(Color.WHITE);
|
||||
if (downloadEntity.isPluggable()
|
||||
&& PackageManager.isInstalled(downloadEntity.getPackageName())) {
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_plugin_style);
|
||||
} else {
|
||||
holder.gameDownloadBtn.setBackgroundResource(R.drawable.game_item_btn_download_style);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PackageUtils.launchApplicationByPackageName(context, gameEntity.getApk().get(0).getPackageName());
|
||||
} else if ("下载中".equals(str)) {
|
||||
Intent intent = new Intent(context, DownloadManagerActivity.class);
|
||||
intent.putExtra("url", gameEntity.getApk().get(0).getUrl());
|
||||
intent.putExtra("entrance", entrance + "+(" + location.split(":")[0] + ")");
|
||||
context.startActivity(intent);
|
||||
} else if ("更新".equals(str)) {
|
||||
if (NetworkUtils.isWifiConnected(context)) {
|
||||
update(context, gameEntity, entrance, location);
|
||||
} else {
|
||||
DialogUtils.showDownloadDialog(context, new DialogUtils.ConfiremListener() {
|
||||
@Override
|
||||
public void onConfirem() {
|
||||
update(context, gameEntity, entrance, location);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
public static void setOnClickListener(final Context context,
|
||||
final TextView downloadBtn,
|
||||
final GameEntity gameEntity,
|
||||
final int position,
|
||||
final RecyclerView.Adapter<? extends RecyclerView.ViewHolder> adapter,
|
||||
final String entrance,
|
||||
final String location) {
|
||||
|
||||
private static void setPluginOnClickListener(final Context context,
|
||||
final TextView downloadBtn,
|
||||
final GameEntity entity,
|
||||
final String entrance,
|
||||
final String location,
|
||||
final boolean isCloseSoftInput) {
|
||||
downloadBtn.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View v) {
|
||||
if (isCloseSoftInput) {
|
||||
InputMethodManager imm = (InputMethodManager) context
|
||||
.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
|
||||
}
|
||||
DownloadDialog.getInstance(context).showPopupWindow(v, entity, entrance, location);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
downloadBtn.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
onNormalClick(context, downloadBtn, gameEntity, position, adapter, entrance, location);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
downloadBtn.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
DownloadDialog.getInstance(context).showPopupWindow(v, gameEntity, entrance, location);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void setOnClickListener(Context context,
|
||||
TextView downloadBtn,
|
||||
GameEntity gameEntity,
|
||||
int position,
|
||||
RecyclerView.Adapter<RecyclerView.ViewHolder> adapter,
|
||||
String entrance,
|
||||
String location,
|
||||
boolean isCloseSoftInput) {
|
||||
}
|
||||
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
setNormalOnClickListener(context, downloadBtn, gameEntity, position, adapter, entrance, location);
|
||||
} else {
|
||||
setPluginOnClickListener(context, downloadBtn, gameEntity, entrance, location, isCloseSoftInput);
|
||||
}
|
||||
public static void onNormalClick(final Context context,
|
||||
final TextView downloadBtn,
|
||||
final GameEntity gameEntity,
|
||||
final int position,
|
||||
final RecyclerView.Adapter<? extends RecyclerView.ViewHolder> adapter,
|
||||
final String entrance,
|
||||
final String location) {
|
||||
|
||||
}
|
||||
String str = downloadBtn.getText().toString();
|
||||
if ("下载".equals(str)) {
|
||||
if (NetworkUtils.isWifiConnected(context)) {
|
||||
download(context, gameEntity, downloadBtn, entrance, location);
|
||||
} else {
|
||||
DialogUtils.showDownloadDialog(context, new DialogUtils.ConfirmListener() {
|
||||
@Override
|
||||
public void onConfirm() {
|
||||
download(context, gameEntity, downloadBtn, entrance, location);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if ("插件化".equals(str)) {
|
||||
if (NetworkUtils.isWifiConnected(context)) {
|
||||
plugin(context, gameEntity, downloadBtn, entrance, location);
|
||||
} else {
|
||||
DialogUtils.showDownloadDialog(context, new DialogUtils.ConfirmListener() {
|
||||
@Override
|
||||
public void onConfirm() {
|
||||
plugin(context, gameEntity, downloadBtn, entrance, location);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if ("安装".equals(str)) {
|
||||
install(context, gameEntity, position, adapter);
|
||||
} else if ("启动".equals(str)) {
|
||||
DataUtils.onGameLaunchEvent(context, gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), location);
|
||||
|
||||
//更新
|
||||
private static void update(Context context,
|
||||
GameEntity gameEntity,
|
||||
String entrance,
|
||||
String location) {
|
||||
DataUtils.onGameUpdateEvent(context, gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), "下载开始");
|
||||
DownloadManager.createDownload(context, gameEntity, "更新", entrance, location);
|
||||
}
|
||||
PackageUtils.launchApplicationByPackageName(context, gameEntity.getApk().get(0).getPackageName());
|
||||
} else if ("下载中".equals(str)) {
|
||||
context.startActivity(
|
||||
DownloadManagerActivity.getDownloadMangerIntent(context, gameEntity.getApk().get(0).getUrl(), entrance + "+(" + location.split(":")[0] + ")"));
|
||||
} else if ("更新".equals(str)) {
|
||||
if (NetworkUtils.isWifiConnected(context)) {
|
||||
update(context, gameEntity, entrance, location);
|
||||
} else {
|
||||
DialogUtils.showDownloadDialog(context, new DialogUtils.ConfirmListener() {
|
||||
@Override
|
||||
public void onConfirm() {
|
||||
update(context, gameEntity, entrance, location);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//下载
|
||||
private static void download(Context context,
|
||||
GameEntity gameEntity,
|
||||
TextView downloadBtn,
|
||||
String entrance,
|
||||
String location) {
|
||||
String msg = FileUtils.isCanDownload(context, gameEntity.getApk().get(0).getSize());
|
||||
if (TextUtils.isEmpty(msg)) {
|
||||
DataUtils.onGameDownloadEvent(context, gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), entrance, "下载开始");
|
||||
//下载
|
||||
private static void download(Context context,
|
||||
GameEntity gameEntity,
|
||||
TextView downloadBtn,
|
||||
String entrance,
|
||||
String location) {
|
||||
String msg = FileUtils.isCanDownload(context, gameEntity.getApk().get(0).getSize());
|
||||
if (TextUtils.isEmpty(msg)) {
|
||||
DataUtils.onGameDownloadEvent(context, gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), entrance, "下载开始");
|
||||
|
||||
DownloadManager.createDownload(context, gameEntity, "下载", entrance, location);
|
||||
Toast.makeText(context, gameEntity.getName() + "已加入下载队列", Toast.LENGTH_SHORT).show();
|
||||
DownloadManager.createDownload(context, gameEntity, "下载", entrance, location);
|
||||
Toast.makeText(context, gameEntity.getName() + "已加入下载队列", Toast.LENGTH_SHORT).show();
|
||||
|
||||
downloadBtn.setText("下载中");
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_downloading_style);
|
||||
downloadBtn.setTextColor(context.getResources().getColorStateList(R.color.text_downloading_style));
|
||||
downloadBtn.setText("下载中");
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_downloading_style);
|
||||
downloadBtn.setTextColor(context.getResources().getColorStateList(R.color.text_downloading_style));
|
||||
|
||||
DownloadManager.getInstance(context).putStatus(gameEntity.getApk().get(0).getUrl(), "downloading");
|
||||
} else {
|
||||
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
DownloadManager.getInstance(context).putStatus(gameEntity.getApk().get(0).getUrl(), "downloading");
|
||||
} else {
|
||||
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
//插件化
|
||||
private static void plugin(Context context,
|
||||
GameEntity gameEntity,
|
||||
TextView downloadBtn,
|
||||
String entrance,
|
||||
String location) {
|
||||
String msg = FileUtils.isCanDownload(context, gameEntity.getApk().get(0).getSize());
|
||||
if (TextUtils.isEmpty(msg)) {
|
||||
DataUtils.onGameDownloadEvent(context, gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), entrance, "下载开始");
|
||||
//插件化
|
||||
private static void plugin(Context context,
|
||||
GameEntity gameEntity,
|
||||
TextView downloadBtn,
|
||||
String entrance,
|
||||
String location) {
|
||||
String msg = FileUtils.isCanDownload(context, gameEntity.getApk().get(0).getSize());
|
||||
if (TextUtils.isEmpty(msg)) {
|
||||
DataUtils.onGameDownloadEvent(context, gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), entrance, "下载开始");
|
||||
|
||||
DownloadManager.createDownload(context, gameEntity, "插件化", entrance, location);
|
||||
Toast.makeText(context, gameEntity.getName() + "已加入下载队列", Toast.LENGTH_SHORT).show();
|
||||
DownloadManager.createDownload(context, gameEntity, "插件化", entrance, location);
|
||||
Toast.makeText(context, gameEntity.getName() + "已加入下载队列", Toast.LENGTH_SHORT).show();
|
||||
|
||||
downloadBtn.setText("下载中");
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_downloading_style);
|
||||
downloadBtn.setTextColor(context.getResources().getColorStateList(R.color.text_downloading_style));
|
||||
downloadBtn.setText("下载中");
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_downloading_style);
|
||||
downloadBtn.setTextColor(context.getResources().getColorStateList(R.color.text_downloading_style));
|
||||
|
||||
DownloadManager.getInstance(context).putStatus(gameEntity.getApk().get(0).getUrl(), "downloading");
|
||||
} else {
|
||||
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
DownloadManager.getInstance(context).putStatus(gameEntity.getApk().get(0).getUrl(), "downloading");
|
||||
} else {
|
||||
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
//安装
|
||||
private static void install(final Context context,
|
||||
GameEntity gameEntity,
|
||||
int position,
|
||||
RecyclerView.Adapter<RecyclerView.ViewHolder> adapter) {
|
||||
DownloadEntity downloadEntity = DownloadManager.getInstance(context).get(gameEntity.getApk().get(0).getUrl());
|
||||
if (downloadEntity != null) {
|
||||
final String path = downloadEntity.getPath();
|
||||
if (FileUtils.isEmptyFile(path)) {
|
||||
Toast.makeText(context, "解析包出错(可能被误删了),请重新下载", Toast.LENGTH_SHORT).show();
|
||||
DownloadManager.getInstance(context).cancel(downloadEntity.getUrl());
|
||||
if (gameEntity.getEntryMap() != null) {
|
||||
gameEntity.getEntryMap().remove(gameEntity.getApk().get(0).getPlatform());
|
||||
}
|
||||
adapter.notifyItemChanged(position);
|
||||
} else {
|
||||
PackageUtils.launchSetup(context, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
//安装
|
||||
private static void install(final Context context,
|
||||
GameEntity gameEntity,
|
||||
int position,
|
||||
RecyclerView.Adapter<? extends RecyclerView.ViewHolder> adapter) {
|
||||
DownloadEntity downloadEntity = DownloadManager.getInstance(context).get(gameEntity.getApk().get(0).getUrl());
|
||||
if (downloadEntity != null) {
|
||||
final String path = downloadEntity.getPath();
|
||||
if (FileUtils.isEmptyFile(path)) {
|
||||
Toast.makeText(context, "解析包出错(可能被误删了),请重新下载", Toast.LENGTH_SHORT).show();
|
||||
DownloadManager.getInstance(context).cancel(downloadEntity.getUrl());
|
||||
if (gameEntity.getEntryMap() != null) {
|
||||
gameEntity.getEntryMap().remove(gameEntity.getApk().get(0).getPlatform());
|
||||
}
|
||||
adapter.notifyItemChanged(position);
|
||||
} else {
|
||||
PackageUtils.launchSetup(context, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//更新
|
||||
private static void update(Context context,
|
||||
GameEntity gameEntity,
|
||||
String entrance,
|
||||
String location) {
|
||||
DataUtils.onGameUpdateEvent(context, gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), "下载开始");
|
||||
DownloadManager.createDownload(context, gameEntity, "更新", entrance, location);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
70
app/src/main/java/com/gh/common/util/EntranceUtils.java
Normal file
70
app/src/main/java/com/gh/common/util/EntranceUtils.java
Normal file
@ -0,0 +1,70 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.gh.gamecenter.MainActivity;
|
||||
import com.gh.gamecenter.SplashScreenActivity;
|
||||
|
||||
/**
|
||||
* @author CsHeng
|
||||
* @Date 2017/4/25
|
||||
* @Time 16:39
|
||||
*/
|
||||
|
||||
public class EntranceUtils {
|
||||
|
||||
public static final String KEY_TO = "to";
|
||||
public static final String KEY_NEWSID = "newsId";
|
||||
public static final String KEY_GAMEID = "gameId";
|
||||
public static final String KEY_ID = "id";
|
||||
public static final String KEY_URL = "url";
|
||||
public static final String HOST_ARTICLE = "article";
|
||||
public static final String HOST_GAME = "game";
|
||||
public static final String HOSt_COLUMN = "column";
|
||||
public static final String HOST_WEB = "web";
|
||||
public static final String HOST_DOWNLOAD = "download";
|
||||
public static final String HOST_SUGGESTION = "suggestion";
|
||||
public static final String KEY_DATA = "data";
|
||||
public static final String KEY_TYPE = "type";
|
||||
public static final String KEY_NAME = "name";
|
||||
public static final String KEY_ENTRANCE = "entrance";
|
||||
public static final String KEY_TARGET = "target";
|
||||
public static final String ENTRANCE_BROWSER = "(浏览器)";
|
||||
public static final String ENTRANCE_UMENG = "(友盟推送)";
|
||||
public static final String ENTRANCE_MIPUSH = "(小米推送)";
|
||||
public static final String ENTRANCE_DOWNLOAD = "(下载跳转)";
|
||||
public static final String KEY_SUGGEST_HINT_TYPE = "suggestHintType";
|
||||
public static final String KEY_PACKAGENAME = "packageName";
|
||||
public static final String KEY_PLATFORM = "platform";
|
||||
public static final String KEY_GAME_NAME = "game_name";
|
||||
public static final String KEY_VERSION = "version";
|
||||
public static final String KEY_CONTENT = "content";
|
||||
public static final String KEY_PLUGIN = "plugin";
|
||||
public static final String KEY_CURRENT_ITEM = "currentItem";
|
||||
|
||||
public static void jumpActivity(Context context, Bundle bundle) {
|
||||
|
||||
//TODO 把其他类似的跳转启动逻辑也处理掉
|
||||
if (RunningUtils.isRunning(context)
|
||||
&& MainActivity.class.getName().equals(RunningUtils.getBaseActivity(context))) {
|
||||
// 应用正在运行,前台或后台
|
||||
String to = bundle.getString(KEY_TO);
|
||||
if (!TextUtils.isEmpty(to)) {
|
||||
Class<?> clazz = ClassUtils.forName(to);
|
||||
if (clazz != null) {
|
||||
Intent intent1 = new Intent(context, clazz);
|
||||
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent1.putExtra(KEY_DATA, bundle);
|
||||
context.startActivity(intent1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 应用未在运行
|
||||
context.startActivity(SplashScreenActivity.getSplashScreenIntent(context, bundle));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -21,7 +21,6 @@ import java.net.URL;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author guanchao wen
|
||||
* @email shuwoom.wgc@gmail.com
|
||||
* @modify hzh 2016/03/16
|
||||
@ -29,356 +28,356 @@ import java.util.UUID;
|
||||
*/
|
||||
public class FileUtils {
|
||||
|
||||
private final static String TEST_FILE_NAME = System.currentTimeMillis() + ".log";
|
||||
private final static String TEST_FILE_NAME = System.currentTimeMillis() + ".log";
|
||||
|
||||
public static String getDownloadDir(Context context) {
|
||||
String dir = null;
|
||||
if (isMounted()) {
|
||||
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
|
||||
dir = checkDir(baseDir + File.separator + "gh-download");
|
||||
File file = new File(dir + File.separator + TEST_FILE_NAME);
|
||||
if (!file.exists()) {
|
||||
try {
|
||||
if (!file.createNewFile()) {
|
||||
// cannot create file
|
||||
Utils.log("cannot create file");
|
||||
dir = null;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
// cannot create file
|
||||
Utils.log("cannot create file");
|
||||
dir = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dir == null) {
|
||||
String baseDir = context.getFilesDir().getAbsolutePath();
|
||||
dir = checkDir(baseDir + File.separator + "gh-download");
|
||||
try {
|
||||
Runtime.getRuntime().exec("chmod 755 " + dir);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
public static String getDownloadPath(Context context, String name) {
|
||||
return getDownloadDir(context) + File.separator + name;
|
||||
}
|
||||
|
||||
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 getDownloadDir(Context context) {
|
||||
String dir = null;
|
||||
if (isMounted()) {
|
||||
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
|
||||
dir = checkDir(baseDir + File.separator + "gh-download");
|
||||
File file = new File(dir + File.separator + TEST_FILE_NAME);
|
||||
if (!file.exists()) {
|
||||
try {
|
||||
if (!file.createNewFile()) {
|
||||
// cannot create file
|
||||
Utils.log("cannot create file");
|
||||
dir = null;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
// cannot create file
|
||||
Utils.log("cannot create file");
|
||||
dir = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dir == null) {
|
||||
String baseDir = context.getFilesDir().getAbsolutePath();
|
||||
dir = checkDir(baseDir + File.separator + "gh-download");
|
||||
try {
|
||||
Runtime.getRuntime().exec("chmod 755 " + dir);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
public static String getPlatformPicDir(Context context) {
|
||||
return checkDir(getDir(context, "PlatformPic"));
|
||||
}
|
||||
|
||||
private static String checkDir(String dir) {
|
||||
File directory = new File(dir);
|
||||
if (directory.exists() && !directory.isDirectory()) {
|
||||
directory.delete();
|
||||
}
|
||||
if (!directory.exists()) {
|
||||
directory.mkdirs();
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
public static boolean isMounted() {
|
||||
return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
|
||||
}
|
||||
|
||||
public static void deleteFile(String savePath) {
|
||||
File file = new File(savePath);
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
private static String checkDir(String dir) {
|
||||
File directory = new File(dir);
|
||||
if (directory.exists() && !directory.isDirectory()) {
|
||||
directory.delete();
|
||||
}
|
||||
if (!directory.exists()) {
|
||||
directory.mkdirs();
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
public static 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();
|
||||
}
|
||||
}
|
||||
public static String getLogPath(Context context, String name) {
|
||||
return checkDir(getDir(context, "log")) + File.separator + name;
|
||||
}
|
||||
|
||||
public static boolean isEmptyFile(String path) {
|
||||
File file = new File(path);
|
||||
return !(file.exists() && file.length() != 0);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
public static boolean isMounted() {
|
||||
return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
|
||||
}
|
||||
public static String getPlatformPicDir(Context context) {
|
||||
return checkDir(getDir(context, "PlatformPic"));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
public static void deleteFile(String savePath) {
|
||||
File file = new File(savePath);
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
// 返回剩余空间 单位MB
|
||||
@SuppressWarnings("deprecation")
|
||||
public static float getFreeSpaceByPath(String path) {
|
||||
StatFs statfs = new StatFs(path);
|
||||
long blockSize = statfs.getBlockSize();
|
||||
long availableBlocks = statfs.getAvailableBlocks();
|
||||
public static 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();
|
||||
}
|
||||
}
|
||||
|
||||
return availableBlocks * blockSize / 1024f / 1024f;
|
||||
}
|
||||
public static boolean isEmptyFile(String path) {
|
||||
File file = new File(path);
|
||||
return !(file.exists() && file.length() != 0);
|
||||
}
|
||||
|
||||
public static String isCanDownload(Context context, 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(getDownloadDir(context));
|
||||
if (freeSpace < packageSize) {
|
||||
msg = "手机存储空间不足,无法进行下载!";
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
public static String isCanDownload(Context context, 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(getDownloadDir(context));
|
||||
if (freeSpace < packageSize) {
|
||||
msg = "手机存储空间不足,无法进行下载!";
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
// 下载文件
|
||||
public static int downloadFile(String url, String savePath) {
|
||||
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();
|
||||
}
|
||||
return code;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (fos != null) {
|
||||
try {
|
||||
fos.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (dis != null) {
|
||||
try {
|
||||
dis.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
// 返回剩余空间 单位MB
|
||||
@SuppressWarnings("deprecation")
|
||||
public static float getFreeSpaceByPath(String path) {
|
||||
StatFs statfs = new StatFs(path);
|
||||
long blockSize = statfs.getBlockSize();
|
||||
long availableBlocks = statfs.getAvailableBlocks();
|
||||
|
||||
// 上传文件
|
||||
public static JSONObject 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
|
||||
return availableBlocks * blockSize / 1024f / 1024f;
|
||||
}
|
||||
|
||||
// 下载文件
|
||||
public static int downloadFile(String url, String savePath) {
|
||||
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();
|
||||
}
|
||||
return code;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (fos != null) {
|
||||
try {
|
||||
fos.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (dis != null) {
|
||||
try {
|
||||
dis.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 上传文件
|
||||
public static JSONObject 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.setConnectTimeout(5 * 1000);
|
||||
connection.setReadTimeout(5 * 1000);
|
||||
// 设置请求属性
|
||||
connection.setRequestProperty("Connection", "Keep-Alive");
|
||||
connection.setRequestProperty("Charset", "UTF-8");
|
||||
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
|
||||
if (token != null) {
|
||||
connection.setRequestProperty("TOKEN", 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;
|
||||
// 从文件读取数据至缓冲区
|
||||
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.flush();
|
||||
dos.close();
|
||||
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.setConnectTimeout(5 * 1000);
|
||||
connection.setReadTimeout(5 * 1000);
|
||||
// 设置请求属性
|
||||
connection.setRequestProperty("Connection", "Keep-Alive");
|
||||
connection.setRequestProperty("Charset", "UTF-8");
|
||||
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
|
||||
if (token != null) {
|
||||
connection.setRequestProperty("TOKEN", 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;
|
||||
// 从文件读取数据至缓冲区
|
||||
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.flush();
|
||||
dos.close();
|
||||
|
||||
InputStream inputStream;
|
||||
try {
|
||||
inputStream = connection.getInputStream();
|
||||
} catch (IOException ioe) {
|
||||
inputStream = connection.getErrorStream();
|
||||
}
|
||||
int ch;
|
||||
StringBuffer b = new StringBuffer();
|
||||
while ((ch = inputStream.read()) != -1) {
|
||||
b.append((char) ch);
|
||||
}
|
||||
// 显示网页响应内容
|
||||
Utils.log("content = " + b.toString().trim());
|
||||
InputStream inputStream;
|
||||
try {
|
||||
inputStream = connection.getInputStream();
|
||||
} catch (IOException ioe) {
|
||||
inputStream = connection.getErrorStream();
|
||||
}
|
||||
int ch;
|
||||
StringBuffer b = new StringBuffer();
|
||||
while ((ch = inputStream.read()) != -1) {
|
||||
b.append((char) ch);
|
||||
}
|
||||
// 显示网页响应内容
|
||||
Utils.log("content = " + b.toString().trim());
|
||||
|
||||
int statusCode = connection.getResponseCode();
|
||||
Utils.log("statusCode = " + statusCode);
|
||||
if (statusCode == 200) {
|
||||
// {"icon":"http:\/\/gh-test-1.oss-cn-qingdao.aliyuncs.com\/pic\/57e4f4d58a3200042d29492f.jpg"}
|
||||
JSONObject response = new JSONObject(b.toString().trim());
|
||||
response.put("statusCode", 200);
|
||||
return response;
|
||||
} else if (statusCode == 403) {
|
||||
JSONObject response = new JSONObject(b.toString().trim());
|
||||
response.put("statusCode", 403);
|
||||
return response;
|
||||
} else if (statusCode == 401) {
|
||||
JSONObject response = new JSONObject();
|
||||
response.put("statusCode", 401);
|
||||
return response;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 显示异常信息
|
||||
e.printStackTrace();
|
||||
Utils.log("Fail:" + e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
int statusCode = connection.getResponseCode();
|
||||
Utils.log("statusCode = " + statusCode);
|
||||
if (statusCode == 200) {
|
||||
// {"icon":"http:\/\/gh-test-1.oss-cn-qingdao.aliyuncs.com\/pic\/57e4f4d58a3200042d29492f.jpg"}
|
||||
JSONObject response = new JSONObject(b.toString().trim());
|
||||
response.put("statusCode", 200);
|
||||
return response;
|
||||
} else if (statusCode == 403) {
|
||||
JSONObject response = new JSONObject(b.toString().trim());
|
||||
response.put("statusCode", 403);
|
||||
return response;
|
||||
} else if (statusCode == 401) {
|
||||
JSONObject response = new JSONObject();
|
||||
response.put("statusCode", 401);
|
||||
return response;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 显示异常信息
|
||||
e.printStackTrace();
|
||||
Utils.log("Fail:" + e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 读取文件,返回byte[]
|
||||
public static byte[] readFile(File file) {
|
||||
if (file == null) {
|
||||
return null;
|
||||
}
|
||||
FileInputStream fis = null;
|
||||
ByteArrayOutputStream bos = null;
|
||||
try {
|
||||
fis = new FileInputStream(file);
|
||||
bos = new ByteArrayOutputStream();
|
||||
byte[] buffer = new byte[2048];
|
||||
int len;
|
||||
while ((len = fis.read(buffer)) != -1) {
|
||||
bos.write(buffer, 0, len);
|
||||
}
|
||||
bos.flush();
|
||||
return bos.toByteArray();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (fis != null) {
|
||||
try {
|
||||
fis.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (bos != null) {
|
||||
try {
|
||||
bos.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// 读取文件,返回byte[]
|
||||
public static byte[] readFile(File file) {
|
||||
if (file == null) {
|
||||
return null;
|
||||
}
|
||||
FileInputStream fis = null;
|
||||
ByteArrayOutputStream bos = null;
|
||||
try {
|
||||
fis = new FileInputStream(file);
|
||||
bos = new ByteArrayOutputStream();
|
||||
byte[] buffer = new byte[2048];
|
||||
int len;
|
||||
while ((len = fis.read(buffer)) != -1) {
|
||||
bos.write(buffer, 0, len);
|
||||
}
|
||||
bos.flush();
|
||||
return bos.toByteArray();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (fis != null) {
|
||||
try {
|
||||
fis.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (bos != null) {
|
||||
try {
|
||||
bos.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 根据byte[],保存文件
|
||||
public static void saveFile(File file, byte[] data) {
|
||||
if (file == null || data == null) {
|
||||
return;
|
||||
}
|
||||
ByteArrayInputStream bis = null;
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
bis = new ByteArrayInputStream(data);
|
||||
fos = new FileOutputStream(file);
|
||||
byte[] buffer = new byte[2048];
|
||||
int len;
|
||||
while ((len = bis.read(buffer)) != -1) {
|
||||
fos.write(buffer, 0, len);
|
||||
}
|
||||
fos.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (bis != null) {
|
||||
try {
|
||||
bis.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (fos != null) {
|
||||
try {
|
||||
fos.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 根据byte[],保存文件
|
||||
public static void saveFile(File file, byte[] data) {
|
||||
if (file == null || data == null) {
|
||||
return;
|
||||
}
|
||||
ByteArrayInputStream bis = null;
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
bis = new ByteArrayInputStream(data);
|
||||
fos = new FileOutputStream(file);
|
||||
byte[] buffer = new byte[2048];
|
||||
int len;
|
||||
while ((len = bis.read(buffer)) != -1) {
|
||||
fos.write(buffer, 0, len);
|
||||
}
|
||||
fos.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (bis != null) {
|
||||
try {
|
||||
bis.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (fos != null) {
|
||||
try {
|
||||
fos.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,15 +1,12 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gh.base.AppController;
|
||||
import com.gh.download.DownloadEntity;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.download.DownloadStatus;
|
||||
import com.gh.gamecenter.GameDetailActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
@ -21,131 +18,109 @@ import java.util.List;
|
||||
|
||||
public class GameUtils {
|
||||
|
||||
/**
|
||||
* 去除与重复sourceList相同的数据
|
||||
*/
|
||||
public static List<GameEntity> removeDuplicateData(List<GameEntity> sourceList, List<GameEntity> rawList) {
|
||||
if (sourceList == null || sourceList.isEmpty()
|
||||
|| rawList == null || rawList.isEmpty()) {
|
||||
return rawList;
|
||||
}
|
||||
String id;
|
||||
for (int i = 0; i < rawList.size(); i++) {
|
||||
id = rawList.get(i).getId();
|
||||
for (GameEntity gameEntity : sourceList) {
|
||||
if (id.equals(gameEntity.getId())) {
|
||||
rawList.remove(i);
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rawList;
|
||||
}
|
||||
/**
|
||||
* 去除与重复sourceList相同的数据
|
||||
*/
|
||||
public static List<GameEntity> removeDuplicateData(List<GameEntity> sourceList, List<GameEntity> rawList) {
|
||||
if (sourceList == null || sourceList.isEmpty()
|
||||
|| rawList == null || rawList.isEmpty()) {
|
||||
return rawList;
|
||||
}
|
||||
String id;
|
||||
for (int i = 0; i < rawList.size(); i++) {
|
||||
id = rawList.get(i).getId();
|
||||
for (GameEntity gameEntity : sourceList) {
|
||||
if (id.equals(gameEntity.getId())) {
|
||||
rawList.remove(i);
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rawList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动游戏详情页面
|
||||
*/
|
||||
public static void startGameDetailActivity(Context context, GameEntity gameEntity, String entrance) {
|
||||
AppController.put("GameEntity", gameEntity);
|
||||
Intent intent = new Intent(context, GameDetailActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.putExtra("entrance", entrance);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
/**
|
||||
* 设置下载按钮状态
|
||||
*/
|
||||
public static void setDownloadBtnStatus(Context context, GameEntity gameEntity, TextView downloadBtn) {
|
||||
String status = getDownloadBtnText(context, gameEntity);
|
||||
downloadBtn.setTextColor(Color.WHITE);
|
||||
downloadBtn.setText(status);
|
||||
if ("插件化".equals(status)) {
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_plugin_style);
|
||||
} else if ("打开".equals(status)) {
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_launch_style);
|
||||
} else {
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_download_style);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动游戏详情页面
|
||||
*/
|
||||
public static void startGameDetailActivity(Context context, String gameId, String entrance) {
|
||||
Intent intent = new Intent(context, GameDetailActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.putExtra("gameId", gameId);
|
||||
intent.putExtra("entrance", entrance);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
/**
|
||||
* 获取下载按钮文案
|
||||
*/
|
||||
public static String getDownloadBtnText(Context context, GameEntity gameEntity) {
|
||||
int doneCount = 0; // 下载完成数量
|
||||
int pluginCount = 0; // 可插件化数量
|
||||
int updateCount = 0; // 可更新数量
|
||||
int installCount = 0; // 已安装数量
|
||||
DownloadEntity downloadEntity;
|
||||
Object gh_id;
|
||||
for (ApkEntity apkEntity : gameEntity.getApk()) {
|
||||
downloadEntity = DownloadManager.getInstance(context).get(apkEntity.getUrl());
|
||||
if (downloadEntity != null) {
|
||||
if (downloadEntity.getStatus().equals(DownloadStatus.done)) {
|
||||
doneCount++;
|
||||
} else if (downloadEntity.isPluggable()) {
|
||||
pluginCount++;
|
||||
} else if (downloadEntity.isUpdate()) {
|
||||
updateCount++;
|
||||
}
|
||||
}
|
||||
if (PackageManager.isCanUpdate(gameEntity.getId(), apkEntity.getPackageName())) {
|
||||
updateCount++;
|
||||
}
|
||||
if (PackageManager.isInstalled(apkEntity.getPackageName())) {
|
||||
gh_id = PackageUtils.getMetaData(context, apkEntity.getPackageName(), "gh_id");
|
||||
if (!PackageUtils.isSignature(context, apkEntity.getPackageName())) { // TODO 外层判断插件化逻辑与多平台弹窗不一致
|
||||
pluginCount++;
|
||||
} else if (gh_id == null || gh_id.equals(gameEntity.getId())) {
|
||||
installCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (doneCount != 0) {
|
||||
return "安装";
|
||||
} else if (pluginCount != 0) {
|
||||
return "插件化";
|
||||
} else if (updateCount != 0) {
|
||||
return "更新";
|
||||
} else if (installCount != 0) {
|
||||
return "打开";
|
||||
} else {
|
||||
return "下载";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置下载按钮状态
|
||||
*/
|
||||
public static void setDownloadBtnStatus(Context context, GameEntity gameEntity, TextView downloadBtn) {
|
||||
String status = getDownloadBtnText(context, gameEntity);
|
||||
downloadBtn.setTextColor(Color.WHITE);
|
||||
downloadBtn.setText(status);
|
||||
if ("插件化".equals(status)) {
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_plugin_style);
|
||||
} else if ("打开".equals(status)) {
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_launch_style);
|
||||
} else {
|
||||
downloadBtn.setBackgroundResource(R.drawable.game_item_btn_download_style);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下载按钮文案
|
||||
*/
|
||||
public static String getDownloadBtnText(Context context, GameEntity gameEntity) {
|
||||
int doneCount = 0; // 下载完成数量
|
||||
int pluginCount = 0; // 可插件化数量
|
||||
int updateCount = 0; // 可更新数量
|
||||
int installCount = 0; // 已安装数量
|
||||
DownloadEntity downloadEntity;
|
||||
Object gh_id;
|
||||
for (ApkEntity apkEntity : gameEntity.getApk()) {
|
||||
downloadEntity = DownloadManager.getInstance(context).get(apkEntity.getUrl());
|
||||
if (downloadEntity != null) {
|
||||
if (downloadEntity.getStatus().equals(DownloadStatus.done)) {
|
||||
doneCount++;
|
||||
} else if (downloadEntity.isPluggable()) {
|
||||
pluginCount++;
|
||||
} else if (downloadEntity.isUpdate()) {
|
||||
updateCount++;
|
||||
}
|
||||
}
|
||||
if (PackageManager.isCanUpdate(gameEntity.getId(), apkEntity.getPackageName())) {
|
||||
updateCount++;
|
||||
}
|
||||
if (PackageManager.isInstalled(apkEntity.getPackageName())) {
|
||||
gh_id = PackageUtils.getMetaData(context, apkEntity.getPackageName(), "gh_id");
|
||||
if (!PackageUtils.isSignature(context, apkEntity.getPackageName())) {
|
||||
pluginCount++;
|
||||
} else if (gh_id == null || gh_id.equals(gameEntity.getId())) {
|
||||
installCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (doneCount != 0) {
|
||||
return "安装";
|
||||
} else if (pluginCount != 0) {
|
||||
return "插件化";
|
||||
} else if (updateCount != 0) {
|
||||
return "更新";
|
||||
} else if (installCount != 0) {
|
||||
return "打开";
|
||||
} else {
|
||||
return "下载";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取GameUpdateEntity
|
||||
*/
|
||||
public static GameUpdateEntity getGameUpdateEntity(GameEntity gameEntity, ApkEntity apkEntity) {
|
||||
GameUpdateEntity gameUpdateEntity = new GameUpdateEntity();
|
||||
gameUpdateEntity.setId(gameEntity.getId());
|
||||
gameUpdateEntity.setIcon(gameEntity.getIcon());
|
||||
gameUpdateEntity.setName(gameEntity.getName());
|
||||
gameUpdateEntity.setPackageName(apkEntity.getPackageName());
|
||||
gameUpdateEntity.setSize(apkEntity.getSize());
|
||||
gameUpdateEntity.setVersion(apkEntity.getVersion());
|
||||
gameUpdateEntity.setGhVersion(apkEntity.getGhVersion());
|
||||
gameUpdateEntity.setUrl(apkEntity.getUrl());
|
||||
gameUpdateEntity.setPlatform(apkEntity.getPlatform());
|
||||
gameUpdateEntity.setEtag(apkEntity.getEtag());
|
||||
gameUpdateEntity.setPluggable(true);
|
||||
gameUpdateEntity.setTag(gameEntity.getTag());
|
||||
gameUpdateEntity.setBrief(gameEntity.getBrief());
|
||||
return gameUpdateEntity;
|
||||
}
|
||||
/**
|
||||
* 获取GameUpdateEntity
|
||||
*/
|
||||
public static GameUpdateEntity getGameUpdateEntity(GameEntity gameEntity, ApkEntity apkEntity) {
|
||||
GameUpdateEntity gameUpdateEntity = new GameUpdateEntity();
|
||||
gameUpdateEntity.setId(gameEntity.getId());
|
||||
gameUpdateEntity.setIcon(gameEntity.getIcon());
|
||||
gameUpdateEntity.setName(gameEntity.getName());
|
||||
gameUpdateEntity.setPackageName(apkEntity.getPackageName());
|
||||
gameUpdateEntity.setSize(apkEntity.getSize());
|
||||
gameUpdateEntity.setVersion(apkEntity.getVersion());
|
||||
gameUpdateEntity.setGhVersion(apkEntity.getGhVersion());
|
||||
gameUpdateEntity.setUrl(apkEntity.getUrl());
|
||||
gameUpdateEntity.setPlatform(apkEntity.getPlatform());
|
||||
gameUpdateEntity.setEtag(apkEntity.getEtag());
|
||||
gameUpdateEntity.setPluggable(true);
|
||||
gameUpdateEntity.setTag(gameEntity.getTag());
|
||||
gameUpdateEntity.setBrief(gameEntity.getBrief());
|
||||
return gameUpdateEntity;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,7 +1,12 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.text.TextUtils;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.LinearLayout.LayoutParams;
|
||||
import android.widget.TextView;
|
||||
@ -17,7 +22,6 @@ import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author 温冠超
|
||||
* @email 294299195@qq.com
|
||||
* @date 2015-8-14
|
||||
@ -26,84 +30,106 @@ import java.util.TimeZone;
|
||||
*/
|
||||
public class GameViewUtils {
|
||||
|
||||
public static void setLabelList(Context context, LinearLayout labelLayout, List<String> tag) {
|
||||
labelLayout.removeAllViews();
|
||||
if (tag == null || tag.isEmpty()) {
|
||||
labelLayout.addView(getGameTagView(context, "官方版", 0));
|
||||
} else {
|
||||
for (int i = 0, size = tag.size() > 3 ? 3 : tag.size(); i < size; i++) {
|
||||
if (i == size - 1) {
|
||||
labelLayout.addView(getGameTagView(context, tag.get(i), 0));
|
||||
} else {
|
||||
labelLayout.addView(getGameTagView(context, tag.get(i), DisplayUtils.dip2px(context, 5)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void setLabelList(Context context, LinearLayout labelLayout, List<String> tag, String tagType) {
|
||||
labelLayout.removeAllViews();
|
||||
if (tag == null || tag.isEmpty()) {
|
||||
labelLayout.addView(getGameTagView(context, "官方版", 0, tagType));
|
||||
} else {
|
||||
for (int i = 0, size = tag.size(); i < size; i++) {
|
||||
View view;
|
||||
if (i == size - 1) {
|
||||
view = getGameTagView(context, tag.get(i), 0, tagType);
|
||||
} else {
|
||||
view = getGameTagView(context, tag.get(i), DisplayUtils.dip2px(context, 6), tagType);
|
||||
}
|
||||
if (view != null) {
|
||||
labelLayout.addView(view);
|
||||
}
|
||||
if (labelLayout.getChildCount() == 3) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static TextView getGameTagView(Context context, String tagStr, int rightMargin) {
|
||||
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(
|
||||
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
||||
lparams.rightMargin = rightMargin;
|
||||
TextView tag = new TextView(context);
|
||||
tag.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10);
|
||||
tag.setSingleLine(true);
|
||||
tag.setText(tagStr);
|
||||
if ("官方版".equals(tagStr) || "已关注".equals(tagStr)) {
|
||||
tag.setBackgroundResource(R.drawable.border_green_bg);
|
||||
tag.setTextColor(context.getResources().getColor(R.color.tag_green));
|
||||
} else {
|
||||
tag.setBackgroundResource(R.drawable.border_blue_bg);
|
||||
tag.setTextColor(context.getResources().getColor(R.color.theme));
|
||||
}
|
||||
tag.setLayoutParams(lparams);
|
||||
tag.setPadding(DisplayUtils.dip2px(context, 3),
|
||||
0,
|
||||
DisplayUtils.dip2px(context, 3),
|
||||
DisplayUtils.dip2px(context, 1));
|
||||
return tag;
|
||||
}
|
||||
private static TextView getGameTagView(Context context, String tagStr, int rightMargin, String tagType) {
|
||||
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(
|
||||
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
||||
lparams.rightMargin = rightMargin;
|
||||
TextView tag = new TextView(context);
|
||||
tag.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10);
|
||||
tag.setSingleLine(true);
|
||||
tag.setText(tagStr);
|
||||
if ("官方版".equals(tagStr) || "已关注".equals(tagStr)) {
|
||||
tag.setBackgroundResource(R.drawable.border_green_bg);
|
||||
tag.setTextColor(ContextCompat.getColor(context, R.color.tag_green));
|
||||
} else {
|
||||
String colorStr;
|
||||
if (!TextUtils.isEmpty(tagType) && tagType.equals("type")) { // 游戏标签
|
||||
colorStr = "#ff6a28";
|
||||
} else {
|
||||
colorStr = TagUtils.getInstance(context).getColor(tagStr);
|
||||
}
|
||||
|
||||
public static String getGameTestDate(long testTime) {
|
||||
if (colorStr == null) {
|
||||
return null;
|
||||
}
|
||||
int color = Color.parseColor(colorStr);
|
||||
GradientDrawable gradientDrawable = new GradientDrawable();
|
||||
gradientDrawable.setColor(Color.TRANSPARENT);
|
||||
gradientDrawable.setStroke(DisplayUtils.dip2px(context, 0.6f), color);
|
||||
tag.setBackgroundDrawable(gradientDrawable);
|
||||
// tag.setBackgroundResource(R.drawable.border_blue_bg);
|
||||
tag.setTextColor(color);
|
||||
}
|
||||
tag.setLayoutParams(lparams);
|
||||
tag.setPadding(DisplayUtils.dip2px(context, 3),
|
||||
0,
|
||||
DisplayUtils.dip2px(context, 3),
|
||||
DisplayUtils.dip2px(context, 1));
|
||||
return tag;
|
||||
}
|
||||
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);
|
||||
format.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
|
||||
public static String getGameTestDate(long testTime) {
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -10,105 +10,105 @@ import java.util.zip.GZIPOutputStream;
|
||||
|
||||
public class GzipUtils {
|
||||
|
||||
private final static int BUFFER = 1024;
|
||||
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 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 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 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 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 数据解压缩
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -41,6 +41,27 @@ public final class HotFix {
|
||||
}
|
||||
}
|
||||
|
||||
private static void injectInAliyunOs(Context context, String patchDexFile, String patchClassName)
|
||||
throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException,
|
||||
InstantiationException, NoSuchFieldException {
|
||||
PathClassLoader obj = (PathClassLoader) context.getClassLoader();
|
||||
String replaceAll = new File(patchDexFile).getName().replaceAll("\\.[a-zA-Z0-9]+", ".lex");
|
||||
Class cls = Class.forName("dalvik.system.LexClassLoader");
|
||||
Object newInstance =
|
||||
cls.getConstructor(new Class[]{String.class, String.class, String.class, ClassLoader.class}).newInstance(
|
||||
new Object[]{context.getDir("dex", 0).getAbsolutePath() + File.separator + replaceAll,
|
||||
context.getDir("dex", 0).getAbsolutePath(), patchDexFile, obj});
|
||||
cls.getMethod("loadClass", new Class[]{String.class}).invoke(newInstance, new Object[]{patchClassName});
|
||||
setField(obj, PathClassLoader.class, "mPaths",
|
||||
appendArray(getField(obj, PathClassLoader.class, "mPaths"), getField(newInstance, cls, "mRawDexPath")));
|
||||
setField(obj, PathClassLoader.class, "mFiles",
|
||||
combineArray(getField(obj, PathClassLoader.class, "mFiles"), getField(newInstance, cls, "mFiles")));
|
||||
setField(obj, PathClassLoader.class, "mZips",
|
||||
combineArray(getField(obj, PathClassLoader.class, "mZips"), getField(newInstance, cls, "mZips")));
|
||||
setField(obj, PathClassLoader.class, "mLexs",
|
||||
combineArray(getField(obj, PathClassLoader.class, "mLexs"), getField(newInstance, cls, "mDexs")));
|
||||
}
|
||||
|
||||
private static boolean hasDexClassLoader() {
|
||||
try {
|
||||
Class.forName("dalvik.system.BaseDexClassLoader");
|
||||
@ -50,85 +71,66 @@ public final class HotFix {
|
||||
}
|
||||
}
|
||||
|
||||
private static void injectInAliyunOs(Context context, String patchDexFile, String patchClassName)
|
||||
throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException,
|
||||
InstantiationException, NoSuchFieldException {
|
||||
PathClassLoader obj = (PathClassLoader) context.getClassLoader();
|
||||
String replaceAll = new File(patchDexFile).getName().replaceAll("\\.[a-zA-Z0-9]+", ".lex");
|
||||
Class cls = Class.forName("dalvik.system.LexClassLoader");
|
||||
Object newInstance =
|
||||
cls.getConstructor(new Class[] {String.class, String.class, String.class, ClassLoader.class}).newInstance(
|
||||
new Object[] {context.getDir("dex", 0).getAbsolutePath() + File.separator + replaceAll,
|
||||
context.getDir("dex", 0).getAbsolutePath(), patchDexFile, obj});
|
||||
cls.getMethod("loadClass", new Class[] {String.class}).invoke(newInstance, new Object[] {patchClassName});
|
||||
setField(obj, PathClassLoader.class, "mPaths",
|
||||
appendArray(getField(obj, PathClassLoader.class, "mPaths"), getField(newInstance, cls, "mRawDexPath")));
|
||||
setField(obj, PathClassLoader.class, "mFiles",
|
||||
combineArray(getField(obj, PathClassLoader.class, "mFiles"), getField(newInstance, cls, "mFiles")));
|
||||
setField(obj, PathClassLoader.class, "mZips",
|
||||
combineArray(getField(obj, PathClassLoader.class, "mZips"), getField(newInstance, cls, "mZips")));
|
||||
setField(obj, PathClassLoader.class, "mLexs",
|
||||
combineArray(getField(obj, PathClassLoader.class, "mLexs"), getField(newInstance, cls, "mDexs")));
|
||||
}
|
||||
|
||||
@TargetApi(14)
|
||||
private static void injectBelowApiLevel14(Context context, String str, String str2)
|
||||
throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
|
||||
PathClassLoader obj = (PathClassLoader) context.getClassLoader();
|
||||
DexClassLoader dexClassLoader =
|
||||
new DexClassLoader(str, context.getDir("dex", 0).getAbsolutePath(), str, context.getClassLoader());
|
||||
dexClassLoader.loadClass(str2);
|
||||
setField(obj, PathClassLoader.class, "mPaths",
|
||||
appendArray(getField(obj, PathClassLoader.class, "mPaths"), getField(dexClassLoader, DexClassLoader.class,
|
||||
"mRawDexPath")
|
||||
));
|
||||
setField(obj, PathClassLoader.class, "mFiles",
|
||||
combineArray(getField(obj, PathClassLoader.class, "mFiles"), getField(dexClassLoader, DexClassLoader.class,
|
||||
"mFiles")
|
||||
));
|
||||
setField(obj, PathClassLoader.class, "mZips",
|
||||
combineArray(getField(obj, PathClassLoader.class, "mZips"), getField(dexClassLoader, DexClassLoader.class,
|
||||
"mZips")));
|
||||
setField(obj, PathClassLoader.class, "mDexs",
|
||||
combineArray(getField(obj, PathClassLoader.class, "mDexs"), getField(dexClassLoader, DexClassLoader.class,
|
||||
"mDexs")));
|
||||
obj.loadClass(str2);
|
||||
}
|
||||
|
||||
private static void injectAboveEqualApiLevel14(Context context, String str, String str2)
|
||||
throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
|
||||
throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
|
||||
PathClassLoader pathClassLoader = (PathClassLoader) context.getClassLoader();
|
||||
Object a = combineArray(getDexElements(getPathList(pathClassLoader)),
|
||||
getDexElements(getPathList(
|
||||
new DexClassLoader(str, context.getDir("dex", 0).getAbsolutePath(), str, context.getClassLoader()))));
|
||||
getDexElements(getPathList(
|
||||
new DexClassLoader(str, context.getDir("dex", 0).getAbsolutePath(), str, context.getClassLoader()))));
|
||||
Object a2 = getPathList(pathClassLoader);
|
||||
setField(a2, a2.getClass(), "dexElements", a);
|
||||
pathClassLoader.loadClass(str2);
|
||||
}
|
||||
|
||||
private static Object getPathList(Object obj) throws ClassNotFoundException, NoSuchFieldException,
|
||||
IllegalAccessException {
|
||||
return getField(obj, Class.forName("dalvik.system.BaseDexClassLoader"), "pathList");
|
||||
}
|
||||
|
||||
private static Object getDexElements(Object obj) throws NoSuchFieldException, IllegalAccessException {
|
||||
return getField(obj, obj.getClass(), "dexElements");
|
||||
}
|
||||
|
||||
private static Object getField(Object obj, Class cls, String str)
|
||||
throws NoSuchFieldException, IllegalAccessException {
|
||||
Field declaredField = cls.getDeclaredField(str);
|
||||
declaredField.setAccessible(true);
|
||||
return declaredField.get(obj);
|
||||
@TargetApi(14)
|
||||
private static void injectBelowApiLevel14(Context context, String str, String str2)
|
||||
throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
|
||||
PathClassLoader obj = (PathClassLoader) context.getClassLoader();
|
||||
DexClassLoader dexClassLoader =
|
||||
new DexClassLoader(str, context.getDir("dex", 0).getAbsolutePath(), str, context.getClassLoader());
|
||||
dexClassLoader.loadClass(str2);
|
||||
setField(obj, PathClassLoader.class, "mPaths",
|
||||
appendArray(getField(obj, PathClassLoader.class, "mPaths"), getField(dexClassLoader, DexClassLoader.class,
|
||||
"mRawDexPath")
|
||||
));
|
||||
setField(obj, PathClassLoader.class, "mFiles",
|
||||
combineArray(getField(obj, PathClassLoader.class, "mFiles"), getField(dexClassLoader, DexClassLoader.class,
|
||||
"mFiles")
|
||||
));
|
||||
setField(obj, PathClassLoader.class, "mZips",
|
||||
combineArray(getField(obj, PathClassLoader.class, "mZips"), getField(dexClassLoader, DexClassLoader.class,
|
||||
"mZips")));
|
||||
setField(obj, PathClassLoader.class, "mDexs",
|
||||
combineArray(getField(obj, PathClassLoader.class, "mDexs"), getField(dexClassLoader, DexClassLoader.class,
|
||||
"mDexs")));
|
||||
obj.loadClass(str2);
|
||||
}
|
||||
|
||||
private static void setField(Object obj, Class cls, String str, Object obj2)
|
||||
throws NoSuchFieldException, IllegalAccessException {
|
||||
throws NoSuchFieldException, IllegalAccessException {
|
||||
Field declaredField = cls.getDeclaredField(str);
|
||||
declaredField.setAccessible(true);
|
||||
declaredField.set(obj, obj2);
|
||||
}
|
||||
|
||||
private static Object appendArray(Object obj, Object obj2) {
|
||||
Class componentType = obj.getClass().getComponentType();
|
||||
int length = Array.getLength(obj);
|
||||
Object newInstance = Array.newInstance(componentType, length + 1);
|
||||
Array.set(newInstance, 0, obj2);
|
||||
for (int i = 1; i < length + 1; i++) {
|
||||
Array.set(newInstance, i, Array.get(obj, i - 1));
|
||||
}
|
||||
return newInstance;
|
||||
}
|
||||
|
||||
private static Object getField(Object obj, Class cls, String str)
|
||||
throws NoSuchFieldException, IllegalAccessException {
|
||||
Field declaredField = cls.getDeclaredField(str);
|
||||
declaredField.setAccessible(true);
|
||||
return declaredField.get(obj);
|
||||
}
|
||||
|
||||
private static Object combineArray(Object obj, Object obj2) {
|
||||
Class componentType = obj2.getClass().getComponentType();
|
||||
int length = Array.getLength(obj2);
|
||||
@ -144,15 +146,13 @@ public final class HotFix {
|
||||
return newInstance;
|
||||
}
|
||||
|
||||
private static Object appendArray(Object obj, Object obj2) {
|
||||
Class componentType = obj.getClass().getComponentType();
|
||||
int length = Array.getLength(obj);
|
||||
Object newInstance = Array.newInstance(componentType, length + 1);
|
||||
Array.set(newInstance, 0, obj2);
|
||||
for (int i = 1; i < length + 1; i++) {
|
||||
Array.set(newInstance, i, Array.get(obj, i - 1));
|
||||
}
|
||||
return newInstance;
|
||||
private static Object getDexElements(Object obj) throws NoSuchFieldException, IllegalAccessException {
|
||||
return getField(obj, obj.getClass(), "dexElements");
|
||||
}
|
||||
|
||||
private static Object getPathList(Object obj) throws ClassNotFoundException, NoSuchFieldException,
|
||||
IllegalAccessException {
|
||||
return getField(obj, Class.forName("dalvik.system.BaseDexClassLoader"), "pathList");
|
||||
}
|
||||
|
||||
}
|
||||
@ -26,11 +26,10 @@ import okhttp3.internal.tls.OkHostnameVerifier;
|
||||
|
||||
/**
|
||||
* Created by khy on 2016/10/8.
|
||||
*
|
||||
*/
|
||||
public class HttpsUtils {
|
||||
|
||||
private static final TrustManager[] TRUST_MANAGERS = new TrustManager[] {
|
||||
private static final TrustManager[] TRUST_MANAGERS = new TrustManager[]{
|
||||
new X509TrustManager() {
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||
@ -85,7 +84,7 @@ public class HttpsUtils {
|
||||
private static KeyStore getHttpsKeyStore(Context context) {
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = context.getResources().openRawResource(R.raw.download);
|
||||
is = context.getResources().openRawResource(R.raw.cacert);
|
||||
//读取证书
|
||||
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
|
||||
certificateFactory.generateCertificate(is);
|
||||
@ -109,25 +108,17 @@ public class HttpsUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static HttpsURLConnection getHttpsURLConnection(URL url) throws Exception {
|
||||
public static HttpsURLConnection getHttpsURLConnection(URL url) throws Exception {
|
||||
HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection();
|
||||
if ("apk2.ghzhushou.com".equals(url.getHost())
|
||||
|| "download.ghzhushou.com".equals(url.getHost())) {
|
||||
if (mSSLSocketFactory == null || mHostnameVerifier == null) {
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(null, TRUST_MANAGERS, null);
|
||||
mSSLSocketFactory = sslContext.getSocketFactory();
|
||||
|
||||
mHostnameVerifier = HOSTNAME_VERIFIER;
|
||||
}
|
||||
httpsURLConnection.setSSLSocketFactory(mSSLSocketFactory);
|
||||
httpsURLConnection.setHostnameVerifier(mHostnameVerifier);
|
||||
} else {
|
||||
if (mSSLSocketFactory == null || mHostnameVerifier == null) {
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(null, TRUST_MANAGERS, null);
|
||||
httpsURLConnection.setSSLSocketFactory(sslContext.getSocketFactory());
|
||||
httpsURLConnection.setHostnameVerifier(HOSTNAME_VERIFIER);
|
||||
mSSLSocketFactory = sslContext.getSocketFactory();
|
||||
|
||||
mHostnameVerifier = HOSTNAME_VERIFIER;
|
||||
}
|
||||
httpsURLConnection.setSSLSocketFactory(mSSLSocketFactory);
|
||||
httpsURLConnection.setHostnameVerifier(mHostnameVerifier);
|
||||
return httpsURLConnection;
|
||||
}
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ import android.content.res.Resources;
|
||||
import android.graphics.drawable.Animatable;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.net.Uri;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.facebook.common.executors.CallerThreadExecutor;
|
||||
@ -24,82 +25,93 @@ public class ImageUtils {
|
||||
|
||||
private static ImageUtils singleton;
|
||||
|
||||
public static ImageUtils getInstance() {
|
||||
if (singleton == null) {
|
||||
synchronized (ImageUtils.class) {
|
||||
if (singleton == null) {
|
||||
singleton = new ImageUtils();
|
||||
return singleton;
|
||||
}
|
||||
}
|
||||
}
|
||||
return singleton;
|
||||
}
|
||||
public static ImageUtils getInstance() {
|
||||
if (singleton == null) {
|
||||
synchronized (ImageUtils.class) {
|
||||
if (singleton == null) {
|
||||
singleton = new ImageUtils();
|
||||
return singleton;
|
||||
}
|
||||
}
|
||||
}
|
||||
return singleton;
|
||||
}
|
||||
|
||||
// 自适应图片宽高
|
||||
public void display(final SimpleDraweeView simpleDraweeView, String url, final int width) {
|
||||
ControllerListener<ImageInfo> listener = new BaseControllerListener<ImageInfo>(){
|
||||
@Override
|
||||
public void onFinalImageSet(String id, ImageInfo imageInfo, Animatable animatable) {
|
||||
if (imageInfo == null){
|
||||
return;
|
||||
}
|
||||
ViewGroup.LayoutParams layoutParams = simpleDraweeView.getLayoutParams();
|
||||
float scale = (float) imageInfo.getHeight() / (float) imageInfo.getWidth();
|
||||
layoutParams.height = (int)(width * scale);
|
||||
simpleDraweeView.setLayoutParams(layoutParams);
|
||||
}
|
||||
};
|
||||
simpleDraweeView.setController(Fresco.newDraweeControllerBuilder()
|
||||
.setUri(url)
|
||||
.setControllerListener(listener)
|
||||
.build());
|
||||
}
|
||||
// 自适应图片宽高
|
||||
public void display(final SimpleDraweeView simpleDraweeView, String url, final int width) {
|
||||
ControllerListener<ImageInfo> listener = new BaseControllerListener<ImageInfo>() {
|
||||
@Override
|
||||
public void onFinalImageSet(String id, ImageInfo imageInfo, Animatable animatable) {
|
||||
if (imageInfo == null) {
|
||||
return;
|
||||
}
|
||||
ViewGroup.LayoutParams layoutParams = simpleDraweeView.getLayoutParams();
|
||||
float scale = (float) imageInfo.getHeight() / (float) imageInfo.getWidth();
|
||||
layoutParams.height = (int) (width * scale);
|
||||
simpleDraweeView.setLayoutParams(layoutParams);
|
||||
}
|
||||
};
|
||||
simpleDraweeView.setController(Fresco.newDraweeControllerBuilder()
|
||||
.setUri(url)
|
||||
.setControllerListener(listener)
|
||||
.build());
|
||||
}
|
||||
|
||||
// 设置缩放类型,设置按压状态下的叠加图
|
||||
public void display(Resources resources, SimpleDraweeView simpleDraweeView,
|
||||
ScalingUtils.ScaleType scaleType, String url) {
|
||||
simpleDraweeView.setHierarchy(new GenericDraweeHierarchyBuilder(resources)
|
||||
.setFadeDuration(500)
|
||||
.setPressedStateOverlay(new ColorDrawable(resources.getColor(R.color.pressed_bg)))
|
||||
.setPlaceholderImage(R.drawable.ocupy2, ScalingUtils.ScaleType.CENTER)
|
||||
.setBackground(new ColorDrawable(resources.getColor(R.color.placeholder_bg)))
|
||||
.setActualImageScaleType(scaleType)
|
||||
.build());
|
||||
simpleDraweeView.setImageURI(url);
|
||||
}
|
||||
// 设置缩放类型,设置按压状态下的叠加图
|
||||
public void display(Resources resources, SimpleDraweeView simpleDraweeView,
|
||||
ScalingUtils.ScaleType scaleType, String url) {
|
||||
final Context context = simpleDraweeView.getContext();
|
||||
simpleDraweeView.setHierarchy(new GenericDraweeHierarchyBuilder(resources)
|
||||
.setFadeDuration(500)
|
||||
.setPressedStateOverlay(new ColorDrawable(ContextCompat.getColor(context, R.color.pressed_bg)))
|
||||
.setPlaceholderImage(R.drawable.ocupy2, ScalingUtils.ScaleType.CENTER)
|
||||
.setBackground(new ColorDrawable(ContextCompat.getColor(context, R.color.placeholder_bg)))
|
||||
.setActualImageScaleType(scaleType)
|
||||
.build());
|
||||
// simpleDraweeView.setImageURI(url);
|
||||
display(simpleDraweeView, url);
|
||||
}
|
||||
|
||||
// 设置占位符
|
||||
public void display(Resources resources, SimpleDraweeView simpleDraweeView, String url, int placeholderImage) {
|
||||
simpleDraweeView.setHierarchy(new GenericDraweeHierarchyBuilder(resources)
|
||||
.setFadeDuration(500)
|
||||
.setPressedStateOverlay(new ColorDrawable(resources.getColor(R.color.pressed_bg)))
|
||||
.setBackground(new ColorDrawable(resources.getColor(R.color.placeholder_bg)))
|
||||
.setPlaceholderImage(placeholderImage)
|
||||
.build());
|
||||
simpleDraweeView.setImageURI(url);
|
||||
}
|
||||
public static void display(SimpleDraweeView simpleDraweeView, String url) {
|
||||
// if (url.startsWith("http://image.ghzs666.com") && url.endsWith(".jpg")) {
|
||||
// url = url + "?x-oss-process=image/format,webp";
|
||||
// }
|
||||
simpleDraweeView.setImageURI(url);
|
||||
}
|
||||
|
||||
// 图片下载监听和设置低高分辨率图片
|
||||
public void display(SimpleDraweeView simpleDraweeView, String url, String lowUrl,
|
||||
ControllerListener<? super ImageInfo> listener) {
|
||||
simpleDraweeView.setController(Fresco.newDraweeControllerBuilder()
|
||||
.setImageRequest(ImageRequest.fromUri(url))
|
||||
.setControllerListener(listener)
|
||||
.setLowResImageRequest(ImageRequest.fromUri(lowUrl)) // 低分辨率图片
|
||||
.build());
|
||||
}
|
||||
// 设置占位符
|
||||
public void display(Resources resources, SimpleDraweeView simpleDraweeView, String url, int placeholderImage) {
|
||||
final Context context = simpleDraweeView.getContext();
|
||||
simpleDraweeView.setHierarchy(new GenericDraweeHierarchyBuilder(resources)
|
||||
.setFadeDuration(500)
|
||||
.setPressedStateOverlay(new ColorDrawable(ContextCompat.getColor(context, R.color.pressed_bg)))
|
||||
.setBackground(new ColorDrawable(ContextCompat.getColor(context, R.color.placeholder_bg)))
|
||||
.setPlaceholderImage(placeholderImage)
|
||||
.build());
|
||||
// simpleDraweeView.setImageURI(url);
|
||||
display(simpleDraweeView, url);
|
||||
}
|
||||
|
||||
// 获取bitmap
|
||||
public void display(Context context, String url, BaseBitmapDataSubscriber dataSubscriber) {
|
||||
ImageRequest imageRequest = ImageRequestBuilder
|
||||
.newBuilderWithSource(Uri.parse(url))
|
||||
.setProgressiveRenderingEnabled(true)
|
||||
.build();
|
||||
// 图片下载监听和设置低高分辨率图片
|
||||
public void display(SimpleDraweeView simpleDraweeView, String url, String lowUrl,
|
||||
ControllerListener<? super ImageInfo> listener) {
|
||||
simpleDraweeView.setController(Fresco.newDraweeControllerBuilder()
|
||||
.setImageRequest(ImageRequest.fromUri(url))
|
||||
.setControllerListener(listener)
|
||||
.setLowResImageRequest(ImageRequest.fromUri(lowUrl)) // 低分辨率图片
|
||||
.build());
|
||||
}
|
||||
|
||||
Fresco.getImagePipeline()
|
||||
.fetchDecodedImage(imageRequest, context)
|
||||
.subscribe(dataSubscriber, CallerThreadExecutor.getInstance());
|
||||
}
|
||||
// 获取bitmap
|
||||
public void display(Context context, String url, BaseBitmapDataSubscriber dataSubscriber) {
|
||||
ImageRequest imageRequest = ImageRequestBuilder
|
||||
.newBuilderWithSource(Uri.parse(url))
|
||||
.setProgressiveRenderingEnabled(true)
|
||||
.build();
|
||||
|
||||
Fresco.getImagePipeline()
|
||||
.fetchDecodedImage(imageRequest, context)
|
||||
.subscribe(dataSubscriber, CallerThreadExecutor.getInstance());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
144
app/src/main/java/com/gh/common/util/InstallUtils.java
Normal file
144
app/src/main/java/com/gh/common/util/InstallUtils.java
Normal file
@ -0,0 +1,144 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
|
||||
import com.gh.gamecenter.eventbus.EBPackage;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* 下载完成跳安装,
|
||||
*/
|
||||
public class InstallUtils {
|
||||
|
||||
private static final int MAX_TIME = 5 * 60 * 1000;
|
||||
|
||||
private static Map<String, Long> installMap;
|
||||
private static Map<String, Long> uninstallMap;
|
||||
|
||||
private static InstallUtils mInstance;
|
||||
private PackageManager packageManager;
|
||||
private Handler handler;
|
||||
private boolean isRunning;
|
||||
|
||||
private InstallUtils(Context context) {
|
||||
isRunning = false;
|
||||
|
||||
packageManager = context.getPackageManager();
|
||||
|
||||
handler = new Handler(context.getMainLooper()) {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if (msg.what == 0x123 && packageManager != null) {
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
List<PackageInfo> packageInfos = packageManager.getInstalledPackages(0);
|
||||
for (PackageInfo packageInfo : packageInfos) {
|
||||
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
|
||||
list.add(packageInfo.packageName);
|
||||
}
|
||||
}
|
||||
if (installMap != null && installMap.size() != 0) {
|
||||
ArrayList<String> keys = new ArrayList<>();
|
||||
for (String packageName : installMap.keySet()) {
|
||||
long time = installMap.get(packageName);
|
||||
if (System.currentTimeMillis() - time >= MAX_TIME) {
|
||||
keys.add(packageName);
|
||||
} else if (list.contains(packageName)) {
|
||||
keys.add(packageName);
|
||||
EventBus.getDefault().post(new EBPackage("安装", packageName));
|
||||
}
|
||||
}
|
||||
for (String key : keys) {
|
||||
installMap.remove(key);
|
||||
}
|
||||
}
|
||||
if (uninstallMap != null && uninstallMap.size() != 0) {
|
||||
ArrayList<String> keys = new ArrayList<>();
|
||||
for (String packageName : uninstallMap.keySet()) {
|
||||
long time = uninstallMap.get(packageName);
|
||||
if (System.currentTimeMillis() - time >= MAX_TIME) {
|
||||
keys.add(packageName);
|
||||
} else if (list.contains(packageName)) {
|
||||
keys.add(packageName);
|
||||
EventBus.getDefault().post(new EBPackage("卸载", packageName));
|
||||
}
|
||||
}
|
||||
for (String key : keys) {
|
||||
uninstallMap.remove(key);
|
||||
}
|
||||
}
|
||||
if ((installMap != null && installMap.size() != 0)
|
||||
|| (uninstallMap != null && uninstallMap.size() != 0)) {
|
||||
sendEmptyMessageDelayed(0x123, 3000);
|
||||
} else {
|
||||
isRunning = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static InstallUtils getInstance(Context context) {
|
||||
if (mInstance == null) {
|
||||
synchronized (InstallUtils.class) {
|
||||
if (mInstance == null) {
|
||||
mInstance = new InstallUtils(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
public void addInstall(String packageName) {
|
||||
if (installMap == null) {
|
||||
installMap = Collections.synchronizedMap(new HashMap<String, Long>());
|
||||
}
|
||||
installMap.put(packageName, System.currentTimeMillis());
|
||||
run();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
if ((installMap == null || installMap.isEmpty()) && (uninstallMap == null || uninstallMap.isEmpty())) {
|
||||
return;
|
||||
}
|
||||
if (isRunning) {
|
||||
return;
|
||||
}
|
||||
isRunning = true;
|
||||
handler.sendEmptyMessageDelayed(0x123, 10000);
|
||||
}
|
||||
|
||||
public void removeInstall(String packageName) {
|
||||
if (installMap != null) {
|
||||
installMap.remove(packageName);
|
||||
}
|
||||
}
|
||||
|
||||
public void addUninstall(String packageName) {
|
||||
if (uninstallMap == null) {
|
||||
uninstallMap = Collections.synchronizedMap(new HashMap<String, Long>());
|
||||
}
|
||||
uninstallMap.put(packageName, System.currentTimeMillis());
|
||||
run();
|
||||
}
|
||||
|
||||
public void removeUninstall(String packageName) {
|
||||
if (uninstallMap != null) {
|
||||
uninstallMap.remove(packageName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,7 +2,6 @@ package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.io.File;
|
||||
@ -13,47 +12,47 @@ import java.util.UUID;
|
||||
|
||||
public class Installation {
|
||||
|
||||
private static final String INSTALLATION = "INSTALLATION";
|
||||
private static final String INSTALLATION = "INSTALLATION";
|
||||
|
||||
private static String sID = null;
|
||||
private static String sID = null;
|
||||
|
||||
public synchronized static String getUUID(Context context) {
|
||||
String imei = ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId();
|
||||
if (!TextUtils.isEmpty(imei)) {
|
||||
return imei;
|
||||
}
|
||||
String android_id = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
|
||||
if (!TextUtils.isEmpty(android_id)) {
|
||||
return android_id;
|
||||
}
|
||||
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;
|
||||
}
|
||||
public synchronized static String getUUID(Context context) {
|
||||
String imei = Util_System_Phone_State.getDeviceId(context);
|
||||
if (!TextUtils.isEmpty(imei)) {
|
||||
return imei;
|
||||
}
|
||||
String android_id = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
|
||||
if (!TextUtils.isEmpty(android_id)) {
|
||||
return android_id;
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
private static void writeInstallationFile(File installation)
|
||||
throws IOException {
|
||||
FileOutputStream out = new FileOutputStream(installation);
|
||||
String id = UUID.randomUUID().toString();
|
||||
out.write(id.getBytes());
|
||||
out.close();
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
56
app/src/main/java/com/gh/common/util/IntentUtils.java
Normal file
56
app/src/main/java/com/gh/common/util/IntentUtils.java
Normal file
@ -0,0 +1,56 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* @author CsHeng
|
||||
* @Date 17/05/2017
|
||||
* @Time 5:23 PM
|
||||
*/
|
||||
|
||||
public class IntentUtils {
|
||||
|
||||
|
||||
public static Intent getWifiIntent() {
|
||||
return new Intent("android.settings.WIFI_SETTINGS");
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Intent getWechatShareIntent(Context context, String picName) {
|
||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
intent.setType("image/*");
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + context.getExternalCacheDir().getPath() + "/ShareImg/" + picName));
|
||||
intent.setComponent(new ComponentName("com.tencent.mm", "com.tencent.mm.ui.tools.ShareImgUI"));
|
||||
return intent;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Intent getSMSIntent(String smsBody) {
|
||||
Intent sendIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("smsto:"));
|
||||
sendIntent.putExtra("sms_body", smsBody);
|
||||
sendIntent.setType("vnd.android-dir/mms-sms");
|
||||
|
||||
sendIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
return sendIntent;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Intent getEmailToGHIntent() {
|
||||
Intent data = new Intent(Intent.ACTION_SENDTO);
|
||||
data.setData(Uri.parse("mailto:"));
|
||||
data.putExtra(Intent.EXTRA_SUBJECT, "快来试试光环助手");
|
||||
data.putExtra(Intent.EXTRA_TEXT, "我用光环助手一段时间了,在里面可以下载各种热门卡牌手游的加速版,绿色安全,超级省心,做日常效率提高3-5倍!\n" +
|
||||
"\n" +
|
||||
"不用肝的感觉真好,快来试试。\n" +
|
||||
"\n" +
|
||||
"光环助手官网地址:\n" +
|
||||
"\n" +
|
||||
"http://www.ghzs666.com/link?source=appshare333");
|
||||
return data;
|
||||
}
|
||||
}
|
||||
150
app/src/main/java/com/gh/common/util/KaiFuUtils.java
Normal file
150
app/src/main/java/com/gh/common/util/KaiFuUtils.java
Normal file
@ -0,0 +1,150 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.KaiFuServerEntity;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Created by khy on 2017/3/19.
|
||||
*/
|
||||
public class KaiFuUtils {
|
||||
|
||||
public static void setKaiFuTimeHint(long curTime, long lastTime, GameEntity entity, boolean isTop) {
|
||||
|
||||
SimpleDateFormat format = new SimpleDateFormat("dd", Locale.getDefault());
|
||||
String curDay = format.format(curTime);
|
||||
String lastDay = format.format(lastTime);
|
||||
if (!curDay.equals(lastDay)) {
|
||||
if (isTop) {
|
||||
entity.setKaifuTimeHint(curTime);
|
||||
} else {
|
||||
entity.setKaifuTimeHint(lastTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void initKaiFuTimeHintView(TextView view, Long time) {
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd", Locale.getDefault());
|
||||
try {
|
||||
long today = format.parse(format.format(new Date())).getTime();
|
||||
if (time >= today && time < today + 86400 * 1000) {
|
||||
view.setText("↓今天开服");
|
||||
view.setTextColor(Color.parseColor("#ffb13c"));
|
||||
} else if (time >= today - 86400 * 1000 && time < today) {
|
||||
view.setText("↑历史开服");
|
||||
view.setTextColor(Color.parseColor("#c7c7c7"));
|
||||
} else if (time > today && time < today + 86400 * 1000 * 2) {
|
||||
view.setText("↓明天开服");
|
||||
view.setTextColor(Color.parseColor("#ffb13c"));
|
||||
} else if (time < today) {
|
||||
view.setText("↑历史开服");
|
||||
view.setTextColor(Color.parseColor("#c7c7c7"));
|
||||
} else if (time > today && time < today + 86400 * 1000 * 3) {
|
||||
view.setText("↓后天开服");
|
||||
view.setTextColor(Color.parseColor("#c7c7c7"));
|
||||
} else {
|
||||
format.applyPattern("↓M月d日开服");
|
||||
view.setText(format.format(time));
|
||||
view.setTextColor(Color.parseColor("#c7c7c7"));
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
format.applyPattern("M月d日开服");
|
||||
view.setText(format.format(time));
|
||||
}
|
||||
}
|
||||
|
||||
public static void setKaiFuTimeHint(TextView top, TextView bottom, List<GameEntity> gameList, int position) {
|
||||
if (position == 0 || position + 1 >= gameList.size()) return;
|
||||
|
||||
GameEntity curGameEntity = gameList.get(position);
|
||||
GameEntity lastGameEntity = gameList.get(position);
|
||||
KaiFuServerEntity curServerEntity = curGameEntity.getServerEntity();
|
||||
KaiFuServerEntity lastServerEntity = lastGameEntity.getServerEntity();
|
||||
|
||||
if (curServerEntity == null || lastServerEntity == null) return;
|
||||
|
||||
long curTime = curServerEntity.getTime() * 1000;
|
||||
long lastTime = lastServerEntity.getTime() * 1000;
|
||||
SimpleDateFormat format = new SimpleDateFormat("dd", Locale.getDefault());
|
||||
String curDay = format.format(curTime);
|
||||
String lastDay = format.format(lastTime);
|
||||
if (!curDay.equals(lastDay)) {
|
||||
|
||||
bottom.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
bottom.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setKaiFuTime(TextView textView, long time) {
|
||||
time = time * 1000;
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd", Locale.getDefault());
|
||||
try {
|
||||
long today = format.parse(format.format(new Date())).getTime();
|
||||
if (time >= today && time < today + 86400 * 1000) {
|
||||
format.applyPattern("HH:mm");
|
||||
textView.setText(String.format("今天 %s", format.format(time)));
|
||||
textView.setBackgroundResource(R.drawable.border_white_bg);
|
||||
textView.setTextColor(Color.parseColor("#ffb13c"));
|
||||
} else if (time >= today - 86400 * 1000 && time < today) {
|
||||
format.applyPattern("HH:mm");
|
||||
textView.setText(String.format("昨天 %s", format.format(time)));
|
||||
textView.setBackgroundResource(R.drawable.kaifu_time_tag_gray);
|
||||
textView.setTextColor(Color.parseColor("#c7c7c7"));
|
||||
} else if (time > today && time < today + 86400 * 1000 * 2) {
|
||||
format.applyPattern("HH:mm");
|
||||
textView.setText(String.format("明天 %s", format.format(time)));
|
||||
textView.setBackgroundResource(R.drawable.border_white_bg);
|
||||
textView.setTextColor(Color.parseColor("#ffb13c"));
|
||||
} else if (time >= today - 86400 * 1000 * 2 && time < today) {
|
||||
format.applyPattern("HH:mm");
|
||||
textView.setText(String.format("前天 %s", format.format(time)));
|
||||
textView.setBackgroundResource(R.drawable.kaifu_time_tag_gray);
|
||||
textView.setTextColor(Color.parseColor("#c7c7c7"));
|
||||
} else if (time > today && time < today + 86400 * 1000 * 3) {
|
||||
format.applyPattern("HH:mm");
|
||||
textView.setText(String.format("后天 %s", format.format(time)));
|
||||
textView.setBackgroundResource(R.drawable.kaifu_time_tag_gray);
|
||||
textView.setTextColor(Color.parseColor("#c7c7c7"));
|
||||
} else {
|
||||
format.applyPattern("MM-dd HH:mm");
|
||||
textView.setText(format.format(time));
|
||||
textView.setBackgroundResource(R.drawable.kaifu_time_tag_gray);
|
||||
textView.setTextColor(Color.parseColor("#c7c7c7"));
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
format.applyPattern("yyyy年MM月dd日 HH:mm");
|
||||
textView.setText(format.format(time));
|
||||
}
|
||||
}
|
||||
|
||||
public static void setKaiFuType(TextView textView, String type) {
|
||||
textView.setText(type);
|
||||
switch (type) {
|
||||
case "不删档内测":
|
||||
textView.setBackgroundColor(Color.parseColor("#c7c7c7"));
|
||||
break;
|
||||
case "删档内测":
|
||||
textView.setBackgroundColor(Color.parseColor("#c7c7c7"));
|
||||
break;
|
||||
case "公测":
|
||||
textView.setBackgroundColor(Color.parseColor("#06d0a8"));
|
||||
break;
|
||||
default:
|
||||
textView.setBackgroundColor(Color.parseColor("#06d0a8"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@ -9,10 +10,11 @@ import android.graphics.Color;
|
||||
import android.text.Html;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gh.base.AppController;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.LibaoDetailActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.adapter.LibaoDetailAdapter;
|
||||
@ -21,19 +23,21 @@ import com.gh.gamecenter.db.info.LibaoInfo;
|
||||
import com.gh.gamecenter.entity.LibaoEntity;
|
||||
import com.gh.gamecenter.entity.LibaoStatusEntity;
|
||||
import com.gh.gamecenter.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.eventbus.EBUISwitch;
|
||||
import com.gh.gamecenter.geetest.GeetestListener;
|
||||
import com.gh.gamecenter.geetest.GeetestUtils;
|
||||
import com.gh.gamecenter.retrofit.JSONObjectResponse;
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.greenrobot.event.EventBus;
|
||||
import okhttp3.ResponseBody;
|
||||
import retrofit2.adapter.rxjava.HttpException;
|
||||
import retrofit2.HttpException;
|
||||
import rx.Observable;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.functions.Func1;
|
||||
@ -45,6 +49,8 @@ import rx.schedulers.Schedulers;
|
||||
*/
|
||||
public class LibaoUtils {
|
||||
|
||||
public static final String REFRESH_LIBAO_TIME = "refreshLiBaoTime";
|
||||
|
||||
// 礼包去重
|
||||
public static List<LibaoEntity> removeDuplicateData(List<LibaoEntity> sourceList, List<LibaoEntity> rawList) {
|
||||
if (sourceList == null || sourceList.isEmpty()
|
||||
@ -79,7 +85,15 @@ public class LibaoUtils {
|
||||
@Override
|
||||
public void onResponse(List<LibaoEntity> response) {
|
||||
LibaoDao libaoDao = new LibaoDao(context);
|
||||
libaoDao.deleteAll(); // 清空之前所有数据
|
||||
for (LibaoEntity libaoEntity : response) {
|
||||
|
||||
if ("ling".equals(libaoEntity.getStatus())) {
|
||||
libaoEntity.setStatus("linged");
|
||||
} else {
|
||||
libaoEntity.setStatus("taoed");
|
||||
}
|
||||
|
||||
LibaoInfo libaoInfo = LibaoInfo.createLibaoInfo(libaoEntity);
|
||||
libaoInfo.setActive(libaoEntity.isActive());
|
||||
libaoDao.add(libaoInfo);
|
||||
@ -122,10 +136,8 @@ public class LibaoUtils {
|
||||
if (e != null && e.code() == 401) {
|
||||
postLibaoLing(context, libaoId, false, listener, captchaCode);
|
||||
return;
|
||||
} else if (e.code() == 410) { // 该接口已废弃
|
||||
} else if (e != null && e.code() == 410) { // 该接口已废弃
|
||||
Utils.toast(context, "领取失败,请安装最新版本的光环助手");
|
||||
} else if (e.code() == 412) {
|
||||
//TODO 需要验证码
|
||||
}
|
||||
listener.postFailed(e);
|
||||
}
|
||||
@ -160,7 +172,7 @@ public class LibaoUtils {
|
||||
}
|
||||
|
||||
public static void deleteLibaoCode(final Context context, final String code, final boolean isCheck,
|
||||
final PostLibaoListener listener) {
|
||||
final PostLibaoListener listener) {
|
||||
TokenUtils.getToken(context, isCheck)
|
||||
.flatMap(new Func1<String, Observable<ResponseBody>>() {
|
||||
@Override
|
||||
@ -203,17 +215,13 @@ public class LibaoUtils {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public interface PostLibaoListener {
|
||||
void postSucced(Object response);
|
||||
void postFailed(Throwable error);
|
||||
}
|
||||
|
||||
public static void initLibaoBtn(final TextView libaoBtn, final LibaoEntity libaoEntity, final LibaoDao libaoDao,
|
||||
public static void initLibaoBtn(final Activity activity, final TextView libaoBtn, final LibaoEntity libaoEntity, final LibaoDao libaoDao,
|
||||
final boolean isInstallRequired, final LibaoDetailAdapter adapter, final String entrance) {
|
||||
|
||||
libaoBtn.setTextColor(Color.WHITE);
|
||||
switch (libaoEntity.getStatus()) {
|
||||
String status = libaoEntity.getStatus();
|
||||
if (TextUtils.isEmpty(status)) return;
|
||||
switch (status) {
|
||||
case "coming":
|
||||
libaoBtn.setText("未开抢");
|
||||
libaoBtn.setBackgroundResource(R.drawable.textview_blue_style);
|
||||
@ -236,10 +244,10 @@ public class LibaoUtils {
|
||||
break;
|
||||
case "linged":
|
||||
int[][] states = new int[2][];
|
||||
states[0] = new int[] { android.R.attr.state_pressed };
|
||||
states[1] = new int[] {};
|
||||
int[] colors = new int[] { Color.WHITE,
|
||||
Color.parseColor("#06D0A8") };
|
||||
states[0] = new int[]{android.R.attr.state_pressed};
|
||||
states[1] = new int[]{};
|
||||
int[] colors = new int[]{Color.WHITE,
|
||||
Color.parseColor("#06D0A8")};
|
||||
ColorStateList sl = new ColorStateList(states, colors);
|
||||
libaoBtn.setText("已领取");
|
||||
libaoBtn.setBackgroundResource(R.drawable.libao_linged_style);
|
||||
@ -247,10 +255,10 @@ public class LibaoUtils {
|
||||
break;
|
||||
case "taoed":
|
||||
int[][] states2 = new int[2][];
|
||||
states2[0] = new int[] { android.R.attr.state_pressed };
|
||||
states2[1] = new int[] {};
|
||||
int[] colors2 = new int[] { Color.WHITE,
|
||||
Color.parseColor("#ffb13c") };
|
||||
states2[0] = new int[]{android.R.attr.state_pressed};
|
||||
states2[1] = new int[]{};
|
||||
int[] colors2 = new int[]{Color.WHITE,
|
||||
Color.parseColor("#ffb13c")};
|
||||
ColorStateList sl2 = new ColorStateList(states2, colors2);
|
||||
libaoBtn.setText("已淘号");
|
||||
libaoBtn.setBackgroundResource(R.drawable.libao_taoed_style);
|
||||
@ -280,12 +288,12 @@ public class LibaoUtils {
|
||||
}
|
||||
|
||||
DialogUtils.showWarningDialog(libaoBtn.getContext(), "条件不符",
|
||||
Html.fromHtml("请先"+ "<font color=\"#06D0A8\">"
|
||||
Html.fromHtml("请先" + "<font color=\"#06D0A8\">"
|
||||
+ "安装《" + libaoEntity.getGame().getName() + "》 "
|
||||
+ platform + "</font>"), "关闭", "立即安装"
|
||||
, new DialogUtils.ConfiremListener() {
|
||||
, new DialogUtils.ConfirmListener() {
|
||||
@Override
|
||||
public void onConfirem() {
|
||||
public void onConfirm() {
|
||||
adapter.openDownload();
|
||||
}
|
||||
}, null);
|
||||
@ -298,13 +306,11 @@ public class LibaoUtils {
|
||||
Utils.toast(libaoBtn.getContext(), "还没到开始领取时间");
|
||||
break;
|
||||
case "查看":
|
||||
AppController.put("libaoEntity", libaoEntity);
|
||||
Intent intent = new Intent(libaoBtn.getContext(), LibaoDetailActivity.class);
|
||||
intent.putExtra("entrance", entrance);
|
||||
Intent intent = LibaoDetailActivity.getLibaoDetailIntent(libaoEntity, libaoBtn, entrance);
|
||||
libaoBtn.getContext().startActivity(intent);
|
||||
break;
|
||||
case "领取":
|
||||
libaoLing(libaoBtn, libaoEntity, adapter, isInstallRequired, libaoDao, null, entrance);
|
||||
libaoLing(activity, libaoBtn, libaoEntity, adapter, isInstallRequired, libaoDao, null, entrance);
|
||||
break;
|
||||
case "淘号":
|
||||
postLibaoTao(libaoBtn.getContext(), libaoEntity.getId(), true, new PostLibaoListener() {
|
||||
@ -321,31 +327,43 @@ public class LibaoUtils {
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(libaoCode)) {
|
||||
Utils.toast(libaoBtn.getContext(), "淘号异常");
|
||||
try {
|
||||
String detail = responseBody.getString("detail");
|
||||
if ("maintaining".equals(detail)) {
|
||||
Utils.toast(libaoBtn.getContext(), "网络状态异常,请稍后再试");
|
||||
} else if ("fail to compete".equals(detail)) {
|
||||
Utils.toast(libaoBtn.getContext(), "淘号失败,稍后重试");
|
||||
} else {
|
||||
Utils.toast(libaoBtn.getContext(), "淘号异常");
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Utils.toast(libaoBtn.getContext(), "淘号成功");
|
||||
|
||||
libaoEntity.setStatus("taoed");
|
||||
|
||||
LibaoInfo libaoInfo = LibaoInfo.createLibaoInfo(libaoEntity);
|
||||
libaoInfo.setCode(libaoCode);
|
||||
// libaoInfo.setTime(String.valueOf(new Date().getTime()));
|
||||
libaoInfo.setTime(Utils.getTime(libaoBtn.getContext()));
|
||||
libaoDao.add(libaoInfo);
|
||||
|
||||
EventBus.getDefault().post(new EBReuse("libaoChanged"));
|
||||
|
||||
libaoEntity.setStatus("taoed");
|
||||
adapter.initLibaoDao();
|
||||
adapter.notifyDataSetChanged();
|
||||
|
||||
final String finalLibaoCode = libaoCode;
|
||||
DialogUtils.showWarningDialog(libaoBtn.getContext(), "淘号成功",Html.fromHtml("礼包码:"
|
||||
DialogUtils.showWarningDialog(libaoBtn.getContext(), "淘号成功", Html.fromHtml("礼包码:"
|
||||
+ "<font color=\"#ffb13c\">" + libaoCode + "</font>" +
|
||||
"<br/>淘号礼包不保证可用,请尽快进入游戏尝试兑换")
|
||||
"<br/>淘号礼包不保证可用,请尽快进入游戏尝试兑换")
|
||||
, "关闭", " 复制礼包码"
|
||||
, new DialogUtils.ConfiremListener() {
|
||||
, new DialogUtils.ConfirmListener() {
|
||||
@Override
|
||||
public void onConfirem() {
|
||||
public void onConfirm() {
|
||||
copyLink(finalLibaoCode, libaoBtn.getContext());
|
||||
|
||||
if (isInstallRequired) {
|
||||
@ -354,9 +372,9 @@ public class LibaoUtils {
|
||||
public void run() {
|
||||
lunningAppDialog(libaoBtn.getContext()
|
||||
, Html.fromHtml("礼包码:"
|
||||
+ "<font color=\"#ffb13c\">" + finalLibaoCode + "</font>"
|
||||
+ "<font color=\"#ffb13c\">" + finalLibaoCode + "</font>"
|
||||
+ " 复制成功"
|
||||
+"<br/>淘号礼包不保证可用,请尽快进入游戏尝试兑换"), libaoEntity);
|
||||
+ "<br/>淘号礼包不保证可用,请尽快进入游戏尝试兑换"), libaoEntity);
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
@ -374,7 +392,7 @@ public class LibaoUtils {
|
||||
try {
|
||||
JSONObject errorJson = new JSONObject(exception.response().errorBody().string());
|
||||
String detail = errorJson.getString("detail");
|
||||
|
||||
Utils.toast(libaoBtn.getContext(), "返回::" + detail);
|
||||
if ("coming".equals(detail)) {
|
||||
Utils.toast(libaoBtn.getContext(), "礼包领取时间未开始");
|
||||
} else if ("finish".equals(detail)) {
|
||||
@ -382,8 +400,17 @@ public class LibaoUtils {
|
||||
} else if ("fetched".equals(detail)) {
|
||||
Utils.toast(libaoBtn.getContext(), "你已领过这个礼包了");
|
||||
getCunHaoXiang(libaoBtn.getContext(), true);
|
||||
libaoBtn.setText("复制");
|
||||
libaoBtn.setBackgroundResource(R.drawable.textview_blue_style);
|
||||
|
||||
int[][] states2 = new int[2][];
|
||||
states2[0] = new int[]{android.R.attr.state_pressed};
|
||||
states2[1] = new int[]{};
|
||||
int[] colors2 = new int[]{Color.WHITE,
|
||||
Color.parseColor("#ffb13c")};
|
||||
ColorStateList sl2 = new ColorStateList(states2, colors2);
|
||||
libaoBtn.setText("已淘号");
|
||||
libaoBtn.setBackgroundResource(R.drawable.libao_taoed_style);
|
||||
libaoBtn.setTextColor(sl2);
|
||||
libaoEntity.setStatus("taoed");
|
||||
} else if ("try tao".equals(detail) || "used up".equals(detail)) {
|
||||
DialogUtils.showHintDialog(libaoBtn.getContext(), "礼包已领光"
|
||||
, "手速不够快,礼包已经被抢光了,十分抱歉", "知道了");
|
||||
@ -396,7 +423,7 @@ public class LibaoUtils {
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
Utils.toast(libaoBtn.getContext(),"礼包处理异常");
|
||||
Utils.toast(libaoBtn.getContext(), "礼包处理异常" + ex.toString());
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -410,7 +437,7 @@ public class LibaoUtils {
|
||||
});
|
||||
}
|
||||
|
||||
private static void libaoLing(final TextView libaoBtn, final LibaoEntity libaoEntity, final LibaoDetailAdapter adapter,
|
||||
private static void libaoLing(final Activity activity, final TextView libaoBtn, final LibaoEntity libaoEntity, final LibaoDetailAdapter adapter,
|
||||
final boolean isInstallRequired, final LibaoDao libaoDao, String captchaCode, final String entrance) {
|
||||
|
||||
postLibaoLing(libaoBtn.getContext(), libaoEntity.getId(), true, new PostLibaoListener() {
|
||||
@ -432,13 +459,15 @@ public class LibaoUtils {
|
||||
}
|
||||
libaoEntity.setAvailable(libaoEntity.getAvailable() - 1);
|
||||
|
||||
libaoEntity.setStatus("linged");
|
||||
|
||||
LibaoInfo libaoInfo = LibaoInfo.createLibaoInfo(libaoEntity);
|
||||
libaoInfo.setTime(Utils.getTime(libaoBtn.getContext()));
|
||||
libaoInfo.setCode(libaoCode);
|
||||
libaoDao.add(libaoInfo);
|
||||
|
||||
EventBus.getDefault().post(new EBReuse("libaoChanged"));
|
||||
|
||||
libaoEntity.setStatus("linged");
|
||||
adapter.initLibaoDao();
|
||||
adapter.notifyDataSetChanged();
|
||||
|
||||
@ -447,18 +476,18 @@ public class LibaoUtils {
|
||||
+ "<font color=\"#00B7FA\">" + libaoCode + "</font>" +
|
||||
"<br/>请尽快使用,礼包码将于60分钟后进入淘号池")
|
||||
, "关闭", " 复制礼包码"
|
||||
, new DialogUtils.ConfiremListener() {
|
||||
, new DialogUtils.ConfirmListener() {
|
||||
@Override
|
||||
public void onConfirem() {
|
||||
public void onConfirm() {
|
||||
copyLink(finalLibaoCode, libaoBtn.getContext());
|
||||
if (isInstallRequired) {
|
||||
libaoBtn.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
lunningAppDialog(libaoBtn.getContext()
|
||||
, Html.fromHtml("礼包码:"
|
||||
, Html.fromHtml("礼包码:"
|
||||
+ "<font color=\"#00B7FA\">" + finalLibaoCode + "</font>"
|
||||
+ " 复制成功" +"<br/>请尽快进入游戏兑换"), libaoEntity);
|
||||
+ " 复制成功" + "<br/>请尽快进入游戏兑换"), libaoEntity);
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
@ -474,8 +503,8 @@ public class LibaoUtils {
|
||||
HttpException exception = (HttpException) error;
|
||||
if (exception.code() == 403) {
|
||||
try {
|
||||
Utils.log("----403" + exception.response().errorBody().string());
|
||||
JSONObject errorJson = new JSONObject(exception.response().errorBody().string());
|
||||
String string = exception.response().errorBody().string();
|
||||
JSONObject errorJson = new JSONObject(string);
|
||||
String detail = errorJson.getString("detail");
|
||||
|
||||
if ("coming".equals(detail)) {
|
||||
@ -484,15 +513,32 @@ public class LibaoUtils {
|
||||
Utils.toast(libaoBtn.getContext(), "礼包领取时间已结束");
|
||||
} else if ("fetched".equals(detail)) {
|
||||
Utils.toast(libaoBtn.getContext(), "你已领过这个礼包了");
|
||||
getCunHaoXiang(libaoBtn.getContext(), true);
|
||||
libaoBtn.setText("复制");
|
||||
libaoBtn.setBackgroundResource(R.drawable.textview_blue_style);
|
||||
int countdown = 0;
|
||||
if (errorJson.toString().contains("countdown")) {
|
||||
countdown = errorJson.getInt("countdown");
|
||||
}
|
||||
if (countdown > 0 && countdown < 60 * 10) {
|
||||
EventBus.getDefault().post(new EBUISwitch(REFRESH_LIBAO_TIME, countdown));
|
||||
} else {
|
||||
getCunHaoXiang(libaoBtn.getContext(), true);
|
||||
}
|
||||
|
||||
int[][] states = new int[2][];
|
||||
states[0] = new int[]{android.R.attr.state_pressed};
|
||||
states[1] = new int[]{};
|
||||
int[] colors = new int[]{Color.WHITE,
|
||||
Color.parseColor("#06D0A8")};
|
||||
ColorStateList sl = new ColorStateList(states, colors);
|
||||
libaoBtn.setText("已领取");
|
||||
libaoBtn.setBackgroundResource(R.drawable.libao_linged_style);
|
||||
libaoBtn.setTextColor(sl);
|
||||
|
||||
libaoEntity.setStatus("linged");
|
||||
} else if ("try tao".equals(detail) || "used up".equals(detail)) {
|
||||
DialogUtils.showHintDialog(libaoBtn.getContext(), "礼包已领光"
|
||||
, "手速不够快,礼包已经被抢光了,十分抱歉", "知道了");
|
||||
libaoEntity.setStatus("used_up");
|
||||
initLibaoBtn(libaoBtn, libaoEntity, libaoDao, isInstallRequired, adapter, entrance);
|
||||
initLibaoBtn(activity, libaoBtn, libaoEntity, libaoDao, isInstallRequired, adapter, entrance);
|
||||
|
||||
} else if ("maintaining".equals(detail)) {
|
||||
Utils.toast(libaoBtn.getContext(), "网络状态异常,请稍后再试");
|
||||
@ -501,18 +547,22 @@ public class LibaoUtils {
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
Utils.toast(libaoBtn.getContext(),"礼包处理异常");
|
||||
Utils.toast(libaoBtn.getContext(), "礼包处理异常");
|
||||
}
|
||||
return;
|
||||
} else if (exception.code() == 412) {
|
||||
// 需要验证
|
||||
GeetestUtils.getInstance(libaoBtn.getContext())
|
||||
.showDialog(new GeetestUtils.GeetestListener() {
|
||||
@Override
|
||||
public void succed(String response) {
|
||||
libaoLing(libaoBtn, libaoEntity, adapter, isInstallRequired, libaoDao, response, entrance);
|
||||
}
|
||||
});
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.e("LIBAO", "context? " + libaoBtn.getContext() + activity);
|
||||
}
|
||||
|
||||
GeetestUtils.getInstance().showDialog(activity, new GeetestListener() {
|
||||
@Override
|
||||
public void onVerified(String captcha) {
|
||||
libaoLing(activity, libaoBtn, libaoEntity, adapter, isInstallRequired, libaoDao, captcha, entrance);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -535,16 +585,16 @@ public class LibaoUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void lunningAppDialog (final Context context, Spanned msg, final LibaoEntity libaoEntity) {
|
||||
public static void lunningAppDialog(final Context context, Spanned msg, final LibaoEntity libaoEntity) {
|
||||
DialogUtils.showWarningDialog(context, "复制成功", msg
|
||||
, "关闭", "启动游戏"
|
||||
, new DialogUtils.ConfiremListener() {
|
||||
, new DialogUtils.ConfirmListener() {
|
||||
@Override
|
||||
public void onConfirem() {
|
||||
public void onConfirm() {
|
||||
if (LibaoUtils.isAppInstalled(context, libaoEntity.getPackageName())) {
|
||||
PackageUtils.launchApplicationByPackageName(context, libaoEntity.getPackageName());
|
||||
} else {
|
||||
Utils.toast(context, "请安装游戏:" + libaoEntity.getGame().getName()
|
||||
Utils.toast(context, "请安装游戏:" + libaoEntity.getGame().getName()
|
||||
+ PlatformUtils.getInstance(context).getPlatformName(libaoEntity.getPlatform()) + "版");
|
||||
}
|
||||
|
||||
@ -552,12 +602,79 @@ public class LibaoUtils {
|
||||
}, null);
|
||||
}
|
||||
|
||||
|
||||
//复制文字
|
||||
public static void copyLink(String copyContent, Context context) {
|
||||
ClipboardManager cmb = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
cmb.setText(copyContent);
|
||||
|
||||
Utils.toast(context,copyContent + " 复制成功");
|
||||
Utils.toast(context, copyContent + " 复制成功");
|
||||
}
|
||||
|
||||
|
||||
// 合并List<LibaoStatusEntity> 和 List<LibaoEntity> 并检查重复领取的礼包
|
||||
public static void initLiBaoEntity(LibaoDao libaoDao, List<LibaoStatusEntity> statusList
|
||||
, List<LibaoEntity> mLibaoList, Context mContext) {
|
||||
|
||||
for (LibaoInfo libaoInfo : libaoDao.getAll()) {
|
||||
for (LibaoStatusEntity libaoStatusEntity : statusList) {
|
||||
if (TextUtils.isEmpty(libaoInfo.getLibaoId()) || TextUtils.isEmpty(libaoStatusEntity.getId())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(libaoStatusEntity.getBeforeStatus())) {
|
||||
libaoStatusEntity.setBeforeStatus(libaoStatusEntity.getStatus());
|
||||
}
|
||||
|
||||
if (libaoInfo.getLibaoId().equals(libaoStatusEntity.getId())) {
|
||||
if ("ling".equals(libaoInfo.getStatus()) || "linged".equals(libaoInfo.getStatus())) {
|
||||
libaoStatusEntity.setStatus("linged");
|
||||
} else {
|
||||
libaoStatusEntity.setStatus("taoed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (LibaoEntity libaoEntity : mLibaoList) {
|
||||
for (LibaoStatusEntity libaoStatusEntity : statusList) {
|
||||
if (libaoEntity.getId().equals(libaoStatusEntity.getId())) {
|
||||
libaoEntity.setAvailable(libaoStatusEntity.getAvailable());
|
||||
libaoEntity.setTotal(libaoStatusEntity.getTotal());
|
||||
|
||||
String beforeStatus = libaoStatusEntity.getBeforeStatus();
|
||||
if (TextUtils.isEmpty(beforeStatus)) {
|
||||
beforeStatus = libaoStatusEntity.getStatus();
|
||||
}
|
||||
int repeat = libaoEntity.getRepeat();
|
||||
if (repeat > 0
|
||||
&& libaoDao.isCanLing(libaoEntity.getId(), mContext)
|
||||
&& ("ling".equals(beforeStatus) || "tao".equals(beforeStatus))) { // 判断是否可以重复领取
|
||||
if ("ling".equals(beforeStatus)) {
|
||||
if (libaoDao.repeatedLingedCount(libaoStatusEntity.getId()) >= repeat) {
|
||||
libaoEntity.setStatus(libaoStatusEntity.getStatus());
|
||||
} else {
|
||||
libaoEntity.setStatus(beforeStatus);
|
||||
}
|
||||
} else {
|
||||
if (libaoDao.repeatedTaoedCount(libaoStatusEntity.getId()) >= repeat) {
|
||||
libaoEntity.setStatus(libaoStatusEntity.getStatus());
|
||||
} else {
|
||||
libaoEntity.setStatus(beforeStatus);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
libaoEntity.setStatus(libaoStatusEntity.getStatus());
|
||||
}
|
||||
libaoEntity.setBeforeStatus(beforeStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface PostLibaoListener {
|
||||
void postSucced(Object response);
|
||||
|
||||
void postFailed(Throwable error);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,73 +6,73 @@ 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 getUpdateMD5(String url, String content) {
|
||||
if (url == null && content == null) {
|
||||
return null;
|
||||
}
|
||||
MessageDigest digest;
|
||||
ByteArrayInputStream bais;
|
||||
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 getUrlMD5(String url) {
|
||||
if (url == null) {
|
||||
return null;
|
||||
}
|
||||
MessageDigest digest;
|
||||
ByteArrayInputStream bais;
|
||||
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);
|
||||
}
|
||||
public static String getContentMD5(String content) {
|
||||
if (content == null) {
|
||||
return null;
|
||||
}
|
||||
MessageDigest digest;
|
||||
ByteArrayInputStream bais;
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -12,12 +12,12 @@ import android.view.ViewGroup;
|
||||
*/
|
||||
public class MeasureHeightLayoutManager extends LinearLayoutManager {
|
||||
|
||||
private int[] mMeasuredDimension = new int[1];
|
||||
|
||||
public MeasureHeightLayoutManager(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
private int[] mMeasuredDimension = new int[1];
|
||||
|
||||
@Override
|
||||
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
|
||||
int widthSpec, int heightSpec) {
|
||||
@ -26,23 +26,26 @@ public class MeasureHeightLayoutManager extends LinearLayoutManager {
|
||||
|
||||
int height = 0;
|
||||
for (int i = 0; i < getItemCount(); i++) {
|
||||
measureScrapChild(recycler, i,
|
||||
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
|
||||
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
|
||||
mMeasuredDimension);
|
||||
height = height + mMeasuredDimension[0];
|
||||
|
||||
try {
|
||||
measureScrapChild(recycler, i,
|
||||
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
|
||||
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
|
||||
mMeasuredDimension);
|
||||
height = height + mMeasuredDimension[0];
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (height > heightSize){
|
||||
if (height > heightSize) {
|
||||
super.onMeasure(recycler, state, widthSpec, heightSpec);
|
||||
}else {
|
||||
} else {
|
||||
setMeasuredDimension(View.MeasureSpec.getSize(widthSpec), height);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
|
||||
int heightSpec, int[] measuredDimension) {
|
||||
int heightSpec, int[] measuredDimension) throws Exception {
|
||||
View view = recycler.getViewForPosition(position);
|
||||
if (view.getVisibility() == View.GONE) {
|
||||
measuredDimension[0] = 0;
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
@ -12,11 +11,11 @@ import android.graphics.Matrix;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.support.v7.widget.GridLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.support.v4.content.*;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
@ -25,6 +24,7 @@ import android.widget.PopupWindow;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.tencent.connect.share.QQShare;
|
||||
import com.tencent.mm.sdk.openapi.IWXAPI;
|
||||
@ -50,54 +50,129 @@ import java.util.List;
|
||||
*/
|
||||
public class MessageShareUtils {
|
||||
private static MessageShareUtils instance;
|
||||
|
||||
private IWXAPI mIWXAPI;
|
||||
private Tencent mTencent;
|
||||
private Bitmap shareBm; //分享截图
|
||||
|
||||
private String picName;
|
||||
|
||||
private boolean isPlugin = false;
|
||||
private int[] arrLogo = {
|
||||
R.drawable.share_wechat_logo,
|
||||
R.drawable.share_wechatmoments_logo,
|
||||
R.drawable.share_qq_logo,
|
||||
R.drawable.share_qzone_logo,
|
||||
R.drawable.share_save
|
||||
};
|
||||
|
||||
private static IWXAPI api;
|
||||
private static Tencent mTencent;
|
||||
private String[] mArrLabel = {"微信好友", "朋友圈", "QQ好友", "QQ空间", "保存"};
|
||||
|
||||
private Handler handler;
|
||||
private PopupWindow mPopupWindow;
|
||||
|
||||
private int[] arrLogo = {R.drawable.share_wechat_logo, R.drawable.share_wechatmoments_logo, R.drawable.share_qq_logo
|
||||
, R.drawable.share_qzone_logo, R.drawable.share_save};
|
||||
private String[] arrLabel = {"微信好友", "朋友圈", "QQ好友", "QQ空间", "保存"};
|
||||
private Context mContext;
|
||||
|
||||
private PopupWindow popupWindow;
|
||||
//TODO 干掉activity,将context变成applicationcontext
|
||||
// private Activity activity; // 用来关闭分享页面
|
||||
//QQ或者QQ空间分享回调处理
|
||||
public IUiListener QqShareListener = new IUiListener() {
|
||||
@Override
|
||||
public void onComplete(Object o) {
|
||||
// activity.finish();
|
||||
// activity.overridePendingTransition(0, 0);//禁止退出Activity 动画
|
||||
Utils.toast(mContext, "分享成功");
|
||||
}
|
||||
|
||||
private Context context;
|
||||
@Override
|
||||
public void onError(UiError uiError) {
|
||||
Utils.toast(mContext, "分享失败");
|
||||
}
|
||||
|
||||
private Activity activity; // 用来关闭分享页面
|
||||
@Override
|
||||
public void onCancel() {
|
||||
// activity.finish();
|
||||
// activity.overridePendingTransition(0, 0);//禁止退出Activity 动画
|
||||
Utils.toast(mContext, "分享已取消");
|
||||
}
|
||||
};
|
||||
// 适配快传成绩单分享
|
||||
private int contentSize;
|
||||
private int paddTop;
|
||||
private int picSize;
|
||||
private int itemSize;
|
||||
private int gridCount;
|
||||
private int marImg;
|
||||
private int shareType;
|
||||
|
||||
private MessageShareUtils(Context context) {
|
||||
mTencent = Tencent.createInstance(Config.TENCENT_APPID, context); //初始化QQ分享
|
||||
mIWXAPI = WXAPIFactory.createWXAPI(context, Config.WECHAT_APPID); //初始化微信分享
|
||||
//TODO changed to application context
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public static MessageShareUtils getInstance(Context context) {
|
||||
if (instance == null) {
|
||||
instance = new MessageShareUtils();
|
||||
mTencent = Tencent.createInstance("1104659243", context); //初始化QQ分享
|
||||
api = WXAPIFactory.createWXAPI(context, "wx3ffd0785fad18396"); //初始化微信分享
|
||||
instance = new MessageShareUtils(context);
|
||||
}
|
||||
instance.context = context;
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void showShareWindows(View view, Bitmap bitmap, String picName, boolean ispopupWindow){
|
||||
//检查是否安装手机QQ
|
||||
public static boolean isQQClientAvailable(Context context) {
|
||||
final PackageManager packageManager = context.getPackageManager();
|
||||
List<PackageInfo> pinfo = packageManager.getInstalledPackages(0);
|
||||
if (pinfo != null) {
|
||||
for (int i = 0; i < pinfo.size(); i++) {
|
||||
String pn = pinfo.get(i).packageName;
|
||||
if (pn.equals("com.tencent.mobileqq")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public IWXAPI getIWXAPI() {
|
||||
return mIWXAPI;
|
||||
}
|
||||
|
||||
public Tencent getTencent() {
|
||||
return mTencent;
|
||||
}
|
||||
|
||||
public void showShareWindows(View view, Bitmap bitmap, String picName, int shareType) {
|
||||
this.shareBm = bitmap;
|
||||
this.picName = picName;
|
||||
this.activity= (Activity) context;
|
||||
this.shareType = shareType;
|
||||
// this.activity = (Activity) mContext;
|
||||
|
||||
RelativeLayout contentView = new RelativeLayout(context);
|
||||
if (shareType == 2) {
|
||||
contentSize = 75;
|
||||
paddTop = 0;
|
||||
gridCount = 4;
|
||||
picSize = 30;
|
||||
itemSize = 75;
|
||||
marImg = 10;
|
||||
} else {
|
||||
contentSize = 100;
|
||||
paddTop = 10;
|
||||
gridCount = 5;
|
||||
picSize = 43;
|
||||
itemSize = 90;
|
||||
marImg = 13;
|
||||
|
||||
}
|
||||
|
||||
RelativeLayout contentView = new RelativeLayout(mContext);
|
||||
contentView.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
contentView.setBackgroundColor(0x8c000000);
|
||||
contentView.setFocusable(true);
|
||||
contentView.setFocusableInTouchMode(true);
|
||||
|
||||
RecyclerView shareRecyclerView = new RecyclerView(context);
|
||||
shareRecyclerView.setPadding(DisplayUtils.dip2px(context, 10), DisplayUtils.dip2px(context, 10), DisplayUtils.dip2px(context, 10), 0);
|
||||
RecyclerView shareRecyclerView = new RecyclerView(mContext);
|
||||
shareRecyclerView.setPadding(DisplayUtils.dip2px(mContext, 10), DisplayUtils.dip2px(mContext, paddTop), DisplayUtils.dip2px(mContext, 10), 0);
|
||||
shareRecyclerView.setBackgroundColor(Color.WHITE);
|
||||
|
||||
//RecyclerView禁止滑动
|
||||
GridLayoutManager gridLayoutManager = new GridLayoutManager(context, 5){
|
||||
GridLayoutManager gridLayoutManager = new GridLayoutManager(mContext, gridCount) {
|
||||
@Override
|
||||
public boolean canScrollVertically() {
|
||||
return false;
|
||||
@ -107,28 +182,29 @@ public class MessageShareUtils {
|
||||
shareRecyclerView.setLayoutManager(gridLayoutManager);
|
||||
shareRecyclerView.setAdapter(new ShareRecyclerViewAdapter());
|
||||
|
||||
if (!ispopupWindow) {
|
||||
if (shareType == 0 || shareType == 2) {
|
||||
LinearLayout llBottom = (LinearLayout) view;
|
||||
ViewGroup.LayoutParams layoutParams = llBottom.getLayoutParams();
|
||||
layoutParams.height = DisplayUtils.dip2px(context, 100);
|
||||
layoutParams.height = DisplayUtils.dip2px(mContext, contentSize);
|
||||
shareRecyclerView.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
llBottom.addView(shareRecyclerView);
|
||||
return;
|
||||
}
|
||||
|
||||
RelativeLayout.LayoutParams rlParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT
|
||||
, DisplayUtils.dip2px(context, 106));
|
||||
, DisplayUtils.dip2px(mContext, 106));
|
||||
rlParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
|
||||
contentView.addView(shareRecyclerView,rlParams);
|
||||
contentView.addView(shareRecyclerView, rlParams);
|
||||
|
||||
popupWindow = new PopupWindow(contentView, LinearLayout.LayoutParams.MATCH_PARENT
|
||||
mPopupWindow = new PopupWindow(contentView, LinearLayout.LayoutParams.MATCH_PARENT
|
||||
, LinearLayout.LayoutParams.MATCH_PARENT, true);
|
||||
popupWindow.setAnimationStyle(R.style.mypopwindow_anim_style);
|
||||
popupWindow.showAtLocation(view, Gravity.BOTTOM, 0, 0);
|
||||
mPopupWindow.setAnimationStyle(R.style.mypopwindow_anim_style);
|
||||
mPopupWindow.showAtLocation(view, Gravity.BOTTOM, 0, 0);
|
||||
|
||||
contentView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
popupWindow.dismiss();
|
||||
mPopupWindow.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
@ -137,138 +213,54 @@ public class MessageShareUtils {
|
||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK
|
||||
&& event.getRepeatCount() == 0 && popupWindow != null
|
||||
&& popupWindow.isShowing()) {
|
||||
popupWindow.dismiss();
|
||||
&& event.getRepeatCount() == 0 && mPopupWindow != null
|
||||
&& mPopupWindow.isShowing()) {
|
||||
mPopupWindow.dismiss();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public class ShareRecyclerViewAdapter extends RecyclerView.Adapter<ShareRecyclerViewAdapter.ViewHolder>{
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
LinearLayout linearLayout = new LinearLayout(context);
|
||||
linearLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, DisplayUtils.dip2px(context, 90)));
|
||||
linearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
linearLayout.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
linearLayout.setBackgroundResource(R.drawable.cardview_item_style);
|
||||
|
||||
ImageView shareLogo = new ImageView(context);
|
||||
LinearLayout.LayoutParams logoParams = new LinearLayout.LayoutParams(DisplayUtils.dip2px(context, 43), DisplayUtils.dip2px(context, 43));
|
||||
logoParams.setMargins(0, DisplayUtils.dip2px(context, 10), 0, 0);
|
||||
shareLogo.setLayoutParams(logoParams);
|
||||
|
||||
TextView shareLabel = new TextView(context);
|
||||
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
layoutParams.setMargins(0, DisplayUtils.dip2px(context,10), 0, 0);
|
||||
shareLabel.setLayoutParams(layoutParams);
|
||||
shareLabel.setGravity(Gravity.CENTER);
|
||||
shareLabel.setTextColor(Color.parseColor("#3a3a3a"));
|
||||
shareLabel.setTextSize(13);
|
||||
|
||||
linearLayout.addView(shareLogo);
|
||||
linearLayout.addView(shareLabel);
|
||||
|
||||
return new ViewHolder(linearLayout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(final ViewHolder holder, int position) {
|
||||
holder.shareLogo.setImageResource(arrLogo[position]);
|
||||
holder.shareLabel.setText(arrLabel[position]);
|
||||
holder.itemView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (holder.getPosition()){
|
||||
case 0:
|
||||
wechatSahre();
|
||||
activity.finish();
|
||||
break;
|
||||
case 1:
|
||||
wechatMomentsSahre();
|
||||
activity.finish();
|
||||
break;
|
||||
case 2:
|
||||
qqSahre();
|
||||
break;
|
||||
case 3:
|
||||
qZoneSahre();
|
||||
break;
|
||||
case 4:
|
||||
String savePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Pictures/ghzhushou/";
|
||||
writeBitmap(savePath, "gh-" + new Date().getTime() + ".jpg", shareBm, true);
|
||||
|
||||
if (popupWindow == null) return;
|
||||
popupWindow.dismiss();
|
||||
activity.finish();
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return arrLogo.length;
|
||||
}
|
||||
|
||||
public class ViewHolder extends RecyclerView.ViewHolder{
|
||||
LinearLayout linearLayout;
|
||||
TextView shareLabel;
|
||||
ImageView shareLogo;
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
linearLayout = (LinearLayout) itemView;
|
||||
shareLogo = (ImageView) linearLayout.getChildAt(0);
|
||||
shareLabel = (TextView) linearLayout.getChildAt(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//QQ分享
|
||||
private void qqSahre(){
|
||||
Utils.toast(context,"分享跳转中...");
|
||||
private void qqSahre() {
|
||||
Utils.toast(mContext, "分享跳转中...");
|
||||
Bundle params = new Bundle();
|
||||
params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE,
|
||||
QQShare.SHARE_TO_QQ_TYPE_IMAGE);
|
||||
params.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL, context.getExternalCacheDir().getPath() + "/ShareImg/" + picName);
|
||||
params.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL, mContext.getExternalCacheDir().getPath() + "/ShareImg/" + picName);
|
||||
params.putString(QQShare.SHARE_TO_QQ_APP_NAME, "光环助手");
|
||||
params.putInt(QQShare.SHARE_TO_QQ_EXT_INT,
|
||||
QQShare.SHARE_TO_QQ_FLAG_QZONE_ITEM_HIDE);
|
||||
mTencent.shareToQQ(
|
||||
(Activity) context, params,QqShareListener);
|
||||
if (popupWindow == null) return;
|
||||
popupWindow.dismiss();
|
||||
(Activity) mContext, params, QqShareListener);
|
||||
if (mPopupWindow == null) return;
|
||||
mPopupWindow.dismiss();
|
||||
}
|
||||
|
||||
//QQ空间分享
|
||||
private void qZoneSahre(){
|
||||
Utils.toast(context,"分享跳转中...");
|
||||
private void qZoneSahre() {
|
||||
Utils.toast(mContext, "分享跳转中...");
|
||||
Bundle params = new Bundle();
|
||||
params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE,
|
||||
QQShare.SHARE_TO_QQ_TYPE_IMAGE);
|
||||
params.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL, context.getExternalCacheDir().getPath() + "/ShareImg/" + picName);
|
||||
params.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL, mContext.getExternalCacheDir().getPath() + "/ShareImg/" + picName);
|
||||
params.putString(QQShare.SHARE_TO_QQ_APP_NAME, "光环助手");
|
||||
params.putInt(QQShare.SHARE_TO_QQ_EXT_INT,
|
||||
QQShare.SHARE_TO_QQ_FLAG_QZONE_AUTO_OPEN);
|
||||
mTencent.shareToQQ(
|
||||
(Activity) context, params,QqShareListener);
|
||||
if (popupWindow == null) return;
|
||||
popupWindow.dismiss();
|
||||
(Activity) mContext, params, QqShareListener);
|
||||
if (mPopupWindow == null) return;
|
||||
mPopupWindow.dismiss();
|
||||
}
|
||||
|
||||
//微信好友分享
|
||||
private void wechatSahre(){
|
||||
Utils.toast(context,"分享跳转中...");
|
||||
private void wechatSahre() {
|
||||
Utils.toast(mContext, "分享跳转中...");
|
||||
|
||||
//官方分享
|
||||
// WXImageObject imgObj = new WXImageObject();
|
||||
// imgObj.setImagePath(context.getExternalCacheDir().getPath() + "/ShareImg/" + picName);
|
||||
// imgObj.setImagePath(mContext.getExternalCacheDir().getPath() + "/ShareImg/" + picName);
|
||||
// WXMediaMessage msg = new WXMediaMessage();
|
||||
// msg.mediaObject = imgObj;
|
||||
//
|
||||
@ -279,31 +271,26 @@ public class MessageShareUtils {
|
||||
//
|
||||
// Bitmap compressBp = compressBitmap(shareBm);
|
||||
// msg.thumbData = Util.bmpToByteArray(compressBp, true);
|
||||
// api.sendReq(req);
|
||||
// mIWXAPI.sendReq(req);
|
||||
|
||||
//调用手机系统分享
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
intent.setType("image/*");
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + context.getExternalCacheDir().getPath() + "/ShareImg/" + picName));
|
||||
intent.setComponent(new ComponentName("com.tencent.mm", "com.tencent.mm.ui.tools.ShareImgUI"));
|
||||
context.startActivity(intent);
|
||||
mContext.startActivity(IntentUtils.getWechatShareIntent(mContext, picName));
|
||||
} catch (Exception e) {
|
||||
Utils.toast(context,"分享失败!请检查是否已安装微信");
|
||||
Utils.toast(mContext, "分享失败!请检查是否已安装微信");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (popupWindow == null) return;
|
||||
popupWindow.dismiss();
|
||||
if (mPopupWindow == null) return;
|
||||
mPopupWindow.dismiss();
|
||||
}
|
||||
|
||||
//微信朋友圈分享
|
||||
private void wechatMomentsSahre(){
|
||||
Utils.toast(context,"分享跳转中...");
|
||||
private void wechatMomentsSahre() {
|
||||
Utils.toast(mContext, "分享跳转中...");
|
||||
|
||||
WXImageObject imgObj = new WXImageObject();
|
||||
imgObj.setImagePath(context.getExternalCacheDir().getPath() + "/ShareImg/" + picName);
|
||||
imgObj.setImagePath(mContext.getExternalCacheDir().getPath() + "/ShareImg/" + picName);
|
||||
WXMediaMessage msg = new WXMediaMessage();
|
||||
msg.mediaObject = imgObj;
|
||||
|
||||
@ -315,14 +302,12 @@ public class MessageShareUtils {
|
||||
|
||||
Bitmap compressBp = compressBitmap(shareBm);
|
||||
msg.thumbData = Util.bmpToByteArray(compressBp, true);
|
||||
api.sendReq(req);
|
||||
mIWXAPI.sendReq(req);
|
||||
|
||||
if (popupWindow == null) return;
|
||||
popupWindow.dismiss();
|
||||
if (mPopupWindow == null) return;
|
||||
mPopupWindow.dismiss();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private String buildTransaction(final String type) {
|
||||
return (type == null) ? String.valueOf(System.currentTimeMillis()) : type + System.currentTimeMillis();
|
||||
}
|
||||
@ -341,7 +326,7 @@ public class MessageShareUtils {
|
||||
|
||||
result.compress(Bitmap.CompressFormat.JPEG, 85, bos);
|
||||
|
||||
while(bos.toByteArray().length > 10 * 1024){
|
||||
while (bos.toByteArray().length > 10 * 1024) {
|
||||
System.out.println(bos.toByteArray().length);
|
||||
matrix.setScale(0.9f, 0.9f);
|
||||
result = Bitmap.createBitmap(result, 0, 0, result.getWidth(), result.getHeight(), matrix, true);
|
||||
@ -353,42 +338,6 @@ public class MessageShareUtils {
|
||||
return result;
|
||||
}
|
||||
|
||||
//QQ或者QQ空间分享回调处理
|
||||
public IUiListener QqShareListener = new IUiListener() {
|
||||
@Override
|
||||
public void onComplete(Object o) {
|
||||
activity.finish();
|
||||
activity.overridePendingTransition(0, 0);//禁止退出Activity 动画
|
||||
Utils.toast(context, "分享成功");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(UiError uiError) {
|
||||
Utils.toast(context, "分享失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
activity.finish();
|
||||
activity.overridePendingTransition(0, 0);//禁止退出Activity 动画
|
||||
Utils.toast(context, "分享已取消");
|
||||
}
|
||||
};
|
||||
|
||||
//检查是否安装手机QQ
|
||||
public static boolean isQQClientAvailable(Context context){
|
||||
final PackageManager packageManager = context.getPackageManager();
|
||||
List<PackageInfo> pinfo = packageManager.getInstalledPackages(0);
|
||||
if (pinfo != null) {
|
||||
for (int i = 0; i < pinfo.size(); i++) {
|
||||
String pn = pinfo.get(i).packageName; if (pn.equals("com.tencent.mobileqq")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//写到存储卡中
|
||||
public void writeBitmap(String path, String name, Bitmap bitmap, boolean isToast) {
|
||||
File file = new File(path);
|
||||
@ -396,7 +345,7 @@ public class MessageShareUtils {
|
||||
file.mkdirs();
|
||||
}
|
||||
|
||||
File _file = new File(path , name);
|
||||
File _file = new File(path, name);
|
||||
if (_file.exists()) {
|
||||
_file.delete();
|
||||
}
|
||||
@ -414,13 +363,9 @@ public class MessageShareUtils {
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 75, fos);
|
||||
}
|
||||
if (isToast) {
|
||||
Utils.toast(context,"成功保存到相册");
|
||||
Utils.toast(mContext, "成功保存到相册");
|
||||
//刷新手机图片库
|
||||
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
|
||||
Uri uri = Uri.fromFile(_file);
|
||||
intent.setData(uri);
|
||||
context.sendBroadcast(intent);
|
||||
Utils.log("保存分享图片路径:" + _file.getAbsolutePath());
|
||||
refreshImage(_file, mContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -438,4 +383,100 @@ public class MessageShareUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void refreshImage(File _file, Context context) {
|
||||
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
|
||||
Uri uri = Uri.fromFile(_file);
|
||||
intent.setData(uri);
|
||||
context.sendBroadcast(intent);
|
||||
Utils.log("保存分享图片路径:" + _file.getAbsolutePath());
|
||||
}
|
||||
|
||||
class ShareRecyclerViewAdapter extends RecyclerView.Adapter<ShareRecyclerViewAdapter.ViewHolder> {
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
LinearLayout linearLayout = new LinearLayout(mContext);
|
||||
linearLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, DisplayUtils.dip2px(mContext, itemSize)));
|
||||
linearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
linearLayout.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
linearLayout.setBackgroundResource(R.drawable.cardview_item_style);
|
||||
|
||||
ImageView shareLogo = new ImageView(mContext);
|
||||
LinearLayout.LayoutParams logoParams = new LinearLayout.LayoutParams(DisplayUtils.dip2px(mContext, picSize), DisplayUtils.dip2px(mContext, picSize));
|
||||
logoParams.setMargins(0, DisplayUtils.dip2px(mContext, 10), 0, 0);
|
||||
shareLogo.setLayoutParams(logoParams);
|
||||
|
||||
TextView shareLabel = new TextView(mContext);
|
||||
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
layoutParams.setMargins(0, DisplayUtils.dip2px(mContext, 10), 0, 0);
|
||||
shareLabel.setLayoutParams(layoutParams);
|
||||
shareLabel.setGravity(Gravity.CENTER);
|
||||
shareLabel.setTextColor(ContextCompat.getColor(mContext, R.color.text_3a3a3a));
|
||||
shareLabel.setTextSize(marImg);
|
||||
|
||||
linearLayout.addView(shareLogo);
|
||||
linearLayout.addView(shareLabel);
|
||||
|
||||
return new ViewHolder(linearLayout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(final ViewHolder holder, int position) {
|
||||
holder.shareLogo.setImageResource(arrLogo[position]);
|
||||
holder.shareLabel.setText(mArrLabel[position]);
|
||||
holder.itemView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (holder.getPosition()) {
|
||||
case 0:
|
||||
wechatSahre();
|
||||
if (shareType != 2) {
|
||||
// activity.finish();
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
wechatMomentsSahre();
|
||||
if (shareType != 2) {
|
||||
// activity.finish();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
qqSahre();
|
||||
break;
|
||||
case 3:
|
||||
qZoneSahre();
|
||||
break;
|
||||
case 4:
|
||||
String savePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Pictures/ghzhushou/";
|
||||
writeBitmap(savePath, "gh-" + new Date().getTime() + ".jpg", shareBm, true);
|
||||
|
||||
if (mPopupWindow == null) return;
|
||||
mPopupWindow.dismiss();
|
||||
// activity.finish();
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return gridCount;
|
||||
}
|
||||
|
||||
public class ViewHolder extends RecyclerView.ViewHolder {
|
||||
LinearLayout linearLayout;
|
||||
TextView shareLabel;
|
||||
ImageView shareLogo;
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
linearLayout = (LinearLayout) itemView;
|
||||
shareLogo = (ImageView) linearLayout.getChildAt(0);
|
||||
shareLabel = (TextView) linearLayout.getChildAt(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -6,102 +6,103 @@ 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;
|
||||
}
|
||||
/**
|
||||
* 判断是否有网络连接
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
/**
|
||||
* 判断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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前网络连接的类型信息
|
||||
* @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";
|
||||
}
|
||||
/**
|
||||
* 判断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";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,11 +1,8 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gh.gamecenter.NewsDetailActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.entity.NewsEntity;
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
@ -23,110 +20,110 @@ import rx.schedulers.Schedulers;
|
||||
|
||||
public class NewsUtils {
|
||||
|
||||
/**
|
||||
* 根据新闻类型获取标签背景资源
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动新闻详情页面
|
||||
*/
|
||||
public static void startNewsDetailActivity(Context context, NewsEntity newsEntity, String entrance) {
|
||||
Intent intent = new Intent(context, NewsDetailActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.putExtra("id", newsEntity.getId());
|
||||
intent.putExtra("title", newsEntity.getTitle());
|
||||
intent.putExtra("type", newsEntity.getType());
|
||||
intent.putExtra("entrance", entrance);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计阅读量
|
||||
/**
|
||||
* 根据新闻类型获取标签背景资源
|
||||
*/
|
||||
public static void statNewsViews(String news_id) {
|
||||
RetrofitManager.getData().postNewsViews(news_id)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<ResponseBody>());
|
||||
}
|
||||
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 if ("热门".equals(type) || "置顶".equals(type)) {
|
||||
return R.drawable.textview_all_red_up;
|
||||
} else {
|
||||
return R.drawable.textview_blue_up;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 去除与重复sourceList相同的数据
|
||||
*/
|
||||
public static List<NewsEntity> removeDuplicateData(List<NewsEntity> sourceList, List<NewsEntity> rawList) {
|
||||
if (sourceList == null || sourceList.isEmpty()
|
||||
|| rawList == null || rawList.isEmpty()) {
|
||||
return rawList;
|
||||
}
|
||||
String id;
|
||||
for (int i = 0; i < rawList.size(); i++) {
|
||||
id = rawList.get(i).getId();
|
||||
for (NewsEntity newsEntity : sourceList) {
|
||||
if (id.equals(newsEntity.getId())) {
|
||||
rawList.remove(i);
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rawList;
|
||||
}
|
||||
/**
|
||||
* 统计阅读量
|
||||
*/
|
||||
public static void statNewsViews(String news_id) {
|
||||
RetrofitManager.getData().postNewsViews(news_id)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<ResponseBody>());
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置新闻类型
|
||||
*/
|
||||
public static void setNewsType(TextView textView, String type) {
|
||||
textView.setText(type);
|
||||
textView.setTextColor(Color.WHITE);
|
||||
if ("活动".equals(type)) {
|
||||
textView.setBackgroundResource(R.drawable.textview_orange_style);
|
||||
} else if ("公告".equals(type)) {
|
||||
textView.setBackgroundResource(R.drawable.textview_red_style);
|
||||
} else if ("评测".equals(type)) {
|
||||
textView.setBackgroundResource(R.drawable.textview_red_style);
|
||||
} else if ("杂谈".equals(type)) {
|
||||
textView.setBackgroundResource(R.drawable.textview_orange_style);
|
||||
} else if ("专题".equals(type)) {
|
||||
textView.setBackgroundResource(R.drawable.textview_blue_style);
|
||||
} else {
|
||||
textView.setBackgroundResource(R.drawable.textview_blue_style);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 去除与重复sourceList相同的数据
|
||||
*/
|
||||
public static List<NewsEntity> removeDuplicateData(List<NewsEntity> sourceList, List<NewsEntity> rawList) {
|
||||
if (sourceList == null || sourceList.isEmpty()
|
||||
|| rawList == null || rawList.isEmpty()) {
|
||||
return rawList;
|
||||
}
|
||||
String id;
|
||||
for (int i = 0; i < rawList.size(); i++) {
|
||||
id = rawList.get(i).getId();
|
||||
for (NewsEntity newsEntity : sourceList) {
|
||||
if (id.equals(newsEntity.getId())) {
|
||||
rawList.remove(i);
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rawList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置新闻发布时间
|
||||
*/
|
||||
public static void setNewsPublishOn(TextView textView, long time) {
|
||||
time = time * 1000;
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd", Locale.getDefault());
|
||||
try {
|
||||
long today = format.parse(format.format(new Date())).getTime();
|
||||
if (time >= today && time < today + 86400 * 1000) {
|
||||
format.applyPattern("HH:mm");
|
||||
textView.setText(format.format(time));
|
||||
} else if (time >= today - 86400 * 1000 && time < today) {
|
||||
format.applyPattern("HH:mm");
|
||||
textView.setText(String.format("昨天 %s", format.format(time)));
|
||||
} else {
|
||||
format.applyPattern("yyyy年MM月dd日 HH:mm");
|
||||
textView.setText(format.format(time));
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
format.applyPattern("yyyy年MM月dd日 HH:mm");
|
||||
textView.setText(format.format(time));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 设置新闻类型
|
||||
*/
|
||||
public static void setNewsType(TextView textView, String type, int priority, int position) {
|
||||
if (priority != 0) {
|
||||
if (position == 0) {
|
||||
textView.setText("置顶");
|
||||
} else {
|
||||
textView.setText("热门");
|
||||
}
|
||||
textView.setBackgroundResource(R.drawable.textview_all_red_style);
|
||||
return;
|
||||
} else {
|
||||
textView.setText(type);
|
||||
}
|
||||
|
||||
textView.setTextColor(Color.WHITE);
|
||||
if ("活动".equals(type)) {
|
||||
textView.setBackgroundResource(R.drawable.textview_orange_style);
|
||||
} else if ("公告".equals(type)) {
|
||||
textView.setBackgroundResource(R.drawable.textview_red_style);
|
||||
} else if ("评测".equals(type)) {
|
||||
textView.setBackgroundResource(R.drawable.textview_red_style);
|
||||
} else if ("杂谈".equals(type)) {
|
||||
textView.setBackgroundResource(R.drawable.textview_orange_style);
|
||||
} else if ("专题".equals(type)) {
|
||||
textView.setBackgroundResource(R.drawable.textview_blue_style);
|
||||
} else {
|
||||
textView.setBackgroundResource(R.drawable.textview_blue_style);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置新闻发布时间
|
||||
*/
|
||||
public static void setNewsPublishOn(TextView textView, long time) {
|
||||
time = time * 1000;
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd", Locale.getDefault());
|
||||
try {
|
||||
long today = format.parse(format.format(new Date())).getTime();
|
||||
if (time >= today && time < today + 86400 * 1000) {
|
||||
format.applyPattern("HH:mm");
|
||||
textView.setText(format.format(time));
|
||||
} else if (time >= today - 86400 * 1000 && time < today) {
|
||||
format.applyPattern("HH:mm");
|
||||
textView.setText(String.format("昨天 %s", format.format(time)));
|
||||
} else {
|
||||
format.applyPattern("yyyy年MM月dd日 HH:mm");
|
||||
textView.setText(format.format(time));
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
format.applyPattern("yyyy年MM月dd日 HH:mm");
|
||||
textView.setText(format.format(time));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -12,74 +12,105 @@ import com.gh.download.DownloadManager;
|
||||
import com.gh.download.DownloadStatus;
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by LGT on 2016/10/10.
|
||||
*/
|
||||
public class NotificationUtils {
|
||||
|
||||
public static void showDownloadDoneNotification(Context context, DownloadEntity downloadEntity, int flag) {
|
||||
NotificationManager nManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("path", downloadEntity.getPath());
|
||||
intent.setAction("com.gh.gamecenter.INSTALL");
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, flag,
|
||||
intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
String text;
|
||||
String title;
|
||||
if (downloadEntity.isPluggable()) {
|
||||
title = "下载完成,点击继续插件化";
|
||||
text = downloadEntity.getName() + " - "
|
||||
+ PlatformUtils.getInstance(context).getPlatformName(downloadEntity.getPlatform());
|
||||
} else {
|
||||
if (downloadEntity.isPlugin()) {
|
||||
text = downloadEntity.getName()
|
||||
+ " - " + PlatformUtils.getInstance(context).getPlatformName(downloadEntity.getPlatform());
|
||||
} else {
|
||||
text = downloadEntity.getName();
|
||||
}
|
||||
title = "下载完成,点击立即安装";
|
||||
}
|
||||
Notification notification = new NotificationCompat.Builder(context)
|
||||
.setSmallIcon(R.drawable.logo)
|
||||
.setTicker(title)
|
||||
.setContentTitle(text)
|
||||
.setContentText(title)
|
||||
.setContentIntent(pendingIntent).build();
|
||||
// notification.defaults = Notification.DEFAULT_SOUND;// 添加系统默认声音
|
||||
notification.flags |= Notification.FLAG_AUTO_CANCEL; // // FLAG_AUTO_CANCEL表明当通知被用户点击时,通知将被清除。
|
||||
nManager.notify(flag, notification);
|
||||
}
|
||||
public static final String ACTION_INSTALL = "com.gh.gamecenter.INSTALL";
|
||||
public static final String ACTION_DOWNLOAD = "com.gh.gamecenter.DOWNLOAD";
|
||||
|
||||
public static void showDownloadingNotification(Context context) {
|
||||
int downloadingSize = 0;
|
||||
for (DownloadEntity entity : DownloadManager.getInstance(context).getAll()) {
|
||||
if (entity.getStatus().equals(DownloadStatus.downloading)
|
||||
|| entity.getStatus().equals(DownloadStatus.waiting)
|
||||
|| entity.getStatus().equals(DownloadStatus.pause)
|
||||
|| entity.getStatus().equals(DownloadStatus.timeout)
|
||||
|| entity.getStatus().equals(DownloadStatus.neterror)) {
|
||||
downloadingSize++;
|
||||
}
|
||||
}
|
||||
if (downloadingSize == 0) {
|
||||
NotificationManager nManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
nManager.cancel(0x123);
|
||||
} else {
|
||||
NotificationManager nManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
Intent intent = new Intent();
|
||||
intent.setAction("com.gh.gamecenter.DOWNLOAD");
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0x123,
|
||||
intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
Notification notification = new NotificationCompat.Builder(context)
|
||||
.setSmallIcon(R.drawable.logo)
|
||||
.setTicker("点击查看详情")
|
||||
.setContentTitle("你有" + downloadingSize + "个游戏正在下载中" )
|
||||
.setContentText("点击查看详情")
|
||||
.setContentIntent(pendingIntent).build();
|
||||
// 快传传输完成消息
|
||||
public static void showKuaiChuanDoneNotification(Context context, String apkPath, String apkName, String packName) {
|
||||
NotificationManager manager = getNotificationManager(context);
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("path", apkPath);
|
||||
intent.setAction(ACTION_INSTALL);
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0x321,
|
||||
intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
String title = "接收完成,点击立即安装";
|
||||
String text = apkName;
|
||||
|
||||
Notification notification = new NotificationCompat.Builder(context)
|
||||
.setSmallIcon(R.drawable.logo)
|
||||
.setTicker(title)
|
||||
.setContentTitle(text)
|
||||
.setContentText(title)
|
||||
.setContentIntent(pendingIntent).build();
|
||||
notification.flags |= Notification.FLAG_AUTO_CANCEL; // // FLAG_AUTO_CANCEL表明当通知被用户点击时,通知将被清除。
|
||||
manager.notify(packName, 0x321, notification);
|
||||
}
|
||||
|
||||
private static NotificationManager getNotificationManager(Context context) {
|
||||
return (NotificationManager) context.getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
}
|
||||
|
||||
public static void showDownloadDoneNotification(Context context, DownloadEntity downloadEntity, int flag) {
|
||||
NotificationManager manager = getNotificationManager(context);
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("path", downloadEntity.getPath());
|
||||
intent.setAction(ACTION_INSTALL);
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, flag,
|
||||
intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
String text;
|
||||
String title;
|
||||
if (downloadEntity.isPluggable()) {
|
||||
title = "下载完成,点击继续插件化";
|
||||
text = downloadEntity.getName() + " - "
|
||||
+ PlatformUtils.getInstance(context).getPlatformName(downloadEntity.getPlatform());
|
||||
} else {
|
||||
if (downloadEntity.isPlugin()) {
|
||||
text = downloadEntity.getName()
|
||||
+ " - " + PlatformUtils.getInstance(context).getPlatformName(downloadEntity.getPlatform());
|
||||
} else {
|
||||
text = downloadEntity.getName();
|
||||
}
|
||||
title = "下载完成,点击立即安装";
|
||||
}
|
||||
Notification notification = new NotificationCompat.Builder(context)
|
||||
.setSmallIcon(R.drawable.logo)
|
||||
.setTicker(title)
|
||||
.setContentTitle(text)
|
||||
.setContentText(title)
|
||||
.setContentIntent(pendingIntent).build();
|
||||
// notification.defaults = Notification.DEFAULT_SOUND;// 添加系统默认声音
|
||||
notification.flags |= Notification.FLAG_AUTO_CANCEL; // // FLAG_AUTO_CANCEL表明当通知被用户点击时,通知将被清除。
|
||||
manager.notify(flag, notification);
|
||||
}
|
||||
|
||||
public static void showDownloadingNotification(Context context) {
|
||||
NotificationManager manager = getNotificationManager(context);
|
||||
int downloadingSize = 0;
|
||||
List<DownloadEntity> all = DownloadManager.getInstance(context).getAll();
|
||||
if (all != null) {
|
||||
for (DownloadEntity entity : all) {
|
||||
if (entity.getStatus().equals(DownloadStatus.downloading)
|
||||
|| entity.getStatus().equals(DownloadStatus.waiting)
|
||||
|| entity.getStatus().equals(DownloadStatus.pause)
|
||||
|| entity.getStatus().equals(DownloadStatus.timeout)
|
||||
|| entity.getStatus().equals(DownloadStatus.neterror)) {
|
||||
downloadingSize++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (downloadingSize == 0) {
|
||||
manager.cancel(0x123);
|
||||
} else {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(ACTION_DOWNLOAD);
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0x123, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
Notification notification = new NotificationCompat.Builder(context)
|
||||
.setSmallIcon(R.drawable.logo)
|
||||
.setTicker("点击查看详情")
|
||||
.setContentTitle("你有" + downloadingSize + "个游戏正在下载中")
|
||||
.setContentText("点击查看详情")
|
||||
.setContentIntent(pendingIntent).build();
|
||||
// notification.defaults = Notification.DEFAULT_SOUND;// 添加系统默认声音
|
||||
notification.flags |= Notification.FLAG_NO_CLEAR; // 通知无法手动清除
|
||||
nManager.notify(0x123, notification);
|
||||
}
|
||||
}
|
||||
notification.flags |= Notification.FLAG_NO_CLEAR; // 通知无法手动清除
|
||||
manager.notify(0x123, notification);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -13,7 +13,10 @@ import android.text.TextUtils;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.gh.gamecenter.entity.GameUpdateEntity;
|
||||
import com.gh.gamecenter.manager.FilterManager;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
@ -24,268 +27,289 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PackageUtils {
|
||||
|
||||
public static final String publicKey = "OpenSSLRSAPublicKey{modulus=a8c4bb5748fec8d5c35db1a7a182d41ba4721a91131a417330af79ef4ddb43f9fa0ff4907b0a613bfe152de0ed8fc1b2e6f94a908aa98a5f7adc1ce814ba7ec919d75d9910bdfd8649b4789da6a90ffb61f0d23ac4f828a78fcd0d6f6120c1c43c1f87f7498a89eb40ca8e32dfc2f9d5c10d612b95192870223674e241e53305abf320d7eed76ded398778576e4db7b17b3bc6a792f13de5e43a6a5fae4276c73e6990ce97f68dff0ec16fc9594f175c8d49cd0d7877340d9de60942ca0efc737e50b6c295dfe0713e4532b4e810e1ea11b702b4a27753e41559cbceb247e7f044ec4e3ab2e8bccd8b9fd71286e63307550bcde86deee95adb8133076269135b,publicExponent=10001}";
|
||||
|
||||
/*
|
||||
* 根据路径,获取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 final String publicKey = "OpenSSLRSAPublicKey{modulus=a8c4bb5748fec8d5c35db1a7a182d41ba4721a91131a417330af79ef4ddb43f9fa0ff4907b0a613bfe152de0ed8fc1b2e6f94a908aa98a5f7adc1ce814ba7ec919d75d9910bdfd8649b4789da6a90ffb61f0d23ac4f828a78fcd0d6f6120c1c43c1f87f7498a89eb40ca8e32dfc2f9d5c10d612b95192870223674e241e53305abf320d7eed76ded398778576e4db7b17b3bc6a792f13de5e43a6a5fae4276c73e6990ce97f68dff0ec16fc9594f175c8d49cd0d7877340d9de60942ca0efc737e50b6c295dfe0713e4532b4e810e1ea11b702b4a27753e41559cbceb247e7f044ec4e3ab2e8bccd8b9fd71286e63307550bcde86deee95adb8133076269135b,publicExponent=10001}";
|
||||
|
||||
/*
|
||||
* 获取meta-data
|
||||
*/
|
||||
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;
|
||||
}
|
||||
/*
|
||||
* 判断是否可以更新,只判断gh_version的大小
|
||||
*/
|
||||
public static boolean isCanUpdate(Context context, GameUpdateEntity gameUpdateEntity) {
|
||||
// 判断是否gh_version是否存在
|
||||
String gh_version = (String) PackageUtils.getMetaData(
|
||||
context, gameUpdateEntity.getPackageName(), "gh_version");
|
||||
if (gh_version != null) {
|
||||
gh_version = gh_version.substring(2);
|
||||
// 判断gh_version的大小
|
||||
return Long.parseLong(gh_version) < Long.parseLong(gameUpdateEntity.getGhVersion());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 根据包名,获取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;
|
||||
}
|
||||
/*
|
||||
* 获取meta-data
|
||||
*/
|
||||
public static Object getMetaData(Context context, String packageName, String name) {
|
||||
try {
|
||||
Bundle metaDate = context.getApplicationContext().getPackageManager().getApplicationInfo(
|
||||
packageName, PackageManager.GET_META_DATA).metaData;
|
||||
if (metaDate != null) {
|
||||
return metaDate.get(name);
|
||||
}
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* 判断是否可以更新,只判断gh_version的大小
|
||||
*/
|
||||
public static boolean isCanUpdate(Context context, GameUpdateEntity gameUpdateEntity) {
|
||||
// 判断是否gh_version是否存在
|
||||
String gh_version = (String) PackageUtils.getMetaData(
|
||||
context, gameUpdateEntity.getPackageName(), "gh_version");
|
||||
if (gh_version != null) {
|
||||
gh_version = gh_version.substring(2);
|
||||
// 判断gh_version的大小
|
||||
return Long.parseLong(gh_version) < Long.parseLong(gameUpdateEntity.getGhVersion());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 判断是否是插件包
|
||||
*/
|
||||
public static boolean isSignature(Context context, String packageName) {
|
||||
String signature = getApkSignatureByPackageName(context, packageName);
|
||||
return publicKey.equals(signature);
|
||||
}
|
||||
|
||||
/*
|
||||
* 判断是否是插件包
|
||||
*/
|
||||
public static boolean isSignature(Context context, String packageName) {
|
||||
String signature = getApkSignatureByPackageName(context, packageName);
|
||||
return publicKey.equals(signature);
|
||||
}
|
||||
/*
|
||||
* 根据包名,获取apk的签名信息
|
||||
*/
|
||||
public static String getApkSignatureByPackageName(Context context, String packageName) {
|
||||
try {
|
||||
PackageInfo packageInfo = context.getApplicationContext().getPackageManager()
|
||||
.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
|
||||
Signature[] signatures = packageInfo.signatures;
|
||||
return parseSignature(signatures[0].toByteArray())[0];
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* 根据apk路径,获取apk包名、签名 根据包名 判断 是否已安装游戏 根据签名 判断 是否一致
|
||||
*/
|
||||
public static boolean isCanLaunchSetup(Context context, String path) {
|
||||
String packageName = getPackageNameByPath(context, path);
|
||||
/*
|
||||
* 解析签名
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(packageName)) {
|
||||
return true;
|
||||
}
|
||||
boolean isContain = com.gh.gamecenter.manager.PackageManager.isInstalled(packageName);
|
||||
if (!isContain) {
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
* 启动安装应用程序
|
||||
*/
|
||||
public static void launchSetup(final Context context, final String path) {
|
||||
if (isCanLaunchSetup(context, path)) {
|
||||
context.startActivity(PackageUtils.getInstallIntent(context, path));
|
||||
} else {
|
||||
DialogUtils.showPluginDialog(context, new DialogUtils.ConfirmListener() {
|
||||
@Override
|
||||
public void onConfirm() {
|
||||
context.startActivity(PackageUtils.getUninstallIntent(context, path));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
boolean isInstalled = isInstalled(context, packageName);
|
||||
if (!isInstalled) {
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
* 根据apk路径,获取apk包名、签名 根据包名 判断 是否已安装游戏 根据签名 判断 是否一致
|
||||
*/
|
||||
public static boolean isCanLaunchSetup(Context context, String path) {
|
||||
String packageName = getPackageNameByPath(context, path);
|
||||
|
||||
String signature = getApkSignatureByPackageName(context, packageName);
|
||||
return publicKey.equals(signature);
|
||||
}
|
||||
if (TextUtils.isEmpty(packageName)) {
|
||||
return true;
|
||||
}
|
||||
boolean isContain = com.gh.gamecenter.manager.PackageManager.isInstalled(packageName);
|
||||
if (!isContain) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* 启动安装应用程序
|
||||
*/
|
||||
public static void launchSetup(final Context context, final String path) {
|
||||
if (isCanLaunchSetup(context, path)) {
|
||||
context.startActivity(PackageUtils.getInstallIntent(path));
|
||||
} else {
|
||||
DialogUtils.showPluginDialog(context, new DialogUtils.ConfiremListener() {
|
||||
@Override
|
||||
public void onConfirem() {
|
||||
context.startActivity(PackageUtils.getUninstallIntent(context, path));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
boolean isInstalled = isInstalled(context, packageName);
|
||||
if (!isInstalled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* 获取应用第一次安装的时间
|
||||
*/
|
||||
public static long getInstalledTime(Context context, String packageName) {
|
||||
try {
|
||||
PackageInfo packageInfo = context.getPackageManager()
|
||||
.getPackageInfo(packageName, 0);
|
||||
return packageInfo.firstInstallTime;
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
String signature = getApkSignatureByPackageName(context, packageName);
|
||||
return publicKey.equals(signature);
|
||||
}
|
||||
|
||||
/*
|
||||
* 解析签名
|
||||
*/
|
||||
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 Intent getInstallIntent(Context context, 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");
|
||||
InstallUtils.getInstance(context).addInstall(getPackageNameByPath(context, path));
|
||||
return installIntent;
|
||||
}
|
||||
|
||||
/*
|
||||
* 返回光环助手的版本信息
|
||||
*/
|
||||
public static String getVersionName(Context context) {
|
||||
try {
|
||||
PackageInfo pkgInfo = context.getPackageManager().getPackageInfo(
|
||||
context.getPackageName(), 0);
|
||||
return pkgInfo.versionName;
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/*
|
||||
* 根据包名,获取卸载游戏的意图
|
||||
*/
|
||||
public static Intent getUninstallIntent(Context context, String path) {
|
||||
Intent uninstallIntent = new Intent();
|
||||
uninstallIntent.setAction("android.intent.action.DELETE");
|
||||
uninstallIntent.addCategory("android.intent.category.DEFAULT");
|
||||
String packageName = getPackageNameByPath(context, path);
|
||||
uninstallIntent.setData(Uri.parse("package:" + packageName));
|
||||
InstallUtils.getInstance(context).addUninstall(packageName);
|
||||
return uninstallIntent;
|
||||
}
|
||||
|
||||
/*
|
||||
* 返回光环助手的版本code
|
||||
*/
|
||||
public static String getVersionCode(Context context) {
|
||||
try {
|
||||
PackageInfo pkgInfo = context.getPackageManager().getPackageInfo(
|
||||
context.getPackageName(), 0);
|
||||
return String.valueOf(pkgInfo.versionCode);
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/*
|
||||
* 根据路径,获取apk的包名
|
||||
*/
|
||||
public static String getPackageNameByPath(Context context, String path) {
|
||||
PackageManager packageManager = context.getApplicationContext().getPackageManager();
|
||||
PackageInfo info = packageManager.getPackageArchiveInfo(path,
|
||||
PackageManager.GET_ACTIVITIES);
|
||||
if (info != null) {
|
||||
ApplicationInfo appInfo = info.applicationInfo;
|
||||
return appInfo.packageName;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* 获取apk的版本
|
||||
*/
|
||||
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 boolean isInstalled(Context context, String packageName) {
|
||||
Intent intent = context.getApplicationContext().getPackageManager().getLaunchIntentForPackage(packageName);
|
||||
return intent != null;
|
||||
}
|
||||
|
||||
/*
|
||||
* 获取所有已安装的软件的包名、版本(非系统应用)
|
||||
*/
|
||||
public static ArrayList<String> getAllPackageName(Context context) {
|
||||
FilterManager filterManager = new FilterManager(context);
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
List<PackageInfo> packageInfos = context.getPackageManager().getInstalledPackages(0);
|
||||
for (PackageInfo packageInfo : packageInfos) {
|
||||
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 long getInstalledTime(Context context, String packageName) {
|
||||
try {
|
||||
PackageInfo packageInfo = context.getApplicationContext().getPackageManager()
|
||||
.getPackageInfo(packageName, 0);
|
||||
return packageInfo.firstInstallTime;
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 启动应用
|
||||
*/
|
||||
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 getVersionName(Context context) {
|
||||
try {
|
||||
PackageInfo pkgInfo = context.getApplicationContext().getPackageManager().getPackageInfo(
|
||||
context.getPackageName(), 0);
|
||||
return pkgInfo.versionName;
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* 根据包名,获取软件名称
|
||||
*/
|
||||
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;
|
||||
}
|
||||
/*
|
||||
* 返回光环助手的版本code
|
||||
*/
|
||||
public static String getVersionCode(Context context) {
|
||||
try {
|
||||
PackageInfo pkgInfo = context.getApplicationContext().getPackageManager().getPackageInfo(
|
||||
context.getPackageName(), 0);
|
||||
return String.valueOf(pkgInfo.versionCode);
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* 根据包名,判断是否已安装该游戏
|
||||
*/
|
||||
public static boolean isInstalled(Context context, String packageName) {
|
||||
Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
|
||||
return intent != null;
|
||||
}
|
||||
/*
|
||||
* 获取apk的版本
|
||||
*/
|
||||
public static String getVersionByPackage(Context context, String packageName) {
|
||||
try {
|
||||
return context.getApplicationContext().getPackageManager().getPackageInfo(packageName,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT).versionName;
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* 根据包名,获取卸载游戏的意图
|
||||
*/
|
||||
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 ArrayList<String> getAllPackageName(Context context) {
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
List<PackageInfo> packageInfos = context.getApplicationContext().getPackageManager().getInstalledPackages(0);
|
||||
for (PackageInfo packageInfo : packageInfos) {
|
||||
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
|
||||
if (!context.getPackageName().equals(packageInfo.packageName)) {
|
||||
list.add(packageInfo.packageName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/*
|
||||
* 根据路径,获取安装游戏的意图
|
||||
*/
|
||||
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 JSONArray getAppList(Context context) {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
try {
|
||||
PackageManager pm = context.getPackageManager();
|
||||
List<PackageInfo> packageInfos = pm.getInstalledPackages(0);
|
||||
for (PackageInfo packageInfo : packageInfos) {
|
||||
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("name", pm.getApplicationLabel(packageInfo.applicationInfo).toString());
|
||||
jsonObject.put("package", packageInfo.packageName);
|
||||
jsonObject.put("version", packageInfo.versionName);
|
||||
jsonArray.put(jsonObject);
|
||||
}
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return jsonArray;
|
||||
}
|
||||
|
||||
/*
|
||||
* 启动应用
|
||||
*/
|
||||
public static void launchApplicationByPackageName(Context context, String packageName) {
|
||||
try {
|
||||
Intent intent = context.getApplicationContext().getPackageManager().getLaunchIntentForPackage(packageName);
|
||||
if (intent != null) {
|
||||
context.startActivity(intent);
|
||||
} else {
|
||||
Toast.makeText(context, "启动失败", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(context, "启动失败", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 根据包名,获取软件名称
|
||||
*/
|
||||
public static String getNameByPackageName(Context context, String packageName) {
|
||||
try {
|
||||
PackageManager pm = context.getApplicationContext().getPackageManager();
|
||||
ApplicationInfo applicationInfo = pm.getApplicationInfo(
|
||||
packageName, 0);
|
||||
return applicationInfo.loadLabel(pm).toString();
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
32
app/src/main/java/com/gh/common/util/PatternUtils.java
Normal file
32
app/src/main/java/com/gh/common/util/PatternUtils.java
Normal file
@ -0,0 +1,32 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.util.Patterns;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
/**
|
||||
* @author CsHeng
|
||||
* @Date 17/05/2017
|
||||
* @Time 2:35 PM
|
||||
*/
|
||||
|
||||
public class PatternUtils {
|
||||
|
||||
// public static final Pattern VALID_EMAIL_ADDRESS_REGEX =
|
||||
// Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
// public static final Pattern VALIDATE_URL_REGEX =
|
||||
// Pattern.compile("((http://|ftp://|https://|www.))(([a-zA-Z0-9\\._-]+\\.[a-zA-Z]{2,6})|([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}))(:[0-9]{1,4})*(/[a-zA-Z0-9\\&%_\\./-~-]*)?");
|
||||
|
||||
public static boolean isEmailAddress(String emailStr) {
|
||||
Matcher matcher = Patterns.EMAIL_ADDRESS.matcher(emailStr);
|
||||
return matcher.matches();
|
||||
}
|
||||
|
||||
public static boolean isUrlAddress(String url) {
|
||||
Matcher matcher = Patterns.WEB_URL.matcher(url);
|
||||
return matcher.matches();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -7,280 +7,286 @@ import android.os.Handler;
|
||||
import android.support.v4.util.ArrayMap;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.gh.base.AppController;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.entity.PlatformEntity;
|
||||
import com.gh.gamecenter.eventbus.EBReuse;
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import de.greenrobot.event.EventBus;
|
||||
import retrofit2.adapter.rxjava.HttpException;
|
||||
import retrofit2.HttpException;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.schedulers.Schedulers;
|
||||
|
||||
public class PlatformUtils {
|
||||
|
||||
private static PlatformUtils mInstance;
|
||||
private static PlatformUtils mInstance;
|
||||
|
||||
private Context context;
|
||||
private Context context;
|
||||
|
||||
private ArrayMap<String, String> platformMap;
|
||||
private ArrayMap<String, Integer> platformPicMap;
|
||||
private ArrayMap<String, String> platformPicUrlMap;
|
||||
private ArrayMap<String, String> platformColorMap;
|
||||
private ArrayMap<String, String> platformMap;
|
||||
private ArrayMap<String, Integer> platformPicMap;
|
||||
private ArrayMap<String, String> platformPicUrlMap;
|
||||
private ArrayMap<String, String> platformColorMap;
|
||||
private boolean isCheck = false;
|
||||
private boolean isUpdate = false;
|
||||
|
||||
private PlatformUtils(Context con) {
|
||||
this.context = con.getApplicationContext();
|
||||
initMap();
|
||||
}
|
||||
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<String, Integer> 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);
|
||||
|
||||
private void initMap() {
|
||||
ArrayMap<String, Integer> 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<String, String> 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<String, String> 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<String, String> platformMap = new ArrayMap<>();
|
||||
ArrayMap<String, String> platformPicUrlMap = new ArrayMap<>();
|
||||
|
||||
ArrayMap<String, String> platformMap = new ArrayMap<>();
|
||||
ArrayMap<String, String> platformPicUrlMap = new ArrayMap<>();
|
||||
SharedPreferences sharedPreferences = context.getSharedPreferences(
|
||||
"gh_platform", Context.MODE_PRIVATE);
|
||||
Set<String> set = sharedPreferences.getStringSet("platform", null);
|
||||
if (set == null) {
|
||||
Properties properties = new Properties();
|
||||
try {
|
||||
properties
|
||||
.load(context.getAssets().open("platform.properties"));
|
||||
Set<String> 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<String> 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);
|
||||
}
|
||||
}
|
||||
|
||||
SharedPreferences sharedPreferences = context.getSharedPreferences(
|
||||
"gh_platform", Context.MODE_PRIVATE);
|
||||
Set<String> set = sharedPreferences.getStringSet("platform", null);
|
||||
if (set == null) {
|
||||
Properties properties = new Properties();
|
||||
try {
|
||||
properties
|
||||
.load(context.getAssets().open("platform.properties"));
|
||||
Set<String> 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<String> 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);
|
||||
}
|
||||
|
||||
updataPlatform(platformMap, platformPicMap, platformPicUrlMap,
|
||||
platformColorMap);
|
||||
}
|
||||
private void checkPlatformPic(final ArrayList<String> 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) {
|
||||
AppController.MAIN_EXECUTOR.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int success = 0;
|
||||
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);
|
||||
int code = FileUtils.downloadFile(url, savePath);
|
||||
if (code == HttpURLConnection.HTTP_OK) {
|
||||
success++;
|
||||
}
|
||||
}
|
||||
if (success == urls.size()) {
|
||||
Handler handler = new Handler(context.getMainLooper());
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
EventBus.getDefault().post(new EBReuse("PlatformChanged"));
|
||||
}
|
||||
});
|
||||
}
|
||||
isCheck = false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
isCheck = false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isCheck = false;
|
||||
private void updataPlatform(ArrayMap<String, String> pMap,
|
||||
ArrayMap<String, Integer> pPMap, ArrayMap<String, String> pUMap,
|
||||
ArrayMap<String, String> pCMap) {
|
||||
platformMap = pMap;
|
||||
platformPicMap = pPMap;
|
||||
platformPicUrlMap = pUMap;
|
||||
platformColorMap = pCMap;
|
||||
}
|
||||
|
||||
private void updataPlatform(ArrayMap<String, String> pMap,
|
||||
ArrayMap<String, Integer> pPMap, ArrayMap<String, String> pUMap,
|
||||
ArrayMap<String, String> pCMap) {
|
||||
platformMap = pMap;
|
||||
platformPicMap = pPMap;
|
||||
platformPicUrlMap = pUMap;
|
||||
platformColorMap = pCMap;
|
||||
}
|
||||
public static PlatformUtils getInstance(Context context) {
|
||||
if (mInstance == null) {
|
||||
mInstance = new PlatformUtils(context);
|
||||
}
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
private void checkPlatformPic(final ArrayList<String> 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() {
|
||||
int success =0;
|
||||
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);
|
||||
int code = FileUtils.downloadFile(url, savePath);
|
||||
if (code == HttpURLConnection.HTTP_OK) {
|
||||
success++;
|
||||
}
|
||||
}
|
||||
if (success == urls.size()) {
|
||||
Handler handler = new Handler(context.getMainLooper());
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
EventBus.getDefault().post(new EBReuse("PlatformChanged"));
|
||||
}
|
||||
});
|
||||
}
|
||||
isCheck = false;
|
||||
}
|
||||
}.start();
|
||||
} else {
|
||||
isCheck = false;
|
||||
}
|
||||
}
|
||||
public String getPlatformColor(String platform) {
|
||||
if ("".equals(platform) || "官方版".equals(platform)) {
|
||||
return "#BB3D42";
|
||||
}
|
||||
String color = platformColorMap.get(platform);
|
||||
if (color != null) {
|
||||
return color;
|
||||
}
|
||||
return "#00B7FA";
|
||||
}
|
||||
|
||||
public String getPlatformColor(String platform) {
|
||||
if ("".equals(platform) || "官方版".equals(platform)) {
|
||||
return "#BB3D42";
|
||||
}
|
||||
String color = platformColorMap.get(platform);
|
||||
if (color != null) {
|
||||
return color;
|
||||
}
|
||||
return "#00B7FA";
|
||||
}
|
||||
public int getPlatformPic(String platform) {
|
||||
if ("".equals(platform) || "官方版".equals(platform)) {
|
||||
return R.drawable.platform_gf;
|
||||
}
|
||||
Integer id = platformPicMap.get(platform);
|
||||
if (id != null) {
|
||||
return id;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getPlatformPic(String platform) {
|
||||
if ("".equals(platform) || "官方版".equals(platform)) {
|
||||
return R.drawable.platform_gf;
|
||||
}
|
||||
Integer id = platformPicMap.get(platform);
|
||||
if (id != null) {
|
||||
return id;
|
||||
}
|
||||
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<String> urls = new ArrayList<>();
|
||||
for (String value : platformPicUrlMap.values()) {
|
||||
urls.add(value);
|
||||
}
|
||||
checkPlatformPic(urls);
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
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<String> 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)) {
|
||||
return "官方版";
|
||||
}
|
||||
String platformName = platformMap.get(platform);
|
||||
if (TextUtils.isEmpty(platformName)) {
|
||||
getPlatform();
|
||||
}
|
||||
return platformName;
|
||||
}
|
||||
|
||||
public String getPlatformName(String platform) {
|
||||
if ("".equals(platform) || "官方版".equals(platform)) {
|
||||
return "官方版";
|
||||
}
|
||||
String platformName = platformMap.get(platform);
|
||||
if (TextUtils.isEmpty(platformName)) {
|
||||
getPlatform();
|
||||
}
|
||||
return platformName;
|
||||
}
|
||||
public void getPlatform() {
|
||||
if (isUpdate) {
|
||||
return;
|
||||
}
|
||||
isUpdate = true;
|
||||
RetrofitManager.getApi().getGamePlatform()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<List<PlatformEntity>>() {
|
||||
@Override
|
||||
public void onResponse(List<PlatformEntity> response) {
|
||||
Set<String> platformSet = new HashSet<>();
|
||||
for (PlatformEntity platformEntity : response) {
|
||||
platformSet.add(platformEntity.toString());
|
||||
}
|
||||
SharedPreferences sp = context.getSharedPreferences("gh_platform", Context.MODE_PRIVATE);
|
||||
sp.edit().putStringSet("platform", platformSet).apply();
|
||||
initMap();
|
||||
EventBus.getDefault().post(new EBReuse("PlatformChanged"));
|
||||
|
||||
boolean isUpdate = false;
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
|
||||
String today = format.format(new Date());
|
||||
sp.edit().putString("refresh_time", today).apply();
|
||||
isUpdate = false;
|
||||
}
|
||||
|
||||
public void getPlatform() {
|
||||
if (isUpdate) {
|
||||
return;
|
||||
}
|
||||
isUpdate = true;
|
||||
RetrofitManager.getApi().getGamePlatform()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<List<PlatformEntity>>(){
|
||||
@Override
|
||||
public void onResponse(List<PlatformEntity> response) {
|
||||
Set<String> platformSet = new HashSet<>();
|
||||
for (PlatformEntity platformEntity : response) {
|
||||
platformSet.add(platformEntity.toString());
|
||||
}
|
||||
SharedPreferences sp = context.getSharedPreferences("gh_platform", Context.MODE_PRIVATE);
|
||||
sp.edit().putStringSet("platform", platformSet).apply();
|
||||
initMap();
|
||||
EventBus.getDefault().post(new EBReuse("PlatformChanged"));
|
||||
|
||||
isUpdate = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(HttpException e) {
|
||||
isUpdate = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
@Override
|
||||
public void onFailure(HttpException e) {
|
||||
isUpdate = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.gh.gamecenter.entity.CommentEntity;
|
||||
import com.gh.gamecenter.retrofit.JSONObjectResponse;
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
@ -11,7 +12,7 @@ import org.json.JSONObject;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.ResponseBody;
|
||||
import retrofit2.adapter.rxjava.HttpException;
|
||||
import retrofit2.HttpException;
|
||||
import rx.Observable;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.functions.Func1;
|
||||
@ -19,18 +20,23 @@ import rx.schedulers.Schedulers;
|
||||
|
||||
/**
|
||||
* Created by khy on 2016/11/9.
|
||||
*
|
||||
*/
|
||||
public class PostCommentUtils {
|
||||
|
||||
public static void addCommentData(final Context context, final String newsId, final String content,
|
||||
final boolean isCheck, final PostCommentListener listener) {
|
||||
final boolean isCheck, final CommentEntity commentEntity,
|
||||
final PostCommentListener listener) {
|
||||
TokenUtils.getToken(context, isCheck)
|
||||
.flatMap(new Func1<String, Observable<ResponseBody>>() {
|
||||
@Override
|
||||
public Observable<ResponseBody> call(String token) {
|
||||
RequestBody body = RequestBody.create(MediaType.parse("application/json"), content);
|
||||
return RetrofitManager.getComment().postNewsComment(token, newsId, body);
|
||||
|
||||
if (commentEntity != null) {
|
||||
return RetrofitManager.getComment().postReplyComment(token, commentEntity.getId(), body);
|
||||
} else {
|
||||
return RetrofitManager.getComment().postNewsComment(token, newsId, body);
|
||||
}
|
||||
}
|
||||
})
|
||||
.subscribeOn(Schedulers.io())
|
||||
@ -39,21 +45,27 @@ public class PostCommentUtils {
|
||||
@Override
|
||||
public void onResponse(JSONObject response) {
|
||||
if (response.length() != 0) {
|
||||
if (listener != null){
|
||||
listener.postSucced(response);
|
||||
if (listener != null) {
|
||||
listener.postSuccess(response);
|
||||
}
|
||||
} else {
|
||||
Utils.toast(context, "提交失败,请检查网络设置");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
super.onError(e);
|
||||
Utils.log("======" + e.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(HttpException e) {
|
||||
if (e != null && e.code() == 401) {
|
||||
addCommentData(context, newsId, content, false, listener);
|
||||
addCommentData(context, newsId, content, false, commentEntity, listener);
|
||||
return;
|
||||
}
|
||||
if (listener != null){
|
||||
if (listener != null) {
|
||||
listener.postFailed(e);
|
||||
}
|
||||
}
|
||||
@ -75,7 +87,7 @@ public class PostCommentUtils {
|
||||
@Override
|
||||
public void onResponse(ResponseBody response) {
|
||||
if (listener != null) {
|
||||
listener.postSucced(null);
|
||||
listener.postSuccess(null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,7 +105,7 @@ public class PostCommentUtils {
|
||||
}
|
||||
|
||||
public static void addReportData(final Context context, final String reportData, boolean isCheck,
|
||||
final PostCommentListener listener) {
|
||||
final PostCommentListener listener) {
|
||||
TokenUtils.getToken(context, isCheck)
|
||||
.flatMap(new Func1<String, Observable<ResponseBody>>() {
|
||||
@Override
|
||||
@ -107,7 +119,7 @@ public class PostCommentUtils {
|
||||
.subscribe(new Response<ResponseBody>() {
|
||||
@Override
|
||||
public void onResponse(ResponseBody response) {
|
||||
listener.postSucced(null);
|
||||
listener.postSuccess(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -122,7 +134,8 @@ public class PostCommentUtils {
|
||||
}
|
||||
|
||||
public interface PostCommentListener {
|
||||
void postSucced(JSONObject response);
|
||||
void postSuccess(JSONObject response);
|
||||
|
||||
void postFailed(Throwable error);
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user