Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
supplier
Overview
Overview
Details
Activity
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
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
王宇航
supplier
Commits
189f3098
Commit
189f3098
authored
Dec 26, 2019
by
王宇航
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
登陸功能未完善
parent
1d52dfe1
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
508 additions
and
46 deletions
+508
-46
config.gradle
+2
-1
public-base/build.gradle
+0
-1
public-base/src/main/java/com/joe/base/utils/encryption/Aes.java
+16
-9
public-base/src/main/java/com/joe/base/utils/encryption/BASE64Decoder.java
+165
-0
public-base/src/main/java/com/joe/base/utils/encryption/BASE64Encoder.java
+116
-0
public-base/src/main/java/com/joe/base/widget/view/MyEditText.java
+26
-13
public-base/src/main/res/values/styles.xml
+4
-1
user-login/build.gradle
+1
-0
user-login/src/main/AndroidManifest.xml
+6
-0
user-login/src/main/debug/AndroidManifest.xml
+9
-0
user-login/src/main/java/com/gingersoft/gsa/cloud/user/login/mvp/bean/TestLoginBean.java
+15
-15
user-login/src/main/java/com/gingersoft/gsa/cloud/user/login/mvp/ui/activity/LoginActivity.java
+54
-1
user-login/src/main/java/com/gingersoft/gsa/cloud/user/login/mvp/ui/activity/LoginOutActivity.java
+80
-0
user-login/src/main/res/layout/user_login_activity_login.xml
+14
-5
No files found.
config.gradle
View file @
189f3098
...
@@ -112,7 +112,8 @@ ext {
...
@@ -112,7 +112,8 @@ ext {
"umeng-analytics"
:
"com.umeng.analytics:analytics:6.0.1"
,
"umeng-analytics"
:
"com.umeng.analytics:analytics:6.0.1"
,
// QMUI
// QMUI
"qmui"
:
"com.qmuiteam:qmui:1.2.0"
,
"qmui"
:
"com.qmuiteam:qmui:1.2.0"
,
"arms"
:
"me.jessyan:arms:2.5.2"
"arms"
:
"me.jessyan:arms:2.5.2"
,
"fastjson"
:
"com.alibaba:fastjson:1.2.46"
]
]
}
}
public-base/build.gradle
View file @
189f3098
...
@@ -36,6 +36,5 @@ dependencies {
...
@@ -36,6 +36,5 @@ dependencies {
androidTestImplementation
'androidx.test.espresso:espresso-core:3.2.0'
androidTestImplementation
'androidx.test.espresso:espresso-core:3.2.0'
implementation
files
(
'libs/javabase64-1.2.jar'
)
implementation
files
(
'libs/javabase64-1.2.jar'
)
implementation
files
(
'libs/sun.misc.BASE64Decoder.jar'
)
implementation
files
(
'libs/sun.misc.BASE64Decoder.jar'
)
implementation
rootProject
.
ext
.
dependencies
[
"qmui"
]
implementation
rootProject
.
ext
.
dependencies
[
"qmui"
]
}
}
public-base/src/main/java/com/joe/base/utils/encryption/Aes.java
View file @
189f3098
package
com
.
joe
.
base
.
utils
.
encryption
;
package
com
.
joe
.
base
.
utils
.
encryption
;
import
android.util.Base64
;
import
java.math.BigInteger
;
import
java.math.BigInteger
;
import
java.nio.charset.StandardCharsets
;
import
javax.crypto.Cipher
;
import
javax.crypto.Cipher
;
import
javax.crypto.KeyGenerator
;
import
javax.crypto.KeyGenerator
;
...
@@ -70,9 +73,16 @@ public class Aes {
...
@@ -70,9 +73,16 @@ public class Aes {
* @return 编码后的base 64 code
* @return 编码后的base 64 code
*/
*/
public
static
String
base64Encode
(
byte
[]
bytes
)
{
public
static
String
base64Encode
(
byte
[]
bytes
)
{
// return Base64.encodeBase64String();
return
java
.
util
.
Base64
.
getEncoder
().
encodeToString
(
bytes
);
// return android.util.Base64.encodeToString(bytes, Base64.NO_WRAP);
return
new
BASE64Encoder
().
encode
(
bytes
);
// return Base64Utils.encode(bytes);
// return new String(Base64.decode(bytes, android.util.Base64.NO_PADDING));
// return Base64.encodeBase64String(bytes);
}
}
//return Base64.encodeBase64String(bytes);
/**
/**
* base 64 decode
* base 64 decode
...
@@ -100,7 +110,7 @@ public class Aes {
...
@@ -100,7 +110,7 @@ public class Aes {
Cipher
cipher
=
Cipher
.
getInstance
(
ALGORITHMSTR
);
Cipher
cipher
=
Cipher
.
getInstance
(
ALGORITHMSTR
);
cipher
.
init
(
Cipher
.
ENCRYPT_MODE
,
new
SecretKeySpec
(
encryptKey
.
getBytes
(),
"AES"
));
cipher
.
init
(
Cipher
.
ENCRYPT_MODE
,
new
SecretKeySpec
(
encryptKey
.
getBytes
(),
"AES"
));
return
cipher
.
doFinal
(
content
.
getBytes
(
"utf-8"
));
return
cipher
.
doFinal
(
content
.
getBytes
(
StandardCharsets
.
UTF_8
));
}
}
...
@@ -162,15 +172,12 @@ public class Aes {
...
@@ -162,15 +172,12 @@ public class Aes {
* 测试
* 测试
*/
*/
public
static
void
main
(
String
[]
args
)
{
public
static
void
main
(
String
[]
args
)
{
String
content
=
"1.0_1577277614752_1be33e87b9024e08800c458df235adca"
;
String
content
=
"{\"passWord\":\"123456\",\"userName\":\"18384840551\"}"
;
System
.
out
.
println
(
"加密前:"
+
content
);
System
.
out
.
println
(
"加密前:"
+
content
);
System
.
out
.
println
(
"加密密钥和解密密钥:"
+
KEY
);
System
.
out
.
println
(
"加密密钥和解密密钥:"
+
KEY
);
String
encrypt
=
aesEncrypt
(
content
,
KEY
);
String
encrypt
=
aesEncrypt
(
content
,
KEY
)
.
replaceAll
(
"\r|\n"
,
""
);
;
System
.
out
.
println
(
"加密后:"
+
encrypt
);
System
.
out
.
println
(
"加密后:"
+
encrypt
);
String
decrypt
=
aesDecrypt
(
encrypt
,
KEY
);
String
decrypt
=
aesDecrypt
(
"encrypt"
,
KEY
);
System
.
out
.
println
(
"解密后:"
+
decrypt
);
System
.
out
.
println
(
"解密后:"
+
decrypt
);
//base64编码
//base64编码
...
...
public-base/src/main/java/com/joe/base/utils/encryption/BASE64Decoder.java
0 → 100644
View file @
189f3098
/*
2 * Copyright (c) 1995, 2000, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
package
com
.
joe
.
base
.
utils
.
encryption
;
import
java.io.OutputStream
;
import
java.io.PushbackInputStream
;
import
java.io.PrintStream
;
import
Decoder.CEFormatException
;
import
Decoder.CEStreamExhausted
;
import
Decoder.CharacterDecoder
;
/**
32 * This class implements a BASE64 Character decoder as specified in RFC1521.
33 *
34 * This RFC is part of the MIME specification which is published by the
35 * Internet Engineering Task Force (IETF). Unlike some other encoding
36 * schemes there is nothing in this encoding that tells the decoder
37 * where a buffer starts or stops, so to use it you will need to isolate
38 * your encoded data into a single chunk and then feed them this decoder.
39 * The simplest way to do that is to read all of the encoded data into a
40 * string and then use:
41 * <pre>
42 * byte mydata[];
43 * BASE64Decoder base64 = new BASE64Decoder();
44 *
45 * mydata = base64.decodeBuffer(bufferString);
46 * </pre>
47 * This will decode the String in <i>bufferString</i> and give you an array
48 * of bytes in the array <i>myData</i>.
49 *
50 * On errors, this class throws a CEFormatException with the following detail
51 * strings:
52 * <pre>
53 * "BASE64Decoder: Not enough bytes for an atom."
54 * </pre>
55 *
56 * @author Chuck McManis
57 * @see CharacterEncoder
58 * @see BASE64Decoder
59 */
public
class
BASE64Decoder
extends
CharacterDecoder
{
/** This class has 4 bytes per atom */
protected
int
bytesPerAtom
()
{
return
(
4
);
}
/** Any multiple of 4 will do, 72 might be common */
protected
int
bytesPerLine
()
{
return
(
72
);
}
/**
74 * This character array provides the character to value map
75 * based on RFC1521.
76 */
private
final
static
char
pem_array
[]
=
{
// 0 1 2 3 4 5 6 7
'A'
,
'B'
,
'C'
,
'D'
,
'E'
,
'F'
,
'G'
,
'H'
,
// 0
'I'
,
'J'
,
'K'
,
'L'
,
'M'
,
'N'
,
'O'
,
'P'
,
// 1
'Q'
,
'R'
,
'S'
,
'T'
,
'U'
,
'V'
,
'W'
,
'X'
,
// 2
'Y'
,
'Z'
,
'a'
,
'b'
,
'c'
,
'd'
,
'e'
,
'f'
,
// 3
'g'
,
'h'
,
'i'
,
'j'
,
'k'
,
'l'
,
'm'
,
'n'
,
// 4
'o'
,
'p'
,
'q'
,
'r'
,
's'
,
't'
,
'u'
,
'v'
,
// 5
'w'
,
'x'
,
'y'
,
'z'
,
'0'
,
'1'
,
'2'
,
'3'
,
// 6
'4'
,
'5'
,
'6'
,
'7'
,
'8'
,
'9'
,
'+'
,
'/'
// 7
};
private
final
static
byte
pem_convert_array
[]
=
new
byte
[
256
];
static
{
for
(
int
i
=
0
;
i
<
255
;
i
++)
{
pem_convert_array
[
i
]
=
-
1
;
}
for
(
int
i
=
0
;
i
<
pem_array
.
length
;
i
++)
{
pem_convert_array
[
pem_array
[
i
]]
=
(
byte
)
i
;
}
}
byte
decode_buffer
[]
=
new
byte
[
4
];
/**
103 * Decode one BASE64 atom into 1, 2, or 3 bytes of data.
104 */
protected
void
decodeAtom
(
PushbackInputStream
inStream
,
OutputStream
outStream
,
int
rem
)
throws
java
.
io
.
IOException
{
int
i
;
byte
a
=
-
1
,
b
=
-
1
,
c
=
-
1
,
d
=
-
1
;
if
(
rem
<
2
)
{
throw
new
CEFormatException
(
"BASE64Decoder: Not enough bytes for an atom."
);
}
do
{
i
=
inStream
.
read
();
if
(
i
==
-
1
)
{
throw
new
CEStreamExhausted
();
}
}
while
(
i
==
'\n'
||
i
==
'\r'
);
decode_buffer
[
0
]
=
(
byte
)
i
;
i
=
readFully
(
inStream
,
decode_buffer
,
1
,
rem
-
1
);
if
(
i
==
-
1
)
{
throw
new
CEStreamExhausted
();
}
if
(
rem
>
3
&&
decode_buffer
[
3
]
==
'='
)
{
rem
=
3
;
}
if
(
rem
>
2
&&
decode_buffer
[
2
]
==
'='
)
{
rem
=
2
;
}
switch
(
rem
)
{
case
4
:
d
=
pem_convert_array
[
decode_buffer
[
3
]
&
0xff
];
// NOBREAK
case
3
:
c
=
pem_convert_array
[
decode_buffer
[
2
]
&
0xff
];
// NOBREAK
case
2
:
b
=
pem_convert_array
[
decode_buffer
[
1
]
&
0xff
];
a
=
pem_convert_array
[
decode_buffer
[
0
]
&
0xff
];
break
;
}
switch
(
rem
)
{
case
2
:
outStream
.
write
(
(
byte
)(((
a
<<
2
)
&
0xfc
)
|
((
b
>>>
4
)
&
3
))
);
break
;
case
3
:
outStream
.
write
(
(
byte
)
(((
a
<<
2
)
&
0xfc
)
|
((
b
>>>
4
)
&
3
))
);
outStream
.
write
(
(
byte
)
(((
b
<<
4
)
&
0xf0
)
|
((
c
>>>
2
)
&
0xf
))
);
break
;
case
4
:
outStream
.
write
(
(
byte
)
(((
a
<<
2
)
&
0xfc
)
|
((
b
>>>
4
)
&
3
))
);
outStream
.
write
(
(
byte
)
(((
b
<<
4
)
&
0xf0
)
|
((
c
>>>
2
)
&
0xf
))
);
outStream
.
write
(
(
byte
)
(((
c
<<
6
)
&
0xc0
)
|
(
d
&
0x3f
))
);
break
;
}
return
;
}
}
\ No newline at end of file
public-base/src/main/java/com/joe/base/utils/encryption/BASE64Encoder.java
0 → 100644
View file @
189f3098
/*
2 * Copyright (c) 1995, 1997, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
package
com
.
joe
.
base
.
utils
.
encryption
;
import
java.io.IOException
;
import
java.io.OutputStream
;
import
Decoder.CharacterEncoder
;
/**
* This class implements a BASE64 Character encoder as specified in RFC1521.
* This RFC is part of the MIME specification as published by the Internet
* Engineering Task Force (IETF). Unlike some other encoding schemes there is
* nothing in this encoding that indicates where a buffer starts or ends.
*
* This means that the encoded text will simply start with the first line of
* encoded text and end with the last line of encoded text.
*
* @author Chuck McManis
* @see CharacterEncoder
* @see BASE64Decoder
*/
public
class
BASE64Encoder
extends
CharacterEncoder
{
/** this class encodes three bytes per atom. */
protected
int
bytesPerAtom
()
{
return
(
3
);
}
/**
* this class encodes 57 bytes per line. This results in a maximum of 57/3 *
* 4 or 76 characters per output line. Not counting the line termination.
*/
protected
int
bytesPerLine
()
{
return
(
57
);
}
/** This array maps the characters to their 6 bit values */
private
final
static
char
pem_array
[]
=
{
// 0 1 2 3 4 5 6 7
'A'
,
'B'
,
'C'
,
'D'
,
'E'
,
'F'
,
'G'
,
'H'
,
// 0
'I'
,
'J'
,
'K'
,
'L'
,
'M'
,
'N'
,
'O'
,
'P'
,
// 1
'Q'
,
'R'
,
'S'
,
'T'
,
'U'
,
'V'
,
'W'
,
'X'
,
// 2
'Y'
,
'Z'
,
'a'
,
'b'
,
'c'
,
'd'
,
'e'
,
'f'
,
// 3
'g'
,
'h'
,
'i'
,
'j'
,
'k'
,
'l'
,
'm'
,
'n'
,
// 4
'o'
,
'p'
,
'q'
,
'r'
,
's'
,
't'
,
'u'
,
'v'
,
// 5
'w'
,
'x'
,
'y'
,
'z'
,
'0'
,
'1'
,
'2'
,
'3'
,
// 6
'4'
,
'5'
,
'6'
,
'7'
,
'8'
,
'9'
,
'+'
,
'/'
// 7
};
/**
* encodeAtom - Take three bytes of input and encode it as 4 printable
* characters. Note that if the length in len is less than three is encodes
* either one or two '=' signs to indicate padding characters.
*/
protected
void
encodeAtom
(
OutputStream
outStream
,
byte
data
[],
int
offset
,
int
len
)
throws
IOException
{
byte
a
,
b
,
c
;
if
(
len
==
1
)
{
a
=
data
[
offset
];
b
=
0
;
c
=
0
;
outStream
.
write
(
pem_array
[(
a
>>>
2
)
&
0x3F
]);
outStream
.
write
(
pem_array
[((
a
<<
4
)
&
0x30
)
+
((
b
>>>
4
)
&
0xf
)]);
outStream
.
write
(
'='
);
outStream
.
write
(
'='
);
}
else
if
(
len
==
2
)
{
a
=
data
[
offset
];
b
=
data
[
offset
+
1
];
c
=
0
;
outStream
.
write
(
pem_array
[(
a
>>>
2
)
&
0x3F
]);
outStream
.
write
(
pem_array
[((
a
<<
4
)
&
0x30
)
+
((
b
>>>
4
)
&
0xf
)]);
outStream
.
write
(
pem_array
[((
b
<<
2
)
&
0x3c
)
+
((
c
>>>
6
)
&
0x3
)]);
outStream
.
write
(
'='
);
}
else
{
a
=
data
[
offset
];
b
=
data
[
offset
+
1
];
c
=
data
[
offset
+
2
];
outStream
.
write
(
pem_array
[(
a
>>>
2
)
&
0x3F
]);
outStream
.
write
(
pem_array
[((
a
<<
4
)
&
0x30
)
+
((
b
>>>
4
)
&
0xf
)]);
outStream
.
write
(
pem_array
[((
b
<<
2
)
&
0x3c
)
+
((
c
>>>
6
)
&
0x3
)]);
outStream
.
write
(
pem_array
[
c
&
0x3F
]);
}
}
}
\ No newline at end of file
public-base/src/main/java/com/joe/base/widget/view/MyEditText.java
View file @
189f3098
...
@@ -67,8 +67,11 @@ public class MyEditText extends RelativeLayout {
...
@@ -67,8 +67,11 @@ public class MyEditText extends RelativeLayout {
//清除按鈕點擊事件
//清除按鈕點擊事件
private
OnClickListener
clearOnClickListener
;
private
OnClickListener
clearOnClickListener
;
//查看密碼按鈕圖標
//查看密碼按鈕圖標兩種狀態
private
Drawable
lookIcon
;
private
Drawable
lookIconUncheck
;
private
Drawable
lookIconChecked
;
//"查看密碼"圖標的大小
//"查看密碼"圖標的大小
private
int
lookIconSiZe
;
private
int
lookIconSiZe
;
//查看密碼按鈕右間距
//查看密碼按鈕右間距
...
@@ -126,7 +129,8 @@ public class MyEditText extends RelativeLayout {
...
@@ -126,7 +129,8 @@ public class MyEditText extends RelativeLayout {
clearIconSiZe
=
typedArray
.
getDimensionPixelSize
(
R
.
styleable
.
MyEditText_ed_clearIconSize
,
0
);
clearIconSiZe
=
typedArray
.
getDimensionPixelSize
(
R
.
styleable
.
MyEditText_ed_clearIconSize
,
0
);
clearIcon
=
typedArray
.
getDrawable
(
R
.
styleable
.
MyEditText_ed_clearRes
);
clearIcon
=
typedArray
.
getDrawable
(
R
.
styleable
.
MyEditText_ed_clearRes
);
clearRightMargin
=
ConvertDpAndPx
.
Px2Dp
(
context
,
typedArray
.
getDimensionPixelSize
(
R
.
styleable
.
MyEditText_ed_clearMarginRight
,
0
));
clearRightMargin
=
ConvertDpAndPx
.
Px2Dp
(
context
,
typedArray
.
getDimensionPixelSize
(
R
.
styleable
.
MyEditText_ed_clearMarginRight
,
0
));
lookIcon
=
typedArray
.
getDrawable
(
R
.
styleable
.
MyEditText_ed_lookIcon
);
lookIconUncheck
=
typedArray
.
getDrawable
(
R
.
styleable
.
MyEditText_ed_lookIcon_uncheck
);
lookIconChecked
=
typedArray
.
getDrawable
(
R
.
styleable
.
MyEditText_ed_lookIcon_checked
);
lookIconSiZe
=
ConvertDpAndPx
.
Px2Dp
(
context
,
typedArray
.
getDimensionPixelSize
(
R
.
styleable
.
MyEditText_ed_lookIconSize
,
0
));
lookIconSiZe
=
ConvertDpAndPx
.
Px2Dp
(
context
,
typedArray
.
getDimensionPixelSize
(
R
.
styleable
.
MyEditText_ed_lookIconSize
,
0
));
lookRightMargin
=
ConvertDpAndPx
.
Px2Dp
(
context
,
typedArray
.
getDimensionPixelSize
(
R
.
styleable
.
MyEditText_ed_lookMarginRight
,
0
));
lookRightMargin
=
ConvertDpAndPx
.
Px2Dp
(
context
,
typedArray
.
getDimensionPixelSize
(
R
.
styleable
.
MyEditText_ed_lookMarginRight
,
0
));
pwdChar
=
typedArray
.
getString
(
R
.
styleable
.
MyEditText_ed_pwdChar
);
pwdChar
=
typedArray
.
getString
(
R
.
styleable
.
MyEditText_ed_pwdChar
);
...
@@ -179,7 +183,7 @@ public class MyEditText extends RelativeLayout {
...
@@ -179,7 +183,7 @@ public class MyEditText extends RelativeLayout {
passwordTransformationMethod
=
new
AsteriskPasswordTransformationMethod
();
passwordTransformationMethod
=
new
AsteriskPasswordTransformationMethod
();
editText
.
setTransformationMethod
(
passwordTransformationMethod
);
//必須在setsingleLine之後才有效
editText
.
setTransformationMethod
(
passwordTransformationMethod
);
//必須在setsingleLine之後才有效
}
}
if
(
inputType
!=
0
)
{
if
(
inputType
!=
0
)
{
editText
.
setInputType
(
inputType
);
editText
.
setInputType
(
inputType
);
}
}
...
@@ -211,9 +215,15 @@ public class MyEditText extends RelativeLayout {
...
@@ -211,9 +215,15 @@ public class MyEditText extends RelativeLayout {
@Override
@Override
public
void
afterTextChanged
(
Editable
editable
)
{
public
void
afterTextChanged
(
Editable
editable
)
{
setMaxLengthText
(
editable
.
toString
().
length
());
setMaxLengthText
(
editable
.
toString
().
length
());
if
(
ivClear
!=
null
)
{
if
(
editable
.
toString
().
length
()
>
0
)
{
ivClear
.
setVisibility
(
VISIBLE
);
}
else
{
ivClear
.
setVisibility
(
GONE
);
}
}
}
}
});
});
this
.
addView
(
editText
);
this
.
addView
(
editText
);
}
}
...
@@ -221,7 +231,7 @@ public class MyEditText extends RelativeLayout {
...
@@ -221,7 +231,7 @@ public class MyEditText extends RelativeLayout {
* 初始化查看密碼按鈕
* 初始化查看密碼按鈕
*/
*/
private
void
initLookIcon
()
{
private
void
initLookIcon
()
{
if
(
lookIcon
!=
null
)
{
if
(
lookIcon
Uncheck
!=
null
)
{
ivLook
=
new
CheckBox
(
context
);
ivLook
=
new
CheckBox
(
context
);
LayoutParams
ivLookParams
=
getImgLayoutParams
(
lookIconSiZe
,
lookIconSiZe
,
lookRightMargin
);
LayoutParams
ivLookParams
=
getImgLayoutParams
(
lookIconSiZe
,
lookIconSiZe
,
lookRightMargin
);
ivLook
.
setButtonDrawable
(
null
);
ivLook
.
setButtonDrawable
(
null
);
...
@@ -232,24 +242,25 @@ public class MyEditText extends RelativeLayout {
...
@@ -232,24 +242,25 @@ public class MyEditText extends RelativeLayout {
}
}
ivLook
.
setLayoutParams
(
ivLookParams
);
ivLook
.
setLayoutParams
(
ivLookParams
);
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
JELLY_BEAN
)
{
ivLook
.
setBackground
(
lookIconUncheck
);
ivLook
.
setBackground
(
lookIcon
);
}
this
.
addView
(
ivLook
);
this
.
addView
(
ivLook
);
ivLook
.
setOnCheckedChangeListener
(
new
CompoundButton
.
OnCheckedChangeListener
()
{
ivLook
.
setOnCheckedChangeListener
((
buttonView
,
isChecked
)
->
{
@Override
public
void
onCheckedChanged
(
CompoundButton
buttonView
,
boolean
isChecked
)
{
if
(
isChecked
)
{
if
(
isChecked
)
{
ivLook
.
setBackground
(
lookIconChecked
);
editText
.
setTransformationMethod
(
HideReturnsTransformationMethod
.
getInstance
());
editText
.
setTransformationMethod
(
HideReturnsTransformationMethod
.
getInstance
());
}
else
{
}
else
{
ivLook
.
setBackground
(
lookIconUncheck
);
if
(
passwordTransformationMethod
==
null
)
{
editText
.
setTransformationMethod
(
new
PasswordTransformationMethod
());
}
else
{
editText
.
setTransformationMethod
(
passwordTransformationMethod
);
//讓密碼顯示為*
editText
.
setTransformationMethod
(
passwordTransformationMethod
);
//讓密碼顯示為*
}
}
}
editText
.
setSelection
(
editText
.
getText
().
toString
().
length
());
editText
.
setSelection
(
editText
.
getText
().
toString
().
length
());
if
(
lookOnClickListener
!=
null
)
{
if
(
lookOnClickListener
!=
null
)
{
lookOnClickListener
.
onClick
(
buttonView
);
lookOnClickListener
.
onClick
(
buttonView
);
}
}
}
});
});
}
}
}
}
...
@@ -263,6 +274,8 @@ public class MyEditText extends RelativeLayout {
...
@@ -263,6 +274,8 @@ public class MyEditText extends RelativeLayout {
ivClear
.
setImageDrawable
(
clearIcon
);
ivClear
.
setImageDrawable
(
clearIcon
);
ivClear
.
setLayoutParams
(
getImgLayoutParams
(
clearIconSiZe
,
clearIconSiZe
,
clearRightMargin
));
ivClear
.
setLayoutParams
(
getImgLayoutParams
(
clearIconSiZe
,
clearIconSiZe
,
clearRightMargin
));
this
.
addView
(
ivClear
);
this
.
addView
(
ivClear
);
//有了內容才顯示清除按鈕
ivClear
.
setVisibility
(
GONE
);
ivClear
.
setOnClickListener
(
view
->
{
ivClear
.
setOnClickListener
(
view
->
{
editText
.
setText
(
""
);
editText
.
setText
(
""
);
if
(
clearOnClickListener
!=
null
)
{
if
(
clearOnClickListener
!=
null
)
{
...
...
public-base/src/main/res/values/styles.xml
View file @
189f3098
...
@@ -57,7 +57,10 @@
...
@@ -57,7 +57,10 @@
<!-- 清除按鈕右間距-->
<!-- 清除按鈕右間距-->
<attr
name=
"ed_clearMarginRight"
format=
"dimension"
/>
<attr
name=
"ed_clearMarginRight"
format=
"dimension"
/>
<!-- 查看密碼按鈕資源文件-->
<!-- 查看密碼按鈕資源文件-->
<attr
name=
"ed_lookIcon"
format=
"reference"
/>
<attr
name=
"ed_lookIcon_uncheck"
format=
"reference"
/>
<!-- 查看密碼按鈕資源文件-->
<attr
name=
"ed_lookIcon_checked"
format=
"reference"
/>
<!-- 查看密碼按鈕右間距-->
<!-- 查看密碼按鈕右間距-->
<attr
name=
"ed_lookMarginRight"
format=
"dimension"
/>
<attr
name=
"ed_lookMarginRight"
format=
"dimension"
/>
<attr
name=
"ed_lookIconSize"
format=
"dimension"
/>
<attr
name=
"ed_lookIconSize"
format=
"dimension"
/>
...
...
user-login/build.gradle
View file @
189f3098
...
@@ -46,4 +46,5 @@ dependencies {
...
@@ -46,4 +46,5 @@ dependencies {
// annotationProcessor rootProject.ext.dependencies["butterknife-compiler"] //Butterknife 插件, 很多人因为没加这个而报错, 切记!!!
// annotationProcessor rootProject.ext.dependencies["butterknife-compiler"] //Butterknife 插件, 很多人因为没加这个而报错, 切记!!!
annotationProcessor
rootProject
.
ext
.
dependencies
[
"dagger2-compiler"
]
//依赖插件
annotationProcessor
rootProject
.
ext
.
dependencies
[
"dagger2-compiler"
]
//依赖插件
implementation
rootProject
.
ext
.
dependencies
[
"autosize"
]
implementation
rootProject
.
ext
.
dependencies
[
"autosize"
]
implementation
rootProject
.
ext
.
dependencies
[
"fastjson"
]
}
}
user-login/src/main/AndroidManifest.xml
View file @
189f3098
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
package=
"com.gingersoft.gsa.cloud.user.login"
>
package=
"com.gingersoft.gsa.cloud.user.login"
>
<uses-permission
android:name=
"android.permission.RECEIVE_USER_PRESENT"
/>
<uses-permission
android:name=
"android.permission.INTERNET"
/>
<uses-permission
android:name=
"android.permission.WAKE_LOCK"
/>
<uses-permission
android:name=
"android.permission.READ_PHONE_STATE"
/>
<uses-permission
android:name=
"android.permission.WRITE_EXTERNAL_STORAGE"
/>
<uses-permission
android:name=
"android.permission.READ_EXTERNAL_STORAGE"
/>
<application>
<application>
<activity
android:name=
".mvp.ui.activity.LoginActivity"
/>
<activity
android:name=
".mvp.ui.activity.LoginActivity"
/>
...
...
user-login/src/main/debug/AndroidManifest.xml
View file @
189f3098
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
package=
"com.gingersoft.gsa.cloud.user.login"
>
package=
"com.gingersoft.gsa.cloud.user.login"
>
<uses-permission
android:name=
"android.permission.RECEIVE_USER_PRESENT"
/>
<uses-permission
android:name=
"android.permission.INTERNET"
/>
<uses-permission
android:name=
"android.permission.WAKE_LOCK"
/>
<uses-permission
android:name=
"android.permission.READ_PHONE_STATE"
/>
<uses-permission
android:name=
"android.permission.WRITE_EXTERNAL_STORAGE"
/>
<uses-permission
android:name=
"android.permission.READ_EXTERNAL_STORAGE"
/>
<application
<application
android:allowBackup=
"true"
android:allowBackup=
"true"
android:icon=
"@mipmap/ic_launcher"
android:icon=
"@mipmap/ic_launcher"
...
@@ -16,6 +23,8 @@
...
@@ -16,6 +23,8 @@
</intent-filter>
</intent-filter>
</activity>
</activity>
<activity
android:name=
".mvp.ui.activity.LoginOutActivity"
/>
<meta-data
<meta-data
android:name=
"design_width_in_dp"
android:name=
"design_width_in_dp"
android:value=
"360"
/>
android:value=
"360"
/>
...
...
user-login/src/main/java/com/gingersoft/gsa/cloud/user/login/mvp/bean/TestLoginBean.java
View file @
189f3098
...
@@ -81,48 +81,48 @@ public class TestLoginBean {
...
@@ -81,48 +81,48 @@ public class TestLoginBean {
* updateBy : nisi sed ut esse ex
* updateBy : nisi sed ut esse ex
*/
*/
private
double
id
;
private
int
id
;
private
double
groupId
;
private
int
groupId
;
private
double
parentId
;
private
int
parentId
;
private
double
merchantsId
;
private
int
merchantsId
;
private
String
userName
;
private
String
userName
;
private
String
mobile
;
private
String
mobile
;
private
String
email
;
private
String
email
;
private
double
status
;
private
int
status
;
private
String
createTime
;
private
String
createTime
;
private
String
createBy
;
private
String
createBy
;
private
String
updateTime
;
private
String
updateTime
;
private
String
updateBy
;
private
String
updateBy
;
public
double
getId
()
{
public
int
getId
()
{
return
id
;
return
id
;
}
}
public
void
setId
(
double
id
)
{
public
void
setId
(
int
id
)
{
this
.
id
=
id
;
this
.
id
=
id
;
}
}
public
double
getGroupId
()
{
public
int
getGroupId
()
{
return
groupId
;
return
groupId
;
}
}
public
void
setGroupId
(
double
groupId
)
{
public
void
setGroupId
(
int
groupId
)
{
this
.
groupId
=
groupId
;
this
.
groupId
=
groupId
;
}
}
public
double
getParentId
()
{
public
int
getParentId
()
{
return
parentId
;
return
parentId
;
}
}
public
void
setParentId
(
double
parentId
)
{
public
void
setParentId
(
int
parentId
)
{
this
.
parentId
=
parentId
;
this
.
parentId
=
parentId
;
}
}
public
double
getMerchantsId
()
{
public
int
getMerchantsId
()
{
return
merchantsId
;
return
merchantsId
;
}
}
public
void
setMerchantsId
(
double
merchantsId
)
{
public
void
setMerchantsId
(
int
merchantsId
)
{
this
.
merchantsId
=
merchantsId
;
this
.
merchantsId
=
merchantsId
;
}
}
...
@@ -150,11 +150,11 @@ public class TestLoginBean {
...
@@ -150,11 +150,11 @@ public class TestLoginBean {
this
.
email
=
email
;
this
.
email
=
email
;
}
}
public
double
getStatus
()
{
public
int
getStatus
()
{
return
status
;
return
status
;
}
}
public
void
setStatus
(
double
status
)
{
public
void
setStatus
(
int
status
)
{
this
.
status
=
status
;
this
.
status
=
status
;
}
}
...
...
user-login/src/main/java/com/gingersoft/gsa/cloud/user/login/mvp/ui/activity/LoginActivity.java
View file @
189f3098
...
@@ -2,10 +2,12 @@ package com.gingersoft.gsa.cloud.user.login.mvp.ui.activity;
...
@@ -2,10 +2,12 @@ package com.gingersoft.gsa.cloud.user.login.mvp.ui.activity;
import
android.content.Intent
;
import
android.content.Intent
;
import
android.os.Bundle
;
import
android.os.Bundle
;
import
android.util.Log
;
import
android.view.View
;
import
android.view.View
;
import
android.widget.EditText
;
import
android.widget.EditText
;
import
android.widget.TextView
;
import
android.widget.TextView
;
import
com.alibaba.fastjson.JSON
;
import
com.gingersoft.gsa.cloud.user.login.R
;
import
com.gingersoft.gsa.cloud.user.login.R
;
import
com.gingersoft.gsa.cloud.user.login.di.component.DaggerLoginComponent
;
import
com.gingersoft.gsa.cloud.user.login.di.component.DaggerLoginComponent
;
import
com.gingersoft.gsa.cloud.user.login.mvp.bean.TestLoginBean
;
import
com.gingersoft.gsa.cloud.user.login.mvp.bean.TestLoginBean
;
...
@@ -15,14 +17,25 @@ import com.jess.arms.utils.ArmsUtils;
...
@@ -15,14 +17,25 @@ import com.jess.arms.utils.ArmsUtils;
import
com.gingersoft.gsa.cloud.user.login.mvp.contract.LoginContract
;
import
com.gingersoft.gsa.cloud.user.login.mvp.contract.LoginContract
;
import
com.gingersoft.gsa.cloud.user.login.mvp.presenter.LoginPresenter
;
import
com.gingersoft.gsa.cloud.user.login.mvp.presenter.LoginPresenter
;
import
com.joe.base.utils.toast.ToastUtils
;
import
com.joe.base.widget.view.MyEditText
;
import
com.joe.base.widget.view.MyEditText
;
import
java.io.IOException
;
import
androidx.annotation.NonNull
;
import
androidx.annotation.NonNull
;
import
androidx.annotation.Nullable
;
import
androidx.annotation.Nullable
;
import
butterknife.BindView
;
import
butterknife.BindView
;
import
butterknife.ButterKnife
;
import
butterknife.ButterKnife
;
import
butterknife.OnClick
;
import
butterknife.OnClick
;
import
okhttp3.Call
;
import
okhttp3.Callback
;
import
okhttp3.FormBody
;
import
okhttp3.Headers
;
import
okhttp3.OkHttpClient
;
import
okhttp3.Request
;
import
okhttp3.RequestBody
;
import
okhttp3.Response
;
import
static
com
.
jess
.
arms
.
utils
.
Preconditions
.
checkNotNull
;
import
static
com
.
jess
.
arms
.
utils
.
Preconditions
.
checkNotNull
;
...
@@ -109,9 +122,49 @@ public class LoginActivity extends BaseActivity<LoginPresenter> implements Login
...
@@ -109,9 +122,49 @@ public class LoginActivity extends BaseActivity<LoginPresenter> implements Login
case
R
.
id
.
tv_gsa_user_login
:
case
R
.
id
.
tv_gsa_user_login
:
//登陸
//登陸
if
(
edAccount
.
getText
()
!=
null
&&
edPwd
.
getText
()
!=
null
)
{
if
(
edAccount
.
getText
()
!=
null
&&
edPwd
.
getText
()
!=
null
)
{
mPresenter
.
login
(
edAccount
.
getText
().
toString
(),
edPwd
.
getText
().
toString
());
// mPresenter.login(edAccount.getText().toString(), edPwd.getText().toString());
login
();
}
}
break
;
break
;
}
}
}
}
private
TestLoginBean
loginBean
;
public
void
login
()
{
OkHttpClient
okHttpClient
=
new
OkHttpClient
();
RequestBody
requestBody
=
new
FormBody
.
Builder
()
.
add
(
"userName"
,
edAccount
.
getText
().
toString
())
.
add
(
"passWord"
,
edPwd
.
getText
().
toString
())
.
build
();
Request
request
=
new
Request
.
Builder
()
.
addHeader
(
"apptype"
,
"9"
)
.
addHeader
(
"mobileId"
,
"1"
)
.
addHeader
(
"mobielModel"
,
""
)
.
addHeader
(
"mobileVersion"
,
""
)
.
url
(
"http://gingersoft.tpddns.cn:58201/ricepon-cloud-gsa/api/gsa/login"
)
.
post
(
requestBody
)
.
build
();
Log
.
e
(
"aaa"
,
"登錄"
);
okHttpClient
.
newCall
(
request
).
enqueue
(
new
Callback
()
{
@Override
public
void
onFailure
(
Call
call
,
IOException
e
)
{
Log
.
e
(
"aaa"
,
"onFailure: "
+
e
.
getMessage
());
}
@Override
public
void
onResponse
(
Call
call
,
Response
response
)
throws
IOException
{
String
json
=
response
.
body
().
string
();
Log
.
e
(
"aaa"
,
"登錄"
+
json
);
ToastUtils
.
show
(
LoginActivity
.
this
,
"登錄成功"
);
Intent
intent
=
new
Intent
(
LoginActivity
.
this
,
LoginOutActivity
.
class
);
intent
.
addFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TOP
);
intent
.
putExtra
(
"json"
,
json
);
startActivity
(
intent
);
}
});
}
}
}
user-login/src/main/java/com/gingersoft/gsa/cloud/user/login/mvp/ui/activity/LoginOutActivity.java
0 → 100644
View file @
189f3098
package
com
.
gingersoft
.
gsa
.
cloud
.
user
.
login
.
mvp
.
ui
.
activity
;
import
android.app.Activity
;
import
android.content.Intent
;
import
android.os.Bundle
;
import
android.util.Log
;
import
android.widget.TextView
;
import
com.alibaba.fastjson.JSON
;
import
com.gingersoft.gsa.cloud.user.login.R
;
import
com.gingersoft.gsa.cloud.user.login.mvp.bean.TestLoginBean
;
import
com.joe.base.utils.encryption.Aes
;
import
com.joe.base.utils.toast.ToastUtils
;
import
java.io.IOException
;
import
androidx.annotation.Nullable
;
import
okhttp3.Call
;
import
okhttp3.Callback
;
import
okhttp3.FormBody
;
import
okhttp3.OkHttpClient
;
import
okhttp3.Request
;
import
okhttp3.RequestBody
;
import
okhttp3.Response
;
/**
* Created by Wyh on 2019/12/25.
*/
public
class
LoginOutActivity
extends
Activity
{
private
TestLoginBean
loginBean
;
@Override
protected
void
onCreate
(
@Nullable
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
setContentView
(
R
.
layout
.
user_login_activity_login_out
);
TextView
tv_json
=
findViewById
(
R
.
id
.
tv_json
);
String
json
=
getIntent
().
getStringExtra
(
"json"
);
loginBean
=
JSON
.
parseObject
(
json
,
TestLoginBean
.
class
);
tv_json
.
setText
(
json
);
findViewById
(
R
.
id
.
tv_gsa_user_loginout
).
setOnClickListener
(
v
->
{
OkHttpClient
okHttpClient
=
new
OkHttpClient
();
RequestBody
requestBody
=
new
FormBody
.
Builder
()
.
build
();
Log
.
e
(
"aaa"
,
"加密前:"
+
loginBean
.
getData
().
getUser
().
getId
()
+
"_"
+
System
.
currentTimeMillis
()
+
"_"
+
loginBean
.
getData
().
getToken
());
// 加密token apptype_id_time_token
// app類型_用戶id_時間戳_登陸token
String
head
=
Aes
.
aesEncrypt
(
"9_"
+
loginBean
.
getData
().
getUser
().
getId
()
+
"_"
+
System
.
currentTimeMillis
()
+
"_"
+
loginBean
.
getData
().
getToken
()).
replaceAll
(
"\r|\n"
,
""
);
Log
.
e
(
"aaa"
,
"加密頭部:"
+
head
);
Request
request
=
new
Request
.
Builder
()
.
addHeader
(
"mobileId"
,
"1"
)
.
addHeader
(
"mobielModel"
,
""
)
.
addHeader
(
"mobileVersion"
,
""
)
.
addHeader
(
"token"
,
head
)
.
url
(
"http://gingersoft.tpddns.cn:58201/ricepon-cloud-gsa/api/gsa/logout"
)
.
post
(
requestBody
)
.
build
();
okHttpClient
.
newCall
(
request
).
enqueue
(
new
Callback
()
{
@Override
public
void
onFailure
(
Call
call
,
IOException
e
)
{
Log
.
e
(
"aaa"
,
"onFailure: "
+
e
.
getMessage
());
}
@Override
public
void
onResponse
(
Call
call
,
Response
response
)
throws
IOException
{
String
json
=
response
.
body
().
string
();
Log
.
e
(
"aaa"
,
"退出登錄:"
+
json
);
ToastUtils
.
show
(
LoginOutActivity
.
this
,
"登出"
);
Intent
intent
=
new
Intent
(
LoginOutActivity
.
this
,
LoginActivity
.
class
);
intent
.
addFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TOP
);
startActivity
(
intent
);
}
});
});
}
}
user-login/src/main/res/layout/user_login_activity_login.xml
View file @
189f3098
...
@@ -31,7 +31,6 @@
...
@@ -31,7 +31,6 @@
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@id/login_title"
/>
app:layout_constraintTop_toBottomOf=
"@id/login_title"
/>
<com.joe.base.widget.view.MyEditText
<com.joe.base.widget.view.MyEditText
android:id=
"@+id/ed_login_user_account"
android:id=
"@+id/ed_login_user_account"
android:layout_width=
"0dp"
android:layout_width=
"0dp"
...
@@ -44,7 +43,6 @@
...
@@ -44,7 +43,6 @@
app:ed_hintColor=
"@color/user_login_edit_color"
app:ed_hintColor=
"@color/user_login_edit_color"
app:ed_isInputIcon=
"false"
app:ed_isInputIcon=
"false"
app:ed_singLeLine=
"true"
app:ed_singLeLine=
"true"
app:ed_text=
"admin"
app:ed_textColor=
"#333"
app:ed_textColor=
"#333"
app:ed_textSize=
"@dimen/edit_text_size"
app:ed_textSize=
"@dimen/edit_text_size"
app:layout_constraintBottom_toBottomOf=
"@id/login_icon"
app:layout_constraintBottom_toBottomOf=
"@id/login_icon"
...
@@ -77,7 +75,6 @@
...
@@ -77,7 +75,6 @@
app:ed_hintColor=
"@color/user_login_edit_color"
app:ed_hintColor=
"@color/user_login_edit_color"
app:ed_isInputIcon=
"false"
app:ed_isInputIcon=
"false"
app:ed_singLeLine=
"true"
app:ed_singLeLine=
"true"
app:ed_text=
"123456"
app:ed_textColor=
"#333"
app:ed_textColor=
"#333"
app:ed_textSize=
"@dimen/edit_text_size"
app:ed_textSize=
"@dimen/edit_text_size"
app:inputType=
"numberPassword"
app:inputType=
"numberPassword"
...
@@ -102,14 +99,26 @@
...
@@ -102,14 +99,26 @@
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginLeft=
"10dp"
android:layout_marginLeft=
"10dp"
android:layout_marginTop=
"
1
0dp"
android:layout_marginTop=
"
2
0dp"
android:layout_marginRight=
"10dp"
android:layout_marginRight=
"10dp"
android:background=
"#AE2E45"
android:background=
"#AE2E45"
android:gravity=
"center"
android:gravity=
"center"
android:padding=
"10dp"
android:padding=
"10dp"
android:text=
"登
陸
"
android:text=
"登
錄
"
android:textColor=
"#fff"
android:textColor=
"#fff"
android:textSize=
"16dp"
android:textSize=
"16dp"
app:layout_constraintTop_toBottomOf=
"@id/tv_forget_pwd"
/>
app:layout_constraintTop_toBottomOf=
"@id/tv_forget_pwd"
/>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"v1.0"
android:textSize=
"16dp"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
app:layout_constraintVertical_bias=
"0.95"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
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