Compare commits
226 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f3fab1b3f6 | |||
| 5340a41298 | |||
| caf2a379d9 | |||
| c59b79427c | |||
| e54fcca53e | |||
| ad416c6a5d | |||
| 4a65c1a5c8 | |||
| 878529f646 | |||
| d01bc1e2d1 | |||
| d63f5f5ab2 | |||
| ad0fb7a55a | |||
| b0258eef77 | |||
| 86d4df8ad9 | |||
| bb11d984f9 | |||
| d3f3d2ca98 | |||
| 0c1e712c79 | |||
| e193a40651 | |||
| 03f36476cb | |||
| a721637be3 | |||
| 722fb1ad64 | |||
| 52a05c3aa4 | |||
| bcbdac6afc | |||
| a9507af3f4 | |||
| 68601ca8be | |||
| a7adc27896 | |||
| d19d0eb571 | |||
| d8e365fe08 | |||
| b34f61ce0d | |||
| 1f24d16f95 | |||
| 738074ec00 | |||
| c8eee33475 | |||
| badf9f9c20 | |||
| 0398cc4ffc | |||
| b88abf6b9a | |||
| a0d193bc52 | |||
| 6ac635f8c6 | |||
| 30c7d71114 | |||
| 0223b3ab22 | |||
| c9663662d5 | |||
| 12bed97638 | |||
| a857af970d | |||
| 7da621583f | |||
| 46a32b62c2 | |||
| 45bcc95e7d | |||
| 7d7bcfaa1d | |||
| 3a9a561c77 | |||
| e8d344256a | |||
| 1a7c1119bf | |||
| 0b6a2503aa | |||
| 459b9f65a9 | |||
| 6c1ebe531e | |||
| 604450292b | |||
| e42361e84a | |||
| a974652f7f | |||
| 309ab54e90 | |||
| 486d680c26 | |||
| 61a5f3a275 | |||
| c865417a4b | |||
| b142feaaae | |||
| 7380854133 | |||
| 8a0f185eda | |||
| bd9604a53e | |||
| 1aeab51f94 | |||
| b16a6fedc6 | |||
| b97c381ed4 | |||
| acb8c723a3 | |||
| 4492307e23 | |||
| e31224b332 | |||
| 6933d6c590 | |||
| 3d58841ce5 | |||
| 0654b0a25f | |||
| 44dde3f91b | |||
| abad30595f | |||
| c4df411560 | |||
| 2974fa4562 | |||
| b086b1cb0c | |||
| 22cf026335 | |||
| 90bd53fe61 | |||
| 9c580a356e | |||
| 7198c28e6f | |||
| 7bf074fddc | |||
| bea1a336e9 | |||
| 97a9e03192 | |||
| 244d57b6bc | |||
| 3cbd484147 | |||
| 8b81819c30 | |||
| 1873ac5d4e | |||
| cf70c1e7fe | |||
| 6f6b26ea4d | |||
| e2708d9078 | |||
| fb5a40c6e4 | |||
| e2a10c1410 | |||
| 5461d3d548 | |||
| c47365e626 | |||
| 3476f8df3a | |||
| f812c1e5c8 | |||
| 391f196005 | |||
| 097dbca26e | |||
| a147118381 | |||
| e6bdde8273 | |||
| 747757faa7 | |||
| 6f21b9d0ae | |||
| e505554aac | |||
| 3323cce890 | |||
| ffd468db1e | |||
| e98e0d1522 | |||
| 13a4f2014c | |||
| 8cbfe6450a | |||
| bcc866888e | |||
| 60911d5dcb | |||
| 7e77d5749e | |||
| 6c3be5627d | |||
| f6a9585700 | |||
| 06fddb7dcd | |||
| 3a3f9a625b | |||
| 3702b104fc | |||
| 3e023089a1 | |||
| 7455674f6b | |||
| c93c0f2fc6 | |||
| 727f02e571 | |||
| 784fae1f5d | |||
| 42ef075912 | |||
| 15307c5223 | |||
| aad3b48883 | |||
| d65d8f1c4c | |||
| c581496975 | |||
| d5481a8888 | |||
| e0a61278fc | |||
| 2c36283833 | |||
| 1b5a8f3a7e | |||
| 95c918b4e3 | |||
| f32cc1673c | |||
| f0fc2f06da | |||
| b6c6abaa5b | |||
| 6ed67c911c | |||
| 1eda223a1e | |||
| 316c0c28ab | |||
| 895d4d5cf1 | |||
| 877df95e02 | |||
| 801f0b95e7 | |||
| 9019f555b5 | |||
| 106b03a316 | |||
| d8faa554be | |||
| 93080a74a7 | |||
| 3ea2ede0cb | |||
| 1242848b6f | |||
| 24d44a2c90 | |||
| 971779a529 | |||
| 14f561c237 | |||
| 3a38e746f6 | |||
| dd3bc9d39d | |||
| 39a8062aef | |||
| 55b6ccb760 | |||
| a8a55eb9bd | |||
| 3eb73439aa | |||
| 466e118579 | |||
| b38032074b | |||
| 9ee771e528 | |||
| 9253ed47e6 | |||
| bc82263286 | |||
| 11979240ab | |||
| 255e6182a9 | |||
| f170abb7ea | |||
| eb80deb413 | |||
| 10ba5a9ba5 | |||
| 94c49cba8b | |||
| 354dca8b04 | |||
| 034488ff34 | |||
| 59c70e23dd | |||
| 7d98a842f1 | |||
| 5f8006dc5a | |||
| 239bd69580 | |||
| bc96f102a1 | |||
| e2ef3f4d01 | |||
| 5c20bbf5e4 | |||
| b07edd256a | |||
| 1478d37889 | |||
| 7151b56de3 | |||
| 220fd9528b | |||
| 1c26c35571 | |||
| 78eb6b7b02 | |||
| 9dc9add896 | |||
| 2d09f8c008 | |||
| 166e1e77ec | |||
| ea782d002b | |||
| f525a3c46d | |||
| bef6cbb212 | |||
| 5e0af8654a | |||
| 032a89e0cd | |||
| c9afb6df02 | |||
| b8092447ff | |||
| bff20bea49 | |||
| 87f2d9c85f | |||
| 154dfc8538 | |||
| 59c4176983 | |||
| fddcdfb3aa | |||
| cdbf7d39a5 | |||
| 6a55821d4d | |||
| a305db7b13 | |||
| 58b1cd4b12 | |||
| 5e7559e43f | |||
| 2a74e35388 | |||
| 5b9bef79da | |||
| e89750c364 | |||
| 9da6cbf097 | |||
| f83f719283 | |||
| 4a1c81ffb4 | |||
| be26f5168b | |||
| 4e6c75995c | |||
| df693ce0c2 | |||
| f0236d7ad5 | |||
| 1d3e2b5c16 | |||
| 545d257135 | |||
| f5164d2102 | |||
| 9af83be9a7 | |||
| 49b0b982f5 | |||
| ad7543e7bc | |||
| 1bd0db013b | |||
| e63a374da1 | |||
| 6564de8a72 | |||
| d57ac57f43 | |||
| 942291d7c5 | |||
| de597bdd36 | |||
| e1fc23a1bb | |||
| 2d551a3f73 | |||
| 9b205366f7 |
@ -266,6 +266,7 @@ dependencies {
|
||||
// for video streaming
|
||||
implementation("com.shuyu:gsyVideoPlayer-java:$gsyVideo", {
|
||||
exclude module: "gsyvideoplayer-androidvideocache"
|
||||
exclude group: "tv.danmaku.ijk.media"
|
||||
})
|
||||
implementation "com.shuyu:GSYVideoPlayer-exo2:$gsyVideo"
|
||||
|
||||
@ -288,9 +289,14 @@ dependencies {
|
||||
|
||||
implementation "com.airbnb.android:lottie:$lottie"
|
||||
|
||||
implementation "net.lingala.zip4j:zip4j:${zip4j}"
|
||||
|
||||
implementation("com.github.piasy:BigImageViewer:$bigImageViewer", {
|
||||
exclude group: 'com.squareup.okhttp3'
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
exclude group: 'com.github.bumptech.glide'
|
||||
})
|
||||
implementation "com.github.PhilJay:MPAndroidChart:${chart}"
|
||||
|
||||
implementation project(':libraries:LGLibrary')
|
||||
implementation project(':libraries:MTA')
|
||||
@ -300,7 +306,6 @@ dependencies {
|
||||
// implementation project(':libraries:WechatShare')
|
||||
implementation project(':libraries:im')
|
||||
implementation project(':libraries:Matisse')
|
||||
implementation project(path: ':libraries:gsyVideoPlayer-proxy_cache')
|
||||
}
|
||||
File propFile = file('sign.properties')
|
||||
if (propFile.exists()) {
|
||||
|
||||
@ -113,7 +113,9 @@
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<!--android:theme = "@android:style/Theme.Black.NoTitleBar.Fullscreen" 退出时屏幕抖动 -->
|
||||
<activity android:name="com.gh.gamecenter.ViewImageActivity" />
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.ImageViewerActivity"
|
||||
android:theme="@style/Theme.Transparent" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.SearchActivity"
|
||||
@ -177,9 +179,9 @@
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:theme="@style/TransparentStatusBarAndNavigationBar"
|
||||
android:name="com.gh.gamecenter.MessageDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/TransparentStatusBarAndNavigationBar" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.LibaoActivity"
|
||||
@ -208,8 +210,8 @@
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.CommentDetailActivity"
|
||||
android:theme="@style/TransparentStatusBarAndNavigationBar"
|
||||
android:screenOrientation="portrait" />
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/TransparentStatusBarAndNavigationBar" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.mygame.MyGameActivity"
|
||||
@ -419,9 +421,9 @@
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:theme="@style/TransparentStatusBarAndNavigationBar"
|
||||
android:name="com.gh.gamecenter.gamedetail.rating.RatingReplyActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/TransparentStatusBarAndNavigationBar" />
|
||||
|
||||
<activity
|
||||
android:name="com.gh.gamecenter.history.HistoryActivity"
|
||||
@ -514,6 +516,20 @@
|
||||
<activity
|
||||
android:name=".qa.answer.draft.AnswerDraftActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name=".gamedetail.rating.RatingFoldActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name=".video.data.VideoDataActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".video.poster.PosterEditActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<activity
|
||||
android:name=".video.poster.PosterClipActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
|
||||
<!-- 使用小米/华为推送弹窗功能提高推送成功率-->
|
||||
<activity
|
||||
@ -607,7 +623,9 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<meta-data android:name="com.huawei.hms.client.appid" android:value="@string/huawei_push_appid"/>
|
||||
<meta-data
|
||||
android:name="com.huawei.hms.client.appid"
|
||||
android:value="@string/huawei_push_appid" />
|
||||
|
||||
<service
|
||||
android:name="com.gh.base.GHUmengNotificationService"
|
||||
|
||||
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright 2018 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 androidx.swiperefreshlayout.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RadialGradient;
|
||||
import android.graphics.Shader;
|
||||
import android.graphics.drawable.ShapeDrawable;
|
||||
import android.graphics.drawable.shapes.OvalShape;
|
||||
import android.view.View;
|
||||
import android.view.animation.Animation;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
/**
|
||||
* Private class created to work around issues with AnimationListeners being
|
||||
* called before the animation is actually complete and support shadows on older
|
||||
* platforms.
|
||||
*/
|
||||
class CircleImageView extends ImageView {
|
||||
|
||||
private static final int KEY_SHADOW_COLOR = 0x1E000000;
|
||||
private static final int FILL_SHADOW_COLOR = 0x3D000000;
|
||||
// PX
|
||||
private static final float X_OFFSET = 0f;
|
||||
private static final float Y_OFFSET = 1.75f;
|
||||
private static final float SHADOW_RADIUS = 3.5f;
|
||||
private static final int SHADOW_ELEVATION = 4;
|
||||
|
||||
private Animation.AnimationListener mListener;
|
||||
int mShadowRadius;
|
||||
|
||||
CircleImageView(Context context, int color) {
|
||||
super(context);
|
||||
final float density = getContext().getResources().getDisplayMetrics().density;
|
||||
final int shadowYOffset = (int) (density * Y_OFFSET);
|
||||
final int shadowXOffset = (int) (density * X_OFFSET);
|
||||
|
||||
mShadowRadius = (int) (density * SHADOW_RADIUS);
|
||||
|
||||
ShapeDrawable circle;
|
||||
if (elevationSupported()) {
|
||||
circle = new ShapeDrawable(new OvalShape());
|
||||
ViewCompat.setElevation(this, SHADOW_ELEVATION * density);
|
||||
} else {
|
||||
OvalShape oval = new OvalShadow(mShadowRadius);
|
||||
circle = new ShapeDrawable(oval);
|
||||
setLayerType(View.LAYER_TYPE_SOFTWARE, circle.getPaint());
|
||||
circle.getPaint().setShadowLayer(mShadowRadius, shadowXOffset, shadowYOffset,
|
||||
KEY_SHADOW_COLOR);
|
||||
final int padding = mShadowRadius;
|
||||
// set padding so the inner image sits correctly within the shadow.
|
||||
setPadding(padding, padding, padding, padding);
|
||||
}
|
||||
circle.getPaint().setColor(color);
|
||||
ViewCompat.setBackground(this, circle);
|
||||
}
|
||||
|
||||
private boolean elevationSupported() {
|
||||
return android.os.Build.VERSION.SDK_INT >= 21;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
if (!elevationSupported()) {
|
||||
setMeasuredDimension(getMeasuredWidth() + mShadowRadius * 2, getMeasuredHeight()
|
||||
+ mShadowRadius * 2);
|
||||
}
|
||||
}
|
||||
|
||||
public void setAnimationListener(Animation.AnimationListener listener) {
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationStart() {
|
||||
super.onAnimationStart();
|
||||
if (mListener != null) {
|
||||
mListener.onAnimationStart(getAnimation());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd() {
|
||||
super.onAnimationEnd();
|
||||
if (mListener != null) {
|
||||
mListener.onAnimationEnd(getAnimation());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the background color of the circle image view.
|
||||
*
|
||||
* @param colorRes Id of a color resource.
|
||||
*/
|
||||
public void setBackgroundColorRes(int colorRes) {
|
||||
setBackgroundColor(ContextCompat.getColor(getContext(), colorRes));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackgroundColor(int color) {
|
||||
if (getBackground() instanceof ShapeDrawable) {
|
||||
((ShapeDrawable) getBackground()).getPaint().setColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
private class OvalShadow extends OvalShape {
|
||||
private RadialGradient mRadialGradient;
|
||||
private Paint mShadowPaint;
|
||||
|
||||
OvalShadow(int shadowRadius) {
|
||||
super();
|
||||
mShadowPaint = new Paint();
|
||||
mShadowRadius = shadowRadius;
|
||||
updateRadialGradient((int) rect().width());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResize(float width, float height) {
|
||||
super.onResize(width, height);
|
||||
updateRadialGradient((int) width);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas, Paint paint) {
|
||||
final int viewWidth = CircleImageView.this.getWidth();
|
||||
final int viewHeight = CircleImageView.this.getHeight();
|
||||
canvas.drawCircle(viewWidth / 2, viewHeight / 2, viewWidth / 2, mShadowPaint);
|
||||
canvas.drawCircle(viewWidth / 2, viewHeight / 2, viewWidth / 2 - mShadowRadius, paint);
|
||||
}
|
||||
|
||||
private void updateRadialGradient(int diameter) {
|
||||
mRadialGradient = new RadialGradient(diameter / 2, diameter / 2,
|
||||
mShadowRadius, new int[] { FILL_SHADOW_COLOR, Color.TRANSPARENT },
|
||||
null, Shader.TileMode.CLAMP);
|
||||
mShadowPaint.setShader(mRadialGradient);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -18,12 +18,17 @@ import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
|
||||
import com.gh.base.fragment.BaseFragment;
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.PackageInstaller;
|
||||
import com.gh.common.util.RunningUtils;
|
||||
import com.gh.common.util.ShareUtils;
|
||||
import com.gh.common.util.StringUtils;
|
||||
@ -44,10 +49,6 @@ import org.json.JSONObject;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import butterknife.ButterKnife;
|
||||
import pub.devrel.easypermissions.EasyPermissions;
|
||||
|
||||
@ -206,7 +207,7 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
|
||||
if (FileUtils.isEmptyFile(showDialog.getPath())) {
|
||||
toast(R.string.install_failure_hint);
|
||||
} else {
|
||||
startActivity(PackageUtils.getUninstallIntent(BaseActivity.this, showDialog.getPath()));
|
||||
PackageInstaller.uninstall(BaseActivity.this, showDialog.getPath());
|
||||
}
|
||||
});
|
||||
} else if (LOGIN_EXCEPTION.equals(showDialog.getType())) {
|
||||
|
||||
@ -14,6 +14,13 @@ import android.view.Window;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.DownloadManagerActivity;
|
||||
@ -31,13 +38,6 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
|
||||
/**
|
||||
* 需要用到工具栏的页面使用
|
||||
* <p>
|
||||
@ -49,7 +49,7 @@ public abstract class ToolBarActivity extends BaseActivity implements ToolbarCon
|
||||
@Nullable
|
||||
private PackageViewModel mPackageViewModel;
|
||||
|
||||
protected RelativeLayout mToolbarContainer;
|
||||
protected View mToolbarContainer;
|
||||
|
||||
protected Toolbar mToolbar;
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ import android.os.Looper
|
||||
import com.gh.common.AppExecutor.ioExecutor
|
||||
import com.gh.common.AppExecutor.lightWeightIoExecutor
|
||||
import com.gh.common.AppExecutor.uiExecutor
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import java.util.concurrent.Executor
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
@ -25,6 +26,8 @@ object AppExecutor {
|
||||
@JvmStatic
|
||||
val ioExecutor = Executors.newCachedThreadPool() // 用 by lazy 可能影响初始化速度
|
||||
|
||||
val cachedScheduler by lazy { Schedulers.from(ioExecutor) }
|
||||
|
||||
class MainThreadExecutor : Executor {
|
||||
private val mainThreadHandler = Handler(Looper.getMainLooper())
|
||||
|
||||
|
||||
@ -4,12 +4,13 @@ import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.webkit.JavascriptInterface
|
||||
import androidx.annotation.Keep
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.gh.base.CurrentActivityHolder
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.view.dsbridge.CompletionHandler
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.ImageViewerActivity
|
||||
import com.gh.gamecenter.LoginActivity
|
||||
import com.gh.gamecenter.ViewImageActivity
|
||||
import com.gh.gamecenter.entity.Badge
|
||||
import com.gh.gamecenter.entity.MtaEvent
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
@ -70,7 +71,6 @@ class DefaultJsApi(var context: Context) {
|
||||
userInfoEntity.badge = null
|
||||
}
|
||||
UserManager.getInstance().userInfoEntity = userInfoEntity
|
||||
AppDatabase.getInstance(context).userInfoDao().updateUserInfo(userInfoEntity)
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
@ -139,7 +139,21 @@ class DefaultJsApi(var context: Context) {
|
||||
|
||||
val context = CurrentActivityHolder.getCurrentActivity()
|
||||
|
||||
context?.startActivity(ViewImageActivity.getViewImageIntent(context, imageEvent.imageList, imageEvent.position, "浏览器"))
|
||||
context?.startActivity(ImageViewerActivity.getIntent(context, imageEvent.imageList, imageEvent.position, "浏览器"))
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun isInstalled(event: Any): String {
|
||||
val localInstalledPackageList = PackageUtils.getAllPackageName(HaloApp.getInstance().application)
|
||||
val packageNameList: ArrayList<String> = event.toString().toObject() ?: ArrayList()
|
||||
|
||||
for (packageName in packageNameList) {
|
||||
if (!localInstalledPackageList.contains(packageName)) {
|
||||
return "false"
|
||||
}
|
||||
}
|
||||
|
||||
return "true"
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
@ -148,7 +162,12 @@ class DefaultJsApi(var context: Context) {
|
||||
|
||||
Base64ImageHolder.image = event.toString()
|
||||
|
||||
context?.startActivity(ViewImageActivity.getBase64ViewImageIntent(context, true))
|
||||
context?.startActivity(ImageViewerActivity.getBase64Intent(context, true))
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun openNotificationSetting(msg: Any){
|
||||
NotificationHelper.show(context as AppCompatActivity)
|
||||
}
|
||||
|
||||
@Keep
|
||||
|
||||
@ -4,15 +4,14 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.text.TextUtils
|
||||
import com.gh.common.util.CheckLoginUtils
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.DirectUtils
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.DirectUtils.directToGameDetailVideoStreaming
|
||||
import com.gh.common.util.DirectUtils.directToGameVideo
|
||||
import com.gh.common.util.DirectUtils.directToVideoDetail
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.gamecenter.*
|
||||
import com.gh.gamecenter.entity.CommunityEntity
|
||||
import com.gh.gamecenter.entity.SimpleGameEntity
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity
|
||||
import com.gh.gamecenter.entity.VideoLinkEntity
|
||||
import com.gh.gamecenter.subject.SubjectActivity
|
||||
@ -50,7 +49,7 @@ object DefaultUrlHandler {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
"qqqun" -> {
|
||||
EntranceUtils.HOST_QQ_QUN -> {
|
||||
val key = uri.getQueryParameter("key")
|
||||
if (!DirectUtils.directToQqGroup(context, key)) {
|
||||
Utils.toast(context, "请检查是否已经安装手机QQ")
|
||||
@ -125,11 +124,11 @@ object DefaultUrlHandler {
|
||||
val categoryId = uri.getQueryParameter("category_id") ?: ""
|
||||
val link = uri.getQueryParameter("link") ?: ""
|
||||
val linkEntity = VideoLinkEntity(title, categoryId, link)
|
||||
// if (!CheckLoginUtils.isLogin()) {
|
||||
// HaloApp.put(EntranceUtils.HOST_UPLOAD_VIDEO, linkEntity)
|
||||
// }
|
||||
val gameId = uri.getQueryParameter("gameId") ?: ""
|
||||
val gameName = uri.getQueryParameter("gameName") ?: ""
|
||||
val simpleGameEntity = SimpleGameEntity(gameId, gameName)
|
||||
CheckLoginUtils.checkLogin(context, null, true, EntranceUtils.ENTRANCE_BROWSER) {
|
||||
DirectUtils.directToVideoManager(context, linkEntity, EntranceUtils.ENTRANCE_BROWSER, "")
|
||||
DirectUtils.directToVideoManager(context, linkEntity, simpleGameEntity, EntranceUtils.ENTRANCE_BROWSER, "")
|
||||
}
|
||||
}
|
||||
EntranceUtils.HOST_USERHOME -> {
|
||||
@ -140,8 +139,17 @@ object DefaultUrlHandler {
|
||||
val referer = uri.getQueryParameter("referer") ?: ""
|
||||
val type = uri.getQueryParameter("type") ?: ""
|
||||
val act = uri.getQueryParameter("act") ?: ""
|
||||
val loaction = if (TextUtils.isEmpty(act)) id else VideoDetailContainerViewModel.Location.VIDEO_ACTIVITY.value
|
||||
directToVideoDetail(context, id, loaction, false, "", entrance, "", referer, type, act)
|
||||
val gameId = uri.getQueryParameter("gameId") ?: ""
|
||||
val fieldId = uri.getQueryParameter("fieldId") ?: ""
|
||||
val sectionName = uri.getQueryParameter("sectionName") ?: ""
|
||||
val location = if (!TextUtils.isEmpty(act)) {
|
||||
VideoDetailContainerViewModel.Location.VIDEO_ACTIVITY.value
|
||||
} else if (!TextUtils.isEmpty(fieldId)) {
|
||||
VideoDetailContainerViewModel.Location.GAME_ZONE.value
|
||||
} else {
|
||||
id
|
||||
}
|
||||
directToVideoDetail(context, id, location, false, gameId, entrance, "", referer, type, act, fieldId, sectionName)
|
||||
}
|
||||
EntranceUtils.HOST_VIDEO_SINGLE -> {
|
||||
val referer = uri.getQueryParameter("referer") ?: ""
|
||||
@ -191,7 +199,7 @@ object DefaultUrlHandler {
|
||||
val name = uri.getQueryParameter("name")
|
||||
?: ""
|
||||
val entity = SubjectRecommendEntity(link = id, name = name, text = name)
|
||||
DirectUtils.directToBlock(context, entity)
|
||||
DirectUtils.directToBlock(context, entity, entrance)
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_SERVER_BLOCK -> {
|
||||
@ -215,14 +223,116 @@ object DefaultUrlHandler {
|
||||
}
|
||||
|
||||
EntranceUtils.HOST_GAME_UPLOAD -> {
|
||||
DirectUtils.directGameUpload(context,entrance = entrance, path = "")
|
||||
DirectUtils.directGameUpload(context, entrance = entrance, path = "")
|
||||
}
|
||||
EntranceUtils.HOST_GAME_ZONE -> {
|
||||
val zoneUrl = uri.getQueryParameter("url") ?: ""
|
||||
DirectUtils.directGameZone(context, id, zoneUrl, entrance)
|
||||
}
|
||||
|
||||
else -> DialogUtils.showLowVersionDialog(context)
|
||||
}
|
||||
return true
|
||||
} else if ("zhiqu" == uri.scheme) {
|
||||
if (PackageUtils.isInstalled(context, "com.beieryouxi.zqyxh")) {
|
||||
val intent = Intent()
|
||||
intent.data = Uri.parse(url)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
context.startActivity(intent)
|
||||
} else {
|
||||
Utils.toast(context, "请安装指趣游戏盒")
|
||||
}
|
||||
}
|
||||
|
||||
if (url.startsWith("alipays:") || url.startsWith("alipay")) {
|
||||
try {
|
||||
context.startActivity(Intent("android.intent.action.VIEW", Uri.parse(url)))
|
||||
} catch (e: Exception) {
|
||||
ToastUtils.showToast("请安装支付宝客户端")
|
||||
}
|
||||
return true
|
||||
} else if (url.startsWith("weixin")) {
|
||||
try {
|
||||
context.startActivity(Intent("android.intent.action.VIEW", Uri.parse(url)))
|
||||
} catch (e: Exception) {
|
||||
ToastUtils.showToast("请安装微信客户端")
|
||||
}
|
||||
return true
|
||||
} else if (url.startsWith("mqqwpa")) {
|
||||
try {
|
||||
context.startActivity(Intent("android.intent.action.VIEW", Uri.parse(url)))
|
||||
} catch (e: Exception) {
|
||||
ToastUtils.showToast("请安装QQ客户端")
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
if ("http" != uri.scheme && "https" != uri.scheme) return true
|
||||
return false
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun transformNormalScheme(context: Context, url: String, entrance: String): Boolean {
|
||||
val uri = Uri.parse(url)
|
||||
if (uri.host == "www.ghzs666.com" || uri.host == "www.ghzs.com" || uri.host == "ask.ghzs.com" || uri.host == "m.ghzs.com") {
|
||||
Utils.log(uri.path)
|
||||
uri.path?.apply {
|
||||
when {
|
||||
contains("game") -> {
|
||||
val gameId = uri.getQueryParameter("gameId") ?: ""
|
||||
DirectUtils.directToGameDetail(context, gameId, entrance, autoDownload = false, scrollToLibao = false, traceEvent = null)
|
||||
}
|
||||
contains("question") -> {
|
||||
val questionId = split("/")[2]
|
||||
val answerId = uri.getQueryParameter("answer")
|
||||
if (answerId.isNullOrEmpty()) {
|
||||
DirectUtils.directToQuestionDetail(context, questionId, entrance, "")
|
||||
} else {
|
||||
DirectUtils.directToAnswerDetail(context, answerId, entrance, "")
|
||||
}
|
||||
}
|
||||
contains("communities") && contains("article") -> {
|
||||
var communityId = ""
|
||||
var type = ""
|
||||
var typeId = ""
|
||||
val split = replace("/communities", "").replace(".html", "").split("/".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
for (text in split) {
|
||||
if (TextUtils.isEmpty(communityId)) {
|
||||
communityId = text
|
||||
continue
|
||||
}
|
||||
if (TextUtils.isEmpty(type)) {
|
||||
type = text
|
||||
continue
|
||||
}
|
||||
if (TextUtils.isEmpty(typeId)) {
|
||||
typeId = text
|
||||
}
|
||||
}
|
||||
if ("articles" == type) {
|
||||
DirectUtils.directToCommunityArticle(
|
||||
context, typeId, communityId,
|
||||
entrance, "文章链接")
|
||||
}
|
||||
}
|
||||
contains("article") -> {
|
||||
val articleId = split("/")[2].replace(".html", "")
|
||||
DirectUtils.directToArticle(context, articleId, entrance)
|
||||
}
|
||||
contains("columns") -> {
|
||||
val columnsId = split("/")[3]
|
||||
val id = uri.getQueryParameter("communityId") ?: ""
|
||||
val name = uri.getQueryParameter("communityName") ?: ""
|
||||
DirectUtils.directToCommunityColumn(context, CommunityEntity(id, name), columnsId, entrance, "")
|
||||
}
|
||||
contains("zone") -> {
|
||||
val gameId = split("/")[2]
|
||||
DirectUtils.directGameZone(context, gameId, url, entrance)
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,6 @@ import com.gh.gamecenter.entity.TimeEntity
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import kotlin.concurrent.fixedRateTimer
|
||||
|
||||
object FixedRateJobHelper {
|
||||
@ -31,7 +30,7 @@ object FixedRateJobHelper {
|
||||
// 时间校对,10分钟一次
|
||||
if ((mExecuteCount * CHECKER_PERIOD) % TIME_PERIOD == 0L) {
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application).api.time
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribeOn(AppExecutor.cachedScheduler)
|
||||
.subscribe(object : Response<TimeEntity>() {
|
||||
override fun onResponse(response: TimeEntity?) {
|
||||
val serverTime = response?.time
|
||||
|
||||
@ -12,11 +12,12 @@ public class Constants {
|
||||
|
||||
public final static int NOT_NETWORK_CODE = 504; // 没有网络的状态码(应该是这个吧!)
|
||||
|
||||
public static final String LOGIN_TOKEN_ID = "userToken_id"; // 用户ID 与服务器无关
|
||||
|
||||
public static final String USER_TOKEN_KEY = "userTokenKey";
|
||||
public static final String USER_INFO_KEY = "userInfoKey";
|
||||
|
||||
public static final String WELCOME_DIALOG_ID = "welcome_dialog_id";
|
||||
public static final String WELCOME_DIALOG_LINK_TITLE = "welcome_dialog_link_title";
|
||||
|
||||
public static final String DEVICE_KEY = "deviceKey";
|
||||
|
||||
public static final String HAS_REQUESTED_NOTIFICATION_PERMISSIONS = "has_requested_notification_permissions";
|
||||
@ -28,12 +29,12 @@ public class Constants {
|
||||
public static final String XPOSED_INSTALLER_PACKAGE_NAME = "de.robv.android.xposed.installer";
|
||||
|
||||
public static final String EB_QUIT_LOGIN = "quit_login";
|
||||
|
||||
|
||||
// 用于避免历史下载掺和到普通下载状态的 ID 修饰符
|
||||
public static final String GAME_ID_DIVIDER = ":";
|
||||
// 用于避免历史下载影响到部分依赖名字作为数据更新条件的修饰符
|
||||
public static final String GAME_NAME_DECORATOR = " ";
|
||||
|
||||
|
||||
// 游戏详情进入时的自定义栏目标签是否已经默认展开过一次的标记
|
||||
public static final String SP_HAS_EXPANDED_GAME_DETAIL_TAGS = "has_expanded_game_detail_tags";
|
||||
// 游戏详情进入时的自定义栏目标签是否已经显示过一次展开更多的浮窗提示
|
||||
@ -42,7 +43,11 @@ public class Constants {
|
||||
// 最近显示的弹窗信息
|
||||
public static final String SP_LAST_OPENING_ID = "last_opening_dialog_id";
|
||||
public static final String SP_LAST_OPENING_TIME = "last_opening_dialog_time";
|
||||
|
||||
|
||||
// 游戏图标和图标角标
|
||||
public static final String RAW_GAME_ICON = "raw_game_icon";
|
||||
public static final String GAME_ICON_SUBSCRIPT = "game_icon_subscript";
|
||||
|
||||
// 新用户首次启动光环的时间
|
||||
public static final String SP_INITIAL_USAGE_TIME = "initial_usage_time";
|
||||
|
||||
@ -108,6 +113,9 @@ public class Constants {
|
||||
public static final String BADGE_ADDRESS_DEV = "http://resource.ghzs.com/page/badge_dev/index.html#/";
|
||||
public static final String BADGE_ADDRESS = "http://resource.ghzs.com/page/badge_pro/index.html#/";
|
||||
|
||||
// 腾讯企点地址
|
||||
public static final String TENCENT_QIDIAN_ADDRESS = "https://url.cn/D80iyMVV?_type=wpa&qidian=true";
|
||||
|
||||
//最少需要多少数据才能上传
|
||||
public static final int DATA_AMOUNT = 20;
|
||||
|
||||
|
||||
@ -40,12 +40,14 @@ import com.gh.common.util.LogUtils;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.common.util.NewsUtils;
|
||||
import com.gh.common.util.NumberUtils;
|
||||
import com.gh.common.util.PackageInstaller;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.PermissionHelper;
|
||||
import com.gh.common.util.PlatformUtils;
|
||||
import com.gh.common.util.ReservationHelper;
|
||||
import com.gh.common.view.DownloadProgressBar;
|
||||
import com.gh.common.view.DrawableView;
|
||||
import com.gh.common.view.GameIconView;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.download.dialog.DownloadDialog;
|
||||
import com.gh.gamecenter.DownloadManagerActivity;
|
||||
@ -313,6 +315,13 @@ public class BindingAdapters {
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("game")
|
||||
public static void setGame(View view, GameEntity gameEntity) {
|
||||
if (gameEntity != null && view instanceof GameIconView) {
|
||||
((GameIconView) view).setGameEntity(gameEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("articleType")
|
||||
public static void setArticleType(TextView view, String articleType) {
|
||||
NewsUtils.setNewsType(view, articleType, 0, 0);
|
||||
@ -427,15 +436,16 @@ public class BindingAdapters {
|
||||
case PLUGIN:
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
ApkEntity apk = gameEntity.getApk().get(0);
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(v.getContext(), gameEntity, apk,
|
||||
() -> {
|
||||
CertificationDialog.showCertificationDialog(v.getContext(), gameEntity, () -> {
|
||||
DialogUtils.showVersionNumberDialog(v.getContext(), gameEntity, () -> {
|
||||
DialogUtils.checkDownload(v.getContext(), apk.getSize(),
|
||||
isSubscribe -> download(progressBar, gameEntity, traceEvent, isSubscribe, entrance, location));
|
||||
});
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(v.getContext(), gameEntity, apk, () -> {
|
||||
CertificationDialog.showCertificationDialog(v.getContext(), gameEntity, () -> {
|
||||
DialogUtils.showVersionNumberDialog(v.getContext(), gameEntity, () -> {
|
||||
DialogUtils.showOverseaDownloadDialog(v.getContext(), gameEntity, () -> {
|
||||
DialogUtils.checkDownload(v.getContext(), apk.getSize(),
|
||||
isSubscribe -> download(progressBar, gameEntity, traceEvent, isSubscribe, entrance, location));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
CertificationDialog.showCertificationDialog(v.getContext(), gameEntity, () -> {
|
||||
DialogUtils.showVersionNumberDialog(v.getContext(), gameEntity, () -> {
|
||||
@ -467,7 +477,7 @@ public class BindingAdapters {
|
||||
if (gameEntity.getApk().size() == 1) {
|
||||
DownloadEntity downloadEntity = DownloadManager.getInstance(progressBar.getContext()).getDownloadEntityByUrl(gameEntity.getApk().get(0).getUrl());
|
||||
if (downloadEntity != null) {
|
||||
PackageUtils.launchSetup(v.getContext(), downloadEntity);
|
||||
PackageInstaller.install(v.getContext(), downloadEntity);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -506,7 +516,7 @@ public class BindingAdapters {
|
||||
HistoryHelper.insertGameEntity(gameEntity);
|
||||
}
|
||||
|
||||
Intent i = new Intent(WebActivity.getIntentForWebGame(progressBar.getContext(), linkEntity.getLink(), gameEntity.getName(), isPlay));
|
||||
Intent i = new Intent(WebActivity.getIntentForWebGame(progressBar.getContext(), linkEntity.getLink(), gameEntity.getName(), isPlay,linkEntity.getCloseButton()));
|
||||
progressBar.getContext().startActivity(i);
|
||||
break;
|
||||
}
|
||||
@ -775,4 +785,17 @@ public class BindingAdapters {
|
||||
}
|
||||
view.setText(span);
|
||||
}
|
||||
|
||||
@BindingAdapter({"setVideoData"})
|
||||
public static void setVideoData(TextView view, int count) {
|
||||
if (count > 0) {
|
||||
view.setCompoundDrawablesWithIntrinsicBounds(ContextCompat.getDrawable(view.getContext(), R.drawable.ic_video_data_up), null, null, null);
|
||||
view.setTextColor(ContextCompat.getColor(view.getContext(), R.color.text_EA3333));
|
||||
view.setText(count + "");
|
||||
} else {
|
||||
view.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
|
||||
view.setTextColor(ContextCompat.getColor(view.getContext(), R.color.text_999999));
|
||||
view.setText("-");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,13 +4,13 @@ import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import android.os.Bundle
|
||||
import android.text.Html
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.*
|
||||
import android.view.animation.AnimationUtils
|
||||
import android.widget.EditText
|
||||
import android.widget.TextView
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import butterknife.BindView
|
||||
import butterknife.ButterKnife
|
||||
import butterknife.OnClick
|
||||
@ -24,31 +24,58 @@ import com.gh.gamecenter.entity.GameEntity
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
|
||||
// 预约弹窗
|
||||
class ReserveDialogFragment
|
||||
: BaseDialogFragment() {
|
||||
: BaseDialogFragment(), KeyboardHeightObserver {
|
||||
// : BaseTrackableDialogFragment() {
|
||||
|
||||
@BindView(R.id.reserve_hint_tv)
|
||||
lateinit var reserveHintTv: TextView
|
||||
|
||||
@BindView(R.id.reserve_content_tv)
|
||||
lateinit var reserveContentTv: TextView
|
||||
|
||||
@BindView(R.id.reserve_completed_content_tv)
|
||||
lateinit var reserveCompletedContentTv: TextView
|
||||
|
||||
@BindView(R.id.mobile_et)
|
||||
lateinit var mobileEt: EditText
|
||||
|
||||
@BindView(R.id.reserve_container)
|
||||
lateinit var reserveContainer: View
|
||||
|
||||
@BindView(R.id.reserve_completed_container)
|
||||
lateinit var reserveCompletedContainer: View
|
||||
|
||||
@BindView(R.id.customizable_btn)
|
||||
lateinit var customizableBtn: TextView
|
||||
|
||||
@BindView(R.id.content_container)
|
||||
lateinit var contentContainer: View
|
||||
|
||||
@BindView(R.id.mobile_index_container)
|
||||
lateinit var mobileIndexContainer: View
|
||||
|
||||
@BindView(R.id.mobile_index_reserve)
|
||||
lateinit var mobileIndexReserve: TextView
|
||||
|
||||
@BindView(R.id.mobile_index_user)
|
||||
lateinit var mobileIndexUser: TextView
|
||||
|
||||
@BindView(R.id.mobile_et_delete)
|
||||
lateinit var mobileEtDelete: View
|
||||
|
||||
@BindView(R.id.layout_container)
|
||||
lateinit var layoutContainer: View
|
||||
|
||||
private lateinit var mViewModel: ReserveViewModel
|
||||
|
||||
private var mSuccessCallback: SuccessCallback? = null
|
||||
@ -57,10 +84,19 @@ class ReserveDialogFragment
|
||||
private var mGameId: String = ""
|
||||
private var mGameName: String = ""
|
||||
|
||||
private var mKeyboardHeightProvider: KeyboardHeightProvider? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
mViewModel = viewModelProvider()
|
||||
mKeyboardHeightProvider = KeyboardHeightProvider(activity)
|
||||
mKeyboardHeightProvider?.start()
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
@ -81,11 +117,14 @@ class ReserveDialogFragment
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
ButterKnife.bind(this, view)
|
||||
|
||||
val reserveContent = "游戏上线,您将<font color='#ff4147'>免费</font>收到短信提醒"
|
||||
|
||||
val reserveContent = "游戏上线,您将收到<font color='#1383EB'>免费短信</font>提醒"
|
||||
reserveContentTv.text = Html.fromHtml(reserveContent)
|
||||
mobileEt.setText(UserManager.getInstance().userInfoEntity.mobile)
|
||||
mobileEt.setSelection(mobileEt.text.length)
|
||||
|
||||
|
||||
mobileEt.setTextChangedListener { s, _, _, _ ->
|
||||
mobileIndexContainer.visibility = View.GONE
|
||||
mobileEtDelete.goneIf(s.trim().isEmpty())
|
||||
}
|
||||
|
||||
mViewModel.reservation.observeNonNull(this) {
|
||||
if (it.success) {
|
||||
@ -94,6 +133,11 @@ class ReserveDialogFragment
|
||||
HistoryHelper.insertGameEntity(mGame!!)
|
||||
}
|
||||
}
|
||||
|
||||
mViewModel.reserveMobile.observe(viewLifecycleOwner, Observer {
|
||||
setMobileIndexHint(it)
|
||||
})
|
||||
|
||||
dialog?.setCanceledOnTouchOutside(true)
|
||||
}
|
||||
|
||||
@ -123,18 +167,57 @@ class ReserveDialogFragment
|
||||
}
|
||||
}
|
||||
|
||||
private fun setMobileIndexHint(reserveMobile: String?) {
|
||||
var userMobile = UserManager.getInstance().userInfoEntity.mobile
|
||||
if (reserveMobile == userMobile) userMobile = null
|
||||
|
||||
if (!reserveMobile.isNullOrEmpty()) {
|
||||
mobileIndexReserve.visibility = View.VISIBLE
|
||||
mobileIndexReserve.text = reserveMobile
|
||||
} else {
|
||||
mobileIndexReserve.visibility = View.GONE
|
||||
}
|
||||
|
||||
if (!userMobile.isNullOrEmpty()) {
|
||||
mobileIndexUser.visibility = View.VISIBLE
|
||||
mobileIndexUser.text = userMobile
|
||||
} else {
|
||||
mobileIndexUser.visibility = View.GONE
|
||||
}
|
||||
mobileIndexContainer.goneIf(mobileIndexUser.visibility == View.GONE && mobileIndexReserve.visibility == View.GONE)
|
||||
if (mobileIndexContainer.visibility ==View.VISIBLE) {
|
||||
mobileIndexContainer.animation = AnimationUtils.loadAnimation(requireContext(), R.anim.reserve_dialog_index_anim)
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.reserve_with_mobile_btn,
|
||||
R.id.reserve_without_mobile_btn,
|
||||
R.id.content_container,
|
||||
R.id.close_btn,
|
||||
R.id.customizable_btn)
|
||||
R.id.customizable_btn,
|
||||
R.id.mobile_index_reserve,
|
||||
R.id.mobile_index_user,
|
||||
R.id.mobile_et_delete,
|
||||
R.id.mobile_et,
|
||||
R.id.layout_container)
|
||||
fun onClick(view: View) {
|
||||
when (view.id) {
|
||||
R.id.reserve_without_mobile_btn -> {
|
||||
// MtaHelper.onEvent("预约游戏", "预约功能操作", "点击无手机号预约")
|
||||
if (mobileIndexContainer.visibility == View.VISIBLE) {
|
||||
mobileIndexContainer.visibility = View.GONE
|
||||
return
|
||||
}
|
||||
|
||||
mViewModel.reserve(gameId = mGameId, gameName = mGameName)
|
||||
}
|
||||
|
||||
R.id.reserve_with_mobile_btn -> {
|
||||
if (mobileIndexContainer.visibility == View.VISIBLE) {
|
||||
mobileIndexContainer.visibility = View.GONE
|
||||
return
|
||||
}
|
||||
|
||||
val mobile = mobileEt.text.toString()
|
||||
if (mobile.length < 11 || !mobile.startsWith("1")) {
|
||||
Utils.toast(context, "手机号格式错误,请检查并重新输入")
|
||||
@ -149,6 +232,61 @@ class ReserveDialogFragment
|
||||
// MtaHelper.onEvent("预约游戏", "预约功能操作", "点击关闭")
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
R.id.content_container -> {
|
||||
mobileIndexContainer.visibility = View.GONE
|
||||
}
|
||||
R.id.mobile_index_reserve -> {
|
||||
mobileEt.setText(mobileIndexReserve.text.toString())
|
||||
mobileEt.setSelection(mobileEt.text.length)
|
||||
mobileIndexContainer.visibility = View.GONE
|
||||
}
|
||||
R.id.mobile_index_user -> {
|
||||
mobileEt.setText(mobileIndexUser.text.toString())
|
||||
mobileEt.setSelection(mobileEt.text.length)
|
||||
mobileIndexContainer.visibility = View.GONE
|
||||
}
|
||||
R.id.mobile_et_delete -> {
|
||||
mobileEt.setText("")
|
||||
}
|
||||
R.id.mobile_et -> {
|
||||
mobileIndexContainer.visibility = View.GONE
|
||||
}
|
||||
R.id.layout_container -> {
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (HaloApp.getInstance().mCacheKeyboardHeight > 0) {
|
||||
val attributes = dialog?.window?.attributes
|
||||
val heightPixels = requireContext().resources.displayMetrics.heightPixels
|
||||
val mCacheKeyboardHeight = HaloApp.getInstance().mCacheKeyboardHeight
|
||||
val statusBarHeight = DisplayUtils.getStatusBarHeight(requireContext().resources)
|
||||
dialog?.window?.attributes?.height = heightPixels - mCacheKeyboardHeight - statusBarHeight
|
||||
attributes?.gravity = Gravity.TOP
|
||||
dialog?.window?.attributes = attributes
|
||||
}
|
||||
mKeyboardHeightProvider?.setKeyboardHeightObserver(this)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mKeyboardHeightProvider?.setKeyboardHeightObserver(null)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mKeyboardHeightProvider?.close()
|
||||
}
|
||||
|
||||
override fun onKeyboardHeightChanged(height: Int, orientation: Int) {
|
||||
if (height > 0) {
|
||||
val attributes = dialog?.window?.attributes
|
||||
attributes?.gravity = Gravity.CENTER
|
||||
dialog?.window?.attributes = attributes
|
||||
HaloApp.getInstance().mCacheKeyboardHeight = height
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,6 +308,12 @@ class ReserveDialogFragment
|
||||
class ReserveViewModel(application: Application) : AndroidViewModel(application) {
|
||||
val reservation = MutableLiveData<Reservation>()
|
||||
|
||||
val reserveMobile = MutableLiveData<String>()
|
||||
|
||||
init {
|
||||
getAppointmentMobile()
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
fun reserve(gameId: String, gameName: String, mobile: String = "") {
|
||||
|
||||
@ -201,5 +345,30 @@ class ReserveViewModel(application: Application) : AndroidViewModel(application)
|
||||
})
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private fun getAppointmentMobile() {
|
||||
RetrofitManager.getInstance(getApplication()).api
|
||||
.getAppointmentMobile(UserManager.getInstance().userId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<ResponseBody>() {
|
||||
override fun onSuccess(data: ResponseBody) {
|
||||
var mobile: String? = null
|
||||
tryCatchInRelease {
|
||||
val jsonArray = JSONArray(data.string())
|
||||
if (jsonArray.length() > 0) {
|
||||
mobile = jsonArray.get(0).toString()
|
||||
}
|
||||
}
|
||||
|
||||
reserveMobile.postValue(mobile)
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
reserveMobile.postValue(null)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
class Reservation(var success: Boolean = false, var withMobile: Boolean = false, var boundWechat: Boolean = false)
|
||||
}
|
||||
@ -15,5 +15,11 @@ data class ExposureEntity(
|
||||
val sequence: Int? = 0,
|
||||
val platform: String? = "",
|
||||
val downloadType: String? = "",
|
||||
val downloadCompleteType: String? = ""
|
||||
val downloadCompleteType: String? = "",
|
||||
|
||||
// 统计启动弹窗相关数据用的 (ugly)
|
||||
@SerializedName("dialog_id")
|
||||
var welcomeDialogId: String? = "",
|
||||
@SerializedName("link_title")
|
||||
var welcomeDialogLinkTitle: String? = ""
|
||||
) : Parcelable
|
||||
@ -39,7 +39,10 @@ data class ExposureEvent(
|
||||
sequence = gameEntity?.sequence,
|
||||
platform = gameEntity?.platform,
|
||||
downloadType = gameEntity?.downloadType,
|
||||
downloadCompleteType = gameEntity?.downloadCompleteType),
|
||||
downloadCompleteType = gameEntity?.downloadCompleteType,
|
||||
// ugly
|
||||
welcomeDialogId = gameEntity?.welcomeDialogId ?: eTrace?.firstOrNull()?.payload?.welcomeDialogId,
|
||||
welcomeDialogLinkTitle = gameEntity?.welcomeDialogTitle ?: eTrace?.firstOrNull()?.payload?.welcomeDialogLinkTitle),
|
||||
source = source,
|
||||
eTrace = eTrace,
|
||||
event = event).apply { gameEntity?.exposureEvent = this }
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.gh.common.filter
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import com.gh.common.AppExecutor
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.util.SPUtils
|
||||
import com.gh.common.util.toJson
|
||||
@ -60,10 +61,11 @@ object RegionSettingHelper {
|
||||
@SuppressLint("CheckResult")
|
||||
@JvmStatic
|
||||
fun getRegionSetting() {
|
||||
// 使用默认的 Schdulers.io() 可能会触发 OOM
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application)
|
||||
.sensitiveApi
|
||||
.getRegionSetting(HaloApp.getInstance().channel)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribeOn(AppExecutor.cachedScheduler)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<RegionSetting>() {
|
||||
override fun onSuccess(data: RegionSetting) {
|
||||
|
||||
@ -15,7 +15,7 @@ import com.gh.gamecenter.room.converter.*
|
||||
import com.gh.gamecenter.room.dao.*
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
@Database(entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class, MyVideoEntity::class], version = 6, exportSchema = false)
|
||||
@Database(entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class, MyVideoEntity::class], version = 7, exportSchema = false)
|
||||
@TypeConverters(CountConverter::class,
|
||||
CommunityConverter::class,
|
||||
TimeConverter::class,
|
||||
@ -63,12 +63,19 @@ abstract class HistoryDatabase : RoomDatabase() {
|
||||
}
|
||||
}
|
||||
|
||||
val MIGRATION_6_7: Migration = object : Migration(6, 7) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("Alter TABLE HistoryGameEntity add iconSubscript TEXT DEFAULT ''")
|
||||
}
|
||||
}
|
||||
|
||||
val instance by lazy {
|
||||
Room.databaseBuilder(HaloApp.getInstance().application, HistoryDatabase::class.java, "USER_TRACK_HISTORY_DATABASE")
|
||||
.addMigrations(MIGRATION_2_3)
|
||||
.addMigrations(MIGRATION_3_4)
|
||||
.addMigrations(MIGRATION_4_5)
|
||||
.addMigrations(MIGRATION_5_6)
|
||||
.addMigrations(MIGRATION_6_7)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,7 +41,8 @@ object HistoryHelper {
|
||||
historyGame.id = updateEntity.id
|
||||
historyGame.brief = updateEntity.brief
|
||||
historyGame.des = ""
|
||||
historyGame.icon = updateEntity.icon
|
||||
historyGame.icon = updateEntity.rawIcon ?: updateEntity.icon
|
||||
historyGame.iconSubscript = historyGame.iconSubscript
|
||||
historyGame.name = updateEntity.name
|
||||
historyGame.tagStyle = updateEntity.tagStyle
|
||||
historyGame.tag = updateEntity.tag
|
||||
@ -55,11 +56,11 @@ object HistoryHelper {
|
||||
historyGame.id = gameEntity.id
|
||||
historyGame.brief = gameEntity.brief
|
||||
historyGame.des = gameEntity.des
|
||||
historyGame.icon = gameEntity.icon
|
||||
historyGame.icon = gameEntity.rawIcon ?: gameEntity.icon
|
||||
historyGame.iconSubscript = gameEntity.iconSubscript
|
||||
historyGame.name = gameEntity.name
|
||||
historyGame.tagStyle = gameEntity.tagStyle
|
||||
historyGame.tag = gameEntity.getTag()
|
||||
historyGame.isLibaoExist = gameEntity.isLibaoExists
|
||||
return historyGame
|
||||
}
|
||||
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
package com.gh.common.loghub
|
||||
|
||||
import android.app.Application
|
||||
import androidx.annotation.Keep
|
||||
import com.aliyun.sls.android.sdk.model.Log
|
||||
import com.aliyun.sls.android.sdk.model.LogGroup
|
||||
import com.gh.common.exposure.ExposureEntity
|
||||
import com.gh.common.exposure.meta.Meta
|
||||
import com.gh.loghub.LoghubHelper
|
||||
import org.json.JSONObject
|
||||
import java.util.concurrent.Executors
|
||||
@ -43,6 +46,23 @@ object LoghubUtils {
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun log(jsonString: String, logStore: String, forcedUpload: Boolean) {
|
||||
loghubEventExecutor.execute {
|
||||
try {
|
||||
val event = LoghubEvent(time = (System.currentTimeMillis() / 1000L).toString(), content = jsonString, logStore = logStore)
|
||||
loghubEventSet.add(event)
|
||||
loghubEventDao.insert(event)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
if (forcedUpload || loghubEventSet.size >= STORE_SIZE) {
|
||||
commitSavedLoghubEvents()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun uploadLogGroup(logGroup: LogGroup, logStore: String) {
|
||||
LoghubHelper.getInstance().uploadLogGroup(logGroup, logStore)
|
||||
}
|
||||
@ -86,4 +106,12 @@ object LoghubUtils {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
data class SimpleLogContainerEntity(
|
||||
var event: String? = null,
|
||||
var action: String? = null,
|
||||
var meta: Meta? = null,
|
||||
var payload: ExposureEntity? = null,
|
||||
var timestamp: Long? = 0)
|
||||
6
app/src/main/java/com/gh/common/util/BiCallback.kt
Normal file
6
app/src/main/java/com/gh/common/util/BiCallback.kt
Normal file
@ -0,0 +1,6 @@
|
||||
package com.gh.common.util
|
||||
|
||||
interface BiCallback<FIRST, SECOND> {
|
||||
fun onFirst(first: FIRST)
|
||||
fun onSecond(second: SECOND)
|
||||
}
|
||||
@ -1,14 +1,19 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.content.Context
|
||||
import android.text.TextUtils
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import com.gh.common.util.CommentUtils.copyText
|
||||
import com.gh.common.view.BugFixedPopupWindow
|
||||
import com.gh.gamecenter.CommentDetailActivity
|
||||
import com.gh.gamecenter.MessageDetailActivity
|
||||
import com.gh.gamecenter.adapter.OnCommentCallBackListener
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.CommentEntity
|
||||
import com.gh.gamecenter.entity.MeEntity
|
||||
import com.gh.gamecenter.entity.Permissions
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.qa.comment.OnCommentOptionClickListener
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.lightgame.utils.Utils
|
||||
@ -23,13 +28,13 @@ import retrofit2.HttpException
|
||||
object CommentHelper {
|
||||
|
||||
@JvmStatic
|
||||
fun showCommunityArticleCommentOptions(context: Context,
|
||||
fun showCommunityArticleCommentOptions(view: View,
|
||||
commentEntity: CommentEntity,
|
||||
showConversation: Boolean,
|
||||
articleId: String,
|
||||
communityId: String,
|
||||
listener: OnCommentCallBackListener?) {
|
||||
showCommentOptions(context = context,
|
||||
listener: OnCommentOptionClickListener?) {
|
||||
showCommentOptions(view = view,
|
||||
commentEntity = commentEntity,
|
||||
showConversation = showConversation,
|
||||
articleId = articleId,
|
||||
@ -38,12 +43,12 @@ object CommentHelper {
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun showAnswerCommentOptions(context: Context,
|
||||
fun showAnswerCommentOptions(view: View,
|
||||
commentEntity: CommentEntity,
|
||||
showConversation: Boolean,
|
||||
answerId: String,
|
||||
listener: OnCommentCallBackListener?) {
|
||||
showCommentOptions(context = context,
|
||||
listener: OnCommentOptionClickListener?) {
|
||||
showCommentOptions(view = view,
|
||||
commentEntity = commentEntity,
|
||||
showConversation = showConversation,
|
||||
answerId = answerId,
|
||||
@ -51,27 +56,34 @@ object CommentHelper {
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun showVideoCommentOptions(context: Context,
|
||||
fun showVideoCommentOptions(view: View,
|
||||
commentEntity: CommentEntity,
|
||||
showConversation: Boolean,
|
||||
videoId: String,
|
||||
listener: OnCommentCallBackListener?) {
|
||||
showCommentOptions(context = context,
|
||||
isVideoAuthor: Boolean,
|
||||
listener: OnCommentOptionClickListener?) {
|
||||
showCommentOptions(view = view,
|
||||
commentEntity = commentEntity,
|
||||
showConversation = showConversation,
|
||||
videoId = videoId,
|
||||
isVideoAuthor = isVideoAuthor,
|
||||
listener = listener)
|
||||
}
|
||||
|
||||
private fun showCommentOptions(context: Context,
|
||||
private fun showCommentOptions(view: View,
|
||||
commentEntity: CommentEntity,
|
||||
showConversation: Boolean,
|
||||
articleId: String? = null,
|
||||
communityId: String? = null,
|
||||
answerId: String? = null,
|
||||
videoId: String? = null,
|
||||
listener: OnCommentCallBackListener? = null) {
|
||||
isVideoAuthor: Boolean = false,
|
||||
listener: OnCommentOptionClickListener? = null) {
|
||||
val context = view.context
|
||||
val dialogOptions = ArrayList<String>()
|
||||
if (isVideoAuthor || (videoId != null && commentEntity.user.id == UserManager.getInstance().userId)) {
|
||||
dialogOptions.add("删除评论")
|
||||
}
|
||||
dialogOptions.add("复制")
|
||||
dialogOptions.add("投诉")
|
||||
|
||||
@ -88,55 +100,75 @@ object CommentHelper {
|
||||
dialogOptions.add("查看对话")
|
||||
}
|
||||
|
||||
DialogUtils.showListDialog(context, dialogOptions, null) {
|
||||
when (it) {
|
||||
"管理" -> showControlDialog(context, answerId, articleId, communityId, commentEntity, commentEntity.me!!)
|
||||
val inflater = LayoutInflater.from(context)
|
||||
val layout = inflater.inflate(R.layout.comment_more_option, null)
|
||||
val popupWindow = BugFixedPopupWindow(layout,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT)
|
||||
val container = layout.findViewById<LinearLayout>(R.id.container)
|
||||
for (text in dialogOptions) {
|
||||
val item = inflater.inflate(R.layout.comment_more_option_item, container, false)
|
||||
container.addView(item)
|
||||
|
||||
"复制" -> copyText(commentEntity.content, context)
|
||||
val hitText = item.findViewById<TextView>(R.id.hint_text)
|
||||
hitText.text = text
|
||||
|
||||
"投诉" -> {
|
||||
context.ifLogin("回答详情-评论-投诉") {
|
||||
showReportTypeDialog(context) { reportType ->
|
||||
item.setOnClickListener {
|
||||
popupWindow.dismiss()
|
||||
listener?.onCommentOptionClick(commentEntity, text)
|
||||
when (text) {
|
||||
"管理" -> showControlDialog(context, answerId, articleId, communityId, commentEntity, commentEntity.me!!)
|
||||
|
||||
val commentListener = object : PostCommentUtils.PostCommentListener {
|
||||
override fun postSuccess(response: JSONObject?) {
|
||||
Utils.toast(context, "感谢您的投诉")
|
||||
}
|
||||
"复制" -> copyText(commentEntity.content, context)
|
||||
|
||||
override fun postFailed(error: Throwable?) {
|
||||
if (error == null) {
|
||||
Utils.toast(context, "投诉失败,请稍后重试")
|
||||
} else {
|
||||
Utils.toast(context, "投诉失败,${error.message}")
|
||||
"投诉" -> {
|
||||
context.ifLogin("回答详情-评论-投诉") {
|
||||
showReportTypeDialog(context) { reportType ->
|
||||
|
||||
val commentListener = object : PostCommentUtils.PostCommentListener {
|
||||
override fun postSuccess(response: JSONObject?) {
|
||||
Utils.toast(context, "感谢您的投诉")
|
||||
}
|
||||
|
||||
override fun postFailed(error: Throwable?) {
|
||||
if (error == null) {
|
||||
Utils.toast(context, "投诉失败,请稍后重试")
|
||||
} else {
|
||||
Utils.toast(context, "投诉失败,${error.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (answerId != null) {
|
||||
PostCommentUtils.postAnswerReportData(context, commentEntity.id, answerId, reportType, commentListener)
|
||||
} else if (articleId != null) {
|
||||
PostCommentUtils.reportCommunityArticleComment(context, communityId, articleId, commentEntity.id, reportType, commentListener)
|
||||
} else {
|
||||
PostCommentUtils.reportVideoComment(context, videoId, commentEntity.id, reportType, commentListener)
|
||||
if (answerId != null) {
|
||||
PostCommentUtils.postAnswerReportData(context, commentEntity.id, answerId, reportType, commentListener)
|
||||
} else if (articleId != null) {
|
||||
PostCommentUtils.reportCommunityArticleComment(context, communityId, articleId, commentEntity.id, reportType, commentListener)
|
||||
} else {
|
||||
PostCommentUtils.reportVideoComment(context, videoId, commentEntity.id, reportType, commentListener)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"查看对话" -> {
|
||||
if (answerId != null) {
|
||||
context.startActivity(CommentDetailActivity
|
||||
.getAnswerCommentIntent(context, commentEntity.id, answerId, null))
|
||||
} else if (articleId != null) {
|
||||
context.startActivity(CommentDetailActivity
|
||||
.getCommunityArticleCommentIntent(context, articleId, commentEntity.id, communityId, null))
|
||||
} else {
|
||||
context.startActivity(CommentDetailActivity
|
||||
.getVideoCommentIntent(context, commentEntity.id, videoId, null))
|
||||
"查看对话" -> {
|
||||
if (answerId != null) {
|
||||
context.startActivity(CommentDetailActivity
|
||||
.getAnswerCommentIntent(context, commentEntity.id, answerId, null))
|
||||
} else if (articleId != null) {
|
||||
context.startActivity(CommentDetailActivity
|
||||
.getCommunityArticleCommentIntent(context, articleId, commentEntity.id, communityId, null))
|
||||
} else {
|
||||
context.startActivity(CommentDetailActivity
|
||||
.getVideoCommentIntent(context, commentEntity.id, videoId, isVideoAuthor, null))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
popupWindow.isTouchable = true
|
||||
popupWindow.isFocusable = true
|
||||
|
||||
popupWindow.showAutoOrientation(view)
|
||||
}
|
||||
|
||||
private fun showControlDialog(context: Context,
|
||||
|
||||
@ -6,7 +6,7 @@ import android.widget.LinearLayout;
|
||||
|
||||
import com.facebook.drawee.drawable.ScalingUtils;
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.gamecenter.ViewImageActivity;
|
||||
import com.gh.gamecenter.ImageViewerActivity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -93,7 +93,7 @@ public class ConcernContentUtils {
|
||||
break;
|
||||
}
|
||||
imageView.setOnClickListener(v -> {
|
||||
Intent checkIntent = ViewImageActivity.getViewImageIntent(context, (ArrayList<String>) list, position, entrance);
|
||||
Intent checkIntent = ImageViewerActivity.getIntent(context, (ArrayList<String>) list, position, entrance);
|
||||
context.startActivity(checkIntent);
|
||||
});
|
||||
return imageView;
|
||||
|
||||
@ -20,12 +20,13 @@ import java.util.Map;
|
||||
public class DataLogUtils {
|
||||
|
||||
// 轮播图
|
||||
public static void uploadLunbotuLog(Context context, String type, String text, String index, String source) {
|
||||
public static void uploadLunbotuLog(Context context, String type, String text, String title, String index, String source) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("index", index);
|
||||
map.put("type", type);
|
||||
map.put("text", text);
|
||||
map.put("source", source);
|
||||
map.put("slide_title", title);
|
||||
uploadLog(context, "slide", map);
|
||||
}
|
||||
|
||||
|
||||
@ -6,6 +6,8 @@ import android.view.View;
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.repository.ReservationRepository;
|
||||
import com.gh.common.view.DownloadProgressBar;
|
||||
import com.gh.common.xapk.XapkInstaller;
|
||||
import com.gh.common.xapk.XapkUnzipStatus;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.adapter.viewholder.DetailViewHolder;
|
||||
@ -13,7 +15,6 @@ import com.gh.gamecenter.entity.LinkEntity;
|
||||
import com.gh.gamecenter.entity.PluginLocation;
|
||||
import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
/**
|
||||
* Created by khy on 27/06/17.
|
||||
@ -112,8 +113,18 @@ public class DetailDownloadUtils {
|
||||
}
|
||||
|
||||
public static void detailInvalidate(DetailViewHolder viewHolder) {
|
||||
viewHolder.mDownloadPb.setProgress((int) (viewHolder.downloadEntity.getPercent() * 10));
|
||||
DownloadEntity downloadEntity = viewHolder.downloadEntity;
|
||||
String xapkStatus = downloadEntity.getMeta().get(XapkInstaller.XAPK_UNZIP_STATUS);
|
||||
|
||||
if (XapkUnzipStatus.UNZIPPING.name().equals(xapkStatus)) {
|
||||
String percent = downloadEntity.getMeta().get(XapkInstaller.XAPK_UNZIP_PERCENT);
|
||||
viewHolder.mDownloadPb.setText("解压中(" + percent + "%)");
|
||||
viewHolder.mDownloadPb.setProgress((int) (Float.valueOf(percent) * 10));
|
||||
viewHolder.mDownloadPb.setDownloadType(DownloadProgressBar.DownloadType.XAPK_UNZIPPING);
|
||||
return;
|
||||
}
|
||||
|
||||
viewHolder.mDownloadPb.setProgress((int) (viewHolder.downloadEntity.getPercent() * 10));
|
||||
switch (downloadEntity.getStatus()) {
|
||||
case downloading:
|
||||
case pause:
|
||||
|
||||
@ -11,6 +11,8 @@ import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.utils.Util_System_Phone_State;
|
||||
import com.tencent.stat.StatConfig;
|
||||
@ -222,8 +224,7 @@ public class DeviceUtils {
|
||||
|
||||
// get sim
|
||||
public static String getSim(Context context) {
|
||||
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
String imsi = tm.getSubscriberId();
|
||||
String imsi = getTelephonySubscriberId(context);
|
||||
if (imsi == null) {
|
||||
return "";
|
||||
}
|
||||
@ -239,6 +240,12 @@ public class DeviceUtils {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getTelephonySubscriberId(Context context) {
|
||||
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
return tm.getSubscriberId();
|
||||
}
|
||||
|
||||
// ping domain
|
||||
public static String ping(String domain) {
|
||||
try {
|
||||
|
||||
@ -39,8 +39,10 @@ import com.gh.common.view.LimitHeightLinearLayout;
|
||||
import com.gh.common.view.MaxHeightNestedScrollView;
|
||||
import com.gh.gamecenter.AboutActivity;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.SuggestionActivity;
|
||||
import com.gh.gamecenter.WebActivity;
|
||||
import com.gh.gamecenter.adapter.viewholder.PrivacyPolicyItemViewHolder;
|
||||
import com.gh.gamecenter.databinding.DialogOverseaConfirmationBinding;
|
||||
import com.gh.gamecenter.databinding.ImprintContentItemBinding;
|
||||
import com.gh.gamecenter.databinding.PrivacyItemBinding;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
@ -48,9 +50,11 @@ import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.PrivacyPolicyEntity;
|
||||
import com.gh.gamecenter.entity.SettingsEntity;
|
||||
import com.gh.gamecenter.entity.TrackableEntity;
|
||||
import com.gh.gamecenter.suggest.SuggestType;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.halo.assistant.fragment.SettingsFragment;
|
||||
import com.lightgame.adapter.BaseRecyclerAdapter;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.utils.AppManager;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
@ -1099,6 +1103,21 @@ public class DialogUtils {
|
||||
final ConfirmListener cmListener,
|
||||
final CancelListener clListener,
|
||||
TrackableEntity trackableEntity) {
|
||||
return showTrackableDialog(context, false, title, message, positive, negative, cmListener, clListener, trackableEntity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param useRoundedCornerStyle 使用圆角样式
|
||||
*/
|
||||
public static Dialog showTrackableDialog(Context context,
|
||||
boolean useRoundedCornerStyle,
|
||||
String title,
|
||||
CharSequence message,
|
||||
String positive,
|
||||
String negative,
|
||||
final ConfirmListener cmListener,
|
||||
final CancelListener clListener,
|
||||
TrackableEntity trackableEntity) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
final TrackableDialog dialog = new TrackableDialog(context,
|
||||
@ -1110,7 +1129,17 @@ public class DialogUtils {
|
||||
trackableEntity.getKeyBackValue(),
|
||||
trackableEntity.getLogShowEvent());
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_alert, null);
|
||||
View contentView;
|
||||
if (useRoundedCornerStyle) {
|
||||
contentView = LayoutInflater.from(context).inflate(R.layout.dialog_alert_with_rounded_corner, null);
|
||||
Window window = dialog.getWindow();
|
||||
if (window != null) {
|
||||
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
}
|
||||
} else {
|
||||
contentView = LayoutInflater.from(context).inflate(R.layout.dialog_alert, null);
|
||||
}
|
||||
|
||||
TextView contentTv = contentView.findViewById(R.id.dialog_content);
|
||||
TextView titleTv = contentView.findViewById(R.id.dialog_title);
|
||||
TextView negativeTv = contentView.findViewById(R.id.dialog_negative);
|
||||
@ -1265,6 +1294,45 @@ public class DialogUtils {
|
||||
}
|
||||
}
|
||||
|
||||
// 海外下载地址弹窗
|
||||
public static void showOverseaDownloadDialog(Context context, GameEntity gameEntity, @NonNull ConfirmListener listener) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
if (gameEntity.getOverseasAddressDialog() == null
|
||||
|| gameEntity.getApk().size() == 0
|
||||
|| !gameEntity.getOverseasAddressDialog().isEnable()) {
|
||||
listener.onConfirm();
|
||||
} else {
|
||||
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
|
||||
|
||||
DialogOverseaConfirmationBinding binding = DataBindingUtil.inflate(LayoutInflater.from(context), R.layout.dialog_oversea_confirmation, null, false);
|
||||
|
||||
View contentView = binding.getRoot();
|
||||
|
||||
binding.setGame(gameEntity);
|
||||
binding.urlTv.setText(gameEntity.getOverseasAddressDialog().getLink());
|
||||
binding.closeIv.setOnClickListener(v -> dialog.dismiss());
|
||||
binding.downloadBtn.setText("下载(" + gameEntity.getApk().get(0).getSize() + ")");
|
||||
binding.downloadBtn.setOnClickListener(v -> {
|
||||
listener.onConfirm();
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
if ("show&download".equals(gameEntity.getOverseasAddressDialog().getStatus())) {
|
||||
gameEntity.getApk().get(0).setUrl(gameEntity.getOverseasAddressDialog().getLink());
|
||||
}
|
||||
|
||||
Window window = dialog.getWindow();
|
||||
if (window != null) {
|
||||
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
}
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
public static void showImprintDialog(Context context, GameEntity gameEntity, String titleName) {
|
||||
context = checkDialogContext(context);
|
||||
Dialog dialog = new Dialog(context, R.style.full_dialog);
|
||||
@ -1341,6 +1409,41 @@ public class DialogUtils {
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public static void showStopServerExplanationDialog(Context context, String content, String gameName) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
final Dialog dialog = new TrackableDialog(context, R.style.GhAlertDialog, "评论说明弹窗", "弹窗", gameName, null, null, true);
|
||||
|
||||
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_stop_service_explanation, null);
|
||||
|
||||
TextView contentTv = contentView.findViewById(R.id.contentTv);
|
||||
MaxHeightNestedScrollView scrollView = contentView.findViewById(R.id.scrollView);
|
||||
if (TextUtils.isEmpty(content)) {
|
||||
content = context.getString(R.string.rating_protection);
|
||||
}
|
||||
contentTv.setText(content);
|
||||
TextView ok = contentView.findViewById(R.id.dialog_ok);
|
||||
scrollView.setScrollChangedListener((l, t, oldl, oldt) -> {
|
||||
MtaHelper.onEvent("评论说明弹窗", "滑动内容", gameName);
|
||||
});
|
||||
ok.setOnClickListener(v -> {
|
||||
MtaHelper.onEvent("评论说明弹窗", "弹窗", "点击我知道了");
|
||||
MtaHelper.onEvent("评论说明弹窗", "点击我知道了", gameName);
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
Window window = dialog.getWindow();
|
||||
if (window != null) {
|
||||
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
WindowManager.LayoutParams params = window.getAttributes();
|
||||
params.width = context.getResources().getDisplayMetrics().widthPixels - DisplayUtils.dip2px(60f);
|
||||
window.setAttributes(params);
|
||||
}
|
||||
}
|
||||
|
||||
public static void showPluggableNeverRemindDialog(Context context, String nameAndPlatform, @NonNull ConfirmListener listener) {
|
||||
context = checkDialogContext(context);
|
||||
|
||||
@ -1368,6 +1471,36 @@ public class DialogUtils {
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public static void showUnzipFailureDialog(Context context, DownloadEntity downloadEntity) {
|
||||
final Context activityContext = checkDialogContext(context);
|
||||
|
||||
final Dialog dialog = new Dialog(activityContext, R.style.GhAlertDialog);
|
||||
Window window = dialog.getWindow();
|
||||
if (window != null) {
|
||||
window.setBackgroundDrawableResource(android.R.color.transparent);
|
||||
}
|
||||
|
||||
View contentView = LayoutInflater.from(activityContext).inflate(R.layout.dialog_unzip_failure, null);
|
||||
|
||||
View cancelBtn = contentView.findViewById(R.id.cancel);
|
||||
View confirmBtn = contentView.findViewById(R.id.confirm);
|
||||
|
||||
|
||||
cancelBtn.setOnClickListener(v -> {
|
||||
dialog.dismiss();
|
||||
});
|
||||
|
||||
confirmBtn.setOnClickListener(v -> {
|
||||
dialog.dismiss();
|
||||
String hint = "《" + downloadEntity.getName() + "》游戏安装包解压失败,问题反馈:";
|
||||
SuggestionActivity.startSuggestionActivity(activityContext, SuggestType.normal, null, hint);
|
||||
});
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(contentView);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context may be is application context
|
||||
* @return activity context
|
||||
|
||||
@ -30,6 +30,7 @@ import com.gh.gamecenter.game.columncollection.detail.ColumnCollectionDetailActi
|
||||
import com.gh.gamecenter.game.upload.GameSubmissionActivity
|
||||
import com.gh.gamecenter.gamedetail.GameDetailFragment
|
||||
import com.gh.gamecenter.manager.UserManager
|
||||
import com.gh.gamecenter.mvvm.Resource
|
||||
import com.gh.gamecenter.mygame.PlayedGameActivity
|
||||
import com.gh.gamecenter.personalhome.UserHomeActivity
|
||||
import com.gh.gamecenter.qa.CommunityFragment
|
||||
@ -39,17 +40,24 @@ import com.gh.gamecenter.qa.article.detail.ArticleDetailActivity
|
||||
import com.gh.gamecenter.qa.column.detail.AskColumnDetailActivity
|
||||
import com.gh.gamecenter.qa.questions.detail.QuestionsDetailActivity
|
||||
import com.gh.gamecenter.qa.subject.CommunitySubjectActivity
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.gh.gamecenter.servers.GameServersActivity
|
||||
import com.gh.gamecenter.subject.SubjectActivity
|
||||
import com.gh.gamecenter.suggest.SuggestType
|
||||
import com.gh.gamecenter.tag.TagsActivity
|
||||
import com.gh.gamecenter.video.data.VideoDataActivity
|
||||
import com.gh.gamecenter.video.detail.VideoDetailActivity
|
||||
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
|
||||
import com.gh.gamecenter.video.game.GameVideoActivity
|
||||
import com.gh.gamecenter.video.videomanager.VideoManagerActivity
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.Util_System_ClipboardManager
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import retrofit2.HttpException
|
||||
|
||||
/**
|
||||
* 跳转用的方法
|
||||
@ -153,7 +161,10 @@ object DirectUtils {
|
||||
|
||||
"answer", "社区回答" -> directToAnswerDetail(context, linkEntity.link ?: "", entrance, path)
|
||||
|
||||
"community", "问答社区" -> directToCommunity(context, CommunityEntity(linkEntity.link!!, linkEntity.text!!))
|
||||
"community", "问答社区" -> {
|
||||
if (linkEntity.link.isNullOrEmpty()) return
|
||||
directToCommunity(context, CommunityEntity(linkEntity.link!!, linkEntity.text!!))
|
||||
}
|
||||
|
||||
"community_article", "社区文章" -> directToCommunityArticle(context, linkEntity.community!!, linkEntity.link!!, entrance, path)
|
||||
|
||||
@ -185,11 +196,14 @@ object DirectUtils {
|
||||
"category", "分类" -> directCategoryDirectory(context, linkEntity.link!!, linkEntity.text!!)
|
||||
|
||||
"block", "版块" -> {
|
||||
directToBlock(context, SubjectRecommendEntity(
|
||||
link = linkEntity.link,
|
||||
text = linkEntity.text,
|
||||
name = linkEntity.name,
|
||||
display = linkEntity.display ?: Display()))
|
||||
if (linkEntity.link.isNullOrEmpty()) return
|
||||
directToBlock(context,
|
||||
SubjectRecommendEntity(
|
||||
link = linkEntity.link,
|
||||
text = linkEntity.text,
|
||||
name = linkEntity.name,
|
||||
display = linkEntity.display ?: Display()),
|
||||
entrance)
|
||||
}
|
||||
|
||||
"column_collection", "专题合集" -> directToColumnCollection(context, linkEntity.link!!, -1, entrance)
|
||||
@ -244,7 +258,7 @@ object DirectUtils {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToQa(context: Context, text: String, id: String) {
|
||||
// context.startActivity(QaActivity.getIntent(context, navigationTitle = text, qaId = id))
|
||||
if (id.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, QaActivity::class.java.simpleName)
|
||||
bundle.putString(KEY_NAVIGATION_TITLE, text)
|
||||
@ -257,7 +271,7 @@ object DirectUtils {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToQaCollection(context: Context, text: String, id: String) {
|
||||
// context.startActivity(QaActivity.getIntent(context, navigationTitle = text, qaCollectionId = id))
|
||||
if (id.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, QaActivity::class.java.simpleName)
|
||||
bundle.putString(KEY_NAVIGATION_TITLE, text)
|
||||
@ -270,13 +284,13 @@ object DirectUtils {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToColumnCollection(context: Context, id: String, position: Int = -1, entrance: String, columnName: String = "") {
|
||||
// context.startActivity(ColumnCollectionDetailActivity.getIntent(context, id, position, entrance, columnName))
|
||||
if (id.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, ColumnCollectionDetailActivity::class.java.name)
|
||||
bundle.putString(KEY_ENTRANCE, entrance)
|
||||
bundle.putString(KEY_COLLECTION_ID,id)
|
||||
bundle.putString(KEY_COLUMNNAME,columnName)
|
||||
bundle.putInt(KEY_POSITION,position)
|
||||
bundle.putString(KEY_COLLECTION_ID, id)
|
||||
bundle.putString(KEY_COLUMNNAME, columnName)
|
||||
bundle.putInt(KEY_POSITION, position)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@ -285,6 +299,7 @@ object DirectUtils {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToArticle(context: Context, id: String, entrance: String? = null) {
|
||||
if (id.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, NewsDetailActivity::class.java.simpleName)
|
||||
@ -328,6 +343,7 @@ object DirectUtils {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToGameDetail(context: Context, id: String, entrance: String? = null, autoDownload: Boolean? = null, scrollToLibao: Boolean = false, traceEvent: ExposureEvent? = null) {
|
||||
if (id.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, GameDetailActivity::class.java.simpleName)
|
||||
@ -356,7 +372,16 @@ object DirectUtils {
|
||||
bundle.putString(KEY_GAMEID, id)
|
||||
bundle.putBoolean(KEY_OPEN_VIDEO_STREAMING, true)
|
||||
bundle.putInt(KEY_TARGET, GameDetailFragment.INDEX_DESC)
|
||||
// GameDetailActivity.startGameDetailToVideoStreaming(context, id, entrance)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directToGameDetail(context: Context, id: String, defaultTab: Int = GameDetailFragment.INDEX_DESC, entrance: String? = null) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, GameDetailActivity::class.java.name)
|
||||
bundle.putString(KEY_ENTRANCE, entrance)
|
||||
bundle.putString(KEY_GAMEID, id)
|
||||
bundle.putInt(KEY_TARGET, defaultTab)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@ -368,6 +393,7 @@ object DirectUtils {
|
||||
// 专栏
|
||||
@JvmStatic
|
||||
fun directToSubject(context: Context, id: String, subjectName: String? = "", entrance: String? = null) {
|
||||
if (id.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
val subjectData = SubjectData(subjectId = id, subjectName = subjectName, isOrder = false)
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
@ -444,6 +470,7 @@ object DirectUtils {
|
||||
|
||||
@JvmStatic
|
||||
fun directToAnswerDetail(context: Context, id: String, entrance: String? = null, path: String? = null) {
|
||||
if (id.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, AnswerDetailActivity::class.java.name)
|
||||
@ -454,6 +481,7 @@ object DirectUtils {
|
||||
|
||||
@JvmStatic
|
||||
fun directToQuestionDetail(context: Context, id: String, entrance: String? = null, path: String? = null) {
|
||||
if (id.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, QuestionsDetailActivity::class.java.name)
|
||||
@ -464,6 +492,7 @@ object DirectUtils {
|
||||
|
||||
@JvmStatic
|
||||
fun directToWebView(context: Context, url: String, entrance: String? = null) {
|
||||
if (url.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, WebActivity::class.java.simpleName)
|
||||
@ -482,8 +511,9 @@ object DirectUtils {
|
||||
|
||||
@JvmStatic
|
||||
fun directToExternalBrowser(context: Context, url: String) {
|
||||
if (url.isEmpty()) return
|
||||
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
||||
if (context !is AppCompatActivity){
|
||||
if (context !is AppCompatActivity) {
|
||||
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
context.startActivity(browserIntent)
|
||||
@ -507,7 +537,7 @@ object DirectUtils {
|
||||
}
|
||||
val str = "mqqwpa://im/chat?chat_type=$chatType&uin=$qq&version=1&src_type=web"
|
||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(str))
|
||||
if (context !is AppCompatActivity){
|
||||
if (context !is AppCompatActivity) {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
context.startActivity(intent)
|
||||
@ -521,12 +551,13 @@ object DirectUtils {
|
||||
// 跳转 QQ 群
|
||||
@JvmStatic
|
||||
fun directToQqGroup(context: Context, groupNumber: String? = null): Boolean {
|
||||
if (groupNumber.isNullOrEmpty()) return false
|
||||
if (ShareUtils.isQQClientAvailable(context)) {
|
||||
val intent = Intent()
|
||||
intent.data = Uri.parse("mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26k%3D$groupNumber")
|
||||
// 此Flag可根据具体产品需要自定义,如设置,则在加群界面按返回,返回手Q主界面,不设置,按返回会返回到呼起产品界面 //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
return try {
|
||||
if (context !is AppCompatActivity){
|
||||
if (context !is AppCompatActivity) {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
context.startActivity(intent)
|
||||
@ -534,7 +565,7 @@ object DirectUtils {
|
||||
} catch (e: Exception) {
|
||||
false
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
Utils.toast(context, "请安装QQ客户端")
|
||||
return false
|
||||
}
|
||||
@ -546,6 +577,7 @@ object DirectUtils {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToGiftDetail(context: Context, giftId: String, entrance: String? = null) {
|
||||
if (giftId.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_TO, LibaoDetailActivity::class.java.simpleName)
|
||||
@ -600,6 +632,7 @@ object DirectUtils {
|
||||
|
||||
@JvmStatic
|
||||
fun directToCommunityArticle(context: Context, community: CommunityEntity?, articleId: String?, entrance: String?, path: String?) {
|
||||
if (articleId.isNullOrEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
bundle.putString(KEY_PATH, path)
|
||||
@ -614,6 +647,7 @@ object DirectUtils {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToCommunityColumn(context: Context, community: CommunityEntity?, subjectId: String, entrance: String?, path: String?) {
|
||||
if (subjectId.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_PATH, path)
|
||||
bundle.putString(KEY_TO, CommunitySubjectActivity::class.java.name)
|
||||
@ -627,7 +661,8 @@ object DirectUtils {
|
||||
* @param fromLocation 可见 [VideoDetailContainerViewModel.Location]
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToVideoDetail(context: Context, videoId: String, fromLocation: String, showComment: Boolean = false, gameId: String = "", entrance: String? = null, path: String? = "", referer: String = "", type: String = "", act: String = "") {
|
||||
fun directToVideoDetail(context: Context, videoId: String, fromLocation: String, showComment: Boolean = false, gameId: String = "", entrance: String? = null,
|
||||
path: String? = "", referer: String = "", type: String = "", act: String = "", fieldId: String = "", sectionName: String = "") {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
|
||||
@ -640,6 +675,8 @@ object DirectUtils {
|
||||
bundle.putString(KEY_REFERER, referer)
|
||||
bundle.putString(KEY_TYPE, type)
|
||||
bundle.putString(KEY_ACTIVITY_NAME, act)
|
||||
bundle.putString(KEY_FIELD_ID, fieldId)
|
||||
bundle.putString(KEY_SECTION_NAME, sectionName)
|
||||
jumpActivity(context, bundle)
|
||||
} else {
|
||||
DialogUtils.showLowSystemVersionDialog(context)
|
||||
@ -677,10 +714,11 @@ object DirectUtils {
|
||||
* 跳转至上传视频
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToVideoManager(context: Context, linkEntity: VideoLinkEntity, entrance: String? = null, path: String? = "") {
|
||||
fun directToVideoManager(context: Context, linkEntity: VideoLinkEntity, simpleGameEntity: SimpleGameEntity, entrance: String? = null, path: String? = "") {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_PATH, path)
|
||||
bundle.putParcelable(VideoLinkEntity::class.java.simpleName, linkEntity)
|
||||
bundle.putParcelable(SimpleGameEntity::class.java.simpleName, simpleGameEntity)
|
||||
bundle.putString(KEY_TO, VideoManagerActivity::class.java.name)
|
||||
bundle.putString(KEY_ENTRANCE, BaseActivity.mergeEntranceAndPath(entrance, path))
|
||||
jumpActivity(context, bundle)
|
||||
@ -691,6 +729,7 @@ object DirectUtils {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToGameVideo(context: Context, gameId: String, entrance: String? = null, path: String? = "") {
|
||||
if (gameId.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_PATH, path)
|
||||
bundle.putString(KEY_TO, GameVideoActivity::class.java.name)
|
||||
@ -738,6 +777,7 @@ object DirectUtils {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directCategoryDirectory(context: Context, categoryId: String, categoryTitle: String, entrance: String? = null, path: String? = "") {
|
||||
if (categoryId.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, CategoryDirectoryActivity::class.java.name)
|
||||
bundle.putString(KEY_CATEGORY_ID, categoryId)
|
||||
@ -766,6 +806,7 @@ object DirectUtils {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directAskColumnDetail(context: Context, columnId: String, community: CommunityEntity, entrance: String? = null, path: String? = "") {
|
||||
if (columnId.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, AskColumnDetailActivity::class.java.name)
|
||||
bundle.putString(KEY_COLUMN_ID, columnId)
|
||||
@ -779,10 +820,11 @@ object DirectUtils {
|
||||
* 跳转到板块
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directToBlock(context: Context, blockData: SubjectRecommendEntity) {
|
||||
fun directToBlock(context: Context, blockData: SubjectRecommendEntity, entrance: String) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, BlockActivity::class.java.name)
|
||||
bundle.putParcelable(KEY_BLOCK_DATA, blockData)
|
||||
bundle.putString(KEY_ENTRANCE, entrance)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@ -814,6 +856,7 @@ object DirectUtils {
|
||||
*/
|
||||
@JvmStatic
|
||||
fun directSimpleArticleList(context: Context, sortType: String, entrance: String? = null, path: String? = "") {
|
||||
if (sortType.isEmpty()) return
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, SimpleArticleListActivity::class.java.name)
|
||||
bundle.putString(KEY_TYPE, sortType)
|
||||
@ -821,4 +864,40 @@ object DirectUtils {
|
||||
bundle.putString(KEY_PATH, path)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directGameZone(context: Context, gameId: String, url: String, entrance: String? = null) {
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application)
|
||||
.sensitiveApi
|
||||
.getGameDigest(gameId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<GameEntity>() {
|
||||
override fun onResponse(response: GameEntity?) {
|
||||
response?.apply {
|
||||
if (zone.status == "on") {
|
||||
if (zone.style == "link") {
|
||||
directToGameDetail(context, gameId, GameDetailFragment.INDEX_TRENDES, entrance)
|
||||
} else {
|
||||
directToWebView(context, url, entrance)
|
||||
}
|
||||
} else {
|
||||
directToWebView(context, url, entrance)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(e: HttpException?) {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun directVideoData(context: Context, entrance: String? = null) {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_TO, VideoDataActivity::class.java.name)
|
||||
bundle.putString(KEY_ENTRANCE, entrance)
|
||||
jumpActivity(context, bundle)
|
||||
}
|
||||
}
|
||||
@ -8,12 +8,6 @@ import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.collection.ArrayMap;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.dialog.CertificationDialog;
|
||||
import com.gh.common.dialog.DeviceRemindDialog;
|
||||
@ -21,6 +15,8 @@ import com.gh.common.dialog.ReserveDialogFragment;
|
||||
import com.gh.common.exposure.ExposureEvent;
|
||||
import com.gh.common.history.HistoryHelper;
|
||||
import com.gh.common.repository.ReservationRepository;
|
||||
import com.gh.common.xapk.XapkInstaller;
|
||||
import com.gh.common.xapk.XapkUnzipStatus;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.download.dialog.DownloadDialog;
|
||||
import com.gh.gamecenter.DownloadManagerActivity;
|
||||
@ -40,6 +36,12 @@ import com.lightgame.utils.Utils;
|
||||
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.collection.ArrayMap;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
/**
|
||||
* todo 下载判断不能以按钮文案为判断条件,否则按钮文案修改时又要修改判断逻辑
|
||||
*/
|
||||
@ -261,6 +263,7 @@ public class DownloadItemUtils {
|
||||
boolean isShowPlatform, boolean isNormal) {
|
||||
|
||||
updateItemViewStatus(holder, true, null);
|
||||
holder.gameProgressbar.setProgressDrawable(context.getResources().getDrawable(R.drawable.progressbar_bg_style));
|
||||
|
||||
String platform = PlatformUtils.getInstance(context).getPlatformName(downloadEntity.getPlatform());
|
||||
|
||||
@ -321,6 +324,17 @@ public class DownloadItemUtils {
|
||||
holder.gameDownloadBtn.setTextColor(ContextCompat.getColorStateList(context, R.color.text_downloading_style));
|
||||
}
|
||||
} else if (status.equals(DownloadStatus.done)) {
|
||||
String xapkStatus = downloadEntity.getMeta().get(XapkInstaller.XAPK_UNZIP_STATUS);
|
||||
if (XapkUnzipStatus.UNZIPPING.name().equals(xapkStatus)) {
|
||||
String percent = downloadEntity.getMeta().get(XapkInstaller.XAPK_UNZIP_PERCENT);
|
||||
holder.gameProgressbar.setProgressDrawable(context.getResources().getDrawable(R.drawable.progressbar_xapk_style));
|
||||
holder.gameDownloadSpeed.setText(R.string.unzipping);
|
||||
holder.gameProgressbar.setProgress((int) (Float.valueOf(percent) * 10));
|
||||
holder.gameDownloadPercentage.setText(percent + "%");
|
||||
holder.gameDownloadBtn.setText(R.string.unzipping);
|
||||
return;
|
||||
}
|
||||
|
||||
holder.gameProgressbar.setProgress(1000);
|
||||
if (isShowPlatform && platform != null) {
|
||||
holder.gameDownloadSpeed.setText(String.format("%s - 下载完成", platform));
|
||||
@ -454,7 +468,7 @@ public class DownloadItemUtils {
|
||||
HistoryHelper.insertGameEntity(gameEntity);
|
||||
}
|
||||
|
||||
Intent i = WebActivity.getIntentForWebGame(context, gameEntity.getH5Link().getLink(), gameEntity.getName(), isPlay);
|
||||
Intent i = WebActivity.getIntentForWebGame(context, gameEntity.getH5Link().getLink(), gameEntity.getName(), isPlay,linkEntity.getCloseButton());
|
||||
context.startActivity(i);
|
||||
});
|
||||
} else if (gameEntity.getApk().size() == 1) {
|
||||
@ -520,8 +534,10 @@ public class DownloadItemUtils {
|
||||
// 先弹下载弹窗(如果需要的话)
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, () -> {
|
||||
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
|
||||
DialogUtils.checkDownload(context, apk.getSize(),
|
||||
isSubscribe -> download(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
|
||||
DialogUtils.showOverseaDownloadDialog(context, gameEntity, () -> {
|
||||
DialogUtils.checkDownload(context, apk.getSize(),
|
||||
isSubscribe -> download(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -530,8 +546,10 @@ public class DownloadItemUtils {
|
||||
DownloadDialogHelper.findAvailableDialogAndShow(context, gameEntity, apk, () -> {
|
||||
CertificationDialog.showCertificationDialog(context, gameEntity, () -> {
|
||||
DialogUtils.showVersionNumberDialog(context, gameEntity, () -> {
|
||||
DialogUtils.checkDownload(context, apk.getSize(),
|
||||
isSubscribe -> download(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
|
||||
DialogUtils.showOverseaDownloadDialog(context, gameEntity, () -> {
|
||||
DialogUtils.checkDownload(context, apk.getSize(),
|
||||
isSubscribe -> download(context, gameEntity, downloadBtn, entrance, location, isSubscribe, traceEvent));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -559,10 +577,6 @@ public class DownloadItemUtils {
|
||||
}
|
||||
DataUtils.onGameLaunchEvent(context, gameEntity.getName(), gameEntity.getApk().get(0).getPlatform(), location);
|
||||
PackageUtils.launchApplicationByPackageName(context, gameEntity.getApk().get(0).getPackageName());
|
||||
} else if (str.equals(context.getString(R.string.waiting))
|
||||
|| str.equals(context.getString(R.string.downloading))) {
|
||||
context.startActivity(DownloadManagerActivity.getDownloadMangerIntent(context,
|
||||
apk.getUrl(), entrance + "+(" + location.split(":")[0] + ")"));
|
||||
} else if (str.equals(context.getString(R.string.update))) {
|
||||
if (entrance.contains("我的游戏")) {
|
||||
MtaHelper.onEvent("我的游戏_启动", "更新", gameEntity.getName());
|
||||
@ -571,6 +585,9 @@ public class DownloadItemUtils {
|
||||
DialogUtils.checkDownload(context, apk.getSize(),
|
||||
isSubscribe -> update(context, gameEntity, entrance, location, isSubscribe, traceEvent));
|
||||
});
|
||||
} else {
|
||||
context.startActivity(DownloadManagerActivity.getDownloadMangerIntent(context,
|
||||
apk.getUrl(), entrance + "+(" + location.split(":")[0] + ")"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -631,9 +648,9 @@ public class DownloadItemUtils {
|
||||
}
|
||||
adapter.notifyItemChanged(position);
|
||||
} else if (PackageUtils.isCanPluggable(apkEntity)) {
|
||||
DialogUtils.showPluginDialog(context, () -> context.startActivity(PackageUtils.getUninstallIntent(context, path)));
|
||||
DialogUtils.showPluginDialog(context, () -> PackageInstaller.uninstall(context, path));
|
||||
} else {
|
||||
PackageUtils.launchSetup(context, downloadEntity);
|
||||
PackageInstaller.install(context, downloadEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,6 +10,8 @@ import android.os.Build
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.gh.common.AppExecutor
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.common.xapk.XapkUnzipStatus
|
||||
import com.gh.gamecenter.R
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DownloadEntity
|
||||
@ -38,9 +40,10 @@ object DownloadNotificationHelper {
|
||||
var requireUpdateNotificationGroupDelay = false
|
||||
val notificationManager = getNotificationManager()
|
||||
val downloadNotificationId = (entity.gameId + entity.packageName).hashCode()
|
||||
val xapkStatus = entity.meta[XapkInstaller.XAPK_UNZIP_STATUS]
|
||||
|
||||
val intent = Intent()
|
||||
if (entity.status == DownloadStatus.done) {
|
||||
if (entity.status == DownloadStatus.done && xapkStatus != XapkUnzipStatus.FAILURE.name) {
|
||||
intent.putExtra(EntranceUtils.KEY_DATA, entity.toJson())
|
||||
intent.putExtra(EntranceUtils.KEY_PATH, entity.path)
|
||||
intent.action = ACTION_INSTALL
|
||||
@ -65,18 +68,23 @@ object DownloadNotificationHelper {
|
||||
.setContentIntent(pendingIntent)
|
||||
.setGroup(DOWNLOAD_GROUP_KEY)
|
||||
.setWhen(whenTime)
|
||||
.setProgress(PROGRESS_MAX, entity.percent.toInt(), false)
|
||||
|
||||
when (entity.status) {
|
||||
DownloadStatus.downloading -> builder.setContentText(String.format("%s(剩%s)",
|
||||
SpeedUtils.getSpeed(entity.speed),
|
||||
SpeedUtils.getRemainTime(entity.size, entity.progress, entity.speed * 1024)))
|
||||
DownloadStatus.done -> builder.setContentText("下载完成,点击立即安装")
|
||||
DownloadStatus.waiting -> builder.setContentText("等待中")
|
||||
DownloadStatus.subscribe,
|
||||
DownloadStatus.timeout,
|
||||
DownloadStatus.neterror -> builder.setContentText("已暂停,连接WiFi自动下载")
|
||||
else -> builder.setContentText("暂停中")
|
||||
|
||||
if (xapkStatus == XapkUnzipStatus.FAILURE.name) {
|
||||
builder.setContentText("《" + entity.name + "》解压失败,点击查看详情~")
|
||||
} else {
|
||||
when (entity.status) {
|
||||
DownloadStatus.downloading -> builder.setContentText(String.format("%s(剩%s)",
|
||||
SpeedUtils.getSpeed(entity.speed),
|
||||
SpeedUtils.getRemainTime(entity.size, entity.progress, entity.speed * 1024)))
|
||||
DownloadStatus.done -> builder.setContentText("下载完成,点击立即安装")
|
||||
DownloadStatus.waiting -> builder.setContentText("等待中")
|
||||
DownloadStatus.subscribe,
|
||||
DownloadStatus.timeout,
|
||||
DownloadStatus.neterror -> builder.setContentText("已暂停,连接WiFi自动下载")
|
||||
else -> builder.setContentText("暂停中")
|
||||
}
|
||||
builder.setProgress(PROGRESS_MAX, entity.percent.toInt(), false)
|
||||
}
|
||||
|
||||
when {
|
||||
@ -91,6 +99,11 @@ object DownloadNotificationHelper {
|
||||
tryCatchInRelease {
|
||||
val notification = builder.build() // 可能会抛出异常
|
||||
notification.flags = notification.flags or Notification.FLAG_NO_CLEAR
|
||||
if (xapkStatus == XapkUnzipStatus.FAILURE.name) {
|
||||
notification.flags = notification.flags or Notification.FLAG_AUTO_CANCEL
|
||||
} else {
|
||||
notification.flags = notification.flags or Notification.FLAG_NO_CLEAR
|
||||
}
|
||||
|
||||
if (entity.status == DownloadStatus.delete
|
||||
|| entity.status == DownloadStatus.cancel
|
||||
@ -98,7 +111,8 @@ object DownloadNotificationHelper {
|
||||
|| entity.status == DownloadStatus.notfound
|
||||
|| entity.status == DownloadStatus.overflow
|
||||
|| (entity.status == DownloadStatus.done // 触发安装事件以后也 cancel 掉通知
|
||||
&& !entity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION].isNullOrEmpty())) {
|
||||
&& !entity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION].isNullOrEmpty()
|
||||
&& xapkStatus != XapkUnzipStatus.FAILURE.name)) {
|
||||
requireUpdateNotificationGroupDelay = true
|
||||
notificationManager.cancel(entity.path, DOWNLOAD_NOTIFICATION_ID)
|
||||
} else {
|
||||
|
||||
@ -6,6 +6,8 @@ import android.preference.PreferenceManager
|
||||
import com.gh.base.BaseActivity
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.exposure.ExposureUtils
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.download.DownloadDataHelper
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.R
|
||||
@ -43,11 +45,15 @@ object DownloadObserver {
|
||||
fun initObserver() {
|
||||
val dataWatcher = object : DataWatcher() {
|
||||
override fun onDataChanged(downloadEntity: DownloadEntity) {
|
||||
// todo 如何处理xapk安装问题
|
||||
val xapkStatus = downloadEntity.meta[XapkInstaller.XAPK_UNZIP_STATUS]
|
||||
if (!xapkStatus.isNullOrEmpty()) return
|
||||
|
||||
val gameId = downloadEntity.getRealGameId(Constants.GAME_ID_DIVIDER)
|
||||
val downloadManager = DownloadManager.getInstance(HaloApp.getInstance().application)
|
||||
|
||||
if (downloadEntity.status != DownloadStatus.downloading) {
|
||||
LogUtils.uploadDownloadEvent(downloadEntity)
|
||||
tryCatchInRelease {
|
||||
DownloadDataHelper.uploadDownloadEvent(downloadEntity)
|
||||
}
|
||||
|
||||
if (DownloadStatus.hijack == downloadEntity.status) {
|
||||
@ -103,7 +109,7 @@ object DownloadObserver {
|
||||
MtaHelper.onEvent("软件更新", "下载完成")
|
||||
tryWithDefaultCatch {
|
||||
// 会有 ActivityNotFoundException 异常,catch 掉不管了
|
||||
mApplication.startActivity(PackageUtils.getInstallIntent(mApplication, downloadEntity.path, true))
|
||||
PackageInstaller.install(mApplication, downloadEntity)
|
||||
}
|
||||
DataLogUtils.uploadUpgradeLog(mApplication, "install") //上传更新安装数据
|
||||
} else {
|
||||
@ -131,7 +137,7 @@ object DownloadObserver {
|
||||
if (PackageUtils.isCanLaunchSetup(mApplication, downloadEntity.path)) {
|
||||
downloadEntity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION] = "YES"
|
||||
tryWithDefaultCatch {
|
||||
mApplication.startActivity(PackageUtils.getInstallIntent(mApplication, downloadEntity.path))
|
||||
PackageInstaller.install(mApplication, downloadEntity, false)
|
||||
}
|
||||
} else {
|
||||
// 弹出卸载提示框
|
||||
|
||||
@ -48,6 +48,7 @@ public class EntranceUtils {
|
||||
public static final String HOST_HELP = "help";//Q&A
|
||||
public static final String HOST_HELP_COLLECTION = "help_collection";//Q&A合集
|
||||
public static final String HOST_GAME_UPLOAD = "game_upload";//游戏上传
|
||||
public static final String HOST_GAME_ZONE = "game_zone";//游戏专区
|
||||
public static final String HOST_COMMUNITY_ARTICLE = "community_article";
|
||||
public static final String HOST_COMMUNITY_COLUMN = "community_column";
|
||||
public static final String HOST_GAME = "game";
|
||||
@ -56,6 +57,7 @@ public class EntranceUtils {
|
||||
public static final String HOST_WEB = "web";
|
||||
public static final String HOST_QQ = "qq";
|
||||
public static final String HOST_QQ_GROUP = "qqgroup";
|
||||
public static final String HOST_QQ_QUN = "qqqun";
|
||||
public static final String HOST_DOWNLOAD = "download";
|
||||
public static final String HOST_UPDATE = "update";
|
||||
public static final String HOST_LIBAO = "libao";
|
||||
@ -81,6 +83,7 @@ public class EntranceUtils {
|
||||
public static final String ENTRANCE_DOWNLOAD = "(下载跳转)";
|
||||
public static final String ENTRANCE_RECOMMEND = "(落地页)";
|
||||
public static final String ENTRANCE_BLOCK_RECOMMEND = "(推荐入口)";
|
||||
public static final String ENTRANCE_AMWAY = "(安利墙)";
|
||||
public static final String KEY_SUGGEST_HINT_TYPE = "suggestHintType";
|
||||
public static final String KEY_PACKAGENAME = "packageName";
|
||||
public static final String KEY_PLATFORM = "platform";
|
||||
@ -162,6 +165,8 @@ public class EntranceUtils {
|
||||
public static final String KEY_WEB_SHARE = "webShare";
|
||||
public static final String KEY_ACTIVITY_NAME = "activityName";//活动名称
|
||||
public static final String KEY_REQUIRE_REDIRECT = "require_redirect"; // 标记需要再跳转
|
||||
public static final String KEY_FIELD_ID = "field_id"; // 专区板块id
|
||||
public static final String KEY_SECTION_NAME = "section_name"; // 专区专题名
|
||||
public static final String KEY_COLUMNNAME = "columnName";
|
||||
public static final String KEY_QA_ID = "qaId";
|
||||
public static final String KEY_QA_COLLECTION_ID = "qaCollectionId";
|
||||
@ -169,6 +174,8 @@ public class EntranceUtils {
|
||||
public static final String KEY_ARTICLE_OPEN_IN_NEW_PAGE = "openArticleInNewPage";
|
||||
public static final String KEY_ONLY_CREATE_DRAFT = "onlyCreateDraft";
|
||||
public static final String KEY_KAIFU_SELECT_TIME = "kaifuSelectTime";
|
||||
public static final String KEY_POSTER_PATH = "posterPath";
|
||||
public static final String KEY_BLACK_THEME = "blackTheme";
|
||||
|
||||
public static void jumpActivity(Context context, Bundle bundle) {
|
||||
bundle.putBoolean(KEY_REQUIRE_REDIRECT, true);
|
||||
|
||||
@ -19,6 +19,7 @@ import androidx.core.text.HtmlCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.*
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.airbnb.lottie.LottieAnimationView
|
||||
@ -34,6 +35,7 @@ import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.WebActivity
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
@ -41,6 +43,7 @@ import io.reactivex.disposables.Disposable
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import java.net.URI
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.regex.Pattern
|
||||
import kotlin.math.abs
|
||||
@ -275,6 +278,15 @@ fun throwExceptionInDebug(message: String = "", predicate: Boolean = true) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 主动抛出异常
|
||||
*/
|
||||
fun throwException(message: String = "", predicate: Boolean = true) {
|
||||
if (predicate) {
|
||||
throw RuntimeException(message)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* String related
|
||||
*/
|
||||
@ -314,6 +326,10 @@ fun String.subStringIfPossible(length: Int): String {
|
||||
}
|
||||
}
|
||||
|
||||
fun String.countOccurrences(char: String): Int {
|
||||
return StringTokenizer(" $this ", char).countTokens() - 1
|
||||
}
|
||||
|
||||
fun String.getFirstElementDividedByDivider(divider: String): String {
|
||||
if (this.contains(divider)) {
|
||||
return this.split(divider.toRegex()).toTypedArray()[0]
|
||||
@ -566,6 +582,17 @@ fun SimpleDraweeView.display(url: String) {
|
||||
ImageUtils.display(this, url)
|
||||
}
|
||||
|
||||
/**
|
||||
* DownloadEntity extension
|
||||
*/
|
||||
fun DownloadEntity.addMetaExtra(key: String, value: String?) {
|
||||
value?.let { meta[key] = value }
|
||||
}
|
||||
|
||||
fun DownloadEntity.getMetaExtra(key: String) : String {
|
||||
return meta[key] ?: ""
|
||||
}
|
||||
|
||||
/**
|
||||
* Process related
|
||||
*/
|
||||
@ -682,6 +709,17 @@ fun LottieAnimationView.doOnAnimationEnd(action: () -> Unit) {
|
||||
})
|
||||
}
|
||||
|
||||
fun String?.getExtension(): String? {
|
||||
this ?: return null
|
||||
|
||||
tryCatchInRelease {
|
||||
val lastDotIndex = this.lastIndexOf('.')
|
||||
return if (lastDotIndex == -1) null else this.substring(lastDotIndex + 1)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检查内容是否一致
|
||||
* @return true:相同 false:不同
|
||||
|
||||
@ -5,6 +5,8 @@ import android.graphics.Color;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.R;
|
||||
@ -22,9 +24,6 @@ import com.lightgame.download.DownloadStatus;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
|
||||
public class GameUtils {
|
||||
|
||||
/**
|
||||
@ -183,6 +182,8 @@ public class GameUtils {
|
||||
GameUpdateEntity gameUpdateEntity = new GameUpdateEntity();
|
||||
gameUpdateEntity.setId(gameEntity.getId());
|
||||
gameUpdateEntity.setIcon(gameEntity.getIcon());
|
||||
gameUpdateEntity.setRawIcon(gameEntity.getRawIcon());
|
||||
gameUpdateEntity.setIconSubscript(gameEntity.getIconSubscript());
|
||||
gameUpdateEntity.setName(gameEntity.getName());
|
||||
gameUpdateEntity.setPackageName(apkEntity.getPackageName());
|
||||
gameUpdateEntity.setSize(apkEntity.getSize());
|
||||
@ -199,6 +200,7 @@ public class GameUtils {
|
||||
gameUpdateEntity.setDownload(gameEntity.getDownload());
|
||||
gameUpdateEntity.setIndexPlugin(gameEntity.getIndexPlugin());
|
||||
gameUpdateEntity.setPluginDesc(gameEntity.getPluginDesc());
|
||||
gameUpdateEntity.setFormat(apkEntity.getFormat());
|
||||
|
||||
GameCollectionEntity pluggableCollection = getPluggableCollectionFromGameEntity(gameEntity, apkEntity.getPackageName());
|
||||
if (pluggableCollection != null) {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import org.json.JSONArray
|
||||
|
||||
@ -10,6 +11,7 @@ import org.json.JSONArray
|
||||
*/
|
||||
object GsonUtils {
|
||||
val gson: Gson = Gson()
|
||||
val gsonThatIgnoreNull: Gson = GsonBuilder().serializeNulls().create()
|
||||
|
||||
@JvmStatic
|
||||
fun <T> fromJson(json: String, t: Class<T>): T {
|
||||
@ -32,4 +34,9 @@ object GsonUtils {
|
||||
fun toJson(any: Any?): String {
|
||||
return gson.toJson(any)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun toJsonIgnoreNull(any: Any?): String {
|
||||
return gsonThatIgnoreNull.toJson(any)
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Bitmap
|
||||
@ -9,21 +10,21 @@ import android.net.Uri
|
||||
import android.os.Build
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.facebook.common.executors.CallerThreadExecutor
|
||||
import com.facebook.drawee.backends.pipeline.Fresco
|
||||
import com.facebook.drawee.controller.BaseControllerListener
|
||||
import com.facebook.drawee.controller.ControllerListener
|
||||
import com.facebook.drawee.drawable.ScalingUtils
|
||||
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.facebook.imagepipeline.core.ImagePipeline
|
||||
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber
|
||||
import com.facebook.imagepipeline.image.ImageInfo
|
||||
import com.facebook.imagepipeline.request.ImageRequest
|
||||
import com.facebook.imagepipeline.request.ImageRequestBuilder
|
||||
import com.gh.common.constant.Config
|
||||
import com.gh.gamecenter.R
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.squareup.picasso.Picasso
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import java.io.ByteArrayOutputStream
|
||||
|
||||
|
||||
@ -216,17 +217,21 @@ object ImageUtils {
|
||||
.build()
|
||||
}
|
||||
|
||||
// 获取bitmap
|
||||
// 获取bitmap (使用 fresco 获取 gif bitmap 会为空,https://github.com/facebook/fresco/issues/241)
|
||||
// 所以这里换用 picasso
|
||||
@SuppressLint("CheckResult")
|
||||
@JvmStatic
|
||||
fun display(context: Context?, url: String?, dataSubscriber: BaseBitmapDataSubscriber) {
|
||||
val imageRequest = ImageRequestBuilder
|
||||
.newBuilderWithSource(Uri.parse(url))
|
||||
.setProgressiveRenderingEnabled(true)
|
||||
.build()
|
||||
|
||||
Fresco.getImagePipeline()
|
||||
.fetchDecodedImage(imageRequest, context)
|
||||
.subscribe(dataSubscriber, CallerThreadExecutor.getInstance())
|
||||
fun getBitmap(url: String, callback: BiCallback<Bitmap, Boolean>) {
|
||||
Single.just(url)
|
||||
.map { Picasso.with(HaloApp.getInstance().application).load(url).priority(Picasso.Priority.HIGH).get() }
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({
|
||||
callback.onFirst(it)
|
||||
}, {
|
||||
callback.onSecond(true)
|
||||
it.printStackTrace()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@ -327,7 +332,7 @@ object ImageUtils {
|
||||
|
||||
//预加载图片
|
||||
@JvmStatic
|
||||
fun prefetchToDiskCache(url: String){
|
||||
fun prefetchToDiskCache(url: String) {
|
||||
val imagePipeline = Fresco.getImagePipeline()
|
||||
val imageRequest = ImageRequest.fromUri(url)
|
||||
imagePipeline.prefetchToDiskCache(imageRequest, HaloApp.getInstance().application)
|
||||
@ -337,4 +342,7 @@ object ImageUtils {
|
||||
fun onLoadFinal(imageInfo: ImageInfo?)
|
||||
}
|
||||
|
||||
fun getVideoSnapshot(videoUrl: String, progress: Long): String {
|
||||
return "$videoUrl?x-oss-process=video/snapshot,t_$progress,f_jpg,w_0,h_0"
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,12 +6,16 @@ import android.os.Build;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.common.exposure.ExposureEntity;
|
||||
import com.gh.common.exposure.ExposureEvent;
|
||||
import com.gh.common.exposure.ExposureSource;
|
||||
import com.gh.common.exposure.meta.Meta;
|
||||
import com.gh.common.exposure.meta.MetaUtil;
|
||||
import com.gh.common.loghub.LoghubUtils;
|
||||
import com.gh.download.DownloadDataHelper;
|
||||
import com.gh.common.loghub.SimpleLogContainerEntity;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.entity.CommunityEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
@ -19,7 +23,6 @@ import com.gh.gamecenter.entity.SpecialColumn;
|
||||
import com.gh.gamecenter.manager.UserManager;
|
||||
import com.gh.gamecenter.qa.entity.Questions;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.utils.Util_System_Phone_State;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
@ -29,8 +32,6 @@ import org.json.JSONObject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Created by khy on 2/01/18.
|
||||
*/
|
||||
@ -53,55 +54,6 @@ public class LogUtils {
|
||||
uploadVideoStreaming(object);
|
||||
}
|
||||
|
||||
public static void uploadDownloadEvent(DownloadEntity downloadEntity) {
|
||||
Context context = HaloApp.getInstance().getApplication();
|
||||
Meta meta = MetaUtil.INSTANCE.getMeta();
|
||||
JSONObject object = new JSONObject();
|
||||
|
||||
try {
|
||||
object.put("event", DownloadDataHelper.getDownloadStatusAlias(downloadEntity));
|
||||
object.put("msg", downloadEntity.getError());
|
||||
object.put("status", downloadEntity.getStatus().getStatus());
|
||||
|
||||
// payload
|
||||
JSONObject payloadObject = new JSONObject();
|
||||
payloadObject.put("game_id", downloadEntity.getGameId());
|
||||
payloadObject.put("gameName", downloadEntity.getName());
|
||||
payloadObject.put("platform", downloadEntity.getPlatform());
|
||||
payloadObject.put("package", downloadEntity.getPackageName());
|
||||
payloadObject.put("filename", downloadEntity.getPath().substring(downloadEntity.getPath().lastIndexOf("/") + 1));
|
||||
payloadObject.put("total_size", (downloadEntity.getSize() / 1024 / 1024));
|
||||
payloadObject.put("completed_size", (downloadEntity.getProgress() / 1024 / 1024));
|
||||
|
||||
object.put("payload", payloadObject);
|
||||
|
||||
// meta
|
||||
JSONObject metaObject = new JSONObject();
|
||||
metaObject.put("android_id", meta.getAndroid_id());
|
||||
metaObject.put("android_sdk", meta.getAndroid_sdk());
|
||||
metaObject.put("android_version", meta.getAndroid_version());
|
||||
metaObject.put("appVersion", meta.getAppVersion());
|
||||
metaObject.put("channel", meta.getChannel());
|
||||
metaObject.put("gid", meta.getGid());
|
||||
metaObject.put("imei", meta.getImei());
|
||||
metaObject.put("mac", meta.getMac());
|
||||
metaObject.put("manufacturer", meta.getManufacturer());
|
||||
metaObject.put("model", meta.getModel());
|
||||
metaObject.put("network", DeviceUtils.getNetwork(context));
|
||||
metaObject.put("os", meta.getOs());
|
||||
metaObject.put("userId", meta.getUserId());
|
||||
|
||||
object.put("meta", metaObject);
|
||||
object.put("timestamp", System.currentTimeMillis() / 1000);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log("LogUtils->" + object.toString());
|
||||
}
|
||||
LoghubUtils.log(object, "download_debug", false);
|
||||
}
|
||||
|
||||
public static void uploadCommunityArticle(String tracers, String articleId, String articleTitle, int readTime, CommunityEntity community, SpecialColumn specialColumn) {
|
||||
JSONObject object = new JSONObject();
|
||||
try {
|
||||
@ -420,6 +372,55 @@ public class LogUtils {
|
||||
uploadVideoStreaming(object);
|
||||
}
|
||||
|
||||
public static void uploadWelcomeDialog(String action, String dialogId, String linkTitle) {
|
||||
ExposureEntity payload = new ExposureEntity();
|
||||
payload.setWelcomeDialogId(dialogId);
|
||||
payload.setWelcomeDialogId(linkTitle);
|
||||
|
||||
SimpleLogContainerEntity entity = new SimpleLogContainerEntity();
|
||||
entity.setEvent("dialog");
|
||||
entity.setAction(action);
|
||||
entity.setMeta(MetaUtil.INSTANCE.getMeta());
|
||||
entity.setPayload(payload);
|
||||
entity.setTimestamp(System.currentTimeMillis() / 1000);
|
||||
|
||||
LoghubUtils.log(GsonUtils.toJsonIgnoreNull(entity), "event", false);
|
||||
}
|
||||
|
||||
public static void uploadLikeFromWelcomeDialog() {
|
||||
String dialogId = (String) HaloApp.get(Constants.WELCOME_DIALOG_ID, false);
|
||||
String linkTitle = (String) HaloApp.get(Constants.WELCOME_DIALOG_LINK_TITLE, false);
|
||||
|
||||
ExposureEntity payload = new ExposureEntity();
|
||||
payload.setWelcomeDialogId(dialogId);
|
||||
payload.setWelcomeDialogLinkTitle(linkTitle);
|
||||
|
||||
SimpleLogContainerEntity entity = new SimpleLogContainerEntity();
|
||||
entity.setEvent("like");
|
||||
entity.setMeta(MetaUtil.INSTANCE.getMeta());
|
||||
entity.setPayload(payload);
|
||||
entity.setTimestamp(System.currentTimeMillis() / 1000);
|
||||
|
||||
LoghubUtils.log(GsonUtils.toJsonIgnoreNull(entity), "event", false);
|
||||
}
|
||||
|
||||
public static void uploadCommentFromWelcomeDialog() {
|
||||
String dialogId = (String) HaloApp.get(Constants.WELCOME_DIALOG_ID, false);
|
||||
String linkTitle = (String) HaloApp.get(Constants.WELCOME_DIALOG_LINK_TITLE, false);
|
||||
|
||||
ExposureEntity payload = new ExposureEntity();
|
||||
payload.setWelcomeDialogId(dialogId);
|
||||
payload.setWelcomeDialogLinkTitle(linkTitle);
|
||||
|
||||
SimpleLogContainerEntity entity = new SimpleLogContainerEntity();
|
||||
entity.setEvent("comment");
|
||||
entity.setMeta(MetaUtil.INSTANCE.getMeta());
|
||||
entity.setPayload(payload);
|
||||
entity.setTimestamp(System.currentTimeMillis() / 1000);
|
||||
|
||||
LoghubUtils.log(GsonUtils.toJsonIgnoreNull(entity), "event", false);
|
||||
}
|
||||
|
||||
private static void uploadShare(JSONObject object) {
|
||||
Meta meta = MetaUtil.INSTANCE.getMeta();
|
||||
JSONObject metaObject = new JSONObject();
|
||||
|
||||
@ -159,7 +159,7 @@ object LoginHelper {
|
||||
if (mAccessToken?.isSessionValid == true) {
|
||||
// 保存 Token 到 SharedPreferences
|
||||
AccessTokenKeeper.writeAccessToken(context, mAccessToken)
|
||||
Toast.makeText(context, "授权成功", Toast.LENGTH_SHORT).show()
|
||||
Utils.toast(context, "授权成功")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -55,6 +55,7 @@ public class LoginUtils {
|
||||
@Override
|
||||
public void onFailure(HttpException e) {
|
||||
super.onFailure(e);
|
||||
listener.onCaptcha(null);
|
||||
if (e == null) {
|
||||
Utils.toast(context, "无法获取验证码,请检查你的网络状态");
|
||||
return;
|
||||
|
||||
@ -96,7 +96,7 @@ object NotificationHelper {
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
private fun show(activity: AppCompatActivity?) {
|
||||
fun show(activity: AppCompatActivity?) {
|
||||
if (activity == null) return
|
||||
RetrofitManager.getInstance(activity).api.bootPopup
|
||||
.subscribeOn(Schedulers.io())
|
||||
|
||||
@ -16,6 +16,18 @@ object NumberUtils {
|
||||
}
|
||||
return s
|
||||
}
|
||||
@JvmStatic
|
||||
fun transSimpleLetterCount(count: Int): String {
|
||||
val s: String
|
||||
s = if (count > 10000) {
|
||||
val number = count / 10000f
|
||||
val fmt = DecimalFormat("#.0")
|
||||
fmt.format(number) + "W"
|
||||
} else {
|
||||
count.toString()
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun transSimpleUsageTime(second: Long): String {
|
||||
|
||||
129
app/src/main/java/com/gh/common/util/PackageInstaller.kt
Normal file
129
app/src/main/java/com/gh/common/util/PackageInstaller.kt
Normal file
@ -0,0 +1,129 @@
|
||||
package com.gh.common.util
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import androidx.core.content.FileProvider
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.xapk.XapkInstaller
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.FileUtils
|
||||
import com.lightgame.utils.Utils
|
||||
import java.io.File
|
||||
|
||||
object PackageInstaller {
|
||||
|
||||
|
||||
/**
|
||||
* 为了兼容java代码
|
||||
*/
|
||||
@JvmStatic
|
||||
fun install(context: Context, downloadEntity: DownloadEntity) {
|
||||
install(context, downloadEntity, true)
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动安装应用程序并取消通知栏安装消息
|
||||
*
|
||||
* 兼容所有包安装(apk,xapk),后续可加上apks
|
||||
*
|
||||
* 主动点击安装如果是xapk则需要toast提示
|
||||
*/
|
||||
@JvmStatic
|
||||
fun install(context: Context, downloadEntity: DownloadEntity, showUnzipToast: Boolean) {
|
||||
// 取消状态栏下载完成的通知,若存在
|
||||
downloadEntity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION] = "YES"
|
||||
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)
|
||||
|
||||
val pkgPath = downloadEntity.path
|
||||
if (XapkInstaller.XAPK_EXTENSION_NAME == pkgPath.getExtension()) {
|
||||
XapkInstaller.install(context, downloadEntity, showUnzipToast)
|
||||
} else {
|
||||
install(context, downloadEntity.path)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动安装应用程序
|
||||
*
|
||||
* 除非特殊情况,请勿使用此方法进行应用安装操作
|
||||
* 除非你已经确定该文件一定是Apk
|
||||
*/
|
||||
@JvmStatic
|
||||
fun install(context: Context, pkgPath: String) {
|
||||
try {
|
||||
if (PackageUtils.isCanLaunchSetup(context, pkgPath)) {
|
||||
val installIntent = getInstallIntent(context, pkgPath)
|
||||
context.startActivity(installIntent)
|
||||
} else {
|
||||
DialogUtils.showPluginDialog(context) {
|
||||
uninstall(context, pkgPath)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Utils.toast(context, e.message)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取启动安装意图
|
||||
*
|
||||
* 除非特殊情况,请勿使用此方法进行应用安装操作
|
||||
* 除非你已经确定该文件一定是Apk且该次安装无需检查签名情况
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getInstallIntent(context: Context, path: String): Intent {
|
||||
var uri = Uri.fromFile(File(path))
|
||||
val installIntent = Intent(Intent.ACTION_VIEW)
|
||||
if ("smartisan" == Build.MANUFACTURER) {
|
||||
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID, File(path))
|
||||
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
installIntent.setDataAndType(uri, "application/vnd.android.package-archive")
|
||||
installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
} else {
|
||||
// 应用内更新不加 FLAG_ACTIVITY_NEW_TASK 在模拟器上会出现安装完成后安装界面也一并消失的类似闪退的表现
|
||||
// Application 上下文就更不用说了
|
||||
val pkgName = PackageUtils.getPackageNameByPath(context, path)
|
||||
if (pkgName == context.packageName || context is Application) {
|
||||
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
installIntent.setDataAndType(uri, "application/vnd.android.package-archive")
|
||||
}
|
||||
InstallUtils.getInstance(context).addInstall(PackageUtils.getPackageNameByPath(context, path))
|
||||
return installIntent
|
||||
}
|
||||
|
||||
/**
|
||||
* 卸载应用
|
||||
*/
|
||||
@JvmStatic
|
||||
fun uninstall(context: Context, path: String) {
|
||||
val uninstallIntent = Intent()
|
||||
uninstallIntent.action = Intent.ACTION_DELETE
|
||||
uninstallIntent.addCategory(Intent.CATEGORY_DEFAULT)
|
||||
val packageName = PackageUtils.getPackageNameByPath(context, path)
|
||||
uninstallIntent.data = Uri.parse("package:$packageName")
|
||||
InstallUtils.getInstance(context).addUninstall(packageName)
|
||||
context.startActivity(uninstallIntent)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getDownloadPath(gameName: String?, format: String?): String {
|
||||
return FileUtils.getDownloadPath(HaloApp.getInstance().application, getDownloadFileName(gameName, format))
|
||||
}
|
||||
|
||||
private fun getDownloadFileName(gameName: String?, format: String?): String {
|
||||
var fileExtension = "apk"
|
||||
if (format == XapkInstaller.XAPK_EXTENSION_NAME) {
|
||||
fileExtension = XapkInstaller.XAPK_EXTENSION_NAME
|
||||
}
|
||||
return MD5Utils.getContentMD5(gameName + "_" + System.currentTimeMillis()) + "." + fileExtension
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,6 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
@ -13,17 +12,18 @@ import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.PowerManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.g00fy2.versioncompare.Version;
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
import com.gh.gamecenter.entity.GameUpdateEntity;
|
||||
import com.gh.gamecenter.manager.PackagesManager;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.lightgame.download.DownloadEntity;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import org.json.JSONArray;
|
||||
@ -31,7 +31,6 @@ import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
@ -42,9 +41,6 @@ import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.FileProvider;
|
||||
|
||||
public class PackageUtils {
|
||||
|
||||
public static final String publicKey = "OpenSSLRSAPublicKey{modulus=a8c4bb5748fec8d5c35db1a7a182d41ba4721a91131a417330af79ef4ddb43f9fa0ff4907b0a613bfe152de0ed8fc1b2e6f94a908aa98a5f7adc1ce814ba7ec919d75d9910bdfd8649b4789da6a90ffb61f0d23ac4f828a78fcd0d6f6120c1c43c1f87f7498a89eb40ca8e32dfc2f9d5c10d612b95192870223674e241e53305abf320d7eed76ded398778576e4db7b17b3bc6a792f13de5e43a6a5fae4276c73e6990ce97f68dff0ec16fc9594f175c8d49cd0d7877340d9de60942ca0efc737e50b6c295dfe0713e4532b4e810e1ea11b702b4a27753e41559cbceb247e7f044ec4e3ab2e8bccd8b9fd71286e63307550bcde86deee95adb8133076269135b,publicExponent=10001}";
|
||||
@ -63,6 +59,8 @@ public class PackageUtils {
|
||||
updateEntity.setId(gameEntity.getId());
|
||||
updateEntity.setName(gameEntity.getName());
|
||||
updateEntity.setIcon(gameEntity.getIcon());
|
||||
updateEntity.setRawIcon(gameEntity.getRawIcon());
|
||||
updateEntity.setIconSubscript(gameEntity.getIconSubscript());
|
||||
updateEntity.setPackageName(apkEntity.getPackageName());
|
||||
updateEntity.setSize(apkEntity.getSize());
|
||||
updateEntity.setVersion(apkEntity.getVersion());
|
||||
@ -76,6 +74,7 @@ public class PackageUtils {
|
||||
updateEntity.setDownload(gameEntity.getDownload());
|
||||
updateEntity.setIndexPlugin(gameEntity.getIndexPlugin());
|
||||
updateEntity.setPluginDesc(gameEntity.getPluginDesc());
|
||||
updateEntity.setFormat(apkEntity.getFormat());
|
||||
updateList.add(updateEntity);
|
||||
}
|
||||
}
|
||||
@ -113,6 +112,7 @@ public class PackageUtils {
|
||||
updateEntity.setTagStyle(gameEntity.getTagStyle());
|
||||
updateEntity.setIndexPlugin(gameEntity.getIndexPlugin());
|
||||
updateEntity.setPluginDesc(gameEntity.getPluginDesc());
|
||||
updateEntity.setFormat(apkEntity.getFormat());
|
||||
updateList.add(updateEntity);
|
||||
}
|
||||
}
|
||||
@ -232,29 +232,6 @@ public class PackageUtils {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* 启动安装应用程序
|
||||
*/
|
||||
public static void launchSetup(final Context context, DownloadEntity downloadEntity) {
|
||||
// 取消状态栏下载完成的通知,若存在
|
||||
downloadEntity.getMeta().put(Constants.MARK_ALREADY_TRIGGERED_INSTALLATION, "YES");
|
||||
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity);
|
||||
launchSetup(context, downloadEntity.getPath());
|
||||
}
|
||||
|
||||
private static void launchSetup(final Context context, final String path) {
|
||||
try {
|
||||
if (isCanLaunchSetup(context, path)) {
|
||||
context.startActivity(PackageUtils.getInstallIntent(context, path));
|
||||
} else {
|
||||
DialogUtils.showPluginDialog(context,
|
||||
() -> context.startActivity(PackageUtils.getUninstallIntent(context, path)));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Utils.toast(context, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 path 获取 apk 信息确定处理方式
|
||||
*
|
||||
@ -291,37 +268,6 @@ public class PackageUtils {
|
||||
return compareSignatureBetweenInstalledAppWithApk(context, packageName, path);
|
||||
}
|
||||
|
||||
/*
|
||||
* 根据路径,获取安装游戏的意图
|
||||
*/
|
||||
public static Intent getInstallIntent(Context context, String path) {
|
||||
return getInstallIntent(context, path, false);
|
||||
}
|
||||
|
||||
public static Intent getInstallIntent(Context context, String path, boolean isInAppUpdate) {
|
||||
Uri uri = Uri.fromFile(new File(path));
|
||||
Intent installIntent = new Intent(Intent.ACTION_VIEW);
|
||||
if ("smartisan".equals(Build.MANUFACTURER)) {
|
||||
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID, new File(path));
|
||||
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
installIntent.setDataAndType(uri, "application/vnd.android.package-archive");
|
||||
installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
} else {
|
||||
// 应用内更新不加 FLAG_ACTIVITY_NEW_TASK 在模拟器上会出现安装完成后安装界面也一并消失的类似闪退的表现
|
||||
// Application 上下文就更不用说了
|
||||
if (isInAppUpdate || context instanceof Application) {
|
||||
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
}
|
||||
installIntent.setDataAndType(uri, "application/vnd.android.package-archive");
|
||||
}
|
||||
InstallUtils.getInstance(context).addInstall(getPackageNameByPath(context, path));
|
||||
return installIntent;
|
||||
}
|
||||
|
||||
/*
|
||||
* 根据包名,获取卸载游戏的意图
|
||||
*/
|
||||
@ -552,9 +498,10 @@ public class PackageUtils {
|
||||
&& !TextUtils.isEmpty(apkEntity.getGhVersion())
|
||||
&& !PackageUtils.isSignedByGh(HaloApp.getInstance().getApplication(), apkEntity.getPackageName());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取调用者的进程名
|
||||
*
|
||||
* @param context 调用者的上下文
|
||||
* @return 进程名
|
||||
*/
|
||||
@ -571,5 +518,38 @@ public class PackageUtils {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 应用是否在前台运行
|
||||
*/
|
||||
public static boolean isAppOnForeground(Context context) {
|
||||
ActivityManager activityManager = (ActivityManager) context.getApplicationContext()
|
||||
.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
if (activityManager == null) return false;
|
||||
|
||||
List<ActivityManager.RunningAppProcessInfo> appProcesses =
|
||||
activityManager.getRunningAppProcesses();
|
||||
if (appProcesses == null) return false;
|
||||
|
||||
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
if (pm == null) return false;
|
||||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
|
||||
if (!pm.isInteractive()) return false;
|
||||
} else {
|
||||
if (!pm.isScreenOn()) return false;
|
||||
}
|
||||
|
||||
String packageName = context.getApplicationContext().getPackageName();
|
||||
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
|
||||
// The name of the process that this object is associated with.
|
||||
if (appProcess.processName.equals(packageName) && appProcess.importance
|
||||
== ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -24,6 +24,9 @@ import android.widget.PopupWindow;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.facebook.common.references.CloseableReference;
|
||||
import com.facebook.datasource.DataSource;
|
||||
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber;
|
||||
@ -54,9 +57,6 @@ import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import static com.gh.common.util.LoginHelper.WEIBO_SCOPE;
|
||||
|
||||
/**
|
||||
@ -247,17 +247,17 @@ public class ShareUtils {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
contentView.setOnClickListener(v -> popupWindow.get().dismiss());
|
||||
contentView.setOnClickListener(v -> safelyDismiss());
|
||||
|
||||
contentView.setOnKeyListener((v, keyCode, event) -> {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK
|
||||
&& event.getRepeatCount() == 0
|
||||
&& popupWindow != null
|
||||
&& popupWindow.get() != null
|
||||
&& popupWindow.get().isShowing()) {
|
||||
if (callBack != null) {
|
||||
callBack.onCancel();
|
||||
}
|
||||
popupWindow.get().dismiss();
|
||||
safelyDismiss();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
@ -298,7 +298,7 @@ public class ShareUtils {
|
||||
}
|
||||
|
||||
if (mShareEntrance != ShareEntrance.shareGh) {
|
||||
popupWindow.get().dismiss();
|
||||
safelyDismiss();
|
||||
}
|
||||
}
|
||||
|
||||
@ -336,9 +336,9 @@ public class ShareUtils {
|
||||
req.message = msg;
|
||||
req.scene = SendMessageToWX.Req.WXSceneSession;
|
||||
|
||||
loadBitMap(shareIcon, msg, req);
|
||||
loadBitmapAndShare(shareIcon, msg, req);
|
||||
if (mShareEntrance != ShareEntrance.shareGh) {
|
||||
popupWindow.get().dismiss();
|
||||
safelyDismiss();
|
||||
}
|
||||
}
|
||||
|
||||
@ -346,10 +346,10 @@ public class ShareUtils {
|
||||
return (type == null) ? String.valueOf(System.currentTimeMillis()) : type + System.currentTimeMillis();
|
||||
}
|
||||
|
||||
private void loadBitMap(final String iconUrl, final WXMediaMessage msg, final SendMessageToWX.Req req) {
|
||||
ImageUtils.display(mContext, iconUrl, new BaseBitmapDataSubscriber() {
|
||||
private void loadBitmapAndShare(final String iconUrl, final WXMediaMessage msg, final SendMessageToWX.Req req) {
|
||||
ImageUtils.getBitmap(iconUrl, new BiCallback<Bitmap, Boolean>() {
|
||||
@Override
|
||||
protected void onNewResultImpl(Bitmap bitmap) {
|
||||
public void onFirst(Bitmap bitmap) {
|
||||
if (mShareEntrance == ShareEntrance.video) {
|
||||
// 分享类型为视频时裁为正方形
|
||||
int dimension = Math.min(bitmap.getWidth(), bitmap.getHeight());
|
||||
@ -367,8 +367,7 @@ public class ShareUtils {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFailureImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
|
||||
Utils.log("分享获取bitmap失败");
|
||||
public void onSecond(Boolean aBoolean) {
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -454,7 +453,7 @@ public class ShareUtils {
|
||||
}
|
||||
|
||||
if (mShareEntrance != ShareEntrance.shareGh) {
|
||||
popupWindow.get().dismiss();
|
||||
safelyDismiss();
|
||||
}
|
||||
}
|
||||
|
||||
@ -497,9 +496,9 @@ public class ShareUtils {
|
||||
req.message = msg;
|
||||
req.scene = SendMessageToWX.Req.WXSceneTimeline;
|
||||
|
||||
loadBitMap(shareIcon, msg, req);
|
||||
loadBitmapAndShare(shareIcon, msg, req);
|
||||
if (mShareEntrance != ShareEntrance.shareGh) {
|
||||
popupWindow.get().dismiss();
|
||||
safelyDismiss();
|
||||
}
|
||||
}
|
||||
|
||||
@ -520,7 +519,7 @@ public class ShareUtils {
|
||||
|
||||
|
||||
if (mShareEntrance != ShareEntrance.shareGh) {
|
||||
popupWindow.get().dismiss();
|
||||
safelyDismiss();
|
||||
}
|
||||
}
|
||||
|
||||
@ -562,8 +561,8 @@ public class ShareUtils {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (mShareEntrance != ShareEntrance.shareGh) {
|
||||
popupWindow.get().dismiss();
|
||||
if (mShareEntrance != ShareEntrance.shareGh ) {
|
||||
safelyDismiss();
|
||||
}
|
||||
}
|
||||
|
||||
@ -575,7 +574,7 @@ public class ShareUtils {
|
||||
cmb.setText(copyContent);
|
||||
if (mShareEntrance != ShareEntrance.shareGh) {
|
||||
Utils.toast(mContext, "复制成功");
|
||||
popupWindow.get().dismiss();
|
||||
safelyDismiss();
|
||||
} else {
|
||||
Utils.toast(mContext, "复制成功,请到微信/QQ粘贴分享");
|
||||
}
|
||||
@ -661,7 +660,7 @@ public class ShareUtils {
|
||||
break;
|
||||
case 7:
|
||||
if (mShareEntrance != ShareEntrance.shareGh) {
|
||||
popupWindow.get().dismiss();
|
||||
safelyDismiss();
|
||||
} else {
|
||||
shareType = "copy_link";
|
||||
LogUtils.uploadShareType(shareType, shareEntrance.getName(), shareUrl, mTitle, mSummary, resourceId);
|
||||
@ -689,6 +688,12 @@ public class ShareUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void safelyDismiss() {
|
||||
if (popupWindow.get() != null) {
|
||||
popupWindow.get().dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
interface OnItemClickListener {
|
||||
void onItemClick(int position);
|
||||
|
||||
@ -5,10 +5,9 @@ import android.graphics.Color
|
||||
import android.graphics.Typeface
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
import android.text.style.AbsoluteSizeSpan
|
||||
import android.text.style.ForegroundColorSpan
|
||||
import android.text.style.StrikethroughSpan
|
||||
import android.text.style.StyleSpan
|
||||
import android.text.TextPaint
|
||||
import android.text.style.*
|
||||
import android.view.View
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.gh.common.view.CenterImageSpan
|
||||
@ -65,6 +64,23 @@ class SpanBuilder(content: String) {
|
||||
return this
|
||||
}
|
||||
|
||||
fun click(start: Int, end: Int, colorRes: Int, onClick: () -> Unit): SpanBuilder {
|
||||
val clickSpan = object : ClickableSpan() {
|
||||
override fun updateDrawState(ds: TextPaint) {
|
||||
super.updateDrawState(ds)
|
||||
ds.color = ContextCompat.getColor(HaloApp.getInstance().application, colorRes)
|
||||
ds.isUnderlineText = false
|
||||
}
|
||||
|
||||
override fun onClick(widget: View) {
|
||||
onClick.invoke()
|
||||
}
|
||||
|
||||
}
|
||||
spannableString.setSpan(clickSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
return this
|
||||
}
|
||||
|
||||
fun build(): SpannableStringBuilder {
|
||||
return spannableString
|
||||
}
|
||||
|
||||
@ -23,6 +23,7 @@ object TimeUtils {
|
||||
|
||||
fun getFormatTime(time: Long, pattern: String = "yyyy-MM-dd"): String {
|
||||
val f = SimpleDateFormat(pattern, Locale.CHINA)
|
||||
f.timeZone = TimeZone.getTimeZone("Asia/Shanghai")
|
||||
return f.format(Date(time * 1000))
|
||||
}
|
||||
|
||||
@ -84,4 +85,19 @@ object TimeUtils {
|
||||
val second = length % 60
|
||||
return String.format(Locale.CHINA, "%02d:%02d", minute, second)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getDayString(date: Long): String {
|
||||
val offSet = Calendar.getInstance().timeZone.rawOffset
|
||||
val today = (System.currentTimeMillis() + offSet) / 86400000
|
||||
val start = (date * 1000 + offSet) / 86400000
|
||||
return when ((start - today).toInt()) {
|
||||
-2 -> "(前天)"
|
||||
-1 -> "(昨天)"
|
||||
0 -> "(今天)"
|
||||
1 -> "(明天)"
|
||||
2 -> "(后天)"
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,7 @@ package com.gh.common.util
|
||||
import android.widget.Toast
|
||||
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.utils.toast.ToastHandler
|
||||
|
||||
object ToastUtils {
|
||||
/** 之前显示的内容 */
|
||||
@ -32,7 +33,7 @@ object ToastUtils {
|
||||
*/
|
||||
fun showToast(message: String, gravity: Int = -1, yOffset: Int = 0) {
|
||||
if (mToast == null) {
|
||||
mToast = Toast.makeText(HaloApp.getInstance().application, message, Toast.LENGTH_SHORT)
|
||||
mToast = ToastHandler.INSTANCE.getToastInstance(HaloApp.getInstance().application, message, Toast.LENGTH_SHORT)
|
||||
if (gravity != -1) mToast!!.setGravity(gravity, 0, yOffset) else
|
||||
mToast!!.setGravity(DisplayUtils.getToastDefaultGravity(), 0, DisplayUtils.getToastOffset())
|
||||
mToast!!.show()
|
||||
|
||||
@ -61,7 +61,7 @@ object VideoRecordUtils {
|
||||
if (!UserManager.getInstance().isLoggedIn) return
|
||||
val requestMap = HashMap<String, Any>()
|
||||
val videoIds = videoRecordSet.toList().map { it.videoId }
|
||||
requestMap["g_id"] = HaloApp.getInstance().gid
|
||||
requestMap["g_id"] = HaloApp.getInstance().gid ?: ""
|
||||
requestMap["time"] = time
|
||||
requestMap["video_id"] = videoIds
|
||||
RetrofitManager.getInstance(HaloApp.getInstance().application).api
|
||||
|
||||
@ -5,10 +5,12 @@ import android.graphics.drawable.Animatable;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
@ -19,6 +21,7 @@ import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gh.gamecenter.R;
|
||||
import com.scwang.smartrefresh.layout.api.RefreshInternal;
|
||||
import com.scwang.smartrefresh.layout.api.RefreshKernel;
|
||||
import com.scwang.smartrefresh.layout.api.RefreshLayout;
|
||||
@ -74,21 +77,21 @@ public abstract class AbstractSwipeRefreshHeader<T extends AbstractSwipeRefreshH
|
||||
progressView.setId(ID_IMAGE_PROGRESS);
|
||||
centerLayout.setId(android.R.id.widget_frame);
|
||||
|
||||
LinearLayout.LayoutParams lpHeaderText = new LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
|
||||
centerLayout.addView(titleView, lpHeaderText);
|
||||
// LinearLayout.LayoutParams lpHeaderText = new LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
|
||||
// centerLayout.addView(titleView, lpHeaderText);
|
||||
|
||||
RelativeLayout.LayoutParams lpHeaderLayout = new RelativeLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
|
||||
lpHeaderLayout.addRule(CENTER_IN_PARENT);
|
||||
thisGroup.addView(centerLayout, lpHeaderLayout);
|
||||
|
||||
RelativeLayout.LayoutParams lpArrow = new RelativeLayout.LayoutParams(mDensityUtil.dip2px(15), mDensityUtil.dip2px(15));
|
||||
RelativeLayout.LayoutParams lpArrow = new RelativeLayout.LayoutParams(mDensityUtil.dip2px(35), mDensityUtil.dip2px(35));
|
||||
lpArrow.addRule(CENTER_VERTICAL);
|
||||
lpArrow.addRule(LEFT_OF, android.R.id.widget_frame);
|
||||
lpArrow.addRule(CENTER_IN_PARENT, android.R.id.widget_frame);
|
||||
thisGroup.addView(arrowView, lpArrow);
|
||||
|
||||
RelativeLayout.LayoutParams lpProgress = new RelativeLayout.LayoutParams((ViewGroup.LayoutParams) lpArrow);
|
||||
lpProgress.addRule(CENTER_VERTICAL);
|
||||
lpProgress.addRule(LEFT_OF, android.R.id.widget_frame);
|
||||
lpProgress.addRule(CENTER_IN_PARENT, android.R.id.widget_frame);
|
||||
progressView.animate().setInterpolator(new LinearInterpolator());
|
||||
thisGroup.addView(progressView, lpProgress);
|
||||
|
||||
|
||||
@ -190,8 +190,8 @@ class AdBannerView : LinearLayout {
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
val ad = mDatas[position % mDatas.size]
|
||||
val view = holder.itemView as ImageView
|
||||
Picasso.with(context).load(ad.image).into(view)
|
||||
val view = holder.itemView as SimpleDraweeView
|
||||
ImageUtils.display(view,ad.image)
|
||||
holder.itemView.setOnClickListener {
|
||||
onItemClick?.invoke(position % mDatas.size)
|
||||
}
|
||||
|
||||
@ -9,6 +9,8 @@ import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
|
||||
public class CropImageBorderView extends View {
|
||||
|
||||
/**
|
||||
@ -28,7 +30,7 @@ public class CropImageBorderView extends View {
|
||||
*/
|
||||
private int mBorderWidth = 1;
|
||||
|
||||
private Paint mPaint, mPaintRect;
|
||||
private Paint mPaint, mPaintRect, mAnglePaint;
|
||||
|
||||
private float mRatio = 1; // 宽高比
|
||||
|
||||
@ -48,7 +50,7 @@ public class CropImageBorderView extends View {
|
||||
|
||||
// 绘制阴影
|
||||
mPaintRect = new Paint();
|
||||
mPaintRect.setARGB(136, 0, 0, 0);
|
||||
mPaintRect.setARGB(80, 0, 0, 0);
|
||||
mPaintRect.setStyle(Style.FILL);
|
||||
|
||||
// 绘制边框
|
||||
@ -56,7 +58,12 @@ public class CropImageBorderView extends View {
|
||||
mPaint.setStyle(Style.STROKE);
|
||||
mPaint.setAntiAlias(true);
|
||||
mPaint.setColor(Color.WHITE);
|
||||
mPaint.setStrokeWidth(mBorderWidth);
|
||||
mPaint.setStrokeWidth(0.5F);
|
||||
|
||||
// 绘制边框
|
||||
mAnglePaint = new Paint();
|
||||
mAnglePaint.setStyle(Style.FILL);
|
||||
mAnglePaint.setColor(Color.WHITE);
|
||||
|
||||
}
|
||||
|
||||
@ -86,6 +93,45 @@ public class CropImageBorderView extends View {
|
||||
canvas.drawRect(mHorizontalPadding, mVerticalPadding,
|
||||
mHorizontalPadding + mWidth, getHeight() - mVerticalPadding, mPaint);
|
||||
|
||||
// 左上
|
||||
canvas.drawRect(mHorizontalPadding - DisplayUtils.dip2px(1F)
|
||||
, mVerticalPadding - DisplayUtils.dip2px(1F)
|
||||
, mHorizontalPadding + DisplayUtils.dip2px(16F)
|
||||
, mVerticalPadding + DisplayUtils.dip2px(1F), mAnglePaint);
|
||||
canvas.drawRect(mHorizontalPadding - DisplayUtils.dip2px(1F)
|
||||
, mVerticalPadding - DisplayUtils.dip2px(1F)
|
||||
, mHorizontalPadding + DisplayUtils.dip2px(1F)
|
||||
, mVerticalPadding + DisplayUtils.dip2px(16F), mAnglePaint);
|
||||
|
||||
// 右上
|
||||
canvas.drawRect(mHorizontalPadding + mWidth - DisplayUtils.dip2px(16F)
|
||||
, mVerticalPadding - DisplayUtils.dip2px(1F)
|
||||
, mHorizontalPadding + mWidth
|
||||
, mVerticalPadding + DisplayUtils.dip2px(1F), mAnglePaint);
|
||||
canvas.drawRect(mHorizontalPadding + mWidth - DisplayUtils.dip2px(1F)
|
||||
, mVerticalPadding - DisplayUtils.dip2px(1F)
|
||||
, mHorizontalPadding + mWidth + DisplayUtils.dip2px(1F)
|
||||
, mVerticalPadding + DisplayUtils.dip2px(16F), mAnglePaint);
|
||||
|
||||
// 左下
|
||||
canvas.drawRect(mHorizontalPadding - DisplayUtils.dip2px(1F)
|
||||
, getHeight() - mVerticalPadding - DisplayUtils.dip2px(16F)
|
||||
, mHorizontalPadding + DisplayUtils.dip2px(1F)
|
||||
, getHeight() - mVerticalPadding - DisplayUtils.dip2px(1F), mAnglePaint);
|
||||
canvas.drawRect(mHorizontalPadding - DisplayUtils.dip2px(1F)
|
||||
, getHeight() - mVerticalPadding - DisplayUtils.dip2px(1F)
|
||||
, mHorizontalPadding + DisplayUtils.dip2px(16F)
|
||||
, getHeight() - mVerticalPadding + DisplayUtils.dip2px(1F), mAnglePaint);
|
||||
|
||||
// 右下
|
||||
canvas.drawRect(mHorizontalPadding + mWidth - DisplayUtils.dip2px(16F)
|
||||
, getHeight() - mVerticalPadding - DisplayUtils.dip2px(1F)
|
||||
, mHorizontalPadding + mWidth
|
||||
, getHeight() - mVerticalPadding + DisplayUtils.dip2px(1F), mAnglePaint);
|
||||
canvas.drawRect(mHorizontalPadding + mWidth - DisplayUtils.dip2px(1F)
|
||||
, getHeight() - mVerticalPadding - DisplayUtils.dip2px(16F)
|
||||
, mHorizontalPadding + mWidth + DisplayUtils.dip2px(1F)
|
||||
, getHeight() - mVerticalPadding + DisplayUtils.dip2px(1F), mAnglePaint);
|
||||
}
|
||||
|
||||
public void setHorizontalPadding(int mHorizontalPadding, float ratio) {
|
||||
|
||||
@ -2,7 +2,6 @@ package com.gh.common.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Matrix;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
import android.widget.ImageView;
|
||||
@ -58,24 +57,17 @@ public class CropImageCustom extends RelativeLayout {
|
||||
return mZoomImageView.clip();
|
||||
}
|
||||
|
||||
// 用户头像压缩规则
|
||||
public boolean savePicture(String path) {
|
||||
float limitSize = 900;
|
||||
int quality = 90;
|
||||
Bitmap bitmap = mZoomImageView.clip();
|
||||
File file = new File(path);
|
||||
|
||||
if (bitmap.getHeight() > limitSize || bitmap.getWidth() > limitSize) {
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.setScale(limitSize / bitmap.getWidth(), limitSize / bitmap.getHeight());
|
||||
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
|
||||
}
|
||||
|
||||
try {
|
||||
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
|
||||
bitmap.compress(Bitmap.CompressFormat.WEBP, quality, bos);
|
||||
bos.flush();
|
||||
bos.close();
|
||||
Bitmap clip = mZoomImageView.clip();
|
||||
try {
|
||||
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(path)));
|
||||
clip.compress(Bitmap.CompressFormat.WEBP, 100, bos);
|
||||
bos.flush();
|
||||
bos.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
|
||||
@ -318,11 +318,18 @@ public class CropImageZoomView extends AppCompatImageView implements
|
||||
|
||||
if (dw <= getWidth() - mHorizontalPadding * 2
|
||||
&& dh <= getHeight() - mVerticalPadding * 2) {// 如果图片的高度<截图区高度,并且图片宽度<截图区宽度时
|
||||
float scaleW = (getWidth() * 1.0f - mHorizontalPadding * 2)
|
||||
/ dw;
|
||||
float scaleW = (getWidth() * 1.0f - mHorizontalPadding * 2) / dw;
|
||||
float scaleH = (getHeight() * 1.0f - mVerticalPadding * 2) / dh;
|
||||
scale = Math.max(scaleW, scaleH);
|
||||
}
|
||||
|
||||
// 宽、高均超出截图区域
|
||||
if (dw > getWidth() - mHorizontalPadding * 2 && dh > getHeight() - mVerticalPadding * 2) {
|
||||
float scaleW = (getWidth() * 1.0f - mHorizontalPadding * 2) / dw;
|
||||
float scaleH = (getHeight() * 1.0f - mVerticalPadding * 2) / dh;
|
||||
scale = Math.max(scaleW, scaleH);
|
||||
}
|
||||
|
||||
initScale = scale;
|
||||
SCALE_MID = initScale * 2;
|
||||
SCALE_MAX = initScale * 4;
|
||||
|
||||
25
app/src/main/java/com/gh/common/view/CustomMarkerView.kt
Normal file
25
app/src/main/java/com/gh/common/view/CustomMarkerView.kt
Normal file
@ -0,0 +1,25 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.gh.common.util.DisplayUtils
|
||||
import com.gh.common.util.dip2px
|
||||
import com.gh.gamecenter.R
|
||||
import com.github.mikephil.charting.components.MarkerView
|
||||
import com.github.mikephil.charting.data.Entry
|
||||
import com.github.mikephil.charting.highlight.Highlight
|
||||
import com.github.mikephil.charting.utils.MPPointF
|
||||
|
||||
class CustomMarkerView(context: Context) : MarkerView(context, R.layout.layout_chart_markerview) {
|
||||
var markerView: TextView = findViewById(R.id.markerView)
|
||||
override fun refreshContent(e: Entry, highlight: Highlight?) {
|
||||
markerView.text = e.y.toInt().toString()
|
||||
super.refreshContent(e, highlight)
|
||||
}
|
||||
|
||||
|
||||
override fun getOffset(): MPPointF {
|
||||
return MPPointF((-(width / 2)).toFloat(), (-height).toFloat() - 3f.dip2px())
|
||||
}
|
||||
}
|
||||
@ -15,12 +15,12 @@ import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
public class DownloadProgressBar extends ProgressBar {
|
||||
public static final int MAX_LENGTH = 1000;
|
||||
public static final int DOWNLOAD_NORMAL_STYLE = 0;
|
||||
@ -38,7 +38,11 @@ public class DownloadProgressBar extends ProgressBar {
|
||||
DOWNLOADING_PLUGIN,
|
||||
RESERVABLE,
|
||||
RESERVED,
|
||||
H5_GAME
|
||||
H5_GAME,
|
||||
|
||||
XAPK_UNZIPPING,
|
||||
XAPK_SUCCESS,
|
||||
XAPK_FAILURE,
|
||||
}
|
||||
|
||||
private PorterDuffXfermode mDuffXFerMode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
|
||||
@ -214,6 +218,12 @@ public class DownloadProgressBar extends ProgressBar {
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.game_item_btn_pause_dn));
|
||||
mDefaultColor = ContextCompat.getColor(getContext(), R.color.all_white);
|
||||
break;
|
||||
case XAPK_FAILURE:
|
||||
case XAPK_SUCCESS:
|
||||
case XAPK_UNZIPPING:
|
||||
setProgressDrawable(getResources().getDrawable(R.drawable.progressbar_xapk_detail_style));
|
||||
mDefaultColor = ContextCompat.getColor(getContext(), R.color.all_white);
|
||||
break;
|
||||
}
|
||||
|
||||
mDownloadType = downloadType;
|
||||
|
||||
117
app/src/main/java/com/gh/common/view/DraggableBigImageView.kt
Normal file
117
app/src/main/java/com/gh/common/view/DraggableBigImageView.kt
Normal file
@ -0,0 +1,117 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.view.ViewConfiguration
|
||||
import com.github.piasy.biv.view.BigImageView
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.sqrt
|
||||
|
||||
class DraggableBigImageView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0)
|
||||
: BigImageView(context, attrs, defStyle) {
|
||||
|
||||
private var mInitScale: Float? = null
|
||||
private val mScaledTouchSlop by lazy { ViewConfiguration.get(context).scaledTouchSlop }
|
||||
private val mDismissEdge by lazy { height * 0.12 }
|
||||
private var mSingleTouch = true
|
||||
private var mFakeDragOffset = 0F
|
||||
private var mLastX = 0F
|
||||
private var mLastY = 0F
|
||||
private var mListener: DragListener? = null
|
||||
|
||||
fun setDragListener(listener: DragListener) {
|
||||
mListener = listener
|
||||
}
|
||||
|
||||
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
|
||||
when (event.actionMasked) {
|
||||
MotionEvent.ACTION_POINTER_DOWN -> {
|
||||
setSingleTouch(false)
|
||||
animate()
|
||||
.translationX(0F).translationY(0F).scaleX(1F).scaleY(1F)
|
||||
.setDuration(200).start()
|
||||
}
|
||||
MotionEvent.ACTION_DOWN -> if (mInitScale == null || mInitScale == 0F) mInitScale = ssiv?.scale
|
||||
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> up()
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
if (mSingleTouch && mInitScale != 0F && ssiv?.scale == mInitScale) {
|
||||
if (mLastX == 0F) mLastX = event.rawX
|
||||
if (mLastY == 0F) mLastY = event.rawY
|
||||
val offsetX = event.rawX - mLastX
|
||||
val offsetY = event.rawY - mLastY
|
||||
fakeDrag(offsetX, offsetY)
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.dispatchTouchEvent(event)
|
||||
}
|
||||
|
||||
private fun fakeDrag(offsetX: Float, offsetY: Float) {
|
||||
if (mFakeDragOffset == 0F) {
|
||||
// 大于60度才响应下拉消失
|
||||
if (abs(offsetY) / sqrt(3F) > abs(offsetX)) {
|
||||
if (offsetY > mScaledTouchSlop) {
|
||||
mFakeDragOffset = mScaledTouchSlop.toFloat()
|
||||
} else if (offsetY < -mScaledTouchSlop) {
|
||||
mFakeDragOffset = (-mScaledTouchSlop).toFloat()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mFakeDragOffset != 0F) {
|
||||
val fixedOffsetY = offsetY - mFakeDragOffset
|
||||
parent?.requestDisallowInterceptTouchEvent(true)
|
||||
val fraction = abs(max(-1F, min(1F, fixedOffsetY / height)))
|
||||
val fakeScale = 1 - min(0.4F, fraction)
|
||||
scaleX = fakeScale
|
||||
scaleY = fakeScale
|
||||
translationY = fixedOffsetY
|
||||
translationX = offsetX / 2
|
||||
mListener?.onDrag(this, fraction)
|
||||
}
|
||||
}
|
||||
|
||||
private fun up() {
|
||||
parent?.requestDisallowInterceptTouchEvent(false)
|
||||
setSingleTouch(true)
|
||||
mFakeDragOffset = 0F
|
||||
mLastX = 0F
|
||||
mLastY = 0F
|
||||
|
||||
if (abs(translationY) > mDismissEdge) {
|
||||
mListener?.onRelease(this, scaleX)
|
||||
} else {
|
||||
val offsetY = translationY
|
||||
val fraction = min(1F, offsetY / height)
|
||||
mListener?.onRestore(this, fraction)
|
||||
|
||||
animate().translationX(0F)
|
||||
.translationY(0F)
|
||||
.scaleX(1F)
|
||||
.scaleY(1F)
|
||||
.setDuration(200).start()
|
||||
}
|
||||
}
|
||||
|
||||
fun isDragging(): Boolean {
|
||||
return mFakeDragOffset != 0F
|
||||
}
|
||||
|
||||
private fun setSingleTouch(value: Boolean) {
|
||||
mSingleTouch = value
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
animate().cancel()
|
||||
}
|
||||
|
||||
interface DragListener {
|
||||
fun onDrag(draggableBigImageView: DraggableBigImageView, fraction: Float)
|
||||
fun onRelease(draggableBigImageView: DraggableBigImageView, scale: Float)
|
||||
fun onRestore(draggableBigImageView: DraggableBigImageView, fraction: Float)
|
||||
}
|
||||
|
||||
}
|
||||
@ -194,6 +194,8 @@ public class ExpandTextView extends AppCompatTextView {
|
||||
|
||||
msp.replace(expandTextStartPosition, length, finalEndText + mExpandText);
|
||||
|
||||
if (expandTextStartPosition + mEndText.length() >= msp.length()) return;
|
||||
|
||||
msp.setSpan(new ClickableSpan() {
|
||||
@Override
|
||||
public void updateDrawState(@NonNull TextPaint ds) {
|
||||
|
||||
53
app/src/main/java/com/gh/common/view/GameIconView.kt
Normal file
53
app/src/main/java/com/gh/common/view/GameIconView.kt
Normal file
@ -0,0 +1,53 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.text.TextUtils
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import com.facebook.drawee.generic.RoundingParams
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.gh.common.util.DisplayUtils
|
||||
import com.gh.common.util.ImageUtils
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.entity.GameEntity
|
||||
import kotlinx.android.synthetic.main.layout_game_icon.view.*
|
||||
|
||||
class GameIconView : ConstraintLayout {
|
||||
|
||||
private var mCornerRadius = 10
|
||||
|
||||
constructor(context: Context) : super(context, null)
|
||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs, 0) {
|
||||
initView(attrs)
|
||||
}
|
||||
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
|
||||
initView(attrs)
|
||||
}
|
||||
|
||||
fun initView(attrs: AttributeSet) {
|
||||
View.inflate(context, R.layout.layout_game_icon, this)
|
||||
|
||||
val ta = context.obtainStyledAttributes(attrs, R.styleable.GameIconView)
|
||||
mCornerRadius = ta.getDimensionPixelSize(R.styleable.GameIconView_gameIconCornerRadius, DisplayUtils.dip2px(10F))
|
||||
ta.recycle()
|
||||
|
||||
val roundingParams = RoundingParams.fromCornersRadius(mCornerRadius.toFloat())
|
||||
gameIconIv.hierarchy.roundingParams = roundingParams
|
||||
gameIconDecoratorIv.hierarchy.roundingParams = roundingParams
|
||||
}
|
||||
|
||||
fun setGameEntity(game: GameEntity) {
|
||||
if (!TextUtils.isEmpty(game.rawIcon)) {
|
||||
ImageUtils.display(gameIconIv, game.rawIcon)
|
||||
ImageUtils.display(gameIconDecoratorIv, game.iconSubscript)
|
||||
} else {
|
||||
ImageUtils.display(gameIconIv, game.icon)
|
||||
}
|
||||
}
|
||||
|
||||
fun getIconIv(): SimpleDraweeView = gameIconIv
|
||||
|
||||
fun getIconDecoratorIv(): SimpleDraweeView = gameIconDecoratorIv
|
||||
|
||||
}
|
||||
@ -4,9 +4,10 @@ import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
|
||||
public class HorizontalItemDecoration extends RecyclerView.ItemDecoration {
|
||||
@ -14,6 +15,7 @@ public class HorizontalItemDecoration extends RecyclerView.ItemDecoration {
|
||||
private Paint paint;
|
||||
private int mInterval = 0;
|
||||
private int mSize = 0;
|
||||
private boolean mIncludeEnd = false;
|
||||
|
||||
public HorizontalItemDecoration(Context context, int interval, int size) {
|
||||
paint = new Paint();
|
||||
@ -22,6 +24,15 @@ public class HorizontalItemDecoration extends RecyclerView.ItemDecoration {
|
||||
mSize = size;
|
||||
}
|
||||
|
||||
public HorizontalItemDecoration(Context context, int interval, int size, boolean includeEnd) {
|
||||
paint = new Paint();
|
||||
paint.setColor(Color.WHITE);
|
||||
mInterval = DisplayUtils.dip2px(context, interval);
|
||||
mSize = size;
|
||||
mIncludeEnd = includeEnd;
|
||||
}
|
||||
|
||||
|
||||
// @Override
|
||||
// public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
|
||||
// int top = parent.getPaddingTop();
|
||||
@ -39,7 +50,7 @@ public class HorizontalItemDecoration extends RecyclerView.ItemDecoration {
|
||||
@Override
|
||||
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
|
||||
RecyclerView.State state) {
|
||||
if (parent.getChildPosition(view) == mSize - 1) {
|
||||
if (!mIncludeEnd && parent.getChildPosition(view) == mSize - 1) {
|
||||
outRect.set(0, 0, 0, 0);
|
||||
} else {
|
||||
outRect.set(0, 0, mInterval, 0);
|
||||
|
||||
@ -9,13 +9,14 @@ import android.text.style.ClickableSpan;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class MessageSpannableTextView extends androidx.appcompat.widget.AppCompatTextView {
|
||||
public class MessageSpannableTextView extends AppCompatTextView {
|
||||
|
||||
private OnSpannableClickListener mSpannableClickListener;
|
||||
|
||||
|
||||
@ -269,6 +269,7 @@ public class NestedScrollWebView2 extends DWebView implements NestedScrollingChi
|
||||
ev.setAction(MotionEvent.ACTION_CANCEL);
|
||||
returnValue = super.onTouchEvent(ev);
|
||||
}
|
||||
initVelocityTrackerIfNotExists();
|
||||
final VelocityTracker velocityTracker = mVelocityTracker;
|
||||
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
|
||||
int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
package com.gh.common.view;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
@ -11,6 +10,9 @@ import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.scwang.smartrefresh.layout.R;
|
||||
import com.scwang.smartrefresh.layout.api.RefreshHeader;
|
||||
import com.scwang.smartrefresh.layout.api.RefreshLayout;
|
||||
@ -23,6 +25,7 @@ import com.scwang.smartrefresh.layout.util.DensityUtil;
|
||||
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
@SuppressWarnings({"unused", "UnusedReturnValue"})
|
||||
public class SwipeRefreshHeader extends AbstractSwipeRefreshHeader<SwipeRefreshHeader> implements RefreshHeader {
|
||||
|
||||
@ -83,7 +86,7 @@ public class SwipeRefreshHeader extends AbstractSwipeRefreshHeader<SwipeRefreshH
|
||||
} else {
|
||||
mArrowDrawable = new ArrowDrawable();
|
||||
mArrowDrawable.setColor(0xff666666);
|
||||
mArrowView.setImageDrawable(mArrowDrawable);
|
||||
mArrowView.setImageResource(com.gh.gamecenter.R.drawable.refresh_icon);
|
||||
}
|
||||
|
||||
if (ta.hasValue(R.styleable.ClassicsHeader_srlDrawableProgress)) {
|
||||
@ -91,7 +94,7 @@ public class SwipeRefreshHeader extends AbstractSwipeRefreshHeader<SwipeRefreshH
|
||||
} else {
|
||||
mProgressDrawable = new ProgressDrawable();
|
||||
mProgressDrawable.setColor(0xff666666);
|
||||
mProgressView.setImageDrawable(mProgressDrawable);
|
||||
mProgressView.setImageResource(com.gh.gamecenter.R.drawable.refresh_anim);
|
||||
}
|
||||
|
||||
if (ta.hasValue(R.styleable.ClassicsHeader_srlTextSizeTitle)) {
|
||||
@ -140,7 +143,7 @@ public class SwipeRefreshHeader extends AbstractSwipeRefreshHeader<SwipeRefreshH
|
||||
mCenterLayout.setVisibility(VISIBLE);
|
||||
mTitleText.setText(REFRESH_HEADER_PULLING);
|
||||
mArrowView.setVisibility(VISIBLE);
|
||||
mArrowView.animate().rotation(0);
|
||||
// mArrowView.animate().rotation(0);
|
||||
break;
|
||||
case Refreshing:
|
||||
case RefreshReleased:
|
||||
@ -153,7 +156,7 @@ public class SwipeRefreshHeader extends AbstractSwipeRefreshHeader<SwipeRefreshH
|
||||
successView.setVisibility(GONE);
|
||||
mCenterLayout.setVisibility(VISIBLE);
|
||||
mTitleText.setText(REFRESH_HEADER_RELEASE);
|
||||
mArrowView.animate().rotation(180);
|
||||
// mArrowView.animate().rotation(180);
|
||||
break;
|
||||
case Loading:
|
||||
successView.setVisibility(GONE);
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
package com.gh.common.view
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.view.ViewConfiguration
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import kotlin.math.abs
|
||||
|
||||
/**
|
||||
* 如非特殊情况请勿使用,会强行改变RecyclerView的拦截事件,可能会出现意料之外的问题
|
||||
*/
|
||||
class TouchSlopRecyclerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null)
|
||||
: RecyclerView(context, attrs) {
|
||||
|
||||
private var mPrevX = 0f
|
||||
|
||||
// 触控角度,用来控制触发左右滑动的敏感度
|
||||
var touchSlop = ViewConfiguration.get(context).scaledTouchSlop
|
||||
|
||||
// 默认关闭,否则会误杀上下滑动事件
|
||||
var touchSlopEnabled = false
|
||||
|
||||
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> mPrevX = event.x
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
val eventX = event.x
|
||||
val xDiff = abs(eventX - mPrevX)
|
||||
if (touchSlopEnabled && xDiff > touchSlop) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onInterceptTouchEvent(event)
|
||||
}
|
||||
}
|
||||
@ -8,6 +8,7 @@ import android.view.ViewGroup
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import com.gh.base.fragment.BaseDialogFragment
|
||||
import com.gh.common.TimeElapsedHelper
|
||||
import com.gh.common.constant.Constants
|
||||
import com.gh.common.constant.Constants.SP_LAST_OPENING_ID
|
||||
import com.gh.common.constant.Constants.SP_LAST_OPENING_TIME
|
||||
import com.gh.common.util.*
|
||||
@ -15,12 +16,19 @@ import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.DialogWelcomeBinding
|
||||
import com.gh.gamecenter.entity.CommunityEntity
|
||||
import com.gh.gamecenter.entity.WelcomeDialogEntity
|
||||
import com.halo.assistant.HaloApp
|
||||
|
||||
class WelcomeDialog : BaseDialogFragment() {
|
||||
|
||||
companion object {
|
||||
const val TAG = "welcome_dialog"
|
||||
|
||||
@JvmStatic
|
||||
fun getInstance(welcomeEntity: WelcomeDialogEntity?) = WelcomeDialog().apply { mWelcomeEntity = welcomeEntity }
|
||||
fun getInstance(welcomeEntity: WelcomeDialogEntity?) = WelcomeDialog().apply {
|
||||
arguments = Bundle()
|
||||
arguments?.putParcelable(TAG, welcomeEntity)
|
||||
LogUtils.uploadWelcomeDialog("show", welcomeEntity?.id, welcomeEntity?.text)
|
||||
}
|
||||
}
|
||||
|
||||
private var mWelcomeEntity: WelcomeDialogEntity? = null
|
||||
@ -34,12 +42,18 @@ class WelcomeDialog : BaseDialogFragment() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
mWelcomeEntity = arguments?.getParcelable(TAG)
|
||||
mTimeHelper = TimeElapsedHelper(this)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
binding = DataBindingUtil.inflate(inflater, R.layout.dialog_welcome, container, false)
|
||||
binding.ivOpeningCover.setOnClickListener {
|
||||
|
||||
HaloApp.put(Constants.WELCOME_DIALOG_ID, mWelcomeEntity?.id)
|
||||
HaloApp.put(Constants.WELCOME_DIALOG_LINK_TITLE, mWelcomeEntity?.text)
|
||||
LogUtils.uploadWelcomeDialog("click", mWelcomeEntity?.id, mWelcomeEntity?.text)
|
||||
|
||||
when (mWelcomeEntity?.type) {
|
||||
EntranceUtils.HOST_ARTICLE -> {
|
||||
DirectUtils.directToArticle(requireContext(), mWelcomeEntity?.link!!, EntranceUtils.ENTRANCE_WELCOME)
|
||||
@ -51,10 +65,10 @@ class WelcomeDialog : BaseDialogFragment() {
|
||||
DirectUtils.directToSubject(requireContext(), mWelcomeEntity?.link!!, null, EntranceUtils.ENTRANCE_WELCOME)
|
||||
}
|
||||
EntranceUtils.HOST_QUESTION -> {
|
||||
DirectUtils.directToQuestionDetail(requireContext(), mWelcomeEntity?.link!!, EntranceUtils.ENTRANCE_WELCOME, "首页弹窗")
|
||||
DirectUtils.directToQuestionDetail(requireContext(), mWelcomeEntity?.link!!, EntranceUtils.ENTRANCE_WELCOME)
|
||||
}
|
||||
EntranceUtils.HOST_ANSWER -> {
|
||||
DirectUtils.directToAnswerDetail(requireContext(), mWelcomeEntity?.link!!, EntranceUtils.ENTRANCE_WELCOME, "首页弹窗")
|
||||
DirectUtils.directToAnswerDetail(requireContext(), mWelcomeEntity?.link!!, EntranceUtils.ENTRANCE_WELCOME)
|
||||
}
|
||||
EntranceUtils.HOST_WEB -> {
|
||||
DirectUtils.directToWebView(requireContext(), mWelcomeEntity?.link!!, EntranceUtils.ENTRANCE_WELCOME)
|
||||
@ -67,7 +81,7 @@ class WelcomeDialog : BaseDialogFragment() {
|
||||
}
|
||||
// else -> DialogUtils.showLowVersionDialog(context)
|
||||
else -> DirectUtils.directToLinkPage(requireContext(), mWelcomeEntity
|
||||
?: WelcomeDialogEntity(), EntranceUtils.ENTRANCE_WELCOME, "首页弹窗")
|
||||
?: WelcomeDialogEntity(), EntranceUtils.ENTRANCE_WELCOME, "")
|
||||
}
|
||||
|
||||
mDismissByClickImage = true
|
||||
@ -111,15 +125,9 @@ class WelcomeDialog : BaseDialogFragment() {
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
val type = if (mDismissByClickImage) {
|
||||
"点击图片"
|
||||
} else {
|
||||
"点击关闭"
|
||||
}
|
||||
val type = if (mDismissByClickImage) "点击图片" else "点击关闭"
|
||||
|
||||
DataUtils.trackTimeEvent(context, "启动弹窗",
|
||||
mTimeHelper?.elapsedTime!!,
|
||||
type, "No parameter.")
|
||||
MtaHelper.onEventWithTime("启动弹窗", mTimeHelper?.elapsedTime!!, type, "No parameter.")
|
||||
|
||||
PreferenceManager.getDefaultSharedPreferences(context?.applicationContext).edit {
|
||||
putString(SP_LAST_OPENING_ID, mWelcomeEntity?.id)
|
||||
|
||||
@ -75,6 +75,12 @@ public class DWebView extends WebView {
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
@JavascriptInterface
|
||||
public String call(String methodName) {
|
||||
return call(methodName, "");
|
||||
}
|
||||
|
||||
@Keep
|
||||
@JavascriptInterface
|
||||
public String call(String methodName, String argStr) {
|
||||
@ -93,7 +99,7 @@ public class DWebView extends WebView {
|
||||
PrintDebugInfo(error);
|
||||
return ret.toString();
|
||||
}
|
||||
Object arg=null;
|
||||
Object arg = null;
|
||||
Method method = null;
|
||||
String callback = null;
|
||||
|
||||
@ -102,7 +108,7 @@ public class DWebView extends WebView {
|
||||
if (args.has("_dscbstub")) {
|
||||
callback = args.getString("_dscbstub");
|
||||
}
|
||||
if(args.has("data")) {
|
||||
if (args.has("data")) {
|
||||
arg = args.get("data");
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
@ -123,7 +129,10 @@ public class DWebView extends WebView {
|
||||
try {
|
||||
method = cls.getMethod(methodName, new Class[]{Object.class});
|
||||
} catch (Exception ex) {
|
||||
|
||||
try {
|
||||
method = cls.getMethod(methodName, new Class[]{});
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,7 +196,12 @@ public class DWebView extends WebView {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
retData = method.invoke(jsb, arg);
|
||||
Class<?>[] methodParameterTypes = method.getParameterTypes();
|
||||
if (methodParameterTypes.length == 0) {
|
||||
retData = method.invoke(jsb);
|
||||
} else {
|
||||
retData = method.invoke(jsb, arg);
|
||||
}
|
||||
ret.put("code", 0);
|
||||
ret.put("data", retData);
|
||||
return ret.toString();
|
||||
@ -307,7 +321,10 @@ public class DWebView extends WebView {
|
||||
try {
|
||||
method = cls.getMethod(nameStr[1], new Class[]{Object.class});
|
||||
} catch (Exception ex) {
|
||||
|
||||
try {
|
||||
method = cls.getMethod(nameStr[1], new Class[]{});
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (method != null) {
|
||||
@ -336,7 +353,7 @@ public class DWebView extends WebView {
|
||||
|| javascriptCloseWindowListener.onClose()) {
|
||||
Context context = getContext();
|
||||
if (context instanceof Activity) {
|
||||
((Activity)context).onBackPressed();
|
||||
((Activity) context).onBackPressed();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -359,7 +376,7 @@ public class DWebView extends WebView {
|
||||
|
||||
@Keep
|
||||
@JavascriptInterface
|
||||
public void returnValue(final Object obj){
|
||||
public void returnValue(final Object obj) {
|
||||
runOnMainThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -422,9 +439,9 @@ public class DWebView extends WebView {
|
||||
runOnMainThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (url != null && url.startsWith("javascript:")){
|
||||
if (url != null && url.startsWith("javascript:")) {
|
||||
DWebView.super.loadUrl(url);
|
||||
}else{
|
||||
} else {
|
||||
callInfoList = new ArrayList<>();
|
||||
DWebView.super.loadUrl(url);
|
||||
}
|
||||
@ -444,9 +461,9 @@ public class DWebView extends WebView {
|
||||
runOnMainThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (url != null && url.startsWith("javascript:")){
|
||||
if (url != null && url.startsWith("javascript:")) {
|
||||
DWebView.super.loadUrl(url, additionalHttpHeaders);
|
||||
}else{
|
||||
} else {
|
||||
callInfoList = new ArrayList<>();
|
||||
DWebView.super.loadUrl(url, additionalHttpHeaders);
|
||||
}
|
||||
@ -996,7 +1013,4 @@ public class DWebView extends WebView {
|
||||
mainHandler.post(runnable);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
15
app/src/main/java/com/gh/common/xapk/IXapkUnzipListener.kt
Normal file
15
app/src/main/java/com/gh/common/xapk/IXapkUnzipListener.kt
Normal file
@ -0,0 +1,15 @@
|
||||
package com.gh.common.xapk
|
||||
|
||||
import com.lightgame.download.DownloadEntity
|
||||
|
||||
interface IXapkUnzipListener {
|
||||
fun onProgress(downloadEntity: DownloadEntity, unzipPath: String, unzipSize: Long, unzipProgress: Long)
|
||||
|
||||
fun onNext(downloadEntity: DownloadEntity, unzipPath: String)
|
||||
|
||||
fun onCancel(downloadEntity: DownloadEntity)
|
||||
|
||||
fun onFailure(downloadEntity: DownloadEntity, exception: Exception)
|
||||
|
||||
fun onSuccess(downloadEntity: DownloadEntity)
|
||||
}
|
||||
175
app/src/main/java/com/gh/common/xapk/XapkInstaller.kt
Normal file
175
app/src/main/java/com/gh/common/xapk/XapkInstaller.kt
Normal file
@ -0,0 +1,175 @@
|
||||
package com.gh.common.xapk
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import com.gh.common.AppExecutor
|
||||
import com.gh.common.util.*
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DataChanger
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.utils.Util_System_Phone_State
|
||||
import com.lightgame.utils.Utils
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* 目前已知的Xapk内容是:只有一个apk包和一个或做多个obb数据包(多余文件不解压,如果存在多个apk包,则以下安装无效)
|
||||
*
|
||||
* 每次安装都会重新跑一遍解压安装流程
|
||||
* 目前检验是否已解压的根据是存在相同文件名且大小一致(暂时想不到校验MD5值的方法)
|
||||
*
|
||||
* obb文件直接解压至根目录即可,无需操作文件
|
||||
* apk文件这解压的gh-download文件夹中
|
||||
*/
|
||||
object XapkInstaller : IXapkUnzipListener {
|
||||
private const val XAPK_PACKAGE_PATH_TAG = "xapk_package_path"
|
||||
|
||||
// private const val XAPK_DATA_PATH_TAG = "xapk_data_path"
|
||||
const val XAPK_EXTENSION_NAME = "xapk"
|
||||
|
||||
// 通过解压过程存放于 DownloadEntity meta
|
||||
const val XAPK_UNZIP_PERCENT = "unzip_percent"
|
||||
const val XAPK_UNZIP_STATUS = "unzip_status"
|
||||
|
||||
const val XAPK_DATA_EXTENSION_NAME = "obb"
|
||||
const val PACKAGE_EXTENSION_NAME = "apk"
|
||||
|
||||
private var mContext = HaloApp.getInstance().application.applicationContext
|
||||
|
||||
// 是否需要开启特定线程处理
|
||||
private val mXapkUnzipThreadMap = Collections.synchronizedMap(HashMap<String, XapkUnzipThread>())
|
||||
|
||||
// 按并行解压
|
||||
@JvmStatic
|
||||
fun install(context: Context, downloadEntity: DownloadEntity, showUnzipToast: Boolean = false) {
|
||||
this.mContext = context
|
||||
|
||||
val filePath = downloadEntity.path
|
||||
if (XAPK_EXTENSION_NAME == filePath.getExtension()) {
|
||||
unzipXapkFile(downloadEntity)
|
||||
if (showUnzipToast) {
|
||||
Utils.toast(mContext, "解压过程请勿退出光环助手!")
|
||||
}
|
||||
} else {
|
||||
throwExceptionInDebug("如果是Apk包请使用PackageInstaller进行安装")
|
||||
PackageInstaller.install(mContext, downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
private fun unzipXapkFile(downloadEntity: DownloadEntity) {
|
||||
if (mXapkUnzipThreadMap[downloadEntity.path] == null) {
|
||||
val xapkUnzipThread = XapkUnzipThread(downloadEntity, this)
|
||||
xapkUnzipThread.start()
|
||||
mXapkUnzipThreadMap[downloadEntity.path] = xapkUnzipThread
|
||||
} else {
|
||||
debugOnly {
|
||||
Utils.log("unzip", "重复解压,该文件解压已在队列中")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onProgress(downloadEntity: DownloadEntity, unzipPath: String, unzipSize: Long, unzipProgress: Long) {
|
||||
AppExecutor.uiExecutor.execute {
|
||||
val df = DecimalFormat("#.0")
|
||||
var percent = 0.0
|
||||
tryCatchInRelease {
|
||||
percent = df.format((unzipProgress / unzipSize.toFloat()) * 100).toDouble()
|
||||
}
|
||||
downloadEntity.meta[XAPK_UNZIP_PERCENT] = percent.toString()
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.UNZIPPING.name
|
||||
DataChanger.notifyDataChanged(downloadEntity)
|
||||
}
|
||||
|
||||
debugOnly {
|
||||
Utils.log("unzip", "onProgress->" + (unzipProgress / unzipSize.toFloat()))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNext(downloadEntity: DownloadEntity, unzipPath: String) {
|
||||
if (PACKAGE_EXTENSION_NAME == unzipPath.getExtension()) {
|
||||
downloadEntity.meta[XAPK_PACKAGE_PATH_TAG] = unzipPath
|
||||
DownloadManager.getInstance(mContext).updateDownloadEntity(downloadEntity)
|
||||
}
|
||||
|
||||
debugOnly {
|
||||
Utils.log("unzip", "onNext->$unzipPath")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消解压回调
|
||||
*
|
||||
* 取消后的表现与下载完成一致
|
||||
*/
|
||||
override fun onCancel(downloadEntity: DownloadEntity) {
|
||||
mXapkUnzipThreadMap.remove(downloadEntity.path)
|
||||
|
||||
AppExecutor.uiExecutor.execute {
|
||||
downloadEntity.meta[XAPK_UNZIP_PERCENT] = "0.0"
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.CANCEL.name
|
||||
DataChanger.notifyDataChanged(downloadEntity)
|
||||
DownloadManager.getInstance(mContext).updateDownloadEntity(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(downloadEntity: DownloadEntity, exception: Exception) {
|
||||
mXapkUnzipThreadMap.remove(downloadEntity.path)
|
||||
|
||||
AppExecutor.uiExecutor.execute {
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.FAILURE.name
|
||||
DownloadNotificationHelper.addOrUpdateDownloadNotification(downloadEntity)
|
||||
DataChanger.notifyDataChanged(downloadEntity)
|
||||
DownloadManager.getInstance(mContext).updateDownloadEntity(downloadEntity)
|
||||
}
|
||||
|
||||
MtaHelper.onEvent("解压失败"
|
||||
, "安卓版本", Build.VERSION.RELEASE
|
||||
, "IMEI", Util_System_Phone_State.getDeviceId(HaloApp.getInstance().application)
|
||||
, "光环版本", BuildConfig.VERSION_NAME
|
||||
, "厂商", Build.MANUFACTURER
|
||||
, "机型", Build.MODEL
|
||||
, "游戏", downloadEntity.name
|
||||
, "网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().application))
|
||||
|
||||
debugOnly {
|
||||
Utils.log("unzip", "onFailure->$exception")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSuccess(downloadEntity: DownloadEntity) {
|
||||
mXapkUnzipThreadMap.remove(downloadEntity.path)
|
||||
|
||||
AppExecutor.uiExecutor.execute {
|
||||
val pkgPath = checkNotNull(downloadEntity.meta[XAPK_PACKAGE_PATH_TAG])
|
||||
PackageInstaller.install(mContext, pkgPath)
|
||||
|
||||
downloadEntity.meta[XAPK_UNZIP_PERCENT] = "100.0"
|
||||
downloadEntity.meta[XAPK_UNZIP_STATUS] = XapkUnzipStatus.SUCCESS.name
|
||||
DataChanger.notifyDataChanged(downloadEntity)
|
||||
DownloadManager.getInstance(mContext).updateDownloadEntity(downloadEntity)
|
||||
}
|
||||
|
||||
debugOnly {
|
||||
Utils.log("unzip", "onSuccess->${downloadEntity.path}")
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun cancelUnzipTask(downloadEntity: DownloadEntity) {
|
||||
val xapkUnzipThread = mXapkUnzipThreadMap[downloadEntity.path]
|
||||
if (xapkUnzipThread != null) {
|
||||
xapkUnzipThread.canceled = true
|
||||
} else {
|
||||
onCancel(downloadEntity) // 刷新页面
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class XapkUnzipStatus(status: String) {
|
||||
UNZIPPING("unzipping"),
|
||||
SUCCESS("success"),
|
||||
CANCEL("cancel"),
|
||||
FAILURE("failure");
|
||||
}
|
||||
211
app/src/main/java/com/gh/common/xapk/XapkUnzipThread.kt
Normal file
211
app/src/main/java/com/gh/common/xapk/XapkUnzipThread.kt
Normal file
@ -0,0 +1,211 @@
|
||||
package com.gh.common.xapk
|
||||
|
||||
import android.os.Environment
|
||||
import com.gh.common.util.getExtension
|
||||
import com.gh.common.util.throwException
|
||||
import com.gh.common.util.throwExceptionInDebug
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.FileUtils
|
||||
import com.lightgame.utils.Utils
|
||||
import net.lingala.zip4j.progress.ProgressMonitor
|
||||
import java.io.File
|
||||
import java.util.zip.ZipFile
|
||||
|
||||
|
||||
class XapkUnzipThread(private var mDownloadEntity: DownloadEntity,
|
||||
private var mUnzipListener: IXapkUnzipListener) : Thread() {
|
||||
|
||||
private val mDefaultBufferSize = 1024 * 1024
|
||||
|
||||
var canceled = false
|
||||
|
||||
override fun run() {
|
||||
super.run()
|
||||
try {
|
||||
val path = mDownloadEntity.path
|
||||
var unzipSize = 0L
|
||||
try {
|
||||
unzipSize = getUnzipSize(path)
|
||||
} catch (e: Exception) {
|
||||
planB()
|
||||
return
|
||||
}
|
||||
|
||||
val msg = FileUtils.isCanDownload(HaloApp.getInstance().application, unzipSize)
|
||||
if (!msg.isNullOrEmpty()) {
|
||||
// 空间不足应该不用刷新页面,保持不变就好
|
||||
Utils.toast(HaloApp.getInstance().application, "设备存储空间不足,请清理后重试!")
|
||||
mUnzipListener.onCancel(mDownloadEntity)
|
||||
return
|
||||
}
|
||||
var unzipProgress = 0L
|
||||
val absolutePath = Environment.getExternalStorageDirectory().absolutePath
|
||||
val xapkFile = File(path)
|
||||
|
||||
ZipFile(xapkFile).use { zip ->
|
||||
for (zipEntry in zip.entries().asSequence()) {
|
||||
val outputFile = if (zipEntry.name.getExtension() == XapkInstaller.XAPK_DATA_EXTENSION_NAME) {
|
||||
File(absolutePath + File.separator + zipEntry.name)
|
||||
} else if (zipEntry.name.getExtension() == XapkInstaller.PACKAGE_EXTENSION_NAME) {
|
||||
// apk文件名称 = xapk文件名+本身的文件名称
|
||||
val fileName = xapkFile.nameWithoutExtension + "_" + zipEntry.name
|
||||
File(FileUtils.getDownloadPath(HaloApp.getInstance().application, fileName))
|
||||
} else continue // 暂时只需要解压xpk/obb文件
|
||||
|
||||
if (zipEntry.isDirectory) {
|
||||
if (!outputFile.exists()) {
|
||||
throwException("unzip create file path failure", !outputFile.mkdirs())
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (!outputFile.parentFile.exists()) {
|
||||
throwException("unzip create file path failure", !outputFile.parentFile.mkdirs())
|
||||
}
|
||||
|
||||
// 如果存在同名且大小一致,可以认为该文件已经解压缩(在不解压缩的情况下如果如果获取压缩文件的MD5????)
|
||||
if (!outputFile.exists()) {
|
||||
throwException("unzip create file failure", !outputFile.createNewFile())
|
||||
} else if (outputFile.length() != zipEntry.size) {
|
||||
throwException("unzip delete existing file failure", !outputFile.delete())
|
||||
throwException("unzip create file failure", !outputFile.createNewFile())
|
||||
} else {
|
||||
unzipProgress += zipEntry.size
|
||||
mUnzipListener.onProgress(mDownloadEntity, outputFile.path, unzipSize, unzipProgress)
|
||||
mUnzipListener.onNext(mDownloadEntity, outputFile.path)
|
||||
continue
|
||||
}
|
||||
|
||||
// unzip
|
||||
zip.getInputStream(zipEntry).use { input ->
|
||||
outputFile.outputStream().use { output ->
|
||||
val buffer = ByteArray(mDefaultBufferSize)
|
||||
var bytes = input.read(buffer)
|
||||
while (bytes >= 0) {
|
||||
output.write(buffer, 0, bytes)
|
||||
unzipProgress += bytes
|
||||
bytes = input.read(buffer)
|
||||
if (canceled) {
|
||||
mUnzipListener.onCancel(mDownloadEntity)
|
||||
return
|
||||
} else {
|
||||
mUnzipListener.onProgress(mDownloadEntity, outputFile.path, unzipSize, unzipProgress)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mUnzipListener.onNext(mDownloadEntity, outputFile.path)
|
||||
}
|
||||
}
|
||||
mUnzipListener.onSuccess(mDownloadEntity)
|
||||
} catch (e: Exception) {
|
||||
if (BuildConfig.DEBUG) throw e
|
||||
mUnzipListener.onFailure(mDownloadEntity, e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 部分未知情况(有可能是项目配置问题,有可能时Zip包破损)原生的ZipFile无法打开压缩包,则启动以下备用方案
|
||||
* 具体复现机型:小米 9(Android 9)
|
||||
* 具体复现的压缩包:太空竞速2 具体可以咨询陈思雨
|
||||
*
|
||||
* 实现方式请参考:https://github.com/srikanth-lingala/zip4j
|
||||
* 注意使用该库的ZipInputStream依然无法解压,提示头文件丢失
|
||||
*
|
||||
* 后续如果有需要可以直接使用该方法进行解压
|
||||
*/
|
||||
private fun planB() {
|
||||
val zipPath = mDownloadEntity.path
|
||||
|
||||
val absolutePath = Environment.getExternalStorageDirectory().absolutePath
|
||||
|
||||
val zipFile = net.lingala.zip4j.ZipFile(zipPath)
|
||||
val progressMonitor = zipFile.progressMonitor
|
||||
zipFile.isRunInThread = true
|
||||
|
||||
val fileHeaders = zipFile.fileHeaders
|
||||
var unzipSize = 0L
|
||||
for (fileHeader in fileHeaders) {
|
||||
unzipSize += fileHeader.uncompressedSize;
|
||||
}
|
||||
|
||||
var unzipProgress = 0L
|
||||
var completedSize = 0L
|
||||
|
||||
for (fileHeader in fileHeaders) {
|
||||
if (canceled) {
|
||||
mUnzipListener.onCancel(mDownloadEntity)
|
||||
return
|
||||
}
|
||||
|
||||
// 暂时只需要解压xpk/obb文件
|
||||
val extension = fileHeader.fileName.getExtension()
|
||||
if (extension != XapkInstaller.XAPK_DATA_EXTENSION_NAME && extension != XapkInstaller.PACKAGE_EXTENSION_NAME) continue
|
||||
|
||||
|
||||
var unzipPath = ""
|
||||
if (extension == XapkInstaller.XAPK_DATA_EXTENSION_NAME) {
|
||||
unzipPath = absolutePath + File.separator + fileHeader.fileName
|
||||
|
||||
if (hasUnzipFile(unzipPath, fileHeader.uncompressedSize)) {
|
||||
mUnzipListener.onNext(mDownloadEntity, unzipPath)
|
||||
continue
|
||||
}
|
||||
|
||||
zipFile.extractFile(fileHeader.fileName, absolutePath)
|
||||
}
|
||||
|
||||
if (extension == XapkInstaller.PACKAGE_EXTENSION_NAME) {
|
||||
val downloadDir = FileUtils.getDownloadDir(HaloApp.getInstance().application)
|
||||
val unzipFileName = File(zipPath).nameWithoutExtension + "_" + fileHeader.fileName
|
||||
unzipPath = downloadDir + File.separator + unzipFileName
|
||||
|
||||
if (hasUnzipFile(unzipPath, fileHeader.uncompressedSize)) {
|
||||
mUnzipListener.onNext(mDownloadEntity, unzipPath)
|
||||
continue
|
||||
}
|
||||
|
||||
zipFile.extractFile(fileHeader.fileName, downloadDir, unzipFileName)
|
||||
}
|
||||
|
||||
throwExceptionInDebug("check unzipPath", unzipPath.isEmpty())
|
||||
|
||||
// 回调太频繁了,变态吗? 4K回调一次,还不能改,FUCK
|
||||
var filterCounter = 0
|
||||
val filterInterval = 1024 * 10
|
||||
while (progressMonitor.state != ProgressMonitor.State.READY) {
|
||||
filterCounter++
|
||||
if (filterCounter % filterInterval == 0) {
|
||||
unzipProgress = completedSize + progressMonitor.workCompleted
|
||||
mUnzipListener.onProgress(mDownloadEntity, unzipPath, unzipSize, unzipProgress)
|
||||
|
||||
if (canceled) {
|
||||
progressMonitor.isCancelAllTasks = true
|
||||
mUnzipListener.onCancel(mDownloadEntity)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
completedSize += fileHeader.uncompressedSize
|
||||
mUnzipListener.onNext(mDownloadEntity, unzipPath)
|
||||
}
|
||||
|
||||
mUnzipListener.onSuccess(mDownloadEntity)
|
||||
}
|
||||
|
||||
private fun hasUnzipFile(unzipPath: String, uncompressedSize: Long): Boolean {
|
||||
val unzipFile = File(unzipPath)
|
||||
if (unzipFile.exists() || unzipFile.length() == uncompressedSize) return true
|
||||
return false
|
||||
}
|
||||
|
||||
private fun getUnzipSize(path: String): Long {
|
||||
var totalSize = 0L
|
||||
for (entry in ZipFile(File(path)).entries()) {
|
||||
totalSize += entry.size
|
||||
}
|
||||
return totalSize
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,21 @@
|
||||
package com.gh.download
|
||||
|
||||
import android.content.pm.PackageManager
|
||||
import com.gh.common.exposure.meta.MetaUtil.getMeta
|
||||
import com.gh.common.loghub.LoghubUtils
|
||||
import com.gh.common.util.DeviceUtils
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import com.lightgame.download.DownloadStatus
|
||||
import com.lightgame.utils.Utils
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
|
||||
object DownloadDataHelper {
|
||||
private const val DOWNLOAD_SPEED_TIME = "download_speed_time"
|
||||
private const val DOWNLOAD_SPEED_SIZE = "download_speed_size"
|
||||
|
||||
const val DOWNLOAD_RESUME_WAY = "download_resume_way"
|
||||
const val DOWNLOAD_RESUME_MANUAL = "manual"
|
||||
const val DOWNLOAD_RESUME_AUTO = "auto"
|
||||
@ -14,9 +24,13 @@ object DownloadDataHelper {
|
||||
const val DOWNLOAD_CANCEL_MANUAL = "manual"
|
||||
const val DOWNLOAD_CANCEL_AUTO = "auto"
|
||||
|
||||
const val DOWNLOAD_FIRST_START = "download_first_start"
|
||||
|
||||
private val mDownloadSpeedMap = HashMap<String, MutableList<Long>>()
|
||||
|
||||
@JvmStatic
|
||||
fun getDownloadStatusAlias(downloadEntity: DownloadEntity): String {
|
||||
val status = downloadEntity.status
|
||||
fun getDownloadStatusAlias(downloadEntity: DownloadEntity, downloadStatus: DownloadStatus? = null): String {
|
||||
val status = downloadStatus ?: downloadEntity.status
|
||||
return if (status == DownloadStatus.add) {
|
||||
"开始下载"
|
||||
} else if (status == DownloadStatus.pause) {
|
||||
@ -53,4 +67,179 @@ object DownloadDataHelper {
|
||||
"未知状态"
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun uploadDownloadEvent(downloadEntity: DownloadEntity) {
|
||||
if (downloadEntity.status != DownloadStatus.downloading) {
|
||||
uploadDownloadStatusEvent(downloadEntity)
|
||||
}
|
||||
|
||||
if (downloadEntity.status == DownloadStatus.downloading) {
|
||||
val startupTime = downloadEntity.meta[DownloadEntity.DOWNLOAD_STARTUP_TIME_KEY]
|
||||
if (startupTime != null) {
|
||||
uploadDownloadStartupTimeEvent(downloadEntity, startupTime.toInt())
|
||||
downloadEntity.meta.remove(DownloadEntity.DOWNLOAD_STARTUP_TIME_KEY)
|
||||
DownloadManager.getInstance(HaloApp.getInstance().application).updateDownloadEntity(downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
if (downloadEntity.status == DownloadStatus.downloading || downloadEntity.status == DownloadStatus.done) {
|
||||
val time = downloadEntity.meta[DOWNLOAD_SPEED_TIME]
|
||||
val size = downloadEntity.meta[DOWNLOAD_SPEED_SIZE]
|
||||
if (downloadEntity.speed == 0L || time == null || size == null) {
|
||||
downloadEntity.meta[DOWNLOAD_SPEED_TIME] = System.currentTimeMillis().toString()
|
||||
downloadEntity.meta[DOWNLOAD_SPEED_SIZE] = downloadEntity.progress.toString()
|
||||
DownloadManager.getInstance(HaloApp.getInstance().application).updateDownloadEntity(downloadEntity)
|
||||
} else {
|
||||
val offset = System.currentTimeMillis() - time.toLong()
|
||||
if (offset > 5000) {
|
||||
//记录并重置
|
||||
val downloadedSize = downloadEntity.progress - size.toLong()
|
||||
val averageSpeed = downloadedSize / offset
|
||||
val speedList = mDownloadSpeedMap[downloadEntity.url]
|
||||
if (speedList == null) {
|
||||
mDownloadSpeedMap[downloadEntity.url] = arrayListOf(averageSpeed)
|
||||
} else {
|
||||
speedList.add(averageSpeed)
|
||||
if (speedList.size >= 6 || downloadEntity.status == DownloadStatus.done) {
|
||||
uploadDownloadAverageSpeed(downloadEntity, speedList)
|
||||
if (downloadEntity.status == DownloadStatus.done) {
|
||||
mDownloadSpeedMap.remove(downloadEntity.url)
|
||||
} else {
|
||||
speedList.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
downloadEntity.meta[DOWNLOAD_SPEED_TIME] = System.currentTimeMillis().toString()
|
||||
downloadEntity.meta[DOWNLOAD_SPEED_SIZE] = downloadEntity.progress.toString()
|
||||
DownloadManager.getInstance(HaloApp.getInstance().application).updateDownloadEntity(downloadEntity)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun uploadDownloadStartupTimeEvent(downloadEntity: DownloadEntity, startupTime: Int) {
|
||||
val jsonObject = JSONObject()
|
||||
|
||||
try {
|
||||
jsonObject.put("event", "下载线程启动")
|
||||
val startupStatus = downloadEntity.meta[DownloadEntity.DOWNLOAD_STARTUP_STATUS_KEY]
|
||||
if (startupStatus != null) {
|
||||
jsonObject.put("msg", getDownloadStatusAlias(downloadEntity, DownloadStatus.valueOf(startupStatus)))
|
||||
}
|
||||
|
||||
jsonObject.put("meta", getMetaJson())
|
||||
jsonObject.put("timestamp", System.currentTimeMillis() / 1000)
|
||||
|
||||
// payload
|
||||
val payloadObject = JSONObject()
|
||||
payloadObject.put("game_id", downloadEntity.gameId)
|
||||
payloadObject.put("gameName", downloadEntity.name)
|
||||
payloadObject.put("platform", downloadEntity.platform)
|
||||
payloadObject.put("package", downloadEntity.packageName)
|
||||
payloadObject.put("filename", downloadEntity.path.substring(downloadEntity.path.lastIndexOf("/") + 1))
|
||||
payloadObject.put("launch_ms", startupTime)
|
||||
jsonObject.put("payload", payloadObject)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log("LogUtils->$jsonObject")
|
||||
}
|
||||
LoghubUtils.log(jsonObject, "download_debug", false)
|
||||
}
|
||||
|
||||
private fun uploadDownloadStatusEvent(downloadEntity: DownloadEntity) {
|
||||
val jsonObject = JSONObject()
|
||||
|
||||
try {
|
||||
jsonObject.put("event", getDownloadStatusAlias(downloadEntity))
|
||||
jsonObject.put("msg", downloadEntity.error)
|
||||
jsonObject.put("status", downloadEntity.status.status)
|
||||
|
||||
jsonObject.put("meta", getMetaJson())
|
||||
jsonObject.put("timestamp", System.currentTimeMillis() / 1000)
|
||||
|
||||
// payload
|
||||
val payloadObject = JSONObject()
|
||||
payloadObject.put("game_id", downloadEntity.gameId)
|
||||
payloadObject.put("gameName", downloadEntity.name)
|
||||
payloadObject.put("platform", downloadEntity.platform)
|
||||
payloadObject.put("package", downloadEntity.packageName)
|
||||
payloadObject.put("filename", downloadEntity.path.substring(downloadEntity.path.lastIndexOf("/") + 1))
|
||||
payloadObject.put("total_size", downloadEntity.size / 1024 / 1024)
|
||||
payloadObject.put("completed_size", downloadEntity.progress / 1024 / 1024)
|
||||
if (downloadEntity.status == DownloadStatus.resume) {
|
||||
if (downloadEntity.meta[DOWNLOAD_FIRST_START] == "YES") {
|
||||
payloadObject.put("is_first_start", true)
|
||||
} else {
|
||||
payloadObject.put("is_first_start", false)
|
||||
}
|
||||
}
|
||||
|
||||
if (downloadEntity.status == DownloadStatus.resume || downloadEntity.status == DownloadStatus.add) {
|
||||
downloadEntity.meta[DOWNLOAD_FIRST_START] = "NO"
|
||||
DownloadManager.getInstance(HaloApp.getInstance().application).updateDownloadEntity(downloadEntity)
|
||||
}
|
||||
jsonObject.put("payload", payloadObject)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log("LogUtils->$jsonObject")
|
||||
}
|
||||
LoghubUtils.log(jsonObject, "download_debug", false)
|
||||
}
|
||||
|
||||
|
||||
private fun uploadDownloadAverageSpeed(downloadEntity: DownloadEntity, averageSpeedList: List<Long>) {
|
||||
val jsonObject = JSONObject()
|
||||
|
||||
try {
|
||||
jsonObject.put("event", "下载进度")
|
||||
jsonObject.put("msg", "")
|
||||
|
||||
jsonObject.put("meta", getMetaJson())
|
||||
jsonObject.put("timestamp", System.currentTimeMillis() / 1000)
|
||||
|
||||
// payload
|
||||
val payloadObject = JSONObject()
|
||||
payloadObject.put("game_id", downloadEntity.gameId)
|
||||
payloadObject.put("gameName", downloadEntity.name)
|
||||
payloadObject.put("platform", downloadEntity.platform)
|
||||
payloadObject.put("package", downloadEntity.packageName)
|
||||
payloadObject.put("filename", downloadEntity.path.substring(downloadEntity.path.lastIndexOf("/") + 1))
|
||||
payloadObject.put("speed_progress", JSONArray(averageSpeedList))
|
||||
payloadObject.put("is_finished", downloadEntity.status == DownloadStatus.done)
|
||||
jsonObject.put("payload", payloadObject)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log("LogUtils->$jsonObject")
|
||||
}
|
||||
LoghubUtils.log(jsonObject, "download_debug", false)
|
||||
}
|
||||
|
||||
private fun getMetaJson(): JSONObject {
|
||||
val context = HaloApp.getInstance().application
|
||||
val meta = getMeta()
|
||||
// meta
|
||||
val metaObject = JSONObject()
|
||||
metaObject.put("android_id", meta.android_id)
|
||||
metaObject.put("android_sdk", meta.android_sdk)
|
||||
metaObject.put("android_version", meta.android_version)
|
||||
metaObject.put("appVersion", meta.appVersion)
|
||||
metaObject.put("channel", meta.channel)
|
||||
metaObject.put("gid", meta.gid)
|
||||
metaObject.put("imei", meta.imei)
|
||||
metaObject.put("mac", meta.mac)
|
||||
metaObject.put("manufacturer", meta.manufacturer)
|
||||
metaObject.put("model", meta.model)
|
||||
metaObject.put("network", DeviceUtils.getNetwork(context))
|
||||
metaObject.put("os", meta.os)
|
||||
metaObject.put("MNC", DeviceUtils.getTelephonySubscriberId(context) ?: "")
|
||||
metaObject.put("userId", meta.userId)
|
||||
return metaObject
|
||||
}
|
||||
}
|
||||
@ -11,10 +11,9 @@ import android.text.TextUtils;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.collection.ArrayMap;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.ProcessLifecycleOwner;
|
||||
|
||||
import com.gh.common.AppExecutor;
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.gh.common.exposure.ExposureEvent;
|
||||
import com.gh.common.exposure.ExposureUtils;
|
||||
import com.gh.common.history.HistoryHelper;
|
||||
@ -22,10 +21,11 @@ import com.gh.common.util.AppDebugConfig;
|
||||
import com.gh.common.util.DataCollectionUtils;
|
||||
import com.gh.common.util.DeviceUtils;
|
||||
import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.ExtensionsKt;
|
||||
import com.gh.common.util.GdtHelper;
|
||||
import com.gh.common.util.HomePluggableHelper;
|
||||
import com.gh.common.util.MD5Utils;
|
||||
import com.gh.common.util.NetworkUtils;
|
||||
import com.gh.common.util.PackageInstaller;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.SPUtils;
|
||||
import com.gh.gamecenter.entity.ApkEntity;
|
||||
@ -243,8 +243,7 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
DownloadEntity downloadEntity = new DownloadEntity();
|
||||
downloadEntity.setUrl(apkEntity.getUrl());
|
||||
downloadEntity.setName(gameEntity.getName());
|
||||
downloadEntity.setPath(FileUtils.getDownloadPath(context,
|
||||
MD5Utils.getContentMD5(gameEntity.getName() + "_" + System.currentTimeMillis()) + ".apk"));
|
||||
downloadEntity.setPath(PackageInstaller.getDownloadPath(gameEntity.getName(), apkEntity.getFormat()));
|
||||
downloadEntity.setETag(apkEntity.getEtag());
|
||||
downloadEntity.setIcon(gameEntity.getIcon());
|
||||
downloadEntity.setPlatform(apkEntity.getPlatform());
|
||||
@ -253,6 +252,8 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
downloadEntity.setEntrance(entrance);
|
||||
downloadEntity.setLocation(location);
|
||||
downloadEntity.setVersionName(apkEntity.getVersion());
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.RAW_GAME_ICON, gameEntity.getRawIcon());
|
||||
ExtensionsKt.addMetaExtra(downloadEntity, Constants.GAME_ICON_SUBSCRIPT, gameEntity.getIconSubscript());
|
||||
int installed = 0;
|
||||
for (ApkEntity apk : gameEntity.getApk()) {
|
||||
if (PackagesManager.INSTANCE.isInstalled(apk.getPackageName())) {
|
||||
@ -645,13 +646,11 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
DataChanger.INSTANCE.deleteObserver(dataWatcher);
|
||||
}
|
||||
|
||||
private void startDownloadService() {
|
||||
public void startDownloadService() {
|
||||
Intent serviceIntent = new Intent(mContext, DownloadService.class);
|
||||
// 当满足系统版本大于 8.0 并且进程处于 CREATED 状态 (ON_STOP后的状态) 的时候才以前台服务开启
|
||||
// "not allowed to start service, app is in background" 的错误概率比 "startForegroundService() did not then call Service.startForeground() " 低
|
||||
// 所以还是老老实实地以 startService 为主吧
|
||||
// 当满足系统版本大于 8.0 并且应用在后台运行时以前台服务开启
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
|
||||
&& ProcessLifecycleOwner.get().getLifecycle().getCurrentState() == Lifecycle.State.CREATED) {
|
||||
&& !PackageUtils.isAppOnForeground(mContext)) {
|
||||
serviceIntent.putExtra(DownloadService.KEY_SERVICE_ACTION, DownloadService.START_FOREGROUND);
|
||||
mContext.startForegroundService(serviceIntent);
|
||||
} else {
|
||||
@ -671,10 +670,16 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
downloadEntity.getMeta().put(DownloadEntity.NETWORK_STATUS_KEY, network);
|
||||
}
|
||||
|
||||
if (status == DownloadStatus.add || status == DownloadStatus.subscribe) {
|
||||
if (downloadEntity.getMeta().get(DownloadDataHelper.DOWNLOAD_FIRST_START) == null) {
|
||||
downloadEntity.getMeta().put(DownloadDataHelper.DOWNLOAD_FIRST_START, "YES");
|
||||
}
|
||||
}
|
||||
|
||||
Intent serviceIntent = getIntent(downloadEntity, status);
|
||||
// 当满足系统版本大于 8.0 、应用在后台运行时以前台服务开启
|
||||
// 当满足系统版本大于 8.0 并且应用在后台运行时以前台服务开启
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
|
||||
&& ProcessLifecycleOwner.get().getLifecycle().getCurrentState() == Lifecycle.State.CREATED) {
|
||||
&& !PackageUtils.isAppOnForeground(mContext)) {
|
||||
serviceIntent.putExtra(DownloadService.KEY_SERVICE_ACTION, DownloadService.START_FOREGROUND);
|
||||
mContext.startForegroundService(serviceIntent);
|
||||
} else {
|
||||
|
||||
@ -2,6 +2,7 @@ package com.gh.download
|
||||
|
||||
import androidx.work.PeriodicWorkRequest
|
||||
import androidx.work.WorkManager
|
||||
import com.gh.common.util.tryWithDefaultCatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
object DownloadWorkManager {
|
||||
@ -22,12 +23,13 @@ object DownloadWorkManager {
|
||||
.addTag(TAG_DOWNLOAD)
|
||||
.build()
|
||||
|
||||
WorkManager.getInstance().enqueue(workerRequest)
|
||||
// TODO 某些特殊场景下会出现 WorkManagerImpl.getInstance() 为空的情况,下版本更新 WorkManager
|
||||
tryWithDefaultCatch { WorkManager.getInstance().enqueue(workerRequest) }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun cancelWorker() {
|
||||
WorkManager.getInstance().cancelAllWorkByTag(TAG_DOWNLOAD)
|
||||
tryWithDefaultCatch { WorkManager.getInstance().cancelAllWorkByTag(TAG_DOWNLOAD) }
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
package com.gh.download.cache;
|
||||
|
||||
public class CacheInfo {
|
||||
public static final long TOTAL_ERROR = -1;//获取进度失败
|
||||
private String url;
|
||||
private long total;
|
||||
private long progress;
|
||||
private String fileName;
|
||||
|
||||
public CacheInfo(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public long getTotal() {
|
||||
return total;
|
||||
}
|
||||
|
||||
public void setTotal(long total) {
|
||||
this.total = total;
|
||||
}
|
||||
|
||||
public long getProgress() {
|
||||
return progress;
|
||||
}
|
||||
|
||||
public void setProgress(long progress) {
|
||||
this.progress = progress;
|
||||
}
|
||||
}
|
||||
@ -1,241 +0,0 @@
|
||||
package com.gh.download.cache;
|
||||
|
||||
import com.danikula.videocache.file.FileNameGenerator;
|
||||
import com.danikula.videocache.file.Md5FileNameGenerator;
|
||||
import com.gh.common.AppExecutor;
|
||||
import com.halo.assistant.HaloApp;
|
||||
import com.shuyu.gsyvideoplayer.utils.StorageUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.ObservableEmitter;
|
||||
import io.reactivex.ObservableOnSubscribe;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Callback;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class CacheManager {
|
||||
private static final AtomicReference<CacheManager> INSTANCE = new AtomicReference<>();
|
||||
private volatile ConcurrentHashMap<String, Call> downCalls;
|
||||
private OkHttpClient mClient;
|
||||
private File cacheDirectory = StorageUtils.getIndividualCacheDirectory(HaloApp.getInstance().getApplication());
|
||||
private FileNameGenerator generator = new Md5FileNameGenerator();
|
||||
private final String TEMP_POSTFIX = ".download";
|
||||
// private final int preLength = 5 * 1024 * 1024;//预加载大小
|
||||
|
||||
|
||||
public static CacheManager getInstance() {
|
||||
for (; ; ) {
|
||||
CacheManager current = INSTANCE.get();
|
||||
if (current != null) {
|
||||
return current;
|
||||
}
|
||||
current = new CacheManager();
|
||||
if (INSTANCE.compareAndSet(null, current)) {
|
||||
return current;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private CacheManager() {
|
||||
downCalls = new ConcurrentHashMap<>();
|
||||
mClient = new OkHttpClient.Builder().build();
|
||||
}
|
||||
|
||||
private synchronized ConcurrentHashMap<String, Call> getDownCalls() {
|
||||
return downCalls;
|
||||
}
|
||||
|
||||
public void download(String url, CacheObserver cacheObserver) {
|
||||
//当前url已下载完成则不再下载
|
||||
for (File file : getAllFile()) {
|
||||
if (file.getName().equals(generator.generate(url))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
Observable.just(url)
|
||||
.filter(s -> !getDownCalls().containsKey(s))//call的map已经有了,就证明正在下载,则这次不下载
|
||||
.flatMap(s -> Observable.just(createDownInfo(s)))
|
||||
.map(this::getRealFileName)
|
||||
.flatMap(cacheInfo -> Observable.create(new DownloadSubscribe(cacheInfo)))
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(cacheObserver);
|
||||
|
||||
}
|
||||
|
||||
public void cancel(String url) {
|
||||
Call call = getDownCalls().get(url);
|
||||
if (call != null) {
|
||||
call.cancel();
|
||||
}
|
||||
getDownCalls().remove(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建DownInfo
|
||||
*
|
||||
* @param url 请求网址
|
||||
* @return DownInfo
|
||||
*/
|
||||
private CacheInfo createDownInfo(String url) {
|
||||
CacheInfo cacheInfo = new CacheInfo(url);
|
||||
long contentLength = getContentLength(url);//获得文件大小
|
||||
cacheInfo.setTotal(contentLength);
|
||||
String fileName = generator.generate(url) + TEMP_POSTFIX;
|
||||
cacheInfo.setFileName(fileName);
|
||||
return cacheInfo;
|
||||
}
|
||||
|
||||
private CacheInfo getRealFileName(CacheInfo cacheInfo) {
|
||||
String fileName = cacheInfo.getFileName();
|
||||
long downloadLength = 0;
|
||||
if (!cacheDirectory.exists()) {
|
||||
cacheDirectory.mkdir();
|
||||
}
|
||||
File file = new File(cacheDirectory, fileName);
|
||||
if (file.exists()) {
|
||||
//找到了文件,代表已经下载过,则获取其长度
|
||||
downloadLength = file.length();
|
||||
}
|
||||
//设置改变过的文件名/大小
|
||||
cacheInfo.setProgress(downloadLength);
|
||||
cacheInfo.setFileName(file.getName());
|
||||
return cacheInfo;
|
||||
}
|
||||
|
||||
|
||||
private class DownloadSubscribe implements ObservableOnSubscribe<CacheInfo> {
|
||||
private CacheInfo cacheInfo;
|
||||
|
||||
public DownloadSubscribe(CacheInfo cacheInfo) {
|
||||
this.cacheInfo = cacheInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe(ObservableEmitter<CacheInfo> e) throws Exception {
|
||||
String url = cacheInfo.getUrl();
|
||||
final long[] downloadLength = {cacheInfo.getProgress()};//已经下载好的长度
|
||||
long contentLength = cacheInfo.getTotal();//文件的总长度
|
||||
// if (downloadLength[0] >= preLength) {
|
||||
if (downloadLength[0] >= contentLength) {
|
||||
e.onComplete();
|
||||
return;
|
||||
}
|
||||
e.onNext(cacheInfo);
|
||||
Request request = new Request.Builder()
|
||||
// .addHeader("RANGE", "bytes=" + downloadLength[0] + "-" + (contentLength > preLength ? preLength : contentLength))
|
||||
.addHeader("RANGE", "bytes=" + downloadLength[0] + "-" + contentLength)
|
||||
.url(url)
|
||||
.build();
|
||||
Call call = mClient.newCall(request);
|
||||
getDownCalls().put(url, call);
|
||||
call.enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) throws IOException {
|
||||
File file = new File(cacheDirectory, cacheInfo.getFileName());
|
||||
InputStream is = null;
|
||||
FileOutputStream fileOutputStream = null;
|
||||
try {
|
||||
is = response.body().byteStream();
|
||||
fileOutputStream = new FileOutputStream(file, true);
|
||||
byte[] buffer = new byte[2048];
|
||||
int len;
|
||||
while (downCalls.get(url) != null && !call.isCanceled() && (len = is.read(buffer)) != -1) {
|
||||
fileOutputStream.write(buffer, 0, len);
|
||||
downloadLength[0] += len;
|
||||
cacheInfo.setProgress(downloadLength[0]);
|
||||
e.onNext(cacheInfo);
|
||||
}
|
||||
fileOutputStream.flush();
|
||||
getDownCalls().remove(url);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
} finally {
|
||||
if (is != null) {
|
||||
is.close();
|
||||
}
|
||||
if (fileOutputStream != null) {
|
||||
fileOutputStream.close();
|
||||
}
|
||||
}
|
||||
if (file.length() == contentLength) {
|
||||
file.renameTo(new File(file.getPath().substring(0, file.getPath().lastIndexOf(TEMP_POSTFIX))));
|
||||
}
|
||||
e.onComplete();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下载长度
|
||||
*
|
||||
* @param downloadUrl
|
||||
* @return
|
||||
*/
|
||||
public long getContentLength(String downloadUrl) {
|
||||
long contentLength = CacheInfo.TOTAL_ERROR;
|
||||
Request request = new Request.Builder()
|
||||
.url(downloadUrl)
|
||||
.build();
|
||||
Response response = null;
|
||||
try {
|
||||
response = mClient.newCall(request).execute();
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
long length = response.body().contentLength();
|
||||
contentLength = length == 0 ? CacheInfo.TOTAL_ERROR : length;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (response != null) {
|
||||
response.close();
|
||||
}
|
||||
}
|
||||
return contentLength;
|
||||
}
|
||||
|
||||
public void removeAllCall() {
|
||||
AppExecutor.getIoExecutor().execute(() -> {
|
||||
for (Map.Entry<String, Call> entry : getDownCalls().entrySet()) {
|
||||
entry.getValue().cancel();
|
||||
}
|
||||
AppExecutor.getUiExecutor().execute(() -> getDownCalls().clear());
|
||||
});
|
||||
}
|
||||
|
||||
private List<File> getAllFile() {
|
||||
try {
|
||||
if (cacheDirectory.exists() && cacheDirectory.isDirectory()) {
|
||||
File[] files = cacheDirectory.listFiles();
|
||||
return Arrays.asList(files);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
package com.gh.download.cache;
|
||||
|
||||
import com.gh.gamecenter.BuildConfig;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import io.reactivex.Observer;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
|
||||
public abstract class CacheObserver implements Observer<CacheInfo> {
|
||||
protected Disposable d;//可以用于取消注册的监听者
|
||||
protected CacheInfo cacheInfo;
|
||||
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
this.d = d;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(CacheInfo cacheInfo) {
|
||||
this.cacheInfo = cacheInfo;
|
||||
if (BuildConfig.DEBUG) {
|
||||
Utils.log(cacheInfo.getProgress() + "-" + cacheInfo.getTotal());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
|
||||
}
|
||||
}
|
||||
@ -91,7 +91,7 @@ object ExoCacheManager {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getContentLength(downloadUrl: String): Long {
|
||||
fun getContentLength(downloadUrl: String): Long {
|
||||
var contentLength = -1L
|
||||
val request = Request.Builder()
|
||||
.url(downloadUrl)
|
||||
|
||||
@ -211,10 +211,10 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
|
||||
} else {
|
||||
if (PackageUtils.isCanPluggable(apkEntity)) {
|
||||
DialogUtils.showPluginDialog(it.context) {
|
||||
it.context.startActivity(PackageUtils.getUninstallIntent(it.context, downloadEntity.path))
|
||||
PackageInstaller.uninstall(it.context, downloadEntity.path)
|
||||
}
|
||||
} else {
|
||||
PackageUtils.launchSetup(it.context, downloadEntity)
|
||||
PackageInstaller.install(it.context, downloadEntity)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -11,9 +11,10 @@ import com.gh.gamecenter.game.GameFragment
|
||||
class BlockActivity : NormalActivity() {
|
||||
|
||||
companion object {
|
||||
fun getIntent(context: Context, blockData: SubjectRecommendEntity): Intent {
|
||||
fun getIntent(context: Context, blockData: SubjectRecommendEntity, entrance: String): Intent {
|
||||
val args = Bundle()
|
||||
args.putParcelable(EntranceUtils.KEY_BLOCK_DATA, blockData)
|
||||
args.putString(EntranceUtils.KEY_ENTRANCE, entrance)
|
||||
return getTargetIntent(context, BlockActivity::class.java, GameFragment::class.java, args)
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,12 +72,14 @@ public class CommentDetailActivity extends NormalActivity {
|
||||
}
|
||||
|
||||
public static Intent getVideoCommentIntent(Context context,
|
||||
String commentId,
|
||||
String videoId,
|
||||
LinkEntity linkEntity) {
|
||||
String commentId,
|
||||
String videoId,
|
||||
boolean isVideoAuthor,
|
||||
LinkEntity linkEntity) {
|
||||
Bundle args = new Bundle();
|
||||
args.putString(EntranceUtils.KEY_COMMENTID, commentId);
|
||||
args.putString(CommentActivity.VIDEO_ID, videoId);
|
||||
args.putBoolean(CommentActivity.IS_VIDEO_AUTHOR, isVideoAuthor);
|
||||
args.putParcelable(EntranceUtils.KEY_LINK, linkEntity);
|
||||
return getTargetIntent(context, CommentDetailActivity.class, NewCommentConversationFragment.class, args);
|
||||
}
|
||||
|
||||
@ -3,20 +3,22 @@ package com.gh.gamecenter;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.gh.base.ToolBarActivity;
|
||||
import com.gh.common.util.BitmapUtils;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.common.view.CropImageCustom;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.lang.ref.SoftReference;
|
||||
|
||||
import butterknife.BindView;
|
||||
@ -25,17 +27,22 @@ public class CropImageActivity extends ToolBarActivity {
|
||||
|
||||
@BindView(R.id.cropimage_custom)
|
||||
public CropImageCustom mCropImageCustom;
|
||||
@BindView(R.id.status_bar)
|
||||
public View mStatusBar;
|
||||
|
||||
public static final String RESULT_CLIP_PATH = "result_clip_path";
|
||||
|
||||
private SoftReference<Bitmap> reference;
|
||||
|
||||
protected boolean mBlackTheme = false;
|
||||
|
||||
@NonNull
|
||||
public static Intent getIntent(Context context, String picturePath, float cropRatio, String entrance) {
|
||||
Intent intent = new Intent(context, CropImageActivity.class);
|
||||
intent.putExtra(EntranceUtils.KEY_PATH, picturePath);
|
||||
intent.putExtra(EntranceUtils.KEY_ENTRANCE, entrance);
|
||||
intent.putExtra(EntranceUtils.KEY_IMAGE_CROP_RATIO, cropRatio);
|
||||
intent.putExtra(EntranceUtils.KEY_BLACK_THEME, true);
|
||||
return intent;
|
||||
}
|
||||
|
||||
@ -46,28 +53,35 @@ public class CropImageActivity extends ToolBarActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
mBlackTheme = getIntent().getBooleanExtra(EntranceUtils.KEY_BLACK_THEME, false);
|
||||
super.onCreate(savedInstanceState);
|
||||
mTitleTv.setTextColor(mBlackTheme ? Color.WHITE : Color.BLACK);
|
||||
mToolbar.setBackgroundColor(getResources().getColor(mBlackTheme ? R.color.text_28282E : R.color.white));
|
||||
mStatusBar.setBackgroundColor(getResources().getColor(mBlackTheme ? R.color.text_28282E : R.color.white));
|
||||
|
||||
setNavigationTitle(getString(R.string.title_crop_image));
|
||||
setToolbarMenu(R.menu.menu_positive);
|
||||
MenuItem menuItem = getMenuItem(R.id.layout_menu_positive);
|
||||
TextView menuButton = menuItem.getActionView().findViewById(R.id.menu_answer_post);
|
||||
menuButton.setTextColor(getResources().getColor(mBlackTheme ? R.color.theme_font : R.color.title));
|
||||
|
||||
float ratio = getIntent().getFloatExtra(EntranceUtils.KEY_IMAGE_CROP_RATIO, 1F);
|
||||
mCropImageCustom.setCropRatio(ratio);
|
||||
|
||||
DisplayUtils.transparentStatusBar(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int provideNavigationIcon() {
|
||||
return mBlackTheme ? R.drawable.ic_toolbar_back_white : R.drawable.ic_bar_back;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
if (item.getItemId() == R.id.layout_menu_positive) {
|
||||
Intent data = new Intent();
|
||||
Bitmap clip = mCropImageCustom.clip();
|
||||
String clipPath = getCacheDir().getAbsolutePath() + File.separator + System.currentTimeMillis() + ".jpg";
|
||||
try {
|
||||
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(clipPath)));
|
||||
clip.compress(Bitmap.CompressFormat.WEBP, 100, bos);
|
||||
bos.flush();
|
||||
bos.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
mCropImageCustom.savePicture(clipPath);
|
||||
|
||||
data.putExtra(RESULT_CLIP_PATH, clipPath);
|
||||
setResult(RESULT_OK, data);
|
||||
|
||||
638
app/src/main/java/com/gh/gamecenter/ImageViewerActivity.kt
Normal file
638
app/src/main/java/com/gh/gamecenter/ImageViewerActivity.kt
Normal file
@ -0,0 +1,638 @@
|
||||
package com.gh.gamecenter
|
||||
|
||||
import android.animation.AnimatorSet
|
||||
import android.animation.ValueAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Color
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.Environment
|
||||
import android.text.TextUtils
|
||||
import android.util.Base64
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewTreeObserver.OnGlobalLayoutListener
|
||||
import android.view.Window
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.RelativeLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.viewpager.widget.PagerAdapter
|
||||
import androidx.viewpager.widget.ViewPager.OnPageChangeListener
|
||||
import butterknife.BindView
|
||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView.DefaultOnImageEventListener
|
||||
import com.facebook.drawee.backends.pipeline.Fresco
|
||||
import com.facebook.imagepipeline.core.ImagePipeline
|
||||
import com.facebook.imagepipeline.request.ImageRequest
|
||||
import com.gh.base.BaseActivity
|
||||
import com.gh.common.Base64ImageHolder.image
|
||||
import com.gh.common.runOnIoThread
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.util.ImageUtils.getTransformLimitUrl
|
||||
import com.gh.common.view.DraggableBigImageView
|
||||
import com.gh.common.view.Gh_RelativeLayout
|
||||
import com.gh.common.view.Gh_ViewPager
|
||||
import com.gh.gamecenter.entity.ImageInfoEntity
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.github.piasy.biv.view.BigImageView
|
||||
import com.github.piasy.biv.view.FrescoImageViewFactory
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import java.io.*
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* 查看游戏截图页面
|
||||
*
|
||||
* @author 黄壮华
|
||||
*
|
||||
* todo BigImageView静态webp/动态webp(ImageInfoExtractor.getImageType(image))判断有问题,导致部分静态webp无法使用缩放功能
|
||||
*/
|
||||
class ImageViewerActivity : BaseActivity(), OnPageChangeListener {
|
||||
|
||||
@BindView(R.id.image_detail_page)
|
||||
lateinit var mViewPager: Gh_ViewPager
|
||||
|
||||
@BindView(R.id.image_detail_progress)
|
||||
lateinit var mProgressHint: TextView
|
||||
|
||||
@BindView(R.id.image_mask)
|
||||
lateinit var mIndicatorMask: View
|
||||
|
||||
@BindView(R.id.image_indicator_tv)
|
||||
lateinit var mIndicatorTv: TextView
|
||||
|
||||
@BindView(R.id.background_view)
|
||||
lateinit var mBackgroundView: View
|
||||
|
||||
private var adapter: ViewImageAdapter? = null
|
||||
private var mImagePipeline: ImagePipeline? = null
|
||||
private var mShowBase64Image = false
|
||||
private var mUrlList: ArrayList<String>? = null
|
||||
private var mViewedSet: HashSet<Int>? = null // 让调用者知道该图片是否被看过了
|
||||
private var mImageInfoMap: MutableMap<String, ImageInfoEntity>? = null
|
||||
private var mBigImageView: BigImageView? = null
|
||||
|
||||
private var mInitialPosition = 0
|
||||
private var mUseEnterAndExitAnimation = false
|
||||
|
||||
private var mLimitWidth = 0
|
||||
private var mOriginLeft = 0
|
||||
private var mOriginTop = 0
|
||||
private var mOriginHeight = 0
|
||||
private var mOriginWidth = 0
|
||||
private var mOriginCenterX = 0
|
||||
private var mOriginCenterY = 0
|
||||
private var mOriginHeightWidthRatio = 0f
|
||||
private var mTargetHeight = 0f
|
||||
private var mTargetWidth = 0f
|
||||
private var mScaleX = 0f
|
||||
private var mScaleY = 0f
|
||||
private var mTranslationX = 0f
|
||||
private var mTranslationY = 0f
|
||||
|
||||
override fun getLayoutId() = R.layout.activity_viewimage
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
mViewedSet = HashSet()
|
||||
mImageInfoMap = HashMap()
|
||||
mImagePipeline = Fresco.getImagePipeline()
|
||||
|
||||
mInitialPosition = savedInstanceState?.getInt(EntranceUtils.KEY_CURRENTITEM, 0) ?: 0
|
||||
|
||||
intent.extras?.let {
|
||||
if (it.getBoolean(KEY_BASE64)) {
|
||||
mShowBase64Image = true
|
||||
mUrlList = ArrayList()
|
||||
mUrlList?.add(image)
|
||||
} else {
|
||||
mUrlList = it.getStringArrayList(KEY_URL_LIST)
|
||||
mInitialPosition = it.getInt(KEY_CURRENT, 0)
|
||||
}
|
||||
mUseEnterAndExitAnimation = it.getBoolean(KEY_USE_ENTER_AND_EXIT_ANIMATION)
|
||||
}
|
||||
mIndicatorMask.goneIf(mUrlList?.size == 1)
|
||||
mIndicatorTv.text = String.format("%d/%d", mInitialPosition + 1, mUrlList!!.size)
|
||||
|
||||
// init slide
|
||||
val outMetrics = DisplayMetrics()
|
||||
windowManager.defaultDisplay.getMetrics(outMetrics)
|
||||
val widthPixels = outMetrics.widthPixels
|
||||
mLimitWidth = if (NetworkUtils.isWifiOr4GConnected(this)) {
|
||||
widthPixels * 2
|
||||
} else {
|
||||
widthPixels
|
||||
}
|
||||
// init viewPage
|
||||
adapter = ViewImageAdapter()
|
||||
mViewPager.adapter = adapter
|
||||
mViewPager.currentItem = mInitialPosition
|
||||
mViewPager.addOnPageChangeListener(this)
|
||||
mProgressHint.setOnClickListener {
|
||||
val position = mViewPager.currentItem
|
||||
val `object`: Any? = mViewPager.findViewWithTag(position)
|
||||
if (`object` != null) {
|
||||
mProgressHint.width = mProgressHint.width
|
||||
val view = `object` as RelativeLayout
|
||||
val imageView: BigImageView = view.findViewById(R.id.viewimage_iv_show)
|
||||
val url = mUrlList!![position]
|
||||
imageView.showImage(Uri.parse(url))
|
||||
imageView.setImageLoaderCallback(object : SimpleImageLoader() {
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onProgress(progress: Int) {
|
||||
if (position == mViewPager.currentItem) { // 防止下载过程中切换图片
|
||||
if (progress < 100) {
|
||||
mProgressHint.text = "$progress%"
|
||||
} else {
|
||||
mProgressHint.text = "已完成"
|
||||
mBaseHandler.postDelayed({
|
||||
if (position == mViewPager.currentItem) { // 防止等待过程中切换图片
|
||||
mProgressHint.visibility = View.GONE
|
||||
}
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
initEnterAnimation()
|
||||
DisplayUtils.transparentStatusAndNavigation(this)
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putInt(EntranceUtils.KEY_CURRENTITEM, mViewPager.currentItem)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
if (mShowBase64Image) {
|
||||
mUrlList!!.clear()
|
||||
image = ""
|
||||
}
|
||||
mViewPager.onDestroy() // 注销EventBus
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float,
|
||||
positionOffsetPixels: Int) {
|
||||
if (positionOffset != 0f) {
|
||||
mProgressHint.visibility = View.GONE
|
||||
} else {
|
||||
val url = mUrlList!![position]
|
||||
val imageInfoEntity = mImageInfoMap!![url]
|
||||
if (imageInfoEntity?.fileSize != null &&
|
||||
!mImagePipeline!!.isInBitmapMemoryCache(ImageRequest.fromUri(url)) &&
|
||||
!mImagePipeline!!.isInDiskCacheSync(ImageRequest.fromUri(url))) {
|
||||
val size = String.format(Locale.CHINA, "%.1fM",
|
||||
Integer.valueOf(imageInfoEntity.fileSize.value) / 1024f / 1024f)
|
||||
mProgressHint.visibility = View.VISIBLE
|
||||
mProgressHint.text = "查看原图($size)"
|
||||
val layoutParams = mProgressHint.layoutParams
|
||||
layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
mProgressHint.layoutParams = layoutParams
|
||||
}
|
||||
}
|
||||
mViewedSet?.add(position)
|
||||
setResult(Activity.RESULT_OK, Intent().putExtra(VIEWED_IMAGE, mViewedSet))
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
var ghRelativeLayout: Gh_RelativeLayout?
|
||||
for (i in 0 until mViewPager.childCount) {
|
||||
if (mViewPager.getChildAt(i).tag != null) {
|
||||
ghRelativeLayout = mViewPager.getChildAt(i) as? Gh_RelativeLayout
|
||||
if (ghRelativeLayout == null) {
|
||||
return
|
||||
}
|
||||
val imageView: BigImageView = ghRelativeLayout.findViewById(R.id.viewimage_iv_show)
|
||||
val ssiv = imageView.ssiv
|
||||
ssiv?.resetScaleAndCenter()
|
||||
}
|
||||
}
|
||||
mIndicatorTv.text = String.format("%d/%d", position + 1, mUrlList!!.size)
|
||||
}
|
||||
|
||||
override fun onPageScrollStateChanged(newState: Int) {}
|
||||
|
||||
private fun initEnterAnimation() {
|
||||
mViewPager.viewTreeObserver
|
||||
.addOnGlobalLayoutListener(object : OnGlobalLayoutListener {
|
||||
override fun onGlobalLayout() {
|
||||
mViewPager.viewTreeObserver.removeOnGlobalLayoutListener(this)
|
||||
mOriginLeft = intent.getIntExtra(KEY_LEFT, 0)
|
||||
mOriginTop = intent.getIntExtra(KEY_TOP, 0)
|
||||
mOriginHeight = intent.getIntExtra(KEY_HEIGHT, 0)
|
||||
mOriginWidth = intent.getIntExtra(KEY_WIDTH, 0)
|
||||
mOriginCenterX = mOriginLeft + mOriginWidth / 2
|
||||
mOriginCenterY = mOriginTop + mOriginHeight / 2
|
||||
mOriginHeightWidthRatio = mOriginHeight.toFloat() / mOriginWidth
|
||||
val location = IntArray(2)
|
||||
mBigImageView?.getLocationOnScreen(location)
|
||||
mTargetHeight = mBigImageView?.height?.toFloat() ?: 0F
|
||||
mTargetWidth = mBigImageView?.width?.toFloat() ?: 0F
|
||||
mScaleX = mOriginWidth.toFloat() / mTargetWidth
|
||||
// TODO 非等比例缩放的图片动画不正常
|
||||
mScaleY = mScaleX
|
||||
val targetCenterX = location[0] + mTargetWidth / 2
|
||||
val targetCenterY = location[1] + mTargetHeight / 2
|
||||
mTranslationX = mOriginCenterX - targetCenterX
|
||||
mTranslationY = mOriginCenterY - targetCenterY
|
||||
|
||||
if (mUseEnterAndExitAnimation) {
|
||||
mBigImageView?.translationX = mTranslationX
|
||||
mBigImageView?.translationY = mTranslationY
|
||||
mBigImageView?.scaleX = mScaleX
|
||||
mBigImageView?.scaleY = mScaleY
|
||||
}
|
||||
|
||||
performEnterAnimation()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun loadImageInfo(position: Int, width: Int) {
|
||||
val url = mUrlList!![position]
|
||||
RetrofitManager.getInstance(this)
|
||||
.api.getImageInfo("$url?x-oss-process=image/info")
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<ImageInfoEntity?>() {
|
||||
override fun onResponse(response: ImageInfoEntity?) {
|
||||
if (response?.imageWidth != null && Integer.valueOf(response.imageWidth.value) > width) {
|
||||
mImageInfoMap!![url] = response
|
||||
if (position == mViewPager.currentItem) {
|
||||
onPageScrolled(position, 0f, 0) // 刷新下载原图提示按钮
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun loadImage(originalUrl: String, decoratedUrl: String?, imageView: BigImageView) {
|
||||
if (TextUtils.isEmpty(originalUrl)) return
|
||||
if (originalUrl.startsWith("data:image/png;base64")) {
|
||||
runOnIoThread {
|
||||
val base64String = originalUrl.replace("data:image/png;base64", "")
|
||||
try {
|
||||
val imageFile = File(cacheDir.absolutePath + File.separator + System.currentTimeMillis() + ".png")
|
||||
val decodedString = Base64.decode(base64String, Base64.DEFAULT)
|
||||
val bos = BufferedOutputStream(FileOutputStream(imageFile))
|
||||
bos.write(decodedString)
|
||||
bos.flush()
|
||||
bos.close()
|
||||
runOnUiThread {
|
||||
imageView.setImageViewFactory(FrescoImageViewFactory())
|
||||
imageView.showImage(Uri.fromFile(imageFile))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 添加GIF支持
|
||||
imageView.setImageViewFactory(FrescoImageViewFactory())
|
||||
imageView.setThumbnailScaleType(ImageView.ScaleType.FIT_CENTER)
|
||||
imageView.showImage(Uri.parse(originalUrl), Uri.parse(decoratedUrl))
|
||||
}
|
||||
}
|
||||
|
||||
private fun finishWithAnimation(fadeOnly: Boolean) {
|
||||
val animatorSet = AnimatorSet()
|
||||
|
||||
val translateXAnimator = ValueAnimator.ofFloat(0F, mTranslationX).apply {
|
||||
addUpdateListener { va -> mBigImageView?.x = (va.animatedValue as Float) }
|
||||
}
|
||||
val translateYAnimator = ValueAnimator.ofFloat(0F, mTranslationY).apply {
|
||||
addUpdateListener { va -> mBigImageView?.y = (va.animatedValue as Float) }
|
||||
}
|
||||
val scaleYAnimator = ValueAnimator.ofFloat(1F, mScaleY).apply {
|
||||
addUpdateListener { va -> mBigImageView?.scaleY = (va.animatedValue as Float) }
|
||||
}
|
||||
val scaleXAnimator = ValueAnimator.ofFloat(1F, mScaleX).apply {
|
||||
addUpdateListener { va -> mBigImageView?.scaleX = (va.animatedValue as Float) }
|
||||
}
|
||||
val backgroundAlphaAnimation = ValueAnimator.ofFloat(1F, 0F).apply {
|
||||
addUpdateListener { va -> mBackgroundView.alpha = (va.animatedValue as Float) }
|
||||
}
|
||||
val alphaAnimator = ValueAnimator.ofFloat(1F, 0F).apply {
|
||||
addUpdateListener { va -> mViewPager.alpha = (va.animatedValue as Float) }
|
||||
}
|
||||
|
||||
animatorSet.apply {
|
||||
if (mUseEnterAndExitAnimation && !fadeOnly) {
|
||||
playTogether(translateXAnimator, translateYAnimator, scaleXAnimator, scaleYAnimator, backgroundAlphaAnimation)
|
||||
} else {
|
||||
playTogether(alphaAnimator, backgroundAlphaAnimation)
|
||||
}
|
||||
duration = ANIMATION_DURATION
|
||||
doOnStart { mIndicatorMask.visibility = View.GONE }
|
||||
doOnEnd {
|
||||
it.removeAllListeners()
|
||||
finish()
|
||||
overridePendingTransition(0, 0)
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
private fun performEnterAnimation() {
|
||||
val animatorSet = AnimatorSet()
|
||||
|
||||
val translateXAnimator = ValueAnimator.ofFloat(mBigImageView!!.x, 0F).apply {
|
||||
addUpdateListener { va -> mBigImageView?.x = (va.animatedValue as Float) }
|
||||
}
|
||||
val translateYAnimator = ValueAnimator.ofFloat(mBigImageView!!.y, 0F).apply {
|
||||
addUpdateListener { va -> mBigImageView?.y = (va.animatedValue as Float) }
|
||||
}
|
||||
val scaleYAnimator = ValueAnimator.ofFloat(mScaleY, 1F).apply {
|
||||
addUpdateListener { va -> mBigImageView?.scaleY = (va.animatedValue as Float) }
|
||||
}
|
||||
val scaleXAnimator = ValueAnimator.ofFloat(mScaleX, 1F).apply {
|
||||
addUpdateListener { va -> mBigImageView?.scaleX = (va.animatedValue as Float) }
|
||||
}
|
||||
val backgroundAlphaAnimator = ValueAnimator.ofFloat(0F, 1F).apply {
|
||||
addUpdateListener { va -> mBackgroundView.alpha = (va.animatedValue as Float) }
|
||||
}
|
||||
|
||||
animatorSet.apply {
|
||||
if (mUseEnterAndExitAnimation) {
|
||||
playTogether(translateXAnimator, translateYAnimator, scaleXAnimator, scaleYAnimator, backgroundAlphaAnimator)
|
||||
} else {
|
||||
playTogether(backgroundAlphaAnimator)
|
||||
}
|
||||
duration = ANIMATION_DURATION
|
||||
doOnStart { mIndicatorMask.visibility = View.GONE }
|
||||
doOnEnd {
|
||||
if (mUrlList?.size != 1) {
|
||||
mIndicatorMask.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
private fun performExitAnimation(view: DraggableBigImageView, scale: Float, fadeOnly: Boolean) {
|
||||
val finalScale = mOriginWidth / mTargetWidth
|
||||
val finalTranslationX = mOriginLeft - (1 - finalScale) * mTargetWidth / 2
|
||||
val finalTranslationY = mOriginTop - ((1 - finalScale) * mTargetHeight + (mTargetHeight * finalScale - mOriginHeight)) / 2
|
||||
|
||||
val animatorSet = AnimatorSet()
|
||||
|
||||
val scaleAnimator = ValueAnimator.ofFloat(scale, finalScale).apply {
|
||||
addUpdateListener { va ->
|
||||
view.scaleX = (va.animatedValue as Float)
|
||||
view.scaleY = (va.animatedValue as Float)
|
||||
}
|
||||
}
|
||||
val translateXAnimator = ValueAnimator.ofFloat(view.x, finalTranslationX).apply {
|
||||
addUpdateListener { va -> view.translationX = (va.animatedValue as Float) }
|
||||
}
|
||||
val translateYAnimator = ValueAnimator.ofFloat(view.y, finalTranslationY).apply {
|
||||
addUpdateListener { va -> view.translationY = (va.animatedValue as Float) }
|
||||
}
|
||||
val backgroundAlphaAnimator = ValueAnimator.ofFloat(mBackgroundView.alpha, 0F).apply {
|
||||
addUpdateListener { va -> mBackgroundView.alpha = (va.animatedValue as Float) }
|
||||
}
|
||||
val alphaAnimator = ValueAnimator.ofFloat(1F, 0F).apply {
|
||||
addUpdateListener { va -> view.alpha = (va.animatedValue as Float) }
|
||||
}
|
||||
|
||||
animatorSet.apply {
|
||||
if (mUseEnterAndExitAnimation && !fadeOnly) {
|
||||
playTogether(scaleAnimator, translateXAnimator, translateYAnimator, backgroundAlphaAnimator)
|
||||
} else {
|
||||
playTogether(backgroundAlphaAnimator, alphaAnimator)
|
||||
}
|
||||
doOnEnd {
|
||||
it.removeAllListeners()
|
||||
finish()
|
||||
overridePendingTransition(0, 0)
|
||||
}
|
||||
interpolator = DecelerateInterpolator()
|
||||
duration = ANIMATION_DURATION
|
||||
}.start()
|
||||
}
|
||||
|
||||
private inner class ViewImageAdapter : PagerAdapter() {
|
||||
override fun getCount() = mUrlList?.size ?: 0
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
override fun instantiateItem(container: ViewGroup, position: Int): Any {
|
||||
val originalUrl = mUrlList!![position]
|
||||
var decoratedUrl: String? = originalUrl
|
||||
val imageRequest = ImageRequest.fromUri(originalUrl)
|
||||
val isInMemoryCache = mImagePipeline!!.isInBitmapMemoryCache(imageRequest)
|
||||
val isInDiskCache = imageRequest != null && mImagePipeline!!.isInDiskCacheSync(imageRequest)
|
||||
val view = View.inflate(container.context, R.layout.viewimage_normal_item, null) as Gh_RelativeLayout
|
||||
val imageView: DraggableBigImageView = view.findViewById(R.id.viewimage_iv_show)
|
||||
if (mBigImageView == null) {
|
||||
mBigImageView = imageView
|
||||
}
|
||||
imageView.setDragListener(object : DraggableBigImageView.DragListener {
|
||||
override fun onRelease(draggableBigImageView: DraggableBigImageView, scale: Float) {
|
||||
performExitAnimation(draggableBigImageView, scale, mViewPager.currentItem != mInitialPosition)
|
||||
}
|
||||
|
||||
override fun onDrag(draggableBigImageView: DraggableBigImageView, fraction: Float) {
|
||||
mBackgroundView.alpha = 1 - fraction
|
||||
mIndicatorMask.visibility = View.GONE
|
||||
}
|
||||
|
||||
override fun onRestore(draggableBigImageView: DraggableBigImageView, fraction: Float) {
|
||||
mBackgroundView.alpha = 1F
|
||||
mIndicatorMask.goneIf(mUrlList?.size == 1)
|
||||
}
|
||||
})
|
||||
if (!isInMemoryCache
|
||||
&& !isInDiskCache
|
||||
&& !NetworkUtils.isWifiOr4GConnected(this@ImageViewerActivity)
|
||||
&& !originalUrl.contains(".gif")) {
|
||||
decoratedUrl = getTransformLimitUrl(originalUrl, mLimitWidth, applicationContext)
|
||||
}
|
||||
val finalUrl = decoratedUrl
|
||||
imageView.setImageLoaderCallback(object : SimpleImageLoader() {
|
||||
override fun onSuccess(image: File) {
|
||||
if (finalUrl != mUrlList!![position]) {
|
||||
val options = BitmapFactory.Options()
|
||||
options.inJustDecodeBounds = true
|
||||
BitmapFactory.decodeFile(File(image.path).absolutePath, options)
|
||||
loadImageInfo(position, options.outWidth) // 加载图片参数,目的是用户显示原文按钮
|
||||
}
|
||||
val ssiv = imageView.ssiv
|
||||
if (ssiv != null) {
|
||||
ssiv.maxScale = 10f // 这个缩放倍数最好很具宽高自动调节
|
||||
ssiv.setOnImageEventListener(object : DefaultOnImageEventListener() {
|
||||
override fun onReady() {
|
||||
ssiv.resetScaleAndCenter()
|
||||
}
|
||||
})
|
||||
ssiv.setOnClickListener { finishWithAnimation(mInitialPosition != mViewPager.currentItem) }
|
||||
}
|
||||
}
|
||||
})
|
||||
loadImage(originalUrl, decoratedUrl, imageView)
|
||||
|
||||
//长按
|
||||
imageView.setOnLongClickListener {
|
||||
// 下滑的时候不弹
|
||||
if (imageView.isDragging()) {
|
||||
return@setOnLongClickListener false
|
||||
}
|
||||
|
||||
val dialog = Dialog(this@ImageViewerActivity)
|
||||
val container1 = LinearLayout(this@ImageViewerActivity)
|
||||
container1.orientation = LinearLayout.VERTICAL
|
||||
container1.setBackgroundColor(Color.WHITE)
|
||||
val reportTv = TextView(this@ImageViewerActivity)
|
||||
reportTv.setPadding(
|
||||
DisplayUtils.dip2px(this@ImageViewerActivity, 20f),
|
||||
DisplayUtils.dip2px(this@ImageViewerActivity, 12f),
|
||||
0,
|
||||
DisplayUtils.dip2px(this@ImageViewerActivity, 12f))
|
||||
reportTv.setText(R.string.save_pic)
|
||||
reportTv.textSize = 17f
|
||||
reportTv.setTextColor(ContextCompat.getColor(applicationContext, R.color.title))
|
||||
reportTv.setBackgroundResource(R.drawable.textview_white_style)
|
||||
val widthPixels = resources.displayMetrics.widthPixels
|
||||
reportTv.layoutParams = LinearLayout.LayoutParams(widthPixels * 9 / 10,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT)
|
||||
container1.addView(reportTv)
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
dialog.setContentView(container1)
|
||||
if (!isFinishing) {
|
||||
dialog.show()
|
||||
}
|
||||
reportTv.setOnClickListener {
|
||||
checkStoragePermissionBeforeAction {
|
||||
saveImageToFile(imageView.currentImageFile, finalUrl)
|
||||
dialog.cancel()
|
||||
}
|
||||
dialog.cancel()
|
||||
}
|
||||
false
|
||||
}
|
||||
view.tag = position
|
||||
container.addView(view)
|
||||
return view
|
||||
}
|
||||
|
||||
private fun saveImageToFile(src: File, curUrl: String?) {
|
||||
var `in`: InputStream? = null
|
||||
var out: OutputStream? = null
|
||||
try {
|
||||
val fileName: String = if (mShowBase64Image) {
|
||||
MD5Utils.getUrlMD5(curUrl!!.substring(0, 50)) + ".png"
|
||||
} else {
|
||||
curUrl!!.substring(curUrl.lastIndexOf("/"))
|
||||
}
|
||||
val savePath = Environment.getExternalStorageDirectory().absolutePath + "/Pictures/ghzhushou/"
|
||||
val file = File(savePath)
|
||||
if (!file.exists()) {
|
||||
file.mkdirs()
|
||||
}
|
||||
val dst = File(savePath, fileName)
|
||||
if (dst.exists()) {
|
||||
dst.delete()
|
||||
}
|
||||
`in` = FileInputStream(src)
|
||||
out = FileOutputStream(dst)
|
||||
val buf = ByteArray(1024)
|
||||
var len: Int
|
||||
while (`in`.read(buf).also { len = it } > 0) {
|
||||
out.write(buf, 0, len)
|
||||
}
|
||||
Utils.toast(this@ImageViewerActivity, "图片已保存到/Pictures/ghzhushou/")
|
||||
MessageShareUtils.refreshImage(this@ImageViewerActivity, dst)
|
||||
} catch (e: Exception) {
|
||||
Utils.log("图片保存失败:$e")
|
||||
} finally {
|
||||
try {
|
||||
out?.close()
|
||||
`in`?.close()
|
||||
} catch (ignore: Exception) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
|
||||
container.removeView(`object` as View)
|
||||
}
|
||||
|
||||
override fun isViewFromObject(view: View, `object`: Any): Boolean {
|
||||
return view === `object`
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
finishWithAnimation(mInitialPosition != mViewPager.currentItem)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val REQUEST_FOR_VIEWED_IMAGE = 921
|
||||
const val VIEWED_IMAGE = "viewed_image"
|
||||
|
||||
private const val KEY_BASE64 = "base64"
|
||||
private const val KEY_URL_LIST = "urls"
|
||||
private const val KEY_CURRENT = "current"
|
||||
private const val KEY_USE_ENTER_AND_EXIT_ANIMATION = "use_enter_and_exit_animation"
|
||||
|
||||
private const val KEY_LEFT = "left"
|
||||
private const val KEY_TOP = "top"
|
||||
private const val KEY_HEIGHT = "height"
|
||||
private const val KEY_WIDTH = "width"
|
||||
|
||||
private const val ANIMATION_DURATION = 350L
|
||||
|
||||
@JvmStatic
|
||||
fun getBase64Intent(context: Context?, showSingleBase64Image: Boolean): Intent {
|
||||
val checkIntent = Intent(context, ImageViewerActivity::class.java)
|
||||
checkIntent.putExtra(KEY_BASE64, showSingleBase64Image)
|
||||
return checkIntent
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getIntent(context: Context, list: ArrayList<String>, position: Int = 0, entrance: String?): Intent {
|
||||
return getIntent(context, list, position, null, entrance)
|
||||
}
|
||||
|
||||
/**
|
||||
* 传入 view 代表使用渐入渐出动画
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getIntent(context: Context, list: ArrayList<String>, position: Int = 0, originalView: View? = null, entrance: String?): Intent {
|
||||
val intent = Intent(context, ImageViewerActivity::class.java)
|
||||
intent.putExtra(KEY_URL_LIST, list)
|
||||
intent.putExtra(KEY_CURRENT, position)
|
||||
intent.putExtra(EntranceUtils.KEY_ENTRANCE, entrance)
|
||||
|
||||
val location = IntArray(2)
|
||||
if (originalView != null) {
|
||||
originalView.getLocationOnScreen(location)
|
||||
intent.putExtra(KEY_LEFT, location[0])
|
||||
intent.putExtra(KEY_TOP, location[1])
|
||||
intent.putExtra(KEY_HEIGHT, originalView.height)
|
||||
intent.putExtra(KEY_WIDTH, originalView.width)
|
||||
intent.putExtra(KEY_USE_ENTER_AND_EXIT_ANIMATION, true)
|
||||
}
|
||||
|
||||
if (context is Activity) {
|
||||
context.overridePendingTransition(0, 0)
|
||||
}
|
||||
|
||||
return intent
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -24,6 +24,7 @@ import com.gh.common.util.ApkActiveUtils;
|
||||
import com.gh.common.util.DetailDownloadUtils;
|
||||
import com.gh.common.util.DeviceTokenUtils;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.common.util.ExtensionsKt;
|
||||
import com.gh.common.util.LibaoUtils;
|
||||
import com.gh.common.view.DownloadProgressBar;
|
||||
import com.gh.common.view.VerticalItemDecoration;
|
||||
@ -375,6 +376,12 @@ public class LibaoDetailActivity extends ToolBarActivity implements LibaoDetailA
|
||||
mGameEntity = response;
|
||||
mAdapter.setGameEntity(mGameEntity);
|
||||
|
||||
// 添加启动弹窗的相关信息
|
||||
if (mEntrance.contains(EntranceUtils.ENTRANCE_WELCOME)
|
||||
&& ExtensionsKt.countOccurrences(mEntrance,("+")) <= 1) {
|
||||
mGameEntity.setWelcomeDialogInfoIfAvailable();
|
||||
}
|
||||
|
||||
DetailDownloadUtils.detailInitDownload(getDetailViewHolder(), true);
|
||||
|
||||
mAdapter.addLibaoDetail(LibaoDetailActivity.this, true);
|
||||
|
||||
@ -53,6 +53,7 @@ import com.gh.common.util.LogUtils;
|
||||
import com.gh.common.util.LunchType;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.common.util.NotificationHelper;
|
||||
import com.gh.common.util.PackageInstaller;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.PlatformUtils;
|
||||
import com.gh.common.util.PushHelper;
|
||||
@ -217,8 +218,7 @@ public class MainActivity extends BaseActivity {
|
||||
// checkTinkerPath(); // 看情况是否需要显示补丁弹窗
|
||||
|
||||
// 必须放在这里,否则会导致获取 baseActivity 不是本应用包名
|
||||
// postDelayed 是为了让 ProcessLifecycleOwner 知道准确状态,避免调用 startForegroundService
|
||||
handler.postDelayed(() -> DownloadManager.getInstance(this).initDownloadService(), 0);
|
||||
DownloadManager.getInstance(this).initDownloadService();
|
||||
|
||||
checkNotificationPermission();
|
||||
|
||||
@ -444,7 +444,7 @@ public class MainActivity extends BaseActivity {
|
||||
"提示", msg,
|
||||
"直接退出",
|
||||
"立即安装",
|
||||
() -> handler.postDelayed(() -> PackageUtils.launchSetup(MainActivity.this, finalDownloadEntity), 200),
|
||||
() -> handler.postDelayed(() -> PackageInstaller.install(MainActivity.this, finalDownloadEntity), 200),
|
||||
this::finish);
|
||||
return true;
|
||||
}
|
||||
@ -772,7 +772,7 @@ public class MainActivity extends BaseActivity {
|
||||
// "操作", "卸载完成",
|
||||
// "网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()));
|
||||
|
||||
startActivity(PackageUtils.getInstallIntent(this, mDownloadEntity.getPath()));
|
||||
PackageInstaller.install(this, mDownloadEntity);
|
||||
}
|
||||
|
||||
// 更新已安装游戏
|
||||
|
||||
@ -17,11 +17,11 @@ import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import android.widget.ScrollView
|
||||
import android.widget.TextView
|
||||
import com.gh.base.BaseActivity
|
||||
import com.gh.base.ToolBarActivity
|
||||
import com.gh.common.util.CommentUtils
|
||||
import com.gh.common.util.DeviceUtils
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.common.util.tryCatchInRelease
|
||||
import com.gh.gamecenter.retrofit.Response
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.ObservableOnSubscribe
|
||||
@ -67,85 +67,85 @@ class NetworkDiagnosisActivity : ToolBarActivity() {
|
||||
|
||||
Observable.create(ObservableOnSubscribe<ProgressAndDetail> {
|
||||
|
||||
var progress = 0
|
||||
var progress = 0
|
||||
|
||||
// 1.获取当前网络情况,network/ip/mac/sim
|
||||
// 1.获取当前网络情况,network/ip/mac/sim
|
||||
|
||||
// Network 2G/3G/4G/WIFI
|
||||
builder.append("Network:")
|
||||
builder.append(DeviceUtils.getNetwork(applicationContext))
|
||||
// Network 2G/3G/4G/WIFI
|
||||
builder.append("Network:")
|
||||
builder.append(DeviceUtils.getNetwork(applicationContext))
|
||||
builder.append("\n")
|
||||
|
||||
progress += 3
|
||||
it.onNext(ProgressAndDetail(progress, builder.toString()))
|
||||
|
||||
// IP
|
||||
builder.append("IP:")
|
||||
builder.append(DeviceUtils.getIPAddress(applicationContext))
|
||||
builder.append("\n")
|
||||
|
||||
progress += 3
|
||||
it.onNext(ProgressAndDetail(progress, builder.toString()))
|
||||
|
||||
// MAC
|
||||
builder.append("MAC:")
|
||||
builder.append(DeviceUtils.getMac(applicationContext))
|
||||
builder.append("\n")
|
||||
|
||||
progress += 3
|
||||
it.onNext(ProgressAndDetail(progress, builder.toString()))
|
||||
|
||||
// SIM
|
||||
builder.append("SIM:")
|
||||
builder.append(DeviceUtils.getSim(applicationContext))
|
||||
builder.append("\n")
|
||||
|
||||
progress += 3
|
||||
it.onNext(ProgressAndDetail(progress, builder.toString()))
|
||||
|
||||
builder.append("-----------------------------------------------------------------------\n")
|
||||
|
||||
// 2.ping域名
|
||||
val domains = arrayOf("api.ghzs.com", "download.ghzs.com", "apk.ghzs666.com", "image.ghzs666.com", "image.ghzhushou.com")
|
||||
for (domain in domains) {
|
||||
builder.append(DeviceUtils.ping(domain))
|
||||
builder.append("-----------------------------------------------------------------------\n")
|
||||
progress += 7
|
||||
it.onNext(ProgressAndDetail(progress, builder.toString()))
|
||||
}
|
||||
|
||||
// 3.okhttp访问链接
|
||||
val urls = arrayOf("https://api.ghzs.com/v3d3/index/columns", "https://download.ghzs.com/game?id=55097638fc1a6fa45f8b4568&platform=9u", "https://apk.ghzs666.com/packed/5af00abc02b30f7c038b456c.apk", "http://image.ghzs666.com/pic/5b29b3c92924bcaf5d438d38.jpg", "http://image.ghzhushou.com/pic/586cad378ab49e0f1b91b3e8.png")
|
||||
for (url in urls) {
|
||||
builder.append("Url:")
|
||||
builder.append(url)
|
||||
builder.append("\n")
|
||||
|
||||
val client = OkHttpClient()
|
||||
val request = Request.Builder()
|
||||
.head()
|
||||
.url(url)
|
||||
.build()
|
||||
try {
|
||||
val response = client.newCall(request).execute()
|
||||
builder.append("Success:\n")
|
||||
builder.append("Response:\n")
|
||||
builder.append(response.toString())
|
||||
builder.append("\n")
|
||||
|
||||
progress += 3
|
||||
it.onNext(ProgressAndDetail(progress, builder.toString()))
|
||||
|
||||
// IP
|
||||
builder.append("IP:")
|
||||
builder.append(DeviceUtils.getIPAddress(applicationContext))
|
||||
builder.append("Response Header:\n")
|
||||
builder.append(response.headers().toString())
|
||||
builder.append("\n")
|
||||
} catch (e: IOException) {
|
||||
builder.append("Error:\n")
|
||||
builder.append(Log.getStackTraceString(e))
|
||||
}
|
||||
builder.append("-----------------------------------------------------------------------\n")
|
||||
progress += 7
|
||||
it.onNext(ProgressAndDetail(progress, builder.toString()))
|
||||
}
|
||||
|
||||
progress += 3
|
||||
it.onNext(ProgressAndDetail(progress, builder.toString()))
|
||||
|
||||
// MAC
|
||||
builder.append("MAC:")
|
||||
builder.append(DeviceUtils.getMac(applicationContext))
|
||||
builder.append("\n")
|
||||
|
||||
progress += 3
|
||||
it.onNext(ProgressAndDetail(progress, builder.toString()))
|
||||
|
||||
// SIM
|
||||
builder.append("SIM:")
|
||||
builder.append(DeviceUtils.getSim(applicationContext))
|
||||
builder.append("\n")
|
||||
|
||||
progress += 3
|
||||
it.onNext(ProgressAndDetail(progress, builder.toString()))
|
||||
|
||||
builder.append("-----------------------------------------------------------------------\n")
|
||||
|
||||
// 2.ping域名
|
||||
val domains = arrayOf("api.ghzs.com", "download.ghzs.com", "apk.ghzs666.com", "image.ghzs666.com", "image.ghzhushou.com")
|
||||
for (domain in domains) {
|
||||
builder.append(DeviceUtils.ping(domain))
|
||||
builder.append("-----------------------------------------------------------------------\n")
|
||||
progress += 7
|
||||
it.onNext(ProgressAndDetail(progress, builder.toString()))
|
||||
}
|
||||
|
||||
// 3.okhttp访问链接
|
||||
val urls = arrayOf("https://api.ghzs.com/v3d3/index/columns", "https://download.ghzs.com/game?id=55097638fc1a6fa45f8b4568&platform=9u", "https://apk.ghzs666.com/packed/5af00abc02b30f7c038b456c.apk", "http://image.ghzs666.com/pic/5b29b3c92924bcaf5d438d38.jpg", "http://image.ghzhushou.com/pic/586cad378ab49e0f1b91b3e8.png")
|
||||
for (url in urls) {
|
||||
builder.append("Url:")
|
||||
builder.append(url)
|
||||
builder.append("\n")
|
||||
|
||||
val client = OkHttpClient()
|
||||
val request = Request.Builder()
|
||||
.head()
|
||||
.url(url)
|
||||
.build()
|
||||
try {
|
||||
val response = client.newCall(request).execute()
|
||||
builder.append("Success:\n")
|
||||
builder.append("Response:\n")
|
||||
builder.append(response.toString())
|
||||
builder.append("\n")
|
||||
builder.append("Response Header:\n")
|
||||
builder.append(response.headers().toString())
|
||||
builder.append("\n")
|
||||
} catch (e: IOException) {
|
||||
builder.append("Error:\n")
|
||||
builder.append(Log.getStackTraceString(e))
|
||||
}
|
||||
builder.append("-----------------------------------------------------------------------\n")
|
||||
progress += 7
|
||||
it.onNext(ProgressAndDetail(progress, builder.toString()))
|
||||
}
|
||||
|
||||
it.onComplete()
|
||||
}).subscribeOn(Schedulers.io())
|
||||
it.onComplete()
|
||||
}).subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Response<ProgressAndDetail>() {
|
||||
override fun onNext(response: ProgressAndDetail) {
|
||||
@ -185,44 +185,46 @@ class NetworkDiagnosisActivity : ToolBarActivity() {
|
||||
// 等待10秒,等待js检查完成
|
||||
view.postDelayed({
|
||||
// WebView生成长图,也就是超过一屏的图片,代码中的bitmap就是最后生成的长图
|
||||
mWebView.measure(View.MeasureSpec.makeMeasureSpec(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED),
|
||||
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED))
|
||||
mWebView.layout(0, 0, mWebView.measuredWidth, mWebView.measuredHeight)
|
||||
mWebView.isDrawingCacheEnabled = true
|
||||
mWebView.buildDrawingCache()
|
||||
val bitmap = Bitmap.createBitmap(mWebView.measuredWidth,
|
||||
mWebView.measuredHeight, Bitmap.Config.ARGB_8888)
|
||||
tryCatchInRelease {
|
||||
mWebView.measure(View.MeasureSpec.makeMeasureSpec(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED),
|
||||
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED))
|
||||
mWebView.layout(0, 0, mWebView.measuredWidth, mWebView.measuredHeight)
|
||||
mWebView.isDrawingCacheEnabled = true
|
||||
mWebView.buildDrawingCache()
|
||||
val bitmap = Bitmap.createBitmap(mWebView.measuredWidth,
|
||||
mWebView.measuredHeight, Bitmap.Config.ARGB_8888)
|
||||
|
||||
// 画布的宽高和WebView的网页保持一致
|
||||
val canvas = Canvas(bitmap)
|
||||
val paint = Paint()
|
||||
canvas.drawBitmap(bitmap, 0F, mWebView.measuredHeight.toFloat(), paint)
|
||||
mWebView.draw(canvas)
|
||||
// 画布的宽高和WebView的网页保持一致
|
||||
val canvas = Canvas(bitmap)
|
||||
val paint = Paint()
|
||||
canvas.drawBitmap(bitmap, 0F, mWebView.measuredHeight.toFloat(), paint)
|
||||
mWebView.draw(canvas)
|
||||
|
||||
// 保存成文件
|
||||
val filePath = bitmap2File(bitmap)
|
||||
// 保存成文件
|
||||
val filePath = bitmap2File(bitmap)
|
||||
|
||||
builder.append("WebView Long Image Path:\n")
|
||||
builder.append(filePath)
|
||||
builder.append("\n")
|
||||
builder.append("\n")
|
||||
builder.append(mSuccessHint)
|
||||
builder.append("WebView Long Image Path:\n")
|
||||
builder.append(filePath)
|
||||
builder.append("\n")
|
||||
builder.append("\n")
|
||||
builder.append(mSuccessHint)
|
||||
|
||||
builder.setSpan(object : ClickableSpan() {
|
||||
override fun updateDrawState(ds: TextPaint) {
|
||||
super.updateDrawState(ds)
|
||||
ds.color = resources.getColor(R.color.theme_font)
|
||||
ds.isUnderlineText = false
|
||||
}
|
||||
builder.setSpan(object : ClickableSpan() {
|
||||
override fun updateDrawState(ds: TextPaint) {
|
||||
super.updateDrawState(ds)
|
||||
ds.color = resources.getColor(R.color.theme_font)
|
||||
ds.isUnderlineText = false
|
||||
}
|
||||
|
||||
override fun onClick(widget: View) {
|
||||
CommentUtils.copyText(builder.toString().replace(mSuccessHint, ""), applicationContext)
|
||||
}
|
||||
}, builder.length - mSuccessHint.length, builder.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
override fun onClick(widget: View) {
|
||||
CommentUtils.copyText(builder.toString().replace(mSuccessHint, ""), applicationContext)
|
||||
}
|
||||
}, builder.length - mSuccessHint.length, builder.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
|
||||
mResult.text = builder
|
||||
mResult.setMovementMethod(LinkMovementMethod.getInstance())
|
||||
setResultProgress(100)
|
||||
mResult.text = builder
|
||||
mResult.setMovementMethod(LinkMovementMethod.getInstance())
|
||||
setResultProgress(100)
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
@ -252,7 +254,7 @@ class NetworkDiagnosisActivity : ToolBarActivity() {
|
||||
override fun handleBackPressed(): Boolean {
|
||||
if (mProgressData < 100) {
|
||||
DialogUtils.showAlertDialog(this, "确认退出", "网络诊断还未完成,退出会终止所有诊断进程,确定退出吗?"
|
||||
,"确定", "取消", DialogUtils.ConfirmListener {
|
||||
, "确定", "取消", DialogUtils.ConfirmListener {
|
||||
finish()
|
||||
}, null)
|
||||
return true
|
||||
|
||||
@ -18,6 +18,10 @@ import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.view.MotionEventCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.ethanhua.skeleton.Skeleton;
|
||||
import com.ethanhua.skeleton.ViewSkeletonScreen;
|
||||
import com.gh.base.OnRequestCallBackListener;
|
||||
@ -65,9 +69,6 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.view.MotionEventCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import butterknife.BindView;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
@ -228,8 +229,8 @@ public class NewsDetailActivity extends ToolBarActivity implements OnClickListen
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == ViewImageActivity.REQUEST_FOR_VIEWED_IMAGE && resultCode == Activity.RESULT_OK) {
|
||||
HashSet<Integer> imageSet = (HashSet<Integer>) data.getExtras().get(ViewImageActivity.VIEWED_IMAGE);
|
||||
if (requestCode == ImageViewerActivity.REQUEST_FOR_VIEWED_IMAGE && resultCode == Activity.RESULT_OK) {
|
||||
HashSet<Integer> imageSet = (HashSet<Integer>) data.getExtras().get(ImageViewerActivity.VIEWED_IMAGE);
|
||||
adapter.replaceDefaultImage(imageSet);
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.common.util.PlatformUtils;
|
||||
import com.gh.common.util.RunningUtils;
|
||||
import com.gh.gamecenter.entity.CommunityEntity;
|
||||
import com.gh.gamecenter.entity.SimpleGameEntity;
|
||||
import com.gh.gamecenter.entity.SubjectRecommendEntity;
|
||||
import com.gh.gamecenter.entity.VideoLinkEntity;
|
||||
import com.gh.gamecenter.manager.UserManager;
|
||||
@ -34,6 +35,7 @@ import static com.gh.common.util.EntranceUtils.HOST_DOWNLOAD;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_GAME;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_LIBAO;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_QQ;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_QQ_QUN;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_QQ_GROUP;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_QUESTION;
|
||||
import static com.gh.common.util.EntranceUtils.HOST_SUGGESTION;
|
||||
@ -97,7 +99,7 @@ public class SkipActivity extends BaseActivity {
|
||||
DirectUtils.directToArticle(this, path, ENTRANCE_BROWSER);
|
||||
break;
|
||||
case HOST_GAME:
|
||||
DirectUtils.directToGameDetail(this, path, ENTRANCE_BROWSER, false, "libao".equals(to),null);
|
||||
DirectUtils.directToGameDetail(this, path, ENTRANCE_BROWSER, false, "libao".equals(to), null);
|
||||
break;
|
||||
case HOST_COLUMN:
|
||||
DirectUtils.directToSubject(this, path, uri.getQueryParameter(KEY_NAME), ENTRANCE_BROWSER);
|
||||
@ -182,21 +184,34 @@ public class SkipActivity extends BaseActivity {
|
||||
String categoryId = uri.getQueryParameter("category_id");
|
||||
String link = uri.getQueryParameter("link");
|
||||
VideoLinkEntity linkEntity = new VideoLinkEntity(title, categoryId, link);
|
||||
// if (!CheckLoginUtils.isLogin()) {
|
||||
// HaloApp.put(HOST_UPLOAD_VIDEO, linkEntity);
|
||||
// }
|
||||
Bundle nextToBundle = VideoManagerActivity.getVideoManagerBundle(linkEntity, EntranceUtils.ENTRANCE_BROWSER, "");
|
||||
CheckLoginUtils.checkLogin(this, nextToBundle, true, EntranceUtils.ENTRANCE_BROWSER, null);
|
||||
gameId = uri.getQueryParameter("gameId");
|
||||
String gameName = uri.getQueryParameter("gameName");
|
||||
SimpleGameEntity simpleGameEntity = new SimpleGameEntity(gameId, gameName, "");
|
||||
Bundle nextToBundle = VideoManagerActivity.getVideoManagerBundle(linkEntity, simpleGameEntity, EntranceUtils.ENTRANCE_BROWSER, "");
|
||||
CheckLoginUtils.checkLogin(this, nextToBundle, true, EntranceUtils.ENTRANCE_BROWSER, () ->
|
||||
DirectUtils.directToVideoManager(SkipActivity.this, linkEntity, simpleGameEntity, EntranceUtils.ENTRANCE_BROWSER, "浏览器"));
|
||||
break;
|
||||
case HOST_VIDEO_SINGLE:
|
||||
DirectUtils.directToVideoDetail(this, path, VideoDetailContainerViewModel.Location.SINGLE_VIDEO.getValue(),
|
||||
false, "", ENTRANCE_BROWSER, "浏览器", TextUtils.isEmpty(referer) ? "" : referer);
|
||||
break;
|
||||
case HOST_VIDEO_MORE:
|
||||
gameId = uri.getQueryParameter("gameId");
|
||||
String act = uri.getQueryParameter("act");
|
||||
String loaction = TextUtils.isEmpty(act) ? path : VideoDetailContainerViewModel.Location.VIDEO_ACTIVITY.getValue();
|
||||
DirectUtils.directToVideoDetail(this, path, loaction,
|
||||
false, "", ENTRANCE_BROWSER, "浏览器", TextUtils.isEmpty(referer) ? "" : referer, type, act);
|
||||
String fieldId = uri.getQueryParameter("fieldId");
|
||||
String sectionName = uri.getQueryParameter("sectionName");
|
||||
String location;
|
||||
if (!TextUtils.isEmpty(act)) {
|
||||
location = VideoDetailContainerViewModel.Location.VIDEO_ACTIVITY.getValue();
|
||||
} else if (!TextUtils.isEmpty(fieldId)) {
|
||||
location = VideoDetailContainerViewModel.Location.GAME_ZONE.getValue();
|
||||
} else {
|
||||
location = path;
|
||||
}
|
||||
DirectUtils.directToVideoDetail(this, path, location,
|
||||
false, TextUtils.isEmpty(gameId) ? "" : gameId, ENTRANCE_BROWSER, "浏览器", TextUtils.isEmpty(referer) ? "" : referer,
|
||||
TextUtils.isEmpty(type) ? "" : type, TextUtils.isEmpty(act) ? "" : act, TextUtils.isEmpty(fieldId) ? "" : fieldId,
|
||||
TextUtils.isEmpty(sectionName) ? "" : sectionName);
|
||||
break;
|
||||
case HOST_VIDEO_STREAMING_HOME:
|
||||
// 把切换放到 MainActivity 处理
|
||||
@ -230,6 +245,13 @@ public class SkipActivity extends BaseActivity {
|
||||
bundle.putString(KEY_DATA, path);
|
||||
EntranceUtils.jumpActivity(this, bundle);
|
||||
break;
|
||||
case HOST_QQ_QUN:
|
||||
String key = uri.getQueryParameter("key");
|
||||
bundle = new Bundle();
|
||||
bundle.putString(KEY_TO, HOST_QQ_GROUP);
|
||||
bundle.putString(KEY_DATA, key);
|
||||
EntranceUtils.jumpActivity(this, bundle);
|
||||
break;
|
||||
case HOST_WEB:
|
||||
bundle = new Bundle();
|
||||
bundle.putString(KEY_TO, HOST_WEB);
|
||||
@ -279,11 +301,11 @@ public class SkipActivity extends BaseActivity {
|
||||
entity.setLink(path);
|
||||
entity.setName(name);
|
||||
entity.setText(name);
|
||||
DirectUtils.directToBlock(this, entity);
|
||||
DirectUtils.directToBlock(this, entity, mEntrance);
|
||||
break;
|
||||
|
||||
case EntranceUtils.HOST_SERVER_BLOCK:
|
||||
DirectUtils.directToGameServers(this,ENTRANCE_BROWSER, "浏览器");
|
||||
DirectUtils.directToGameServers(this, ENTRANCE_BROWSER, "浏览器");
|
||||
break;
|
||||
|
||||
case EntranceUtils.HOST_AMWAY_BLOCK:
|
||||
@ -302,6 +324,10 @@ public class SkipActivity extends BaseActivity {
|
||||
case EntranceUtils.HOST_GAME_UPLOAD:
|
||||
DirectUtils.directGameUpload(this, ENTRANCE_BROWSER, "浏览器");
|
||||
break;
|
||||
case EntranceUtils.HOST_GAME_ZONE:
|
||||
String zoneUrl = uri.getQueryParameter("url");
|
||||
DirectUtils.directGameZone(this, path, zoneUrl, ENTRANCE_BROWSER);
|
||||
break;
|
||||
|
||||
default:
|
||||
EntranceUtils.jumpActivity(this, new Bundle()); // 跳转至首页
|
||||
|
||||
@ -15,6 +15,12 @@ import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.g00fy2.versioncompare.Version;
|
||||
import com.gh.base.BaseActivity;
|
||||
import com.gh.common.AppExecutor;
|
||||
@ -33,6 +39,7 @@ import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.PlatformUtils;
|
||||
import com.gh.common.util.SPUtils;
|
||||
import com.gh.common.util.TagUtils;
|
||||
import com.gh.common.util.TeaHelper;
|
||||
import com.gh.common.util.UsageStatsHelper;
|
||||
import com.gh.download.DownloadManager;
|
||||
import com.gh.gamecenter.entity.AuthDialogEntity;
|
||||
@ -56,11 +63,6 @@ import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import pub.devrel.easypermissions.AfterPermissionGranted;
|
||||
@ -169,9 +171,7 @@ public class SplashScreenActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
private void requestPermission() {
|
||||
if (EasyPermissions.hasPermissions(this, mPermissions)) {
|
||||
GdtHelper.INSTANCE.logAction(ActionType.START_APP, GdtHelper.NETWORK_TYPE, DeviceUtils.getNetwork(this));
|
||||
} else {
|
||||
if (!EasyPermissions.hasPermissions(this, mPermissions)) {
|
||||
checkAndRequestPermission();
|
||||
}
|
||||
}
|
||||
@ -276,6 +276,10 @@ public class SplashScreenActivity extends BaseActivity {
|
||||
private void launchMainActivity() {
|
||||
getUniqueId();
|
||||
|
||||
// 在可能获取了相关权限后才初始化SDK/发送激活数据
|
||||
TeaHelper.init(getApplication(), HaloApp.getInstance().getChannel());
|
||||
GdtHelper.INSTANCE.logAction(ActionType.START_APP, GdtHelper.NETWORK_TYPE, DeviceUtils.getNetwork(this));
|
||||
|
||||
Bundle bundle = getIntent().getExtras();
|
||||
Intent intent = new Intent(SplashScreenActivity.this, MainActivity.class);
|
||||
if (bundle != null) intent.putExtras(bundle);
|
||||
|
||||
@ -1,482 +1,482 @@
|
||||
package com.gh.gamecenter;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Base64;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager.OnPageChangeListener;
|
||||
|
||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
|
||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
||||
import com.facebook.imagepipeline.core.ImagePipeline;
|
||||
import com.facebook.imagepipeline.request.ImageRequest;
|
||||
import com.gh.base.BaseActivity;
|
||||
import com.gh.common.AppExecutor;
|
||||
import com.gh.common.Base64ImageHolder;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.EntranceUtils;
|
||||
import com.gh.common.util.ImageUtils;
|
||||
import com.gh.common.util.MD5Utils;
|
||||
import com.gh.common.util.MessageShareUtils;
|
||||
import com.gh.common.util.NetworkUtils;
|
||||
import com.gh.common.util.PermissionHelper;
|
||||
import com.gh.common.util.SimpleImageLoader;
|
||||
import com.gh.common.view.Gh_RelativeLayout;
|
||||
import com.gh.common.view.Gh_ViewPager;
|
||||
import com.gh.gamecenter.entity.ImageInfoEntity;
|
||||
import com.gh.gamecenter.retrofit.Response;
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
import com.github.piasy.biv.view.BigImageView;
|
||||
import com.github.piasy.biv.view.FrescoImageViewFactory;
|
||||
import com.lightgame.utils.Utils;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import butterknife.BindView;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
/**
|
||||
* 查看游戏截图页面
|
||||
*
|
||||
* @author 黄壮华
|
||||
*
|
||||
* todo BigImageView静态webp/动态webp(ImageInfoExtractor.getImageType(image))判断有问题,导致部分静态webp无法使用缩放功能
|
||||
*/
|
||||
public class ViewImageActivity extends BaseActivity implements OnPageChangeListener {
|
||||
|
||||
public static final int REQUEST_FOR_VIEWED_IMAGE = 921;
|
||||
public static final String VIEWED_IMAGE = "viewed_image";
|
||||
|
||||
@BindView(R.id.image_detail_page)
|
||||
Gh_ViewPager mViewPager;
|
||||
@BindView(R.id.image_detail_progress)
|
||||
TextView mProgressHint;
|
||||
@BindView(R.id.image_mask)
|
||||
View mIndicatorMask;
|
||||
@BindView(R.id.image_indicator_tv)
|
||||
TextView mIndicatorTv;
|
||||
|
||||
private ViewImageAdapter adapter;
|
||||
|
||||
private ImagePipeline mImagePipeline;
|
||||
|
||||
private boolean mShowBase64Image = false;
|
||||
|
||||
private static final String KEY_BASE64 = "base64";
|
||||
|
||||
private static final String KEY_URLS = "urls";
|
||||
private static final String KEY_CURRENT = "current";
|
||||
|
||||
private ArrayList<String> urls;
|
||||
private HashSet<Integer> mViewedSet; // 让调用者知道该图片是否被看过了
|
||||
private Map<String, ImageInfoEntity> mImageInfoMap;
|
||||
|
||||
private int mLimitWidth;
|
||||
|
||||
private boolean isOrientation;
|
||||
|
||||
public static Intent getBase64ViewImageIntent(Context context, boolean showSingleBase64Image) {
|
||||
Intent checkIntent = new Intent(context, ViewImageActivity.class);
|
||||
checkIntent.putExtra(KEY_BASE64, showSingleBase64Image);
|
||||
return checkIntent;
|
||||
}
|
||||
|
||||
public static Intent getViewImageIntent(Context context, ArrayList<String> list, int position, String entrance) {
|
||||
Intent checkIntent = new Intent(context, ViewImageActivity.class);
|
||||
checkIntent.putExtra(KEY_URLS, list);
|
||||
checkIntent.putExtra(KEY_CURRENT, position);
|
||||
checkIntent.putExtra(EntranceUtils.KEY_ENTRANCE, entrance);
|
||||
return checkIntent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_viewimage;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mViewedSet = new HashSet<>();
|
||||
mImageInfoMap = new HashMap<>();
|
||||
// init data
|
||||
int current = 0;
|
||||
Bundle extras = getIntent().getExtras();
|
||||
if (extras != null) {
|
||||
if (extras.getBoolean(KEY_BASE64)) {
|
||||
mShowBase64Image = true;
|
||||
urls = new ArrayList<>();
|
||||
urls.add(Base64ImageHolder.INSTANCE.getImage());
|
||||
} else {
|
||||
urls = extras.getStringArrayList(KEY_URLS);
|
||||
current = extras.getInt(KEY_CURRENT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
current = savedInstanceState.getInt(EntranceUtils.KEY_CURRENTITEM, 0);
|
||||
isOrientation = savedInstanceState.getBoolean("isOrientation");
|
||||
}
|
||||
|
||||
if (urls.size() > 1) mIndicatorMask.setVisibility(View.VISIBLE);
|
||||
mIndicatorTv.setText(String.format("%d/%d", current + 1, urls.size()));
|
||||
|
||||
mImagePipeline = Fresco.getImagePipeline();
|
||||
|
||||
// init slide
|
||||
DisplayMetrics outMetrics = new DisplayMetrics();
|
||||
getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
|
||||
int widthPixels = outMetrics.widthPixels;
|
||||
if (NetworkUtils.isWifiOr4GConnected(this)) {
|
||||
mLimitWidth = widthPixels * 2;
|
||||
} else {
|
||||
mLimitWidth = widthPixels;
|
||||
}
|
||||
// init viewPage
|
||||
adapter = new ViewImageAdapter();
|
||||
mViewPager.setAdapter(adapter);
|
||||
mViewPager.setCurrentItem(current);
|
||||
mViewPager.addOnPageChangeListener(this);
|
||||
|
||||
if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
isOrientation = true; // 横屏
|
||||
} else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
|
||||
isOrientation = false;// 竖屏
|
||||
}
|
||||
|
||||
mProgressHint.setOnClickListener(v -> {
|
||||
int position = mViewPager.getCurrentItem();
|
||||
Object object = mViewPager.findViewWithTag(position);
|
||||
if (object != null) {
|
||||
mProgressHint.setWidth(mProgressHint.getWidth());
|
||||
RelativeLayout view = (RelativeLayout) object;
|
||||
final BigImageView imageView = view.findViewById(R.id.viewimage_iv_show);
|
||||
String url = urls.get(position);
|
||||
imageView.showImage(Uri.parse(url));
|
||||
imageView.setImageLoaderCallback(new SimpleImageLoader() {
|
||||
@Override
|
||||
public void onProgress(int progress) {
|
||||
if (position == mViewPager.getCurrentItem()) { // 防止下载过程中切换图片
|
||||
if (progress < 100) {
|
||||
mProgressHint.setText((progress + "%"));
|
||||
} else {
|
||||
mProgressHint.setText("已完成");
|
||||
mBaseHandler.postDelayed(() -> {
|
||||
if (position == mViewPager.getCurrentItem()) { // 防止等待过程中切换图片
|
||||
mProgressHint.setVisibility(View.GONE);
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
DisplayUtils.transparentStatusAndNavigation(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putInt(EntranceUtils.KEY_CURRENTITEM, mViewPager.getCurrentItem());
|
||||
outState.putBoolean("isOrientation", isOrientation);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mShowBase64Image) {
|
||||
urls.clear();
|
||||
Base64ImageHolder.INSTANCE.setImage("");
|
||||
}
|
||||
mViewPager.onDestroy(); // 注销EventBus
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset,
|
||||
int positionOffsetPixels) {
|
||||
if (positionOffset != 0) {
|
||||
mProgressHint.setVisibility(View.GONE);
|
||||
} else {
|
||||
String url = urls.get(position);
|
||||
ImageInfoEntity imageInfoEntity = mImageInfoMap.get(url);
|
||||
if (imageInfoEntity != null && imageInfoEntity.getFileSize() != null &&
|
||||
!mImagePipeline.isInBitmapMemoryCache(ImageRequest.fromUri(url)) &&
|
||||
!mImagePipeline.isInDiskCacheSync(ImageRequest.fromUri(url))) {
|
||||
String size = String.format(Locale.CHINA, "%.1fM",
|
||||
Integer.valueOf(imageInfoEntity.getFileSize().getValue()) / 1024F / 1024F);
|
||||
mProgressHint.setVisibility(View.VISIBLE);
|
||||
mProgressHint.setText(("查看原图(" + size + ")"));
|
||||
ViewGroup.LayoutParams layoutParams = mProgressHint.getLayoutParams();
|
||||
layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
mProgressHint.setLayoutParams(layoutParams);
|
||||
}
|
||||
}
|
||||
|
||||
mViewedSet.add(position);
|
||||
setResult(Activity.RESULT_OK, new Intent().putExtra(VIEWED_IMAGE, mViewedSet));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
Gh_RelativeLayout ghRelativeLayout;
|
||||
for (int i = 0; i < mViewPager.getChildCount(); i++) {
|
||||
if (mViewPager.getChildAt(i).getTag() != null) {
|
||||
ghRelativeLayout = (Gh_RelativeLayout) mViewPager.getChildAt(i);
|
||||
if (ghRelativeLayout == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
BigImageView imageView = ghRelativeLayout.findViewById(R.id.viewimage_iv_show);
|
||||
SubsamplingScaleImageView ssiv = imageView.getSSIV();
|
||||
if (ssiv != null) ssiv.resetScaleAndCenter();
|
||||
|
||||
}
|
||||
}
|
||||
mIndicatorTv.setText(String.format("%d/%d", position + 1, urls.size()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int newState) {
|
||||
|
||||
}
|
||||
|
||||
private void loadImageInfo(int position, int width) {
|
||||
String url = urls.get(position);
|
||||
RetrofitManager.getInstance(this)
|
||||
.getApi().getImageInfo(url + "?x-oss-process=image/info")
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<ImageInfoEntity>() {
|
||||
@Override
|
||||
public void onResponse(@Nullable ImageInfoEntity response) {
|
||||
if (response != null && response.getImageWidth() != null &&
|
||||
Integer.valueOf(response.getImageWidth().getValue()) > width) {
|
||||
mImageInfoMap.put(url, response);
|
||||
if (position == mViewPager.getCurrentItem()) {
|
||||
onPageScrolled(position, 0, 0); // 刷新下载原图提示按钮
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void loadImage(String url, final BigImageView imageView) {
|
||||
if (TextUtils.isEmpty(url)) return;
|
||||
|
||||
if (url.startsWith("data:image/png;base64")) {
|
||||
AppExecutor.getIoExecutor().execute(() -> {
|
||||
String base64String = url.replace("data:image/png;base64", "");
|
||||
try {
|
||||
File imageFile = new File(getCacheDir().getAbsolutePath() + File.separator + System.currentTimeMillis() + ".png");
|
||||
|
||||
byte[] decodedString = Base64.decode(base64String, Base64.DEFAULT);
|
||||
|
||||
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(imageFile));
|
||||
bos.write(decodedString);
|
||||
bos.flush();
|
||||
bos.close();
|
||||
|
||||
AppExecutor.getUiExecutor().execute(() -> {
|
||||
imageView.setImageViewFactory(new FrescoImageViewFactory());
|
||||
imageView.showImage(Uri.fromFile(imageFile));
|
||||
});
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 添加GIF支持
|
||||
imageView.setImageViewFactory(new FrescoImageViewFactory());
|
||||
imageView.showImage(Uri.parse(url));
|
||||
}
|
||||
}
|
||||
|
||||
private class ViewImageAdapter extends PagerAdapter {
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
if (urls == null) {
|
||||
return 0;
|
||||
}
|
||||
return urls.size();
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@NonNull
|
||||
@Override
|
||||
public Object instantiateItem(@NonNull ViewGroup container, int position) {
|
||||
String url = urls.get(position);
|
||||
ImageRequest imageRequest = ImageRequest.fromUri(url);
|
||||
boolean isInMemoryCache = mImagePipeline.isInBitmapMemoryCache(imageRequest);
|
||||
boolean isInDiskCache = imageRequest != null && mImagePipeline.isInDiskCacheSync(imageRequest);
|
||||
|
||||
Gh_RelativeLayout view = (Gh_RelativeLayout) View.inflate(container.getContext(), R.layout.viewimage_normal_item, null);
|
||||
BigImageView imageView = view.findViewById(R.id.viewimage_iv_show);
|
||||
|
||||
if (!isInMemoryCache
|
||||
&& !isInDiskCache
|
||||
&& !NetworkUtils.isWifiOr4GConnected(ViewImageActivity.this)
|
||||
&& !url.contains(".gif")) {
|
||||
url = ImageUtils.getTransformLimitUrl(url, mLimitWidth, getApplicationContext());
|
||||
}
|
||||
|
||||
String finalUrl = url;
|
||||
imageView.setImageLoaderCallback(new SimpleImageLoader() {
|
||||
@Override
|
||||
public void onSuccess(File image) {
|
||||
if (!finalUrl.equals(urls.get(position))) {
|
||||
BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
options.inJustDecodeBounds = true;
|
||||
BitmapFactory.decodeFile(new File(image.getPath()).getAbsolutePath(), options);
|
||||
loadImageInfo(position, options.outWidth); // 加载图片参数,目的是用户显示原文按钮
|
||||
}
|
||||
SubsamplingScaleImageView ssiv = imageView.getSSIV();
|
||||
if (ssiv != null) {
|
||||
ssiv.setMaxScale(10f); // 这个缩放倍数最好很具宽高自动调节
|
||||
ssiv.setOnImageEventListener(new SubsamplingScaleImageView.DefaultOnImageEventListener() {
|
||||
@Override
|
||||
public void onReady() {
|
||||
ssiv.resetScaleAndCenter();
|
||||
}
|
||||
});
|
||||
ssiv.setOnClickListener(v -> finish());
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
loadImage(url, imageView);
|
||||
|
||||
//长按
|
||||
imageView.setOnLongClickListener(v -> {
|
||||
final Dialog dialog = new Dialog(ViewImageActivity.this);
|
||||
|
||||
LinearLayout container1 = new LinearLayout(ViewImageActivity.this);
|
||||
container1.setOrientation(LinearLayout.VERTICAL);
|
||||
container1.setBackgroundColor(Color.WHITE);
|
||||
|
||||
final TextView reportTv = new TextView(ViewImageActivity.this);
|
||||
reportTv.setPadding(
|
||||
DisplayUtils.dip2px(ViewImageActivity.this, 20),
|
||||
DisplayUtils.dip2px(ViewImageActivity.this, 12),
|
||||
0,
|
||||
DisplayUtils.dip2px(ViewImageActivity.this, 12));
|
||||
reportTv.setText(R.string.save_pic);
|
||||
reportTv.setTextSize(17);
|
||||
reportTv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.title));
|
||||
reportTv.setBackgroundResource(R.drawable.textview_white_style);
|
||||
int widthPixels = getResources().getDisplayMetrics().widthPixels;
|
||||
reportTv.setLayoutParams(new LinearLayout.LayoutParams((widthPixels * 9) / 10,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT));
|
||||
container1.addView(reportTv);
|
||||
|
||||
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
dialog.setContentView(container1);
|
||||
|
||||
if (!isFinishing()) {
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
reportTv.setOnClickListener(v1 -> {
|
||||
PermissionHelper.checkStoragePermissionBeforeAction(ViewImageActivity.this, () -> {
|
||||
saveImageToFile(imageView.getCurrentImageFile(), finalUrl);
|
||||
dialog.cancel();
|
||||
});
|
||||
dialog.cancel();
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
view.setTag(position);
|
||||
container.addView(view);
|
||||
return view;
|
||||
}
|
||||
|
||||
private void saveImageToFile(File src, String curUrl) {
|
||||
InputStream in = null;
|
||||
OutputStream out = null;
|
||||
try {
|
||||
String fileName;
|
||||
if (mShowBase64Image) {
|
||||
fileName = MD5Utils.getUrlMD5(curUrl.substring(0, 50)) + ".png";
|
||||
} else {
|
||||
fileName = curUrl.substring(curUrl.lastIndexOf("/"));
|
||||
}
|
||||
String savePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Pictures/ghzhushou/";
|
||||
File file = new File(savePath);
|
||||
if (!file.exists()) {
|
||||
file.mkdirs();
|
||||
}
|
||||
|
||||
File dst = new File(savePath, fileName);
|
||||
if (dst.exists()) {
|
||||
dst.delete();
|
||||
}
|
||||
|
||||
in = new FileInputStream(src);
|
||||
out = new FileOutputStream(dst);
|
||||
byte[] buf = new byte[1024];
|
||||
int len;
|
||||
while ((len = in.read(buf)) > 0) {
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
|
||||
Utils.toast(ViewImageActivity.this, "图片已保存到/Pictures/ghzhushou/");
|
||||
MessageShareUtils.refreshImage(ViewImageActivity.this, dst);
|
||||
} catch (Exception e) {
|
||||
Utils.log("图片保存失败:" + e.toString());
|
||||
} finally {
|
||||
try {
|
||||
if (out != null) out.close();
|
||||
if (in != null) in.close();
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
|
||||
container.removeView((View) object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
|
||||
return view == object;
|
||||
}
|
||||
}
|
||||
}
|
||||
//package com.gh.gamecenter;
|
||||
//
|
||||
//import android.annotation.SuppressLint;
|
||||
//import android.app.Activity;
|
||||
//import android.app.Dialog;
|
||||
//import android.content.Context;
|
||||
//import android.content.Intent;
|
||||
//import android.content.res.Configuration;
|
||||
//import android.graphics.BitmapFactory;
|
||||
//import android.graphics.Color;
|
||||
//import android.net.Uri;
|
||||
//import android.os.Bundle;
|
||||
//import android.os.Environment;
|
||||
//import android.text.TextUtils;
|
||||
//import android.util.Base64;
|
||||
//import android.util.DisplayMetrics;
|
||||
//import android.view.View;
|
||||
//import android.view.ViewGroup;
|
||||
//import android.view.Window;
|
||||
//import android.widget.LinearLayout;
|
||||
//import android.widget.RelativeLayout;
|
||||
//import android.widget.TextView;
|
||||
//
|
||||
//import androidx.annotation.NonNull;
|
||||
//import androidx.annotation.Nullable;
|
||||
//import androidx.core.content.ContextCompat;
|
||||
//import androidx.viewpager.widget.PagerAdapter;
|
||||
//import androidx.viewpager.widget.ViewPager.OnPageChangeListener;
|
||||
//
|
||||
//import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
|
||||
//import com.facebook.drawee.backends.pipeline.Fresco;
|
||||
//import com.facebook.imagepipeline.core.ImagePipeline;
|
||||
//import com.facebook.imagepipeline.request.ImageRequest;
|
||||
//import com.gh.base.BaseActivity;
|
||||
//import com.gh.common.AppExecutor;
|
||||
//import com.gh.common.Base64ImageHolder;
|
||||
//import com.gh.common.util.DisplayUtils;
|
||||
//import com.gh.common.util.EntranceUtils;
|
||||
//import com.gh.common.util.ImageUtils;
|
||||
//import com.gh.common.util.MD5Utils;
|
||||
//import com.gh.common.util.MessageShareUtils;
|
||||
//import com.gh.common.util.NetworkUtils;
|
||||
//import com.gh.common.util.PermissionHelper;
|
||||
//import com.gh.common.util.SimpleImageLoader;
|
||||
//import com.gh.common.view.Gh_RelativeLayout;
|
||||
//import com.gh.common.view.Gh_ViewPager;
|
||||
//import com.gh.gamecenter.entity.ImageInfoEntity;
|
||||
//import com.gh.gamecenter.retrofit.Response;
|
||||
//import com.gh.gamecenter.retrofit.RetrofitManager;
|
||||
//import com.github.piasy.biv.view.BigImageView;
|
||||
//import com.github.piasy.biv.view.FrescoImageViewFactory;
|
||||
//import com.lightgame.utils.Utils;
|
||||
//
|
||||
//import java.io.BufferedOutputStream;
|
||||
//import java.io.File;
|
||||
//import java.io.FileInputStream;
|
||||
//import java.io.FileOutputStream;
|
||||
//import java.io.InputStream;
|
||||
//import java.io.OutputStream;
|
||||
//import java.util.ArrayList;
|
||||
//import java.util.HashMap;
|
||||
//import java.util.HashSet;
|
||||
//import java.util.Locale;
|
||||
//import java.util.Map;
|
||||
//
|
||||
//import butterknife.BindView;
|
||||
//import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
//import io.reactivex.schedulers.Schedulers;
|
||||
//
|
||||
///**
|
||||
// * 查看游戏截图页面
|
||||
// *
|
||||
// * @author 黄壮华
|
||||
// *
|
||||
// * todo BigImageView静态webp/动态webp(ImageInfoExtractor.getImageType(image))判断有问题,导致部分静态webp无法使用缩放功能
|
||||
// */
|
||||
//public class ViewImageActivity extends BaseActivity implements OnPageChangeListener {
|
||||
//
|
||||
// public static final int REQUEST_FOR_VIEWED_IMAGE = 921;
|
||||
// public static final String VIEWED_IMAGE = "viewed_image";
|
||||
//
|
||||
// @BindView(R.id.image_detail_page)
|
||||
// Gh_ViewPager mViewPager;
|
||||
// @BindView(R.id.image_detail_progress)
|
||||
// TextView mProgressHint;
|
||||
// @BindView(R.id.image_mask)
|
||||
// View mIndicatorMask;
|
||||
// @BindView(R.id.image_indicator_tv)
|
||||
// TextView mIndicatorTv;
|
||||
//
|
||||
// private ViewImageAdapter adapter;
|
||||
//
|
||||
// private ImagePipeline mImagePipeline;
|
||||
//
|
||||
// private boolean mShowBase64Image = false;
|
||||
//
|
||||
// private static final String KEY_BASE64 = "base64";
|
||||
//
|
||||
// private static final String KEY_URLS = "urls";
|
||||
// private static final String KEY_CURRENT = "current";
|
||||
//
|
||||
// private ArrayList<String> urls;
|
||||
// private HashSet<Integer> mViewedSet; // 让调用者知道该图片是否被看过了
|
||||
// private Map<String, ImageInfoEntity> mImageInfoMap;
|
||||
//
|
||||
// private int mLimitWidth;
|
||||
//
|
||||
// private boolean isOrientation;
|
||||
//
|
||||
// public static Intent getBase64ViewImageIntent(Context context, boolean showSingleBase64Image) {
|
||||
// Intent checkIntent = new Intent(context, ViewImageActivity.class);
|
||||
// checkIntent.putExtra(KEY_BASE64, showSingleBase64Image);
|
||||
// return checkIntent;
|
||||
// }
|
||||
//
|
||||
// public static Intent getViewImageIntent(Context context, ArrayList<String> list, int position, String entrance) {
|
||||
// Intent checkIntent = new Intent(context, ViewImageActivity.class);
|
||||
// checkIntent.putExtra(KEY_URLS, list);
|
||||
// checkIntent.putExtra(KEY_CURRENT, position);
|
||||
// checkIntent.putExtra(EntranceUtils.KEY_ENTRANCE, entrance);
|
||||
// return checkIntent;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected int getLayoutId() {
|
||||
// return R.layout.activity_viewimage;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void onCreate(Bundle savedInstanceState) {
|
||||
// super.onCreate(savedInstanceState);
|
||||
// mViewedSet = new HashSet<>();
|
||||
// mImageInfoMap = new HashMap<>();
|
||||
// // init data
|
||||
// int current = 0;
|
||||
// Bundle extras = getIntent().getExtras();
|
||||
// if (extras != null) {
|
||||
// if (extras.getBoolean(KEY_BASE64)) {
|
||||
// mShowBase64Image = true;
|
||||
// urls = new ArrayList<>();
|
||||
// urls.add(Base64ImageHolder.INSTANCE.getImage());
|
||||
// } else {
|
||||
// urls = extras.getStringArrayList(KEY_URLS);
|
||||
// current = extras.getInt(KEY_CURRENT, 0);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (savedInstanceState != null) {
|
||||
// current = savedInstanceState.getInt(EntranceUtils.KEY_CURRENTITEM, 0);
|
||||
// isOrientation = savedInstanceState.getBoolean("isOrientation");
|
||||
// }
|
||||
//
|
||||
// if (urls.size() > 1) mIndicatorMask.setVisibility(View.VISIBLE);
|
||||
// mIndicatorTv.setText(String.format("%d/%d", current + 1, urls.size()));
|
||||
//
|
||||
// mImagePipeline = Fresco.getImagePipeline();
|
||||
//
|
||||
// // init slide
|
||||
// DisplayMetrics outMetrics = new DisplayMetrics();
|
||||
// getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
|
||||
// int widthPixels = outMetrics.widthPixels;
|
||||
// if (NetworkUtils.isWifiOr4GConnected(this)) {
|
||||
// mLimitWidth = widthPixels * 2;
|
||||
// } else {
|
||||
// mLimitWidth = widthPixels;
|
||||
// }
|
||||
// // init viewPage
|
||||
// adapter = new ViewImageAdapter();
|
||||
// mViewPager.setAdapter(adapter);
|
||||
// mViewPager.setCurrentItem(current);
|
||||
// mViewPager.addOnPageChangeListener(this);
|
||||
//
|
||||
// if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
// isOrientation = true; // 横屏
|
||||
// } else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
|
||||
// isOrientation = false;// 竖屏
|
||||
// }
|
||||
//
|
||||
// mProgressHint.setOnClickListener(v -> {
|
||||
// int position = mViewPager.getCurrentItem();
|
||||
// Object object = mViewPager.findViewWithTag(position);
|
||||
// if (object != null) {
|
||||
// mProgressHint.setWidth(mProgressHint.getWidth());
|
||||
// RelativeLayout view = (RelativeLayout) object;
|
||||
// final BigImageView imageView = view.findViewById(R.id.viewimage_iv_show);
|
||||
// String url = urls.get(position);
|
||||
// imageView.showImage(Uri.parse(url));
|
||||
// imageView.setImageLoaderCallback(new SimpleImageLoader() {
|
||||
// @Override
|
||||
// public void onProgress(int progress) {
|
||||
// if (position == mViewPager.getCurrentItem()) { // 防止下载过程中切换图片
|
||||
// if (progress < 100) {
|
||||
// mProgressHint.setText((progress + "%"));
|
||||
// } else {
|
||||
// mProgressHint.setText("已完成");
|
||||
// mBaseHandler.postDelayed(() -> {
|
||||
// if (position == mViewPager.getCurrentItem()) { // 防止等待过程中切换图片
|
||||
// mProgressHint.setVisibility(View.GONE);
|
||||
// }
|
||||
// }, 500);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// DisplayUtils.transparentStatusAndNavigation(this);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void onSaveInstanceState(Bundle outState) {
|
||||
// super.onSaveInstanceState(outState);
|
||||
// outState.putInt(EntranceUtils.KEY_CURRENTITEM, mViewPager.getCurrentItem());
|
||||
// outState.putBoolean("isOrientation", isOrientation);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void onDestroy() {
|
||||
// super.onDestroy();
|
||||
// if (mShowBase64Image) {
|
||||
// urls.clear();
|
||||
// Base64ImageHolder.INSTANCE.setImage("");
|
||||
// }
|
||||
// mViewPager.onDestroy(); // 注销EventBus
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onPageScrolled(int position, float positionOffset,
|
||||
// int positionOffsetPixels) {
|
||||
// if (positionOffset != 0) {
|
||||
// mProgressHint.setVisibility(View.GONE);
|
||||
// } else {
|
||||
// String url = urls.get(position);
|
||||
// ImageInfoEntity imageInfoEntity = mImageInfoMap.get(url);
|
||||
// if (imageInfoEntity != null && imageInfoEntity.getFileSize() != null &&
|
||||
// !mImagePipeline.isInBitmapMemoryCache(ImageRequest.fromUri(url)) &&
|
||||
// !mImagePipeline.isInDiskCacheSync(ImageRequest.fromUri(url))) {
|
||||
// String size = String.format(Locale.CHINA, "%.1fM",
|
||||
// Integer.valueOf(imageInfoEntity.getFileSize().getValue()) / 1024F / 1024F);
|
||||
// mProgressHint.setVisibility(View.VISIBLE);
|
||||
// mProgressHint.setText(("查看原图(" + size + ")"));
|
||||
// ViewGroup.LayoutParams layoutParams = mProgressHint.getLayoutParams();
|
||||
// layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
// mProgressHint.setLayoutParams(layoutParams);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// mViewedSet.add(position);
|
||||
// setResult(Activity.RESULT_OK, new Intent().putExtra(VIEWED_IMAGE, mViewedSet));
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onPageSelected(int position) {
|
||||
// Gh_RelativeLayout ghRelativeLayout;
|
||||
// for (int i = 0; i < mViewPager.getChildCount(); i++) {
|
||||
// if (mViewPager.getChildAt(i).getTag() != null) {
|
||||
// ghRelativeLayout = (Gh_RelativeLayout) mViewPager.getChildAt(i);
|
||||
// if (ghRelativeLayout == null) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// BigImageView imageView = ghRelativeLayout.findViewById(R.id.viewimage_iv_show);
|
||||
// SubsamplingScaleImageView ssiv = imageView.getSSIV();
|
||||
// if (ssiv != null) ssiv.resetScaleAndCenter();
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// mIndicatorTv.setText(String.format("%d/%d", position + 1, urls.size()));
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onPageScrollStateChanged(int newState) {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// private void loadImageInfo(int position, int width) {
|
||||
// String url = urls.get(position);
|
||||
// RetrofitManager.getInstance(this)
|
||||
// .getApi().getImageInfo(url + "?x-oss-process=image/info")
|
||||
// .subscribeOn(Schedulers.io())
|
||||
// .observeOn(AndroidSchedulers.mainThread())
|
||||
// .subscribe(new Response<ImageInfoEntity>() {
|
||||
// @Override
|
||||
// public void onResponse(@Nullable ImageInfoEntity response) {
|
||||
// if (response != null && response.getImageWidth() != null &&
|
||||
// Integer.valueOf(response.getImageWidth().getValue()) > width) {
|
||||
// mImageInfoMap.put(url, response);
|
||||
// if (position == mViewPager.getCurrentItem()) {
|
||||
// onPageScrolled(position, 0, 0); // 刷新下载原图提示按钮
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// private void loadImage(String url, final BigImageView imageView) {
|
||||
// if (TextUtils.isEmpty(url)) return;
|
||||
//
|
||||
// if (url.startsWith("data:image/png;base64")) {
|
||||
// AppExecutor.getIoExecutor().execute(() -> {
|
||||
// String base64String = url.replace("data:image/png;base64", "");
|
||||
// try {
|
||||
// File imageFile = new File(getCacheDir().getAbsolutePath() + File.separator + System.currentTimeMillis() + ".png");
|
||||
//
|
||||
// byte[] decodedString = Base64.decode(base64String, Base64.DEFAULT);
|
||||
//
|
||||
// BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(imageFile));
|
||||
// bos.write(decodedString);
|
||||
// bos.flush();
|
||||
// bos.close();
|
||||
//
|
||||
// AppExecutor.getUiExecutor().execute(() -> {
|
||||
// imageView.setImageViewFactory(new FrescoImageViewFactory());
|
||||
// imageView.showImage(Uri.fromFile(imageFile));
|
||||
// });
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// });
|
||||
// } else {
|
||||
// // 添加GIF支持
|
||||
// imageView.setImageViewFactory(new FrescoImageViewFactory());
|
||||
// imageView.showImage(Uri.parse(url));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private class ViewImageAdapter extends PagerAdapter {
|
||||
//
|
||||
// @Override
|
||||
// public int getCount() {
|
||||
// if (urls == null) {
|
||||
// return 0;
|
||||
// }
|
||||
// return urls.size();
|
||||
// }
|
||||
//
|
||||
// @SuppressLint("MissingPermission")
|
||||
// @NonNull
|
||||
// @Override
|
||||
// public Object instantiateItem(@NonNull ViewGroup container, int position) {
|
||||
// String url = urls.get(position);
|
||||
// ImageRequest imageRequest = ImageRequest.fromUri(url);
|
||||
// boolean isInMemoryCache = mImagePipeline.isInBitmapMemoryCache(imageRequest);
|
||||
// boolean isInDiskCache = imageRequest != null && mImagePipeline.isInDiskCacheSync(imageRequest);
|
||||
//
|
||||
// Gh_RelativeLayout view = (Gh_RelativeLayout) View.inflate(container.getContext(), R.layout.viewimage_normal_item, null);
|
||||
// BigImageView imageView = view.findViewById(R.id.viewimage_iv_show);
|
||||
//
|
||||
// if (!isInMemoryCache
|
||||
// && !isInDiskCache
|
||||
// && !NetworkUtils.isWifiOr4GConnected(ViewImageActivity.this)
|
||||
// && !url.contains(".gif")) {
|
||||
// url = ImageUtils.getTransformLimitUrl(url, mLimitWidth, getApplicationContext());
|
||||
// }
|
||||
//
|
||||
// String finalUrl = url;
|
||||
// imageView.setImageLoaderCallback(new SimpleImageLoader() {
|
||||
// @Override
|
||||
// public void onSuccess(File image) {
|
||||
// if (!finalUrl.equals(urls.get(position))) {
|
||||
// BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
// options.inJustDecodeBounds = true;
|
||||
// BitmapFactory.decodeFile(new File(image.getPath()).getAbsolutePath(), options);
|
||||
// loadImageInfo(position, options.outWidth); // 加载图片参数,目的是用户显示原文按钮
|
||||
// }
|
||||
// SubsamplingScaleImageView ssiv = imageView.getSSIV();
|
||||
// if (ssiv != null) {
|
||||
// ssiv.setMaxScale(10f); // 这个缩放倍数最好很具宽高自动调节
|
||||
// ssiv.setOnImageEventListener(new SubsamplingScaleImageView.DefaultOnImageEventListener() {
|
||||
// @Override
|
||||
// public void onReady() {
|
||||
// ssiv.resetScaleAndCenter();
|
||||
// }
|
||||
// });
|
||||
// ssiv.setOnClickListener(v -> finish());
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// loadImage(url, imageView);
|
||||
//
|
||||
// //长按
|
||||
// imageView.setOnLongClickListener(v -> {
|
||||
// final Dialog dialog = new Dialog(ViewImageActivity.this);
|
||||
//
|
||||
// LinearLayout container1 = new LinearLayout(ViewImageActivity.this);
|
||||
// container1.setOrientation(LinearLayout.VERTICAL);
|
||||
// container1.setBackgroundColor(Color.WHITE);
|
||||
//
|
||||
// final TextView reportTv = new TextView(ViewImageActivity.this);
|
||||
// reportTv.setPadding(
|
||||
// DisplayUtils.dip2px(ViewImageActivity.this, 20),
|
||||
// DisplayUtils.dip2px(ViewImageActivity.this, 12),
|
||||
// 0,
|
||||
// DisplayUtils.dip2px(ViewImageActivity.this, 12));
|
||||
// reportTv.setText(R.string.save_pic);
|
||||
// reportTv.setTextSize(17);
|
||||
// reportTv.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.title));
|
||||
// reportTv.setBackgroundResource(R.drawable.textview_white_style);
|
||||
// int widthPixels = getResources().getDisplayMetrics().widthPixels;
|
||||
// reportTv.setLayoutParams(new LinearLayout.LayoutParams((widthPixels * 9) / 10,
|
||||
// LinearLayout.LayoutParams.WRAP_CONTENT));
|
||||
// container1.addView(reportTv);
|
||||
//
|
||||
// dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
// dialog.setContentView(container1);
|
||||
//
|
||||
// if (!isFinishing()) {
|
||||
// dialog.show();
|
||||
// }
|
||||
//
|
||||
// reportTv.setOnClickListener(v1 -> {
|
||||
// PermissionHelper.checkStoragePermissionBeforeAction(ViewImageActivity.this, () -> {
|
||||
// saveImageToFile(imageView.getCurrentImageFile(), finalUrl);
|
||||
// dialog.cancel();
|
||||
// });
|
||||
// dialog.cancel();
|
||||
// });
|
||||
//
|
||||
// return false;
|
||||
// });
|
||||
//
|
||||
// view.setTag(position);
|
||||
// container.addView(view);
|
||||
// return view;
|
||||
// }
|
||||
//
|
||||
// private void saveImageToFile(File src, String curUrl) {
|
||||
// InputStream in = null;
|
||||
// OutputStream out = null;
|
||||
// try {
|
||||
// String fileName;
|
||||
// if (mShowBase64Image) {
|
||||
// fileName = MD5Utils.getUrlMD5(curUrl.substring(0, 50)) + ".png";
|
||||
// } else {
|
||||
// fileName = curUrl.substring(curUrl.lastIndexOf("/"));
|
||||
// }
|
||||
// String savePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Pictures/ghzhushou/";
|
||||
// File file = new File(savePath);
|
||||
// if (!file.exists()) {
|
||||
// file.mkdirs();
|
||||
// }
|
||||
//
|
||||
// File dst = new File(savePath, fileName);
|
||||
// if (dst.exists()) {
|
||||
// dst.delete();
|
||||
// }
|
||||
//
|
||||
// in = new FileInputStream(src);
|
||||
// out = new FileOutputStream(dst);
|
||||
// byte[] buf = new byte[1024];
|
||||
// int len;
|
||||
// while ((len = in.read(buf)) > 0) {
|
||||
// out.write(buf, 0, len);
|
||||
// }
|
||||
//
|
||||
// Utils.toast(ViewImageActivity.this, "图片已保存到/Pictures/ghzhushou/");
|
||||
// MessageShareUtils.refreshImage(ViewImageActivity.this, dst);
|
||||
// } catch (Exception e) {
|
||||
// Utils.log("图片保存失败:" + e.toString());
|
||||
// } finally {
|
||||
// try {
|
||||
// if (out != null) out.close();
|
||||
// if (in != null) in.close();
|
||||
// } catch (Exception ignore) {
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// @Override
|
||||
// public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
|
||||
// container.removeView((View) object);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
|
||||
// return view == object;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
@ -227,11 +227,12 @@ public class WebActivity extends NormalActivity {
|
||||
return getTargetIntent(context, WebActivity.class, WebFragment.class, bundle);
|
||||
}
|
||||
|
||||
public static Intent getIntentForWebGame(Context context, String url, String gameName, boolean interveneBackpress) {
|
||||
public static Intent getIntentForWebGame(Context context, String url, String gameName, boolean interveneBackpress, String closeButton) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(EntranceUtils.KEY_URL, url);
|
||||
bundle.putString(KEY_GAME_NAME, gameName);
|
||||
bundle.putBoolean(WebFragment.KEY_LEAVE_WEB_PAGE_TO_HANDLE_TITLE, true);
|
||||
bundle.putString(WebFragment.KEY_CLOSE_BUTTON, closeButton);
|
||||
if (interveneBackpress) {
|
||||
bundle.putBoolean(KEY_REQUIRE_BACK_CONFIRMATION, true);
|
||||
bundle.putString(WebFragment.KEY_BACK_CONFIRMATION_CONTENT, "退出后将不保存当前游戏进度,确定退出吗?");
|
||||
|
||||
@ -7,10 +7,9 @@ import android.graphics.Bitmap;
|
||||
import android.media.ThumbnailUtils;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.facebook.common.references.CloseableReference;
|
||||
import com.facebook.datasource.DataSource;
|
||||
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber;
|
||||
import com.facebook.imagepipeline.image.CloseableImage;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.gh.common.util.BiCallback;
|
||||
import com.gh.common.util.ImageUtils;
|
||||
import com.gh.common.util.LogUtils;
|
||||
import com.gh.common.util.ShareUtils;
|
||||
@ -26,8 +25,6 @@ import com.sina.weibo.sdk.utils.Utility;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Created by khy on 2016/11/23.
|
||||
* <p>
|
||||
@ -80,7 +77,7 @@ public class WeiBoShareActivity extends Activity implements WbShareCallback {
|
||||
mWeiboShareAPI = new WbShareHandler(this);
|
||||
mWeiboShareAPI.registerApp();
|
||||
|
||||
weiboLoadBitMap(shareIcon);
|
||||
loadIconAndShare(shareIcon);
|
||||
}
|
||||
|
||||
|
||||
@ -89,10 +86,10 @@ public class WeiBoShareActivity extends Activity implements WbShareCallback {
|
||||
mWeiboShareAPI.doResultIntent(intent, this); //当前应用唤起微博分享后,返回当前应用
|
||||
}
|
||||
|
||||
private void weiboLoadBitMap(String iconUrl) {
|
||||
ImageUtils.display(this, iconUrl, new BaseBitmapDataSubscriber() {
|
||||
private void loadIconAndShare(String iconUrl) {
|
||||
ImageUtils.getBitmap(iconUrl, new BiCallback<Bitmap, Boolean>() {
|
||||
@Override
|
||||
protected void onNewResultImpl(Bitmap bitmap) {
|
||||
public void onFirst(Bitmap bitmap) {
|
||||
Utils.log("分享获取bitmap成功,准备分享");
|
||||
|
||||
if (ShareUtils.ShareEntrance.video.name().equals(mShareType)) {
|
||||
@ -144,8 +141,7 @@ public class WeiBoShareActivity extends Activity implements WbShareCallback {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFailureImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
|
||||
Utils.log("分享获取bitmap失败");
|
||||
public void onSecond(Boolean aBoolean) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -11,9 +11,12 @@ import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.collection.ArrayMap;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.gh.common.util.BitmapUtils;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.PackageInstaller;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.adapter.viewholder.KcSelectGameViewHolder;
|
||||
import com.gh.gamecenter.entity.InstallGameEntity;
|
||||
@ -28,8 +31,6 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.collection.ArrayMap;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.ObservableEmitter;
|
||||
import io.reactivex.ObservableOnSubscribe;
|
||||
@ -74,17 +75,17 @@ public class CleanApkAdapter extends BaseRecyclerAdapter<KcSelectGameViewHolder>
|
||||
|
||||
private void init() {
|
||||
Observable.create(new ObservableOnSubscribe<Object>() {
|
||||
@Override
|
||||
public void subscribe(ObservableEmitter<Object> emitter) {
|
||||
// 扫描和获取apk数据 分步操作 尽量避免 StackoverflowError
|
||||
FindAllAPKPath(Environment.getExternalStorageDirectory());
|
||||
LoadApkData();
|
||||
emitter.onComplete();
|
||||
}
|
||||
})
|
||||
@Override
|
||||
public void subscribe(ObservableEmitter<Object> emitter) {
|
||||
// 扫描和获取apk数据 分步操作 尽量避免 StackoverflowError
|
||||
FindAllAPKPath(Environment.getExternalStorageDirectory());
|
||||
LoadApkData();
|
||||
emitter.onComplete();
|
||||
}
|
||||
})
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Response<Object>(){
|
||||
.subscribe(new Response<Object>() {
|
||||
@Override
|
||||
public void onComplete() {
|
||||
super.onComplete();
|
||||
@ -264,7 +265,7 @@ public class CleanApkAdapter extends BaseRecyclerAdapter<KcSelectGameViewHolder>
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mIsScanOver) {
|
||||
mContext.startActivity(PackageUtils.getInstallIntent(mContext, gameEntity.getGamePath()));
|
||||
mContext.startActivity(PackageInstaller.getInstallIntent(mContext, gameEntity.getGamePath()));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -9,6 +9,8 @@ import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.common.exposure.ExposureEvent;
|
||||
import com.gh.common.exposure.ExposureSource;
|
||||
@ -27,8 +29,6 @@ import com.gh.gamecenter.game.data.GameItemData;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* ImagePagerAdapter
|
||||
*
|
||||
@ -100,10 +100,10 @@ public class ImagePagerAdapter extends RecyclingPagerAdapter {
|
||||
|
||||
// 轮播图数据统计
|
||||
if (mContext instanceof MainActivity) {
|
||||
DataLogUtils.uploadLunbotuLog(mContext, slideEntity.getType(), slideEntity.getText(), String
|
||||
DataLogUtils.uploadLunbotuLog(mContext, slideEntity.getType(), slideEntity.getText(), "", String
|
||||
.valueOf(getPosition(position) % size + 1), "游戏库");
|
||||
} else {
|
||||
DataLogUtils.uploadLunbotuLog(mContext, slideEntity.getType(), slideEntity.getText(), String
|
||||
DataLogUtils.uploadLunbotuLog(mContext, slideEntity.getType(), slideEntity.getText(), "", String
|
||||
.valueOf(getPosition(position) % size + 1), mSource);
|
||||
}
|
||||
|
||||
|
||||
@ -9,6 +9,10 @@ import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||
|
||||
import com.gh.base.OnRequestCallBackListener;
|
||||
import com.gh.common.util.DisplayUtils;
|
||||
import com.gh.common.util.ImageUtils;
|
||||
@ -38,9 +42,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import retrofit2.HttpException;
|
||||
@ -177,7 +178,12 @@ public class LibaoDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
}
|
||||
});
|
||||
|
||||
ImageUtils.display(holder.libaoGameIcon, mLibaoEntity.getIcon());
|
||||
if (mLibaoEntity.getGame() != null) {
|
||||
ImageUtils.display(holder.libaoGameIcon.getIconIv(), mLibaoEntity.getGame().getIcon());
|
||||
ImageUtils.display(holder.libaoGameIcon.getIconDecoratorIv(), mLibaoEntity.getGame().getIconSubscript());
|
||||
} else {
|
||||
ImageUtils.display(holder.libaoGameIcon.getIconIv(), mLibaoEntity.getIcon());
|
||||
}
|
||||
holder.libaoName.setText(mLibaoEntity.getName());
|
||||
if (TextUtils.isEmpty(mLibaoEntity.getPlatform())) {
|
||||
holder.libaoGameName.setText(mLibaoEntity.getGame().getName());
|
||||
|
||||
@ -9,7 +9,11 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||
|
||||
import com.gh.common.constant.Config;
|
||||
import com.gh.common.databind.BindingAdapters;
|
||||
import com.gh.common.util.CheckLoginUtils;
|
||||
import com.gh.common.util.CommentUtils;
|
||||
import com.gh.common.util.ConcernContentUtils;
|
||||
@ -55,8 +59,6 @@ import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import retrofit2.HttpException;
|
||||
@ -276,7 +278,12 @@ public class MessageDetailAdapter extends BaseRecyclerAdapter<ViewHolder> {
|
||||
mContext.getResources().getDisplayMetrics().widthPixels - DisplayUtils.dip2px(mContext, 34));
|
||||
}
|
||||
|
||||
ImageUtils.display(viewHolder.thumb, mConcernEntity.getGameIcon());
|
||||
if (mConcernEntity.getGame() != null) {
|
||||
ImageUtils.display(viewHolder.thumb.getIconIv(), mConcernEntity.getGame().getIcon());
|
||||
ImageUtils.display(viewHolder.thumb.getIconDecoratorIv(), mConcernEntity.getGame().getIconSubscript());
|
||||
} else {
|
||||
ImageUtils.display(viewHolder.thumb.getIconIv(), mConcernEntity.getGameIcon());
|
||||
}
|
||||
viewHolder.title.setText(mConcernEntity.getGameName());
|
||||
NewsUtils.setNewsPublishOn(viewHolder.time, mConcernEntity.getTime());
|
||||
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
package com.gh.gamecenter.adapter.viewholder;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.base.BaseRecyclerViewHolder;
|
||||
import com.gh.common.view.GameIconView;
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
import butterknife.BindView;
|
||||
@ -16,7 +15,7 @@ import butterknife.BindView;
|
||||
public class ConcernViewHolder extends BaseRecyclerViewHolder {
|
||||
|
||||
@BindView(R.id.concern_item_icon)
|
||||
public SimpleDraweeView concern_item_icon;
|
||||
public GameIconView concern_item_icon;
|
||||
|
||||
@BindView(R.id.concern_item_name)
|
||||
public TextView concern_item_name;
|
||||
@ -24,9 +23,6 @@ public class ConcernViewHolder extends BaseRecyclerViewHolder {
|
||||
@BindView(R.id.concern_item_concern)
|
||||
public TextView concern_item_concern;
|
||||
|
||||
@BindView(R.id.concern_libao_icon)
|
||||
public ImageView concern_libao_icon;
|
||||
|
||||
public ConcernViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ import com.gh.common.util.DialogUtils;
|
||||
import com.gh.common.util.DownloadDialogHelper;
|
||||
import com.gh.common.util.LogUtils;
|
||||
import com.gh.common.util.MtaHelper;
|
||||
import com.gh.common.util.PackageInstaller;
|
||||
import com.gh.common.util.PackageUtils;
|
||||
import com.gh.common.util.PermissionHelper;
|
||||
import com.gh.common.util.ReservationHelper;
|
||||
@ -135,16 +136,8 @@ public class DetailViewHolder {
|
||||
MtaHelper.onEvent("游戏详情_新", "更新", mGameEntity.getName());
|
||||
}
|
||||
|
||||
String autoDownloadPlatform = v.getTag() instanceof String ? (String) v.getTag() : "";
|
||||
v.setTag(null);
|
||||
switch (mViewHolder.mDownloadPb.getDownloadType()) {
|
||||
case DOWNLOADING_PLUGIN:
|
||||
case DOWNLOADING_NORMAL:
|
||||
Intent intent = DownloadManagerActivity.getDownloadMangerIntent(mViewHolder.context,
|
||||
mGameEntity.getApk().get(0).getUrl(),
|
||||
StringUtils.buildString(mEntrance, "+(", mName, "[", mTitle, "])"));
|
||||
mViewHolder.context.startActivity(intent);
|
||||
break;
|
||||
case NONE_WITH_HINT:
|
||||
case NONE:
|
||||
String offStatus = mGameEntity.getDownloadOffStatus();
|
||||
@ -172,7 +165,9 @@ public class DetailViewHolder {
|
||||
() -> {
|
||||
CertificationDialog.showCertificationDialog(mViewHolder.context, mGameEntity, () -> {
|
||||
DialogUtils.showVersionNumberDialog(mViewHolder.context, mGameEntity, () -> {
|
||||
DialogUtils.checkDownload(mViewHolder.context, apk.getSize(), this::download);
|
||||
DialogUtils.showOverseaDownloadDialog(mViewHolder.context, mGameEntity, () -> {
|
||||
DialogUtils.checkDownload(mViewHolder.context, apk.getSize(), this::download);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -212,7 +207,7 @@ public class DetailViewHolder {
|
||||
mDownloadEntity = DownloadManager.getInstance(mViewHolder.context).getDownloadEntityByUrl(mGameEntity.getApk().get(0).getUrl());
|
||||
}
|
||||
if (mDownloadEntity != null) {
|
||||
PackageUtils.launchSetup(mViewHolder.context, mDownloadEntity);
|
||||
PackageInstaller.install(mViewHolder.context, mDownloadEntity);
|
||||
}
|
||||
});
|
||||
break;
|
||||
@ -248,14 +243,21 @@ public class DetailViewHolder {
|
||||
MtaHelper.onEvent("H5页面", "入口", "详情页_" + mGameEntity.getName());
|
||||
LinkEntity linkEntity = mGameEntity.getH5Link();
|
||||
|
||||
boolean isPlay = "play".equals(linkEntity.getType()); // 是否为开始玩
|
||||
boolean isPlay = "play".equals(linkEntity.getType()); // 是否为开始玩
|
||||
if (isPlay) {
|
||||
HistoryHelper.insertGameEntity(mGameEntity);
|
||||
}
|
||||
|
||||
Intent i = new Intent(WebActivity.getIntentForWebGame(mViewHolder.context, linkEntity.getLink(), mGameEntity.getName(),isPlay));
|
||||
Intent i = new Intent(WebActivity.getIntentForWebGame(mViewHolder.context, linkEntity.getLink(), mGameEntity.getName(), isPlay, linkEntity.getCloseButton()));
|
||||
mViewHolder.context.startActivity(i);
|
||||
break;
|
||||
|
||||
default:
|
||||
Intent intent = DownloadManagerActivity.getDownloadMangerIntent(mViewHolder.context,
|
||||
mGameEntity.getApk().get(0).getUrl(),
|
||||
StringUtils.buildString(mEntrance, "+(", mName, "[", mTitle, "])"));
|
||||
mViewHolder.context.startActivity(intent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,8 +5,8 @@ import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.base.BaseRecyclerViewHolder;
|
||||
import com.gh.common.view.GameIconView;
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
import butterknife.BindView;
|
||||
@ -17,7 +17,7 @@ import butterknife.BindView;
|
||||
public class GameDownloadViewHolder extends BaseRecyclerViewHolder {
|
||||
|
||||
@BindView(R.id.dm_item_iv_icon)
|
||||
public SimpleDraweeView dmIcon;
|
||||
public GameIconView dmIcon;
|
||||
|
||||
@BindView(R.id.dm_item_tv_title)
|
||||
public TextView dmTitle;
|
||||
@ -37,6 +37,9 @@ public class GameDownloadViewHolder extends BaseRecyclerViewHolder {
|
||||
@BindView(R.id.dm_item_tv_startorpause)
|
||||
public TextView dmStartorpause;
|
||||
|
||||
@BindView(R.id.unzip_failure_hint)
|
||||
public View unzipFailureHint;
|
||||
|
||||
public GameDownloadViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
|
||||
@ -3,8 +3,8 @@ package com.gh.gamecenter.adapter.viewholder;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.base.BaseRecyclerViewHolder;
|
||||
import com.gh.common.view.GameIconView;
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
import butterknife.BindView;
|
||||
@ -15,7 +15,7 @@ import butterknife.BindView;
|
||||
public class GameUpdateViewHolder extends BaseRecyclerViewHolder {
|
||||
|
||||
@BindView(R.id.gu_item_iv_icon)
|
||||
public SimpleDraweeView guIcon;
|
||||
public GameIconView guIcon;
|
||||
|
||||
@BindView(R.id.gu_item_tv_name)
|
||||
public TextView guName;
|
||||
|
||||
@ -7,9 +7,9 @@ import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.base.BaseRecyclerViewHolder;
|
||||
import com.gh.common.view.DrawableView;
|
||||
import com.gh.common.view.GameIconView;
|
||||
import com.gh.gamecenter.databinding.GameItemBinding;
|
||||
import com.gh.gamecenter.entity.ColorEntity;
|
||||
import com.gh.gamecenter.entity.GameEntity;
|
||||
@ -17,7 +17,7 @@ import com.gh.gamecenter.entity.GameEntity;
|
||||
|
||||
public class GameViewHolder extends BaseRecyclerViewHolder {
|
||||
|
||||
public SimpleDraweeView gameThumb;
|
||||
public GameIconView gameThumb;
|
||||
public TextView gameName;
|
||||
public TextView gameDownloadBtn;
|
||||
public TextView gameDes;
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
package com.gh.gamecenter.adapter.viewholder;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.gh.base.BaseRecyclerViewHolder;
|
||||
import com.gh.common.view.GameIconView;
|
||||
import com.gh.gamecenter.R;
|
||||
|
||||
import butterknife.BindView;
|
||||
@ -24,7 +25,7 @@ public class LibaoDetailTopViewHolder extends BaseRecyclerViewHolder {
|
||||
@BindView(R.id.libaodetail_copy_btn)
|
||||
public TextView libaoCopyBtn;
|
||||
@BindView(R.id.libaodetail_game_icon)
|
||||
public SimpleDraweeView libaoGameIcon;
|
||||
public GameIconView libaoGameIcon;
|
||||
@BindView(R.id.libaodetail_libaocode_rv)
|
||||
public RecyclerView libaoCodeRv;
|
||||
|
||||
|
||||
@ -3,9 +3,9 @@ package com.gh.gamecenter.adapter.viewholder;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.gh.base.BaseRecyclerViewHolder;
|
||||
import com.gh.base.OnListClickListener;
|
||||
import com.gh.common.view.GameIconView;
|
||||
import com.gh.gamecenter.R;
|
||||
import com.gh.gamecenter.entity.LibaoEntity;
|
||||
|
||||
@ -25,7 +25,7 @@ public class LibaoNormalViewHolder extends BaseRecyclerViewHolder<LibaoEntity> {
|
||||
@BindView(R.id.libao_btn_status)
|
||||
public TextView libaoBtnStatus;
|
||||
@BindView(R.id.libao_game_icon)
|
||||
public SimpleDraweeView libaoGameIcon;
|
||||
public GameIconView libaoGameIcon;
|
||||
|
||||
public LibaoNormalViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user