Merge branch 'dev' into dev-5.6.0

This commit is contained in:
juntao
2021-12-15 15:58:44 +08:00
26 changed files with 1079 additions and 39 deletions

View File

@ -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}"

View File

@ -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";

View File

@ -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
}
/**

View 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);
}
}
}

View File

@ -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";

View File

@ -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) {

View File

@ -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
}

View File

@ -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();
}

View File

@ -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 {

View File

@ -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);
}

View File

@ -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
)

View File

@ -114,7 +114,7 @@ class GameVerticalAdapter(
tempViewHolder.recommendTv = recommendTv
tempViewHolder.recommendContainer = recommendConstraintLayout
tempViewHolder.gameInfo = gameInfoGroup
tempViewHolder.gameServerType
tempViewHolder.gameServerType = serverTypeTv
DownloadItemUtils.updateItem(
mContext,

View File

@ -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);
/**
* 获取新闻详情
*/

View File

@ -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;
}

View File

@ -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
}
}

View File

@ -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)
}
})
}
}

View File

@ -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"
}
}

View File

@ -114,7 +114,6 @@ class RealNameInfoViewModel(application: Application) : AndroidViewModel(applica
PackageInstaller.install(HaloApp.getInstance(), pendingDownloadEntity)
RealNameHelper.pendingInstallPkgPath = ""
}
}
}

View File

@ -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

View 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>

View File

@ -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>

View File

@ -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"

View File

@ -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

View File

@ -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