Merge branch 'dev' into dev-5.6.0
This commit is contained in:
@ -330,6 +330,8 @@ dependencies {
|
||||
})
|
||||
implementation "com.github.PhilJay:MPAndroidChart:${chart}"
|
||||
|
||||
implementation "com.lahm.library:easy-protector-release:${easyProtector}"
|
||||
|
||||
implementation "com.github.hsiafan:apk-parser:${apkParser}"
|
||||
implementation "org.nanohttpd:nanohttpd:${nanohttpd}"
|
||||
|
||||
|
||||
@ -216,6 +216,8 @@ public class Constants {
|
||||
// 用户是否需要 weibo x86 so
|
||||
public static final String SP_USER_NEED_WEIBO_X86_SO = "user_need_weibo_x86_so";
|
||||
|
||||
// 当前设备是不是模拟器
|
||||
public static final String SP_IS_EMULATOR = "is_emulator";
|
||||
|
||||
// 内容视频播放选项
|
||||
public static final String SP_CONTENT_VIDEO_OPTION = "content_video_option";
|
||||
|
||||
@ -26,6 +26,7 @@ object DialogHelper {
|
||||
*
|
||||
* uiModificationCallback,可用来手动微调样式的回调,可使用 binding 来修改颜色、文字大小等
|
||||
*/
|
||||
// TODO 提供 dismiss callback
|
||||
fun showDialog(
|
||||
context: Context,
|
||||
title: String,
|
||||
@ -38,10 +39,10 @@ object DialogHelper {
|
||||
uiModificationCallback: ((binding: DialogAlertDefaultBinding) -> Unit)? = null,
|
||||
trackMtaEvent: Boolean = false,
|
||||
mtaEvent: String = "",
|
||||
mtaKey: String = "") {
|
||||
mtaKey: String = ""): Dialog? {
|
||||
val solidContext = checkDialogContext(context)
|
||||
|
||||
if (solidContext is Activity && solidContext.isFinishing) return
|
||||
if (solidContext is Activity && solidContext.isFinishing) return null
|
||||
|
||||
val dialog = if (trackMtaEvent) {
|
||||
TrackableDialog(solidContext, R.style.GhAlertDialog, mtaEvent, mtaKey)
|
||||
@ -103,6 +104,8 @@ object DialogHelper {
|
||||
dialog.setContentView(contentView)
|
||||
dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
dialog.show()
|
||||
|
||||
return dialog
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
378
app/src/main/java/com/gh/common/util/EmulatorUtil.java
Normal file
378
app/src/main/java/com/gh/common/util/EmulatorUtil.java
Normal file
@ -0,0 +1,378 @@
|
||||
package com.gh.common.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.gh.common.constant.Constants;
|
||||
import com.lahm.library.CheckResult;
|
||||
import com.lahm.library.CommandUtil;
|
||||
|
||||
import static android.content.Context.SENSOR_SERVICE;
|
||||
import static com.lahm.library.CheckResult.RESULT_EMULATOR;
|
||||
import static com.lahm.library.CheckResult.RESULT_MAYBE_EMULATOR;
|
||||
import static com.lahm.library.CheckResult.RESULT_UNKNOWN;
|
||||
|
||||
public class EmulatorUtil {
|
||||
|
||||
private SimpleCallback<Boolean> mCallback;
|
||||
|
||||
private EmulatorUtil() {
|
||||
|
||||
}
|
||||
|
||||
private static class SingletonHolder {
|
||||
private static final EmulatorUtil INSTANCE = new EmulatorUtil();
|
||||
}
|
||||
|
||||
public static EmulatorUtil getSingleInstance() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
public void readSysProperty(Context context, SimpleCallback<Boolean> callback) {
|
||||
if (context == null)
|
||||
throw new IllegalArgumentException("context must not be null");
|
||||
|
||||
mCallback = callback;
|
||||
|
||||
int suspectCount = 0;
|
||||
|
||||
//检测硬件名称
|
||||
CheckResult hardwareResult = checkFeaturesByHardware();
|
||||
switch (hardwareResult.result) {
|
||||
case RESULT_MAYBE_EMULATOR:
|
||||
++suspectCount;
|
||||
break;
|
||||
case RESULT_EMULATOR:
|
||||
mCallback.onCallback(true);
|
||||
return;
|
||||
}
|
||||
|
||||
//检测渠道
|
||||
CheckResult flavorResult = checkFeaturesByFlavor();
|
||||
switch (flavorResult.result) {
|
||||
case RESULT_MAYBE_EMULATOR:
|
||||
++suspectCount;
|
||||
break;
|
||||
case RESULT_EMULATOR:
|
||||
mCallback.onCallback(true);
|
||||
return;
|
||||
}
|
||||
|
||||
//检测设备型号
|
||||
CheckResult modelResult = checkFeaturesByModel();
|
||||
switch (modelResult.result) {
|
||||
case RESULT_MAYBE_EMULATOR:
|
||||
++suspectCount;
|
||||
break;
|
||||
case RESULT_EMULATOR:
|
||||
mCallback.onCallback(true);
|
||||
return;
|
||||
}
|
||||
|
||||
//检测硬件制造商
|
||||
CheckResult manufacturerResult = checkFeaturesByManufacturer();
|
||||
switch (manufacturerResult.result) {
|
||||
case RESULT_MAYBE_EMULATOR:
|
||||
++suspectCount;
|
||||
break;
|
||||
case RESULT_EMULATOR:
|
||||
mCallback.onCallback(true);
|
||||
return;
|
||||
}
|
||||
|
||||
//检测主板名称
|
||||
CheckResult boardResult = checkFeaturesByBoard();
|
||||
switch (boardResult.result) {
|
||||
case RESULT_MAYBE_EMULATOR:
|
||||
++suspectCount;
|
||||
break;
|
||||
case RESULT_EMULATOR:
|
||||
mCallback.onCallback(true);
|
||||
return;
|
||||
}
|
||||
|
||||
//检测主板平台
|
||||
CheckResult platformResult = checkFeaturesByPlatform();
|
||||
switch (platformResult.result) {
|
||||
case RESULT_MAYBE_EMULATOR:
|
||||
++suspectCount;
|
||||
break;
|
||||
case RESULT_EMULATOR:
|
||||
mCallback.onCallback(true);
|
||||
return;
|
||||
}
|
||||
|
||||
//检测基带信息
|
||||
CheckResult baseBandResult = checkFeaturesByBaseBand();
|
||||
switch (baseBandResult.result) {
|
||||
case RESULT_MAYBE_EMULATOR:
|
||||
suspectCount += 2;//模拟器基带信息为null的情况概率相当大
|
||||
break;
|
||||
case RESULT_EMULATOR:
|
||||
mCallback.onCallback(true);
|
||||
return;
|
||||
}
|
||||
|
||||
//检测传感器数量
|
||||
int sensorNumber = getSensorNumber(context);
|
||||
if (sensorNumber <= 7) ++suspectCount;
|
||||
|
||||
//检测是否支持闪光灯
|
||||
boolean supportCameraFlash = supportCameraFlash(context);
|
||||
if (!supportCameraFlash) ++suspectCount;
|
||||
//检测是否支持相机
|
||||
boolean supportCamera = supportCamera(context);
|
||||
if (!supportCamera) ++suspectCount;
|
||||
//检测是否支持蓝牙
|
||||
boolean supportBluetooth = supportBluetooth(context);
|
||||
if (!supportBluetooth) ++suspectCount;
|
||||
|
||||
//检测光线传感器
|
||||
boolean hasLightSensor = hasLightSensor(context);
|
||||
if (!hasLightSensor) ++suspectCount;
|
||||
|
||||
//检测进程组信息
|
||||
CheckResult cgroupResult = checkFeaturesByCgroup();
|
||||
if (cgroupResult.result == RESULT_MAYBE_EMULATOR) ++suspectCount;
|
||||
|
||||
if (suspectCount > 3) {
|
||||
mCallback.onCallback(true);
|
||||
return;
|
||||
}
|
||||
// 如果有陀螺仪传感器就根据陀螺仪传感器数值判断,因为模拟器的陀螺仪数值都是0.0
|
||||
checkGyroscopeSensor(context);
|
||||
}
|
||||
|
||||
private String getProperty(String propName) {
|
||||
String property = CommandUtil.getSingleInstance().getProperty(propName);
|
||||
return TextUtils.isEmpty(property) ? null : property;
|
||||
}
|
||||
|
||||
/**
|
||||
* 特征参数-硬件名称
|
||||
*
|
||||
* @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机
|
||||
*/
|
||||
private CheckResult checkFeaturesByHardware() {
|
||||
String hardware = getProperty("ro.hardware");
|
||||
if (null == hardware) return new CheckResult(RESULT_MAYBE_EMULATOR, null);
|
||||
int result;
|
||||
String tempValue = hardware.toLowerCase();
|
||||
switch (tempValue) {
|
||||
case "ttvm"://天天模拟器
|
||||
case "nox"://夜神模拟器
|
||||
case "cancro"://网易MUMU模拟器
|
||||
case "intel"://逍遥模拟器
|
||||
case "vbox":
|
||||
case "vbox86"://腾讯手游助手
|
||||
case "android_x86"://雷电模拟器
|
||||
result = RESULT_EMULATOR;
|
||||
break;
|
||||
default:
|
||||
result = RESULT_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
return new CheckResult(result, hardware);
|
||||
}
|
||||
|
||||
/**
|
||||
* 特征参数-渠道
|
||||
*
|
||||
* @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机
|
||||
*/
|
||||
private CheckResult checkFeaturesByFlavor() {
|
||||
String flavor = getProperty("ro.build.flavor");
|
||||
if (null == flavor) return new CheckResult(RESULT_MAYBE_EMULATOR, null);
|
||||
int result;
|
||||
String tempValue = flavor.toLowerCase();
|
||||
if (tempValue.contains("vbox")) result = RESULT_EMULATOR;
|
||||
else if (tempValue.contains("sdk_gphone")) result = RESULT_EMULATOR;
|
||||
else result = RESULT_UNKNOWN;
|
||||
return new CheckResult(result, flavor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 特征参数-设备型号
|
||||
*
|
||||
* @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机
|
||||
*/
|
||||
private CheckResult checkFeaturesByModel() {
|
||||
String model = getProperty("ro.product.model");
|
||||
if (null == model) return new CheckResult(RESULT_MAYBE_EMULATOR, null);
|
||||
int result;
|
||||
String tempValue = model.toLowerCase();
|
||||
if (tempValue.contains("google_sdk")) result = RESULT_EMULATOR;
|
||||
else if (tempValue.contains("emulator")) result = RESULT_EMULATOR;
|
||||
else if (tempValue.contains("android sdk built for x86")) result = RESULT_EMULATOR;
|
||||
else result = RESULT_UNKNOWN;
|
||||
return new CheckResult(result, model);
|
||||
}
|
||||
|
||||
/**
|
||||
* 特征参数-硬件制造商
|
||||
*
|
||||
* @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机
|
||||
*/
|
||||
private CheckResult checkFeaturesByManufacturer() {
|
||||
String manufacturer = getProperty("ro.product.manufacturer");
|
||||
if (null == manufacturer) return new CheckResult(RESULT_MAYBE_EMULATOR, null);
|
||||
int result;
|
||||
String tempValue = manufacturer.toLowerCase();
|
||||
if (tempValue.contains("genymotion")) result = RESULT_EMULATOR;
|
||||
else if (tempValue.contains("netease")) result = RESULT_EMULATOR;//网易MUMU模拟器
|
||||
else result = RESULT_UNKNOWN;
|
||||
return new CheckResult(result, manufacturer);
|
||||
}
|
||||
|
||||
/**
|
||||
* 特征参数-主板名称
|
||||
*
|
||||
* @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机
|
||||
*/
|
||||
private CheckResult checkFeaturesByBoard() {
|
||||
String board = getProperty("ro.product.board");
|
||||
if (null == board) return new CheckResult(RESULT_MAYBE_EMULATOR, null);
|
||||
int result;
|
||||
String tempValue = board.toLowerCase();
|
||||
if (tempValue.contains("android")) result = RESULT_EMULATOR;
|
||||
else if (tempValue.contains("goldfish")) result = RESULT_EMULATOR;
|
||||
else result = RESULT_UNKNOWN;
|
||||
return new CheckResult(result, board);
|
||||
}
|
||||
|
||||
/**
|
||||
* 特征参数-主板平台
|
||||
*
|
||||
* @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机
|
||||
*/
|
||||
private CheckResult checkFeaturesByPlatform() {
|
||||
String platform = getProperty("ro.board.platform");
|
||||
if (null == platform) return new CheckResult(RESULT_MAYBE_EMULATOR, null);
|
||||
int result;
|
||||
String tempValue = platform.toLowerCase();
|
||||
if (tempValue.contains("android")) result = RESULT_EMULATOR;
|
||||
else result = RESULT_UNKNOWN;
|
||||
return new CheckResult(result, platform);
|
||||
}
|
||||
|
||||
/**
|
||||
* 特征参数-基带信息
|
||||
*
|
||||
* @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机
|
||||
*/
|
||||
private CheckResult checkFeaturesByBaseBand() {
|
||||
String baseBandVersion = getProperty("gsm.version.baseband");
|
||||
if (null == baseBandVersion) return new CheckResult(RESULT_MAYBE_EMULATOR, null);
|
||||
int result;
|
||||
if (baseBandVersion.contains("1.0.0.0")) result = RESULT_EMULATOR;
|
||||
else result = RESULT_UNKNOWN;
|
||||
return new CheckResult(result, baseBandVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取传感器数量
|
||||
*/
|
||||
private int getSensorNumber(Context context) {
|
||||
SensorManager sm = (SensorManager) context.getSystemService(SENSOR_SERVICE);
|
||||
return sm.getSensorList(Sensor.TYPE_ALL).size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否支持相机
|
||||
*/
|
||||
private boolean supportCamera(Context context) {
|
||||
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否支持闪光灯
|
||||
*/
|
||||
private boolean supportCameraFlash(Context context) {
|
||||
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否支持蓝牙
|
||||
*/
|
||||
private boolean supportBluetooth(Context context) {
|
||||
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否存在光传感器来判断是否为模拟器
|
||||
* 部分真机也不存在温度和压力传感器。其余传感器模拟器也存在。
|
||||
*
|
||||
* @return false为模拟器
|
||||
*/
|
||||
private boolean hasLightSensor(Context context) {
|
||||
SensorManager sensorManager = (SensorManager) context.getSystemService(SENSOR_SERVICE);
|
||||
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); //光线传感器
|
||||
if (null == sensor) return false;
|
||||
else return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 特征参数-进程组信息
|
||||
*/
|
||||
private CheckResult checkFeaturesByCgroup() {
|
||||
String filter = CommandUtil.getSingleInstance().exec("cat /proc/self/cgroup");
|
||||
if (null == filter) return new CheckResult(RESULT_MAYBE_EMULATOR, null);
|
||||
return new CheckResult(RESULT_UNKNOWN, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否可以拨打电话和发短信
|
||||
*/
|
||||
private void checkCallPhone(Context context) {
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:123456"));
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
Intent intent2 = new Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:123456"));
|
||||
intent2.putExtra("sms_body", "test");
|
||||
|
||||
if (intent.resolveActivity(context.getPackageManager()) == null || intent2.resolveActivity(context.getPackageManager()) == null) {
|
||||
mCallback.onCallback(true);
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkGyroscopeSensor(Context context) {
|
||||
SensorManager sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
|
||||
SensorEventListener listener = new SensorEventListener() {
|
||||
int changeTimes = 0;
|
||||
int zeroTimes = 0;
|
||||
|
||||
@Override
|
||||
public void onSensorChanged(SensorEvent event) {
|
||||
changeTimes++;
|
||||
if (event.values[0] == 0.0 && event.values[1] == 0.0 && event.values[2] == 0.0) {
|
||||
zeroTimes++;
|
||||
}
|
||||
if (changeTimes > 50) {
|
||||
if (changeTimes == zeroTimes) {
|
||||
checkCallPhone(context);
|
||||
}
|
||||
sensorManager.unregisterListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
|
||||
}
|
||||
};
|
||||
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
|
||||
if (sensor != null) {
|
||||
sensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_FASTEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -238,7 +238,8 @@ public class EntranceUtils {
|
||||
public static final String KEY_CATEGORY_LIST = "categoty_list";
|
||||
public static final String KEY_IS_FREE = "is_free";
|
||||
public static final String KEY_IS_SIGN = "is_sign";
|
||||
public static final String KEY_IS_FORCED_TO_CERTICIFICE = "is_forced_to_certificate";
|
||||
public static final String KEY_IS_FORCED_TO_CERTIFICATE = "is_forced_to_certificate";
|
||||
public static final String KEY_IS_FORCED_TO_CERTIFICATE_BUT_WITH_BACKDOOR = "is_forced_to_certificate_but_with_backdoor";
|
||||
public static final String KEY_IS_CHOOSE_APK = "is_choose_apk";
|
||||
public static final String KEY_TAB_INDEX = "tab_index";
|
||||
public static final String KEY_IS_CATEGORY_V2 = "is_category_v2";
|
||||
|
||||
@ -22,6 +22,8 @@ object RealNameHelper {
|
||||
* 弹未成年人不能下载游戏弹窗
|
||||
*/
|
||||
fun showRealNameUnqualifiedDialog(downloadEntity: DownloadEntity) {
|
||||
// 是否强制实名
|
||||
val isForced = downloadEntity.getMetaExtra("force_real_name") != "false"
|
||||
|
||||
val contentText = if (downloadEntity.status == DownloadStatus.done) {
|
||||
"为保护未成年身心健康成长\n" + "根据相关政策要求,该游戏不对未成年人开放"
|
||||
@ -55,6 +57,9 @@ object RealNameHelper {
|
||||
* 弹需要实名弹窗
|
||||
*/
|
||||
fun showRealNameUncertificatedDialog(downloadEntity: DownloadEntity) {
|
||||
// 是否强制实名
|
||||
val isForced = downloadEntity.getMetaExtra("force_real_name") != "false"
|
||||
|
||||
NewLogUtils.logCertificationTrigger(downloadEntity.gameId, downloadEntity.name)
|
||||
|
||||
val contentText = if (downloadEntity.status == DownloadStatus.done) {
|
||||
@ -68,7 +73,7 @@ object RealNameHelper {
|
||||
ToastUtils.toast("为保护未成年身心健康成长,根据相关政策要求,该游戏不对未成年人开放")
|
||||
} else {
|
||||
NewLogUtils.logCertificationHintDialogAppearance()
|
||||
DialogHelper.showDialog(
|
||||
val dialog = DialogHelper.showDialog(
|
||||
currentActivity,
|
||||
title = "实名提示",
|
||||
content = contentText,
|
||||
@ -80,7 +85,8 @@ object RealNameHelper {
|
||||
currentActivity,
|
||||
ShellActivity.Type.REAL_NAME_INFO
|
||||
).apply {
|
||||
putExtra(EntranceUtils.KEY_IS_FORCED_TO_CERTICIFICE, true)
|
||||
putExtra(EntranceUtils.KEY_IS_FORCED_TO_CERTIFICATE, true)
|
||||
putExtra(EntranceUtils.KEY_IS_FORCED_TO_CERTIFICATE_BUT_WITH_BACKDOOR, !isForced)
|
||||
}
|
||||
)
|
||||
if (downloadEntity.status == DownloadStatus.done) {
|
||||
@ -90,8 +96,20 @@ object RealNameHelper {
|
||||
},
|
||||
cancelClickCallback = {
|
||||
NewLogUtils.logCertificationHintDialogOptionsClicked("取消")
|
||||
if (!isForced) {
|
||||
DownloadManager.getInstance(HaloApp.getInstance())
|
||||
.resumeAllInvisiblePendingTask()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
dialog?.setOnCancelListener {
|
||||
NewLogUtils.logCertificationHintDialogOptionsClicked("取消")
|
||||
if (!isForced) {
|
||||
DownloadManager.getInstance(HaloApp.getInstance())
|
||||
.resumeAllInvisiblePendingTask()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (downloadEntity.status != DownloadStatus.done) {
|
||||
|
||||
@ -21,7 +21,6 @@ import java.io.File
|
||||
import java.net.URLEncoder
|
||||
import java.util.*
|
||||
import kotlin.collections.HashMap
|
||||
import java.lang.Exception
|
||||
|
||||
|
||||
object UploadImageUtils {
|
||||
@ -35,6 +34,7 @@ object UploadImageUtils {
|
||||
poster,
|
||||
game_upload,
|
||||
user_background,
|
||||
id_photo,
|
||||
comment
|
||||
}
|
||||
|
||||
|
||||
@ -403,6 +403,12 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
if (downloadEntity != null) {
|
||||
String url = downloadEntity.getUrl();
|
||||
checkDownloadEntryRecordValidate(url);
|
||||
|
||||
// 添加当前设备为模拟器的标签
|
||||
if (HaloApp.getInstance().isEmulator) {
|
||||
downloadEntity.getMeta().put("isEmulator", "true");
|
||||
}
|
||||
|
||||
if (isDownloadCompleted(url)) {
|
||||
downloadEntity.setStatus(DownloadStatus.done);
|
||||
DataChanger.INSTANCE.notifyDataChanged(downloadEntity);
|
||||
@ -1128,7 +1134,9 @@ public class DownloadManager implements DownloadStatusListener {
|
||||
*/
|
||||
public void resumeAllInvisiblePendingTask() {
|
||||
for (DownloadEntity task : mInvisiblePendingTaskList) {
|
||||
add(task);
|
||||
if ("false".equals(task.getMeta().get("force_real_name"))) {
|
||||
add(task);
|
||||
}
|
||||
}
|
||||
mInvisiblePendingTaskList.clear();
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import com.gh.base.fragment.BaseFragment
|
||||
import com.gh.common.util.EntranceUtils
|
||||
import com.gh.gamecenter.amway.AmwaySuccessFragment
|
||||
import com.halo.assistant.fragment.SwitchInstallMethodFragment
|
||||
import com.halo.assistant.fragment.user.ManuallyRealNameFragment
|
||||
import com.halo.assistant.fragment.user.RealNameInfoFragment
|
||||
|
||||
/**
|
||||
@ -32,6 +33,7 @@ class ShellActivity : ToolBarActivity() {
|
||||
Type.AMWAY_SUCCESS -> startFragment(AmwaySuccessFragment().with(bundle))
|
||||
Type.SWITCH_INSTALL_METHOD -> startFragment(SwitchInstallMethodFragment())
|
||||
Type.REAL_NAME_INFO -> startFragment(RealNameInfoFragment().with(bundle))
|
||||
Type.MANUALLY_REAL_NAME -> startFragment(ManuallyRealNameFragment().with(bundle?.getBundle(EntranceUtils.KEY_DATA)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,7 +59,8 @@ class ShellActivity : ToolBarActivity() {
|
||||
enum class Type(val value: String) {
|
||||
AMWAY_SUCCESS("amway_success"),
|
||||
SWITCH_INSTALL_METHOD("switch_install_method"),
|
||||
REAL_NAME_INFO("real_name_info");
|
||||
REAL_NAME_INFO("real_name_info"),
|
||||
MANUALLY_REAL_NAME("manually_real_name");
|
||||
|
||||
companion object {
|
||||
fun fromString(typeString: String): Type {
|
||||
|
||||
@ -29,7 +29,7 @@ public class UserInfoEditActivity extends NormalActivity {
|
||||
public static Intent getIntent(Context context, String editType, Boolean isForcedToCertificate) {
|
||||
Bundle args = new Bundle();
|
||||
args.putString(UserViewModel.KEY_EDIT_TYPE, editType);
|
||||
args.putBoolean(EntranceUtils.KEY_IS_FORCED_TO_CERTICIFICE, isForcedToCertificate);
|
||||
args.putBoolean(EntranceUtils.KEY_IS_FORCED_TO_CERTIFICATE, isForcedToCertificate);
|
||||
return getTargetIntent(context, UserInfoEditActivity.class, UserInfoEditFragment.class, args);
|
||||
}
|
||||
|
||||
|
||||
@ -1,10 +1,13 @@
|
||||
package com.gh.gamecenter.entity
|
||||
|
||||
import androidx.room.Entity
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
@Entity
|
||||
data class IdCardEntity(
|
||||
var id: String? = null,
|
||||
var name: String? = null,
|
||||
var revise: Boolean? = false,
|
||||
@SerializedName("id_photo")
|
||||
var idPhoto: String? = null
|
||||
)
|
||||
@ -114,7 +114,7 @@ class GameVerticalAdapter(
|
||||
tempViewHolder.recommendTv = recommendTv
|
||||
tempViewHolder.recommendContainer = recommendConstraintLayout
|
||||
tempViewHolder.gameInfo = gameInfoGroup
|
||||
tempViewHolder.gameServerType
|
||||
tempViewHolder.gameServerType = serverTypeTv
|
||||
|
||||
DownloadItemUtils.updateItem(
|
||||
mContext,
|
||||
|
||||
@ -176,6 +176,12 @@ public interface ApiService {
|
||||
@POST("./certification:check")
|
||||
Single<ResponseBody> postCertificationCheck(@Body RequestBody body);
|
||||
|
||||
/**
|
||||
* 实名认证人工审核
|
||||
*/
|
||||
@POST("./certification:review")
|
||||
Single<ResponseBody> postCertificationReview(@Body RequestBody body);
|
||||
|
||||
/**
|
||||
* 获取新闻详情
|
||||
*/
|
||||
|
||||
@ -28,6 +28,7 @@ import com.gh.common.util.DeviceUtils;
|
||||
import com.gh.common.util.DownloadNotificationHelper;
|
||||
import com.gh.common.util.DownloadObserver;
|
||||
import com.gh.common.util.EnvHelper;
|
||||
import com.gh.common.util.EmulatorUtil;
|
||||
import com.gh.common.util.HomeBottomBarHelper;
|
||||
import com.gh.common.util.ImageUtils;
|
||||
import com.gh.common.util.PackageHelper;
|
||||
@ -77,6 +78,7 @@ public class HaloApp extends MultiDexApplication {
|
||||
public boolean isBrandNewInstall = false; // 当前用户是否是安装光环后第一次打开
|
||||
public boolean isNewForThisVersion = false; // 当前用户是否是安装当前版本后第一次打开 (包括全新和更新)
|
||||
public boolean isRunningForeground = false; // 标记当前 APP 是否处于前台运行中
|
||||
public boolean isEmulator = false; // 当前设备是否为模拟器
|
||||
|
||||
public int mCacheKeyboardHeight = 0;
|
||||
|
||||
@ -210,30 +212,37 @@ public class HaloApp extends MultiDexApplication {
|
||||
if (initImmediately) {
|
||||
delay = 0;
|
||||
}
|
||||
|
||||
postInit(delay);
|
||||
|
||||
mIsPostInitialized = true;
|
||||
}
|
||||
|
||||
private void postInit(long delay) {
|
||||
AppExecutor.getUiExecutor().executeWithDelay(() -> {
|
||||
initThirdPartySdk();
|
||||
|
||||
|
||||
DataUtils.getGid();
|
||||
|
||||
|
||||
FixedRateJobHelper.begin();
|
||||
|
||||
RegionSettingHelper.getRegionSetting();
|
||||
|
||||
|
||||
PackageRepository.initData();
|
||||
|
||||
|
||||
// 刷新内存中的用户信息,避免应用进程重建时因没有用户信息数据而显示为掉登录状态
|
||||
UserRepository.getInstance(this).getLoginUserInfo();
|
||||
|
||||
|
||||
checkIfDeviceIsEmulator();
|
||||
|
||||
initReceiver();
|
||||
initPackageChangesReceiver();
|
||||
initConnectivityChangesReceiver();
|
||||
|
||||
|
||||
initTimeConsumingAction();
|
||||
|
||||
|
||||
// 注册回调以用于做各种统计
|
||||
ProcessLifecycleOwner.get().getLifecycle().addObserver(new ProcessorLifeCycleOwner());
|
||||
|
||||
|
||||
// 开发环境不要强制捕获相关异常,这些异常通常是需要处理的
|
||||
if (!BuildConfig.DEBUG) {
|
||||
RxJavaPlugins.setErrorHandler(throwable -> {
|
||||
@ -243,8 +252,6 @@ public class HaloApp extends MultiDexApplication {
|
||||
});
|
||||
}
|
||||
}, delay);
|
||||
|
||||
mIsPostInitialized = true;
|
||||
}
|
||||
|
||||
private void initThirdPartySdk() {
|
||||
@ -331,6 +338,21 @@ public class HaloApp extends MultiDexApplication {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查当前设备是否为模拟器
|
||||
*/
|
||||
private void checkIfDeviceIsEmulator() {
|
||||
isEmulator = SPUtils.getBoolean(Constants.SP_IS_EMULATOR);
|
||||
if (!isEmulator) {
|
||||
EmulatorUtil.getSingleInstance().readSysProperty(HaloApp.getInstance().getApplication(), arg -> {
|
||||
if (arg) {
|
||||
SPUtils.setBoolean(Constants.SP_IS_EMULATOR, true);
|
||||
isEmulator = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPostInitialized() {
|
||||
return mIsPostInitialized;
|
||||
}
|
||||
|
||||
@ -0,0 +1,199 @@
|
||||
package com.halo.assistant.fragment.user
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.MediaStore
|
||||
import android.text.TextUtils
|
||||
import android.view.View
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.gh.base.fragment.WaitingDialogFragment
|
||||
import com.gh.common.util.*
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.databinding.FragmentManuallyRealNameBinding
|
||||
import com.gh.gamecenter.entity.IdCardEntity
|
||||
import com.gh.gamecenter.normal.NormalFragment
|
||||
import com.squareup.picasso.Picasso
|
||||
import io.reactivex.disposables.Disposable
|
||||
|
||||
class ManuallyRealNameFragment : NormalFragment() {
|
||||
|
||||
private var mDialog: WaitingDialogFragment? = null
|
||||
private var mDisposable: Disposable? = null
|
||||
|
||||
private val mViewModel: ManuallyRealNameViewModel by viewModels()
|
||||
|
||||
private val mBinding: FragmentManuallyRealNameBinding by lazy {
|
||||
FragmentManuallyRealNameBinding.inflate(layoutInflater)
|
||||
}
|
||||
|
||||
override fun getLayoutId(): Int = 0
|
||||
override fun getInflatedLayout(): View = mBinding.root
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
mBinding.toolbar.normalTitle.text = "人工审核"
|
||||
mBinding.toolbar.normalToolbar.setNavigationOnClickListener { requireActivity().finish() }
|
||||
|
||||
initView()
|
||||
|
||||
mViewModel.resultLiveData.observe(viewLifecycleOwner) {
|
||||
if (it) showSuccessView()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
|
||||
if (data == null) return
|
||||
if (requestCode == REQUEST_IMAGE) {
|
||||
val selectedImage = data.data ?: return
|
||||
val filePathColumn = arrayOf(MediaStore.Images.Media.DATA)
|
||||
|
||||
val cursor = requireContext().contentResolver.query(
|
||||
selectedImage,
|
||||
filePathColumn,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
) ?: return
|
||||
|
||||
cursor.moveToFirst()
|
||||
|
||||
val columnIndex = cursor.getColumnIndex(filePathColumn[0])
|
||||
val picturePath = cursor.getString(columnIndex)
|
||||
cursor.close()
|
||||
|
||||
uploadPicture(selectedImage, picturePath)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
mBinding.imageIv.setOnClickListener {
|
||||
PermissionHelper.checkStoragePermissionBeforeAction(
|
||||
requireContext(),
|
||||
object : EmptyCallback {
|
||||
override fun onCallback() {
|
||||
selectImage()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
mBinding.clearIv.setOnClickListener {
|
||||
removeUploadedImage()
|
||||
updateSubmitBtn()
|
||||
}
|
||||
|
||||
mBinding.nameEt.setText(arguments?.getString(EntranceUtils.KEY_NAME) ?: "")
|
||||
mBinding.idCardEt.setText(arguments?.getString(EntranceUtils.KEY_ID) ?: "")
|
||||
|
||||
mBinding.nameEt.setSelection(mBinding.nameEt.text.length)
|
||||
mBinding.idCardEt.setSelection(mBinding.idCardEt.text.length)
|
||||
|
||||
mBinding.nameEt.doOnTextChanged { _, _, _, _ ->
|
||||
updateSubmitBtn()
|
||||
}
|
||||
|
||||
mBinding.idCardEt.doOnTextChanged { _, _, _, _ ->
|
||||
updateSubmitBtn()
|
||||
}
|
||||
|
||||
mBinding.clearIv.visibility = View.GONE
|
||||
mBinding.contactTv.visibility = View.VISIBLE
|
||||
mBinding.contactTv.enlargeTouchArea()
|
||||
mBinding.contactTv.setOnClickListener {
|
||||
DirectUtils.directToQqConversation(it.context, RealNameInfoFragment.CONTACT_QQ)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSubmitBtn() {
|
||||
val validationPair =
|
||||
isInputValid(mBinding.nameEt.text.toString(), mBinding.idCardEt.text.toString())
|
||||
|
||||
mBinding.submitBtn.isEnabled = validationPair.first
|
||||
if (validationPair.first) {
|
||||
mBinding.submitBtn.alpha = 1F
|
||||
mBinding.submitBtn.setOnClickListener {
|
||||
val idCardEntity = IdCardEntity(
|
||||
id = mBinding.idCardEt.text.toString(),
|
||||
name = mBinding.nameEt.text.toString(),
|
||||
idPhoto = mViewModel.remoteImageUrl
|
||||
)
|
||||
|
||||
mViewModel.postCertificationReview(idCardEntity)
|
||||
}
|
||||
} else {
|
||||
mBinding.submitBtn.alpha = 0.4F
|
||||
}
|
||||
}
|
||||
|
||||
private fun selectImage() {
|
||||
val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
|
||||
startActivityForResult(intent, REQUEST_IMAGE)
|
||||
}
|
||||
|
||||
private fun removeUploadedImage() {
|
||||
mViewModel.remoteImageUrl = null
|
||||
mBinding.imageIv.setImageResource(R.drawable.bg_manually_real_name_image_placeholder)
|
||||
}
|
||||
|
||||
//上传图片
|
||||
private fun uploadPicture(internalImageUri: Uri, filePath: String) {
|
||||
if (TextUtils.isEmpty(filePath)) return
|
||||
|
||||
mDialog = WaitingDialogFragment.newInstance("上传图片中")
|
||||
mDialog?.show(childFragmentManager, "loading")
|
||||
|
||||
mDisposable = UploadImageUtils.uploadImage(
|
||||
UploadImageUtils.UploadType.id_photo,
|
||||
filePath,
|
||||
object : UploadImageUtils.OnUploadImageListener {
|
||||
override fun onSuccess(imageUrl: String) {
|
||||
if (!isAdded) return
|
||||
|
||||
mDialog?.dismissAllowingStateLoss()
|
||||
mViewModel.remoteImageUrl = imageUrl
|
||||
|
||||
mBinding.clearIv.visibility = View.VISIBLE
|
||||
Picasso.with(requireContext()).load(internalImageUri).into(mBinding.imageIv)
|
||||
updateSubmitBtn()
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable?) {
|
||||
mDialog?.dismissAllowingStateLoss()
|
||||
ToastUtils.toast("图片上传失败 ${e?.localizedMessage}")
|
||||
}
|
||||
|
||||
override fun onProgress(total: Long, progress: Long) {
|
||||
// do nothing
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun showSuccessView() {
|
||||
mBinding.successContainer.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
private fun isInputValid(name: String, idCard: String): Pair<Boolean, String> {
|
||||
if (TextUtils.isEmpty(name)) {
|
||||
return Pair(false, "请输入姓名")
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(idCard)) {
|
||||
return Pair(false, "请输入证件号码")
|
||||
}
|
||||
|
||||
if (mViewModel.remoteImageUrl == null) {
|
||||
return Pair(false, "请上传证件照")
|
||||
}
|
||||
|
||||
return Pair(true, "")
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val REQUEST_IMAGE = 101
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
package com.halo.assistant.fragment.user
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.gh.common.util.ErrorHelper
|
||||
import com.gh.common.util.GsonUtils
|
||||
import com.gh.gamecenter.entity.IdCardEntity
|
||||
import com.gh.gamecenter.entity.UserInfoEntity
|
||||
import com.gh.gamecenter.retrofit.BiResponse
|
||||
import com.gh.gamecenter.retrofit.RetrofitManager
|
||||
import com.halo.assistant.HaloApp
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.HttpException
|
||||
|
||||
class ManuallyRealNameViewModel(application: Application) : AndroidViewModel(application) {
|
||||
|
||||
var remoteImageUrl: String ?= null
|
||||
|
||||
var resultLiveData = MutableLiveData<Boolean>()
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
fun postCertificationReview(idCardEntity: IdCardEntity) {
|
||||
val userInfoEntity = UserInfoEntity()
|
||||
userInfoEntity.idCard = idCardEntity
|
||||
val body = RequestBody.create(
|
||||
MediaType.parse("application/json"), GsonUtils.toJson(userInfoEntity)
|
||||
)
|
||||
RetrofitManager.getInstance(HaloApp.getInstance()).api.postCertificationReview(body)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : BiResponse<ResponseBody?>() {
|
||||
override fun onFailure(exception: Exception) {
|
||||
ErrorHelper.handleError(
|
||||
HaloApp.getInstance(),
|
||||
(exception as? HttpException)?.response()?.errorBody()?.string()
|
||||
)
|
||||
}
|
||||
|
||||
override fun onSuccess(data: ResponseBody?) {
|
||||
resultLiveData.postValue(true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -11,14 +11,17 @@ import androidx.core.widget.doOnTextChanged
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.gh.common.util.*
|
||||
import com.gh.common.view.CustomLinkMovementMethod
|
||||
import com.gh.download.DownloadManager
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.ShellActivity
|
||||
import com.gh.gamecenter.databinding.FragmentRealNameBinding
|
||||
import com.gh.gamecenter.normal.NormalFragment
|
||||
import kotlinx.android.synthetic.main.fragment_real_name.*
|
||||
import org.json.JSONObject
|
||||
|
||||
class RealNameInfoFragment : NormalFragment() {
|
||||
|
||||
private var mHasBackdoor: Boolean = false // 是否留有不实名完成也自动开始下载的后门
|
||||
private var mIsForcedToCertificate: Boolean = false
|
||||
private val mViewModel: RealNameInfoViewModel by viewModels()
|
||||
|
||||
@ -35,7 +38,10 @@ class RealNameInfoFragment : NormalFragment() {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
mIsForcedToCertificate =
|
||||
arguments?.getBoolean(EntranceUtils.KEY_IS_FORCED_TO_CERTICIFICE) ?: false
|
||||
arguments?.getBoolean(EntranceUtils.KEY_IS_FORCED_TO_CERTIFICATE) ?: false
|
||||
mHasBackdoor =
|
||||
arguments?.getBoolean(EntranceUtils.KEY_IS_FORCED_TO_CERTIFICATE_BUT_WITH_BACKDOOR)
|
||||
?: false
|
||||
|
||||
mBinding.toolbar.normalTitle.text = "实名认证"
|
||||
mBinding.toolbar.normalToolbar.setNavigationOnClickListener { requireActivity().finish() }
|
||||
@ -54,6 +60,13 @@ class RealNameInfoFragment : NormalFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onParentActivityFinish() {
|
||||
super.onParentActivityFinish()
|
||||
if (mHasBackdoor) {
|
||||
DownloadManager.getInstance(requireContext()).resumeAllInvisiblePendingTask()
|
||||
}
|
||||
}
|
||||
|
||||
private fun isRealNameInfoExist(): Boolean {
|
||||
val userInfoEntity = mViewModel.getUserInfo()
|
||||
return if (userInfoEntity != null) {
|
||||
@ -95,7 +108,30 @@ class RealNameInfoFragment : NormalFragment() {
|
||||
.bold(0, 5)
|
||||
.build()
|
||||
|
||||
mBinding.nameEt.filters = arrayOf(TextHelper.getFilter(20, "最多20个字"))
|
||||
val manualHintString = "若您提交的真实身份信息未通过认证或者您持有的为港澳台\\国外身份证件,可转交人工审核"
|
||||
mBinding.manualHintTv.text =
|
||||
SpanBuilder(manualHintString)
|
||||
.click(
|
||||
manualHintString.length - "人工审核".length,
|
||||
manualHintString.length,
|
||||
isUnderlineText = true,
|
||||
colorRes = R.color.theme_font
|
||||
) {
|
||||
startActivity(
|
||||
ShellActivity.getIntent(
|
||||
requireContext(),
|
||||
ShellActivity.Type.MANUALLY_REAL_NAME,
|
||||
Bundle().apply {
|
||||
putString(EntranceUtils.KEY_NAME, nameEt.text.toString())
|
||||
putString(EntranceUtils.KEY_ID, idCardEt.text.toString())
|
||||
}
|
||||
)
|
||||
)
|
||||
requireActivity().finish()
|
||||
}
|
||||
.build()
|
||||
mBinding.manualHintTv.movementMethod = CustomLinkMovementMethod.getInstance()
|
||||
|
||||
mBinding.idCardEt.filters = arrayOf(TextHelper.getFilter(18, "身份证号码最长18位"))
|
||||
|
||||
mBinding.nameEt.doOnTextChanged { _, _, _, _ ->
|
||||
@ -104,6 +140,16 @@ class RealNameInfoFragment : NormalFragment() {
|
||||
mBinding.idCardEt.doOnTextChanged { _, _, _, _ ->
|
||||
updateSubmitBtn()
|
||||
}
|
||||
mBinding.contactTv.visibility = View.VISIBLE
|
||||
mBinding.contactTv.enlargeTouchArea()
|
||||
mBinding.contactTv.setOnClickListener {
|
||||
DirectUtils.directToQqConversation(it.context, CONTACT_QQ)
|
||||
}
|
||||
|
||||
// 适配小屏幕 or 大文字手机
|
||||
if (isScreenUnableToShowAllTheContent()) {
|
||||
changeToCompatView()
|
||||
}
|
||||
}
|
||||
|
||||
private fun initDisplayOnlyView() {
|
||||
@ -111,8 +157,7 @@ class RealNameInfoFragment : NormalFragment() {
|
||||
|
||||
mBinding.badgeContainer.visibility = View.VISIBLE
|
||||
mBinding.run {
|
||||
val set = ConstraintSet()
|
||||
set.run {
|
||||
ConstraintSet().run {
|
||||
clone(infoContainer)
|
||||
clear(R.id.nameTv, ConstraintSet.TOP)
|
||||
connect(
|
||||
@ -146,7 +191,7 @@ class RealNameInfoFragment : NormalFragment() {
|
||||
mBinding.reEditInfoBtn.setOnClickListener {
|
||||
startActivity(
|
||||
ShellActivity.getIntent(requireContext(), ShellActivity.Type.REAL_NAME_INFO).apply {
|
||||
putExtra(EntranceUtils.KEY_IS_FORCED_TO_CERTICIFICE, true)
|
||||
putExtra(EntranceUtils.KEY_IS_FORCED_TO_CERTIFICATE, true)
|
||||
}
|
||||
)
|
||||
requireActivity().finish()
|
||||
@ -159,7 +204,7 @@ class RealNameInfoFragment : NormalFragment() {
|
||||
|
||||
mBinding.submitBtn.isEnabled = validationPair.first
|
||||
if (validationPair.first) {
|
||||
mBinding.submitBtn.background = R.drawable.button_round_2496ff.toDrawable()
|
||||
mBinding.submitBtn.alpha = 1F
|
||||
mBinding.submitBtn.setOnClickListener {
|
||||
val o = JSONObject()
|
||||
o.put("id", mBinding.idCardEt.text.toString())
|
||||
@ -167,7 +212,7 @@ class RealNameInfoFragment : NormalFragment() {
|
||||
mViewModel.postCertification(o.toString(), mIsForcedToCertificate)
|
||||
}
|
||||
} else {
|
||||
mBinding.submitBtn.background = R.drawable.button_round_2496ff_alpha_40.toDrawable()
|
||||
mBinding.submitBtn.alpha = 0.4F
|
||||
}
|
||||
mBinding.errorHintTv.text = validationPair.second
|
||||
}
|
||||
@ -191,4 +236,95 @@ class RealNameInfoFragment : NormalFragment() {
|
||||
return Pair(true, "")
|
||||
}
|
||||
|
||||
/**
|
||||
* 屏幕高度小于等于 1080 (16:9) 的设备看作无法显示完整内容
|
||||
*/
|
||||
private fun isScreenUnableToShowAllTheContent(): Boolean {
|
||||
return DisplayUtils.getScreenHeight() <= 1080
|
||||
}
|
||||
|
||||
private fun changeToCompatView() {
|
||||
mBinding.bodyTv.setLineSpacing(0F, 1F)
|
||||
mBinding.hintTv.setLineSpacing(0F, 1F)
|
||||
mBinding.manualHintTv.setLineSpacing(0F, 1F)
|
||||
|
||||
// 把空隙缩窄
|
||||
ConstraintSet().apply {
|
||||
clone(mBinding.infoContainer)
|
||||
clear(R.id.nameTv, ConstraintSet.TOP)
|
||||
connect(
|
||||
R.id.nameTv,
|
||||
ConstraintSet.TOP,
|
||||
R.id.hintTv,
|
||||
ConstraintSet.BOTTOM,
|
||||
4F.dip2px()
|
||||
)
|
||||
}.applyTo(mBinding.infoContainer)
|
||||
|
||||
ConstraintSet().apply {
|
||||
clone(mBinding.infoContainer)
|
||||
clear(R.id.idCardTv, ConstraintSet.TOP)
|
||||
connect(
|
||||
R.id.idCardTv,
|
||||
ConstraintSet.TOP,
|
||||
R.id.nameEt,
|
||||
ConstraintSet.BOTTOM,
|
||||
4F.dip2px()
|
||||
)
|
||||
}.applyTo(mBinding.infoContainer)
|
||||
|
||||
ConstraintSet().apply {
|
||||
clone(mBinding.infoContainer)
|
||||
clear(R.id.nameEt, ConstraintSet.TOP)
|
||||
connect(
|
||||
R.id.nameEt,
|
||||
ConstraintSet.TOP,
|
||||
R.id.nameTv,
|
||||
ConstraintSet.BOTTOM,
|
||||
4F.dip2px()
|
||||
)
|
||||
}.applyTo(mBinding.infoContainer)
|
||||
|
||||
ConstraintSet().apply {
|
||||
clone(mBinding.infoContainer)
|
||||
clear(R.id.idCardEt, ConstraintSet.TOP)
|
||||
connect(
|
||||
R.id.idCardEt,
|
||||
ConstraintSet.TOP,
|
||||
R.id.idCardTv,
|
||||
ConstraintSet.BOTTOM,
|
||||
4F.dip2px()
|
||||
)
|
||||
}.applyTo(mBinding.infoContainer)
|
||||
|
||||
ConstraintSet().apply {
|
||||
clone(mBinding.infoContainer)
|
||||
clear(R.id.hintTv, ConstraintSet.TOP)
|
||||
connect(
|
||||
R.id.hintTv,
|
||||
ConstraintSet.TOP,
|
||||
R.id.bodyTv,
|
||||
ConstraintSet.BOTTOM,
|
||||
4F.dip2px()
|
||||
)
|
||||
}.applyTo(mBinding.infoContainer)
|
||||
|
||||
// 把按钮上移
|
||||
ConstraintSet().apply {
|
||||
clone(mBinding.infoContainer)
|
||||
clear(R.id.submitBtn, ConstraintSet.TOP)
|
||||
connect(
|
||||
R.id.submitBtn,
|
||||
ConstraintSet.TOP,
|
||||
R.id.idCardEt,
|
||||
ConstraintSet.BOTTOM,
|
||||
4F.dip2px()
|
||||
)
|
||||
}.applyTo(mBinding.infoContainer)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val CONTACT_QQ = "800177318"
|
||||
}
|
||||
|
||||
}
|
||||
@ -114,7 +114,6 @@ class RealNameInfoViewModel(application: Application) : AndroidViewModel(applica
|
||||
PackageInstaller.install(HaloApp.getInstance(), pendingDownloadEntity)
|
||||
RealNameHelper.pendingInstallPkgPath = ""
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -127,7 +127,7 @@ public class UserInfoEditFragment extends NormalFragment {
|
||||
super.onCreate(savedInstanceState);
|
||||
setHasOptionsMenu(true);
|
||||
mEditType = getArguments().getString(UserViewModel.KEY_EDIT_TYPE);
|
||||
mIsForcedToCertificate = getArguments().getBoolean(EntranceUtils.KEY_IS_FORCED_TO_CERTICIFICE);
|
||||
mIsForcedToCertificate = getArguments().getBoolean(EntranceUtils.KEY_IS_FORCED_TO_CERTIFICATE);
|
||||
|
||||
initMenu(R.menu.menu_button);
|
||||
mSaveMenuItem = getItemMenu(R.id.menu_button);
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 316 B |
Binary file not shown.
|
After Width: | Height: | Size: 5.5 KiB |
181
app/src/main/res/layout/fragment_manually_real_name.xml
Normal file
181
app/src/main/res/layout/fragment_manually_real_name.xml
Normal file
@ -0,0 +1,181 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include
|
||||
android:id="@+id/toolbar"
|
||||
layout="@layout/reuse_toolbar"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/infoContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/nameTv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:includeFontPadding="false"
|
||||
android:text="真实姓名"
|
||||
android:textColor="@color/theme_and_333"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/nameEt"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:background="@drawable/bg_shape_fa_radius_2"
|
||||
android:hint="请输入真实姓名"
|
||||
android:padding="8dp"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/text_title"
|
||||
android:textColorHint="@color/text_body"
|
||||
android:textCursorDrawable="@drawable/cursor_color"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintTop_toBottomOf="@id/nameTv" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/idCardTv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:includeFontPadding="false"
|
||||
android:text="身份证件号"
|
||||
android:textColor="@color/theme_and_333"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/nameEt" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/idCardEt"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:background="@drawable/bg_shape_fa_radius_2"
|
||||
android:hint="请输入本人身份证\护照\通行证号码"
|
||||
android:padding="8dp"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/text_title"
|
||||
android:textColorHint="@color/text_body"
|
||||
android:textCursorDrawable="@drawable/cursor_color"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintTop_toBottomOf="@id/idCardTv" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/imageTv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:includeFontPadding="false"
|
||||
android:text="上传首次证件照正面"
|
||||
android:textColor="@color/theme_and_333"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/idCardEt" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageIv"
|
||||
android:layout_width="158dp"
|
||||
android:layout_height="100dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:src="@drawable/bg_manually_real_name_image_placeholder"
|
||||
android:scaleType="centerCrop"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/imageTv" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/imageHintTv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="证件照仅用于身份证认证审核"
|
||||
android:textColor="@color/text_subtitleDesc"
|
||||
android:textSize="11sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/imageIv" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/clearIv"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
app:layout_constraintEnd_toEndOf="@id/imageIv"
|
||||
app:layout_constraintTop_toTopOf="@id/imageIv" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/submitBtn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="44dp"
|
||||
android:layout_marginTop="100dp"
|
||||
android:background="@drawable/download_button_normal_style"
|
||||
android:gravity="center"
|
||||
android:text="提交人工审核"
|
||||
android:alpha="0.4"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/imageIv" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/successContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:background="@color/white"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="48dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@id/submitBtn"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:src="@drawable/ic_manually_real_name_success" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="已提交人工审核,将在1-3个工作日完成审核"
|
||||
android:textColor="@color/text_title"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/contactTv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:text="联系客服"
|
||||
android:textColor="@color/theme_font"
|
||||
android:textSize="14sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@ -140,7 +140,8 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="44dp"
|
||||
android:layout_marginTop="100dp"
|
||||
android:background="@drawable/button_round_2496ff_alpha_40"
|
||||
android:alpha="0.4"
|
||||
android:background="@drawable/download_button_normal_style"
|
||||
android:gravity="center"
|
||||
android:text="提交"
|
||||
android:textColor="@color/white"
|
||||
@ -150,6 +151,20 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/idCardEt" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manualHintTv"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:includeFontPadding="false"
|
||||
android:lineSpacingExtra="3dp"
|
||||
android:textColor="@color/text_subtitleDesc"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/submitBtn"
|
||||
tools:text="若您提交的真实身份信息未通过认证或者您持有的为港澳台\国外身份证件,可转交人工审核" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/errorHintTv"
|
||||
android:layout_width="wrap_content"
|
||||
@ -177,6 +192,20 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/contactTv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:text="联系客服"
|
||||
android:textColor="@color/theme_font"
|
||||
android:textSize="14sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@ -105,6 +105,7 @@ ext {
|
||||
toolargetool = "0.3.0"
|
||||
chart = "3.1.0"
|
||||
zip4j = "2.6.1"
|
||||
easyProtector = "1.1.2"
|
||||
whatTheStack = "0.1.0_rt"
|
||||
apkParser = "v2.6.10"
|
||||
nanohttpd = "2.3.1"
|
||||
|
||||
@ -52,7 +52,7 @@ QUICK_LOGIN_APPKEY=002BAABA2C078342DA33BEAB0A4C6A25
|
||||
|
||||
# hosts
|
||||
DEV_API_HOST=https\://dev-and-api.ghzs.com/v5d5d0/
|
||||
API_HOST=https\://and-api.ghzs.com/v5d4d0/
|
||||
API_HOST=https\://and-api.ghzs.com/v5d5d0/
|
||||
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
||||
@ -35,12 +35,9 @@ if [ ! -f app/build/outputs/apk/internal/release/app-internal-release.apk ]; the
|
||||
fi
|
||||
mv app/build/outputs/apk/internal/release/app-internal-release.apk app/build/tmp/${version}-${versionCode}-internal-${build_time}.apk
|
||||
|
||||
./gradlew rPR -I init.flutter.gradle
|
||||
if [ ! -f app/build/outputs/apk/publish/release/app-publish-release.apk ]; then
|
||||
./gradlew rPR -I init.gradle
|
||||
fi
|
||||
mv app/build/outputs/apk/publish/release/app-publish-release.apk app/build/tmp/${version}-${versionCode}-publish-${build_time}.apk
|
||||
|
||||
git checkout app/build.gradle
|
||||
git checkout gradle.properties
|
||||
git checkout settings.gradle
|
||||
git checkout settings.gradle
|
||||
|
||||
cd assistant_flutter
|
||||
git checkout pubspec.lock
|
||||
Reference in New Issue
Block a user