Commit 33ff1a8f authored by shiyl's avatar shiyl

Merge branch 'dev_commodity' of...

Merge branch 'dev_commodity' of https://git.yidian-inc.com:8021/bp/ShenghuoquanBusiness into dev_commodity
parents 5fa0259e 44f6a5e8
...@@ -93,7 +93,6 @@ dependencies { ...@@ -93,7 +93,6 @@ dependencies {
implementation('com.yidian.android:CommonComponent:0.0.88') { implementation('com.yidian.android:CommonComponent:0.0.88') {
exclude(group: 'com.yidian.android', module: 'NetworkImageLib') exclude(group: 'com.yidian.android', module: 'NetworkImageLib')
} }
implementation files('libs/ks3-androidsdk-1.4.9.jar')
api 'com.github.bumptech.glide:glide:4.11.0' api 'com.github.bumptech.glide:glide:4.11.0'
kapt 'com.github.bumptech.glide:compiler:4.11.0' kapt 'com.github.bumptech.glide:compiler:4.11.0'
......
...@@ -16,7 +16,9 @@ import com.yidian.common.bean.LocalSelectedImageBean ...@@ -16,7 +16,9 @@ import com.yidian.common.bean.LocalSelectedImageBean
import com.yidian.common.bean.SelectedImageBean import com.yidian.common.bean.SelectedImageBean
import com.yidian.common.bean.UploadImageBean import com.yidian.common.bean.UploadImageBean
import com.yidian.common.utils.GlideEngine import com.yidian.common.utils.GlideEngine
import com.yidian.common.utils.KS3Core import com.yidian.framework.mobile.insight.manage.XInsight
import com.yidian.framework.mobile.insight.storage.ImageUploadListener
import com.yidian.framework.mobile.insight.storage.bean.ImageUploadBean
import com.yidian.xarc.xrouter.ResultResolver import com.yidian.xarc.xrouter.ResultResolver
import com.yidian.xpage.observer.DStackActivityManager import com.yidian.xpage.observer.DStackActivityManager
import com.yidian.yac.core.zap.ZapService import com.yidian.yac.core.zap.ZapService
...@@ -35,7 +37,6 @@ import kotlin.collections.ArrayList ...@@ -35,7 +37,6 @@ import kotlin.collections.ArrayList
* 提供调用原生相机拍照、图片选择器、图片预览、图片上传能力 * 提供调用原生相机拍照、图片选择器、图片预览、图片上传能力
*/ */
// TODO: 7/9/21 动态获取权限 // TODO: 7/9/21 动态获取权限
// TODO: 7/9/21 清除缓存
class ImageService : ZapService() { class ImageService : ZapService() {
companion object { companion object {
...@@ -250,35 +251,38 @@ class ImageService : ZapService() { ...@@ -250,35 +251,38 @@ class ImageService : ZapService() {
resolver.fail(CODE_FILE_NOT_EXIST, "file not exist", "文件不存在") resolver.fail(CODE_FILE_NOT_EXIST, "file not exist", "文件不存在")
return return
} }
KS3Core.INSTANCE.uploadObject(file, KS3Core.ObjectType.IMAGE, KS3Core.ScenarioType.COMMODITY, object : KS3Core.OnKS3TaskListener { XInsight.uploadImage(
override fun onTaskStart() { file, ScenarioType.COMMODITY.scenario,
object : ImageUploadListener {
override fun onTaskStart(tag: String?) {
} }
override fun onTaskProgress(progress: Double) { override fun onTaskProgress(progress: Double?, tag: String?) {
} }
override fun onTaskFinish() { override fun onTaskFinish(tag: String?) {
} }
override fun onTaskCancel() { override fun onTaskCancel(tag: String?) {
} }
override fun onTaskSuccess(bucket: String?, objectKey: String?) { override fun onTaskSuccess(bucket: String?, objectKey: String?, imageUploadBean: ImageUploadBean?, tag: String?) {
resolver.success(JSONObject(gson.toJson(UploadImageBean(id, "${bucket}/${objectKey}")))) resolver.success(JSONObject(gson.toJson(imageUploadBean?.image_id?.let { imageId -> UploadImageBean(id, imageId) })))
// 删除临时文件 // 删除临时文件
clearCache(picOriginalPath + it.data.fileName, it.data.compressPath) clearCache(picOriginalPath + it.data.fileName, it.data.compressPath)
} }
override fun onTaskFailure(statesCode: Int, message: String?) { override fun onTaskFailure(code: Int, msg: String?, tag: String?) {
resolver.fail(CODE_FILE_UPLOAD_FAIL, "upload failed", "上传失败") resolver.fail(CODE_FILE_UPLOAD_FAIL, "upload failed", "上传失败")
// 删除临时文件 // 删除临时文件
clearCache(picOriginalPath + it.data.fileName, it.data.compressPath) clearCache(picOriginalPath + it.data.fileName, it.data.compressPath)
} }
}) }, id
)
} ?: resolver.fail(CODE_FILE_NOT_EXIST, "file not exist", "文件不存在") } ?: resolver.fail(CODE_FILE_NOT_EXIST, "file not exist", "文件不存在")
} }
...@@ -306,4 +310,13 @@ class ImageService : ZapService() { ...@@ -306,4 +310,13 @@ class ImageService : ZapService() {
File(compressPath).apply { if (exists()) delete() } File(compressPath).apply { if (exists()) delete() }
} }
/**
* 业务场景类型
* 图片上传时需要区分
*/
enum class ScenarioType(val scenario: String) {
// 商品
COMMODITY("shq_goods")
}
} }
package com.yidian.common.utils
import android.content.Context
import android.graphics.Bitmap
import id.zelory.compressor.Compressor
import id.zelory.compressor.constraint.destination
import id.zelory.compressor.constraint.format
import id.zelory.compressor.constraint.quality
import id.zelory.compressor.constraint.resolution
import kotlinx.coroutines.Dispatchers
import java.io.File
/**
* author: yinjiacheng
* date: 7/15/21 10:55 PM
* description: 图片压缩工具
* https://github.com/zetbaitsu/Compressor
*/
object ImageCompressUtils {
/**
* 图片压缩
* @param srcFile 源文件
* @param destFile 目标文件
* @param destWidth 目标宽度
* @param destHeight 目标高度
* @param quality 压缩质量
* @param format 压缩格式
* @param syncOrAsync 同步or异步
*/
suspend fun compress(
context: Context,
srcFile: File,
destFile: File? = null,
destWidth: Int? = null,
destHeight: Int? = null,
quality: Int? = null,
format: Bitmap.CompressFormat = Bitmap.CompressFormat.JPEG,
syncOrAsync: Boolean = false
): File {
return Compressor.compress(context, srcFile, if (syncOrAsync) Dispatchers.Main else Dispatchers.IO) {
destFile?.let { destination(it) }
destWidth?.let { width -> destHeight?.let { height -> resolution(width, height) } }
quality?.let { quality(it) }
format(format)
}
}
}
...@@ -74,9 +74,6 @@ dependencies { ...@@ -74,9 +74,6 @@ dependencies {
implementation rootProject.ext.dependencies.publicImplementation implementation rootProject.ext.dependencies.publicImplementation
testImplementation rootProject.ext.dependencies.testImplementation testImplementation rootProject.ext.dependencies.testImplementation
androidTestImplementation rootProject.ext.dependencies.androidTestImplementation androidTestImplementation rootProject.ext.dependencies.androidTestImplementation
implementation(name: 'meglive_still', ext: 'aar')
implementation project(':idcard_quality')
implementation files('libs/ks3-androidsdk-1.4.9.jar')
implementation ('com.yidian.android:CommonComponent:0.0.88'){ implementation ('com.yidian.android:CommonComponent:0.0.88'){
exclude(group: 'com.yidian.android', module: 'NetworkImageLib') exclude(group: 'com.yidian.android', module: 'NetworkImageLib')
} }
......
...@@ -112,4 +112,9 @@ object Constant { ...@@ -112,4 +112,9 @@ object Constant {
// 服务端返回的业务错误码 // 服务端返回的业务错误码
const val ERROR_CODE_PERSONAL_AUTH_INFO_DUPLICATE = 2103010 // 身份证号已认证并且认证手机号不是当前手机号 const val ERROR_CODE_PERSONAL_AUTH_INFO_DUPLICATE = 2103010 // 身份证号已认证并且认证手机号不是当前手机号
// 身份证、营业执照压缩参数
const val COMPRESS_DEST_WIDTH = 480 // 目标宽度
const val COMPRESS_DEST_HEIGHT = 640 // 目标高度
const val COMPRESS_DEST_QUALITY = 50 // 目标质量
} }
...@@ -9,7 +9,6 @@ import com.yidian.common.HawkConfig ...@@ -9,7 +9,6 @@ import com.yidian.common.HawkConfig
import com.yidian.common.XRouterPathConstants import com.yidian.common.XRouterPathConstants
import com.yidian.common.XRouterPathConstants.Companion.LOGIN_LIFE_CIRCLE import com.yidian.common.XRouterPathConstants.Companion.LOGIN_LIFE_CIRCLE
import com.yidian.common.base.BaseActivity import com.yidian.common.base.BaseActivity
import com.yidian.common.extensions.clickAntiShake
import com.yidian.common.extensions.hide import com.yidian.common.extensions.hide
import com.yidian.common.extensions.show import com.yidian.common.extensions.show
import com.yidian.common.http.HttpResult import com.yidian.common.http.HttpResult
...@@ -22,7 +21,7 @@ import com.yidian.shenghuoquan.newscontent.http.callback.IGetLifeAccountListCall ...@@ -22,7 +21,7 @@ import com.yidian.shenghuoquan.newscontent.http.callback.IGetLifeAccountListCall
import com.yidian.shenghuoquan.newscontent.http.httpbean.IMobileLoginCallback import com.yidian.shenghuoquan.newscontent.http.httpbean.IMobileLoginCallback
import com.yidian.shenghuoquan.newscontent.http.httpbean.LifeAccountItemBean import com.yidian.shenghuoquan.newscontent.http.httpbean.LifeAccountItemBean
import com.yidian.shenghuoquan.newscontent.http.httpbean.MobileLoginBean import com.yidian.shenghuoquan.newscontent.http.httpbean.MobileLoginBean
import com.yidian.shenghuoquan.newscontent.ui.auth.LifeAccountAuthDataManager import com.yidian.shenghuoquan.newscontent.ui.auth.LifeAccountAuthDataManagerV2
import com.yidian.shenghuoquan.newscontent.ui.auth.LifeAccountIdentityActivity import com.yidian.shenghuoquan.newscontent.ui.auth.LifeAccountIdentityActivity
import com.yidian.shenghuoquan.newscontent.ui.center.MerchantCenterActivity import com.yidian.shenghuoquan.newscontent.ui.center.MerchantCenterActivity
import com.yidian.shenghuoquan.newscontent.utils.CountDownTimerUtils import com.yidian.shenghuoquan.newscontent.utils.CountDownTimerUtils
...@@ -170,8 +169,8 @@ class LoginLifeCircleActivity : BaseActivity<ActivityLoginBinding>(), IGetLifeAc ...@@ -170,8 +169,8 @@ class LoginLifeCircleActivity : BaseActivity<ActivityLoginBinding>(), IGetLifeAc
// 生活号id // 生活号id
StorageUtil.deleteLifeAccountId() StorageUtil.deleteLifeAccountId()
// 清除内存中的认证数据 // 清除内存中的认证数据
LifeAccountAuthDataManager.personalAuthData.clearData() LifeAccountAuthDataManagerV2.personalAuthData.clearData()
LifeAccountAuthDataManager.merchantAuthData.clearData() LifeAccountAuthDataManagerV2.merchantAuthData.clearData()
} }
override fun onDestroy() { override fun onDestroy() {
......
...@@ -41,7 +41,7 @@ class LifeAccountPersonalAuthActivity : ...@@ -41,7 +41,7 @@ class LifeAccountPersonalAuthActivity :
/** /**
* 当前fragment * 当前fragment
*/ */
private lateinit var curFragment: LifeAccountIDCardAuthFragment private lateinit var curFragment: LifeAccountIDCardAuthFragmentV2
/** /**
* 认证数据 还原认证流程用 * 认证数据 还原认证流程用
...@@ -92,11 +92,11 @@ class LifeAccountPersonalAuthActivity : ...@@ -92,11 +92,11 @@ class LifeAccountPersonalAuthActivity :
private fun initData() { private fun initData() {
// 如果有已存在的认证流程则还原进度 // 如果有已存在的认证流程则还原进度
authData?.let { LifeAccountAuthDataManager.generatePersonalAuthData(it) } authData?.let { LifeAccountAuthDataManagerV2.generatePersonalAuthData(it) }
authData?.occupation?.let { viewBind.svOccupation.setContentResult(it) } authData?.occupation?.let { viewBind.svOccupation.setContentResult(it) }
curFragment = LifeAccountIDCardAuthFragment() curFragment = LifeAccountIDCardAuthFragmentV2()
val bundle = Bundle() val bundle = Bundle()
bundle.putSerializable(LifeAccountIDCardAuthFragment.EXTRA_AUTH_DATA, authData) bundle.putSerializable(LifeAccountIDCardAuthFragmentV2.EXTRA_AUTH_DATA, authData)
curFragment.arguments = bundle curFragment.arguments = bundle
supportFragmentManager.beginTransaction() supportFragmentManager.beginTransaction()
.add(R.id.fragment_container, curFragment).commit() .add(R.id.fragment_container, curFragment).commit()
...@@ -106,9 +106,9 @@ class LifeAccountPersonalAuthActivity : ...@@ -106,9 +106,9 @@ class LifeAccountPersonalAuthActivity :
* 检查是否可以进行下一步 * 检查是否可以进行下一步
*/ */
fun checkNextCondition() { fun checkNextCondition() {
if (LifeAccountAuthDataManager.personalAuthData.isAgreePrivacyAgreement if (LifeAccountAuthDataManagerV2.personalAuthData.isAgreePrivacyAgreement
&& !LifeAccountAuthDataManager.personalAuthData.occupation.isNullOrEmpty() && !LifeAccountAuthDataManagerV2.personalAuthData.occupation.isNullOrEmpty()
&& LifeAccountAuthDataManager.personalAuthData.isFaceAuthPass && LifeAccountAuthDataManagerV2.personalAuthData.isFaceAuthPass
) { ) {
viewBind.tvNext.alpha = 1f viewBind.tvNext.alpha = 1f
viewBind.tvNext.isEnabled = true viewBind.tvNext.isEnabled = true
...@@ -130,14 +130,14 @@ class LifeAccountPersonalAuthActivity : ...@@ -130,14 +130,14 @@ class LifeAccountPersonalAuthActivity :
* 避免在升级企业认证时出现数据异常 * 避免在升级企业认证时出现数据异常
*/ */
private fun clearLifeAccountAuthData() { private fun clearLifeAccountAuthData() {
LifeAccountAuthDataManager.personalAuthData.isAgreePrivacyAgreement = false LifeAccountAuthDataManagerV2.personalAuthData.isAgreePrivacyAgreement = false
LifeAccountAuthDataManager.personalAuthData.occupation = null LifeAccountAuthDataManagerV2.personalAuthData.occupation = null
LifeAccountAuthDataManager.personalAuthData.isFaceAuthPass = false LifeAccountAuthDataManagerV2.personalAuthData.isFaceAuthPass = false
LifeAccountAuthDataManager.personalAuthData.realName = null LifeAccountAuthDataManagerV2.personalAuthData.realName = null
LifeAccountAuthDataManager.personalAuthData.idCardNum = null LifeAccountAuthDataManagerV2.personalAuthData.idCardNum = null
LifeAccountAuthDataManager.personalAuthData.occupation = null LifeAccountAuthDataManagerV2.personalAuthData.occupation = null
LifeAccountAuthDataManager.personalAuthData.isIDCardPortraitFaceUpload = false LifeAccountAuthDataManagerV2.personalAuthData.isIDCardPortraitFaceUpload = false
LifeAccountAuthDataManager.personalAuthData.isIDCardNationalEmblemFaceUpload = false LifeAccountAuthDataManagerV2.personalAuthData.isIDCardNationalEmblemFaceUpload = false
} }
override fun onClick(v: View?) { override fun onClick(v: View?) {
...@@ -192,7 +192,7 @@ class LifeAccountPersonalAuthActivity : ...@@ -192,7 +192,7 @@ class LifeAccountPersonalAuthActivity :
when (event?.name) { when (event?.name) {
XEventConfig.CHOOSE_CAREER -> { XEventConfig.CHOOSE_CAREER -> {
val selectedCareer = event.body as String val selectedCareer = event.body as String
LifeAccountAuthDataManager.personalAuthData.occupation = selectedCareer LifeAccountAuthDataManagerV2.personalAuthData.occupation = selectedCareer
viewBind.svOccupation.setContentResult(selectedCareer) viewBind.svOccupation.setContentResult(selectedCareer)
checkNextCondition() checkNextCondition()
} }
...@@ -206,7 +206,7 @@ class LifeAccountPersonalAuthActivity : ...@@ -206,7 +206,7 @@ class LifeAccountPersonalAuthActivity :
// 清空职业标签回显 // 清空职业标签回显
viewBind.svOccupation.clearContentResult() viewBind.svOccupation.clearContentResult()
// 清空身份信息页 直接替换fragment // 清空身份信息页 直接替换fragment
val targetFragment = LifeAccountIDCardAuthFragment() val targetFragment = LifeAccountIDCardAuthFragmentV2()
supportFragmentManager.beginTransaction().remove(curFragment).add(R.id.fragment_container, targetFragment).commit() supportFragmentManager.beginTransaction().remove(curFragment).add(R.id.fragment_container, targetFragment).commit()
curFragment = targetFragment curFragment = targetFragment
} }
......
...@@ -54,9 +54,11 @@ object BitmapUtil { ...@@ -54,9 +54,11 @@ object BitmapUtil {
fun generateFileFromBitmap(bitmap: Bitmap?, quality: Int, destPath: String) { fun generateFileFromBitmap(bitmap: Bitmap?, quality: Int, destPath: String) {
val file = File(destPath) val file = File(destPath)
if (file.exists()) file.delete() if (file.exists()) file.delete()
file.parentFile?.mkdirs() if (file.parentFile?.exists() == false) file.parentFile?.mkdirs()
file.createNewFile() file.createNewFile()
bitmap?.compress(Bitmap.CompressFormat.JPEG, quality, FileOutputStream(destPath)) val outputStream = FileOutputStream(destPath)
bitmap?.compress(Bitmap.CompressFormat.JPEG, quality, outputStream)
outputStream.close()
} }
/** /**
......
...@@ -21,9 +21,13 @@ object FileUtil { ...@@ -21,9 +21,13 @@ object FileUtil {
if (uri != null) { if (uri != null) {
val file = File(path) val file = File(path)
if (file.exists()) file.delete() if (file.exists()) file.delete()
file.parentFile?.mkdirs() if (file.parentFile?.exists() == false) file.parentFile?.mkdirs()
file.createNewFile() file.createNewFile()
context?.contentResolver?.openInputStream(uri)?.copyTo(FileOutputStream(path)) val inputStream = context?.contentResolver?.openInputStream(uri)
val outputStream = FileOutputStream(path)
inputStream?.copyTo(outputStream)
inputStream?.close()
outputStream.close()
} }
} }
...@@ -35,9 +39,11 @@ object FileUtil { ...@@ -35,9 +39,11 @@ object FileUtil {
fun copyFileFromAssets(context: Context?, assetFileName: String, destPath: String) { fun copyFileFromAssets(context: Context?, assetFileName: String, destPath: String) {
val file = File(destPath) val file = File(destPath)
if (file.exists()) file.delete() if (file.exists()) file.delete()
file.parentFile?.mkdirs() if (file.parentFile?.exists() == false) file.parentFile?.mkdirs()
file.createNewFile() file.createNewFile()
context?.assets?.open(assetFileName)?.copyTo(FileOutputStream(file)) val outputStream = FileOutputStream(file)
context?.assets?.open(assetFileName)?.copyTo(outputStream)
outputStream.close()
} }
/** /**
...@@ -49,7 +55,7 @@ object FileUtil { ...@@ -49,7 +55,7 @@ object FileUtil {
if (data.isNullOrEmpty()) return if (data.isNullOrEmpty()) return
val file = File(destPath) val file = File(destPath)
if (file.exists()) file.delete() if (file.exists()) file.delete()
file.parentFile?.mkdirs() if (file.parentFile?.exists() == false) file.parentFile?.mkdirs()
file.createNewFile() file.createNewFile()
File(destPath).writeText(data) File(destPath).writeText(data)
} }
......
...@@ -397,3 +397,6 @@ public static final int *; ...@@ -397,3 +397,6 @@ public static final int *;
-keep class com.amap.api.navi.**{*;} -keep class com.amap.api.navi.**{*;}
-keep class com.autonavi.**{*;} -keep class com.autonavi.**{*;}
#XInsight
-keep public class com.megvii.**{*;}
...@@ -20,6 +20,10 @@ import com.yidian.common.services.XPageService ...@@ -20,6 +20,10 @@ import com.yidian.common.services.XPageService
import com.yidian.common.services.http.MBHttpReqService import com.yidian.common.services.http.MBHttpReqService
import com.yidian.common.utils.UMConfigUtils import com.yidian.common.utils.UMConfigUtils
import com.yidian.commonutil.CommonUtilLifecycleModule import com.yidian.commonutil.CommonUtilLifecycleModule
import com.yidian.framework.mobile.insight.config.ServerUrlConfig
import com.yidian.framework.mobile.insight.config.XDiamondProvide
import com.yidian.framework.mobile.insight.manage.XInsight
import com.yidian.framework.mobile.insight.manage.XInsightConfig
import com.yidian.framework.mobile.xdiamond.SecretUtil import com.yidian.framework.mobile.xdiamond.SecretUtil
import com.yidian.http.ServiceFactory import com.yidian.http.ServiceFactory
import com.yidian.news.util.ProcessUtil import com.yidian.news.util.ProcessUtil
...@@ -57,10 +61,12 @@ class YdSubwayApplication : YdBaseApplication() { ...@@ -57,10 +61,12 @@ class YdSubwayApplication : YdBaseApplication() {
loadService() loadService()
registerActivityLifecycleCallbacks(activityLifecycle) registerActivityLifecycleCallbacks(activityLifecycle)
// 初始化磐石SDK // 初始化磐石SDK
SecretUtil.init(BuildConfig.IS_ENCRYPT_DEBUG_KEY) SecretUtil.init(BuildConfig.IS_ENCRYPT_DEBUG_KEY, BuildConfig.DEBUG)
// 初始化App升级 // 初始化App升级
initAppUpgrade() initAppUpgrade()
initSmartRefreshLayout() initSmartRefreshLayout()
// 初始化慧眼
initXInsight()
Timber.tag("启动").e("onCreate 执行完成") Timber.tag("启动").e("onCreate 执行完成")
} }
} }
...@@ -249,4 +255,50 @@ class YdSubwayApplication : YdBaseApplication() { ...@@ -249,4 +255,50 @@ class YdSubwayApplication : YdBaseApplication() {
}) })
} }
/**
* 慧眼
*/
private fun initXInsight() {
val config = XInsightConfig()
config.cv = AppConfig.cv
config.device_finger = FtDeviceFingerManager.getDeviceFinger()
config.distribution = AppConfig.distribution
config.isEncryption = AppConfig.IS_ENCRYPT
config.version = AppConfig.version
config.serverUrlConfig = ServerUrlConfig.DEV_SERVER_URL
val provide = object : XDiamondProvide {
override fun sign(str: String?): String? {
if (str == null) return null
return SecretUtil.sign(str)
}
override fun rsaEncrypt(str: String?): String? {
if (str == null) return null
return SecretUtil.rsaEncrypt(str)
}
override fun rsaDecrypt(str: String?): String? {
if (str == null) return null
return SecretUtil.rsaDecrypt(str)
}
override fun aesEncrypt(str: String?): String? {
if (str == null) return null
return SecretUtil.aesEncrypt(str)
}
override fun aesDecrypt(str: String?): String? {
if (str == null) return null
return SecretUtil.aesDecrypt(str)
}
override fun verifySign(src: String?, sign: String?): Boolean {
if (src == null || sign == null) return false
return SecretUtil.verifySign(src, sign)
}
}
XInsight.init(this, AppConfig.appid, BuildConfig.DEBUG, config, provide)
}
} }
...@@ -128,7 +128,9 @@ ext.dependencies = [ ...@@ -128,7 +128,9 @@ ext.dependencies = [
'io.reactivex.rxjava3:rxjava:3.0.9', 'io.reactivex.rxjava3:rxjava:3.0.9',
'com.yidian.framework.mobile:ydhttp:1.1.3-SNAPSHOT', 'com.yidian.framework.mobile:ydhttp:1.1.3-SNAPSHOT',
'com.yidian.framework.mobile:ydutils:1.0.1-SNAPSHOT', 'com.yidian.framework.mobile:ydutils:1.0.1-SNAPSHOT',
'com.yidian.framework.mobile:xdiamond:1.0.6', 'com.yidian.framework.mobile:xdiamond:1.0.7',
// 慧眼
'com.yidian.framework.mobile.xinsight:xinsight:1.1.5',
'com.loopj.android:android-async-http:1.4.9', 'com.loopj.android:android-async-http:1.4.9',
// 屏幕适配 // 屏幕适配
...@@ -136,7 +138,9 @@ ext.dependencies = [ ...@@ -136,7 +138,9 @@ ext.dependencies = [
//https://github.com/CymChad/BaseRecyclerViewAdapterHelper //https://github.com/CymChad/BaseRecyclerViewAdapterHelper
'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4', 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4',
// PictureSelector2.0 https://github.com/LuckSiege/PictureSelector // PictureSelector2.0 https://github.com/LuckSiege/PictureSelector
'io.github.lucksiege:pictureselector:v2.7.3-rc05' 'io.github.lucksiege:pictureselector:v2.7.3-rc05',
// Compressor https://github.com/zetbaitsu/Compressor
'id.zelory:compressor:3.0.1'
], ],
other : [ other : [
':CommonLib:Common' ':CommonLib:Common'
......
apply plugin: 'com.android.library'
android {
compileSdkVersion build_versions.compileSdkVersion
defaultConfig {
minSdkVersion build_versions.minSdkVersion
targetSdkVersion build_versions.targetSdkVersion
versionCode rootProject.ext.android.versionCode
versionName rootProject.ext.android.versionName
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
android {
lintOptions {
abortOnError false
}
}
}
dependencies {
api fileTree(include: ['*.jar'], dir: 'libs')
androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
implementation 'com.android.support:appcompat-v7:25+'
implementation 'com.android.support.constraint:constraint-layout:2.0.1'
}
package com.megvii.demo;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumentation test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.megvii.idcard.demo", appContext.getPackageName());
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.megvii.idcard.quality">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true">
<activity
android:name="com.megvii.demo.activity.IDCardDetectActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:launchMode="singleTask"
android:screenOrientation="portrait" />
</application>
</manifest>
\ No newline at end of file
package com.megvii.demo.bo;
public class Constant {
public static final String ISVERTICAL="ISVERTICAL";
public static final String CARD_SIDE="CARDSIDE";
public static final String VERSION_ID="MegIDCardQuality 1.4.1A";
public final static String CACHEIMAGE = "idcard";
}
package com.megvii.demo.utils;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Build;
import android.view.View;
import com.megvii.demo.bo.Constant;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class CommonUtils {
/**
* 把dp根据当前屏幕密度转换成px
*
* @param context
* @param dpValue
* @return
*/
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 保存bitmap至指定Picture文件夹
*/
public static String saveBitmap(Context mContext, Bitmap bitmaptosave, String fileName) {
if (bitmaptosave == null)
return null;
File mediaStorageDir = mContext
.getExternalFilesDir(Constant.CACHEIMAGE);
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
return null;
}
}
// String bitmapFileName = System.currentTimeMillis() + ".jpg";
// String bitmapFileName = System.currentTimeMillis() + "";
FileOutputStream fos = null;
try {
fos = new FileOutputStream(mediaStorageDir + "/" + fileName);
boolean successful = bitmaptosave.compress(
Bitmap.CompressFormat.JPEG, 100, fos);
if (successful)
return mediaStorageDir.getAbsolutePath() + "/" + fileName;
else
return null;
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void toggleHideyBar(Activity activity) {
int uiOptions = activity.getWindow().getDecorView().getSystemUiVisibility();
int newUiOptions = uiOptions;
if (Build.VERSION.SDK_INT >= 14) {
newUiOptions ^= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
}
if (Build.VERSION.SDK_INT >= 16) {
newUiOptions ^= View.SYSTEM_UI_FLAG_FULLSCREEN;
}
if (Build.VERSION.SDK_INT >= 19) {
newUiOptions ^= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
}
activity.getWindow().getDecorView().setSystemUiVisibility(newUiOptions);
}
public static byte[] bmp2byteArr(Bitmap bmp) {
if (bmp == null || bmp.isRecycled())
return null;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 90, byteArrayOutputStream);
if (byteArrayOutputStream != null) {
try {
byteArrayOutputStream.close();
} catch (IOException e) {
}
}
return byteArrayOutputStream.toByteArray();
}
public static String saveBytw(Context context, byte[] b, String fileName) {
BufferedOutputStream stream = null;
File file = null;
try {
file = context.getExternalFilesDir("megvii");
FileOutputStream fstream = new FileOutputStream(file + "/" + fileName + "_" + System.currentTimeMillis());
stream = new BufferedOutputStream(fstream);
stream.write(b);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
return file.getAbsolutePath();
}
}
package com.megvii.demo.utils;
import android.content.Context;
import android.util.Base64;
import com.megvii.demo.bo.Constant;
import java.util.UUID;
public class Configuration {
public static String getUUID(Context context) {
String uuid = SpFileUtil.getString(context, SpFileUtil.FILE_NAME, SpFileUtil.KEY_UUID, "");
if ("".equals(uuid)) {
uuid = UUID.randomUUID().toString();
uuid = Base64.encodeToString(uuid.getBytes(), Base64.DEFAULT);
SpFileUtil.saveString(context, SpFileUtil.FILE_NAME, SpFileUtil.KEY_UUID, uuid);
}
return uuid;
}
public static void setIsVertical(Context context, boolean ISVERTICAL) { //屏幕方向 0竖屏 1 横屏
SpFileUtil.saveBoolean(context, SpFileUtil.FILE_NAME, Constant.ISVERTICAL, ISVERTICAL);
}
public static boolean getIsVertical(Context context) {
return SpFileUtil.getBoolean(context, SpFileUtil.FILE_NAME, Constant.ISVERTICAL, true);
}
public static void setCardType(Context context, int cardType) { //0:双面,1:人像面,2:国徽面(默认人像面)
SpFileUtil.saveInt(context, SpFileUtil.FILE_NAME, Constant.CARD_SIDE, cardType);
}
public static int getCardType(Context context) {
return SpFileUtil.getInt(context, SpFileUtil.FILE_NAME, Constant.CARD_SIDE, 1);
}
}
package com.megvii.demo.utils;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
import android.util.Log;
import android.view.Surface;
import android.widget.RelativeLayout;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ICamera {
public Camera mCamera;
public int cameraWidth;
public int cameraHeight;
private int cameraId = 0;// 后置摄像头
private boolean mIsVertical = false;
private int screenWidth;
private int screenHeight;
public ICamera(boolean isVertical) {
this.mIsVertical = isVertical;
}
/**
* 打开相机
*/
public Camera openCamera(Activity activity) {
try {
screenWidth = activity.getWindowManager().getDefaultDisplay()
.getWidth();
screenHeight = activity.getWindowManager().getDefaultDisplay()
.getHeight();
mCamera = Camera.open(cameraId);
CameraInfo cameraInfo = new CameraInfo();
Camera.getCameraInfo(cameraId, cameraInfo);
Parameters params = mCamera.getParameters();
Camera.Size bestPreviewSize = getNearestRatioSize(
mCamera.getParameters(), screenWidth, screenHeight);
cameraWidth = bestPreviewSize.width;
cameraHeight = bestPreviewSize.height;
params.setPreviewSize(cameraWidth, cameraHeight);
List<String> focusModes = params.getSupportedFocusModes();
if (focusModes
.contains(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
params.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
int rotation = getCameraAngle(activity);
if (!mIsVertical && cameraId == 0){
mCamera.setDisplayOrientation(0);
}else{
mCamera.setDisplayOrientation(getCameraAngle(activity));
}
mCamera.setParameters(params);
return mCamera;
} catch (Exception e) {
return null;
}
}
public void autoFocus() {
try {
if (mCamera != null) {
Parameters parameters = mCamera.getParameters();
List<String> focusModes = parameters.getSupportedFocusModes();
if (focusModes.contains(Parameters.FOCUS_MODE_AUTO)) {
parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO);
mCamera.cancelAutoFocus();
parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO);
mCamera.setParameters(parameters);
mCamera.autoFocus(null);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 通过屏幕参数、相机预览尺寸计算布局参数
public RelativeLayout.LayoutParams getLayoutParam(Activity activity) {
float scale = cameraWidth * 1.0f / cameraHeight;
int layout_width = screenWidth;
int layout_height = (int) (layout_width * 1.0f * scale);
Log.w("layoutParam:","screenWidth = "+screenWidth);
Log.w("layoutParam:","layout_width = "+layout_width);
Log.w("layoutParam:","layout_height = "+layout_height);
if(!mIsVertical){
layout_height = screenHeight;
layout_width = (int) (layout_height * 1.0f * scale);
Log.w("layoutParam:","layout_height = "+layout_height);
Log.w("layoutParam:","layout_width = "+layout_width);
}
RelativeLayout.LayoutParams layout_params = new RelativeLayout.LayoutParams(
layout_width, layout_height);
return layout_params;
}
/**
* 预览回调
*/
public void setPreviewCallback(Camera.PreviewCallback mActivity) {
// public void actionDetect(Camera.PreviewCallback mActivity) {
try {
if (mCamera != null) {
mCamera.setPreviewCallback(mActivity);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void startPreview(SurfaceTexture surfaceTexture) {
try {
if (mCamera != null) {
try {
mCamera.setPreviewTexture(surfaceTexture);
mCamera.startPreview();
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void closeCamera() {
try {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.release();
mCamera = null;
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 通过传入的宽高算出最接近于宽高值的相机大小
*/
private Camera.Size calBestPreviewSize(Parameters camPara,
final int width, final int height) {
List<Camera.Size> allSupportedSize = camPara.getSupportedPreviewSizes();
ArrayList<Camera.Size> widthLargerSize = new ArrayList<Camera.Size>();
for (Camera.Size tmpSize : allSupportedSize) {
if (tmpSize.width > tmpSize.height) {
widthLargerSize.add(tmpSize);
}
}
Collections.sort(widthLargerSize, new Comparator<Camera.Size>() {
@Override
public int compare(Camera.Size lhs, Camera.Size rhs) {
int off_one = Math.abs(lhs.width * lhs.height - width * height);
int off_two = Math.abs(rhs.width * rhs.height - width * height);
return off_one - off_two;
}
});
return widthLargerSize.get(0);
}
public Camera.Size getNearestRatioSize(Parameters para,
final int screenWidth, final int screenHeight) {
List<Camera.Size> supportedSize = para.getSupportedPreviewSizes();
if (mIsVertical) {
for (Camera.Size tmp : supportedSize) {
if (tmp.width == 640 && tmp.height == 480) {
return tmp;
}
}
}else{
for (Camera.Size tmp : supportedSize) {
if (tmp.width == 1280 && tmp.height == 720) {
return tmp;
}
}
}
Collections.sort(supportedSize, new Comparator<Camera.Size>() {
@Override
public int compare(Camera.Size lhs, Camera.Size rhs) {
int diff1 = (((int) ((1000 * (Math.abs(lhs.width
/ (float) lhs.height - screenWidth
/ (float) screenHeight))))) << 16)
- lhs.width;
int diff2 = (((int) (1000 * (Math.abs(rhs.width
/ (float) rhs.height - screenWidth
/ (float) screenHeight)))) << 16)
- rhs.width;
return diff1 - diff2;
}
});
return supportedSize.get(0);
}
/**
* 打开前置或后置摄像头
*/
public Camera getCameraSafely(int cameraId) {
Camera camera = null;
try {
camera = Camera.open(cameraId);
} catch (Exception e) {
camera = null;
}
return camera;
}
public RelativeLayout.LayoutParams getParams(Camera camera) {
Parameters camPara = camera.getParameters();
// 注意Screen是否初始化
Camera.Size bestPreviewSize = calBestPreviewSize(camPara, screenWidth,
screenHeight);
cameraWidth = bestPreviewSize.width;
cameraHeight = bestPreviewSize.height;
camPara.setPreviewSize(cameraWidth, cameraHeight);
camera.setParameters(camPara);
float scale = bestPreviewSize.width / bestPreviewSize.height;
RelativeLayout.LayoutParams layoutPara = new RelativeLayout.LayoutParams(
(int) (bestPreviewSize.width),
(int) (bestPreviewSize.width / scale));
layoutPara.addRule(RelativeLayout.CENTER_HORIZONTAL);// 设置照相机水平居中
return layoutPara;
}
public Bitmap getBitMap(byte[] data, Camera camera, boolean mIsFrontalCamera) {
int width = camera.getParameters().getPreviewSize().width;
int height = camera.getParameters().getPreviewSize().height;
YuvImage yuvImage = new YuvImage(data, camera.getParameters()
.getPreviewFormat(), width, height, null);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
yuvImage.compressToJpeg(new Rect(0, 0, width, height), 80,
byteArrayOutputStream);
byte[] jpegData = byteArrayOutputStream.toByteArray();
// 获取照相后的bitmap
Bitmap tmpBitmap = BitmapFactory.decodeByteArray(jpegData, 0,
jpegData.length);
Matrix matrix = new Matrix();
matrix.reset();
if (mIsFrontalCamera) {
matrix.setRotate(-90);
} else {
matrix.setRotate(90);
}
tmpBitmap = Bitmap.createBitmap(tmpBitmap, 0, 0, tmpBitmap.getWidth(),
tmpBitmap.getHeight(), matrix, true);
tmpBitmap = tmpBitmap.copy(Bitmap.Config.ARGB_8888, true);
int hight = tmpBitmap.getHeight() > tmpBitmap.getWidth() ? tmpBitmap
.getHeight() : tmpBitmap.getWidth();
float scale = hight / 800.0f;
if (scale > 1) {
tmpBitmap = Bitmap.createScaledBitmap(tmpBitmap,
(int) (tmpBitmap.getWidth() / scale),
(int) (tmpBitmap.getHeight() / scale), false);
}
return tmpBitmap;
}
/**
* 获取照相机旋转角度
*/
public int getCameraAngle(Activity activity) {
int rotateAngle = 90;
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
rotateAngle = (info.orientation + degrees) % 360;
rotateAngle = (360 - rotateAngle) % 360; // compensate the mirror
} else { // back-facing
rotateAngle = (info.orientation - degrees + 360) % 360;
}
return rotateAngle;
}
}
\ No newline at end of file
package com.megvii.demo.utils;
import android.content.Context;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class ModelUtil {
public static byte[] readModel(Context context, int rawId) {
InputStream inputStream = null;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int count = -1;
try {
inputStream = context.getResources().openRawResource(rawId);
while ((count = inputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, count);
}
byteArrayOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return byteArrayOutputStream.toByteArray();
}
}
package com.megvii.demo.utils;
public class RotaterUtil {
public static byte[] rotate(byte[] data, int imageWidth, int imageHeight,
int rotate) {
switch (rotate) {
case 0:
return data;
case 90:
return rotateYUV420Degree90(data, imageWidth, imageHeight);
case 180:
return rotateYUV420Degree180(data, imageWidth, imageHeight);
case 270:
return rotateYUV420Degree270(data, imageWidth, imageHeight);
}
return data;
}
public static byte[] rotateYUV420Degree90(byte[] data, int imageWidth,
int imageHeight) {
byte[] yuv = new byte[imageWidth * imageHeight * 3 / 2];
// Rotate the Y luma
int i = 0;
for (int x = 0; x < imageWidth; x++) {
for (int y = imageHeight - 1; y >= 0; y--) {
yuv[i] = data[y * imageWidth + x];
i++;
}
}
// Rotate the U and V color components
i = imageWidth * imageHeight * 3 / 2 - 1;
for (int x = imageWidth - 1; x > 0; x = x - 2) {
for (int y = 0; y < imageHeight / 2; y++) {
yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + x];
i--;
yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth)
+ (x - 1)];
i--;
}
}
return yuv;
}
public static byte[] rotateYUV420Degree180(byte[] data, int imageWidth,
int imageHeight) {
byte[] yuv = new byte[imageWidth * imageHeight * 3 / 2];
int i = 0;
int count = 0;
for (i = imageWidth * imageHeight - 1; i >= 0; i--) {
yuv[count] = data[i];
count++;
}
i = imageWidth * imageHeight * 3 / 2 - 1;
for (i = imageWidth * imageHeight * 3 / 2 - 1; i >= imageWidth
* imageHeight; i -= 2) {
yuv[count++] = data[i - 1];
yuv[count++] = data[i];
}
return yuv;
}
public static byte[] rotateYUV420Degree270(byte[] data, int imageWidth,
int imageHeight) {
byte[] yuv = new byte[imageWidth * imageHeight * 3 / 2];
// Rotate the Y luma
int index = 0;
int i = 0;
for (int x = imageWidth - 1; x >= 0; x--) {
index = 0;
for (int y = 0; y < imageHeight; y++) {
yuv[i] = data[index + x];
i++;
index += imageWidth;
}
}
// Rotate the U and V color components
i = imageWidth * imageHeight;
int count = imageWidth * imageHeight;
for (int x = imageWidth - 1; x > 0; x = x - 2) {
index = count;
for (int y = 0; y < imageHeight / 2; y++) {
yuv[i] = data[index + (x - 1)];
i++;
yuv[i] = data[index + x];
i++;
index += imageWidth;
}
}
return yuv;
}
}
package com.megvii.demo.utils;
import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import java.util.Map;
public class SpFileUtil {
/**
* 保存在手机里的文件名
*/
public static final String FILE_NAME = "meg_idcard_quality";
public static final String KEY_UUID = "key_uuid";
/**
* @WARNING Be careful, this maybe overwrite a exist value.<br>
*/
public static void removeKey(Context context, String filename, String key) {
if (context != null) {
SharedPreferences preferences = context.getSharedPreferences(filename, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.remove(key);
editor.apply();
}
}
/**
* @WARNNING Be careful, this maybe overwrite a exist value.<br>
*/
public static void saveString(Context context, String filename, String key, String value) {
if (context != null) {
SharedPreferences preferences = context.getSharedPreferences(filename, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putString(key, value);
editor.apply();
}
}
/**
* get String from shared Preferences.<br>
*
* @PROMPT if the img_demo_target value is not exist, it will return the defaultValue.
*/
public static String getString(Context context, String filename, String key, String defaultValue) {
try {
SharedPreferences preferences = context.getSharedPreferences(filename, Context.MODE_PRIVATE);
return preferences.getString(key, defaultValue);
} catch (Exception e) {
e.printStackTrace();
}
return defaultValue;
}
/**
* @WARNNING Be careful, this maybe overwrite a exist value.<br>
*/
public static void savelong(Context context, String filename, String key, long value) {
if (context != null) {
SharedPreferences preferences = context.getSharedPreferences(filename, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putLong(key, value);
editor.apply();
}
}
/**
* get long value from shared Preferences.<br>
*
* @PROMPT if the img_demo_target value is not exist, it will return the defaultValue.
*/
public static long getlong(Context context, String filename, String key, long defaultValue) {
try {
SharedPreferences preferences = context.getSharedPreferences(filename, Context.MODE_PRIVATE);
return preferences.getLong(key, defaultValue);
} catch (Exception e) {
e.printStackTrace();
}
return defaultValue;
}
/**
* @WARNNING Be careful, this maybe overwrite a exist value.<br>
*/
public static void saveInt(Context context, String filename, String key, int value) {
if (context != null) {
SharedPreferences preferences = context.getSharedPreferences(filename, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putInt(key, value);
editor.apply();
}
}
/**
* get int value from shared Preferences.<br>
*
* @PROMPT if the img_demo_target value is not exist, it will return the defaultValue.
*/
public static int getInt(Context context, String filename, String key, int defaultValue) {
try {
SharedPreferences preferences = context.getSharedPreferences(filename, Context.MODE_PRIVATE);
return preferences.getInt(key, defaultValue);
} catch (Exception e) {
e.printStackTrace();
}
return defaultValue;
}
/**
* @WARNNING Be careful, this maybe overwrite a exist value.<br>
*/
public static void saveFloat(Context context, String filename, String key, float value) {
if (context != null) {
SharedPreferences preferences = context.getSharedPreferences(filename, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putFloat(key, value);
editor.apply();
}
}
/**
* get float value from shared Preferences.<br>
*
* @PROMPT if the img_demo_target value is not exist, it will return the defaultValue.
*/
public static float getFloat(Context context, String filename, String key, float defaultValue) {
try {
SharedPreferences preferences = context.getSharedPreferences(filename, Context.MODE_PRIVATE);
return preferences.getFloat(key, defaultValue);
} catch (Exception e) {
e.printStackTrace();
}
return defaultValue;
}
/**
* @WARNNING Be careful, this maybe overwrite a exist value.<br>
*/
public static void saveBoolean(Context context, String filename, String key, boolean value) {
if (context != null) {
SharedPreferences preferences = context.getSharedPreferences(filename, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean(key, value);
editor.apply();
}
}
/**
* get boolean value from shared Preferences.<br>
*
* @PROMPT if the img_demo_target value is not exist, it will return the defaultValue.
*/
public static boolean getBoolean(Context context, String filename, String key, boolean defaultValue) {
try {
SharedPreferences preferences = context.getSharedPreferences(filename, Context.MODE_PRIVATE);
return preferences.getBoolean(key, defaultValue);
} catch (Exception e) {
e.printStackTrace();
}
return defaultValue;
}
/**
* get key-value map of particular filename from shared Preferences.<br>
*/
public static Map<String, ?> getFile(Context context, String filename) {
try {
SharedPreferences preferences = context.getSharedPreferences(filename, Context.MODE_PRIVATE);
return preferences.getAll();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void clearFile(Context context, String filename) {
try {
SharedPreferences preferences = context.getSharedPreferences(filename, Context.MODE_PRIVATE);
preferences.edit().clear().apply();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 保存ContentValues 的数据
*
* @param mContext
* @param contentValues
*/
public static void saveData(Context mContext, ContentValues contentValues) {
try {
int size = (contentValues != null && contentValues.size() > 0)
? contentValues.size() : 0;
if (size > 0) {
for (String colName : contentValues.keySet()) {
SpFileUtil.saveString(mContext, SpFileUtil.FILE_NAME, colName, contentValues.get(colName).toString());
}
}
} catch (Throwable e) {
}
}
}
package com.megvii.demo.utils;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;
public class StatusBarCompat {
private static final int INVALID_VAL = -1;
private static final int COLOR_DEFAULT = Color.parseColor("#20000000");
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static void compat(Activity activity, int statusColor) {
//当前手机版本为5.0及以上
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (statusColor != INVALID_VAL) {
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);//设置高亮反转
activity.getWindow().setStatusBarColor(statusColor);
}
return;
}
//当前手机版本为4.4
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
&& Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
int color = COLOR_DEFAULT;
ViewGroup contentview = (ViewGroup) activity.findViewById(android.R.id.content);
if (statusColor != INVALID_VAL) {
color = statusColor;
}
View statusBarView = new View(activity);
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
getStatusBarHeight(activity)
);
statusBarView.setBackgroundColor(color);
contentview.addView(statusBarView, lp);
}
}
public static int getStatusBarHeight(Context context) {
int result = 0;
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
}
\ No newline at end of file
package com.megvii.demo.view;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import com.megvii.idcard.quality.R;
import com.megvii.idcardquality.bean.IDCardAttr;
public class IDCardGuide extends View {
private Bitmap mCircleBmp;
private Canvas mCanvas;
private float IDCARD_RATIO = 856.0f / 540.0f;
private int mViewWidth = 0;
private int mViewHeight = 0;
private float reduceRatio = 1.0f;
private Rect srcRect;
private Rect bitmapRect;
private RectF roundRec;
private RectF disRectF;
private Paint mRectPaint;
private Paint mCirclePaint;
private Paint duffXmodePaint;
private PorterDuffXfermode duffXmode;
private int rectType = 1;//1小框80% 2 大框88%
private float roundRectLeft1;
private float roundRectTop1;
private float roundRectRight1;
private float roundRectBottom1;
private float roundRectLeft;
private float roundRectTop;
private float roundRectRight;
private float roundRectBottom;
private float roundRectLeft2;
private float roundRectTop2;
private float roundRectRight2;
private float roundRectBottom2;
private boolean isDrawImage = true;//是否画框
public static final float BIG_RECT_PERCENT = 0.85f;//大框的比例
public static final float SMALL_RECT_PERCENT = 0.65f;//小框的比例
public IDCardGuide(Context context) {
this(context, null);
}
public IDCardGuide(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public IDCardGuide(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void computeArgs() {
mViewWidth = getWidth();
mViewHeight = getHeight();
}
private void init(Context context) {
srcRect = new Rect();
disRectF = new RectF();
roundRec = new RectF();
bitmapRect = new Rect();
mRectPaint = new Paint();
mRectPaint.setAntiAlias(true);
mCirclePaint = new Paint();
mCirclePaint.setAntiAlias(true);
duffXmodePaint = new Paint();
duffXmodePaint.setAntiAlias(true);
}
private Bitmap bitmap;
public void setCardSide(IDCardAttr.IDCardSide cardSide) {
int bitmapId = R.mipmap.bg_sfz_empty_icon;
bitmap = BitmapFactory.decodeResource(getContext().getResources(), bitmapId);
isDrawImage = true;
isDrawLine = true;
rectType = 1;
roundRectColor = Color.parseColor("#FFFFFF");
requestLayout();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
float roundRectWidth = width * BIG_RECT_PERCENT;
float roundRectHeight = roundRectWidth / IDCARD_RATIO;
roundRectLeft1 = (width - roundRectWidth) / 2;
roundRectRight1 = roundRectLeft1 + roundRectWidth;
float previewHeight = width * (4 / 3.0f);
float roundCenterY = previewHeight * (2 / 5.0f) + getResources().getDimension(R.dimen.checktrue_title_bar_height);
roundRectTop1 = roundCenterY - roundRectHeight / 2;
roundRectBottom1 = roundCenterY + roundRectHeight / 2;
roundRectWidth = width * SMALL_RECT_PERCENT;
roundRectHeight = roundRectWidth / IDCARD_RATIO;
roundRectLeft2 = (width - roundRectWidth) / 2;
roundRectRight2 = roundRectLeft2 + roundRectWidth;
roundRectTop2 = roundCenterY - roundRectHeight / 2;
roundRectBottom2 = roundCenterY + roundRectHeight / 2;
roundRectLeft = rectType == 1 ? roundRectLeft1 : roundRectLeft2;
roundRectRight = rectType == 1 ? roundRectRight1 : roundRectRight2;
roundRectTop = rectType == 1 ? roundRectTop1 : roundRectTop2;
roundRectBottom = rectType == 1 ? roundRectBottom1 : roundRectBottom2;
}
@Override
protected void onDraw(Canvas canvas) {
computeArgs();
drawRectAndEmpCicle();
disRectF.set(0f, 0f, getWidth(), getHeight());
canvas.drawBitmap(mCircleBmp, srcRect, disRectF, mRectPaint);
drawRoundRect(canvas);
}
/**
* 画一个挖出圆角空间的矩形(因为效率原因在绘画时先进行缩放)
*
* @return
*/
private void drawRectAndEmpCicle() {
mRectPaint.setColor(Color.parseColor("#99000000"));
// mRectPaint.setColor(Color.argb(125, 0, 0, 0));
//阴影层图像
if (mCircleBmp == null) {
mCircleBmp = Bitmap.createBitmap((int) (mViewWidth / reduceRatio), (int) (mViewHeight / reduceRatio), Bitmap.Config.ARGB_8888);
}
if (mCanvas == null) {
mCanvas = new Canvas(mCircleBmp);
}
srcRect.set(0, 0, (int) (mViewWidth / reduceRatio), (int) (mViewHeight / reduceRatio));
mCanvas.drawRect(srcRect, mRectPaint);
if (isDrawImage) {
if (duffXmode == null) {
duffXmode = new PorterDuffXfermode(PorterDuff.Mode.XOR);
}
duffXmodePaint.setXfermode(duffXmode);
roundRec.set(roundRectLeft / reduceRatio, roundRectTop / reduceRatio, roundRectRight / reduceRatio, roundRectBottom / reduceRatio);
mCanvas.drawRoundRect(roundRec, 20, 20, duffXmodePaint);
duffXmodePaint.setXfermode(null);
}
}
private boolean isDrawLine = false;
public void setDrawLine(boolean flag) {
isDrawLine = flag;
if (!flag) {
roundRectColor = Color.parseColor("#67DAFF");
}
invalidate();
}
private int roundRectColor = Color.parseColor("#FFFFFF");
private void drawRoundRect(Canvas canvas) {
if (isDrawImage) {
mCirclePaint.setColor(roundRectColor);
if (!isDrawLine) {//蓝色线
mCirclePaint.setStrokeWidth(getResources().getDimension(R.dimen.dimen_3));
} else {//白色线
mCirclePaint.setStrokeWidth(getResources().getDimension(R.dimen.dimen_1));
}
mCirclePaint.setStyle(Paint.Style.STROKE);
roundRec.set(roundRectLeft, roundRectTop, roundRectRight, roundRectBottom);
canvas.drawRoundRect(roundRec, 20, 20, mCirclePaint);
}
}
public RectF getPosition(int rectType) {
RectF rectF = new RectF();
if (rectType == 1) {
rectF.left = roundRectLeft1 / (float) getWidth();
rectF.top = roundRectTop1 / (float) getHeight();
rectF.right = roundRectRight1 / (float) getWidth();
rectF.bottom = roundRectBottom1 / (float) getHeight();
} else if (rectType == 2) {
rectF.left = roundRectLeft2 / (float) getWidth();
rectF.top = roundRectTop2 / (float) getHeight();
rectF.right = roundRectRight2 / (float) getWidth();
rectF.bottom = roundRectBottom2 / (float) getHeight();
}
return rectF;
}
public RectF getScreenPosition(int rectType) {
RectF rectF = new RectF();
if (rectType == 1) {
rectF.left = roundRectLeft1;
rectF.top = roundRectTop1;
rectF.right = roundRectRight1;
rectF.bottom = roundRectBottom1;
} else if (rectType == 2) {
rectF.left = roundRectLeft2;
rectF.top = roundRectTop2;
rectF.right = roundRectRight2;
rectF.bottom = roundRectBottom2;
}
return rectF;
}
}
package com.megvii.demo.view;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import com.megvii.idcard.quality.R;
import com.megvii.idcardquality.bean.IDCardAttr;
public class IDCardGuideH extends View {
private Bitmap mCircleBmp;
private Canvas mCanvas;
private float IDCARD_RATIO = 856.0f / 540.0f;
private int mViewWidth = 0;
private int mViewHeight = 0;
private float reduceRatio = 1.0f;
private Rect srcRect;
private Rect bitmapRect;
private RectF roundRec;
private RectF disRectF;
private Paint mRectPaint;
private Paint mCirclePaint;
private Paint duffXmodePaint;
private PorterDuffXfermode duffXmode;
private int rectType = 1;//1小框80% 2 大框88%
private float roundRectLeft1;
private float roundRectTop1;
private float roundRectRight1;
private float roundRectBottom1;
private float roundRectLeft;
private float roundRectTop;
private float roundRectRight;
private float roundRectBottom;
private float roundRectLeft2;
private float roundRectTop2;
private float roundRectRight2;
private float roundRectBottom2;
private Bitmap lineBitmap;
private boolean isDrawImage = true;//是否画框
public static final float BIG_RECT_PERCENT = 0.95f;//大框的比例
public static final float SMALL_RECT_PERCENT = 0.65f;//小框的比例
public IDCardGuideH(Context context) {
this(context, null);
}
public IDCardGuideH(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public IDCardGuideH(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void computeArgs() {
mViewWidth = getWidth();
mViewHeight = getHeight();
}
private void init(Context context) {
srcRect = new Rect();
disRectF = new RectF();
roundRec = new RectF();
bitmapRect = new Rect();
mRectPaint = new Paint();
mRectPaint.setAntiAlias(true);
mCirclePaint = new Paint();
mCirclePaint.setAntiAlias(true);
duffXmodePaint = new Paint();
duffXmodePaint.setAntiAlias(true);
}
private Bitmap bitmap;
public void setCardSide(IDCardAttr.IDCardSide cardSide) {
int bitmapId = R.mipmap.bg_sfz_empty_icon;
bitmap = BitmapFactory.decodeResource(getContext().getResources(), bitmapId);
isDrawImage = true;
rectType = 1;
roundRectColor = Color.parseColor("#FFFFFF");
requestLayout();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
float roundRectHeight = height * 0.52f;
// float roundRectHeight = width * (4 / 3.0f);
// float roundRectWidth = roundRectHeight * (4 / 3.0f);
float roundRectWidth = roundRectHeight * IDCARD_RATIO;
roundRectLeft1 = (width - roundRectWidth) / 2;
roundRectRight1 = roundRectLeft1 + roundRectWidth;
float roundCenterY = height / 2;
roundRectTop1 = roundCenterY - roundRectHeight / 2;
roundRectBottom1 = roundCenterY + roundRectHeight / 2;
roundRectHeight = height * 0.67f;
roundRectWidth = roundRectHeight * (3 / 4.0f);
// roundRectWidth = roundRectHeight * IDCARD_RATIO;
roundRectLeft2 = (width - roundRectWidth) / 2;
roundRectRight2 = roundRectLeft2 + roundRectWidth;
roundRectTop2 = roundCenterY - roundRectHeight / 2;
roundRectBottom2 = roundCenterY + roundRectHeight / 2;
roundRectLeft = rectType == 1 ? roundRectLeft1 : roundRectLeft2;
roundRectRight = rectType == 1 ? roundRectRight1 : roundRectRight2;
roundRectTop = rectType == 1 ? roundRectTop1 : roundRectTop2;
roundRectBottom = rectType == 1 ? roundRectBottom1 : roundRectBottom2;
// int width = MeasureSpec.getSize(widthMeasureSpec);
// int height = MeasureSpec.getSize(heightMeasureSpec);
//
// float roundRectWidth = width * BIG_RECT_PERCENT;
// float roundRectHeight = roundRectWidth / IDCARD_RATIO;
//
// roundRectLeft1 = (width - roundRectWidth) / 2;
// roundRectRight1 = roundRectLeft1 + roundRectWidth;
//
// float previewHeight = width * (4 / 3.0f);
// float roundCenterY = previewHeight * (2 / 5.0f) + getResources().getDimension(R.dimen.checktrue_title_bar_height);
//
// roundRectTop1 = roundCenterY - roundRectHeight / 2;
// roundRectBottom1 = roundCenterY + roundRectHeight / 2;
//
// roundRectWidth = width * SMALL_RECT_PERCENT;
// roundRectHeight = roundRectWidth / IDCARD_RATIO;
// roundRectLeft2 = (width - roundRectWidth) / 2;
// roundRectRight2 = roundRectLeft2 + roundRectWidth;
// roundRectTop2 = roundCenterY - roundRectHeight / 2;
// roundRectBottom2 = roundCenterY + roundRectHeight / 2;
//
// roundRectLeft = rectType == 1 ? roundRectLeft1 : roundRectLeft2;
// roundRectRight = rectType == 1 ? roundRectRight1 : roundRectRight2;
// roundRectTop = rectType == 1 ? roundRectTop1 : roundRectTop2;
// roundRectBottom = rectType == 1 ? roundRectBottom1 : roundRectBottom2;
}
@Override
protected void onDraw(Canvas canvas) {
computeArgs();
drawRectAndEmpCicle();
//将bitmap拷贝到canvas上并恢复原来大小
disRectF.set(0f, 0f, getWidth(), getHeight());
canvas.drawBitmap(mCircleBmp, srcRect, disRectF, mRectPaint);
drawRoundRect(canvas);
}
/**
* 画一个挖出圆角空间的矩形(因为效率原因在绘画时先进行缩放)
*
* @return
*/
private void drawRectAndEmpCicle() {
mRectPaint.setColor(Color.argb(125, 0, 0, 0));
//阴影层图像
if (mCircleBmp == null) {
mCircleBmp = Bitmap.createBitmap((int) (mViewWidth / reduceRatio), (int) (mViewHeight / reduceRatio), Bitmap.Config.ARGB_8888);
}
if (mCanvas == null) {
mCanvas = new Canvas(mCircleBmp);
}
srcRect.set(0, 0, (int) (mViewWidth / reduceRatio), (int) (mViewHeight / reduceRatio));
mCanvas.drawRect(srcRect, mRectPaint);
if (isDrawImage) {
if (duffXmode == null) {
duffXmode = new PorterDuffXfermode(PorterDuff.Mode.XOR);
}
duffXmodePaint.setXfermode(duffXmode);
roundRec.set(roundRectLeft / reduceRatio, roundRectTop / reduceRatio, roundRectRight / reduceRatio, roundRectBottom / reduceRatio);
mCanvas.drawRoundRect(roundRec, 20, 20, duffXmodePaint);
duffXmodePaint.setXfermode(null);
}
}
public void setDrawLine(boolean flag) {
if (!flag) {
roundRectColor = Color.parseColor("#3DDCFF");
}
invalidate();
}
private int roundRectColor = Color.parseColor("#FFFFFF");
private void drawRoundRect(Canvas canvas) {
if (isDrawImage) {
mCirclePaint.setColor(roundRectColor);
mCirclePaint.setStrokeWidth(getResources().getDimension(R.dimen.dimen_3));
mCirclePaint.setStyle(Paint.Style.STROKE);
roundRec.set(roundRectLeft, roundRectTop, roundRectRight, roundRectBottom);
canvas.drawRoundRect(roundRec, 20, 20, mCirclePaint);
bitmapRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight());
canvas.drawBitmap(bitmap, bitmapRect, roundRec, null);
}
}
public RectF getPosition(int rectType) {
RectF rectF = new RectF();
if (rectType == 1) {
rectF.left = roundRectLeft1 / (float) getWidth();
rectF.top = roundRectTop1 / (float) getHeight();
rectF.right = roundRectRight1 / (float) getWidth();
rectF.bottom = roundRectBottom1 / (float) getHeight();
} else if (rectType == 2) {
rectF.left = roundRectLeft2 / (float) getWidth();
rectF.top = roundRectTop2 / (float) getHeight();
rectF.right = roundRectRight2 / (float) getWidth();
rectF.bottom = roundRectBottom2 / (float) getHeight();
}
return rectF;
}
public RectF getScreenPosition(int rectType) {
RectF rectF = new RectF();
if (rectType == 1) {
rectF.left = roundRectLeft1;
rectF.top = roundRectTop1;
rectF.right = roundRectRight1;
rectF.bottom = roundRectBottom1;
} else if (rectType == 2) {
rectF.left = roundRectLeft2;
rectF.top = roundRectTop2;
rectF.right = roundRectRight2;
rectF.bottom = roundRectBottom2;
}
return rectF;
}
}
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- <scale
android:duration="500"
android:fillAfter="true"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="0.8"
android:toYScale="0.8" /> -->
<translate
android:duration="300"
android:fromXDelta="100%p"
android:startOffset="100"
android:toXDelta="0" />
<!-- <scale
android:duration="500"
android:fillAfter="true"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="800"
android:toXScale="1.25"
android:toYScale="1.25" /> -->
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- <scale
android:duration="500"
android:fillAfter="true"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="0.8"
android:toYScale="0.8" /> -->
<translate
android:duration="300"
android:fromXDelta="-100%p"
android:startOffset="100"
android:toXDelta="0" />
<!-- <scale
android:duration="500"
android:fillAfter="true"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="800"
android:toXScale="1.25"
android:toYScale="1.25" /> -->
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<!--<scale-->
<!--android:duration="100"-->
<!--android:fillAfter="true"-->
<!--android:fromXScale="1.0"-->
<!--android:fromYScale="1.0"-->
<!--android:pivotX="50%"-->
<!--android:pivotY="50%"-->
<!--android:toXScale="0.95"-->
<!--android:toYScale="0.95" /> -->
<translate
android:duration="300"
android:fromXDelta="0"
android:startOffset="100"
android:toXDelta="-100%p" />
<!--<scale-->
<!--android:duration="100"-->
<!--android:fillAfter="true"-->
<!--android:fromXScale="1.0"-->
<!--android:fromYScale="1.0"-->
<!--android:pivotX="50%"-->
<!--android:pivotY="50%"-->
<!--android:startOffset="600"-->
<!--android:toXScale="1.05"-->
<!--android:toYScale="1.05" /> -->
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<!--<scale-->
<!--android:duration="100"-->
<!--android:fillAfter="true"-->
<!--android:fromXScale="1.0"-->
<!--android:fromYScale="1.0"-->
<!--android:pivotX="50%"-->
<!--android:pivotY="50%"-->
<!--android:toXScale="0.95"-->
<!--android:toYScale="0.95" />-->
<translate
android:duration="300"
android:fromXDelta="0"
android:startOffset="100"
android:toXDelta="100%p" />
<!--<scale-->
<!--android:duration="100"-->
<!--android:fillAfter="true"-->
<!--android:fromXScale="1.0"-->
<!--android:fromYScale="1.0"-->
<!--android:pivotX="50%"-->
<!--android:pivotY="50%"-->
<!--android:startOffset="600"-->
<!--android:toXScale="1.05"-->
<!--android:toYScale="1.05" />-->
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!-- 上下滑入式 -->
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="200"
android:fromYDelta="100%p"
android:toYDelta="0"
/>
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="200"
/>
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!-- 上下滑入式 -->
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="200"
android:fromYDelta="0"
android:toYDelta="50%p" />
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:duration="200"
/>
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="20dp"/>
<solid android:color="@color/toast_checktrue_bg_color"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rl_idcard_cn_root_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:fitsSystemWindows="true">
<TextureView
android:id="@+id/idcardscan_cn_layout_surface"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.megvii.demo.view.IDCardGuide
android:id="@+id/idcardscan_cn_layout_guide"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="false"
android:focusable="false" />
<ImageView
android:id="@+id/iv_people_light_icon"
android:layout_width="347dp"
android:layout_height="220dp"
android:layout_centerInParent="true"
android:background="@mipmap/bg_people_light_icon"
android:visibility="gone" />
<ImageView
android:id="@+id/iv_china_light_icon"
android:layout_width="347dp"
android:layout_height="220dp"
android:layout_centerInParent="true"
android:background="@mipmap/bg_china_light_icon"
android:visibility="gone" />
<ImageView
android:id="@+id/ib_animal_breath_view"
android:layout_width="347dp"
android:layout_height="220dp"
android:layout_centerInParent="true"
android:background="@mipmap/bg_sfz_light"
android:visibility="gone" />
<ImageView
android:id="@+id/ib_animal_one_view"
android:layout_width="347dp"
android:layout_height="220dp"
android:layout_centerInParent="true"
android:background="@mipmap/bg_sfz_light"
android:visibility="gone" />
<TextView
android:id="@+id/tv_tip_text"
android:layout_width="286dp"
android:layout_height="30dp"
android:layout_centerInParent="true"
android:textColor="#FFFFFFFF"
android:textSize="20sp"
android:visibility="gone" />
<include layout="@layout/view_toast" />
<com.megvii.demo.view.IDCardGuideH
android:id="@+id/idcardscan_cn_layout_guide_h"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="false"
android:focusable="false"
android:visibility="visible" />
<ImageView
android:id="@+id/iv_idcard_cn_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone" />
<ImageView
android:id="@+id/iv_icon_tick_all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@mipmap/icon_tick"
android:visibility="gone" />
<RelativeLayout
android:id="@+id/rl_megvii_idcard_cn_tips"
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:background="@android:color/white"
android:visibility="visible">
<TextView
android:id="@+id/tv_megvii_idcard_cn_tips"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="@dimen/idcard_cn_dimen_30"
android:text="@string/idcard_cn_tips_face"
android:textColor="@color/idcard_cn_tips_text_color"
android:textSize="@dimen/idcard_cn_tips_text_size" />
</RelativeLayout>
<TextView
android:id="@+id/tv_megvii_idcard_cn_h_tips"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="@dimen/idcard_cn_horizontal_tips_margin_bottom"
android:text="@string/idcard_cn_tips_emblem"
android:textColor="@color/idcard_cn_tips_text_color"
android:textSize="@dimen/idcard_cn_tips_text_size"
android:visibility="gone" />
<include
android:id="@+id/in_idcard_cn_title_bar"
layout="@layout/view_title_bar" />
<RelativeLayout
android:id="@+id/rl_megvii_idcard_cn_title_bar_h"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/idcard_cn_dimen_10"
android:background="@android:color/transparent"
android:visibility="gone">
<RelativeLayout
android:id="@+id/rl_megvii_idcard_cn_goback_h"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_megvii_idcard_cn_bg_icon_h"
android:layout_width="@dimen/idcard_cn_gb_icon_width"
android:layout_height="@dimen/idcard_cn_gb_icon_height"
android:layout_centerVertical="true"
android:layout_marginLeft="@dimen/idcard_cn_gb_icon_marg_left"
android:background="@mipmap/iv_megvii_idcard_cn_back_h" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="@id/tv_megvii_idcard_cn_bg_icon_h"
android:text="返回"
android:textColor="@color/idcard_cn_white"
android:textSize="@dimen/idcard_cn_gb_text_size" />
</RelativeLayout>
<TextView
android:id="@+id/tv_megvii_idcard_cn_tips_h"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text=""
android:textColor="@color/idcard_cn_white"
android:textSize="@dimen/idcard_cn_gb_text_size" />
</RelativeLayout>
<ImageView
android:id="@+id/iv_idcard_cn_bottom_logo_h"
android:layout_width="105dp"
android:layout_height="12dp"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="@dimen/idcard_cn_dimen_20"
android:layout_marginBottom="@dimen/idcard_cn_dimen_10"
android:visibility="gone" />
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal"
android:layout_height="match_parent">
<ImageView
android:id="@+id/result_face_image"
android:layout_width="100dp"
android:layout_marginTop="50dp"
android:layout_height="100dp"
android:scaleType="fitCenter" />
<ImageView
android:id="@+id/result_idcard_image"
android:layout_width="300dp"
android:layout_height="200dp"
android:layout_marginTop="10dp"
android:scaleType="fitCenter" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/idcard_cn_title_bar_height"
android:background="@color/idcard_cn_white">
<RelativeLayout
android:id="@+id/rl_megvii_idcard_cn_goback"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_megvii_idcard_cn_bg_icon"
android:layout_width="@dimen/idcard_cn_gb_icon_width"
android:layout_height="@dimen/idcard_cn_gb_icon_height"
android:layout_centerVertical="true"
android:layout_marginLeft="@dimen/idcard_cn_gb_icon_marg_left"
android:background="@mipmap/iv_megvii_idcard_cn_back" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="@id/tv_megvii_idcard_cn_bg_icon"
android:text="返回"
android:textColor="@color/idcard_cn_gb_text_color"
android:textSize="@dimen/idcard_cn_gb_text_size" />
</RelativeLayout>
<TextView
android:id="@+id/tv_megvii_idcard_cn_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="识别结果"
android:textSize="@dimen/idcard_cn_gb_text_size"
android:textColor="@color/idcard_cn_tips_bg_color"
android:layout_centerInParent="true"
android:visibility="gone"
/>
<TextView
android:id="@+id/tv_megvii_idcard_cn_right"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textColor="#00B2E3"
android:textSize="@dimen/idcard_cn_gb_text_size"
android:gravity="center"
android:paddingLeft="@dimen/idcard_cn_dimen_15"
android:paddingRight="@dimen/idcard_cn_dimen_15"
android:text="重新拍摄"
android:layout_alignParentRight="true"
android:visibility="gone"
/>
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_toast"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="@drawable/auth_toast_bg"
android:visibility="gone"
android:orientation="vertical">
<ImageView
android:id="@+id/iv_auth_toast_tip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="8dp"
android:visibility="gone"
android:background="@mipmap/icon_auth_toast_tip" />
<TextView
android:id="@+id/toast_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="40dp"
android:paddingTop="6dp"
android:paddingRight="40dp"
android:paddingBottom="6dp"
android:text="请将身份证四边与线框对齐"
android:textColor="@color/toast_checktrue_text_color"
android:textSize="@dimen/checktrue_toast_text_size" />
</RelativeLayout>
\ No newline at end of file
<resources>
<style name="Megvii_idcard_cn_SDKTheme" parent="@android:style/Theme.Holo.NoActionBar.TranslucentDecor">
</style>
<style name="idcard_cn_TranslutTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- values-v19下的主题 -->
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">false</item>
</style>
<style name="idcard_cn_FullScreenTheme" parent="@android:style/Theme.Holo.Light.NoActionBar.Fullscreen">
<!-- values-v19下的主题 -->
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">false</item>
</style>
</resources>
\ No newline at end of file
<resources>
<style name="idcard_cn_AppTheme" parent="@android:style/Theme.Holo.NoActionBar.TranslucentDecor">
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
<style name="idcard_cn_TranslutTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- values-v21下的主题 -->
<item name="android:windowTranslucentStatus">false</item>
<item name="android:windowTranslucentNavigation">false</item>
<!-- android 5.0开始,需要把颜色设置成透明,否则状态栏会呈现系统默认的浅灰色 -->
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
<style name="idcard_cn_FullScreenTheme" parent="@android:style/Theme.Holo.Light.NoActionBar.Fullscreen">
<!-- values-v21下的主题 -->
<item name="android:windowTranslucentStatus">false</item>
<item name="android:windowTranslucentNavigation">false</item>
<!-- android 5.0开始,需要把颜色设置成透明,否则状态栏会呈现系统默认的浅灰色 -->
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="idcard_cn_white">#FFFFFF</color>
<color name="idcard_cn_black">#000000</color>
<color name="idcard_cn_flash_bg_color">#FFFFFF</color>
<color name="idcard_cn_tips_bg_color">#282830</color>
<color name="idcard_cn_tips_text_color">#4A4A4A</color>
<color name="idcard_cn_toast_text_color">#FFFFFF</color>
<color name="idcard_cn_title_bar_bg_color">#FAFAFA</color>
<color name="idcard_cn_gb_text_color">#5FA3FA</color>
<color name="idcard_cn_falsh_page_text_color">#4A4A4A</color>
<color name="idcard_cn_toast_bg_color">#80000000</color>
<color name="idcard_cn_upload_btn_bg_color">#5FA3FA</color>
<color name="idcard_cn_info_text_color">#515666</color>
<color name="idcard_cn_press_color">#3171C2</color>
<color name="idcard_cn_agreement_unchecked_bt_color">#CFD6DD</color>
<color name="idcard_cn_blue">#51c3f6</color>
<color name="toast_checktrue_bg_color">#80000000</color>
<color name="toast_checktrue_text_color">#FFFFFF</color>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="idcard_cn_title_bar_height">44dp</dimen>
<dimen name="idcard_cn_flash_page_big_text">32sp</dimen>
<dimen name="idcard_cn_flash_page_big_text_margin">40dp</dimen>
<dimen name="idcard_cn_tips_bg_height">190dp</dimen>
<dimen name="idcard_cn_tips_text_size">32sp</dimen>
<dimen name="idcard_cn_tips_text_detail_size">14sp</dimen>
<dimen name="idcard_cn_toast_text_size">12sp</dimen>
<dimen name="idcard_cn_toast_text_padding_top">7dp</dimen>
<dimen name="idcard_cn_toast_text_padding_left">25dp</dimen>
<dimen name="idcard_cn_result_big_text_size">30sp</dimen>
<dimen name="idcard_cn_result_small_text_size">18sp</dimen>
<dimen name="idcard_cn_gb_icon_width">18dp</dimen>
<dimen name="idcard_cn_gb_icon_height">18dp</dimen>
<dimen name="idcard_cn_gb_icon_marg_left">16dp</dimen>
<dimen name="idcard_cn_gb_text_size">18sp</dimen>
<dimen name="idcard_cn_horizontal_tips_margin_bottom">24dp</dimen>
<dimen name="idcard_cn_result_item_height">50dp</dimen>
<dimen name="idcard_cn_info_text_size">14sp</dimen>
<dimen name="idcard_cn_warning_small_text_margin">10dp</dimen>
<dimen name="idcard_cn_dialog_content_margin_left">25dp</dimen>
<dimen name="idcard_cn_dialog_content_margin_top">15dp</dimen>
<dimen name="idcard_cn_dialog_line_margin_top">22dp</dimen>
<dimen name="idcard_cn_flash_image_width">258dp</dimen>
<dimen name="idcard_cn_flash_image_height">170dp</dimen>
<dimen name="idcard_cn_image_desc_text_size">14sp</dimen>
<dimen name="idcard_cn_falsh_page_start_btn_text">16sp</dimen>
<dimen name="idcard_cn_user_agree_text_size">12sp</dimen>
<dimen name="idcard_cn_user_agree_text_margin_left">8dp</dimen>
<dimen name="idcard_cn_check_box_size">13.5dip</dimen>
<dimen name="idcard_cn_start_bt_width">300dp</dimen>
<dimen name="idcard_cn_start_bt_height">44dp</dimen>
<dimen name="idcard_cn_start_bt_margin_bottom">80dp</dimen>
<dimen name="idcard_guide_round_rect_left">15dp</dimen>
<dimen name="idcard_guide_landscape_round_rect_width">398dp</dimen>
<dimen name="idcard_guide_landscape_round_rect_height">254dp</dimen>
<dimen name="idcard_cn_dimen_20">20dp</dimen>
<dimen name="idcard_cn_dimen_10">10dp</dimen>
<dimen name="idcard_cn_dimen_15">15dp</dimen>
<dimen name="idcard_cn_dimen_30">30dp</dimen>
<dimen name="idcard_cn_dimen_16">16dp</dimen>
<dimen name="idcard_cn_dimen_90">90dp</dimen>
<dimen name="idcard_cn_dimen_28">28dp</dimen>
<dimen name="idcard_cn_dimen_4">4dp</dimen>
<dimen name="idcard_cn_dimen_60">60dp</dimen>
<dimen name="idcard_cn_dimen_1">1dp</dimen>
<dimen name="idcard_cn_dimen_3">3dp</dimen>
<dimen name="idcard_cn_dimen_5">5dp</dimen>
<dimen name="dimen_1">1dp</dimen>
<dimen name="dimen_2">2dp</dimen>
<dimen name="dimen_5">5dp</dimen>
<dimen name="dimen_3">3dp</dimen>
<dimen name="checktrue_toast_text_size">16sp</dimen>
<dimen name="checktrue_bg_tick_bg_height">35dp</dimen>
<dimen name="checktrue_bg_tick_top_margin">32dp</dimen>
<dimen name="checktrue_bg_tick_left_margin">28dp</dimen>
<dimen name="checktrue_toast_text_padding_height">10dp</dimen>
<dimen name="idcard_checktrue_rect_big_offset">16dp</dimen>
<dimen name="idcard_checktrue_rect_little_offset">8dp</dimen>
<dimen name="checktrue_title_bar_height">44dp</dimen>
<dimen name="dimen_90">90dp</dimen>
</resources>
\ No newline at end of file
<resources>
<string name="app_name">身份证质量检测</string>
<string name="idcard_cn_tips_face">人像面拍摄</string>
<string name="idcard_cn_tips_face_detial">请将身份证人像面放在框内</string>
<string name="idcard_cn_tips_emblem">国徽面拍摄</string>
<string name="idcard_cn_tips_emblem_detial">请将身份证国徽面放在框内</string>
<string name="remind_idcard_quality_failed_1">未检测到身份证</string>
<string name="remind_idcard_quality_failed_2">请对齐线框</string>
<string name="remind_idcard_quality_failed_2_1">请再次对齐线框</string>
<string name="remind_idcard_quality_failed_3">图像不清晰,请调整拍摄</string>
<string name="remind_idcard_quality_failed_4">存在反光,请调整拍摄</string>
<string name="remind_idcard_quality_failed_5">存在阴影,请调整拍摄</string>
<string name="remind_idcard_quality_failed_6">请拍摄人像面</string>
<string name="remind_idcard_quality_failed_7">请拍摄国徽面</string>
<string name="remind_idcard_quality_failed_8">身份证倒置,请放正</string>
<string name="tip_good_again">很好,请再次对齐</string>
<string name="idcard_cn_upload">确认并上传</string>
<string name="idcard_cn_re_shoot">重新拍摄</string>
<string name="idcard_cn_warning_text">识别失败</string>
<string name="idcard_cn_warning_small_text">请注意拍摄角度及光线,并确保身份证两面文字清晰</string>
<string name="idcard_cn_dialog_content">拍摄时请将身份证放入框内,请注意拍摄角度及光线,并确保身份证两面文字清晰</string>
<string name="idcard_cn_agree_toast_text">请先同意并勾选《FaceID用户协议》</string>
<string name="idcard_cn_guide_text_double_side">即将进行身份证人像面和国徽面的扫描拍摄</string>
<string name="idcard_cn_guide_text_front_side">即将进行身份证人像面的扫描拍摄</string>
<string name="idcard_cn_guide_text_back_side">即将进行身份证国徽面的扫描拍摄</string>
<string name="tip_rect_first_tip">请保证身份证边缘与线框对齐</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="idcard_cn_Transparent">
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsTranslucent">true</item>
</style>
<style name="idcard_cn_TranslutTheme" parent="Megvii_idcard_cn_SDKTheme">
<!-- values下的主题 在4.4之前的版本,设置不了。直接跟随系统主题 -->
</style>
<style name="IDCard_CN_NoActionBar.Slide" parent="idcard_cn_TranslutTheme">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowAnimationStyle">@style/IDCard.CN.DarkActionBar.Slide.Animation</item>
</style>
<style name="idcard_cn_FullScreenTheme" parent="@android:style/Theme.Holo.Light.NoActionBar.Fullscreen">
</style>
<style name="idcard_info_style">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">@color/idcard_cn_info_text_color</item>
<item name="android:textSize">@dimen/idcard_cn_info_text_size</item>
<item name="android:layout_centerVertical">true</item>
</style>
<style name="IDCard_CN_AnimBottom" parent="@android:style/Animation">
<item name="android:windowEnterAnimation">@anim/idcard_cn_push_bottom_in</item>
<item name="android:windowExitAnimation">@anim/idcard_cn_push_bottom_out</item>
</style>
<style name="IDCard.CN.DarkActionBar.Slide.Animation" parent="@android:style/Animation.Activity">
<item name="android:activityOpenEnterAnimation">@anim/idcard_cn_mg_slide_in_left</item>
<item name="android:activityOpenExitAnimation">@anim/idcard_cn_mg_slide_out_left</item>
<item name="android:activityCloseEnterAnimation">@anim/idcard_cn_mg_slide_in_left</item>
<item name="android:activityCloseExitAnimation">@anim/idcard_cn_mg_slide_out_left</item>
</style>
</resources>
\ No newline at end of file
package com.megvii.demo;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}
\ No newline at end of file
...@@ -10,4 +10,3 @@ include ':Components:xbirdbusiness' ...@@ -10,4 +10,3 @@ include ':Components:xbirdbusiness'
//setBinding(new Binding([gradle: this])) //setBinding(new Binding([gradle: this]))
//evaluate(new File("../YDSubway_flutter/.android", 'include_flutter.groovy')) //evaluate(new File("../YDSubway_flutter/.android", 'include_flutter.groovy'))
include ':Components:userinfo' include ':Components:userinfo'
include ':idcard_quality'
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment