基线备份:thirdparty 变体完成 + Android 4.2 兼容改造前
包含内容: - thirdparty flavor 独立 applicationId + Intent 入口(ThirdPartyEntryActivity) - 58 后端接口适配(单 /api 路径、code 0/200、camelCase 字段、UNBOUND 轮询) - MAC 硬件锚定校验(防一凭证多设备共用) - EPG mac 覆盖 SDK init(sMacOverride)+ ChannelManger 初始化对齐 - 提示文案优化(设备未注册/权益未绑定)
This commit is contained in:
194
app/src/main/java/com/pukka/jiecheng/utils/ActivitedDialog.java
Executable file
194
app/src/main/java/com/pukka/jiecheng/utils/ActivitedDialog.java
Executable file
@@ -0,0 +1,194 @@
|
||||
/**
|
||||
* @file ActivitedDialog.java
|
||||
* @description
|
||||
* @author ainetv
|
||||
* @date 2026-03-20
|
||||
*/
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
import com.pukka.jiecheng.R;
|
||||
import com.pukka.jiecheng.request.AsApiRequester;
|
||||
|
||||
public class ActivitedDialog extends Dialog {
|
||||
|
||||
private Activity activity;
|
||||
|
||||
private TextView tvActivatedValue;
|
||||
private TextView tvTotalValue;
|
||||
private TextView tvFailValue;
|
||||
private TextView tvUnusedValue;
|
||||
private View btnConfirm;
|
||||
private OnConfirmListener listener;
|
||||
private boolean isShowing = false;
|
||||
|
||||
public interface OnConfirmListener {
|
||||
void onConfirm();
|
||||
}
|
||||
|
||||
public void setOnConfirmListener(OnConfirmListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public ActivitedDialog(@NonNull Activity activity) {
|
||||
super(activity, R.style.FullScreenDialog);
|
||||
this.activity = activity;
|
||||
initView();
|
||||
}
|
||||
|
||||
public ActivitedDialog(@NonNull Activity activity, @StringRes int textResId) {
|
||||
super(activity, R.style.FullScreenDialog);
|
||||
this.activity = activity;
|
||||
initView();
|
||||
setText(activity.getString(textResId));
|
||||
}
|
||||
|
||||
public ActivitedDialog(@NonNull Activity activity, String text) {
|
||||
super(activity, R.style.FullScreenDialog);
|
||||
this.activity = activity;
|
||||
initView();
|
||||
setText(text);
|
||||
}
|
||||
|
||||
public ActivitedDialog(@NonNull Activity activity, AsApiRequester.CheckBenefitsResult result) {
|
||||
super(activity, R.style.FullScreenDialog);
|
||||
this.activity = activity;
|
||||
initView();
|
||||
setActivationData(result);
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
setActivationData(text);
|
||||
}
|
||||
|
||||
public void setText(@StringRes int textResId) {
|
||||
setText(activity.getString(textResId));
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
setContentView(R.layout.dialog_activation_success);
|
||||
setCancelable(false);
|
||||
setCanceledOnTouchOutside(false);
|
||||
|
||||
Window window = getWindow();
|
||||
if (window != null) {
|
||||
window.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
|
||||
WindowManager.LayoutParams.MATCH_PARENT);
|
||||
window.setGravity(android.view.Gravity.CENTER);
|
||||
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
}
|
||||
|
||||
tvActivatedValue = findViewById(R.id.tvActivatedValue);
|
||||
tvTotalValue = findViewById(R.id.tvTotalValue);
|
||||
tvFailValue = findViewById(R.id.tvFailValue);
|
||||
tvUnusedValue = findViewById(R.id.tvUnusedValue);
|
||||
btnConfirm = findViewById(R.id.btnConfirm);
|
||||
|
||||
btnConfirm.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (listener != null) {
|
||||
listener.onConfirm();
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
// Add support for DPAD center key / Enter key
|
||||
btnConfirm.setOnKeyListener(new View.OnKeyListener() {
|
||||
@Override
|
||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||
if (event.getAction() == KeyEvent.ACTION_DOWN &&
|
||||
(keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER)) {
|
||||
if (listener != null) {
|
||||
listener.onConfirm();
|
||||
}
|
||||
dismiss();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setActivationData(String data) {
|
||||
tvActivatedValue.setText(resolveDisplayValue(data));
|
||||
tvTotalValue.setText("--");
|
||||
tvFailValue.setText("--");
|
||||
tvUnusedValue.setText("--");
|
||||
}
|
||||
|
||||
public void setActivationData(AsApiRequester.CheckBenefitsResult result) {
|
||||
if (result == null) {
|
||||
tvActivatedValue.setText("--");
|
||||
tvTotalValue.setText("--");
|
||||
tvFailValue.setText("--");
|
||||
tvUnusedValue.setText("--");
|
||||
return;
|
||||
}
|
||||
tvActivatedValue.setText(resolveDisplayValue(result.usedCardCount));
|
||||
tvTotalValue.setText(resolveDisplayValue(result.totalCardCount));
|
||||
tvFailValue.setText(resolveDisplayValue(result.failCardCount));
|
||||
tvUnusedValue.setText(resolveDisplayValue(result.unusedCardCount));
|
||||
}
|
||||
|
||||
private String resolveDisplayValue(String value) {
|
||||
if (value == null) {
|
||||
return "--";
|
||||
}
|
||||
String trimValue = value.trim();
|
||||
return trimValue.isEmpty() ? "--" : trimValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
if (isShowing) {
|
||||
return;
|
||||
}
|
||||
isShowing = true;
|
||||
super.show();
|
||||
requestConfirmFocus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismiss() {
|
||||
if (!isShowing) {
|
||||
return;
|
||||
}
|
||||
isShowing = false;
|
||||
super.dismiss();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
}
|
||||
|
||||
private void requestConfirmFocus() {
|
||||
if (btnConfirm == null) {
|
||||
return;
|
||||
}
|
||||
btnConfirm.setFocusable(true);
|
||||
btnConfirm.setFocusableInTouchMode(true);
|
||||
btnConfirm.requestFocus();
|
||||
btnConfirm.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!btnConfirm.hasFocus()) {
|
||||
btnConfirm.requestFocus();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
118
app/src/main/java/com/pukka/jiecheng/utils/ActivityMonitor.java
Executable file
118
app/src/main/java/com/pukka/jiecheng/utils/ActivityMonitor.java
Executable file
@@ -0,0 +1,118 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.pukka.libcore.utils.LogUtils;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
|
||||
public class ActivityMonitor implements Application.ActivityLifecycleCallbacks {
|
||||
|
||||
public static ActivityMonitor mAppStatusManager;
|
||||
private final Application application;
|
||||
//是否前台
|
||||
private boolean isForground;
|
||||
//Activity运行个数
|
||||
private int activeCount;
|
||||
|
||||
private static final String TAG = "ActivityManager";
|
||||
//activity栈管理
|
||||
private static Stack<Activity> activityStack;
|
||||
//activity栈管理
|
||||
private static Stack<Activity> saveStack;
|
||||
// 详情页的activity栈管理
|
||||
private static Stack<Activity> playBseStack;
|
||||
//保存的播放详情页数量
|
||||
private static final int MAX_ACTIVITY_DETAIL_NUM = 2;
|
||||
private ActivityMonitor(Application application){
|
||||
this.application = application;
|
||||
activityStack = new Stack<>();
|
||||
playBseStack = new Stack<>();
|
||||
saveStack = new Stack<>();
|
||||
application.registerActivityLifecycleCallbacks(this);
|
||||
}
|
||||
|
||||
public static void init(Application application){
|
||||
if(mAppStatusManager == null){
|
||||
mAppStatusManager = new ActivityMonitor(application);
|
||||
}
|
||||
}
|
||||
|
||||
public static ActivityMonitor getInstance(){
|
||||
return mAppStatusManager;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
|
||||
LogUtils.d("onActivityCreated -- activity : "+activity);
|
||||
activityStack.add(activity);
|
||||
LogUtils.d("onActivityCreated -- activityStack : "+activityStack);
|
||||
saveStack.add(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStarted(@NonNull Activity activity) {
|
||||
LogUtils.d("onActivityStarted -- activity : "+activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResumed(@NonNull Activity activity) {
|
||||
LogUtils.d("onActivityResumed -- activity : "+activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityPaused(@NonNull Activity activity) {
|
||||
LogUtils.d("onActivityPaused -- activity : "+activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStopped(Activity activity) {
|
||||
LogUtils.d("onActivityStopped -- activity : "+activity);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityDestroyed(Activity activity) {
|
||||
LogUtils.d("onActivityDestroyed -- activity : "+activity);
|
||||
activityStack.remove(activity);
|
||||
LogUtils.d("onActivityDestroyed -- activityStack : "+activityStack);
|
||||
saveStack.remove(activity);
|
||||
}
|
||||
|
||||
|
||||
public Activity getLastAct(){
|
||||
return activityStack.lastElement();
|
||||
}
|
||||
|
||||
public String getPreAct(){
|
||||
LogUtils.d("getPreAct -- saveStack : "+saveStack);
|
||||
if (!saveStack.isEmpty()){
|
||||
int pos = saveStack.size()-2;
|
||||
if (pos >= 0){
|
||||
return saveStack.get(pos).getLocalClassName();
|
||||
}
|
||||
}
|
||||
return "null";
|
||||
}
|
||||
|
||||
/**
|
||||
* 把传入的activity finish掉
|
||||
* @param activity
|
||||
*/
|
||||
public void removeActivity(Activity activity){
|
||||
if (activity != null && !activity.isFinishing() && !activity.isDestroyed()){
|
||||
activity.finish();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
74
app/src/main/java/com/pukka/jiecheng/utils/BuglyInitManager.java
Executable file
74
app/src/main/java/com/pukka/jiecheng/utils/BuglyInitManager.java
Executable file
@@ -0,0 +1,74 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.pukka.jiecheng.BuildConfig;
|
||||
import com.pukka.libcore.utils.LogUtils;
|
||||
import com.pukka.libcore.utils.SharedPreferenceUtils;
|
||||
import com.tencent.bugly.crashreport.CrashReport;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public final class BuglyInitManager {
|
||||
private static final String USER_AGREEMENT_FILE = "userAgreementJc";
|
||||
private static final String USER_AGREEMENT_KEY = "userAgreementJc";
|
||||
private static final String BUGLY_DEBUG_FILE = "bugly_debug";
|
||||
private static final String BUGLY_TEST_CRASH_KEY = "bugly_test_crash_once";
|
||||
private static final AtomicBoolean INITIALIZED = new AtomicBoolean(false);
|
||||
|
||||
private BuglyInitManager() {
|
||||
}
|
||||
|
||||
public static void initIfPrivacyAgreed(Context context) {
|
||||
if (!isPrivacyAgreed()) {
|
||||
return;
|
||||
}
|
||||
init(context);
|
||||
}
|
||||
|
||||
public static boolean isPrivacyAgreed() {
|
||||
return "1".equals(SharedPreferenceUtils.getString(USER_AGREEMENT_FILE, USER_AGREEMENT_KEY, "0"));
|
||||
}
|
||||
|
||||
public static void init(Context context) {
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
if (INITIALIZED.get()) {
|
||||
return;
|
||||
}
|
||||
String appId = BuildConfig.BUGLY_APP_ID;
|
||||
if (TextUtils.isEmpty(appId)) {
|
||||
LogUtils.e("Bugly init skipped: BUGLY_APP_ID is empty");
|
||||
return;
|
||||
}
|
||||
if (INITIALIZED.compareAndSet(false, true)) {
|
||||
CrashReport.UserStrategy strategy = new CrashReport.UserStrategy(context.getApplicationContext());
|
||||
strategy.setAppChannel(getChannelForReport());
|
||||
CrashReport.initCrashReport(context.getApplicationContext(), appId, BuildConfig.DEBUG, strategy);
|
||||
}
|
||||
}
|
||||
|
||||
public static void triggerTestExceptionOnceIfInDebug(Context context) {
|
||||
// if (context == null || !BuildConfig.DEBUG) {
|
||||
// return;
|
||||
// }
|
||||
// if (!isPrivacyAgreed()) {
|
||||
// return;
|
||||
// }
|
||||
// init(context);
|
||||
// if (SharedPreferenceUtils.getBoolean(BUGLY_DEBUG_FILE, BUGLY_TEST_CRASH_KEY, false)) {
|
||||
// return;
|
||||
// }
|
||||
// SharedPreferenceUtils.put(BUGLY_DEBUG_FILE, BUGLY_TEST_CRASH_KEY, true);
|
||||
CrashReport.testJavaCrash();
|
||||
}
|
||||
|
||||
private static String getChannelForReport() {
|
||||
// if (!TextUtils.isEmpty(BuildConfig.CHANNEL_ID)) {
|
||||
// return BuildConfig.CHANNEL_ID;
|
||||
// }
|
||||
return BuildConfig.FLAVOR;
|
||||
}
|
||||
}
|
||||
22
app/src/main/java/com/pukka/jiecheng/utils/BuildConfigUtils.java
Executable file
22
app/src/main/java/com/pukka/jiecheng/utils/BuildConfigUtils.java
Executable file
@@ -0,0 +1,22 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.pukka.jiecheng.BuildConfig;
|
||||
import com.pukka.libcore.utils.LogUtils;
|
||||
|
||||
|
||||
public class BuildConfigUtils {
|
||||
public static void initBuildConfig(Context context){
|
||||
com.pukka.libcore.base.BuildConfig.FLAVOR = BuildConfig.FLAVOR;
|
||||
com.pukka.libcore.base.BuildConfig.BUILD_TYPE = BuildConfig.BUILD_TYPE;
|
||||
com.pukka.libcore.base.BuildConfig.VERSION_NAME = BuildConfig.VERSION_NAME;
|
||||
com.pukka.libcore.base.BuildConfig.VERSION_CODE = BuildConfig.VERSION_CODE;
|
||||
LogUtils.d("MainActivity -- FLAVOR : " + com.pukka.libcore.base.BuildConfig.FLAVOR);
|
||||
LogUtils.d("MainActivity -- VERSION_CODE : " + com.pukka.libcore.base.BuildConfig.VERSION_CODE);
|
||||
LogUtils.d("MainActivity -- VERSION_NAME : " + com.pukka.libcore.base.BuildConfig.VERSION_NAME);
|
||||
LogUtils.d("MainActivity -- BUILD_TYPE : " + com.pukka.libcore.base.BuildConfig.BUILD_TYPE);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
359
app/src/main/java/com/pukka/jiecheng/utils/ChannelManger.java
Executable file
359
app/src/main/java/com/pukka/jiecheng/utils/ChannelManger.java
Executable file
@@ -0,0 +1,359 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import static com.pukka.libcore.base.BaseConst.serviceComboCode;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.migu.libnetwork.HttpRequestCallback;
|
||||
import com.migu.libnetwork.HttpUtils;
|
||||
import com.pukka.jiecheng.JcConfig;
|
||||
import com.pukka.jiecheng.login.bean.GetCloudLoginBean;
|
||||
import com.pukka.jiecheng.login.bean.GetQueryUsableBean;
|
||||
import com.pukka.jiecheng.login.bean.QueryVipInfoBean;
|
||||
import com.pukka.jiecheng.order.bean.ActivateBean;
|
||||
import com.pukka.libcore.base.BaseConst;
|
||||
import com.pukka.libcore.base.BuildConfig;
|
||||
import com.pukka.libcore.boxShared.BoxSharedParameters;
|
||||
import com.pukka.libcore.boxShared.BoxSharedParamsUtils;
|
||||
import com.pukka.libcore.boxShared.MacUtils;
|
||||
import com.pukka.libcore.utils.ContextUtils;
|
||||
import com.pukka.libcore.utils.DateUtils;
|
||||
import com.pukka.libcore.utils.JsonUtils;
|
||||
import com.pukka.libcore.utils.LogUtils;
|
||||
import com.pukka.libcore.utils.MD5Utils;
|
||||
import com.pukka.libcore.utils.SharedPreferenceUtils;
|
||||
import com.pukka.libcore.utils.SpTimeUtils;
|
||||
import com.pukka.libcore.utils.StringUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ChannelManger {
|
||||
public static final String TAG = "ChannelManger";
|
||||
public static String publicKeyStr_could = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoDFiT8rDa6ftkRCxO8GctdhOYsEcmyrwyy0IYZKperNNukZnRYG0ucmmZ1C+9NWvVdmzoV1ikl5gBjdWlmnBzRZxtlaUaygm9/TrFDzOHzNLrkLtz1HSuSxNVMoOIaaSOdBcGtehK220td4U1jJFsyGwX/nsNhrlZ7Nhg3iFsrhAJ/9V7FLSJSc4W7XEKA36L5MBj/urCZNVbK7VIlfTfZy5W0CA8IwzEOPClkzjDG6H/s2zW/acxkyWBcOOBtNuNPUtQrmHKB9HJc0oxlbEVxW9UZ0rEWyFm/JN1z2ItMw+8upmFKbCGTXW6/1kzRs9Nsgc3zAqUzTMvT9qlDoeqwIDAQAB";
|
||||
public static String publicKeyStr_Hotel = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs9MGm6Wz0Z9GuImV1drFJNVOJ6F9Pno/qqdj2q5RqFb/1AxrkaiCKjaeCYZmhSR3F9BqO8nC2L2JGqYn17bTAzLcti3gcoSyy7BVt+nq0pDQsoQ/2CloMY2okMatcfENsUGz1IhrAwUxUfQcdk9lS8T5bKshxXnZKKXhLBEh3xsOMBZNhWssGadj8gtmuW8CHEXyi/04Php8erpOjpba4zgAwCRzMEC54fcSraD+h81U6S/jkuZSvhGVVl0AYLHSJIyTkfOjYxbjDZh4XH/Wco/p0zeQH4a3gP+bTj8bsDZIjfeprLHnwshEdNfUx2HP8++zkJLO2VT/NM2C/ILqWwIDAQAB";
|
||||
public static String publicKeyStr_Hotel_release = "";
|
||||
public static String publicKeyStr_could_release = "";
|
||||
|
||||
|
||||
public static void initChannel() {
|
||||
LogUtils.d(TAG, "initChannel:" + BuildConfig.FLAVOR);
|
||||
LogUtils.d(TAG, "initChannel:isJcHotel");
|
||||
// if (BuildConfig.BUILD_TYPE.contains("release")) {
|
||||
// JetsenxSdkUtil.ACCESSER = "JSTASJD";
|
||||
// JetsenxSdkUtil.SECRET = "kMeWsBu0QsTXpnft";
|
||||
// JetsenxSdkUtil.AGCODE = "1100101010200492358120169";
|
||||
// BaseConst.agentVendorCode = JetsenxSdkUtil.AGCODE;
|
||||
// BaseConst.serviceComboCode = "1100121010200494755850172";
|
||||
// BaseConst.serviceGroupCode = "1100122010201752209710182";
|
||||
// BaseConst.businessLine = "4100450011381755998420012";
|
||||
// publicKeyStr_Hotel_release = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtlfaNsJwQ8wuVdITMLJPrXMeD9idJ0aTziOgkZZhigwzhyPNDAqw+nCKeJGGoTJyhbjPXKtnyI8eNpj+xhCCMXUD3BxOVMFWBhFxzIl83IQJG43mPRXwsJrI4oCYDaKv5aeZZBqF0OLPglXU+q19/28ltONvxcKp8YxXagmixzz1SDgLITM3s3ExqiaScK1dcpPtXbCpI4GXPP9l0ekkCBAo/d1oQqbxHvdE5ufAhEZ042k5tVHUgX9cUoedA9F2JcPhc+zUNCJUAQLvfVXxqNdhwxA4TY+64OX2iSje/cTqxp+4RcrX4rbUIYZitVQCRexZjKz7Yd/KXp8CKCho6wIDAQAB";
|
||||
// } else {
|
||||
// JetsenxSdkUtil.ACCESSER = "ASJDTEST";
|
||||
// JetsenxSdkUtil.SECRET = "ykgEDrYccunGtb0x";
|
||||
// JetsenxSdkUtil.AGCODE = "1100101010200492358120169";
|
||||
// BaseConst.agentVendorCode = JetsenxSdkUtil.AGCODE;
|
||||
// BaseConst.serviceComboCode = "1100121010200492753300170";
|
||||
// BaseConst.serviceGroupCode = "1100122010200493334770171";
|
||||
// BaseConst.businessLine = "4100450011967708592750001";
|
||||
// publicKeyStr_Hotel = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnemyIjwf1S5PsqgPhwiPGcF2Efa4UvFiFpg34+d2ZHQ6mkTTaussXCWQQRZGUfGbvkhIJOspGxmxtaMYgNxMQv9BT5B6xcnMILqYzG40hc2N3EiLm4hDYP12f8pshikh5aNxolbgkdA+Y2vrMf2KNucArMh8gT1mUuQRyUMiefy+N/kk2nK2p6SSX0628/BtczNgj13MaMHMlr8krNTlzB/22M8WMSk10nFS4ULp1KOPia8VxqzMIFKeREPIHIUnarz+llFIj6zKGg0ocqS6KEml7jv1yCgBpmyA2kAGEgnuTreO/5h5DqXByKLBEW8bYDiMUb7H/58IRerrITXfVQIDAQAB";
|
||||
//
|
||||
// }
|
||||
JetsenxSdkUtil.ACCESSER = "JSTASJD";
|
||||
JetsenxSdkUtil.SECRET = "kMeWsBu0QsTXpnft";
|
||||
JetsenxSdkUtil.AGCODE = "1100101010200492358120169";
|
||||
BaseConst.agentVendorCode = JetsenxSdkUtil.AGCODE;
|
||||
BaseConst.serviceComboCode = "1100121010200494755850172";
|
||||
BaseConst.serviceGroupCode = "1100122010201752209710182";
|
||||
BaseConst.businessLine = "4100450011381755998420012";
|
||||
publicKeyStr_Hotel_release = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtlfaNsJwQ8wuVdITMLJPrXMeD9idJ0aTziOgkZZhigwzhyPNDAqw+nCKeJGGoTJyhbjPXKtnyI8eNpj+xhCCMXUD3BxOVMFWBhFxzIl83IQJG43mPRXwsJrI4oCYDaKv5aeZZBqF0OLPglXU+q19/28ltONvxcKp8YxXagmixzz1SDgLITM3s3ExqiaScK1dcpPtXbCpI4GXPP9l0ekkCBAo/d1oQqbxHvdE5ufAhEZ042k5tVHUgX9cUoedA9F2JcPhc+zUNCJUAQLvfVXxqNdhwxA4TY+64OX2iSje/cTqxp+4RcrX4rbUIYZitVQCRexZjKz7Yd/KXp8CKCho6wIDAQAB";
|
||||
|
||||
BoxSharedParameters.getInstance().setNewTvPass(true);
|
||||
}
|
||||
|
||||
public static void loginAuto(String uid, OnCallBack onCallBack) {
|
||||
String baseHost = JcConfig.getBaseUrl();
|
||||
String host = baseHost + "ums_api/api/v1/third/login";
|
||||
|
||||
String timestamp = String.valueOf(System.currentTimeMillis());
|
||||
String accesser = JetsenxSdkUtil.ACCESSER;
|
||||
String businessLine = BaseConst.businessLine;
|
||||
String serviceComboCode = BaseConst.serviceComboCode;
|
||||
String nonce = UUID.randomUUID().toString().replace("-", "");
|
||||
|
||||
TreeMap<String, String> params = new TreeMap<>();
|
||||
params.put("timestamp", timestamp);
|
||||
params.put("nonce", nonce);
|
||||
params.put("serviceComboCode", serviceComboCode);
|
||||
|
||||
String url = UrlParamBuilder.buildUrl(host, params);
|
||||
|
||||
HashMap<String, String> signMap = new HashMap<>();
|
||||
signMap.put("accesser", accesser);
|
||||
signMap.put("businessLine", businessLine);
|
||||
signMap.put("uid", uid); //此处需要传递安柠的用户的唯一标识
|
||||
signMap.put("mac", MacUtils.getMac(ContextUtils.getApplicationContext())); //安柠设备mac
|
||||
signMap.put("nonce", nonce); //注意:此处的nonce,需要和接口的url参数相同
|
||||
signMap.put("timestamp", timestamp); //注意:此处的时间戳,需要和接口的url参数相同
|
||||
signMap.put("serviceComboCode", serviceComboCode);
|
||||
// 使用 Gson 转为 JSON 字符串 注意:若无gson依赖,改为其它任意安全的json转化字符串方法均可
|
||||
Gson gson = new Gson();
|
||||
String encryptData = gson.toJson(signMap);
|
||||
LogUtils.d(TAG, "待加密字符串为:" + encryptData);
|
||||
//公钥字符串,联系华视开发获取
|
||||
String keyStr = "";
|
||||
|
||||
if (BuildConfig.BUILD_TYPE.contains("release")) {
|
||||
keyStr = publicKeyStr_Hotel_release;
|
||||
} else {
|
||||
keyStr = publicKeyStr_Hotel;
|
||||
}
|
||||
|
||||
String encrypt = RsaSignUtil.encrypt(keyStr, encryptData);
|
||||
|
||||
HttpUtils.getInstance().executePostCloudLogin(url, new TreeMap(), JetsenxSdkUtil.TENANT, encrypt, new HttpRequestCallback() {
|
||||
@Override
|
||||
public void onRequestNetFail(int type) {
|
||||
onCallBack.over(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestSuccess(String result, int type) {
|
||||
LogUtils.d(TAG, "loginCloud:" + result);
|
||||
try {
|
||||
//test
|
||||
//result="{\"retCode\":\"E0000000\",\"retMsg\":\"登录失败\",\"retInfo\":null}";
|
||||
GetCloudLoginBean bean = new Gson().fromJson(result, GetCloudLoginBean.class);
|
||||
String retCode = bean.getRetCode();
|
||||
if (!StringUtils.isEmpty(retCode) && retCode.equals("00000000")) {
|
||||
String phone = bean.getRetInfo().getExternalId();
|
||||
String token = bean.getRetInfo().getToken();
|
||||
JetsenxSdkUtil.init(ContextUtils.getApplicationContext(), JetsenxSdkUtil.AGCODE, MacUtils.getMac(ContextUtils.getApplicationContext()), phone, JetsenxSdkUtil.TENANT, JetsenxSdkUtil.SECRET, JetsenxSdkUtil.ACCESSER, "1", "");
|
||||
long time = System.currentTimeMillis();
|
||||
SpTimeUtils.getInstance(ContextUtils.getContext()).setString("phoneMember2", phone + "@" + time, 6 * SpTimeUtils.TIME_DAY);
|
||||
SharedPreferenceUtils.put("phoneToken", token);
|
||||
BoxSharedParameters.getInstance().setUserId(phone);
|
||||
BoxSharedParameters.getInstance().setToken(token);
|
||||
LogUtils.d(TAG, "登录成功");
|
||||
onCallBack.over(true);
|
||||
} else {
|
||||
LogUtils.d(TAG, "登录失败");
|
||||
onCallBack.over(false);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogUtils.d(TAG, "登录Exception:" + e);
|
||||
onCallBack.over(false);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestFail(String value, String failCode, int type) {
|
||||
LogUtils.d(TAG, "onRequestFail:" + value);
|
||||
onCallBack.over(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void queryUsable(OnDeviceNoActCallBack onDeviceNoActCallBack) {
|
||||
LogUtils.d(TAG, "queryUsable:");
|
||||
String baseHost = JcConfig.getBaseUrl();
|
||||
String host = baseHost + "ccms_api/hswj/api/card/query-usable?serviceComboCode=" + BaseConst.serviceComboCode;
|
||||
HttpUtils.getInstance().mHttpGetUserInfo(host, BoxSharedParameters.getInstance().getToken(), JcConfig.header, new HttpRequestCallback() {
|
||||
@Override
|
||||
public void onRequestNetFail(int type) {
|
||||
onDeviceNoActCallBack.goHome();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestSuccess(String result, int type) {
|
||||
LogUtils.d(TAG, "queryUsable onRequestSuccess:" + result);
|
||||
try {
|
||||
if (!StringUtils.isEmpty(result)) {
|
||||
GetQueryUsableBean bean = new Gson().fromJson(result, GetQueryUsableBean.class);
|
||||
if (bean.getRetInfo() != null) {
|
||||
if (!bean.getRetInfo().getCards().isEmpty()) {
|
||||
String str = bean.getRetInfo().getCards().get(0).getActivateCode();
|
||||
activate(str, onDeviceNoActCallBack);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
LogUtils.d("当前用户无可激活卡密,获取会员到期时间");
|
||||
//如果用户没注册过,返回当前用户无可激活卡密;如果用户已经激活过卡,已经是会员,也会返回当前用户无可激活卡密
|
||||
queryVipInfo(onDeviceNoActCallBack);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
onDeviceNoActCallBack.goHome();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestFail(String value, String failCode, int type) {
|
||||
onDeviceNoActCallBack.goHome();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 卡密激活接口
|
||||
**/
|
||||
private static void activate(String activateCode, OnDeviceNoActCallBack onDeviceNoActCallBack) {
|
||||
LogUtils.d(TAG, "activate:");
|
||||
try {
|
||||
String token = BoxSharedParameters.getInstance().getToken();
|
||||
LogUtils.d("token:" + token);
|
||||
if (StringUtils.isEmpty(token) || StringUtils.isEmpty(activateCode)) {
|
||||
return;
|
||||
}
|
||||
String memberCode = BaseConst.getMemberCode(token);
|
||||
LogUtils.d("memberCode:" + memberCode);
|
||||
long timestamp = System.currentTimeMillis() / 1000;
|
||||
LogUtils.d("timestamp:" + timestamp);
|
||||
String oldSign = "activateCode=" + activateCode + "&memberCode=" + memberCode + "×tamp=" + timestamp;
|
||||
LogUtils.d("oldSign:" + oldSign);
|
||||
String stringSignTemp = oldSign + "&key=" + JcConfig.key;
|
||||
LogUtils.d("stringSignTemp:" + stringSignTemp);
|
||||
String sign = MD5Utils.getMD5(stringSignTemp).toUpperCase();
|
||||
LogUtils.d("sign1:" + sign);
|
||||
String url = JcConfig.ACTIVATE + "sign=" + sign;
|
||||
LogUtils.d("url:" + url);
|
||||
JsonObject content = new JsonObject();
|
||||
content.addProperty("activateCode", activateCode);
|
||||
content.addProperty("memberCode", memberCode);
|
||||
content.addProperty("timestamp", timestamp);
|
||||
content.addProperty("serviceComboCode", serviceComboCode);
|
||||
String strContent = content.toString();
|
||||
LogUtils.d("strContent:" + strContent);
|
||||
HttpUtils.getInstance().mHttpPostActivate(url, strContent, JcConfig.header, new HttpRequestCallback() {
|
||||
@Override
|
||||
public void onRequestNetFail(int type) {
|
||||
LogUtils.d(TAG, "mHttpPostActivate onRequestNetFail()");
|
||||
onDeviceNoActCallBack.goHome();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestSuccess(String result, int type) {
|
||||
LogUtils.d(TAG, "mHttpPostActivate onRequestSuccess:" + result);
|
||||
try {
|
||||
if (!StringUtils.isEmpty(result)) {
|
||||
ActivateBean activateBean = JsonUtils.json2Object(result, ActivateBean.class);
|
||||
String retCode = activateBean.getRetCode();
|
||||
if (!StringUtils.isEmpty(retCode) && !retCode.equals("00000000")) {
|
||||
LogUtils.d("激活失败");
|
||||
onDeviceNoActCallBack.errorMessage("403");
|
||||
return;
|
||||
}
|
||||
}
|
||||
onDeviceNoActCallBack.goHome();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
onDeviceNoActCallBack.goHome();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestFail(String value, String failCode, int type) {
|
||||
LogUtils.d(TAG, "mHttpPostActivate onRequestFail()");
|
||||
onDeviceNoActCallBack.goHome();
|
||||
}
|
||||
});
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
onDeviceNoActCallBack.goHome();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会员到期时间
|
||||
* 本接口有签名校验功能,sign=Md5(businessLine + requestTime + uid + key),其中key固定为
|
||||
* c25svtwbTyCE
|
||||
* <p>
|
||||
* {"retCode":"00000000","retMsg":"操作成功","retInfo":{"vipExpireTime":null,"isVip":false}}
|
||||
*/
|
||||
private static void queryVipInfo(OnDeviceNoActCallBack onDeviceNoActCallBack) {
|
||||
String requestTime = System.currentTimeMillis() + "";
|
||||
String uid = MacUtils.getMac(ContextUtils.getApplicationContext());
|
||||
String preSign = BaseConst.businessLine + requestTime + uid + "c25svtwbTyCE";
|
||||
LogUtils.d("preSign=" + preSign);
|
||||
String sign = MD5Utils.getMD5(preSign);
|
||||
LogUtils.d("sign=" + sign);
|
||||
String url = JcConfig.QUERYVIPINFO + "requestTime=" + requestTime + "&uid=" + uid + "&businessLine=" + BaseConst.businessLine + "&sign=" + sign;
|
||||
HttpUtils.getInstance().mHttpPostQueryVipInfo(url, JcConfig.header, new HttpRequestCallback() {
|
||||
@Override
|
||||
public void onRequestNetFail(int type) {
|
||||
LogUtils.d(TAG, "mHttpPostQueryVipInfo onRequestNetFail()");
|
||||
onDeviceNoActCallBack.goHome();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestSuccess(String result, int type) {
|
||||
LogUtils.d(TAG, "mHttpPostQueryVipInfo onRequestSuccess:" + result);
|
||||
try {
|
||||
QueryVipInfoBean bean = new Gson().fromJson(result, QueryVipInfoBean.class);
|
||||
String retCode = bean.getRetCode();
|
||||
if (!StringUtils.isEmpty(retCode) && retCode.equals("00000000")) {
|
||||
boolean isVip = bean.getRetInfo().isIsVip();
|
||||
if (isVip) {
|
||||
//{"retCode":"00000000","retMsg":"操作成功","retInfo":{"vipExpireTime":"2026-02-24 11:22:39","isVip":true}}
|
||||
String vipExpireTime = bean.getRetInfo().getVipExpireTime();
|
||||
LogUtils.d("Vip到期日期:" + vipExpireTime);
|
||||
int temp = DateUtils.compareDate(DateUtils.getNowDate(), DateUtils.convertToDate(vipExpireTime, "yyyy-MM-dd HH:mm:ss"));
|
||||
if (temp <= 0) {
|
||||
LogUtils.d("VIP没到期,跳转到首页");
|
||||
onDeviceNoActCallBack.goHome();
|
||||
} else {
|
||||
LogUtils.d("VIP到期,显示错误码402");
|
||||
onDeviceNoActCallBack.errorMessage("402");
|
||||
}
|
||||
} else {
|
||||
LogUtils.d("不是vip,显示错误码402");
|
||||
onDeviceNoActCallBack.errorMessage("402");
|
||||
}
|
||||
} else {
|
||||
//可能该mac在其他环境上注册过导致请求参数异常
|
||||
LogUtils.d("请求参数异常,显示错误码403");
|
||||
onDeviceNoActCallBack.errorMessage("403");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
onDeviceNoActCallBack.goHome();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestFail(String value, String failCode, int type) {
|
||||
LogUtils.d(TAG, "mHttpPostActivate onRequestFail()");
|
||||
onDeviceNoActCallBack.goHome();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public interface OnCallBack {
|
||||
void over(boolean isLogin);
|
||||
}
|
||||
|
||||
public interface OnDeviceNoActCallBack {
|
||||
void errorMessage(String message);
|
||||
|
||||
void goHome();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是安柠酒店
|
||||
*/
|
||||
public static boolean isAnNingHotel() {
|
||||
return BoxSharedParamsUtils.isJcHotel() && "ANNING".equals(com.pukka.jiecheng.BuildConfig.HOTEL_TYPE);
|
||||
}
|
||||
/**
|
||||
* 是否需要去掉首页我的页面
|
||||
* */
|
||||
public static boolean isNeedMy(){
|
||||
return com.pukka.jiecheng.BuildConfig.NEED_MY;
|
||||
}
|
||||
}
|
||||
30
app/src/main/java/com/pukka/jiecheng/utils/CloudKeyCodeUtils.java
Executable file
30
app/src/main/java/com/pukka/jiecheng/utils/CloudKeyCodeUtils.java
Executable file
@@ -0,0 +1,30 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import com.pukka.libcore.boxShared.BoxSharedParamsUtils;
|
||||
import com.pukka.libcore.utils.LogUtils;
|
||||
|
||||
/**
|
||||
* 云主机版本
|
||||
* 遥控器按键适配
|
||||
* */
|
||||
public class CloudKeyCodeUtils {
|
||||
/**
|
||||
* 遥控器按键适配 返回和确认按键键值转换
|
||||
* */
|
||||
public static int changeToKeyCode(int keyCode){
|
||||
if(BoxSharedParamsUtils.isJcCloud() || BoxSharedParamsUtils.isJcHotel()){
|
||||
//遥控器返回键是97
|
||||
if(keyCode == 97){
|
||||
LogUtils.d("遥控器返回按键适配");
|
||||
keyCode = KeyEvent.KEYCODE_BACK;
|
||||
}
|
||||
if(keyCode == 96){
|
||||
LogUtils.d("遥控器OK按键适配");
|
||||
keyCode = KeyEvent.KEYCODE_DPAD_CENTER;
|
||||
}
|
||||
}
|
||||
return keyCode;
|
||||
}
|
||||
}
|
||||
16
app/src/main/java/com/pukka/jiecheng/utils/ColorSpanUtils.java
Executable file
16
app/src/main/java/com/pukka/jiecheng/utils/ColorSpanUtils.java
Executable file
@@ -0,0 +1,16 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
|
||||
public class ColorSpanUtils {
|
||||
public static SpannableString textColorChanges(String fullText, String colorText, @ColorInt int color) {
|
||||
SpannableString spannableString = new SpannableString(fullText);
|
||||
ForegroundColorSpan colorSpan = new ForegroundColorSpan(color);
|
||||
spannableString.setSpan(colorSpan, fullText.indexOf(colorText), fullText.indexOf(colorText) + colorText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
return spannableString;
|
||||
}
|
||||
}
|
||||
61
app/src/main/java/com/pukka/jiecheng/utils/ColorUtil.java
Executable file
61
app/src/main/java/com/pukka/jiecheng/utils/ColorUtil.java
Executable file
@@ -0,0 +1,61 @@
|
||||
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
|
||||
/**
|
||||
* [颜色工具类]<BR>
|
||||
*
|
||||
* @author wcg
|
||||
* @version [V0.1.0.1, 2023/11/27 0027]
|
||||
* @since V0.1.0.1
|
||||
*/
|
||||
public class ColorUtil {
|
||||
private static final String START_STR = "#";
|
||||
|
||||
private static final int ALPHA_MAX = 100;
|
||||
|
||||
/**
|
||||
* 设置shape color
|
||||
* strokeWidth 边框宽度
|
||||
* strokeColor 边框颜色
|
||||
*/
|
||||
public static void setBackgroundShapeColor(View view, String strColor, int strokeWidth) {
|
||||
if (view == null || TextUtils.isEmpty(strColor)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
GradientDrawable drawable = (GradientDrawable) view.getBackground();
|
||||
drawable.setColor(ColorUtils.setAlphaComponent(Color.parseColor(strColor), getAlphaValue(10)));
|
||||
if (strokeWidth > 0 && strColor.startsWith(START_STR)) {
|
||||
drawable.setStroke(strokeWidth,
|
||||
ColorUtils.setAlphaComponent(Color.parseColor(strColor), getAlphaValue(50)));
|
||||
}
|
||||
view.setBackground(drawable);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取透明度值 十进制
|
||||
*
|
||||
* @param alphaPercent 不透明度百分比
|
||||
* @return 0~255
|
||||
*/
|
||||
public static int getAlphaValue(int alphaPercent) {
|
||||
if (alphaPercent >= 0 && alphaPercent <= ALPHA_MAX) {
|
||||
float temp = 255 * alphaPercent * 1.0f / 100f;
|
||||
// 四舍五入
|
||||
return Math.round(temp);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
146
app/src/main/java/com/pukka/jiecheng/utils/CommonLoadingDialog.java
Executable file
146
app/src/main/java/com/pukka/jiecheng/utils/CommonLoadingDialog.java
Executable file
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
* @file CommonLoadingDialog.java
|
||||
* @description 通用Loading弹框,支持文案配置,不可取消
|
||||
* @author ainetv
|
||||
* @date 2026-03-20
|
||||
*/
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.SystemClock;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
|
||||
import com.pukka.jiecheng.R;
|
||||
|
||||
public class CommonLoadingDialog extends Dialog {
|
||||
public enum Mode {
|
||||
FULLSCREEN,
|
||||
ACTIVATION_SMALL
|
||||
}
|
||||
|
||||
private static final long SHOW_DISMISS_INTERVAL_MS = 120L;
|
||||
|
||||
private Activity activity;
|
||||
private ImageView idIvLoading;
|
||||
private TextView idTvText;
|
||||
private ConstraintLayout clContent;
|
||||
private final Mode mode;
|
||||
private long lastShowTimestamp;
|
||||
private long lastDismissTimestamp;
|
||||
|
||||
public CommonLoadingDialog(@NonNull Activity activity) {
|
||||
this(activity, Mode.FULLSCREEN);
|
||||
}
|
||||
|
||||
public CommonLoadingDialog(@NonNull Activity activity, Mode mode) {
|
||||
super(activity, mode == Mode.ACTIVATION_SMALL ? R.style.ActivationLoadingDialog : R.style.FullScreenDialog);
|
||||
this.activity = activity;
|
||||
this.mode = mode;
|
||||
initView();
|
||||
}
|
||||
|
||||
public CommonLoadingDialog(@NonNull Activity activity, @StringRes int textResId) {
|
||||
this(activity, Mode.FULLSCREEN);
|
||||
setText(textResId);
|
||||
}
|
||||
|
||||
public CommonLoadingDialog(@NonNull Activity activity, String text) {
|
||||
this(activity, Mode.FULLSCREEN);
|
||||
setText(text);
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
int layoutRes = mode == Mode.ACTIVATION_SMALL
|
||||
? R.layout.layout_activation_loading_small
|
||||
: R.layout.layout_common_loading;
|
||||
View view = View.inflate(activity, layoutRes, null);
|
||||
idIvLoading = view.findViewById(R.id.id_iv_loading);
|
||||
idTvText = view.findViewById(R.id.id_tv_text);
|
||||
clContent = view.findViewById(R.id.cl_content);
|
||||
|
||||
Animation animation = AnimationUtils.loadAnimation(activity, R.anim.rotate_anim);
|
||||
idIvLoading.startAnimation(animation);
|
||||
|
||||
setContentView(view);
|
||||
Window window = getWindow();
|
||||
if (window != null) {
|
||||
if (mode == Mode.ACTIVATION_SMALL) {
|
||||
window.setLayout(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT);
|
||||
} else {
|
||||
window.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
|
||||
WindowManager.LayoutParams.MATCH_PARENT);
|
||||
}
|
||||
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
window.getDecorView().setSystemUiVisibility(
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||
window.setDimAmount(0f);
|
||||
}
|
||||
setCancelable(false);
|
||||
setCanceledOnTouchOutside(false);
|
||||
getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
|
||||
setOnKeyListener(new OnKeyListener() {
|
||||
@Override
|
||||
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
|
||||
return keyCode == KeyEvent.KEYCODE_BACK;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setText(@StringRes int textResId) {
|
||||
if (idTvText != null) {
|
||||
idTvText.setText(textResId);
|
||||
}
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
if (idTvText != null) {
|
||||
idTvText.setText(text);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
if (activity == null || activity.isFinishing() || activity.isDestroyed()) {
|
||||
return;
|
||||
}
|
||||
if (super.isShowing()) {
|
||||
return;
|
||||
}
|
||||
long now = SystemClock.elapsedRealtime();
|
||||
if (now - lastDismissTimestamp < SHOW_DISMISS_INTERVAL_MS) {
|
||||
return;
|
||||
}
|
||||
super.show();
|
||||
lastShowTimestamp = now;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismiss() {
|
||||
if (!super.isShowing()) {
|
||||
return;
|
||||
}
|
||||
long now = SystemClock.elapsedRealtime();
|
||||
if (now - lastShowTimestamp < SHOW_DISMISS_INTERVAL_MS) {
|
||||
return;
|
||||
}
|
||||
super.dismiss();
|
||||
lastDismissTimestamp = now;
|
||||
}
|
||||
}
|
||||
206
app/src/main/java/com/pukka/jiecheng/utils/CrashHandler.java
Executable file
206
app/src/main/java/com/pukka/jiecheng/utils/CrashHandler.java
Executable file
@@ -0,0 +1,206 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.pukka.jiecheng.MainActivity;
|
||||
import com.pukka.libcore.utils.AppManager;
|
||||
import com.pukka.libcore.utils.DateUtils;
|
||||
import com.pukka.libcore.utils.LogUtils;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Author: wxf
|
||||
* Date: 2023/4/25 15:44
|
||||
* Description:全局异常捕获
|
||||
*/
|
||||
public class CrashHandler implements Thread.UncaughtExceptionHandler {
|
||||
private static final String TAG = CrashHandler.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* 程序Context对象
|
||||
*/
|
||||
private Context context;
|
||||
|
||||
/**
|
||||
* 系统默认的UncaughtException处理类
|
||||
*/
|
||||
private Thread.UncaughtExceptionHandler defalutHandler;
|
||||
|
||||
/**
|
||||
* 用来存储设备信息和异常信息
|
||||
*/
|
||||
private final Map<String, String> infos = new HashMap<String, String>();
|
||||
|
||||
private CrashHandler() {
|
||||
}
|
||||
|
||||
private static final class InstanceHolder {
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
static final CrashHandler INSTANCE = new CrashHandler(); // 单例模式
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取CrashHandler实例
|
||||
*
|
||||
* @return CrashHandler
|
||||
*/
|
||||
public static CrashHandler getInstance() {
|
||||
return InstanceHolder.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 异常处理初始化
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
public void init(Context context) {
|
||||
this.context = context;
|
||||
// 获取系统默认的UncaughtException处理器
|
||||
defalutHandler = Thread.getDefaultUncaughtExceptionHandler();
|
||||
// 设置该CrashHandler为程序的默认处理器
|
||||
Thread.setDefaultUncaughtExceptionHandler(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当UncaughtException发生时会转入该函数来处理
|
||||
*/
|
||||
@Override
|
||||
public void uncaughtException(@NonNull Thread thread, @NonNull Throwable ex) {
|
||||
Log.i(TAG, "uncaughtException=====" + "crash UncaughtExceptionHandler ");
|
||||
// 自定义错误处理
|
||||
boolean res = handleException(ex);
|
||||
if (!res && defalutHandler != null) {
|
||||
// 如果用户没有处理则让系统默认的异常处理器来处理
|
||||
defalutHandler.uncaughtException(thread, ex);
|
||||
|
||||
} else {
|
||||
Log.i(TAG, "uncaughtException=====" + "kill app");
|
||||
Activity activity = AppManager.getAppManager().currentActivity();
|
||||
|
||||
if (activity instanceof MainActivity) {
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
System.exit(1);
|
||||
} else {
|
||||
Intent intent = new Intent(context, MainActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(intent);
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
|
||||
*
|
||||
* @param ex
|
||||
* @return true:如果处理了该异常信息;否则返回false.
|
||||
*/
|
||||
private boolean handleException(final Throwable ex) {
|
||||
LogUtils.e("handleException=====" + "自定义错误处理,收集错误信息 发送错误报告等操作均在此完成");
|
||||
|
||||
//MGJSEPG-12834
|
||||
if (ex == null || ex.getMessage() == null) {
|
||||
return false;
|
||||
}
|
||||
LogUtils.d("uncaughtException:" + ex.getMessage());
|
||||
Log.e(TAG, "uncaughtException:\n", ex);
|
||||
// 收集设备参数信息 \日志信息
|
||||
collectDeviceInfo(context);
|
||||
// 保存日志文件
|
||||
saveCrashInfo2File(context, ex);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存错误信息到文件中
|
||||
*
|
||||
* @param ex
|
||||
*/
|
||||
private void saveCrashInfo2File(Context context, Throwable ex) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Map.Entry<String, String> entry : infos.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
String value = entry.getValue();
|
||||
sb.append(key).append("=").append(value).append("\n");
|
||||
}
|
||||
|
||||
Writer writer = new StringWriter();
|
||||
PrintWriter printWriter = new PrintWriter(writer);
|
||||
ex.printStackTrace(printWriter);
|
||||
Throwable cause = ex.getCause();
|
||||
while (cause != null) {
|
||||
cause.printStackTrace(printWriter);
|
||||
cause = cause.getCause();
|
||||
}
|
||||
printWriter.close();
|
||||
String result = writer.toString();
|
||||
sb.append(result);
|
||||
try {
|
||||
long timestamp = System.currentTimeMillis();
|
||||
String time = DateUtils.getStringNowDate();
|
||||
String fileName = "crash-" + time + "-" + timestamp + ".log";
|
||||
File dir = new File(context.getFilesDir() + "/crash");
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
}
|
||||
OutputStreamWriter write =
|
||||
new OutputStreamWriter(new FileOutputStream(dir.getAbsolutePath() + fileName), "UTF-8");
|
||||
BufferedWriter fileWrite = new BufferedWriter(write);
|
||||
fileWrite.write(sb.toString());
|
||||
fileWrite.close();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "an error occured while writing file...", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 收集设备参数信息
|
||||
*
|
||||
* @param ctx
|
||||
*/
|
||||
public void collectDeviceInfo(Context ctx) {
|
||||
try {
|
||||
PackageManager pm = ctx.getPackageManager();
|
||||
PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);
|
||||
if (pi != null) {
|
||||
String versionName = pi.versionName == null ? "null" : pi.versionName;
|
||||
String versionCode = pi.versionCode + "";
|
||||
infos.put("versionName", versionName);
|
||||
infos.put("versionCode", versionCode);
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
LogUtils.e("an error occured when collect package info");
|
||||
}
|
||||
Field[] fields = Build.class.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
infos.put(field.getName(), field.get(null).toString());
|
||||
LogUtils.e(field.getName() + " : " + field.get(null));
|
||||
} catch (Exception e) {
|
||||
LogUtils.e("an error occured when collect crash info");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
96
app/src/main/java/com/pukka/jiecheng/utils/DataValueUtils.java
Executable file
96
app/src/main/java/com/pukka/jiecheng/utils/DataValueUtils.java
Executable file
@@ -0,0 +1,96 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
//
|
||||
// Source code recreated from a .class file by IntelliJ IDEA
|
||||
// (powered by FernFlower decompiler)
|
||||
//
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import org.json.JSONException;
|
||||
|
||||
public class DataValueUtils {
|
||||
private static final String TAG = "DataValueUtils";
|
||||
|
||||
public DataValueUtils() {
|
||||
}
|
||||
|
||||
public static String getDataValues(String dataAll, String... valueKeys) {
|
||||
String value = dataAll;
|
||||
|
||||
try {
|
||||
for(int i = 0; i < valueKeys.length; ++i) {
|
||||
JSONObject jsonObject = JSON.parseObject(value);
|
||||
value = jsonObject.getString(valueKeys[i]);
|
||||
if (i == valueKeys.length - 1) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
} catch (Exception var5) {
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public static String setDataValue(String dataAll, String keys, String values) {
|
||||
try {
|
||||
JSONObject json = null;
|
||||
json = JSONObject.parseObject(dataAll);
|
||||
Set<String> keySet = json.keySet();
|
||||
Iterator var5 = keySet.iterator();
|
||||
|
||||
while(true) {
|
||||
while(var5.hasNext()) {
|
||||
String key = (String)var5.next();
|
||||
Object obj = json.get(key);
|
||||
if (obj instanceof JSONArray) {
|
||||
JSONArray arr = (JSONArray)obj;
|
||||
|
||||
for(int i = 0; i < arr.size(); ++i) {
|
||||
String child = setDataValue(arr.get(i).toString(), keys, values);
|
||||
arr.set(i, JSONObject.parse(child));
|
||||
}
|
||||
|
||||
json.put(key, arr);
|
||||
} else if (obj instanceof JSONObject) {
|
||||
JSONObject sub = (JSONObject)obj;
|
||||
String substr = setDataValue(sub.toJSONString(), keys, values);
|
||||
json.put(key, JSONObject.parse(substr));
|
||||
} else if (key.equals(keys)) {
|
||||
json.put(key, values);
|
||||
}
|
||||
}
|
||||
|
||||
return json.toJSONString();
|
||||
}
|
||||
} catch (Exception var11) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public static org.json.JSONObject toJSONObject(String dataAll) {
|
||||
org.json.JSONObject jsonObject = new org.json.JSONObject();
|
||||
|
||||
try {
|
||||
JSONObject json = null;
|
||||
json = JSONObject.parseObject(dataAll);
|
||||
Set<String> keySet = json.keySet();
|
||||
Iterator var4 = keySet.iterator();
|
||||
|
||||
while(var4.hasNext()) {
|
||||
String key = (String)var4.next();
|
||||
Object obj = json.get(key);
|
||||
jsonObject.put(key, obj);
|
||||
}
|
||||
|
||||
return jsonObject;
|
||||
} catch (JSONException var7) {
|
||||
var7.printStackTrace();
|
||||
return jsonObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
47
app/src/main/java/com/pukka/jiecheng/utils/GridSpacingItemDecoration.java
Executable file
47
app/src/main/java/com/pukka/jiecheng/utils/GridSpacingItemDecoration.java
Executable file
@@ -0,0 +1,47 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
/**
|
||||
* @Auther: sunmm
|
||||
* @datetime: 2025/4/17 9:46
|
||||
* @desc:
|
||||
*/
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {
|
||||
private final int spanCount;
|
||||
private final int spacing;
|
||||
private final boolean includeEdge;
|
||||
|
||||
public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) {
|
||||
this.spanCount = spanCount;
|
||||
this.spacing = spacing;
|
||||
this.includeEdge = includeEdge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
|
||||
int position = parent.getChildAdapterPosition(view);
|
||||
int column = position % spanCount;
|
||||
int currentRow = position / spanCount;
|
||||
if (includeEdge) {
|
||||
outRect.left = spacing - column * spacing / spanCount;
|
||||
outRect.right = (column + 1) * spacing / spanCount;
|
||||
if (position < spanCount) outRect.top = spacing;
|
||||
outRect.bottom = spacing;
|
||||
} else {
|
||||
outRect.left = column * spacing / spanCount;
|
||||
outRect.right = spacing - (column + 1) * spacing / spanCount;
|
||||
|
||||
// 行间距处理
|
||||
if (currentRow > 0) {
|
||||
// 第二行 - 使用边缘行间距
|
||||
outRect.top = spacing;
|
||||
}
|
||||
//if (position >= spanCount) outRect.top = spacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
63
app/src/main/java/com/pukka/jiecheng/utils/IsLoginTimerUtil.java
Executable file
63
app/src/main/java/com/pukka/jiecheng/utils/IsLoginTimerUtil.java
Executable file
@@ -0,0 +1,63 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import com.pukka.jiecheng.login.viewmodel.IsLoginViewModel;
|
||||
import com.pukka.jiecheng.order.viewmodel.OrderViewModel;
|
||||
import com.pukka.libcore.boxShared.BoxSharedParameters;
|
||||
import com.pukka.libcore.threading.DispatchQueue;
|
||||
import com.pukka.libcore.utils.LogUtils;
|
||||
|
||||
/**
|
||||
* 微信小程序是否登录轮询工具类
|
||||
* */
|
||||
public class IsLoginTimerUtil {
|
||||
private static IsLoginTimerUtil isLoginTimerUtil;
|
||||
private static final Object LOCK = new Object();
|
||||
private Runnable timerRunnable;
|
||||
//是否在登录页面开启过轮询
|
||||
private boolean isStartTimer = false;
|
||||
public static IsLoginTimerUtil getInstance() {
|
||||
synchronized (LOCK) {
|
||||
if (null == isLoginTimerUtil) {
|
||||
isLoginTimerUtil = new IsLoginTimerUtil();
|
||||
}
|
||||
return isLoginTimerUtil;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 定时器监听
|
||||
*/
|
||||
public void startTimer(IsLoginViewModel isLoginViewModel) {
|
||||
isStartTimer = true;
|
||||
stopTimer();
|
||||
timerRunnable = () -> isLogin(isLoginViewModel);
|
||||
//3s轮询
|
||||
DispatchQueue.global.timer(500, 3000, timerRunnable);
|
||||
}
|
||||
|
||||
public void stopTimer() {
|
||||
if (null != timerRunnable) {
|
||||
LogUtils.i("stopTimer()");
|
||||
DispatchQueue.global.remove(timerRunnable);
|
||||
timerRunnable = null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 轮询接口
|
||||
*/
|
||||
public void isLogin(IsLoginViewModel isLoginViewModel) {
|
||||
if(null != isLoginViewModel){
|
||||
if(BoxSharedParameters.getInstance().isLogin()){
|
||||
LogUtils.d("用户已经登录,暂停轮询是否登录接口");
|
||||
stopTimer();
|
||||
return;
|
||||
}
|
||||
isLoginViewModel.isLogin();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 是否在登录页面开启过轮询
|
||||
*/
|
||||
public boolean isStartTimer() {
|
||||
return isStartTimer;
|
||||
}
|
||||
}
|
||||
163
app/src/main/java/com/pukka/jiecheng/utils/ItemOnClickUtils.java
Executable file
163
app/src/main/java/com/pukka/jiecheng/utils/ItemOnClickUtils.java
Executable file
@@ -0,0 +1,163 @@
|
||||
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
import com.google.gson.Gson;
|
||||
import com.migu.bean.GetLayoutBean;
|
||||
import com.pukka.jiecheng.filter.FilterActivity;
|
||||
import com.pukka.jiecheng.index.IndexAmberManager;
|
||||
import com.pukka.jiecheng.index.IndexConstant;
|
||||
import com.pukka.jiecheng.video.VideoDetailActivity;
|
||||
import com.pukka.libcore.base.BaseUrl;
|
||||
import com.pukka.libcore.base.BuildConfig;
|
||||
import com.pukka.libcore.utils.AppUtils;
|
||||
import com.pukka.libcore.utils.JsonUtils;
|
||||
import com.pukka.libcore.utils.LogUtils;
|
||||
import com.pukka.libcore.utils.StringUtils;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Author: wxf
|
||||
* Date: 2023/3/15 16:19
|
||||
* Description:首页点击处理
|
||||
*/
|
||||
public class ItemOnClickUtils {
|
||||
|
||||
// 首页推荐位点击处理
|
||||
@SuppressLint("WrongConstant")
|
||||
public static void indexItemOnClick(View view, GetLayoutBean.DataBean floor, int position, Context mContext) {
|
||||
GetLayoutBean.DataBean.ExtraDataBean mItemData = floor.getExtraData().get(position);
|
||||
if (mItemData == null) {
|
||||
return;
|
||||
}
|
||||
IndexAmberManager.recommendClick(mItemData,(position+1)+"");
|
||||
String targetType = mItemData.getType();
|
||||
LogUtils.d("getType-----" + targetType);
|
||||
switch (targetType) {
|
||||
// 点播详情页
|
||||
case "1":
|
||||
String showType = mItemData.getShowtype();
|
||||
if(StringUtils.isEmpty(showType) || showType.equals("1")){
|
||||
LogUtils.d("视频推荐位==");
|
||||
String reserved = mItemData.getReserved1();
|
||||
if(!StringUtils.isEmpty(reserved)) {
|
||||
try {
|
||||
JSONObject jsonObject = new JSONObject(reserved);
|
||||
String code = jsonObject.getString("code");
|
||||
LogUtils.d("vod reserved getContentcode=" + code);
|
||||
if (!TextUtils.isEmpty(code)) {
|
||||
MgRoute.go2DetailActivity(mContext, code);
|
||||
} else {
|
||||
Toast.makeText(mContext, "未找到内容id", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}catch (Exception exception){
|
||||
exception.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
LogUtils.d("vod getContentcode=" + mItemData.getContentcode());
|
||||
if (!TextUtils.isEmpty(mItemData.getContentcode())) {
|
||||
MgRoute.go2DetailActivity(mContext, mItemData.getContentcode());
|
||||
} else {
|
||||
Toast.makeText(mContext, "未找到内容id", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LogUtils.d("普通推荐位 vod getContentcode=" + mItemData.getContentcode());
|
||||
if (!TextUtils.isEmpty(mItemData.getContentcode())) {
|
||||
MgRoute.go2DetailActivity(mContext, mItemData.getContentcode());
|
||||
} else {
|
||||
Toast.makeText(mContext, "未找到内容id", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
break;
|
||||
// 点播播放页
|
||||
case "2":
|
||||
if(!StringUtils.isEmpty(mItemData.getReserved1())) {
|
||||
try {
|
||||
JSONObject jsonObject = new JSONObject(mItemData.getReserved1());
|
||||
String code1 = jsonObject.getString("code");
|
||||
LogUtils.d("vod reserved getContentcode=" + code1);
|
||||
if (!TextUtils.isEmpty(code1)) {
|
||||
MgRoute.go2DetailActivity(mContext, code1);
|
||||
} else {
|
||||
Toast.makeText(mContext, "未找到内容id", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}catch (Exception exception){
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}else {
|
||||
LogUtils.d("vod getContentcode=" + mItemData.getContentcode());
|
||||
if (!TextUtils.isEmpty(mItemData.getContentcode())) {
|
||||
MgRoute.go2FullPlayerActivity(mContext, mItemData.getContentcode());
|
||||
} else {
|
||||
Toast.makeText(mContext, "未找到内容id", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
break;
|
||||
// 列表页
|
||||
case "3":
|
||||
String listParam = mItemData.getPlayurl();
|
||||
if (!TextUtils.isEmpty(listParam)) {
|
||||
String[] split = listParam.split("&");
|
||||
String listId="";
|
||||
String parentId="";
|
||||
if (split.length>=2){
|
||||
// 子栏目id
|
||||
listId = split[0];
|
||||
// 父栏目id
|
||||
parentId = split[1];
|
||||
}else if (split.length == 1){
|
||||
parentId = listParam;
|
||||
}
|
||||
MgRoute.go2ListActivity(mContext,parentId,listId);
|
||||
} else {
|
||||
Toast.makeText(mContext, "未找到栏目id", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
break;
|
||||
// 外链
|
||||
case "5":
|
||||
String url =mItemData.getPlayurl();
|
||||
if(!StringUtils.isEmpty(url)) {
|
||||
MgRoute.go2SimpleWebActivity(mContext, url);
|
||||
}else{
|
||||
Toast.makeText(mContext, "没有配置外链地址", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
break;
|
||||
// 跳转APK
|
||||
case "6":
|
||||
String playurl = mItemData.getPlayurl();
|
||||
if(!StringUtils.isEmpty(playurl)){
|
||||
LogUtils.d("playUrl="+playurl);
|
||||
String[] strings = playurl.split("&&");
|
||||
if(strings.length>1){
|
||||
String packageName = strings[0];
|
||||
String className = strings[1];
|
||||
LogUtils.d("packageName="+packageName+" className="+className);
|
||||
AppUtils.startApkByPackageAndClass(mContext,packageName,className);
|
||||
}else{
|
||||
AppUtils.startApkByPackageAndClass(mContext,playurl,"");
|
||||
}
|
||||
}else{
|
||||
Toast.makeText(mContext, "配置包名和类名为空", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
break;
|
||||
// 无动作
|
||||
case "7":
|
||||
break;
|
||||
case "8":
|
||||
FilterActivity.start(mContext);
|
||||
break;
|
||||
default:
|
||||
LogUtils.d("do nothing");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
656
app/src/main/java/com/pukka/jiecheng/utils/JetsenxSdkUtil.java
Executable file
656
app/src/main/java/com/pukka/jiecheng/utils/JetsenxSdkUtil.java
Executable file
@@ -0,0 +1,656 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.jetsenxsdk.api.JetsenxSdk;
|
||||
import com.jetsenxsdk.bean.VideoInfo;
|
||||
import com.jetsenxsdk.callback.JetsenxInitCallback;
|
||||
import com.jetsenxsdk.callback.JetsenxPricesCallback;
|
||||
import com.jetsenxsdk.callback.JetsenxUrlCallback;
|
||||
import com.pukka.jiecheng.newtv.NewTvUtils;
|
||||
import com.pukka.jiecheng.video.bean.PlayCodeBean;
|
||||
import com.pukka.jiecheng.video.utils.PlayRecordContentManager;
|
||||
import com.pukka.jiecheng.video.utils.PlayRecordManager;
|
||||
import com.pukka.jiecheng.video.utils.PlayRecordShortManager;
|
||||
import com.pukka.libcore.base.BaseConst;
|
||||
import com.pukka.libcore.boxShared.BoxSharedParameters;
|
||||
import com.pukka.libcore.boxShared.MacUtils;
|
||||
import com.pukka.libcore.threading.DispatchQueue;
|
||||
import com.pukka.libcore.utils.LogUtils;
|
||||
import com.pukka.libcore.utils.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* [获取播放串]<BR>
|
||||
*
|
||||
* @author wxf
|
||||
* @version [V0.1.0.1, 2025/5/23 0027]
|
||||
* @since V0.1.0.1
|
||||
*/
|
||||
public class JetsenxSdkUtil {
|
||||
public static String AGCODE = "1100101010208919998410060";
|
||||
public static String TENANT = "huashitv";
|
||||
public static String ACCESSER = "JSTPKTEST";
|
||||
public static String SECRET = "utudfD9gVU94r52D";
|
||||
private static final String TAG = "JetsenxSdkUtil";
|
||||
|
||||
private static Handler orderTimeOutHandler = new Handler();
|
||||
|
||||
private static Thread thread;
|
||||
|
||||
private static String productCodeSp;
|
||||
|
||||
private static String sUid = "";
|
||||
|
||||
/**
|
||||
* 第三方变体(thirdparty)EPG 传入的 MAC 覆盖。
|
||||
*
|
||||
* 背景:EPG 在后端用该 MAC 注册设备并下发卡密(thirdCardNo),SDK init 必须用同一 MAC
|
||||
* 才能与后端权益绑定匹配;若回退 MacUtils.getMac 本机自采集 MAC,会导致权益不生效。
|
||||
* 为空时回退本机自采集(原版行为不变)。
|
||||
* 进程级静态:ThirdPartyEntryActivity 解析 Intent extras 时设置。
|
||||
*/
|
||||
private static volatile String sMacOverride = "";
|
||||
|
||||
/**
|
||||
* 设置 SDK init 的 MAC 覆盖值(EPG 传入的 mac 优先)。
|
||||
* 传空字符串/null 清除覆盖,恢复本机自采集。
|
||||
*/
|
||||
public static void setMacOverride(String mac) {
|
||||
String normalized = mac == null ? "" : mac.trim();
|
||||
if (normalized.equals(sMacOverride)) {
|
||||
return;
|
||||
}
|
||||
sMacOverride = normalized;
|
||||
LogUtils.d(TAG, "setMacOverride: " + (TextUtils.isEmpty(normalized) ? "<cleared>" : normalized));
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取 SDK init 的 MAC 覆盖值(空串表示未设置)。
|
||||
*/
|
||||
public static String getMacOverride() {
|
||||
return sMacOverride;
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记当前是否有 re-init 正在进行,保证 globalInit 串行执行
|
||||
* volatile 确保多线程可见性,synchronized 块保证检查-置位原子性
|
||||
*/
|
||||
private static volatile boolean sReInitializing = false;
|
||||
|
||||
/**
|
||||
* 等待中的 re-init 请求队列(FIFO),前一个 init 完成后依次触发下一个
|
||||
* 避免多个 JetsenxSdk.init 并发执行损坏 SDK 内部鉴权状态
|
||||
*/
|
||||
private static final List<InitTask> sPendingReInitQueue = new ArrayList<>();
|
||||
|
||||
public interface InitMemberCodeCallback {
|
||||
void onSuccess(String memberCode);
|
||||
void onFail(String message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 封装一次 re-init 请求的上下文与回调,用于排队等待
|
||||
*/
|
||||
private static class InitTask {
|
||||
final Context context;
|
||||
final InitMemberCodeCallback callback;
|
||||
|
||||
InitTask(Context context, InitMemberCodeCallback callback) {
|
||||
this.context = context;
|
||||
this.callback = callback;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*
|
||||
* @param context 上下文
|
||||
* @param agcode 捷成华视网聚分配的渠道号
|
||||
* @param mac mac 可以传空
|
||||
* @param uid uid 用户的唯一标识
|
||||
* @param tenant 租户
|
||||
* @param secret 秘钥
|
||||
* @param accesser 请求者账号
|
||||
* @param utype 用户类型 1-手机号,2-三方ID,3-mac,4-sn,5-其他
|
||||
* @param extendJson 拓展数据
|
||||
*/
|
||||
public static void init(Context context, String agcode, String mac, String uid, String tenant, String secret, String accesser, String utype,
|
||||
String extendJson) {
|
||||
init(context, agcode, mac, uid, tenant, secret, accesser, utype, extendJson, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局初始化方法,复用已缓存的 uid
|
||||
*
|
||||
* @param context 上下文
|
||||
* @param callback 初始化结果回调
|
||||
*/
|
||||
public static void globalInit(Context context, InitMemberCodeCallback callback) {
|
||||
if (TextUtils.isEmpty(sUid)) {
|
||||
LogUtils.d(TAG, "globalInit skipped: no verified uid cached in current process");
|
||||
if (callback != null) {
|
||||
callback.onFail("缺少可复用的SDK初始化标识");
|
||||
}
|
||||
return;
|
||||
}
|
||||
synchronized (sPendingReInitQueue) {
|
||||
if (sReInitializing) {
|
||||
// 已有 init 在飞行中:本次请求入队等待,避免并发 init 损坏 SDK 内部状态
|
||||
sPendingReInitQueue.add(new InitTask(context, callback));
|
||||
LogUtils.d(TAG, "globalInit queued: another re-init in flight, pending=" + sPendingReInitQueue.size());
|
||||
return;
|
||||
}
|
||||
sReInitializing = true;
|
||||
}
|
||||
// 首个请求:真正调用 SDK init,用内部包装回调统一放行下一个排队请求
|
||||
// try-catch 保护 SDK 同步抛异常的场景:放行队列避免永久锁死,回调 onFail 避免异常上抛调用方线程
|
||||
try {
|
||||
init(context, sUid, new InitMemberCodeCallback() {
|
||||
@Override
|
||||
public void onSuccess(String memberCode) {
|
||||
dispatchNextReInit();
|
||||
if (callback != null) {
|
||||
try {
|
||||
callback.onSuccess(memberCode);
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "globalInit onSuccess callback exception: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(String message) {
|
||||
dispatchNextReInit();
|
||||
if (callback != null) {
|
||||
try {
|
||||
callback.onFail(message);
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "globalInit onFail callback exception: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
LogUtils.e(TAG, "globalInit init invoke exception: " + e.getMessage());
|
||||
// SDK init 同步异常:sReInitializing 已置 true,必须放行队列,否则后续请求永久排队
|
||||
dispatchNextReInit();
|
||||
if (callback != null) {
|
||||
try {
|
||||
callback.onFail("SDK初始化调用异常: " + e.getMessage());
|
||||
} catch (Exception ce) {
|
||||
LogUtils.e(TAG, "globalInit onFail callback exception: " + ce.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前 re-init 完成后,放行队列中下一个等待请求
|
||||
* 下一个请求重新走 globalInit 入口,sReInitializing 已置 false 会真正执行 init,串行逻辑闭环
|
||||
*/
|
||||
private static void dispatchNextReInit() {
|
||||
InitTask next;
|
||||
synchronized (sPendingReInitQueue) {
|
||||
sReInitializing = false;
|
||||
next = sPendingReInitQueue.isEmpty() ? null : sPendingReInitQueue.remove(0);
|
||||
}
|
||||
if (next != null) {
|
||||
globalInit(next.context, next.callback);
|
||||
}
|
||||
}
|
||||
|
||||
public static void cacheReusableUid(String uid) {
|
||||
if (TextUtils.isEmpty(uid)) {
|
||||
LogUtils.d(TAG, "cacheReusableUid ignored: empty uid");
|
||||
return;
|
||||
}
|
||||
sUid = uid;
|
||||
LogUtils.d(TAG, "cacheReusableUid success");
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取已缓存的 SDK uid。
|
||||
*
|
||||
* <p>该字段由 {@link #cacheReusableUid(String)} 写入,主要写入场景:
|
||||
* <ul>
|
||||
* <li>MainActivity.onActivated 收到 /api/jst/check 10200 时写入 thirdCardNo</li>
|
||||
* <li>VideoDetailActivity.onCheckActivated 收到 BenefitOrderController 阶段三 10200 时写入 thirdCardNo</li>
|
||||
* <li>VideoDetailActivity.onCheckActivated asAScan 10900 路径因 thirdCardNo 为空,不写入</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>外部使用场景:UI 入口短路(详情页进入时若 sUid 已存在,跳过扫码下单直接展示"已购买VIP")。
|
||||
* 注意:该字段为进程内静态变量,应用冷启动后为空,需等 MainActivity 启动时 /api/jst/check
|
||||
* 轮询填充后才能复用。</p>
|
||||
*
|
||||
* @return 已缓存的 uid;为空字符串表示未缓存
|
||||
*/
|
||||
public static String getSuid() {
|
||||
return sUid;
|
||||
}
|
||||
|
||||
public static void clearReusableUid() {
|
||||
sUid = "";
|
||||
LogUtils.d(TAG, "clearReusableUid: sUid cleared");
|
||||
}
|
||||
|
||||
/**
|
||||
* 简化的初始化方法
|
||||
*
|
||||
* @param context 上下文
|
||||
* @param uid 用户的唯一标识(如第三方卡号 thirdCardNo)
|
||||
* @param callback 初始化结果回调
|
||||
*/
|
||||
public static void init(Context context, String uid, InitMemberCodeCallback callback) {
|
||||
// EPG 传入的 MAC 覆盖优先(thirdparty 变体):后端权益以 EPG 注册的 MAC 绑定,
|
||||
// 本机自采集 MAC 与之不匹配会导致 SDK 鉴权失败、权益不生效
|
||||
String mac = TextUtils.isEmpty(sMacOverride) ? MacUtils.getMac(context) : sMacOverride;
|
||||
String utype = "2";
|
||||
if (!TextUtils.isEmpty(uid) && uid.matches("^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$")) {
|
||||
mac = uid;
|
||||
utype = "3";
|
||||
}
|
||||
init(context, AGCODE, mac, uid, TENANT, SECRET, ACCESSER, utype, "", callback);
|
||||
}
|
||||
|
||||
public static void init(Context context, String agcode, String mac, String uid, String tenant, String secret, String accesser, String utype,
|
||||
String extendJson, InitMemberCodeCallback callback) {
|
||||
LogUtils.d("渠道信息> agcode:" + agcode + " mac:" + mac + " uid:" + uid + " tenant:" + tenant + " secret:" + secret + " accesser:" + accesser + " utype:" + utype + " extendJson:" + extendJson + " comboCode:"+BaseConst.serviceComboCode);
|
||||
if (StringUtils.isEmpty(mac)) {
|
||||
//防止初始化报600错误,非法参数的错误,保底
|
||||
mac = "CC:8C:DA:C6:E9:9B";
|
||||
}
|
||||
//如果用户没有登录,获取不到手机号,则使用mac的方式初始化
|
||||
if(StringUtils.isEmpty(uid)){
|
||||
LogUtils.d("电话号码获取不到,使用Mac方式登录");
|
||||
utype = "3";
|
||||
uid = mac;
|
||||
}
|
||||
// JetsenxSdk.init(context, agcode, mac, uid, tenant, secret, accesser, utype, extendJson, new JetsenxInitCallback() {
|
||||
JetsenxSdk.init(context, agcode, mac, uid, tenant, secret, accesser, utype, extendJson,BaseConst.serviceComboCode, new JetsenxInitCallback() {
|
||||
|
||||
@Override
|
||||
public void onInitSuccess(String s, boolean b) {
|
||||
LogUtils.d("onInitSuccess()");
|
||||
if (callback != null) {
|
||||
callback.onSuccess(s);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(String s, String s1) {
|
||||
LogUtils.d("onFail s=" + s);
|
||||
LogUtils.d("onFail s1=" + s1);
|
||||
if (callback != null) {
|
||||
callback.onFail(StringUtils.isEmpty(s1) ? "SDK初始化失败" : s1);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 2.获取付费内容播放地址接口
|
||||
*
|
||||
* @param productCode 产品编码
|
||||
* @param programCode 节目编码
|
||||
*/
|
||||
public static void getVideoUrls(String productCode, String programCode) {
|
||||
LogUtils.d("productCode:" + productCode + " programCode:" + programCode);
|
||||
JetsenxSdk.getVideoUrls(productCode, programCode, new JetsenxUrlCallback() {
|
||||
@Override
|
||||
public void onVideoUrls(VideoInfo[] videoInfos) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(String s, String s1) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 未来播控一直不返回的处理的提示
|
||||
* */
|
||||
// public static void weiLaiCheckTimeOut(){
|
||||
// LogUtils.d("未来鉴权超时3秒,放通处理,继续播放");
|
||||
// //checkValue = true;
|
||||
// }
|
||||
// /**
|
||||
// * 未来鉴权是否通过 true 通过; false 不通过
|
||||
// * */
|
||||
// public static boolean checkValue = false;
|
||||
// /**
|
||||
// * 未来播控一直不返回的处理
|
||||
// */
|
||||
// private static Runnable mFeaturePlayRunnable;
|
||||
/**
|
||||
* 未来播控鉴权,超时处理
|
||||
* */
|
||||
public static void newtvCheckQuery(String programCode,String programName, GetVideoUrlCallback getVideoUrlCallback){
|
||||
// checkValue = false;
|
||||
// mFeaturePlayRunnable =()->getFreeVideoUrls(programCode,programName, getVideoUrlCallback);
|
||||
// DispatchQueue.main.remove(mFeaturePlayRunnable);
|
||||
// DispatchQueue.main.after(3000,mFeaturePlayRunnable);
|
||||
DispatchQueue.global.async(() -> {
|
||||
//String timeStartCheck = DateUtils.getStringNowDate();
|
||||
boolean checkValue = NewTvUtils.newtvCheckQuery(programCode, "program");
|
||||
//String timeEndCheck = DateUtils.getStringNowDate();
|
||||
//int timeSecond = DateUtils.getSecondCompareStringDate(timeStartCheck,timeEndCheck);
|
||||
//LogUtils.d("未来鉴权耗时:"+timeSecond);
|
||||
// if(timeSecond>3){
|
||||
// LogUtils.d("未来播控鉴权超时3秒,流程丢弃,已经在mFeaturePlayRunnable处理了");
|
||||
// }else{
|
||||
DispatchQueue.main.async(() -> {
|
||||
LogUtils.d("未来鉴权结果 checkValue="+checkValue);
|
||||
//DispatchQueue.main.remove(mFeaturePlayRunnable);
|
||||
if (checkValue) { //未来鉴权通过
|
||||
LogUtils.d("未来鉴权通过,获取播放地址");
|
||||
getFreeVideoUrls(programCode,programName, getVideoUrlCallback);
|
||||
} else {
|
||||
if(null != getVideoUrlCallback){
|
||||
//未来播控鉴权失败,1001,销毁播放器
|
||||
getVideoUrlCallback.onResponse("1001");
|
||||
}
|
||||
ToastUtils.showLongToast("该节目已下线");
|
||||
}
|
||||
});
|
||||
// }
|
||||
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 4、获取免费内容播放地址接口
|
||||
*
|
||||
* @param programCode 节目编码
|
||||
*/
|
||||
public static void getFreeVideoUrls(String programCode,String programName, GetVideoUrlCallback getVideoUrlCallback) {
|
||||
LogUtils.d("programCode:" + programCode);
|
||||
if (StringUtils.isEmpty(programCode)) {
|
||||
return;
|
||||
}
|
||||
JetsenxSdk.getFreeVideoUrls(programCode, new JetsenxUrlCallback() {
|
||||
@Override
|
||||
public void onVideoUrls(VideoInfo[] videoInfos) {
|
||||
if (null != videoInfos && videoInfos.length>0) {
|
||||
String videoUrl;
|
||||
NewTvUtils.sensorsPlayBean.init();
|
||||
NewTvUtils.sensorsPlayBean.setCpID(programCode);
|
||||
NewTvUtils.sensorsPlayBean.setCpName(programName);
|
||||
String videoUrl_1080="", videoUrl_720 = "";
|
||||
for (VideoInfo info:videoInfos
|
||||
) {
|
||||
if (info.getFormat().contains("720")
|
||||
&&TextUtils.isEmpty(videoUrl_720)){
|
||||
videoUrl_720 = info.getVideoUrl();
|
||||
PlayCodeBean playCodeBean = new PlayCodeBean();
|
||||
playCodeBean.setMovieCode(info.movieCode);
|
||||
playCodeBean.setProgramCode(info.progCode);
|
||||
playCodeBean.setSpecCode(info.specCode);
|
||||
PlayRecordShortManager.setPlayCodeBean(playCodeBean);
|
||||
PlayRecordContentManager.setPlayCodeBean(playCodeBean);
|
||||
}else if (info.getFormat().contains("1080")
|
||||
&&TextUtils.isEmpty(videoUrl_1080)){
|
||||
videoUrl_1080 = info.getVideoUrl();
|
||||
PlayCodeBean playCodeBean = new PlayCodeBean();
|
||||
playCodeBean.setMovieCode(info.movieCode);
|
||||
playCodeBean.setProgramCode(info.progCode);
|
||||
playCodeBean.setSpecCode(info.specCode);
|
||||
PlayRecordShortManager.setPlayCodeBean(playCodeBean);
|
||||
PlayRecordContentManager.setPlayCodeBean(playCodeBean);
|
||||
}
|
||||
}
|
||||
if (!TextUtils.isEmpty(videoUrl_1080)) {
|
||||
//高清
|
||||
videoUrl = videoUrl_1080;
|
||||
NewTvUtils.resolution = "0";
|
||||
LogUtils.d("videoUrl_1080:" + videoUrl_1080);
|
||||
} else {
|
||||
//标清
|
||||
videoUrl = videoUrl_720;
|
||||
NewTvUtils.resolution = "1";
|
||||
LogUtils.d("videoUrl_720:" + videoUrl_720);
|
||||
}
|
||||
LogUtils.d("videoUrl:" + videoUrl);
|
||||
if (null != getVideoUrlCallback) {
|
||||
getVideoUrlCallback.onResponse(videoUrl);
|
||||
}
|
||||
}else{
|
||||
if (null != getVideoUrlCallback) {
|
||||
//为短视频切换频道,销毁播放器
|
||||
LogUtils.d("没有获取到播放地址");
|
||||
getVideoUrlCallback.onResponse("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(String s, String s1) {
|
||||
LogUtils.d("onFail s=" + s);
|
||||
LogUtils.d("onFail s1=" + s1);
|
||||
getVideoUrlCallback.onResponse("");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void getAllVideoUrl(boolean isProgram, String parentContentType, String programCode, OnGetAllVideoUrlCallback onGetAllVideoUrlCallback) {
|
||||
LogUtils.d(TAG, "getAllVideoUrl parentContentType:" + parentContentType + " programCode:" + programCode);
|
||||
// isTimeOut = -1;
|
||||
// if (thread != null) {
|
||||
// thread.interrupt();
|
||||
// }
|
||||
// orderTimeOutHandler.removeCallbacksAndMessages(null);
|
||||
if (BoxSharedParameters.getInstance().isNewTvPass()) {
|
||||
LogUtils.d(TAG, "getAllVideoUrl 未来鉴权放通");
|
||||
getAllVideoUrlNext(parentContentType, programCode, onGetAllVideoUrlCallback);
|
||||
return;
|
||||
}
|
||||
|
||||
DispatchQueue.global.async(() -> {
|
||||
try {
|
||||
boolean isOrderOk = NewTvUtils.newtvCheckQuery(programCode, isProgram ? "program" : "programset");
|
||||
if (isOrderOk) {
|
||||
LogUtils.d(TAG, "getAllVideoUrl 未来鉴权成功");
|
||||
getAllVideoUrlNext(parentContentType, programCode, onGetAllVideoUrlCallback);
|
||||
} else {
|
||||
LogUtils.d(TAG, "getAllVideoUrl 未来鉴权失败");
|
||||
onGetAllVideoUrlCallback.onErr("1111", "该节目已下线");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Task interrupted");
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
// thread = new Thread(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// try {
|
||||
// boolean isOrderOk = NewTvUtils.newtvCheckQuery(programCode, isProgram ? "program" : "programset");
|
||||
// if (isTimeOut == 2) {
|
||||
// return;
|
||||
// }
|
||||
// isTimeOut = 1;
|
||||
// if (isOrderOk) {
|
||||
// orderTimeOutHandler.removeCallbacksAndMessages(null);
|
||||
// LogUtils.d(TAG, "getAllVideoUrl 未来鉴权成功");
|
||||
// getAllVideoUrlNext(parentContentType, programCode, onGetAllVideoUrlCallback);
|
||||
// } else {
|
||||
// LogUtils.d(TAG, "getAllVideoUrl 未来鉴权失败");
|
||||
// onGetAllVideoUrlCallback.onErr("1111", "该节目已下线");
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// System.out.println("Task interrupted");
|
||||
// Thread.currentThread().interrupt();
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// thread.start();
|
||||
// orderTimeOutHandler.postDelayed(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// if (isTimeOut == -1) {
|
||||
// isTimeOut = 2;
|
||||
// LogUtils.d(TAG, "getAllVideoUrl 未来鉴权超时");
|
||||
// getAllVideoUrlNext(parentContentType, programCode, onGetAllVideoUrlCallback);
|
||||
// }
|
||||
// }
|
||||
// }, 5000);
|
||||
}
|
||||
|
||||
// private static int isTimeOut = -1;
|
||||
|
||||
private static void getAllVideoUrlNext(String parentContentType, String programCode, OnGetAllVideoUrlCallback onGetAllVideoUrlCallback) {
|
||||
if (!TextUtils.isEmpty(productCodeSp)) {
|
||||
getAllVideoUrl2(parentContentType, productCodeSp, programCode, onGetAllVideoUrlCallback);
|
||||
} else {
|
||||
JetsenxSdk.getAllAssetPrices(ACCESSER, SECRET, new JetsenxPricesCallback() {
|
||||
@Override
|
||||
public void onAllAssetPrices(List<Map<String, Object>> list) {
|
||||
if (null != list) {
|
||||
LogUtils.d(TAG, "onAllAssetPrices list.size:" + list.size());
|
||||
String productCode = list.get(0).get("packageCode").toString();
|
||||
LogUtils.d(TAG, "packageCode:" + productCode);
|
||||
productCodeSp = productCode;
|
||||
getAllVideoUrl2(parentContentType, productCode, programCode, onGetAllVideoUrlCallback);
|
||||
} else {
|
||||
onGetAllVideoUrlCallback.onErr("-2", "productCode is NULL");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(String s, String s1) {
|
||||
LogUtils.d(TAG, "onFail s=" + s);
|
||||
LogUtils.d(TAG, "onFail s1=" + s1);
|
||||
onGetAllVideoUrlCallback.onErr(s, s1);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static void getAllVideoUrl2(String parentContentType, String productCode, String programCode, OnGetAllVideoUrlCallback onGetAllVideoUrlCallback) {
|
||||
LogUtils.d(TAG, "videoUrl parentContentType:" + parentContentType);
|
||||
if (TextUtils.isEmpty(parentContentType)) {
|
||||
onGetAllVideoUrlCallback.onErr("-1", "parentContentType is NULL");
|
||||
} else if (!parentContentType.equals("8")) {
|
||||
getVideoUrls2(productCode, programCode, onGetAllVideoUrlCallback);
|
||||
} else {
|
||||
getFreeVideoUrls2(programCode, onGetAllVideoUrlCallback);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void getVideoUrls2(String productCode, String programCode, OnGetAllVideoUrlCallback onGetAllVideoUrlCallback) {
|
||||
LogUtils.d(TAG, "videoUrl productCode:" + productCode + " programCode:" + programCode);
|
||||
JetsenxSdk.getVideoUrls(productCode, programCode, new JetsenxUrlCallback() {
|
||||
@Override
|
||||
public void onVideoUrls(VideoInfo[] videoInfos) {
|
||||
LogUtils.d(TAG, "videoUrl_all:" + Arrays.toString(videoInfos));
|
||||
if (null != videoInfos && videoInfos.length>0) {
|
||||
String videoUrl_1080="", videoUrl_720 = "";
|
||||
for (VideoInfo info:videoInfos
|
||||
) {
|
||||
if (info.getFormat().contains("720")
|
||||
&&TextUtils.isEmpty(videoUrl_720)){
|
||||
videoUrl_720 = info.getVideoUrl();
|
||||
PlayCodeBean playCodeBean = new PlayCodeBean();
|
||||
playCodeBean.setMovieCode(info.movieCode);
|
||||
playCodeBean.setProgramCode(info.progCode);
|
||||
playCodeBean.setSpecCode(info.specCode);
|
||||
PlayRecordManager.playCodeMaps.put(720,playCodeBean);
|
||||
}else if (info.getFormat().contains("1080")
|
||||
&&TextUtils.isEmpty(videoUrl_1080)){
|
||||
videoUrl_1080 = info.getVideoUrl();
|
||||
PlayCodeBean playCodeBean = new PlayCodeBean();
|
||||
playCodeBean.setMovieCode(info.movieCode);
|
||||
playCodeBean.setProgramCode(info.progCode);
|
||||
playCodeBean.setSpecCode(info.specCode);
|
||||
PlayRecordManager.playCodeMaps.put(1080,playCodeBean);
|
||||
}
|
||||
}
|
||||
LogUtils.d(TAG, "videoUrl_1080:" + videoUrl_1080);
|
||||
LogUtils.d(TAG, "videoUrl_720:" + videoUrl_720);
|
||||
if (null != onGetAllVideoUrlCallback) {
|
||||
onGetAllVideoUrlCallback.onResponse(videoUrl_1080, videoUrl_720, false);
|
||||
}
|
||||
}else {
|
||||
onGetAllVideoUrlCallback.onErr("411", "未返回播放地址");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(String s, String s1) {
|
||||
LogUtils.d(TAG, "videoUrl onFail:" + s + " msg:" + s1);
|
||||
onGetAllVideoUrlCallback.onErr(s, s1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void getFreeVideoUrls2(String programCode, OnGetAllVideoUrlCallback onGetAllVideoUrlCallback) {
|
||||
LogUtils.d(TAG, "videoUrl programCode:" + programCode);
|
||||
if (StringUtils.isEmpty(programCode)) {
|
||||
return;
|
||||
}
|
||||
JetsenxSdk.getFreeVideoUrls(programCode, new JetsenxUrlCallback() {
|
||||
@Override
|
||||
public void onVideoUrls(VideoInfo[] videoInfos) {
|
||||
if (null != videoInfos && videoInfos.length>0) {
|
||||
String videoUrl_1080="", videoUrl_720 = "";
|
||||
for (VideoInfo info:videoInfos
|
||||
) {
|
||||
if (info.getFormat().contains("720")
|
||||
&&TextUtils.isEmpty(videoUrl_720)){
|
||||
videoUrl_720 = info.getVideoUrl();
|
||||
PlayCodeBean playCodeBean = new PlayCodeBean();
|
||||
playCodeBean.setMovieCode(info.movieCode);
|
||||
playCodeBean.setProgramCode(info.progCode);
|
||||
playCodeBean.setSpecCode(info.specCode);
|
||||
PlayRecordManager.playCodeMaps.put(720,playCodeBean);
|
||||
}else if (info.getFormat().contains("1080")
|
||||
&&TextUtils.isEmpty(videoUrl_1080)){
|
||||
videoUrl_1080 = info.getVideoUrl();
|
||||
PlayCodeBean playCodeBean = new PlayCodeBean();
|
||||
playCodeBean.setMovieCode(info.movieCode);
|
||||
playCodeBean.setProgramCode(info.progCode);
|
||||
playCodeBean.setSpecCode(info.specCode);
|
||||
PlayRecordManager.playCodeMaps.put(1080,playCodeBean);
|
||||
}
|
||||
}
|
||||
LogUtils.d(TAG, "videoUrl_1080:" + videoUrl_1080);
|
||||
LogUtils.d(TAG, "videoUrl_720:" + videoUrl_720);
|
||||
if (null != onGetAllVideoUrlCallback) {
|
||||
onGetAllVideoUrlCallback.onResponse(videoUrl_1080, videoUrl_720, true);
|
||||
}
|
||||
}else {
|
||||
onGetAllVideoUrlCallback.onErr("410", "未返回播放地址");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(String s, String s1) {
|
||||
LogUtils.d(TAG, "videoUrl onFail:" + s + " msg:" + s1);
|
||||
onGetAllVideoUrlCallback.onErr(s, s1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public interface GetVideoUrlCallback {
|
||||
void onResponse(String videoUrl);
|
||||
}
|
||||
|
||||
|
||||
public interface OnGetAllVideoUrlCallback {
|
||||
void onResponse(String videoUrl_1080, String videoUrl_720, boolean isFree);
|
||||
|
||||
void onErr(String code, String msg);
|
||||
}
|
||||
|
||||
}
|
||||
293
app/src/main/java/com/pukka/jiecheng/utils/MgRoute.java
Executable file
293
app/src/main/java/com/pukka/jiecheng/utils/MgRoute.java
Executable file
@@ -0,0 +1,293 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.pukka.jiecheng.R;
|
||||
import com.pukka.jiecheng.aboutmy.AboutMyActivity;
|
||||
import com.pukka.jiecheng.device.DeviceActivity;
|
||||
import com.pukka.jiecheng.history.HistoryActivity;
|
||||
import com.pukka.jiecheng.index.IndexAmberManager;
|
||||
import com.pukka.jiecheng.list.ListActivity;
|
||||
import com.pukka.jiecheng.login.LoginActivity;
|
||||
import com.pukka.jiecheng.order.OrderActivity;
|
||||
import com.pukka.jiecheng.search.SearchActivity;
|
||||
import com.pukka.jiecheng.video.VideoDetailActivity;
|
||||
import com.pukka.jiecheng.web.SimpleWebActivity;
|
||||
import com.pukka.libcore.boxShared.BoxSharedParameters;
|
||||
import com.pukka.libcore.utils.LogUtils;
|
||||
import com.pukka.libcore.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* Author: wxf
|
||||
* Date: 2023/2/3 13:14
|
||||
* Description:跳转路由
|
||||
*/
|
||||
public class MgRoute {
|
||||
/**
|
||||
* 跳转到原生搜索页面
|
||||
*/
|
||||
public static void go2Search(Context context) {
|
||||
LogUtils.d("search 0");
|
||||
Intent intent = new Intent(context, SearchActivity.class);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到原生搜索页面
|
||||
*/
|
||||
public static void go2Search(Context context, int type) {
|
||||
LogUtils.d("search 0:"+type);
|
||||
Intent intent = new Intent(context, SearchActivity.class);
|
||||
intent.putExtra("byPos", type);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到更多历史页面
|
||||
*/
|
||||
public static void go2HisMore(Context context) {
|
||||
HistoryActivity.start(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到更多收藏页面
|
||||
*/
|
||||
public static void go2ColMore(Context context,int position) {
|
||||
HistoryActivity.start(context,position);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到订购页面
|
||||
*/
|
||||
public static void go2Order(Context context) {
|
||||
// if (!BoxSharedParameters.getInstance().isLogin()){
|
||||
// LoginActivity.start(context);
|
||||
// return;
|
||||
// }
|
||||
Intent intent = new Intent(context, OrderActivity.class);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
/**
|
||||
* 跳转到我的订购
|
||||
*/
|
||||
public static void go2Order(Context context,String go_type) {
|
||||
// if (!BoxSharedParameters.getInstance().isLogin()){
|
||||
// LoginActivity.start(context);
|
||||
// return;
|
||||
// }
|
||||
Intent intent = new Intent(context, OrderActivity.class);
|
||||
intent.putExtra(OrderActivity.go_type_param,go_type);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到设备页面
|
||||
*/
|
||||
public static void go2Device(Context context) {
|
||||
Intent intent = new Intent(context, DeviceActivity.class);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
/**
|
||||
* 跳转到帮助页面
|
||||
*/
|
||||
public static void go2AboutMy(Context context) {
|
||||
Intent intent = new Intent(context, AboutMyActivity.class);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
/**
|
||||
* 跳转到设置面
|
||||
*/
|
||||
public static void go2Setting(Context context) {
|
||||
// Intent intent = new Intent(context, MainWebActivity.class);
|
||||
// Bundle bundle = new Bundle();
|
||||
// StringBuilder sbUrl = new StringBuilder();
|
||||
// sbUrl.append(BaseUrl.getSingleton().getBaseEpgHttpUrl());
|
||||
// sbUrl.append(MgRoute.urlSetting);
|
||||
// bundle.putString("url",sbUrl.toString());
|
||||
// intent.putExtras(bundle);
|
||||
// context.startActivity(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到收藏面
|
||||
*/
|
||||
public static void go2Collect(Context context) {
|
||||
// Intent intent = new Intent(context, MainWebActivity.class);
|
||||
// Bundle bundle = new Bundle();
|
||||
// StringBuilder sbUrl = new StringBuilder();
|
||||
// sbUrl.append(BaseUrl.getSingleton().getBaseEpgHttpUrl());
|
||||
// sbUrl.append(MgRoute.urlCollect);
|
||||
// bundle.putString("url",sbUrl.toString());
|
||||
// intent.putExtras(bundle);
|
||||
// context.startActivity(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到更多历史记录
|
||||
*/
|
||||
public static void go2History(Context context) {
|
||||
// LogUtils.d("go to history:go2History");
|
||||
// isGo2TopClick=false;
|
||||
// ItemOnClickUtils.go2Epg(context,"", IndexConstant.getHistoryUrl(),"noparam","");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 首页TOP,跳转分发
|
||||
*
|
||||
* @param context context
|
||||
* @param view view
|
||||
* @param pageType 导航或二级页
|
||||
*/
|
||||
public static void topRoute(Context context, View view, String pageType) {
|
||||
if (view.getId() == R.id.id_iv_history) {
|
||||
IndexAmberManager.topButtonClick("历史记录");
|
||||
HistoryActivity.start(context);
|
||||
} else if (view.getId() == R.id.id_iv_search || view.getId() == R.id.id_bottom_cl_search) {
|
||||
int type = 2;
|
||||
if (view.getId() == R.id.id_iv_search) {
|
||||
type = 1;
|
||||
}
|
||||
if (type == 1) {
|
||||
IndexAmberManager.topButtonClick("搜索");
|
||||
} else {
|
||||
IndexAmberManager.bottomButtonClick("搜索");
|
||||
}
|
||||
go2Search(context, type);
|
||||
} else if (view.getId() == R.id.id_iv_order) {
|
||||
IndexAmberManager.topButtonClick("订购中心");
|
||||
go2Order(context);
|
||||
} else if(view.getId() == R.id.id_iv_help){
|
||||
go2AboutMy(context);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 我的页面 收藏
|
||||
*/
|
||||
public static void myRouteColl(Context context, int contentId) {
|
||||
// isGo2TopClick=false;
|
||||
// Intent intent = new Intent(context, MainWebActivity.class);
|
||||
// Bundle bundle = new Bundle();
|
||||
// StringBuilder sbUrl = new StringBuilder();
|
||||
// sbUrl.append(BaseUrl.getSingleton().getBaseEpgHttpUrl());
|
||||
// sbUrl.append(BaseUrl.getSingleton().getHttpMidUrl()+"/pages/vod_detail/index.html?programCode=");
|
||||
// sbUrl.append(contentId);
|
||||
// sbUrl.append("&fromAppIndex=true");
|
||||
// bundle.putString("url",sbUrl.toString());
|
||||
// intent.putExtras(bundle);
|
||||
// context.startActivity(intent);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 跳转到用户协议
|
||||
*/
|
||||
public static void go2UserAgree(Context context, String url) {
|
||||
LogUtils.d("url=" + url);
|
||||
Intent intent = new Intent(context, SimpleWebActivity.class);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("url",url);
|
||||
intent.putExtras(bundle);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到图片
|
||||
*/
|
||||
public static void go2ImageActivity(Context context, String imageUrl) {
|
||||
// isGo2TopClick=true;
|
||||
// Intent intent = new Intent(context, ImageActivity.class);
|
||||
// intent.putExtra("IMAGEURL",imageUrl);
|
||||
// context.startActivity(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转外链
|
||||
*/
|
||||
public static void go2SimpleWebActivity(Context context, String url) {
|
||||
Intent starter = new Intent(context, SimpleWebActivity.class);
|
||||
starter.putExtra("url", url);
|
||||
context.startActivity(starter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转列表页
|
||||
*/
|
||||
public static void go2ListActivity(Context context, String parentId, String listId) {
|
||||
Intent intent = new Intent(context, ListActivity.class);
|
||||
intent.putExtra(ListActivity.PARENTID, parentId);
|
||||
intent.putExtra(ListActivity.LISTID, listId);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
private static long lastClickTime = 0;
|
||||
private static final long CLICK_INTERVAL = 1000; // 1秒内防止重复点击
|
||||
/**
|
||||
* 跳转详情页
|
||||
*/
|
||||
public static void go2DetailActivity(Context context, String contentCode) {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
if (currentTime - lastClickTime < CLICK_INTERVAL) {
|
||||
LogUtils.d("1秒内防止重复点击");
|
||||
return;
|
||||
}
|
||||
lastClickTime = currentTime;
|
||||
VideoDetailActivity.start(context, contentCode, "");
|
||||
}
|
||||
/**
|
||||
* 跳转详情页
|
||||
*/
|
||||
public static void go2DetailActivity(Context context, String contentCode,String contentType) {
|
||||
VideoDetailActivity.start(context, contentCode, contentType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到全屏播放页面
|
||||
*/
|
||||
public static void go2FullPlayerActivity(Context context, String contentCode) {
|
||||
VideoDetailActivity.startFull(context, contentCode, "");
|
||||
}
|
||||
|
||||
// 解析appParam 格式例如:gameId:6771&&gameType:1
|
||||
public static String getGameParam(String appParam){
|
||||
try {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
for (String keyValue : appParam.split("&&")) {
|
||||
String[] keyValues = keyValue.split(":");
|
||||
if (keyValues.length == 2) {
|
||||
String key = keyValues[0];
|
||||
int value = Integer.valueOf(keyValues[1]);
|
||||
jsonObject.put(key,value);
|
||||
}
|
||||
}
|
||||
String str = jsonObject.toJSONString();
|
||||
LogUtils.d("getGameParam="+str);
|
||||
return str;
|
||||
}catch (Exception ex){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
/**
|
||||
* 启动云游戏或启动本地游戏
|
||||
* 跳转到游戏
|
||||
* */
|
||||
public static void startActivityByClass(Context context,String packageName,String className,String appParams){
|
||||
try {
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("param", appParams);
|
||||
ComponentName cn = new ComponentName(packageName, className);
|
||||
intent.setComponent(cn);
|
||||
context.startActivity(intent);
|
||||
}catch (Exception ex){
|
||||
LogUtils.e("class start error="+ex.getMessage());
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
68
app/src/main/java/com/pukka/jiecheng/utils/NewRecordCollManager.java
Executable file
68
app/src/main/java/com/pukka/jiecheng/utils/NewRecordCollManager.java
Executable file
@@ -0,0 +1,68 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.migu.bean.ContentListBean;
|
||||
import com.pukka.jiecheng.video.bean.SendAddPlayRecordBean;
|
||||
import com.pukka.libcore.utils.LogUtils;
|
||||
|
||||
public class NewRecordCollManager {
|
||||
public static String getDataJson(ContentListBean.ResultEntity mContentData, String contentcode) {
|
||||
SendAddPlayRecordBean bean = new SendAddPlayRecordBean();
|
||||
bean.setParentcode(mContentData.getCode());
|
||||
bean.setContentcode(contentcode);
|
||||
bean.setActordisplay(mContentData.getActordisplay());
|
||||
bean.setCategoryname(mContentData.getCategoryname());
|
||||
bean.setActordisplayen(mContentData.getActordisplay());
|
||||
bean.setCategoryid(mContentData.getCatalogid());
|
||||
bean.setCategorynameen("");
|
||||
bean.setContentkindname(mContentData.getContentkindname());
|
||||
bean.setContentcountryid("");
|
||||
bean.setContentkindid("");
|
||||
bean.setContentname(mContentData.getName());
|
||||
bean.setCpname(mContentData.getCpname());
|
||||
bean.setContenttype(mContentData.getContenttype() + "");
|
||||
bean.setContentkindnameen("");
|
||||
bean.setContentyearid("");
|
||||
bean.setEpisodeindex(getRecordIndex(mContentData,contentcode));
|
||||
bean.setExtendimg("");
|
||||
bean.setSpid("");
|
||||
bean.setSpName("");
|
||||
bean.setIcon("");
|
||||
bean.setOriginalcountry(mContentData.getOriginalcountry());
|
||||
bean.setWriterdisplay(mContentData.getWriterdisplay());
|
||||
String img = "";
|
||||
if (!TextUtils.isEmpty(mContentData.getMidimg())) {
|
||||
img = mContentData.getMidimg();
|
||||
} else if (!TextUtils.isEmpty(mContentData.getMidimg2())) {
|
||||
img = mContentData.getMidimg2();
|
||||
} else if (!TextUtils.isEmpty(mContentData.getPosterimg())) {
|
||||
img = mContentData.getPosterimg();
|
||||
}
|
||||
bean.setMidimg2(img);
|
||||
bean.setMidimg(img);
|
||||
bean.setPosterimg3(img);
|
||||
bean.setOriginalcountryen("");
|
||||
bean.setWriterdisplayen("");
|
||||
String str = new Gson().toJson(bean);
|
||||
LogUtils.d("addPlayRecord:" + str);
|
||||
return str;
|
||||
}
|
||||
|
||||
private static String getRecordIndex(ContentListBean.ResultEntity mContentData, String code) {
|
||||
int recordIndex = 0;
|
||||
if (mContentData.getContenttype() == 2 || mContentData.getContenttype() == 3) {
|
||||
if (mContentData.getSubcontents() != null) {
|
||||
for (int i = 0; i < mContentData.getSubcontents().size(); i++) {
|
||||
if (mContentData.getSubcontents().get(i).getContentcode().equals(code)) {
|
||||
recordIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (recordIndex+1)+"";
|
||||
}
|
||||
|
||||
}
|
||||
141
app/src/main/java/com/pukka/jiecheng/utils/NextPageManger.java
Executable file
141
app/src/main/java/com/pukka/jiecheng/utils/NextPageManger.java
Executable file
@@ -0,0 +1,141 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分页管理器
|
||||
*
|
||||
* @param <T> 数据集合列表
|
||||
* @param <V> 适配器
|
||||
*/
|
||||
public class NextPageManger<T, V extends RecyclerView.Adapter> {
|
||||
private final List<T> list = new ArrayList<>();
|
||||
private int pageIndex = 1;
|
||||
private boolean isNextPage;
|
||||
private int pageTotal;
|
||||
private OnUpdateCallBack onUpdateCallBack;
|
||||
private V adapter;
|
||||
|
||||
/**
|
||||
* 刷新数据调用接口的监听
|
||||
*/
|
||||
public void setOnUpdateCallBack(OnUpdateCallBack onUpdateCallBack) {
|
||||
this.onUpdateCallBack = onUpdateCallBack;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置适配器
|
||||
*/
|
||||
public void setAdapter(V adapter) {
|
||||
this.adapter = adapter;
|
||||
}
|
||||
|
||||
public void setPageIndex(int pageIndex) {
|
||||
this.pageIndex = pageIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行分页操作
|
||||
*/
|
||||
public void nextPage() {
|
||||
if (onUpdateCallBack == null) {
|
||||
return;
|
||||
}
|
||||
if (isNextPage) {
|
||||
isNextPage = false;
|
||||
pageIndex++;
|
||||
onUpdateCallBack.onUpdate();
|
||||
} else {
|
||||
onUpdateCallBack.onNoMoreDate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分页数据失败zhix
|
||||
*/
|
||||
public void notifyDataFail() {
|
||||
if (pageIndex > 1) {
|
||||
pageIndex--;
|
||||
}
|
||||
if (pageTotal <= pageIndex) {
|
||||
isNextPage = false;
|
||||
} else {
|
||||
isNextPage = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分页数据成功执行
|
||||
*
|
||||
* @param pageTotal 总页数
|
||||
* @param dateList 分页数据集合
|
||||
*/
|
||||
public void notifyData(int pageTotal, List<T> dateList) {
|
||||
notifyData(null,pageTotal,dateList);
|
||||
}
|
||||
|
||||
public void notifyData(RecyclerView recyclerView,int pageTotal, List<T> dateList) {
|
||||
this.pageTotal = pageTotal;
|
||||
if (pageIndex == 1) {
|
||||
if (dateList.isEmpty()){
|
||||
onUpdateCallBack.onNoDate();
|
||||
}
|
||||
int oldSize = list.size();
|
||||
list.clear();
|
||||
if (adapter != null) {
|
||||
if (oldSize > 0) {
|
||||
adapter.notifyItemRangeRemoved(0, oldSize);
|
||||
}
|
||||
}
|
||||
if (!dateList.isEmpty()) {
|
||||
list.addAll(dateList);
|
||||
if (adapter != null) {
|
||||
adapter.notifyItemRangeInserted(0, dateList.size());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int positionInserted = list.size();
|
||||
this.list.addAll(dateList);
|
||||
if (adapter != null) {
|
||||
adapter.notifyItemRangeInserted(positionInserted, dateList.size());
|
||||
}
|
||||
}
|
||||
if (pageTotal <= pageIndex) {
|
||||
isNextPage = false;
|
||||
} else {
|
||||
isNextPage = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回数据集合,适配器构造时放入
|
||||
*/
|
||||
public List<T> getList() {
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回当前页数,接口获取分页数据时放入
|
||||
*/
|
||||
public int getPageIndex() {
|
||||
return pageIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回是否可以分页操作
|
||||
*/
|
||||
public boolean isNextPage() {
|
||||
return isNextPage;
|
||||
}
|
||||
|
||||
public interface OnUpdateCallBack {
|
||||
void onUpdate();
|
||||
|
||||
void onNoMoreDate();
|
||||
|
||||
void onNoDate();
|
||||
}
|
||||
}
|
||||
24
app/src/main/java/com/pukka/jiecheng/utils/PageNumberUtil.java
Executable file
24
app/src/main/java/com/pukka/jiecheng/utils/PageNumberUtil.java
Executable file
@@ -0,0 +1,24 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
public class PageNumberUtil {
|
||||
/**
|
||||
* 计算总页数
|
||||
* */
|
||||
public static int calculateTotalPages(int totalItems, int pageSize) {
|
||||
if (totalItems <= 0) {
|
||||
return 0; // 没有数据时返回0页
|
||||
}
|
||||
if (pageSize <= 0) {
|
||||
throw new IllegalArgumentException("每页大小必须大于0");
|
||||
}
|
||||
return (totalItems - 1) / pageSize + 1;
|
||||
}
|
||||
/**
|
||||
* 计算当前页数
|
||||
* @param position 当前position
|
||||
* @param itemsPerPage 每页项数
|
||||
* */
|
||||
public static int calculatePage(int position, int itemsPerPage) {
|
||||
return (position / itemsPerPage) + 1;
|
||||
}
|
||||
}
|
||||
118
app/src/main/java/com/pukka/jiecheng/utils/PaginationUtil.java
Executable file
118
app/src/main/java/com/pukka/jiecheng/utils/PaginationUtil.java
Executable file
@@ -0,0 +1,118 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分页工具类
|
||||
* */
|
||||
public class PaginationUtil<T> {
|
||||
|
||||
private List<T> allData; // 所有数据
|
||||
private int currentPage; // 当前页码
|
||||
private int pageSize; // 每页大小
|
||||
private int totalPages; // 总页数
|
||||
private int totalItems; // 总数据量
|
||||
|
||||
public PaginationUtil(List<T> allData, int pageSize) {
|
||||
this.allData = allData;
|
||||
this.pageSize = pageSize;
|
||||
this.totalItems = allData.size();
|
||||
this.totalPages = (int) Math.ceil((double) totalItems / pageSize);
|
||||
this.currentPage = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前页数据
|
||||
*/
|
||||
public List<T> getCurrentPageData() {
|
||||
int start = (currentPage - 1) * pageSize;
|
||||
int end = Math.min(start + pageSize, totalItems);
|
||||
// if (start >= totalItems) {
|
||||
// return List.of();
|
||||
// }
|
||||
return allData.subList(start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到指定页
|
||||
*/
|
||||
public List<T> goToPage(int pageNumber) {
|
||||
if (pageNumber < 1) {
|
||||
pageNumber = 1;
|
||||
} else if (pageNumber > totalPages) {
|
||||
pageNumber = totalPages;
|
||||
}
|
||||
this.currentPage = pageNumber;
|
||||
return getCurrentPageData();
|
||||
}
|
||||
|
||||
/**
|
||||
* 下一页
|
||||
*/
|
||||
public List<T> nextPage() {
|
||||
if (hasNextPage()) {
|
||||
currentPage++;
|
||||
}
|
||||
return getCurrentPageData();
|
||||
}
|
||||
|
||||
/**
|
||||
* 上一页
|
||||
*/
|
||||
public List<T> previousPage() {
|
||||
if (hasPreviousPage()) {
|
||||
currentPage--;
|
||||
}
|
||||
return getCurrentPageData();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否有下一页
|
||||
*/
|
||||
public boolean hasNextPage() {
|
||||
return currentPage < totalPages;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否有上一页
|
||||
*/
|
||||
public boolean hasPreviousPage() {
|
||||
return currentPage > 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分页信息
|
||||
*/
|
||||
public PageInfo getPageInfo() {
|
||||
return new PageInfo(currentPage, pageSize, totalPages, totalItems);
|
||||
}
|
||||
|
||||
// Getters
|
||||
public int getCurrentPage() { return currentPage; }
|
||||
public int getPageSize() { return pageSize; }
|
||||
public int getTotalPages() { return totalPages; }
|
||||
public int getTotalItems() { return totalItems; }
|
||||
|
||||
/**
|
||||
* 分页信息类
|
||||
*/
|
||||
public static class PageInfo {
|
||||
private int currentPage;
|
||||
private int pageSize;
|
||||
private int totalPages;
|
||||
private int totalItems;
|
||||
|
||||
public PageInfo(int currentPage, int pageSize, int totalPages, int totalItems) {
|
||||
this.currentPage = currentPage;
|
||||
this.pageSize = pageSize;
|
||||
this.totalPages = totalPages;
|
||||
this.totalItems = totalItems;
|
||||
}
|
||||
|
||||
// Getters
|
||||
public int getCurrentPage() { return currentPage; }
|
||||
public int getPageSize() { return pageSize; }
|
||||
public int getTotalPages() { return totalPages; }
|
||||
public int getTotalItems() { return totalItems; }
|
||||
}
|
||||
}
|
||||
49
app/src/main/java/com/pukka/jiecheng/utils/PayResultTimerUtil.java
Executable file
49
app/src/main/java/com/pukka/jiecheng/utils/PayResultTimerUtil.java
Executable file
@@ -0,0 +1,49 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.pukka.jiecheng.order.viewmodel.OrderViewModel;
|
||||
import com.pukka.libcore.threading.DispatchQueue;
|
||||
import com.pukka.libcore.utils.LogUtils;
|
||||
|
||||
/**
|
||||
* 轮询工具类
|
||||
* */
|
||||
public class PayResultTimerUtil {
|
||||
private static PayResultTimerUtil payResultTimerUtil;
|
||||
private static final Object LOCK = new Object();
|
||||
private Runnable timerRunnable;
|
||||
public static PayResultTimerUtil getInstance() {
|
||||
synchronized (LOCK) {
|
||||
if (null == payResultTimerUtil) {
|
||||
payResultTimerUtil = new PayResultTimerUtil();
|
||||
}
|
||||
return payResultTimerUtil;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 定时器监听
|
||||
*/
|
||||
public void startTimer(OrderViewModel orderViewModel,String preOrderCode) {
|
||||
stopTimer();
|
||||
timerRunnable = () -> getPayResultCycle(orderViewModel,preOrderCode);
|
||||
//3s轮询
|
||||
DispatchQueue.global.timer(500, 3000, timerRunnable);
|
||||
}
|
||||
|
||||
public void stopTimer() {
|
||||
if (null != timerRunnable) {
|
||||
LogUtils.i("stopTimer()");
|
||||
DispatchQueue.global.remove(timerRunnable);
|
||||
timerRunnable = null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 轮询接口
|
||||
*/
|
||||
public void getPayResultCycle(OrderViewModel orderViewModel,String preOrderCode) {
|
||||
if(null != orderViewModel){
|
||||
orderViewModel.getPayResultCycle(preOrderCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
107
app/src/main/java/com/pukka/jiecheng/utils/QRCodeUtil.java
Executable file
107
app/src/main/java/com/pukka/jiecheng/utils/QRCodeUtil.java
Executable file
@@ -0,0 +1,107 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.common.CharacterSetECI;
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
/**
|
||||
* @ClassName: QRCodeUtil
|
||||
* @Description: 二维码工具类
|
||||
* @Author Wangnan
|
||||
* @Date 2017/2/8
|
||||
*/
|
||||
|
||||
public class QRCodeUtil {
|
||||
|
||||
/**
|
||||
* 创建二维码位图
|
||||
*
|
||||
* @param content 字符串内容(支持中文)
|
||||
* @param width 位图宽度(单位:px)
|
||||
* @param height 位图高度(单位:px)
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
public static Bitmap createQRCodeBitmap(String content, int width, int height){
|
||||
return createQRCodeBitmap(content, width, height, "UTF-8", "", "", Color.BLACK, Color.WHITE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建二维码位图 (支持自定义配置和自定义样式)
|
||||
*
|
||||
* @param content 字符串内容
|
||||
* @param width 位图宽度,要求>=0(单位:px)
|
||||
* @param height 位图高度,要求>=0(单位:px)
|
||||
* @param character_set 字符集/字符转码格式 (支持格式:{@link CharacterSetECI })。传null时,zxing源码默认使用 "ISO-8859-1"
|
||||
* @param error_correction 容错级别 (支持级别:{@link ErrorCorrectionLevel })。传null时,zxing源码默认使用 "L"
|
||||
* @param margin 空白边距 (可修改,要求:整型且>=0), 传null时,zxing源码默认使用"4"。
|
||||
* @param color_black 黑色色块的自定义颜色值
|
||||
* @param color_white 白色色块的自定义颜色值
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
public static Bitmap createQRCodeBitmap(String content, int width, int height,
|
||||
@Nullable String character_set, @Nullable String error_correction, @Nullable String margin,
|
||||
@ColorInt int color_black, @ColorInt int color_white){
|
||||
|
||||
/** 1.参数合法性判断 */
|
||||
if(TextUtils.isEmpty(content)){ // 字符串内容判空
|
||||
return null;
|
||||
}
|
||||
|
||||
if(width < 0 || height < 0){ // 宽和高都需要>=0
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
/** 2.设置二维码相关配置,生成BitMatrix(位矩阵)对象 */
|
||||
Hashtable<EncodeHintType, String> hints = new Hashtable<>();
|
||||
|
||||
if(!TextUtils.isEmpty(character_set)) {
|
||||
hints.put(EncodeHintType.CHARACTER_SET, character_set); // 字符转码格式设置
|
||||
}
|
||||
|
||||
if(!TextUtils.isEmpty(error_correction)){
|
||||
hints.put(EncodeHintType.ERROR_CORRECTION, error_correction); // 容错级别设置
|
||||
}
|
||||
|
||||
if(!TextUtils.isEmpty(margin)){
|
||||
hints.put(EncodeHintType.MARGIN, margin); // 空白边距设置
|
||||
}
|
||||
BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
|
||||
|
||||
/** 3.创建像素数组,并根据BitMatrix(位矩阵)对象为数组元素赋颜色值 */
|
||||
int[] pixels = new int[width * height];
|
||||
for(int y = 0; y < height; y++){
|
||||
for(int x = 0; x < width; x++){
|
||||
if(bitMatrix.get(x, y)){
|
||||
pixels[y * width + x] = color_black; // 黑色色块像素设置
|
||||
} else {
|
||||
pixels[y * width + x] = color_white; // 白色色块像素设置
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 4.创建Bitmap对象,根据像素数组设置Bitmap每个像素点的颜色值,之后返回Bitmap对象 */
|
||||
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
|
||||
return bitmap;
|
||||
} catch ( WriterException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
105
app/src/main/java/com/pukka/jiecheng/utils/QRCodeWriter.java
Executable file
105
app/src/main/java/com/pukka/jiecheng/utils/QRCodeWriter.java
Executable file
@@ -0,0 +1,105 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.Writer;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
import com.google.zxing.qrcode.encoder.ByteMatrix;
|
||||
import com.google.zxing.qrcode.encoder.Encoder;
|
||||
import com.google.zxing.qrcode.encoder.QRCode;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* This object renders a QR Code as a BitMatrix 2D array of greyscale values.
|
||||
*
|
||||
* @author dswitkin@google.com (Daniel Switkin)
|
||||
*/
|
||||
public final class QRCodeWriter implements Writer {
|
||||
|
||||
private static final int QUIET_ZONE_SIZE = 0;
|
||||
|
||||
@Override
|
||||
public BitMatrix encode(String contents, BarcodeFormat format, int width, int height)
|
||||
throws WriterException {
|
||||
|
||||
return encode(contents, format, width, height, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BitMatrix encode(String contents,
|
||||
BarcodeFormat format,
|
||||
int width,
|
||||
int height,
|
||||
Map<EncodeHintType,?> hints) throws WriterException {
|
||||
|
||||
if (contents.isEmpty()) {
|
||||
throw new IllegalArgumentException("Found empty contents");
|
||||
}
|
||||
|
||||
if (format != BarcodeFormat.QR_CODE) {
|
||||
throw new IllegalArgumentException("Can only encode QR_CODE, but got " + format);
|
||||
}
|
||||
|
||||
if (width < 0 || height < 0) {
|
||||
throw new IllegalArgumentException("Requested dimensions are too small: " + width + 'x' +
|
||||
height);
|
||||
}
|
||||
|
||||
ErrorCorrectionLevel errorCorrectionLevel = ErrorCorrectionLevel.L;
|
||||
int quietZone = QUIET_ZONE_SIZE;
|
||||
if (hints != null) {
|
||||
ErrorCorrectionLevel requestedECLevel = (ErrorCorrectionLevel) hints.get(EncodeHintType.ERROR_CORRECTION);
|
||||
if (requestedECLevel != null) {
|
||||
errorCorrectionLevel = requestedECLevel;
|
||||
}
|
||||
Integer quietZoneInt = (Integer) hints.get(EncodeHintType.MARGIN);
|
||||
if (quietZoneInt != null) {
|
||||
quietZone = quietZoneInt;
|
||||
}
|
||||
}
|
||||
|
||||
QRCode code = Encoder.encode(contents, errorCorrectionLevel, hints);
|
||||
return renderResult(code, width, height, quietZone);
|
||||
}
|
||||
|
||||
// Note that the input matrix uses 0 == white, 1 == black, while the output matrix uses
|
||||
// 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap).
|
||||
private static BitMatrix renderResult(QRCode code, int width, int height, int quietZone) {
|
||||
ByteMatrix input = code.getMatrix();
|
||||
if (input == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
int inputWidth = input.getWidth();
|
||||
int inputHeight = input.getHeight();
|
||||
int qrWidth = inputWidth + (quietZone * 2);
|
||||
int qrHeight = inputHeight + (quietZone * 2);
|
||||
int outputWidth = Math.max(width, qrWidth);
|
||||
int outputHeight = Math.max(height, qrHeight);
|
||||
|
||||
int multiple = Math.min(outputWidth / qrWidth, outputHeight / qrHeight);
|
||||
// Padding includes both the quiet zone and the extra white pixels to accommodate the requested
|
||||
// dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone.
|
||||
// If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will
|
||||
// handle all the padding from 100x100 (the actual QR) up to 200x160.
|
||||
int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
|
||||
int topPadding = (outputHeight - (inputHeight * multiple)) / 2;
|
||||
|
||||
BitMatrix output = new BitMatrix(outputWidth, outputHeight);
|
||||
|
||||
for (int inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {
|
||||
// Write the contents of this row of the barcode
|
||||
for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {
|
||||
if (input.get(inputX, inputY) == 1) {
|
||||
output.setRegion(outputX, outputY, multiple, multiple);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
274
app/src/main/java/com/pukka/jiecheng/utils/ResUtil.java
Executable file
274
app/src/main/java/com/pukka/jiecheng/utils/ResUtil.java
Executable file
@@ -0,0 +1,274 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.Resources.NotFoundException;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.TypedValue;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.pukka.libcore.utils.AppContext;
|
||||
import com.pukka.libcore.utils.ContextUtils;
|
||||
|
||||
|
||||
public final class ResUtil {
|
||||
private static final String TAG = "ResUtil";
|
||||
private static final float ROUNDING = 0.5F;
|
||||
|
||||
private ResUtil() {
|
||||
}
|
||||
|
||||
public static Resources getResources() {
|
||||
return ContextUtils.getContext().getResources();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Resources getResources(Context context) {
|
||||
if (null != context) {
|
||||
Resources resources = context.getResources();
|
||||
if (null != resources) {
|
||||
return resources;
|
||||
}
|
||||
}
|
||||
|
||||
return AppContext.getContext().getResources();
|
||||
}
|
||||
|
||||
public static String getString(int resId) {
|
||||
try {
|
||||
return AppContext.getContext().getString(resId);
|
||||
} catch (NotFoundException var2) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getString(int resId, Object... formatArgs) {
|
||||
try {
|
||||
return AppContext.getContext().getString(resId, formatArgs);
|
||||
} catch (NotFoundException var3) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getQuantityString(int resId, int quantity, Object... formatArgs) {
|
||||
try {
|
||||
return AppContext.getContext().getResources().getQuantityString(resId, quantity, formatArgs);
|
||||
} catch (NotFoundException var4) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static ArrayMap<Integer, Integer> dimensionPixelSizeMap = new ArrayMap<>();
|
||||
|
||||
public static int getDimensionPixelSize(int resId) {
|
||||
try {
|
||||
Integer value = dimensionPixelSizeMap.get(resId);
|
||||
if (value == null) {
|
||||
value = AppContext.getContext().getResources().getDimensionPixelSize(resId);
|
||||
dimensionPixelSizeMap.put(resId, value);
|
||||
}
|
||||
return value;
|
||||
} catch (NotFoundException var2) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getIdentifier(String name, String defType, String defPackTAGe) {
|
||||
try {
|
||||
return AppContext.getContext().getResources().getIdentifier(name, defType, defPackTAGe);
|
||||
} catch (NotFoundException var4) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static float getDimension(int resId) {
|
||||
try {
|
||||
return AppContext.getContext().getResources().getDimension(resId);
|
||||
} catch (NotFoundException var2) {
|
||||
return 0.0F;
|
||||
}
|
||||
}
|
||||
|
||||
public static float getFloat(int resId) {
|
||||
try {
|
||||
TypedValue outValue = new TypedValue();
|
||||
AppContext.getContext().getResources().getValue(resId, outValue, true);
|
||||
return outValue.getFloat();
|
||||
} catch (NotFoundException var2) {
|
||||
return 0.0F;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getColor(int resId) {
|
||||
try {
|
||||
return AppContext.getContext().getResources().getColor(resId);
|
||||
} catch (NotFoundException var2) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getInt(int resId) {
|
||||
try {
|
||||
return AppContext.getContext().getResources().getInteger(resId);
|
||||
} catch (NotFoundException var2) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static Drawable getDrawable(int resId) {
|
||||
try {
|
||||
return AppContext.getContext().getResources().getDrawable(resId);
|
||||
} catch (NotFoundException var2) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] getStringArray(int resId) {
|
||||
try {
|
||||
return AppContext.getContext().getResources().getStringArray(resId);
|
||||
} catch (NotFoundException var2) {
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
|
||||
public static int[] getIntegerArray(int resId) {
|
||||
try {
|
||||
return AppContext.getContext().getResources().getIntArray(resId);
|
||||
} catch (NotFoundException var2) {
|
||||
return new int[0];
|
||||
}
|
||||
}
|
||||
|
||||
public static ColorStateList getColorStateList(int resId) {
|
||||
try {
|
||||
return AppContext.getContext().getResources().getColorStateList(resId);
|
||||
} catch (NotFoundException var2) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean getBoolean(int resId) {
|
||||
try {
|
||||
return AppContext.getContext().getResources().getBoolean(resId);
|
||||
} catch (NotFoundException var2) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static int dp2Px(float dp) {
|
||||
float scale = AppContext.getContext().getResources().getDisplayMetrics().density;
|
||||
return (int)(dp * scale + 0.5F);
|
||||
}
|
||||
|
||||
public static int sp2Px(float sp) {
|
||||
float scale = AppContext.getContext().getResources().getDisplayMetrics().scaledDensity;
|
||||
return (int)(sp * scale + 0.5F);
|
||||
}
|
||||
|
||||
public static int px2Dp(float px) {
|
||||
float scale = AppContext.getContext().getResources().getDisplayMetrics().density;
|
||||
return (int)(px / scale + 0.5F);
|
||||
}
|
||||
|
||||
public static boolean isDirectionLTR() {
|
||||
return getResources().getConfiguration().getLayoutDirection() == 0;
|
||||
}
|
||||
|
||||
public static int getIdentifier(Context context, String name, String defType, String defPackTAGe) {
|
||||
try {
|
||||
return getResources(context).getIdentifier(name, defType, defPackTAGe);
|
||||
} catch (NotFoundException var5) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getColor(Context context, int resId) {
|
||||
try {
|
||||
return getResources(context).getColor(resId);
|
||||
} catch (NotFoundException var3) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static Drawable getDrawable(Context context, int resId) {
|
||||
try {
|
||||
return getResources(context).getDrawable(resId);
|
||||
} catch (NotFoundException var3) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] getStringArray(Context context, int resId) {
|
||||
try {
|
||||
return getResources(context).getStringArray(resId);
|
||||
} catch (NotFoundException var3) {
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
|
||||
public static ColorStateList getColorStateList(Context context, int resId) {
|
||||
try {
|
||||
return getResources(context).getColorStateList(resId);
|
||||
} catch (NotFoundException var3) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean getBoolean(Context context, int resId) {
|
||||
try {
|
||||
return getResources(context).getBoolean(resId);
|
||||
} catch (NotFoundException var3) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static DisplayMetrics getDisplayMetrics() {
|
||||
return getResources().getDisplayMetrics();
|
||||
}
|
||||
|
||||
public static Configuration getConfiguration() {
|
||||
return getResources().getConfiguration();
|
||||
}
|
||||
|
||||
public static int getDimensionPixelOffset(int resId) {
|
||||
try {
|
||||
return getResources().getDimensionPixelOffset(resId);
|
||||
} catch (NotFoundException var2) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* activity 判定以及转化
|
||||
*/
|
||||
public static FragmentActivity scanForActivity(Context cont) {
|
||||
if (cont == null) {
|
||||
return null;
|
||||
} else if (cont instanceof FragmentActivity){
|
||||
return (FragmentActivity)cont;
|
||||
} else if (cont instanceof ContextWrapper) {
|
||||
return scanForActivity(((ContextWrapper)cont).getBaseContext());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int getColor(String color) {
|
||||
try {
|
||||
return Color.parseColor(color);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
144
app/src/main/java/com/pukka/jiecheng/utils/RsaSignUtil.java
Executable file
144
app/src/main/java/com/pukka/jiecheng/utils/RsaSignUtil.java
Executable file
@@ -0,0 +1,144 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.util.Base64;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
|
||||
/**
|
||||
* 纯 JDK 实现的 RSA 工具类
|
||||
* 不依赖任何第三方库
|
||||
*/
|
||||
public class RsaSignUtil {
|
||||
|
||||
// 加密算法
|
||||
private static final String CIPHER_ALGORITHM = "RSA/ECB/PKCS1Padding";
|
||||
// 密钥算法
|
||||
private static final String KEY_ALGORITHM = "RSA";
|
||||
|
||||
/**
|
||||
* 免登录接口加密demo
|
||||
*
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
HashMap<String, String> signMap = new HashMap<>();
|
||||
signMap.put("accesser", "ANNINGTEST");
|
||||
signMap.put("businessLine", "4100450011967708592750001");
|
||||
signMap.put("uid", "xiaoqiangtest1111111"); //此处需要传递安柠的用户的唯一标识
|
||||
signMap.put("mac", "11:22:cc:dd:cc"); //安柠设备mac
|
||||
signMap.put("nonce", UUID.randomUUID().toString().replace("-", "")); //注意:此处的nonce,需要和接口的url参数相同
|
||||
signMap.put("timestamp", System.currentTimeMillis() + ""); //注意:此处的时间戳,需要和接口的url参数相同
|
||||
signMap.put("serviceComboCode", "1100121010201665723750127");
|
||||
// 使用 Gson 转为 JSON 字符串 注意:若无gson依赖,改为其它任意安全的json转化字符串方法均可
|
||||
Gson gson = new Gson();
|
||||
String encryptData = gson.toJson(signMap);
|
||||
System.out.println("待加密字符串为:" + encryptData);
|
||||
//公钥字符串,联系华视开发获取
|
||||
String publicKeyStr = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoDFiT8rDa6ftkRCxO8GctdhOYsEcmyrwyy0IYZKperNNukZnRYG0ucmmZ1C+9NWvVdmzoV1ikl5gBjdWlmnBzRZxtlaUaygm9/TrFDzOHzNLrkLtz1HSuSxNVMoOIaaSOdBcGtehK220td4U1jJFsyGwX/nsNhrlZ7Nhg3iFsrhAJ/9V7FLSJSc4W7XEKA36L5MBj/urCZNVbK7VIlfTfZy5W0CA8IwzEOPClkzjDG6H/s2zW/acxkyWBcOOBtNuNPUtQrmHKB9HJc0oxlbEVxW9UZ0rEWyFm/JN1z2ItMw+8upmFKbCGTXW6/1kzRs9Nsgc3zAqUzTMvT9qlDoeqwIDAQAB";
|
||||
String encrypt = encrypt(publicKeyStr, encryptData);
|
||||
System.out.println("加密后的字符串为:" + encrypt);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用公钥加密字符串
|
||||
*
|
||||
* @param key 公钥
|
||||
* @param plainText 明文字符串
|
||||
* @return 加密后的Base64编码字符串
|
||||
*/
|
||||
public static String encrypt(PublicKey key, String plainText) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key);
|
||||
|
||||
// 将字符串转换为字节数组
|
||||
byte[] plainTextBytes = plainText.getBytes("UTF-8");
|
||||
|
||||
// 分段加密(RSA有加密数据长度限制)
|
||||
int inputLen = plainTextBytes.length;
|
||||
int maxEncryptBlock = 245; // 2048位密钥的最大加密块大小
|
||||
|
||||
byte[] encryptedData = new byte[0];
|
||||
int offset = 0;
|
||||
|
||||
while (inputLen - offset > 0) {
|
||||
if (inputLen - offset > maxEncryptBlock) {
|
||||
byte[] encryptedBlock = cipher.doFinal(plainTextBytes, offset, maxEncryptBlock);
|
||||
encryptedData = concatenateByteArrays(encryptedData, encryptedBlock);
|
||||
offset += maxEncryptBlock;
|
||||
} else {
|
||||
byte[] encryptedBlock = cipher.doFinal(plainTextBytes, offset, inputLen - offset);
|
||||
encryptedData = concatenateByteArrays(encryptedData, encryptedBlock);
|
||||
offset = inputLen;
|
||||
}
|
||||
}
|
||||
// 返回Base64编码的加密数据
|
||||
return android.util.Base64.encodeToString(encryptedData, android.util.Base64.NO_WRAP);
|
||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException
|
||||
| InvalidKeyException | IllegalBlockSizeException
|
||||
| BadPaddingException | java.io.UnsupportedEncodingException e) {
|
||||
throw new RuntimeException("加密失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用Base64编码的公钥字符串加密
|
||||
*
|
||||
* @param publicKeyStr Base64编码的公钥字符串
|
||||
* @param plainText 明文字符串
|
||||
* @return 加密后的Base64编码字符串
|
||||
*/
|
||||
public static String encrypt(String publicKeyStr, String plainText) {
|
||||
try {
|
||||
PublicKey publicKey = getPublicKeyFromString(publicKeyStr);
|
||||
return encrypt(publicKey, plainText);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("加密失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Base64编码的字符串获取公钥
|
||||
*
|
||||
* @param publicKeyStr Base64编码的公钥字符串
|
||||
* @return PublicKey对象
|
||||
*/
|
||||
public static PublicKey getPublicKeyFromString(String publicKeyStr) {
|
||||
try {
|
||||
byte[] keyBytes = android.util.Base64.decode(publicKeyStr, Base64.NO_WRAP);
|
||||
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
|
||||
return keyFactory.generatePublic(keySpec);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("获取公钥失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并字节数组
|
||||
*
|
||||
* @param a 第一个字节数组
|
||||
* @param b 第二个字节数组
|
||||
* @return 合并后的字节数组
|
||||
*/
|
||||
private static byte[] concatenateByteArrays(byte[] a, byte[] b) {
|
||||
byte[] result = new byte[a.length + b.length];
|
||||
System.arraycopy(a, 0, result, 0, a.length);
|
||||
System.arraycopy(b, 0, result, a.length, b.length);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
339
app/src/main/java/com/pukka/jiecheng/utils/ToastUtils.java
Executable file
339
app/src/main/java/com/pukka/jiecheng/utils/ToastUtils.java
Executable file
@@ -0,0 +1,339 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.Gravity;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
import com.pukka.libcore.utils.ContextUtils;
|
||||
|
||||
/**
|
||||
* Toast相关工具类
|
||||
*/
|
||||
public class ToastUtils {
|
||||
|
||||
private ToastUtils() {
|
||||
throw new UnsupportedOperationException("u can't instantiate me...");
|
||||
}
|
||||
|
||||
private static Toast sToast;
|
||||
private static Handler sHandler = new Handler(Looper.getMainLooper());
|
||||
private static boolean isJumpWhenMore;
|
||||
|
||||
/**
|
||||
* 吐司初始化
|
||||
*
|
||||
* @param isJumpWhenMore 当连续弹出吐司时,是要弹出新吐司还是只修改文本内容
|
||||
* <p>{@code true}: 弹出新吐司<br>{@code false}: 只修改文本内容</p>
|
||||
* <p>如果为{@code false}的话可用来做显示任意时长的吐司</p>
|
||||
*/
|
||||
public static void init(boolean isJumpWhenMore) {
|
||||
ToastUtils.isJumpWhenMore = isJumpWhenMore;
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全地显示短时吐司
|
||||
*
|
||||
* @param text 文本
|
||||
*/
|
||||
public static void showShortToastSafe(final CharSequence text) {
|
||||
sHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showToast(text, Toast.LENGTH_SHORT,Gravity.CENTER);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全地显示短时吐司
|
||||
*
|
||||
* @param resId 资源Id
|
||||
*/
|
||||
public static void showShortToastSafe(final @StringRes int resId) {
|
||||
sHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showToast(resId, Toast.LENGTH_SHORT);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全地显示短时吐司
|
||||
*
|
||||
* @param resId 资源Id
|
||||
* @param args 参数
|
||||
*/
|
||||
public static void showShortToastSafe(final @StringRes int resId, final Object... args) {
|
||||
sHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showToast(resId, Toast.LENGTH_SHORT, args);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全地显示短时吐司
|
||||
*
|
||||
* @param format 格式
|
||||
* @param args 参数
|
||||
*/
|
||||
public static void showShortToastSafe(final String format, final Object... args) {
|
||||
sHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showToast(format, Toast.LENGTH_SHORT, args);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全地显示长时吐司
|
||||
*
|
||||
* @param text 文本
|
||||
*/
|
||||
public static void showLongToastSafe(final CharSequence text) {
|
||||
sHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showToast(text, Toast.LENGTH_LONG,Gravity.CENTER);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全地显示长时吐司
|
||||
*
|
||||
* @param resId 资源Id
|
||||
*/
|
||||
public static void showLongToastSafe(final @StringRes int resId) {
|
||||
sHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showToast(resId, Toast.LENGTH_LONG);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全地显示长时吐司
|
||||
*
|
||||
* @param resId 资源Id
|
||||
* @param args 参数
|
||||
*/
|
||||
public static void showLongToastSafe(final @StringRes int resId, final Object... args) {
|
||||
sHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showToast(resId, Toast.LENGTH_LONG, args);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全地显示长时吐司
|
||||
*
|
||||
* @param format 格式
|
||||
* @param args 参数
|
||||
*/
|
||||
public static void showLongToastSafe(final String format, final Object... args) {
|
||||
sHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showToast(format, Toast.LENGTH_LONG, args);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示短时吐司
|
||||
*
|
||||
* @param text 文本
|
||||
*/
|
||||
public static void showShortToast(CharSequence text) {
|
||||
showToast(text, Toast.LENGTH_SHORT,Gravity.CENTER);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param text 文本
|
||||
*/
|
||||
public static void showLongBottomToast(CharSequence text) {
|
||||
sHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showBottomToast(text, Toast.LENGTH_SHORT);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示短时吐司
|
||||
*
|
||||
* @param resId 资源Id
|
||||
*/
|
||||
public static void showShortToast(@StringRes int resId) {
|
||||
showToast(resId, Toast.LENGTH_SHORT);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示短时吐司
|
||||
*
|
||||
* @param resId 资源Id
|
||||
* @param args 参数
|
||||
*/
|
||||
public static void showShortToast(@StringRes int resId, Object... args) {
|
||||
showToast(resId, Toast.LENGTH_SHORT, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示短时吐司
|
||||
*
|
||||
* @param format 格式
|
||||
* @param args 参数
|
||||
*/
|
||||
public static void showShortToast(String format, Object... args) {
|
||||
showToast(format, Toast.LENGTH_SHORT, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示长时吐司
|
||||
*
|
||||
* @param text 文本
|
||||
*/
|
||||
public static void showLongToast(CharSequence text) {
|
||||
showToast(text, Toast.LENGTH_LONG,Gravity.CENTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示长时吐司
|
||||
*
|
||||
* @param text 文本
|
||||
*/
|
||||
public static void showLongToast(CharSequence text,int gravity) {
|
||||
showToast(text, Toast.LENGTH_LONG,gravity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示长时吐司
|
||||
*
|
||||
* @param resId 资源Id
|
||||
*/
|
||||
public static void showLongToast(@StringRes int resId) {
|
||||
showToast(resId, Toast.LENGTH_LONG);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示长时吐司
|
||||
*
|
||||
* @param resId 资源Id
|
||||
* @param args 参数
|
||||
*/
|
||||
public static void showLongToast(@StringRes int resId, Object... args) {
|
||||
showToast(resId, Toast.LENGTH_LONG, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示长时吐司
|
||||
*
|
||||
* @param format 格式
|
||||
* @param args 参数
|
||||
*/
|
||||
public static void showLongToast(String format, Object... args) {
|
||||
showToast(format, Toast.LENGTH_LONG, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示吐司
|
||||
*
|
||||
* @param resId 资源Id
|
||||
* @param duration 显示时长
|
||||
*/
|
||||
private static void showToast(@StringRes int resId, int duration) {
|
||||
showToast(ContextUtils.getContext().getResources().getText(resId).toString(), duration);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示吐司
|
||||
*
|
||||
* @param resId 资源Id
|
||||
* @param duration 显示时长
|
||||
* @param args 参数
|
||||
*/
|
||||
private static void showToast(@StringRes int resId, int duration, Object... args) {
|
||||
showToast(String.format(ContextUtils.getContext().getResources().getString(resId), args), duration);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示吐司
|
||||
*
|
||||
* @param format 格式
|
||||
* @param duration 显示时长
|
||||
* @param args 参数
|
||||
*/
|
||||
private static void showToast(String format, int duration, Object... args) {
|
||||
showToast(String.format(format, args), duration,Gravity.CENTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示吐司
|
||||
*
|
||||
* @param text 文本
|
||||
* @param duration 显示时长
|
||||
*/
|
||||
private static void showToast(CharSequence text, int duration,int gravity) {
|
||||
if (isJumpWhenMore) {
|
||||
cancelToast();
|
||||
}
|
||||
if (sToast == null) {
|
||||
sToast = Toast.makeText(ContextUtils.getContext(), text, duration);
|
||||
//Android 11 空指针
|
||||
// TextView tv = (TextView) sToast.getView().findViewById(android.R.id.message);
|
||||
// tv.setTextSize(18);
|
||||
sToast.setGravity(gravity, 0, gravity == Gravity.BOTTOM ? 90 : 0);
|
||||
} else {
|
||||
sToast.setText(text);
|
||||
sToast.setDuration(duration);
|
||||
}
|
||||
sToast.show();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 显示吐司
|
||||
*
|
||||
* @param text 文本
|
||||
* @param duration 显示时长
|
||||
*/
|
||||
private static void showBottomToast(CharSequence text, int duration) {
|
||||
if (isJumpWhenMore) {
|
||||
cancelToast();
|
||||
}
|
||||
if (sToast == null) {
|
||||
sToast = Toast.makeText(ContextUtils.getContext(), text, duration);
|
||||
// TextView tv = (TextView) sToast.getView().findViewById(android.R.id.message);
|
||||
// tv.setTextSize(18);
|
||||
// sToast.setGravity(Gravity., 0, 0);
|
||||
} else {
|
||||
sToast.setText(text);
|
||||
sToast.setDuration(duration);
|
||||
}
|
||||
sToast.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消吐司显示
|
||||
*/
|
||||
public static void cancelToast() {
|
||||
if (sToast != null) {
|
||||
sToast.cancel();
|
||||
sToast = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
81
app/src/main/java/com/pukka/jiecheng/utils/TopStyleUtils.java
Executable file
81
app/src/main/java/com/pukka/jiecheng/utils/TopStyleUtils.java
Executable file
@@ -0,0 +1,81 @@
|
||||
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
import com.pukka.jiecheng.R;
|
||||
|
||||
/**
|
||||
* Author: wxf
|
||||
* Date: 2023/1/12 10:48
|
||||
* Description:Top样式切换
|
||||
*/
|
||||
public class TopStyleUtils {
|
||||
// 搜索、历史、订购、帮助 样式切换
|
||||
public static void topStyleChange(Context context, View view, boolean focus) {
|
||||
// ConstraintLayout constraintLayout = (ConstraintLayout) view;
|
||||
// View icon = constraintLayout.getChildAt(0);
|
||||
// icon.setSelected(focus);
|
||||
// TextView textView = (TextView) constraintLayout.getChildAt(1);
|
||||
if (focus) {
|
||||
view.animate().scaleX(1.1f).scaleY(1.1f).setDuration(100).start();
|
||||
// textView.setTextColor(context.getResources().getColor(R.color.index_top_text_focus));
|
||||
// textView.getPaint().setFakeBoldText(true);
|
||||
} else {
|
||||
view.animate().scaleX(1.0f).scaleY(1.0f).setDuration(100).start();
|
||||
// textView.setTextColor(context.getResources().getColor(R.color.index_top_text_nor));
|
||||
// textView.getPaint().setFakeBoldText(false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void topImageChange(View view, boolean focus) {
|
||||
if (focus) {
|
||||
ViewCompat.animate(view).scaleX(1.05f).scaleY(1.05f).setDuration(100).start();
|
||||
} else {
|
||||
ViewCompat.animate(view).scaleX(1.0f).scaleY(1.0f).setDuration(100).start();
|
||||
}
|
||||
}
|
||||
|
||||
public static void topImageChangeFilter(View view, boolean focus) {
|
||||
if (focus) {
|
||||
ViewCompat.animate(view).scaleX(1.02f).scaleY(1.02f).setDuration(100).start();
|
||||
} else {
|
||||
ViewCompat.animate(view).scaleX(1.0f).scaleY(1.0f).setDuration(100).start();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 一行的大模板 放大 防止焦点框外溢
|
||||
* */
|
||||
public static void topImageChange3(View view, boolean focus) {
|
||||
if (focus) {
|
||||
ViewCompat.animate(view).scaleX(1.02f).scaleY(1.05f).setDuration(100).start();
|
||||
} else {
|
||||
ViewCompat.animate(view).scaleX(1.0f).scaleY(1.0f).setDuration(100).start();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 对view放大1.05f
|
||||
*
|
||||
* @param view view
|
||||
* @param focus focus
|
||||
*/
|
||||
public static void topImageChange2(View view, boolean focus) {
|
||||
if (focus) {
|
||||
ViewCompat.animate(view).scaleX(1.03f).scaleY(1.05f).setDuration(100).start();
|
||||
} else {
|
||||
ViewCompat.animate(view).scaleX(1.0f).scaleY(1.0f).setDuration(100).start();
|
||||
}
|
||||
}
|
||||
public static void topImageChange4(View view, boolean focus) {
|
||||
if (focus) {
|
||||
ViewCompat.animate(view).scaleX(1.03f).scaleY(1.03f).setDuration(100).start();
|
||||
} else {
|
||||
ViewCompat.animate(view).scaleX(1.0f).scaleY(1.0f).setDuration(100).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
87
app/src/main/java/com/pukka/jiecheng/utils/UiUtils.java
Executable file
87
app/src/main/java/com/pukka/jiecheng/utils/UiUtils.java
Executable file
@@ -0,0 +1,87 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.pukka.jiecheng.R;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public class UiUtils {
|
||||
|
||||
/**
|
||||
* 赛事卡片推荐位类型
|
||||
*/
|
||||
public static int POSITION_TYPE_SPORT_CARD = 1;
|
||||
|
||||
/**
|
||||
* 把数字转化成Dimen文件里对应的值
|
||||
*
|
||||
* @param mContext
|
||||
* @param number 原始数值
|
||||
* @return
|
||||
*/
|
||||
public static int numberConvertDimenValue(Context mContext, int number) {
|
||||
int dimenId = mContext.getResources().getIdentifier("qb_px_" + number, "dimen", mContext.getPackageName());
|
||||
int value = mContext.getResources().getDimensionPixelSize(dimenId);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 重新设置宽高
|
||||
*
|
||||
* @param mContext
|
||||
* @param width
|
||||
* @param height
|
||||
* @param params
|
||||
*/
|
||||
public static void resetLayoutParams(Context mContext, int width, int height, ViewGroup.LayoutParams params) {
|
||||
resetLayoutParams(mContext,width,height,0,params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 重新设置宽高
|
||||
*
|
||||
* @param mContext
|
||||
* @param width
|
||||
* @param height
|
||||
* @param recommendedPositionType 推荐位类型 1赛事卡片 0 其他类型
|
||||
* @param params
|
||||
*/
|
||||
public static void resetLayoutParams(Context mContext, int width, int height, int recommendedPositionType,ViewGroup.LayoutParams params) {
|
||||
int realWith = UiUtils.numberConvertDimenValue(mContext, width);
|
||||
int realHeight = UiUtils.numberConvertDimenValue(mContext, height);
|
||||
double rate = UiUtils.divNum(realWith, realHeight);
|
||||
//1赛事卡片推荐位固定高度22 其他类型23
|
||||
int showHeight = mContext.getResources().getDimensionPixelSize(recommendedPositionType == POSITION_TYPE_SPORT_CARD ? R.dimen.qb_px_22 : R.dimen.qb_px_23);
|
||||
params.width = (int) (rate * showHeight);
|
||||
params.height = showHeight;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 提供精确的除法运算
|
||||
*
|
||||
* @param v1 被除数
|
||||
* @param v2 除数
|
||||
* @return 两个参数的商
|
||||
*/
|
||||
public static double divNum(int v1, int v2) {
|
||||
try {
|
||||
if (0 == v1 || 0 == v2) {
|
||||
return 0;
|
||||
}
|
||||
BigDecimal b1 = BigDecimal.valueOf(v1);
|
||||
BigDecimal b2 = BigDecimal.valueOf(v2);
|
||||
return b1.divide(b2, 2, BigDecimal.ROUND_HALF_UP).doubleValue();
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
185
app/src/main/java/com/pukka/jiecheng/utils/UpdateDialog.java
Executable file
185
app/src/main/java/com/pukka/jiecheng/utils/UpdateDialog.java
Executable file
@@ -0,0 +1,185 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.pukka.jiecheng.R;
|
||||
import com.pukka.jiecheng.index.IndexActivity;
|
||||
import com.pukka.libcore.utils.LogUtils;
|
||||
|
||||
|
||||
/**
|
||||
* @Author luoyuhang
|
||||
* @create 2022/1/5 0005 9:27
|
||||
*/
|
||||
public class UpdateDialog extends AlertDialog {
|
||||
|
||||
|
||||
UpdateNoOnClickListener mUpdateNoOnClickListener;
|
||||
ForceUpdateOnClickListener forceUpdateOnClickListener;
|
||||
private Context mContext;
|
||||
|
||||
private TextView mUpdateNow;
|
||||
private RelativeLayout two_rl;
|
||||
private RelativeLayout err_rl;
|
||||
private TextView err_btn;
|
||||
private TextView text2;
|
||||
private TextView text1;
|
||||
private TextView mTemporaryNo;
|
||||
private ProgressBar mProgressBar;
|
||||
// private TextView mPercent;
|
||||
|
||||
public UpdateDialog(Context context) {
|
||||
super(context);
|
||||
this.mContext = context;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
getWindow().setBackgroundDrawableResource(android.R.color.transparent);
|
||||
super.onCreate(savedInstanceState);
|
||||
this.setContentView(R.layout.update_dialog);
|
||||
setCancelable(false);
|
||||
mUpdateNow = findViewById(R.id.tv_update_now);
|
||||
err_rl = findViewById(R.id.err_rl);
|
||||
err_btn = findViewById(R.id.err_btn);
|
||||
two_rl = findViewById(R.id.two_rl);
|
||||
text1 = findViewById(R.id.text1);
|
||||
text2 = findViewById(R.id.text2);
|
||||
mTemporaryNo = findViewById(R.id.tv_temporary_no);
|
||||
mProgressBar = findViewById(R.id.id_progressBar);
|
||||
// mPercent = findViewById(R.id.tv_percent);
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
|
||||
text2.setOnClickListener(v -> {
|
||||
if (null != forceUpdateOnClickListener) {
|
||||
text2.setVisibility(View.GONE);
|
||||
text1.setVisibility(View.GONE);
|
||||
mProgressBar.setVisibility(View.VISIBLE);
|
||||
// mPercent.setVisibility(View.VISIBLE);
|
||||
forceUpdateOnClickListener.update(v);
|
||||
}
|
||||
});
|
||||
|
||||
err_btn.setOnClickListener(v->{
|
||||
|
||||
if (mContext instanceof IndexActivity){
|
||||
((IndexActivity) mContext).killApp();
|
||||
}
|
||||
});
|
||||
|
||||
mUpdateNow.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View arg0) {
|
||||
two_rl.setVisibility(View.GONE);
|
||||
mProgressBar.setVisibility(View.VISIBLE);
|
||||
// mPercent.setVisibility(View.VISIBLE);
|
||||
if (mUpdateNoOnClickListener != null) {
|
||||
mUpdateNoOnClickListener.update(arg0);
|
||||
}
|
||||
}
|
||||
});
|
||||
mTemporaryNo.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View arg0) {
|
||||
if (mUpdateNoOnClickListener != null) {
|
||||
mUpdateNoOnClickListener.no(arg0);
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
CloudKeyCodeUtils.changeToKeyCode(keyCode);
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
if ((text2.getVisibility() == View.VISIBLE || err_rl.getVisibility() == View.VISIBLE) && mContext !=null) {
|
||||
if (mContext instanceof IndexActivity){
|
||||
((IndexActivity) mContext).killApp();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
public void setUpdateNoOnClickListener(UpdateNoOnClickListener onClickListener) {
|
||||
this.mUpdateNoOnClickListener = onClickListener;
|
||||
}
|
||||
|
||||
public void setForceUpdateOnClickListener(ForceUpdateOnClickListener forceUpdateOnClickListener) {
|
||||
this.forceUpdateOnClickListener = forceUpdateOnClickListener;
|
||||
}
|
||||
|
||||
public void showForceUpdate() {
|
||||
text2.setVisibility(View.VISIBLE);
|
||||
text1.setVisibility(View.VISIBLE);
|
||||
err_rl.setVisibility(View.GONE);
|
||||
text2.setFocusable(true);
|
||||
text2.requestFocus();
|
||||
}
|
||||
|
||||
|
||||
public void showError() {
|
||||
err_rl.setVisibility(View.VISIBLE);
|
||||
hideUpdate();
|
||||
text2.setVisibility(View.GONE);
|
||||
text1.setVisibility(View.GONE);
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
// mPercent.setVisibility(View.GONE);
|
||||
err_btn.requestFocus();
|
||||
}
|
||||
|
||||
|
||||
public void showUpdate() {
|
||||
two_rl.setVisibility(View.VISIBLE);
|
||||
err_rl.setVisibility(View.GONE);
|
||||
mUpdateNow.setFocusable(true);
|
||||
mTemporaryNo.setFocusable(true);
|
||||
mUpdateNow.requestFocus();
|
||||
}
|
||||
|
||||
public void hideUpdate() {
|
||||
two_rl.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
public void showProgressBar() {
|
||||
mProgressBar.setVisibility(View.VISIBLE);
|
||||
// mPercent.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
public ProgressBar getmProgressBar() {
|
||||
return mProgressBar;
|
||||
}
|
||||
|
||||
// public TextView getmPercent() {
|
||||
// return mPercent;
|
||||
// }
|
||||
|
||||
public void showDialog() {
|
||||
show();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public interface ForceUpdateOnClickListener {
|
||||
void update(View view);
|
||||
}
|
||||
|
||||
public interface UpdateNoOnClickListener {
|
||||
void update(View view);
|
||||
|
||||
void no(View view);
|
||||
}
|
||||
}
|
||||
53
app/src/main/java/com/pukka/jiecheng/utils/UpdateOtherDialog.java
Executable file
53
app/src/main/java/com/pukka/jiecheng/utils/UpdateOtherDialog.java
Executable file
@@ -0,0 +1,53 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.pukka.jiecheng.R;
|
||||
import com.pukka.libcore.fresco.PkSimpleDraweeView;
|
||||
|
||||
|
||||
/**
|
||||
* @Author luoyuhang
|
||||
* @create 2022/1/5 0005 9:27
|
||||
*/
|
||||
public class UpdateOtherDialog extends AlertDialog {
|
||||
|
||||
String mUrl;
|
||||
private ProgressBar mProgressBar;
|
||||
private PkSimpleDraweeView iv_icon;
|
||||
private TextView tv_title;
|
||||
|
||||
public UpdateOtherDialog(Context context, String url) {
|
||||
super(context);
|
||||
this.mUrl = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
if (null != getWindow()) {
|
||||
getWindow().setBackgroundDrawableResource(android.R.color.transparent);
|
||||
}
|
||||
super.onCreate(savedInstanceState);
|
||||
this.setContentView(R.layout.update_other_dialog);
|
||||
setCancelable(false);
|
||||
mProgressBar = findViewById(R.id.progressBar);
|
||||
tv_title = findViewById(R.id.tv_title);
|
||||
iv_icon = findViewById(R.id.iv_icon);
|
||||
}
|
||||
|
||||
public ProgressBar getmProgressBar() {
|
||||
return mProgressBar;
|
||||
}
|
||||
|
||||
public void setIcon(String iconStr) {
|
||||
iv_icon.setImageURI(iconStr);
|
||||
}
|
||||
|
||||
public void setTitle(String titleStr) {
|
||||
tv_title.setText(titleStr);
|
||||
}
|
||||
}
|
||||
71
app/src/main/java/com/pukka/jiecheng/utils/UrlParamBuilder.java
Executable file
71
app/src/main/java/com/pukka/jiecheng/utils/UrlParamBuilder.java
Executable file
@@ -0,0 +1,71 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import java.util.Map;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class UrlParamBuilder {
|
||||
|
||||
/**
|
||||
* 使用Map拼接URL参数(基础版本)
|
||||
* @param baseUrl 基础URL
|
||||
* @param params 参数Map
|
||||
* @return 拼接后的完整URL
|
||||
*/
|
||||
public static String buildUrl(String baseUrl, Map<String, String> params) {
|
||||
if (params == null || params.isEmpty()) {
|
||||
return baseUrl;
|
||||
}
|
||||
|
||||
StringBuilder urlBuilder = new StringBuilder(baseUrl);
|
||||
|
||||
// 判断基础URL是否已包含问号
|
||||
boolean hasQuery = baseUrl.contains("?");
|
||||
|
||||
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||
if (entry.getKey() != null && entry.getValue() != null) {
|
||||
if (!hasQuery) {
|
||||
urlBuilder.append("?");
|
||||
hasQuery = true;
|
||||
} else {
|
||||
urlBuilder.append("&");
|
||||
}
|
||||
|
||||
urlBuilder.append(entry.getKey())
|
||||
.append("=")
|
||||
.append(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return urlBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 带URL编码的版本
|
||||
*/
|
||||
public static String buildUrlEncoded(String baseUrl, Map<String, String> params) {
|
||||
if (params == null || params.isEmpty()) {
|
||||
return baseUrl;
|
||||
}
|
||||
|
||||
StringBuilder urlBuilder = new StringBuilder(baseUrl);
|
||||
boolean hasQuery = baseUrl.contains("?");
|
||||
|
||||
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||
if (entry.getKey() != null && entry.getValue() != null) {
|
||||
if (!hasQuery) {
|
||||
urlBuilder.append("?");
|
||||
hasQuery = true;
|
||||
} else {
|
||||
urlBuilder.append("&");
|
||||
}
|
||||
|
||||
urlBuilder.append(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8))
|
||||
.append("=")
|
||||
.append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
|
||||
return urlBuilder.toString();
|
||||
}
|
||||
}
|
||||
140
app/src/main/java/com/pukka/jiecheng/utils/VideoContainerHelper.java
Executable file
140
app/src/main/java/com/pukka/jiecheng/utils/VideoContainerHelper.java
Executable file
@@ -0,0 +1,140 @@
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
import com.pukka.jiecheng.R;
|
||||
import com.pukka.jiecheng.widget.VideoContainer;
|
||||
import com.pukka.libcore.utils.LogUtils;
|
||||
|
||||
|
||||
/**
|
||||
* @author wangkai
|
||||
* @version [V1.0.0, 2023/7/7]
|
||||
* @brief 计算VideoView是否完全可见辅助类
|
||||
* @since V1.0.0
|
||||
*/
|
||||
public class VideoContainerHelper {
|
||||
|
||||
private VideoContainer mVideoContainer;
|
||||
|
||||
private VideoContainerHelper() {
|
||||
}
|
||||
|
||||
private static class SingletonHolder {
|
||||
private static final VideoContainerHelper INSTANCE = new VideoContainerHelper();
|
||||
}
|
||||
|
||||
public static VideoContainerHelper getInstance() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
|
||||
private LinearLayoutManager mLinearLayoutManager;
|
||||
|
||||
/**
|
||||
* 设置LinearLayoutManager,用于计算VideoView是否完全可见
|
||||
*
|
||||
* @param linearLayoutManager LinearLayoutManager
|
||||
*/
|
||||
public void setLinearLayoutManager(LinearLayoutManager linearLayoutManager) {
|
||||
mLinearLayoutManager = linearLayoutManager;
|
||||
LogUtils.d("setLinearLayoutManager:" + mLinearLayoutManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算VideoView是否完全可见
|
||||
*/
|
||||
public void calculateVideoVisible() {
|
||||
if (mLinearLayoutManager == null) {
|
||||
return;
|
||||
}
|
||||
LogUtils.d("calculateVideoVisible:" + mLinearLayoutManager);
|
||||
mVideoContainer = null;
|
||||
int firstPosition = mLinearLayoutManager.findFirstVisibleItemPosition();
|
||||
int lastPosition = mLinearLayoutManager.findLastVisibleItemPosition();
|
||||
int firstCplPosition = mLinearLayoutManager.findFirstCompletelyVisibleItemPosition();
|
||||
int lastCplPosition = mLinearLayoutManager.findLastCompletelyVisibleItemPosition();
|
||||
for (int pos = firstPosition; pos <= lastPosition; pos++) {
|
||||
boolean isCompletelyVisible = pos >= firstCplPosition && pos <= lastCplPosition;
|
||||
LogUtils.d("wcg, calculateVideoVisible isCompletelyVisible: " + isCompletelyVisible);
|
||||
View itemView = mLinearLayoutManager.findViewByPosition(pos);
|
||||
LogUtils.d("pos: " + pos);
|
||||
LogUtils.d("itemView: " + itemView);
|
||||
if (itemView != null) {
|
||||
VideoContainer videoContainer = itemView.findViewById(R.id.id_video_container);
|
||||
if (videoContainer != null) {
|
||||
videoContainer.onVisibilityChange(isCompletelyVisible);
|
||||
if (isCompletelyVisible) {
|
||||
mVideoContainer = videoContainer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public void calculateVideoVisible(int pos){
|
||||
if (mLinearLayoutManager == null) {
|
||||
return;
|
||||
}
|
||||
LogUtils.d("calculateVideoVisible:" + mLinearLayoutManager);
|
||||
mVideoContainer = null;
|
||||
View itemView = mLinearLayoutManager.findViewByPosition(pos);
|
||||
LogUtils.d("pos: " + pos);
|
||||
LogUtils.d("itemView: " + itemView);
|
||||
if (itemView != null) {
|
||||
VideoContainer videoContainer = itemView.findViewById(R.id.id_video_container);
|
||||
if (videoContainer != null) {
|
||||
boolean isCompletelyVisible = true;
|
||||
//videoContainer.onVisibilityChange(true);
|
||||
if (isCompletelyVisible) {
|
||||
mVideoContainer = videoContainer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为全屏
|
||||
*
|
||||
* @return 是否为全屏
|
||||
*/
|
||||
public boolean isFullScreen() {
|
||||
return null != mVideoContainer && mVideoContainer.isFullScreen();
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出全屏
|
||||
*/
|
||||
public void exitFullScreen() {
|
||||
if (mVideoContainer != null) {
|
||||
mVideoContainer.exitFullScreen();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放播放器
|
||||
*/
|
||||
public void release() {
|
||||
if (mVideoContainer != null) {
|
||||
mVideoContainer.release();
|
||||
}
|
||||
}
|
||||
|
||||
public void startPlay(){
|
||||
if (mVideoContainer != null) {
|
||||
mVideoContainer.startPlay();
|
||||
}
|
||||
}
|
||||
|
||||
public void releaseLayout(){
|
||||
mLinearLayoutManager = null;
|
||||
}
|
||||
|
||||
public void setVideoGetFocus(boolean videoGetFocus){
|
||||
if (mVideoContainer != null) {
|
||||
mVideoContainer.setVideoGetFocus(videoGetFocus);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
89
app/src/main/java/com/pukka/jiecheng/utils/XCrashInitManager.java
Executable file
89
app/src/main/java/com/pukka/jiecheng/utils/XCrashInitManager.java
Executable file
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* @file XCrashInitManager.java
|
||||
* @description XCrash初始化管理,按权限优先使用jcCrash目录,失败时降级到应用私有目录
|
||||
* @author ainetv
|
||||
* @date 2026-03-26
|
||||
*/
|
||||
package com.pukka.jiecheng.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Environment;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.pukka.libcore.utils.LogUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import xcrash.XCrash;
|
||||
|
||||
public final class XCrashInitManager {
|
||||
private static final String TAG = "XCrashInitManager";
|
||||
private static final AtomicBoolean INITIALIZED = new AtomicBoolean(false);
|
||||
|
||||
private XCrashInitManager() {
|
||||
}
|
||||
|
||||
public static void initWithStoragePermission(Context context) {
|
||||
if (INITIALIZED.get()) {
|
||||
LogUtils.d(TAG, "xcrash already initialized, skip");
|
||||
return;
|
||||
}
|
||||
String preferredDir = buildPreferredDir(context);
|
||||
if (TextUtils.isEmpty(preferredDir)) {
|
||||
initWithFallback(context, "preferred dir unavailable");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
ensureDir(preferredDir);
|
||||
XCrash.init(context, new XCrash.InitParameters().setLogDir(preferredDir));
|
||||
INITIALIZED.set(true);
|
||||
LogUtils.i(TAG, "xcrash initialized with jcCrash dir: " + preferredDir);
|
||||
} catch (Throwable throwable) {
|
||||
LogUtils.e(TAG, "xcrash init jcCrash failed, fallback. reason: " + throwable.getMessage());
|
||||
initWithFallback(context, "init jcCrash failed");
|
||||
}
|
||||
}
|
||||
|
||||
public static void initWithFallback(Context context, String reason) {
|
||||
if (INITIALIZED.get()) {
|
||||
LogUtils.d(TAG, "xcrash already initialized, skip fallback");
|
||||
return;
|
||||
}
|
||||
String fallbackDir = buildFallbackDir(context);
|
||||
try {
|
||||
ensureDir(fallbackDir);
|
||||
XCrash.init(context, new XCrash.InitParameters().setLogDir(fallbackDir));
|
||||
INITIALIZED.set(true);
|
||||
LogUtils.w(TAG, "xcrash fallback init success, reason: " + reason + ", dir: " + fallbackDir);
|
||||
} catch (Throwable throwable) {
|
||||
LogUtils.e(TAG, "xcrash fallback init failed: " + throwable.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static String buildPreferredDir(Context context) {
|
||||
if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
|
||||
return null;
|
||||
}
|
||||
File externalRoot = Environment.getExternalStorageDirectory();
|
||||
if (externalRoot == null) {
|
||||
return null;
|
||||
}
|
||||
return new File(externalRoot, "jcCrash").getAbsolutePath();
|
||||
}
|
||||
|
||||
private static String buildFallbackDir(Context context) {
|
||||
return new File(context.getFilesDir(), "jcCrash").getAbsolutePath();
|
||||
}
|
||||
|
||||
private static void ensureDir(String path) {
|
||||
File dir = new File(path);
|
||||
if (dir.exists()) {
|
||||
return;
|
||||
}
|
||||
boolean mkdirsSuccess = dir.mkdirs();
|
||||
if (!mkdirsSuccess) {
|
||||
throw new IllegalStateException("create dir failed: " + path);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user