Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
ShenghuoquanBusiness
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
bp
ShenghuoquanBusiness
Commits
ef82a071
Commit
ef82a071
authored
Jun 02, 2021
by
yinjiacheng
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add 个人认证流程相关接口
parent
7f18ade4
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
298 additions
and
20 deletions
+298
-20
URLs.kt
...onLib/Common/src/main/java/com/yidian/common/http/URLs.kt
+6
-2
LifeAccountPersonalAuthData.kt
...nghuoquan/newscontent/bean/LifeAccountPersonalAuthData.kt
+9
-0
ApiService.kt
...va/com/yidian/shenghuoquan/newscontent/http/ApiService.kt
+72
-0
CommonService.kt
...com/yidian/shenghuoquan/newscontent/http/CommonService.kt
+13
-0
IAuthAuthenticationCallback.kt
.../newscontent/http/callback/IAuthAuthenticationCallback.kt
+13
-0
IAuthCompleteCallback.kt
...uoquan/newscontent/http/callback/IAuthCompleteCallback.kt
+11
-0
IAuthLiveIdentityCallback.kt
...an/newscontent/http/callback/IAuthLiveIdentityCallback.kt
+11
-0
IAuthPersonalCheckCallback.kt
...n/newscontent/http/callback/IAuthPersonalCheckCallback.kt
+11
-0
AuthAuthenticationBean.kt
...oquan/newscontent/http/httpbean/AuthAuthenticationBean.kt
+19
-0
AuthCompleteBean.kt
...henghuoquan/newscontent/http/httpbean/AuthCompleteBean.kt
+10
-0
AuthPersonalCheckBean.kt
...uoquan/newscontent/http/httpbean/AuthPersonalCheckBean.kt
+24
-0
LifeAccountAuthDataManager.kt
...huoquan/newscontent/ui/auth/LifeAccountAuthDataManager.kt
+40
-0
LifeAccountIDCardAuthFragment.kt
...quan/newscontent/ui/auth/LifeAccountIDCardAuthFragment.kt
+56
-16
activity_life_account_personal_auth.xml
...c/main/res/layout/activity_life_account_personal_auth.xml
+3
-2
No files found.
CommonLib/Common/src/main/java/com/yidian/common/http/URLs.kt
View file @
ef82a071
...
...
@@ -6,8 +6,8 @@ class URLs {
companion
object
{
val
BASE_URL
:
String
private
const
val
BASE_URL_DEBUG
=
"http://bp-
test
.go2yd.com"
private
const
val
BASE_URL_PRO
=
"http://bp-
test
.go2yd.com"
private
const
val
BASE_URL_DEBUG
=
"http://bp-
dev
.go2yd.com"
private
const
val
BASE_URL_PRO
=
"http://bp-
dev
.go2yd.com"
init
{
BASE_URL
=
if
(
BuildConfig
.
ENV_DEBUG
){
...
...
@@ -33,5 +33,9 @@ class URLs {
const
val
mobileLogin
=
"/user/user/login"
const
val
accountList
=
"/merchant/auth/account_list"
const
val
createLifeAccount
=
"/merchant/enterprise/create_life"
const
val
authPersonalCheck
=
"/merchant/auth/personal_check"
const
val
authLiveIdentity
=
"/merchant/auth/live_identity"
const
val
authComplete
=
"/merchant/auth/complete"
const
val
authAuthentication
=
"/merchant/auth/authentication"
}
}
\ No newline at end of file
Components/newscontent/src/main/java/com/yidian/shenghuoquan/newscontent/bean/LifeAccountPersonalAuthData.kt
View file @
ef82a071
...
...
@@ -12,4 +12,13 @@ class LifeAccountPersonalAuthData {
var
idCardNationalEmblemFaceObjectKey
:
String
=
""
var
liveDetectBizToken
:
String
=
""
var
liveDetectObjectKey
:
String
=
""
var
idCardPortraitFaceCompleteness
:
Int
=
-
1
var
idCardNationalEmblemFaceCompleteness
:
Int
=
-
1
var
gender
:
String
=
""
var
occupation
:
String
=
"工程师"
var
address
:
String
=
""
var
nationality
:
String
=
""
var
validDateStart
:
String
=
""
var
validDateEnd
:
String
=
""
var
issuedBy
:
String
=
""
}
Components/newscontent/src/main/java/com/yidian/shenghuoquan/newscontent/http/ApiService.kt
View file @
ef82a071
...
...
@@ -7,6 +7,10 @@ import com.yidian.common.http.TransformUtil
import
com.yidian.http.ServiceFactory
import
com.yidian.shenghuoquan.newscontent.bean.CreateLifeAccountBean
import
com.yidian.shenghuoquan.newscontent.bean.ICreateLifeAccountCallback
import
com.yidian.shenghuoquan.newscontent.http.callback.IAuthAuthenticationCallback
import
com.yidian.shenghuoquan.newscontent.http.callback.IAuthCompleteCallback
import
com.yidian.shenghuoquan.newscontent.http.callback.IAuthLiveIdentityCallback
import
com.yidian.shenghuoquan.newscontent.http.callback.IAuthPersonalCheckCallback
import
com.yidian.shenghuoquan.newscontent.http.httpbean.*
import
okhttp3.MultipartBody
...
...
@@ -225,5 +229,73 @@ class ApiService {
}
})
}
// 101 身份信息校验接口
fun
authPersonalCheck
(
apiCallback
:
IAuthPersonalCheckCallback
,
requestParams
:
AuthPersonalCheckBean
.
Request
)
{
val
paramsMap
=
HttpParamsUtils
.
getParamsMap
()
ServiceFactory
.
getInstance
().
createService
(
CommonService
::
class
.
java
)
.
authPersonalCheck
(
paramsMap
,
requestParams
)
.
compose
(
TransformUtil
.
defaultSchedulers
())
.
subscribe
(
object
:
HttpResultSubscriber
<
Any
>()
{
override
fun
onSuccess
(
result
:
HttpResult
<
Any
>?)
{
apiCallback
.
authPersonCheckSuccess
()
}
override
fun
onFailer
(
result
:
HttpResult
<
Any
>?)
{
apiCallback
.
authPersonCheckFailure
(
result
?.
reason
)
}
})
}
// 102 活体识别成功后回调接口
fun
authLiveIdentity
(
apiCallback
:
IAuthLiveIdentityCallback
)
{
val
paramsMap
=
HttpParamsUtils
.
getParamsMap
()
ServiceFactory
.
getInstance
().
createService
(
CommonService
::
class
.
java
)
.
authLiveIdentity
(
paramsMap
)
.
compose
(
TransformUtil
.
defaultSchedulers
())
.
subscribe
(
object
:
HttpResultSubscriber
<
Any
>()
{
override
fun
onSuccess
(
result
:
HttpResult
<
Any
>?)
{
apiCallback
.
authLiveIdentitySuccess
()
}
override
fun
onFailer
(
result
:
HttpResult
<
Any
>?)
{
apiCallback
.
authLiveIdentityFailure
(
result
?.
reason
)
}
})
}
// 103 认证完成后创建生活号
fun
authComplete
(
apiCallback
:
IAuthCompleteCallback
,
requestParams
:
AuthCompleteBean
.
Request
)
{
val
paramsMap
=
HttpParamsUtils
.
getParamsMap
()
ServiceFactory
.
getInstance
().
createService
(
CommonService
::
class
.
java
)
.
authComplete
(
paramsMap
,
requestParams
)
.
compose
(
TransformUtil
.
defaultSchedulers
())
.
subscribe
(
object
:
HttpResultSubscriber
<
Any
>()
{
override
fun
onSuccess
(
result
:
HttpResult
<
Any
>?)
{
apiCallback
.
authCompleteSuccess
()
}
override
fun
onFailer
(
result
:
HttpResult
<
Any
>?)
{
apiCallback
.
authCompleteFailure
(
result
?.
reason
)
}
})
}
// 104 检测是否可以个人认证,返回认证信息
fun
authAuthentication
(
apiCallback
:
IAuthAuthenticationCallback
)
{
val
paramsMap
=
HttpParamsUtils
.
getParamsMap
()
ServiceFactory
.
getInstance
().
createService
(
CommonService
::
class
.
java
)
.
authAuthentication
(
paramsMap
)
.
compose
(
TransformUtil
.
defaultSchedulers
())
.
subscribe
(
object
:
HttpResultSubscriber
<
AuthAuthenticationBean
.
Response
>()
{
override
fun
onSuccess
(
result
:
HttpResult
<
AuthAuthenticationBean
.
Response
>?)
{
apiCallback
.
authAuthenticationSuccess
(
result
?.
result
)
}
override
fun
onFailer
(
result
:
HttpResult
<
AuthAuthenticationBean
.
Response
>?)
{
apiCallback
.
authAuthenticationFailure
(
result
?.
reason
)
}
})
}
}
}
Components/newscontent/src/main/java/com/yidian/shenghuoquan/newscontent/http/CommonService.kt
View file @
ef82a071
...
...
@@ -59,4 +59,17 @@ interface CommonService {
@Headers
(
"Content-Type: application/json"
)
@POST
(
URLs
.
createLifeAccount
)
fun
createLifeAccount
(
@QueryMap
commonParams
:
Map
<
String
,
String
>,
@Body
requestParams
:
CreateLifeAccountBean
.
Request
)
:
Observable
<
HttpResult
<
Any
?>>
@Headers
(
"Content-Type: application/json"
)
@POST
(
URLs
.
authPersonalCheck
)
fun
authPersonalCheck
(
@QueryMap
commonParams
:
Map
<
String
,
String
>,
@Body
requestParams
:
AuthPersonalCheckBean
.
Request
)
:
Observable
<
HttpResult
<
Any
>>
@GET
(
URLs
.
authLiveIdentity
)
fun
authLiveIdentity
(
@QueryMap
commonParams
:
Map
<
String
,
String
>):
Observable
<
HttpResult
<
Any
>>
@GET
(
URLs
.
authComplete
)
fun
authComplete
(
@QueryMap
commonParams
:
Map
<
String
,
String
>,
@QueryMap
requestParams
:
AuthCompleteBean
.
Request
):
Observable
<
HttpResult
<
Any
>>
@GET
(
URLs
.
authAuthentication
)
fun
authAuthentication
(
@QueryMap
commonParams
:
Map
<
String
,
String
>):
Observable
<
HttpResult
<
AuthAuthenticationBean
.
Response
>>
}
\ No newline at end of file
Components/newscontent/src/main/java/com/yidian/shenghuoquan/newscontent/http/callback/IAuthAuthenticationCallback.kt
0 → 100644
View file @
ef82a071
package
com.yidian.shenghuoquan.newscontent.http.callback
import
com.yidian.shenghuoquan.newscontent.http.httpbean.AuthAuthenticationBean
/**
* author: yinjiacheng
* date: 6/1/21 8:13 PM
* description: API /merchant/auth/authentication
*/
interface
IAuthAuthenticationCallback
{
fun
authAuthenticationSuccess
(
result
:
AuthAuthenticationBean
.
Response
?)
fun
authAuthenticationFailure
(
message
:
String
?)
}
\ No newline at end of file
Components/newscontent/src/main/java/com/yidian/shenghuoquan/newscontent/http/callback/IAuthCompleteCallback.kt
0 → 100644
View file @
ef82a071
package
com.yidian.shenghuoquan.newscontent.http.callback
/**
* author: yinjiacheng
* date: 6/1/21 7:43 PM
* description: API /merchant/auth/complete
*/
interface
IAuthCompleteCallback
{
fun
authCompleteSuccess
()
fun
authCompleteFailure
(
message
:
String
?)
}
\ No newline at end of file
Components/newscontent/src/main/java/com/yidian/shenghuoquan/newscontent/http/callback/IAuthLiveIdentityCallback.kt
0 → 100644
View file @
ef82a071
package
com.yidian.shenghuoquan.newscontent.http.callback
/**
* author: yinjiacheng
* date: 6/1/21 7:52 PM
* description: API /merchant/auth/live_identity
*/
interface
IAuthLiveIdentityCallback
{
fun
authLiveIdentitySuccess
()
fun
authLiveIdentityFailure
(
message
:
String
?)
}
\ No newline at end of file
Components/newscontent/src/main/java/com/yidian/shenghuoquan/newscontent/http/callback/IAuthPersonalCheckCallback.kt
0 → 100644
View file @
ef82a071
package
com.yidian.shenghuoquan.newscontent.http.callback
/**
* author: yinjiacheng
* date: 6/1/21 5:50 PM
* description: API /merchant/auth/personal_check
*/
interface
IAuthPersonalCheckCallback
{
fun
authPersonCheckSuccess
()
fun
authPersonCheckFailure
(
message
:
String
?)
}
\ No newline at end of file
Components/newscontent/src/main/java/com/yidian/shenghuoquan/newscontent/http/httpbean/AuthAuthenticationBean.kt
0 → 100644
View file @
ef82a071
package
com.yidian.shenghuoquan.newscontent.http.httpbean
/**
* author: yinjiacheng
* date: 6/1/21 7:54 PM
* description: API /merchant/auth/authentication
*/
class
AuthAuthenticationBean
(
val
response
:
Response
)
{
data class
Response
(
val
audit_status
:
Int
,
val
back_id_card
:
String
,
val
create_time
:
String
,
val
front_id_card
:
String
,
val
full_name
:
String
,
val
id_card
:
String
,
val
live_identity_status
:
Int
,
val
occupation
:
String
)
}
\ No newline at end of file
Components/newscontent/src/main/java/com/yidian/shenghuoquan/newscontent/http/httpbean/AuthCompleteBean.kt
0 → 100644
View file @
ef82a071
package
com.yidian.shenghuoquan.newscontent.http.httpbean
/**
* author: yinjiacheng
* date: 6/1/21 7:40 PM
* description: API /merchant/auth/complete
*/
class
AuthCompleteBean
(
val
request
:
Request
)
{
data class
Request
(
val
mobile
:
String
)
}
\ No newline at end of file
Components/newscontent/src/main/java/com/yidian/shenghuoquan/newscontent/http/httpbean/AuthPersonalCheckBean.kt
0 → 100644
View file @
ef82a071
package
com.yidian.shenghuoquan.newscontent.http.httpbean
/**
* author: yinjiacheng
* date: 6/1/21 5:46 PM
* description: API /merchant/auth/personal_check
*/
class
AuthPersonalCheckBean
(
val
request
:
Request
)
{
data class
Request
(
val
front_img
:
String
,
val
bak_img
:
String
,
val
front_completeness
:
Int
,
val
bak_completeness
:
Int
,
val
id_card
:
String
,
val
gender
:
String
,
val
name
:
String
,
val
occupation
:
String
,
val
address
:
String
,
val
nationality
:
String
,
val
valid_date_start
:
String
,
val
valid_date_end
:
String
,
val
issued_by
:
String
)
}
\ No newline at end of file
Components/newscontent/src/main/java/com/yidian/shenghuoquan/newscontent/ui/auth/LifeAccountAuthDataManager.kt
View file @
ef82a071
package
com.yidian.shenghuoquan.newscontent.ui.auth
import
com.yidian.shenghuoquan.newscontent.bean.LifeAccountPersonalAuthData
import
com.yidian.shenghuoquan.newscontent.http.httpbean.AuthPersonalCheckBean
import
com.yidian.shenghuoquan.newscontent.http.httpbean.GetIDCardOCRBean
/**
* author: yinjiacheng
...
...
@@ -8,5 +10,43 @@ import com.yidian.shenghuoquan.newscontent.bean.LifeAccountPersonalAuthData
* description: 生活号认证数据管理
*/
object
LifeAccountAuthDataManager
{
val
personalAuthData
by
lazy
{
LifeAccountPersonalAuthData
()
}
/**
* 将身份证OCR结果填入
*/
fun
generatePersonalAuthData
(
data
:
GetIDCardOCRBean
.
Response
)
{
personalAuthData
.
idCardPortraitFaceCompleteness
=
data
.
posit
.
completeness
personalAuthData
.
idCardNationalEmblemFaceCompleteness
=
data
.
posit
.
completeness
personalAuthData
.
idCardNum
=
data
.
posit
.
idcard_number
personalAuthData
.
gender
=
data
.
posit
.
gender
personalAuthData
.
realName
=
data
.
posit
.
name
personalAuthData
.
address
=
data
.
posit
.
address
personalAuthData
.
nationality
=
data
.
posit
.
nationality
personalAuthData
.
validDateStart
=
data
.
back
.
valid_date_start
personalAuthData
.
validDateEnd
=
data
.
back
.
valid_date_end
personalAuthData
.
issuedBy
=
data
.
back
.
issued_by
}
/**
* 使用个人认证数据生成身份信息校验接口请求体
*/
fun
generateAuthPersonalCheckRequest
():
AuthPersonalCheckBean
.
Request
{
return
AuthPersonalCheckBean
.
Request
(
personalAuthData
.
idCardPortraitFaceObjectKey
,
personalAuthData
.
idCardNationalEmblemFaceObjectKey
,
personalAuthData
.
idCardPortraitFaceCompleteness
,
personalAuthData
.
idCardNationalEmblemFaceCompleteness
,
personalAuthData
.
idCardNum
,
personalAuthData
.
gender
,
personalAuthData
.
realName
,
personalAuthData
.
occupation
,
personalAuthData
.
address
,
personalAuthData
.
nationality
,
personalAuthData
.
validDateStart
,
personalAuthData
.
validDateEnd
,
personalAuthData
.
issuedBy
)
}
}
\ No newline at end of file
Components/newscontent/src/main/java/com/yidian/shenghuoquan/newscontent/ui/auth/LifeAccountIDCardAuthFragment.kt
View file @
ef82a071
...
...
@@ -30,6 +30,8 @@ import com.yidian.shenghuoquan.newscontent.bean.BottomSelectBean
import
com.yidian.shenghuoquan.newscontent.constant.Constant
import
com.yidian.shenghuoquan.newscontent.databinding.FragmentLifeAccountIdCardAuthBinding
import
com.yidian.shenghuoquan.newscontent.http.ApiService
import
com.yidian.shenghuoquan.newscontent.http.callback.IAuthLiveIdentityCallback
import
com.yidian.shenghuoquan.newscontent.http.callback.IAuthPersonalCheckCallback
import
com.yidian.shenghuoquan.newscontent.http.httpbean.*
import
com.yidian.shenghuoquan.newscontent.ui.dialog.BottomSelectDialog
import
com.yidian.shenghuoquan.newscontent.utils.BitmapUtil
...
...
@@ -47,7 +49,8 @@ import java.io.FileOutputStream
class
LifeAccountIDCardAuthFragment
:
BaseFragment
<
FragmentLifeAccountIdCardAuthBinding
>(),
View
.
OnClickListener
,
BottomSelectAdapter
.
OnItemClickListener
<
BottomSelectBean
>,
IGetIDCardOCRCallback
,
AuthPersonalGetTokenCallback
,
IdentifyIdOcrVerifyCallback
,
PreCallback
,
DetectCallback
,
KS3Core
.
OnKS3TaskListener
{
DetectCallback
,
KS3Core
.
OnKS3TaskListener
,
IAuthPersonalCheckCallback
,
IAuthLiveIdentityCallback
{
companion
object
{
// 身份证采集页面回传数据
...
...
@@ -184,15 +187,11 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
}
}
R
.
id
.
iv_face_auth_start
->
{
// 若存在上一次活体检测数据则删除 处理活体检测失败 再次进入
File
(
cachePath
+
Constant
.
FILE_PATH_ALIVE_DETECT_VERIFY_DATA
).
delete
()
// 跳转人脸认证
ApiService
.
authPersonalGetToken
(
this
,
AuthPersonalGetTokenBean
.
Request
(
LifeAccountAuthDataManager
.
personalAuthData
.
idCardNum
,
LifeAccountAuthDataManager
.
personalAuthData
.
realName
,
Constant
.
TYPE_MEG_LIVE
)
// 判断是否满足条件进行活体检测
if
(!
checkFaceAuthCondition
())
return
ApiService
.
authPersonalCheck
(
this
,
LifeAccountAuthDataManager
.
generateAuthPersonalCheckRequest
()
)
}
}
...
...
@@ -403,12 +402,7 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
override
fun
getIDCardOCRSuccess
(
result
:
GetIDCardOCRBean
.
Response
?)
{
// 存储认证使用的信息
result
?.
posit
?.
name
?.
let
{
LifeAccountAuthDataManager
.
personalAuthData
.
realName
=
it
}
result
?.
posit
?.
idcard_number
?.
let
{
LifeAccountAuthDataManager
.
personalAuthData
.
idCardNum
=
it
}
result
?.
let
{
LifeAccountAuthDataManager
.
generatePersonalAuthData
(
it
)
}
// 回显OCR结果
viewBinding
.
evRealName
.
fillEditContent
(
result
?.
posit
?.
name
)
viewBinding
.
evIdCardNumber
.
fillEditContent
(
result
?.
posit
?.
idcard_number
)
...
...
@@ -445,6 +439,8 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
changeFaceAuthUI
(
true
)
// 删除活体检测数据
File
(
cachePath
+
Constant
.
FILE_PATH_ALIVE_DETECT_VERIFY_DATA
).
delete
()
// 回调server 保存活体识别认证状态
ApiService
.
authLiveIdentity
(
this
)
}
}
...
...
@@ -532,6 +528,38 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
)
}
override
fun
authPersonCheckSuccess
()
{
// 身份信息校验成功后才允许进行人脸验证
// 若存在上一次活体检测数据则删除 处理活体检测失败 再次进入
File
(
cachePath
+
Constant
.
FILE_PATH_ALIVE_DETECT_VERIFY_DATA
).
delete
()
// 跳转人脸认证
ApiService
.
authPersonalGetToken
(
this
,
AuthPersonalGetTokenBean
.
Request
(
LifeAccountAuthDataManager
.
personalAuthData
.
idCardNum
,
LifeAccountAuthDataManager
.
personalAuthData
.
realName
,
Constant
.
TYPE_MEG_LIVE
)
)
}
override
fun
authPersonCheckFailure
(
message
:
String
?)
{
Log
.
e
(
Constant
.
LIFE_ACCOUNT_AUTH_TAG
,
"request auth personal check failure: message: $message"
)
}
override
fun
authLiveIdentitySuccess
()
{
}
override
fun
authLiveIdentityFailure
(
message
:
String
?)
{
Log
.
e
(
Constant
.
LIFE_ACCOUNT_AUTH_TAG
,
"request auth live identity failure: message: $message"
)
}
/**
* 人脸验证结果UI
* @param result true为验证通过 false为验证未通过
...
...
@@ -550,6 +578,18 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
}
}
/**
* 本地校验是否可以进行人脸验证
* 必须同时满足真实姓名已填、身份证号已填、身份证两面已上传
*/
private
fun
checkFaceAuthCondition
():
Boolean
{
return
LifeAccountAuthDataManager
.
personalAuthData
.
realName
.
isNotEmpty
()
&&
LifeAccountAuthDataManager
.
personalAuthData
.
idCardNum
.
isNotEmpty
()
&&
LifeAccountAuthDataManager
.
personalAuthData
.
idCardPortraitFaceObjectKey
.
isNotEmpty
()
&&
LifeAccountAuthDataManager
.
personalAuthData
.
idCardNationalEmblemFaceObjectKey
.
isNotEmpty
()
}
/**
* 通过Uri获取文件全路径
* 适配Android Q
...
...
Components/newscontent/src/main/res/layout/activity_life_account_personal_auth.xml
View file @
ef82a071
...
...
@@ -84,8 +84,9 @@
android:layout_width=
"27dp"
android:layout_height=
"27dp"
android:layout_marginEnd=
"2dp"
android:background=
"@drawable/selector_protocol_check"
android:button=
"@null"
/>
android:button=
"@drawable/selector_protocol_check"
android:clickable=
"true"
android:focusable=
"true"
/>
<com.yidian.nightmode.widget.YdTextView
android:layout_width=
"wrap_content"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment