mirror of
https://gitee.com/beecue/fastbee.git
synced 2025-12-18 08:55:53 +08:00
Compare commits
898 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8216db72b4 | ||
|
|
8501632079 | ||
|
|
1a3c6fd460 | ||
|
|
2cf44dc4ef | ||
|
|
7b361e6eae | ||
|
|
07392576f3 | ||
|
|
79d2a82e2d | ||
|
|
d357a68e35 | ||
|
|
ce0abdfbb1 | ||
|
|
bc93c2d2eb | ||
|
|
5f33234e8b | ||
|
|
73f66f8d78 | ||
|
|
3c7a64327d | ||
|
|
fa25f771a2 | ||
|
|
3e4d271be8 | ||
|
|
63d2258911 | ||
|
|
f48e7a1579 | ||
|
|
44f3182ec3 | ||
|
|
0306e5c6cb | ||
|
|
4dc62fdecd | ||
|
|
61a9c0a846 | ||
|
|
b3cb59e151 | ||
|
|
9dad5ec04c | ||
|
|
6cf181ee8d | ||
|
|
d7b5ce1c16 | ||
|
|
c5a9d0d567 | ||
|
|
f5af688500 | ||
|
|
908c4e58a7 | ||
|
|
1e7bd72bfa | ||
|
|
5058e2edc7 | ||
|
|
d56c600643 | ||
|
|
c5ddae9565 | ||
|
|
edf2dc0b88 | ||
|
|
21f0a90a2d | ||
|
|
fe28413ab2 | ||
|
|
25bcaae210 | ||
|
|
a082c61f6b | ||
|
|
2ad5d6ff28 | ||
|
|
7f58d3e12b | ||
|
|
7079610ee4 | ||
|
|
5bb2794e8c | ||
|
|
4ec2f3eeaa | ||
|
|
bc5b492d26 | ||
|
|
a3625cd254 | ||
|
|
3500faf044 | ||
|
|
5b6ec185c4 | ||
|
|
f545198645 | ||
|
|
32cc5e794e | ||
|
|
461ab2a37e | ||
|
|
44bd079c06 | ||
|
|
70f466e471 | ||
|
|
8d60474904 | ||
|
|
2df210fe6b | ||
|
|
00f5c882e2 | ||
|
|
25239c32cb | ||
|
|
bfd2977ff4 | ||
|
|
8c9031acef | ||
|
|
f5598f1663 | ||
|
|
d681d4b22b | ||
|
|
0215feb4b0 | ||
|
|
905e36243c | ||
|
|
201bbfeefb | ||
|
|
39aba490c6 | ||
|
|
54f2487330 | ||
|
|
ff51ea78af | ||
|
|
e404cd26d4 | ||
|
|
b86acd933b | ||
|
|
5fc141719a | ||
|
|
8939c78e37 | ||
|
|
19fedbe841 | ||
|
|
1805c99f4f | ||
|
|
56577f4262 | ||
|
|
12dc1e869e | ||
|
|
7f5d432f5a | ||
|
|
d979c9025a | ||
|
|
f71cbff3d7 | ||
|
|
645fca0119 | ||
|
|
4065392ccc | ||
|
|
bc8b5796d2 | ||
|
|
18568aa663 | ||
|
|
38e236a8ff | ||
|
|
8099d7bdcc | ||
|
|
a5a88ae379 | ||
|
|
462da2a6ce | ||
|
|
f7e9e403b0 | ||
|
|
2772c49df1 | ||
|
|
1afceda43c | ||
|
|
4920d84516 | ||
|
|
14ad72b6fa | ||
|
|
59f4185d2b | ||
|
|
59c83b1601 | ||
|
|
e8c192dbd4 | ||
|
|
1424423769 | ||
|
|
0615f005b7 | ||
|
|
c2a7aafcd4 | ||
|
|
d8e07328c7 | ||
|
|
5abe95f617 | ||
|
|
c12352ffea | ||
|
|
5715a15d46 | ||
|
|
92b504d78a | ||
|
|
c8a9fd0a99 | ||
|
|
4af4f250eb | ||
|
|
6d50802b60 | ||
|
|
87cb9f2ba1 | ||
|
|
2f481c1b13 | ||
|
|
cfebb8753f | ||
|
|
a7f60c902a | ||
|
|
aab9710423 | ||
|
|
a56ab82a94 | ||
|
|
984a5e6357 | ||
|
|
f48a7e0e4a | ||
|
|
4dbf1f0bee | ||
|
|
f866fd2d9c | ||
|
|
ebad891de7 | ||
|
|
93c73501a2 | ||
|
|
7983f72429 | ||
|
|
642cf21648 | ||
|
|
c869f5ea10 | ||
|
|
90b165775e | ||
|
|
ba47af758f | ||
|
|
9aed2047cb | ||
|
|
90e9409b7a | ||
|
|
6e1cd1eac0 | ||
|
|
2c17dda169 | ||
|
|
940123b78d | ||
|
|
60c0949edf | ||
|
|
6702e3414f | ||
|
|
00084ed066 | ||
|
|
65390f9ca8 | ||
|
|
1c026ab07a | ||
|
|
9ef70c53a5 | ||
|
|
d6d506ff6a | ||
|
|
12e2203abc | ||
|
|
6fa84b7ecb | ||
|
|
34902ae252 | ||
|
|
28fccca86b | ||
|
|
9dcea014cf | ||
|
|
d6cda401fd | ||
|
|
67534a1f16 | ||
|
|
841db27f80 | ||
|
|
c74ea3df6a | ||
|
|
ee78bf6efc | ||
|
|
cbd545f309 | ||
|
|
b2ea3dec75 | ||
|
|
6477eb3340 | ||
|
|
cf80f4e078 | ||
|
|
55a3b95a97 | ||
|
|
653fe8bc1f | ||
|
|
b143c30501 | ||
|
|
386376c6c3 | ||
|
|
2eacd9152a | ||
|
|
58f59e9bcf | ||
|
|
7de646467b | ||
|
|
d222bad4db | ||
|
|
0d0bdc0c6c | ||
|
|
2684250a66 | ||
|
|
98fe700042 | ||
|
|
054e414b48 | ||
|
|
de7e2529a3 | ||
|
|
3135ee0a37 | ||
|
|
043fdbb7c0 | ||
|
|
41a4d50ebf | ||
|
|
273999cad0 | ||
|
|
b463bbc8c9 | ||
|
|
069641c573 | ||
|
|
ded912d330 | ||
|
|
84eead7649 | ||
|
|
3e910456c5 | ||
|
|
771c38f9fe | ||
|
|
800755efda | ||
|
|
5539c1b6af | ||
|
|
3d44f4674c | ||
|
|
488a8a3e59 | ||
|
|
13a5427091 | ||
|
|
110c3180ec | ||
|
|
5657855a9a | ||
|
|
269e3abb77 | ||
|
|
80004c4e18 | ||
|
|
023de2f606 | ||
|
|
19976fbede | ||
|
|
50fb897c7d | ||
|
|
f9925a7455 | ||
|
|
701a2f4300 | ||
|
|
703f5a6673 | ||
|
|
80a1467535 | ||
|
|
e39d3d2f03 | ||
|
|
dcdf6e1b7c | ||
|
|
e88a521639 | ||
|
|
e879c1cbe9 | ||
|
|
280f989c00 | ||
|
|
32e334efb8 | ||
|
|
8dd6e5e343 | ||
|
|
6ae7e1919a | ||
|
|
e8cde958c2 | ||
|
|
ea749d47c8 | ||
|
|
57a210248a | ||
|
|
2c7b8de7c7 | ||
|
|
774d70b75b | ||
|
|
07fbe02ac2 | ||
|
|
30318787ee | ||
|
|
2752bb3647 | ||
|
|
8e64d49b90 | ||
|
|
46596ce594 | ||
|
|
31e491370e | ||
|
|
740c5cdcf0 | ||
|
|
79d955e83c | ||
|
|
a1f2f4f4da | ||
|
|
1e96479113 | ||
|
|
950cf7a7fa | ||
|
|
0923e9b20b | ||
|
|
7bff5bee97 | ||
|
|
107dc8e42b | ||
|
|
46907660ae | ||
|
|
2e74171a0a | ||
|
|
92e239622b | ||
|
|
b40557ab1e | ||
|
|
a56af5e85d | ||
|
|
a58a577460 | ||
|
|
c7d41d8f3e | ||
|
|
573549a3f0 | ||
|
|
87a086542c | ||
|
|
804e75b4ac | ||
|
|
892473542e | ||
|
|
a1f4c0402e | ||
|
|
92182e1855 | ||
|
|
7b36e97ca3 | ||
|
|
62bafb0d8e | ||
|
|
26374e5ad4 | ||
|
|
3ffedaedbf | ||
|
|
e07c826485 | ||
|
|
d682330e32 | ||
|
|
171b95d98d | ||
|
|
b1b3799b3a | ||
|
|
3723a81b6d | ||
|
|
96aefac613 | ||
|
|
b4130a0b81 | ||
|
|
b5ba56b1a8 | ||
|
|
1ed0c285f0 | ||
|
|
f878e6c474 | ||
|
|
ce129df06e | ||
|
|
b0f0eb470a | ||
|
|
579706ccc7 | ||
|
|
44d22390b3 | ||
|
|
cbdf57e703 | ||
|
|
ddf8568312 | ||
|
|
6b79111f38 | ||
|
|
0e03ea56f7 | ||
|
|
da7b555464 | ||
|
|
12c4df6edc | ||
|
|
cb36fba7bd | ||
|
|
69b4ef6eaa | ||
|
|
02dc846662 | ||
|
|
68fa636b6f | ||
|
|
294d5d0fef | ||
|
|
10ba5298ac | ||
|
|
2102ad3b97 | ||
|
|
bdbfb187ab | ||
|
|
e9f0175286 | ||
|
|
b007f4889c | ||
|
|
5c3558f43a | ||
|
|
5c873b7178 | ||
|
|
6bdb2a2b37 | ||
|
|
7f16b3f99c | ||
|
|
7342928e69 | ||
|
|
15d3a8c049 | ||
|
|
ab24a46604 | ||
|
|
fbc41863d6 | ||
|
|
588eeb0101 | ||
|
|
84aa98595e | ||
|
|
1c4cc3c9b9 | ||
|
|
6c31985a19 | ||
|
|
796123fdfd | ||
|
|
7d4396695f | ||
|
|
0934096254 | ||
|
|
73e64ed0e0 | ||
|
|
ce7bbf8c46 | ||
|
|
b2d94772a6 | ||
|
|
909b874a2c | ||
|
|
42fd321016 | ||
|
|
e3bde6a0b0 | ||
|
|
e4f2b9c221 | ||
|
|
e731a9472b | ||
|
|
61d5a6cca6 | ||
|
|
bdd7600262 | ||
|
|
be39afcba4 | ||
|
|
697ecacd43 | ||
|
|
7fd35fc2e6 | ||
|
|
7c32115ab7 | ||
|
|
d8aad8c175 | ||
|
|
0289a53278 | ||
|
|
497bfaecf1 | ||
|
|
4f0474bcc1 | ||
|
|
1e7293a819 | ||
|
|
338927673d | ||
|
|
3b72e1bbc1 | ||
|
|
a05a7fe5d5 | ||
|
|
50d548ec9a | ||
|
|
5879b00f31 | ||
|
|
a160fc9514 | ||
|
|
e3316fcd61 | ||
|
|
f9256a397a | ||
|
|
a3a3f56d90 | ||
|
|
6924802b1f | ||
|
|
1947a67827 | ||
|
|
fb51c2a205 | ||
|
|
f93d95e5cc | ||
|
|
129953092e | ||
|
|
145e02c7ad | ||
|
|
339e065031 | ||
|
|
fc753c2898 | ||
|
|
5171094988 | ||
|
|
90badd1eaf | ||
|
|
67f8f66254 | ||
|
|
86e4ce4191 | ||
|
|
62b14ca053 | ||
|
|
e94a770425 | ||
|
|
fd7f186ccc | ||
|
|
c887c9b011 | ||
|
|
d9da66db28 | ||
|
|
844ebaa295 | ||
|
|
d7cc5bb278 | ||
|
|
7e4e7292ce | ||
|
|
51ea00fbfd | ||
|
|
d3a8bba37a | ||
|
|
2cd73153d9 | ||
|
|
c0a9f1ec80 | ||
|
|
7ba47dc100 | ||
|
|
033bb16e24 | ||
|
|
1ee43b0a87 | ||
|
|
a7b9b1e0c4 | ||
|
|
bd9beba488 | ||
|
|
58231abdd6 | ||
|
|
d7feda4eb3 | ||
|
|
f42d1541fa | ||
|
|
52fa0aceaa | ||
|
|
89595fbf84 | ||
|
|
faaf0e387a | ||
|
|
ad036ff911 | ||
|
|
3a47422f12 | ||
|
|
f685093eca | ||
|
|
37630007c2 | ||
|
|
00240fa258 | ||
|
|
b3ed268175 | ||
|
|
c629033690 | ||
|
|
66d5edb668 | ||
|
|
88dc744d3d | ||
|
|
dd0b0942be | ||
|
|
ebea98ca99 | ||
|
|
d33c66d49c | ||
|
|
813d3c0254 | ||
|
|
802150e815 | ||
|
|
df27c1aace | ||
|
|
9dfc874d6f | ||
|
|
267b45581f | ||
|
|
5ef51b9609 | ||
|
|
7af1b6711e | ||
|
|
a1c9ef99ad | ||
|
|
796468d123 | ||
|
|
f88bc5fdf3 | ||
|
|
966318e5cf | ||
|
|
305bd9c303 | ||
|
|
7c93778b94 | ||
|
|
6275eb4aa5 | ||
|
|
2c617701d4 | ||
|
|
208b230ce0 | ||
|
|
9a4613eb74 | ||
|
|
d46ef4ad51 | ||
|
|
780e5477d8 | ||
|
|
f302f8c8bc | ||
|
|
468ec83bfe | ||
|
|
c2d884e910 | ||
|
|
381ff00ea4 | ||
|
|
452c5a5903 | ||
|
|
3795bc067b | ||
|
|
5b8f1f39f3 | ||
|
|
0e2dd62f9c | ||
|
|
5fca93c76a | ||
|
|
1b11ffc4c8 | ||
|
|
cb338037d2 | ||
|
|
19a6b28cb8 | ||
|
|
b9f56459d4 | ||
|
|
a574bcc5aa | ||
|
|
b2fb001618 | ||
|
|
5ebdb8d05e | ||
|
|
13663aad63 | ||
|
|
4f9ac0dca5 | ||
|
|
6562746f1e | ||
|
|
fb75e72a43 | ||
|
|
5cef61cc04 | ||
|
|
e70385bd26 | ||
|
|
f7b6883dff | ||
|
|
82d3f73eeb | ||
|
|
c9434d4be7 | ||
|
|
422ebf51d8 | ||
|
|
a908ca60a9 | ||
|
|
c883ec828f | ||
|
|
b87a1dc6f0 | ||
|
|
146d84dcab | ||
|
|
e32153c222 | ||
|
|
1c56c7709b | ||
|
|
d0f48cfd77 | ||
|
|
fc34514bb3 | ||
|
|
a640f3f17e | ||
|
|
d8990643f4 | ||
|
|
98cb6da924 | ||
|
|
54ca3ab0d2 | ||
|
|
2b79c5df16 | ||
|
|
31867085ea | ||
|
|
6df3279909 | ||
|
|
550a390703 | ||
|
|
8b42e52db0 | ||
|
|
2b1b73abff | ||
|
|
9cd08b74d1 | ||
|
|
8355faf39e | ||
|
|
228b741ba5 | ||
|
|
e286465946 | ||
|
|
2904f0b43d | ||
|
|
5f675aa796 | ||
|
|
eeac05745f | ||
|
|
33a7ba9645 | ||
|
|
8571f899da | ||
|
|
34b0cd53ea | ||
|
|
fdb2d71d2e | ||
|
|
a8f6dcf882 | ||
|
|
6f2800cdb8 | ||
|
|
72cd1e95fd | ||
|
|
b6af649c30 | ||
|
|
44ed5a27b3 | ||
|
|
0052178b5a | ||
|
|
87f7a6eb86 | ||
|
|
5660a399b8 | ||
|
|
9dd368c883 | ||
|
|
f2b80eaf2f | ||
|
|
f2af26998a | ||
|
|
952c2e09c0 | ||
|
|
40d6a49bfc | ||
|
|
267d60fb1a | ||
|
|
70098975d5 | ||
|
|
54dc335b02 | ||
|
|
d8e35ebfc3 | ||
|
|
653eee4e76 | ||
|
|
1aa94d3e50 | ||
|
|
e6ccf6ee58 | ||
|
|
1f7a127499 | ||
|
|
24f2e65f2b | ||
|
|
c9a036043e | ||
|
|
edf36d3dd1 | ||
|
|
39e7e78b3a | ||
|
|
12b88d2a93 | ||
|
|
ba128edd40 | ||
|
|
ed1401ccb8 | ||
|
|
4632e69def | ||
|
|
b7b693b6d6 | ||
|
|
6e0becee7c | ||
|
|
3fea5132ce | ||
|
|
c3d3d524de | ||
|
|
5423f2fb7f | ||
|
|
d6c69594b9 | ||
|
|
f8eb314bd0 | ||
|
|
dad1d22d69 | ||
|
|
cb2aa585c4 | ||
|
|
46aa17f320 | ||
|
|
4999c2abcb | ||
|
|
168d987779 | ||
|
|
c9623a5ec6 | ||
|
|
f281ccc1da | ||
|
|
e36c9849a8 | ||
|
|
b78bf54e21 | ||
|
|
c226922f07 | ||
|
|
1cf1a60583 | ||
|
|
1f9636ac96 | ||
|
|
c768af6cf9 | ||
|
|
1a5c9b8c39 | ||
|
|
96715753b0 | ||
|
|
b6cd6975f8 | ||
|
|
aab50e5a78 | ||
|
|
ed5b747844 | ||
|
|
8fb9d5dba9 | ||
|
|
6a3fab6198 | ||
|
|
9b23b5e712 | ||
|
|
ad0cd5dd11 | ||
|
|
d057601c72 | ||
|
|
68fbd6caa0 | ||
|
|
a8f0c72a3f | ||
|
|
bc4686e598 | ||
|
|
b7a5b69619 | ||
|
|
4a251eccc4 | ||
|
|
e944b695b1 | ||
|
|
24a0d67a33 | ||
|
|
89a85a295e | ||
|
|
9790bff15c | ||
|
|
dd8747f66b | ||
|
|
e1b0231490 | ||
|
|
17dbdcb66a | ||
|
|
badd1e414f | ||
|
|
b6d02938fd | ||
|
|
8e2e910b5f | ||
|
|
1337db3dff | ||
|
|
36dab8cd5a | ||
|
|
cf1fa1a0f1 | ||
|
|
a116e4d44b | ||
|
|
fe122ce31a | ||
|
|
dc59b81841 | ||
|
|
34571698ee | ||
|
|
ed1a940238 | ||
|
|
51b9389128 | ||
|
|
84573a7283 | ||
|
|
2883c0c553 | ||
|
|
497f480cad | ||
|
|
aa9efa0121 | ||
|
|
d8010fce1e | ||
|
|
076a5c2905 | ||
|
|
5866624317 | ||
|
|
c9bc4ba0e2 | ||
|
|
be2fcad8dc | ||
|
|
f06383e46b | ||
|
|
16d3d26a31 | ||
|
|
2e0fd23695 | ||
|
|
0bec7efd5c | ||
|
|
f3a80259eb | ||
|
|
d25592232b | ||
|
|
042761259e | ||
|
|
7f524eb48b | ||
|
|
bcca79dfc1 | ||
|
|
5c40f81e3d | ||
|
|
1f54ec3a85 | ||
|
|
4429882b60 | ||
|
|
00e11e7cb6 | ||
|
|
2714fc076f | ||
|
|
d7fc72e45d | ||
|
|
214a55898c | ||
|
|
90b1eb2da0 | ||
|
|
391a5310e0 | ||
|
|
b339724a25 | ||
|
|
ea403c0be5 | ||
|
|
6ed91b856a | ||
|
|
17ef0b28ef | ||
|
|
f793b62627 | ||
|
|
2788764430 | ||
|
|
d31fae1077 | ||
|
|
14197e7436 | ||
|
|
4dde2bd121 | ||
|
|
6c58e34bec | ||
|
|
f07b05eaa1 | ||
|
|
315f9f8d18 | ||
|
|
ca688aa975 | ||
|
|
d25d81967d | ||
|
|
8a1db44119 | ||
|
|
1970b9f007 | ||
|
|
416935e530 | ||
|
|
6fc2a47527 | ||
|
|
ba91433bb1 | ||
|
|
f783503b51 | ||
|
|
5219a0c766 | ||
|
|
d032413a56 | ||
|
|
8fb4f017e5 | ||
|
|
c43459e987 | ||
|
|
81232fbb04 | ||
|
|
34d6a676ea | ||
|
|
eb755f7e6f | ||
|
|
177a8fbba8 | ||
|
|
28ead10408 | ||
|
|
44f682c3ba | ||
|
|
1113ed0c50 | ||
|
|
6e052c64ab | ||
|
|
a2bbaeb15a | ||
|
|
317c728f37 | ||
|
|
767fdebe2c | ||
|
|
475cb507cf | ||
|
|
eaf2eac028 | ||
|
|
9412466747 | ||
|
|
b98b326674 | ||
|
|
dbc229b1b7 | ||
|
|
8ea10bb813 | ||
|
|
7e00d8c0d6 | ||
|
|
86940906ca | ||
|
|
568e4fbb25 | ||
|
|
2094e117c1 | ||
|
|
ccb0da2779 | ||
|
|
32f284b3c4 | ||
|
|
3172f37090 | ||
|
|
85e3f1f6c8 | ||
|
|
c82e65eea4 | ||
|
|
a0e8628e8a | ||
|
|
1b6f4ae53c | ||
|
|
7f91d1cbaa | ||
|
|
4018b2b02b | ||
|
|
ddd3b77182 | ||
|
|
59cc0ad683 | ||
|
|
6511c32b02 | ||
|
|
d523a1bf1f | ||
|
|
b65a19ad7f | ||
|
|
3b75b121c4 | ||
|
|
747eac3879 | ||
|
|
881bc88f5c | ||
|
|
23fe83f85c | ||
|
|
0a59ea9478 | ||
|
|
091782d000 | ||
|
|
bc147649c7 | ||
|
|
1b345cbbdd | ||
|
|
70173b9b82 | ||
|
|
bd4dd405d2 | ||
|
|
bc694b8a6f | ||
|
|
cd63e1eba4 | ||
|
|
303d6dc6b0 | ||
|
|
50e478317c | ||
|
|
72467de6b9 | ||
|
|
0997fb4eed | ||
|
|
a6b2bed0f8 | ||
|
|
118c4814fb | ||
|
|
14f49580b9 | ||
|
|
1625cd0628 | ||
|
|
e18d1de429 | ||
|
|
24b1fa84e5 | ||
|
|
7b715ea6e3 | ||
|
|
64c5834901 | ||
|
|
4217347366 | ||
|
|
cbc180ac9f | ||
|
|
2fad6d3213 | ||
|
|
992e6503fd | ||
|
|
be51ff7e4d | ||
|
|
025c127707 | ||
|
|
b016b32154 | ||
|
|
c26a7183ae | ||
|
|
a9e2013138 | ||
|
|
69e527416c | ||
|
|
224d4e1f7e | ||
|
|
4a5d29e87e | ||
|
|
cabc91f3bc | ||
|
|
f5c4042f58 | ||
|
|
b020aa4561 | ||
|
|
9236004a26 | ||
|
|
c5b544771b | ||
|
|
909bc54249 | ||
|
|
5d49f84949 | ||
|
|
08b3607123 | ||
|
|
e86407130c | ||
|
|
afa550986a | ||
|
|
6a5d0169a7 | ||
|
|
b6ccc1531e | ||
|
|
17438df5da | ||
|
|
08a9aad8ab | ||
|
|
7a83ba8984 | ||
|
|
83d3e58bb3 | ||
|
|
e9f94c4344 | ||
|
|
412bc8e5d0 | ||
|
|
d443ebe790 | ||
|
|
480d82e422 | ||
|
|
c3185f324f | ||
|
|
3015b7d576 | ||
|
|
5a0b0ae6e2 | ||
|
|
6a5dc2a6c5 | ||
|
|
a236687ecd | ||
|
|
d8435da52c | ||
|
|
b0c2ed9b13 | ||
|
|
45a497af97 | ||
|
|
6510c04154 | ||
|
|
d8650dcaa1 | ||
|
|
9bdcf7a60d | ||
|
|
bb2cdebac3 | ||
|
|
28bfe461dc | ||
|
|
5326e8543e | ||
|
|
513b10d939 | ||
|
|
47d702ee76 | ||
|
|
e44a2fe9fd | ||
|
|
9d2f87496b | ||
|
|
e2a1b673d6 | ||
|
|
5152eb5239 | ||
|
|
5b277fa130 | ||
|
|
a8ab4bf2e2 | ||
|
|
2abaae21b0 | ||
|
|
1a8d39f92d | ||
|
|
a0a3987209 | ||
|
|
63c3f0b6a2 | ||
|
|
36afa809c4 | ||
|
|
00d9340825 | ||
|
|
4de11c5f96 | ||
|
|
d95e625297 | ||
|
|
31a64b6638 | ||
|
|
f052bda831 | ||
|
|
4bc2b41a38 | ||
|
|
843492ccba | ||
|
|
81e9ef6373 | ||
|
|
9b1ecf7bf3 | ||
|
|
2651004e1c | ||
|
|
eb2e3b911f | ||
|
|
1d4361b2cf | ||
|
|
3ac00be115 | ||
|
|
2009fe796c | ||
|
|
1a5df34c4f | ||
|
|
217f2d2773 | ||
|
|
81f1ca8a23 | ||
|
|
6b759faeb9 | ||
|
|
3163364da3 | ||
|
|
69c4111f02 | ||
|
|
8c50fe34a0 | ||
|
|
cd067db4a7 | ||
|
|
e9790da1a2 | ||
|
|
3e65de2837 | ||
|
|
fe2ab6da14 | ||
|
|
7a89e5646f | ||
|
|
1cddbd94bc | ||
|
|
95da9027e6 | ||
|
|
0afd5fab02 | ||
|
|
68ed6c1c24 | ||
|
|
8ec1311675 | ||
|
|
27882d8f23 | ||
|
|
5623a6dd64 | ||
|
|
736d269c3b | ||
|
|
5bb5fbf334 | ||
|
|
3bdaeb0c29 | ||
|
|
4f383d9d77 | ||
|
|
4e0d01d5ea | ||
|
|
7f4a87722b | ||
|
|
1e6d392a24 | ||
|
|
0998dae5d4 | ||
|
|
446119aa5e | ||
|
|
182689204d | ||
|
|
8fdfcf1251 | ||
|
|
873fe19f9e | ||
|
|
462d5d38f8 | ||
|
|
e28c829613 | ||
|
|
af30a8d2cd | ||
|
|
734f3e7f9d | ||
|
|
e2df0340cf | ||
|
|
e80e04351e | ||
|
|
cffa1ec5e8 | ||
|
|
e6d67faaf9 | ||
|
|
8dde2fea92 | ||
|
|
77178e05e8 | ||
|
|
0521511dfd | ||
|
|
f646a360ad | ||
|
|
187e0e2244 | ||
|
|
ee56d4ab64 | ||
|
|
c8207a007b | ||
|
|
c8a2c752c4 | ||
|
|
d3a8ec0a1e | ||
|
|
abf4229bae | ||
|
|
775da3c22b | ||
|
|
c1891dc005 | ||
|
|
9ab21a2d8d | ||
|
|
0d31f3aef9 | ||
|
|
02f7bd8969 | ||
|
|
ba0ee06f63 | ||
|
|
f649065d6c | ||
|
|
b91a823c95 | ||
|
|
00d5bd9bb5 | ||
|
|
28aa2f32bc | ||
|
|
5170305537 | ||
|
|
9d923b3a08 | ||
|
|
41a6fdb6cd | ||
|
|
e3c0946553 | ||
|
|
977261156b | ||
|
|
ff37b79f4d | ||
|
|
06e7186e13 | ||
|
|
6b5ae7d2f6 | ||
|
|
5852c2ae20 | ||
|
|
5c79a1d839 | ||
|
|
ad1a7a0c4c | ||
|
|
4bbcb17f9f | ||
|
|
be5b940a9f | ||
|
|
600c3a4f0e | ||
|
|
503c0dddd6 | ||
|
|
f118ab4cc7 | ||
|
|
c3a991cf9c | ||
|
|
9793885107 | ||
|
|
401cb9846d | ||
|
|
8d8b2d2bb0 | ||
|
|
4cb4d209cf | ||
|
|
f34697803f | ||
|
|
b205f9a922 | ||
|
|
bb94b3f003 | ||
|
|
3253ef9ab4 | ||
|
|
7a7e9827ca | ||
|
|
d5367fc414 | ||
|
|
940a9eda63 | ||
|
|
36f98dc3cb | ||
|
|
47c94df5cf | ||
|
|
389fb975c3 | ||
|
|
cdb13035ea | ||
|
|
d05dd8fc62 | ||
|
|
6c7b3549ce | ||
|
|
7eb45e1590 | ||
|
|
24049b5e54 | ||
|
|
8ed517e181 | ||
|
|
1f3326f16f | ||
|
|
9b38ba2fce | ||
|
|
6a35304341 | ||
|
|
5a39be4df6 | ||
|
|
e47b417f4e | ||
|
|
23edf7e794 | ||
|
|
1bc1fbb354 | ||
|
|
d81d612b1c | ||
|
|
3cd360e429 | ||
|
|
9b2c23f51a | ||
|
|
7d06b42ea6 | ||
|
|
ef8e262d08 | ||
|
|
4eb4b43673 | ||
|
|
cb2bb065f9 | ||
|
|
78fe543e5b | ||
|
|
759323313b | ||
|
|
89ecf1f29a | ||
|
|
5122c3f932 | ||
|
|
c28dc9c663 | ||
|
|
012b373289 | ||
|
|
9c10303c47 | ||
|
|
50399c2271 | ||
|
|
1adcfae81d | ||
|
|
3486bff376 | ||
|
|
7b796183d1 | ||
|
|
8b9b34ce41 | ||
|
|
808b7a20bf | ||
|
|
5baa1af72e | ||
|
|
3a8973a50a | ||
|
|
f52751af82 | ||
|
|
8bb86e9501 | ||
|
|
a8b82e97f7 | ||
|
|
8dabf88501 | ||
|
|
2763de5f2e | ||
|
|
7aa4bbe8b3 | ||
|
|
e813fd6ec9 | ||
|
|
a3336ccc3f | ||
|
|
04a603732d | ||
|
|
b84193b053 | ||
|
|
ffd5a1269b | ||
|
|
9c8a3e8779 | ||
|
|
2427259171 | ||
|
|
ff7da228f1 | ||
|
|
050ff7c2d3 | ||
|
|
d66ada3b0b | ||
|
|
836fd3f85b | ||
|
|
14d64c6f73 | ||
|
|
2fcdca1274 | ||
|
|
b9cddf96a8 | ||
|
|
9cd0c02dfc | ||
|
|
542f9fa448 | ||
|
|
0580fbb8e7 | ||
|
|
ffc733aa2d | ||
|
|
da7b3e9b3b | ||
|
|
0d904cdc23 | ||
|
|
0613cd4373 | ||
|
|
45a3e7d140 | ||
|
|
bfd491b1bd | ||
|
|
5bbdd075b1 | ||
|
|
128eea7f82 | ||
|
|
ae938f5dec | ||
|
|
232feec794 | ||
|
|
fa91c71ce1 | ||
|
|
7b96b852af | ||
|
|
ad430ea6f3 | ||
|
|
dfb021b1af | ||
|
|
8c14d18802 | ||
|
|
abc22ba4bc | ||
|
|
8d8c5b7d3b | ||
|
|
4998ceb93b | ||
|
|
8aca9b4c7d | ||
|
|
1f7f14d214 | ||
|
|
ae57373818 | ||
|
|
1d1df08df8 | ||
|
|
1fb37828a7 | ||
|
|
b0605eb980 | ||
|
|
f23caa6742 | ||
|
|
c708b0f16f | ||
|
|
437143e01a | ||
|
|
c71f437b98 | ||
|
|
d9c4185983 | ||
|
|
e6b48fdc13 | ||
|
|
77d8ebabc6 | ||
|
|
a8bc50f67c | ||
|
|
5c97293269 | ||
|
|
2365b8aab7 | ||
|
|
975adfb602 | ||
|
|
4e0dc1ed9d | ||
|
|
d6ff7a2077 | ||
|
|
7b673421ad | ||
|
|
df355a880b | ||
|
|
e8b5fffe19 | ||
|
|
e50ba21896 | ||
|
|
bee5ff48f4 | ||
|
|
33aecb6bda | ||
|
|
7af68fee6b | ||
|
|
545e8f45da | ||
|
|
7838cfcbe0 | ||
|
|
dbaee1db02 | ||
|
|
fe4902da1c | ||
|
|
a341927725 | ||
|
|
cd72875761 | ||
|
|
10a6553c96 | ||
|
|
a2898581bc | ||
|
|
f85dc2e8d5 | ||
|
|
fbd3fe258d | ||
|
|
8ef3e805db | ||
|
|
5a980a7043 | ||
|
|
7c061bbb9b | ||
|
|
2096a6e755 | ||
|
|
1e2280f69d | ||
|
|
b16621221e | ||
|
|
8b2c22efe2 |
@@ -1,13 +0,0 @@
|
||||
### 该问题是怎么引起的?
|
||||
|
||||
|
||||
|
||||
### 重现步骤
|
||||
|
||||
|
||||
|
||||
### 报错信息
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
### 相关的Issue
|
||||
|
||||
|
||||
### 原因(目的、解决的问题等)
|
||||
|
||||
|
||||
### 描述(做了什么,变更了什么)
|
||||
|
||||
|
||||
### 测试用例(新增、改动、可能影响的功能)
|
||||
|
||||
|
||||
|
||||
|
||||
788
LICENSE
788
LICENSE
@@ -1,127 +1,661 @@
|
||||
木兰宽松许可证, 第2版
|
||||
|
||||
木兰宽松许可证, 第2版
|
||||
2020年1月 http://license.coscl.org.cn/MulanPSL2
|
||||
|
||||
|
||||
您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束:
|
||||
|
||||
0. 定义
|
||||
|
||||
“软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。
|
||||
|
||||
“贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。
|
||||
|
||||
“贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。
|
||||
|
||||
“法人实体”是指提交贡献的机构及其“关联实体”。
|
||||
|
||||
“关联实体”是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。
|
||||
|
||||
1. 授予版权许可
|
||||
|
||||
每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。
|
||||
|
||||
2. 授予专利许可
|
||||
|
||||
每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。
|
||||
|
||||
3. 无商标许可
|
||||
|
||||
“本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。
|
||||
|
||||
4. 分发限制
|
||||
|
||||
您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。
|
||||
|
||||
5. 免责声明与责任限制
|
||||
|
||||
“软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。
|
||||
|
||||
6. 语言
|
||||
“本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。
|
||||
|
||||
条款结束
|
||||
|
||||
如何将木兰宽松许可证,第2版,应用到您的软件
|
||||
|
||||
如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步:
|
||||
|
||||
1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字;
|
||||
|
||||
2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中;
|
||||
|
||||
3, 请将如下声明文本放入每个源文件的头部注释中。
|
||||
|
||||
Copyright (c) [Year] [name of copyright holder]
|
||||
[Software Name] is licensed under Mulan PSL v2.
|
||||
You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
You may obtain a copy of Mulan PSL v2 at:
|
||||
http://license.coscl.org.cn/MulanPSL2
|
||||
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
See the Mulan PSL v2 for more details.
|
||||
|
||||
|
||||
Mulan Permissive Software License,Version 2
|
||||
|
||||
Mulan Permissive Software License,Version 2 (Mulan PSL v2)
|
||||
January 2020 http://license.coscl.org.cn/MulanPSL2
|
||||
|
||||
Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions:
|
||||
|
||||
0. Definition
|
||||
|
||||
Software means the program and related documents which are licensed under this License and comprise all Contribution(s).
|
||||
|
||||
Contribution means the copyrightable work licensed by a particular Contributor under this License.
|
||||
|
||||
Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License.
|
||||
|
||||
Legal Entity means the entity making a Contribution and all its Affiliates.
|
||||
|
||||
Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity.
|
||||
|
||||
1. Grant of Copyright License
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not.
|
||||
|
||||
2. Grant of Patent License
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken.
|
||||
|
||||
3. No Trademark License
|
||||
|
||||
No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in Section 4.
|
||||
|
||||
4. Distribution Restriction
|
||||
|
||||
You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software.
|
||||
|
||||
5. Disclaimer of Warranty and Limitation of Liability
|
||||
|
||||
THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
6. Language
|
||||
|
||||
THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL.
|
||||
|
||||
END OF THE TERMS AND CONDITIONS
|
||||
|
||||
How to Apply the Mulan Permissive Software License,Version 2 (Mulan PSL v2) to Your Software
|
||||
|
||||
To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps:
|
||||
|
||||
i Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner;
|
||||
|
||||
ii Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package;
|
||||
|
||||
iii Attach the statement to the appropriate annotated syntax at the beginning of each source file.
|
||||
|
||||
|
||||
Copyright (c) [Year] [name of copyright holder]
|
||||
[Software Name] is licensed under Mulan PSL v2.
|
||||
You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
You may obtain a copy of Mulan PSL v2 at:
|
||||
http://license.coscl.org.cn/MulanPSL2
|
||||
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
See the Mulan PSL v2 for more details.
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing under
|
||||
this license.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your version
|
||||
supports such interaction) an opportunity to receive the Corresponding
|
||||
Source of your version by providing access to the Corresponding Source
|
||||
from a network server at no charge, through some standard or customary
|
||||
means of facilitating copying of software. This Corresponding Source
|
||||
shall include the Corresponding Source for any work covered by version 3
|
||||
of the GNU General Public License that is incorporated pursuant to the
|
||||
following paragraph.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU Affero General Public License from time to time. Such new versions
|
||||
will be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU Affero General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU Affero General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU Affero General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for the
|
||||
specific requirements.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
193
README.md
193
README.md
@@ -1,110 +1,119 @@
|
||||
|
||||
### 一、项目简介
|
||||
|
||||
1. **物美智能([wumei-smart](http://www.wumei.live/introduce.html))]是一套开源的软硬件系统,可用于二次开发和学习,快速搭建自己的智能家居系统。** 硬件工程师可以把自己的设备集成到系统;软件工程师可以使用项目中的设备熟悉软硬件交互。[演示视频 >>](https://space.bilibili.com/471004321)<br />
|
||||
<br /><br />
|
||||
|
||||
2. 服务端使用spring boot、数据库mysql和redis、前端vue、移动端android、硬件端ESP-IDF和Arduino等。软硬件交互基于Mqtt协议,使用EMQ代理服务器。系统架构图如下:
|
||||
<br /><br />
|
||||

|
||||

|
||||

|
||||
|
||||
3. 硬件端提供接入文档,需要设备支持网络功能,项目里面包含ESP-IDF和Arduino的硬件代码和接入示例。同时制作了智能开关(wifi通断器)板子,可用于学习和生活中,控制2500W以下的用电设备。硬件完整示例代码采用ESP-IDF框架4.2版本,基于乐鑫ESP32S2芯片,安信可ESP-12K模组。[详情和购买方式 >> ](https://gitee.com/kerwincui/wumei-smart/wikis/pages?sort_id=4233922&doc_id=1506495)<br /><br />
|
||||
 <br />
|
||||
* 手机、电脑远程控制
|
||||
* 遥控配对、清码和控制
|
||||
* 空气温湿度监控
|
||||
* 雷达感应和报警
|
||||
* 220V和5V电压供电,阻性负载2500W,感性负载250W
|
||||
|
||||
<br />
|
||||
[](https://gitee.com/activity/2025opensource?ident=IKKZS9)
|
||||
|
||||
|
||||
### 二、相关开发板
|
||||
1. NodeMCU开发板制作一个智能开关
|
||||

|
||||
2. Wifi控制器和LED灯板制作七彩智能灯
|
||||

|
||||
3. 物联网开发板 [详情和购买方式 >>](https://gitee.com/kerwincui/wumei-smart/wikis/pages?sort_id=4233922&doc_id=1506495)
|
||||

|
||||
4. 物联网入门学习套件 [详情和购买方式 >>](https://gitee.com/kerwincui/wumei-smart/wikis/pages?sort_id=4233922&doc_id=1506495)
|
||||

|
||||
FastBee 是一款面向中小企业与个人开发者的**轻量**、**易用**、**全栈**开源物联网平台。
|
||||
|
||||
---
|
||||
|
||||
### 一、项目介绍
|
||||
|
||||
FastBee 集设备管理、数据监控、多端应用于一体,支持[一键容器化部署](https://fastbee.cn/doc/install/docker.html),适用于智能家居、智慧办公、智慧社区、农业监测、水利监测、工业控制等多种场景。平台基于 Spring Boot 开发,<b>内置高性能 MQTT 服务端,无需额外部署 EMQX 或其他 MQTT 服务端</b>,前端采用 Vue 与 ElementUI,移动端支持微信小程序、Android、iOS 及 H5,设备端兼容 ESP32、ESP8266、树莓派、合宙等常见硬件。
|
||||
|
||||
---
|
||||
|
||||
### 二、系统功能
|
||||
|
||||
| 系统功能 | 功能说明 |
|
||||
|----------------|--------------------------------------------------------------------------|
|
||||
| 产品管理 | 创建产品、定义物模型、设置设备认证方式、管理产品分类及固件版本 |
|
||||
| 设备管理 | 设备注册、分组、实时状态监测、远程控制、操作日志追溯及设备分享功能 |
|
||||
| 物模型管理 | 提供标准化的属性、功能和事件定义,实现设备与平台的数据语义统一 |
|
||||
| 规则脚本 | 对设备上报和平台下发的原始数据进行处理,转发后匹配设备交互格式 |
|
||||
| MQTT 接入 | 内置基于 Netty 开发的高性能 MQTT Broker,无需额外部署第三方服务 |
|
||||
| 视频监控接入 | 支持 GB/T 28181 国家标准协议,实现视频直播与设备管理 |
|
||||
| 权限管理 | 基于成熟的若依权限框架,实现用户、角色、部门、岗位及操作日志的精细化管控 |
|
||||
| 多数据源 | 支持 MySQL、PostgreSQL、MSSQL 等关系型数据库 |
|
||||
| 硬件 SDK | 提供 ESP-IDF、Arduino、树莓派、合宙等常见硬件平台的接入示例与 SDK |
|
||||
| 多端应用支持 | 提供 Web 控制台(Vue + ElementUI)、微信小程序、Android/iOS App 及 H5 界面 |
|
||||
| 一键部署 | 推荐使用 Docker 容器化部署,支持[快速搭建](https://fastbee.cn/doc/install/docker.html)完整环境 |
|
||||
|
||||
|
||||
<br />
|
||||
|
||||
### 三、技术栈
|
||||
* 后端
|
||||
- 相关技术:Spring boot、MyBatis、Spring Security、Jwt、Mysql、Redis、Mongodb、Mqtt等
|
||||
- 开发工具:IDEA
|
||||
* 前端
|
||||
- 相关技术:ES6、Vue、Vuex、Vue-router、Vue-cli、Axios、Element-ui等
|
||||
- 开发工具:Visual Studio Code
|
||||
* 安卓
|
||||
- 相关技术:XUI、XPage、XAop、XHttp2等
|
||||
- 开发工具:Android Studio
|
||||
* 硬件端
|
||||
- 相关技术: ESP-IDF、Arduino、FreeRTOS等
|
||||
- 开发工具:Visual Studio Code 和 Arduino
|
||||
[](https://gitee.com/beecue/FastBee-Arduino)
|
||||
|
||||
<br />
|
||||
---
|
||||
|
||||
### 四、快速部署系统
|
||||
#### 1. 安装docker
|
||||
#### 2. 命令窗口运行如下命令(完成后端、前端、数据库、EMQX部署):
|
||||
### 三、快速开始
|
||||
|
||||
```
|
||||
docker run \
|
||||
--name wumei-smart \
|
||||
--publish 80:80 \
|
||||
--publish 18083:18083 \
|
||||
--publish 1883:1883 \
|
||||
--publish 3306:3306 \
|
||||
--publish 6379:6379 \
|
||||
--restart always \
|
||||
--detach \
|
||||
registry.cn-chengdu.aliyuncs.com/kerwincui/wumei-smart:1.0
|
||||
```
|
||||
1. **环境准备**:确保服务器已安装 `Docker` 和 `Docker Compose`。
|
||||
2. **执行命令**:
|
||||
```bash
|
||||
sudo wget -c https://hub.fastbee.cn/resource/install.sh && bash ./install.sh
|
||||
```
|
||||
根据提示选择“开源版本”,脚本将自动完成所有服务的拉取与启动。
|
||||
3. **访问系统**:部署完成后,通过浏览器访问 `http://你的服务器IP:端口`,默认账号为 `admin`,密码为 `admin123`。
|
||||
4. **详细步骤**:请查阅 [官方安装文档](https://fastbee.cn/doc/install/docker.html)。
|
||||
|
||||
#### 3. 扫码下载APP安装,打开APP,跳过登录,配置服务端地址
|
||||

|
||||
---
|
||||
|
||||
测试账号:wumei admin123;配置成功后默认账号:admin admin123
|
||||
|
||||
#### 4. 硬件代码烧录到设备
|
||||
* [Arduino接入Demo](https://gitee.com/kerwincui/wumei-smart/tree/master/firmware/arduino)
|
||||
* [ESP-IDF接入Demo](https://gitee.com/kerwincui/wumei-smart/tree/master/firmware/esp-idf)
|
||||
### 四、技术栈
|
||||
##### 服务端
|
||||
- 相关技术:Spring boot、MyBatis、Spring Security、Jwt、Mysql、Redis、TDengine、Netty等
|
||||
- 开发工具:IDEA
|
||||
- 源码目录:spring-boot文件夹下
|
||||
|
||||
<br />
|
||||
##### Web端
|
||||
- 相关技术:ES6、Vue、Vuex、Vue-router、Vue-cli、Axios、Element-ui、Echart等
|
||||
- 开发工具:Visual Studio Code
|
||||
- 源码目录:vue文件夹下
|
||||
|
||||
### 五、系统部分图片
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
##### 移动端(微信小程序 / Android / Ios / H5)
|
||||
- 相关技术:uniapp、[uView](https://www.uviewui.com/)、[uChart](https://www.ucharts.cn/)
|
||||
- 开发工具:HBuilder
|
||||
- 源码地址:[https://gitee.com/beecue/fastbee-app](https://gitee.com/beecue/fastbee-app)
|
||||
|
||||
<br />
|
||||
##### 硬件端
|
||||
- 相关技术: ESP-IDF、Arduino、FreeRTOS、Python、Lua等
|
||||
- 开发工具:Visual Studio Code 和 Arduino等
|
||||
- 源码地址:[https://gitee.com/beecue/fastbee-sdk](https://gitee.com/beecue/fastbee-sdk)
|
||||
|
||||
### 六、相关教程
|
||||
##### 部署与运维
|
||||
- 相关技术:docker、docker-compose、shell
|
||||
- [快速部署](https://fastbee.cn/doc/install/docker.html):安装好docker和docker-compose后执行命令 ` sudo wget -c https://hub.fastbee.cn/resource/install.sh && bash ./install.sh ` 然后选择开源版本,等待完成部署
|
||||
|
||||
* [项目文档](https://gitee.com/kerwincui/wumei-smart/wikis/pages)
|
||||
* [ESP-IDF完整固件代码](https://gitee.com/kerwincui/wumei-smart/tree/master/firmware/esp-idf/wumei-smart-firmware)
|
||||
* [演示视频](https://space.bilibili.com/471004321)
|
||||
* [硬件详情和购买方式](https://gitee.com/kerwincui/wumei-smart/wikis/pages?sort_id=4233922&doc_id=1506495)
|
||||
* [物美智能官网](http://wumei.live)
|
||||
* [若依文档](http://doc.ruoyi.vip/ruoyi-vue/),前端和后端基于Ruoyi-Vue,前后端分离权限管理系统
|
||||
* [XUI](https://gitee.com/xuexiangjys/XUI),Android基于XUI开发,是一个简洁而优雅的原生UI框架
|
||||
* [ESP-IDF编程指南](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/index.html)
|
||||
* [EMQ文档](https://docs.emqx.cn)
|
||||
|空气检测仪| 物联网开发板 | Air724开发板 | 智能开关| [查看更多>>](https://fastbee.cn/doc/device/) |
|
||||
| :----: | :----------: |:----------: |:----------: |:----------: |
|
||||
|  |  |  | |  |
|
||||
|
||||
<br />
|
||||
---
|
||||
|
||||
### 七、加入互助交流群:1073236354
|
||||
<a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=P_oc91N6KC39zp2PEV_-BY3xMnAokeZ8&jump_from=webapi"><img border="0" src="//pub.idqqimg.com/wpa/images/group.png" alt="物美智能wumeismart" title="物美智能wumeismart"></a>
|
||||
<br /><br />
|
||||
### 五、其他
|
||||
|
||||
### 八、APP和管理端登录   测试账号:wumei  密码:admin123
|
||||
* APP:[进入下载界面>>>](https://gitee.com/kerwincui/wumei-smart/wikis/pages?sort_id=4203153&doc_id=1506495)
|
||||
* 管理端:[进入登录界面>>>](http://iot.wumei.live/)
|
||||
1. **商用授权**:开源版本采用 AGPL3 协议,可用于个人学习和使用,商业用途推荐购买[商业版本授权](https://fastbee.cn/doc/pages/sponsor/)。
|
||||
2. **在线演示**:[商业版本演示地址](https://iot.fastbee.cn/)(开源版本暂仅支持 MQTT 协议)。
|
||||
3. **系统文档**:[https://fastbee.cn/doc/](https://fastbee.cn/doc/)
|
||||
4. **QQ 交流群**:720136372、946029159、1073236354
|
||||
|
||||
---
|
||||
|
||||
### 六、部分图片
|
||||
|
||||

|
||||

|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-19ef5b528bb044253848722118b694bef47.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-8b4c24353bc2340b8362438b87ceac27a9d.png"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-a0c864679be6c4f9bb5547244aeb19657b4.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-9cc3bc5abe8dd95cb3924e5f7b6864a0342.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-ec8c6251884d81f234487d3e25d459ce302.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-e5e7ef5027723051e97d6861d4296c08da5.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-3ae8cef86db794ff37d9186e83b12b88958.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-e20900a12e3781467d05163665ca04645fa.png"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-5c755895fc1a7ba02d487b75cf493ffb0df.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/up-4e279e657c6f8b6af2d58fa215ab7fae02d.jpg"></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
---
|
||||
|
||||
FastBee 项目代码完全开源,覆盖设备 SDK、后端服务、前端应用和移动端,兼顾成熟度、性能与开发效率,适合中小企业快速构建物联网业务,也便于开发者进行二次开发与学习研究。
|
||||
57
RoadMap.md
Normal file
57
RoadMap.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# 架构优化
|
||||
- 代码简化
|
||||
- 业务&协议解耦
|
||||
- 关键组件支持横向拓展
|
||||
- 网络协议支持横向拓展,包括:mqtt broker,tcp,coap,udp,sip等
|
||||
- 协议插件化
|
||||
- 编码脚本化
|
||||
- 业务代码模版化
|
||||
- 消息总线
|
||||
|
||||
# 功能优化
|
||||
- 网关/子网关:上线,绑定,拓扑,消息代理/透传/轮询等功能完善
|
||||
- 设备详情简化,运行状态,监测,历史记录等界面优化,组件可编辑
|
||||
- 设备OT能力完善,配合SDK完善设备产测,设备出厂配置,设备一键注网,设备批量上线,设备升级,设备维护&替换等流程
|
||||
- 设备IT能力完善,更方便对接联动第三方系统,打通数据烟囱,集成更多三方SDK
|
||||
- 消息路由,消息流转,消息编解码,消息过滤更加灵活
|
||||
|
||||
# 功能拓展
|
||||
- 规则引擎
|
||||
- 组态
|
||||
- 可视化大屏
|
||||
- 视频监控协议
|
||||
- 视频分析,图形识别能力
|
||||
- coap协议
|
||||
- sip协议
|
||||
- snmp协议
|
||||
- tr069/tr369协议
|
||||
- plc对接
|
||||
- modbus rtu/ascii/tcp等协议
|
||||
- ai能力
|
||||
- gpt能力
|
||||
|
||||
# 设备SDK
|
||||
- esp-idf框架搭建
|
||||
- 基于esp-aliyun编写fastbee相关mqtt接入示例
|
||||
- esp-modbus示例完善,增加mqtt透传,主站轮询指令下发等特性
|
||||
- esp-aliyun重构,升级esp-idf5.0
|
||||
- esp-fastbee组件模块开发
|
||||
- rt-thread,openwrt等os接入组件开发
|
||||
- 尝试适配更多硬件方案,rk,esp32,stm32,合宙等等
|
||||
- 免费帮10家不同类型设备厂商接入平台
|
||||
|
||||
# 文档完善
|
||||
- 新手入门任务
|
||||
- 各模块使用说明书
|
||||
- 调试方式文档
|
||||
- 二次开发说明书
|
||||
- 三方工具关键组件使用说明
|
||||
- 简化代码二发和部署流程
|
||||
- 交付方式优化:docker镜像,一键部署包等方式
|
||||
|
||||
# 社区建设
|
||||
- 发展一批Committer
|
||||
- 规范issues和pr流程
|
||||
- 完善测试用例和测试流程
|
||||
- 完善自动化发布,代码静态检查,自动化测试等流程
|
||||
- 与行业伙伴共同打造5-8个垂直行业典型案例
|
||||
16
android/.gitignore
vendored
16
android/.gitignore
vendored
@@ -1,16 +0,0 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/LocalRepository
|
||||
/keystores
|
||||
/local.properties
|
||||
/.idea/caches
|
||||
/.idea/codeStyles
|
||||
/.idea/inspectionProfiles
|
||||
/.idea/libraries
|
||||
/.idea/dictionaries
|
||||
/.idea/markdown-navigator
|
||||
/.idea/*.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
7
android/.idea/copyright/profiles_settings.xml
generated
7
android/.idea/copyright/profiles_settings.xml
generated
@@ -1,7 +0,0 @@
|
||||
<component name="CopyrightManager">
|
||||
<settings default="xuexiang">
|
||||
<module2copyright>
|
||||
<element module="Project Files" copyright="xuexiang" />
|
||||
</module2copyright>
|
||||
</settings>
|
||||
</component>
|
||||
6
android/.idea/copyright/xuexiang.xml
generated
6
android/.idea/copyright/xuexiang.xml
generated
@@ -1,6 +0,0 @@
|
||||
<component name="CopyrightManager">
|
||||
<copyright>
|
||||
<option name="notice" value="Copyright (C) &#36;today.year xuexiangjys(xuexiangjys@163.com) Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. " />
|
||||
<option name="myName" value="xuexiang" />
|
||||
</copyright>
|
||||
</component>
|
||||
191
android/LICENSE
191
android/LICENSE
@@ -1,191 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, and
|
||||
distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright
|
||||
owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all other entities
|
||||
that control, are controlled by, or are under common control with that entity.
|
||||
For the purposes of this definition, "control" means (i) the power, direct or
|
||||
indirect, to cause the direction or management of such entity, whether by
|
||||
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising
|
||||
permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications, including
|
||||
but not limited to software source code, documentation source, and configuration
|
||||
files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical transformation or
|
||||
translation of a Source form, including but not limited to compiled object code,
|
||||
generated documentation, and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or Object form, made
|
||||
available under the License, as indicated by a copyright notice that is included
|
||||
in or attached to the work (an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object form, that
|
||||
is based on (or derived from) the Work and for which the editorial revisions,
|
||||
annotations, elaborations, or other modifications represent, as a whole, an
|
||||
original work of authorship. For the purposes of this License, Derivative Works
|
||||
shall not include works that remain separable from, or merely link (or bind by
|
||||
name) to the interfaces of, the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including the original version
|
||||
of the Work and any modifications or additions to that Work or Derivative Works
|
||||
thereof, that is intentionally submitted to Licensor for inclusion in the Work
|
||||
by the copyright owner or by an individual or Legal Entity authorized to submit
|
||||
on behalf of the copyright owner. For the purposes of this definition,
|
||||
"submitted" means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems, and
|
||||
issue tracking systems that are managed by, or on behalf of, the Licensor for
|
||||
the purpose of discussing and improving the Work, but excluding communication
|
||||
that is conspicuously marked or otherwise designated in writing by the copyright
|
||||
owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
|
||||
of whom a Contribution has been received by Licensor and subsequently
|
||||
incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License.
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby
|
||||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||
irrevocable copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the Work and such
|
||||
Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License.
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby
|
||||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||
irrevocable (except as stated in this section) patent license to make, have
|
||||
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
|
||||
such license applies only to those patent claims licensable by such Contributor
|
||||
that are necessarily infringed by their Contribution(s) alone or by combination
|
||||
of their Contribution(s) with the Work to which such Contribution(s) was
|
||||
submitted. If You institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
|
||||
Contribution incorporated within the Work constitutes direct or contributory
|
||||
patent infringement, then any patent licenses granted to You under this License
|
||||
for that Work shall terminate as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution.
|
||||
|
||||
You may reproduce and distribute copies of the Work or Derivative Works thereof
|
||||
in any medium, with or without modifications, and in Source or Object form,
|
||||
provided that You meet the following conditions:
|
||||
|
||||
You must give any other recipients of the Work or Derivative Works a copy of
|
||||
this License; and
|
||||
You must cause any modified files to carry prominent notices stating that You
|
||||
changed the files; and
|
||||
You must retain, in the Source form of any Derivative Works that You distribute,
|
||||
all copyright, patent, trademark, and attribution notices from the Source form
|
||||
of the Work, excluding those notices that do not pertain to any part of the
|
||||
Derivative Works; and
|
||||
If the Work includes a "NOTICE" text file as part of its distribution, then any
|
||||
Derivative Works that You distribute must include a readable copy of the
|
||||
attribution notices contained within such NOTICE file, excluding those notices
|
||||
that do not pertain to any part of the Derivative Works, in at least one of the
|
||||
following places: within a NOTICE text file distributed as part of the
|
||||
Derivative Works; within the Source form or documentation, if provided along
|
||||
with the Derivative Works; or, within a display generated by the Derivative
|
||||
Works, if and wherever such third-party notices normally appear. The contents of
|
||||
the NOTICE file are for informational purposes only and do not modify the
|
||||
License. You may add Your own attribution notices within Derivative Works that
|
||||
You distribute, alongside or as an addendum to the NOTICE text from the Work,
|
||||
provided that such additional attribution notices cannot be construed as
|
||||
modifying the License.
|
||||
You may add Your own copyright statement to Your modifications and may provide
|
||||
additional or different license terms and conditions for use, reproduction, or
|
||||
distribution of Your modifications, or for any such Derivative Works as a whole,
|
||||
provided Your use, reproduction, and distribution of the Work otherwise complies
|
||||
with the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions.
|
||||
|
||||
Unless You explicitly state otherwise, any Contribution intentionally submitted
|
||||
for inclusion in the Work by You to the Licensor shall be under the terms and
|
||||
conditions of this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify the terms of
|
||||
any separate license agreement you may have executed with Licensor regarding
|
||||
such Contributions.
|
||||
|
||||
6. Trademarks.
|
||||
|
||||
This License does not grant permission to use the trade names, trademarks,
|
||||
service marks, or product names of the Licensor, except as required for
|
||||
reasonable and customary use in describing the origin of the Work and
|
||||
reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, Licensor provides the
|
||||
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
|
||||
including, without limitation, any warranties or conditions of TITLE,
|
||||
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
|
||||
solely responsible for determining the appropriateness of using or
|
||||
redistributing the Work and assume any risks associated with Your exercise of
|
||||
permissions under this License.
|
||||
|
||||
8. Limitation of Liability.
|
||||
|
||||
In no event and under no legal theory, whether in tort (including negligence),
|
||||
contract, or otherwise, unless required by applicable law (such as deliberate
|
||||
and grossly negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special, incidental,
|
||||
or consequential damages of any character arising as a result of this License or
|
||||
out of the use or inability to use the Work (including but not limited to
|
||||
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
|
||||
any and all other commercial damages or losses), even if such Contributor has
|
||||
been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability.
|
||||
|
||||
While redistributing the Work or Derivative Works thereof, You may choose to
|
||||
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
|
||||
other liability obligations and/or rights consistent with this License. However,
|
||||
in accepting such obligations, You may act only on Your own behalf and on Your
|
||||
sole responsibility, not on behalf of any other Contributor, and only if You
|
||||
agree to indemnify, defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason of your
|
||||
accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work
|
||||
|
||||
To apply the Apache License to your work, attach the following boilerplate
|
||||
notice, with the fields enclosed by brackets "{}" replaced with your own
|
||||
identifying information. (Don't include the brackets!) The text should be
|
||||
enclosed in the appropriate comment syntax for the file format. We also
|
||||
recommend that a file or class name and description of purpose be included on
|
||||
the same "printed page" as the copyright notice for easier identification within
|
||||
third-party archives.
|
||||
|
||||
Copyright 2018 xuexiangjys
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -1,5 +0,0 @@
|
||||
Android项目打包
|
||||
1. 修改工程根目录的gradle.properties中的isNeedPackage=true。
|
||||
2. 添加并配置keystore,在versions.gradle中修改app_release相关参数。
|
||||
3. 如果考虑使用友盟统计的话,在local.properties中设置应用的友盟ID:APP_ID_UMENG。
|
||||
4. 使用./gradlew clean assembleReleaseChannels进行多渠道打包。
|
||||
1
android/app/.gitignore
vendored
1
android/app/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
/build
|
||||
@@ -1,138 +0,0 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'img-optimizer'
|
||||
//打包时,记得设置true启用
|
||||
if (isNeedPackage.toBoolean() && isUseBooster.toBoolean()) {
|
||||
apply plugin: 'com.didiglobal.booster'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion build_versions.target_sdk
|
||||
buildToolsVersion build_versions.build_tools
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.kerwin.wumei"
|
||||
minSdkVersion 17
|
||||
targetSdkVersion build_versions.target_sdk
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
multiDexEnabled true
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
|
||||
javaCompileOptions {
|
||||
annotationProcessorOptions {
|
||||
arguments = [ moduleName : project.getName() ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
if (isNeedPackage.toBoolean()) {
|
||||
release {
|
||||
storeFile file(app_release.storeFile)
|
||||
storePassword app_release.storePassword
|
||||
keyAlias app_release.keyAlias
|
||||
keyPassword app_release.keyPassword
|
||||
}
|
||||
}
|
||||
|
||||
debug {
|
||||
storeFile file("./debug.jks")
|
||||
storePassword "123456"
|
||||
keyAlias "debug"
|
||||
keyPassword "123456"
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled true
|
||||
shrinkResources true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
if (isNeedPackage.toBoolean()) {
|
||||
signingConfig signingConfigs.release
|
||||
|
||||
Properties properties = new Properties()
|
||||
properties.load(project.rootProject.file('local.properties').newDataInputStream())
|
||||
def appID = properties.getProperty("APP_ID_UMENG")
|
||||
if (appID != null) {
|
||||
buildConfigField "String", "APP_ID_UMENG", appID
|
||||
} else {
|
||||
buildConfigField "String", "APP_ID_UMENG", '""'
|
||||
}
|
||||
} else {
|
||||
signingConfig signingConfigs.debug
|
||||
buildConfigField "String", "APP_ID_UMENG", '""'
|
||||
}
|
||||
}
|
||||
|
||||
debug {
|
||||
debuggable true
|
||||
minifyEnabled false
|
||||
|
||||
signingConfig signingConfigs.debug
|
||||
buildConfigField "String", "APP_ID_UMENG", '""'
|
||||
}
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation project(path: ':esptouch')
|
||||
testImplementation deps.junit
|
||||
androidTestImplementation deps.runner
|
||||
androidTestImplementation deps.espresso.core
|
||||
|
||||
//分包
|
||||
implementation deps.androidx.multidex
|
||||
|
||||
implementation 'com.alibaba.android:vlayout:1.2.36'
|
||||
//下拉刷新
|
||||
implementation 'com.github.xuexiangjys.SmartRefreshLayout:refresh-header:1.1.5'
|
||||
implementation 'com.github.xuexiangjys.SmartRefreshLayout:refresh-layout:1.1.5'
|
||||
//WebView
|
||||
implementation 'com.github.xuexiangjys.AgentWeb:agentweb-core:1.0.0'
|
||||
implementation 'com.github.xuexiangjys.AgentWeb:agentweb-download:1.0.0'//选填
|
||||
//腾讯的键值对存储mmkv
|
||||
implementation 'com.tencent:mmkv:1.0.22'
|
||||
//屏幕适配AutoSize
|
||||
implementation 'me.jessyan:autosize:1.1.2'
|
||||
//umeng统计
|
||||
implementation 'com.umeng.umsdk:analytics:8.0.2'
|
||||
implementation 'com.umeng.umsdk:common:2.0.2'
|
||||
|
||||
//预加载占位控件
|
||||
implementation 'me.samlss:broccoli:1.0.0'
|
||||
|
||||
implementation 'com.zzhoujay.richtext:richtext:3.0.8'
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||
|
||||
//ANR异常捕获
|
||||
implementation 'com.github.anrwatchdog:anrwatchdog:1.4.0'
|
||||
|
||||
//美团多渠道打包
|
||||
implementation 'com.meituan.android.walle:library:1.1.6'
|
||||
|
||||
//rxutil2
|
||||
implementation deps.rxbinding
|
||||
implementation 'com.github.xuexiangjys:rxutil2:1.2.0'
|
||||
|
||||
// circleprogressview 圆形进度动画控件
|
||||
implementation 'com.king.view:circleprogressview:1.1.2'
|
||||
}
|
||||
//自动添加X-Library依赖
|
||||
apply from: 'x-library.gradle'
|
||||
//walle多渠道打包
|
||||
apply from: 'multiple-channel.gradle'
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
# 美团
|
||||
meituan
|
||||
# 三星
|
||||
samsungapps
|
||||
# 小米
|
||||
xiaomi
|
||||
# 91助手
|
||||
91com
|
||||
# 魅族
|
||||
meizu
|
||||
# 豌豆荚
|
||||
wandou
|
||||
# Google Play
|
||||
googleplay
|
||||
# 百度
|
||||
baidu
|
||||
# 360
|
||||
360cn
|
||||
# 应用宝
|
||||
myapp
|
||||
# 华为
|
||||
huawei
|
||||
# 蒲公英
|
||||
pgyer
|
||||
github
|
||||
Binary file not shown.
@@ -1,10 +0,0 @@
|
||||
apply plugin: 'walle'
|
||||
|
||||
walle {
|
||||
// 指定渠道包的输出路径
|
||||
apkOutputFolder = new File("${project.buildDir}/outputs/channels")
|
||||
// 定制渠道包的APK的文件名称
|
||||
apkFileNameFormat = '${appName}-${packageName}-${channel}-${buildType}-v${versionName}-${versionCode}-${buildTime}.apk'
|
||||
// 渠道配置文件
|
||||
channelFile = new File("${project.getProjectDir()}/channel")
|
||||
}
|
||||
276
android/app/proguard-rules.pro
vendored
276
android/app/proguard-rules.pro
vendored
@@ -1,276 +0,0 @@
|
||||
#=========================================基础不变的混淆配置=========================================##
|
||||
#指定代码的压缩级别
|
||||
-optimizationpasses 5
|
||||
#包名不混合大小写
|
||||
-dontusemixedcaseclassnames
|
||||
#不去忽略非公共的库类
|
||||
-dontskipnonpubliclibraryclasses
|
||||
# 指定不去忽略非公共的库的类的成员
|
||||
-dontskipnonpubliclibraryclassmembers
|
||||
#优化 不优化输入的类文件
|
||||
-dontoptimize
|
||||
#预校验
|
||||
-dontpreverify
|
||||
#混淆时是否记录日志
|
||||
-verbose
|
||||
# 混淆时所采用的算法
|
||||
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
|
||||
#保护注解
|
||||
-keepattributes *Annotation*
|
||||
#忽略警告
|
||||
-ignorewarnings
|
||||
|
||||
##记录生成的日志数据,gradle build时在本项目根目录输出##
|
||||
#apk 包内所有 class 的内部结构
|
||||
-dump class_files.txt
|
||||
#未混淆的类和成员
|
||||
-printseeds seeds.txt
|
||||
#列出从 apk 中删除的代码
|
||||
-printusage unused.txt
|
||||
#混淆前后的映射
|
||||
-printmapping mapping.txt
|
||||
# 并保留源文件名为"Proguard"字符串,而非原始的类名 并保留行号
|
||||
-keepattributes SourceFile,LineNumberTable
|
||||
########记录生成的日志数据,gradle build时 在本项目根目录输出-end#####
|
||||
|
||||
#需要保留的东西
|
||||
# 保持哪些类不被混淆
|
||||
-keep public class * extends android.app.Fragment
|
||||
-keep public class * extends android.app.Activity
|
||||
-keep public class * extends android.app.Application
|
||||
-keep public class * extends android.app.Service
|
||||
-keep public class * extends android.content.BroadcastReceiver
|
||||
-keep public class * extends android.content.ContentProvider
|
||||
-keep public class * extends android.app.backup.BackupAgentHelper
|
||||
-keep public class * extends android.preference.Preference
|
||||
-keep public class * extends android.support.v4.**
|
||||
-keep public class com.android.vending.licensing.ILicensingService
|
||||
|
||||
#如果有引用v4包可以添加下面这行
|
||||
-keep public class * extends android.support.v4.app.Fragment
|
||||
|
||||
##########JS接口类不混淆,否则执行不了
|
||||
-dontwarn com.android.JsInterface.**
|
||||
-keep class com.android.JsInterface.** {*; }
|
||||
|
||||
#极光推送和百度lbs android sdk一起使用proguard 混淆的问题#http的类被混淆后,导致apk定位失败,保持apache 的http类不被混淆就好了
|
||||
-dontwarn org.apache.**
|
||||
-keep class org.apache.**{ *; }
|
||||
|
||||
-keep public class * extends android.view.View {
|
||||
public <init>(android.content.Context);
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||
public void set*(...);
|
||||
}
|
||||
|
||||
#保持 native 方法不被混淆
|
||||
-keepclasseswithmembernames class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
#保持自定义控件类不被混淆
|
||||
-keepclasseswithmembers class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
}
|
||||
|
||||
#保持自定义控件类不被混淆
|
||||
-keepclassmembers class * extends android.app.Activity {
|
||||
public void *(android.view.View);
|
||||
}
|
||||
|
||||
#保持 Parcelable 不被混淆
|
||||
-keep class * implements android.os.Parcelable {
|
||||
public static final android.os.Parcelable$Creator *;
|
||||
}
|
||||
|
||||
#保持 Serializable 不被混淆
|
||||
-keepnames class * implements java.io.Serializable
|
||||
|
||||
#保持 Serializable 不被混淆并且enum 类也不被混淆
|
||||
-keepclassmembers class * implements java.io.Serializable {
|
||||
static final long serialVersionUID;
|
||||
private static final java.io.ObjectStreamField[] serialPersistentFields;
|
||||
!static !transient <fields>;
|
||||
!private <fields>;
|
||||
!private <methods>;
|
||||
private void writeObject(java.io.ObjectOutputStream);
|
||||
private void readObject(java.io.ObjectInputStream);
|
||||
java.lang.Object writeReplace();
|
||||
java.lang.Object readResolve();
|
||||
}
|
||||
|
||||
#保持枚举 enum 类不被混淆 如果混淆报错,建议直接使用上面的 -keepclassmembers class * implements java.io.Serializable即可
|
||||
-keepclassmembers enum * {
|
||||
public static **[] values();
|
||||
public static ** valueOf(java.lang.String);
|
||||
}
|
||||
|
||||
-keepclassmembers class * {
|
||||
public void *ButtonClicked(android.view.View);
|
||||
}
|
||||
|
||||
#不混淆资源类
|
||||
-keep class **.R$* {*;}
|
||||
|
||||
#===================================混淆保护自己项目的部分代码以及引用的第三方jar包library=============================#######
|
||||
#如果引用了v4或者v7包
|
||||
-dontwarn android.support.**
|
||||
|
||||
|
||||
# AndroidX 防止混淆
|
||||
-dontwarn com.google.android.material.**
|
||||
-dontnote com.google.android.material.**
|
||||
-dontwarn androidx.**
|
||||
-keep class com.google.android.material.** {*;}
|
||||
-keep class androidx.** {*;}
|
||||
-keep public class * extends androidx.**
|
||||
-keep interface androidx.** {*;}
|
||||
-keepclassmembers class * {
|
||||
@androidx.annotation.Keep *;
|
||||
}
|
||||
|
||||
# zxing
|
||||
-dontwarn com.google.zxing.**
|
||||
-keep class com.google.zxing.**{*;}
|
||||
|
||||
#SignalR推送
|
||||
-keep class microsoft.aspnet.signalr.** { *; }
|
||||
|
||||
# 极光推送混淆
|
||||
-dontoptimize
|
||||
-dontpreverify
|
||||
-dontwarn cn.jpush.**
|
||||
-keep class cn.jpush.** { *; }
|
||||
-dontwarn cn.jiguang.**
|
||||
-keep class cn.jiguang.** { *; }
|
||||
|
||||
# 数据库框架OrmLite
|
||||
-keepattributes *DatabaseField*
|
||||
-keepattributes *DatabaseTable*
|
||||
-keepattributes *SerializedName*
|
||||
-keep class com.j256.**
|
||||
-keepclassmembers class com.j256.** { *; }
|
||||
-keep enum com.j256.**
|
||||
-keepclassmembers enum com.j256.** { *; }
|
||||
-keep interface com.j256.**
|
||||
-keepclassmembers interface com.j256.** { *; }
|
||||
|
||||
#XHttp2
|
||||
-keep class com.xuexiang.xhttp2.model.** { *; }
|
||||
-keep class com.xuexiang.xhttp2.cache.model.** { *; }
|
||||
-keep class com.xuexiang.xhttp2.cache.stategy.**{*;}
|
||||
-keep class com.xuexiang.xhttp2.annotation.** { *; }
|
||||
|
||||
#okhttp
|
||||
-dontwarn com.squareup.okhttp3.**
|
||||
-keep class com.squareup.okhttp3.** { *;}
|
||||
-dontwarn okio.**
|
||||
-dontwarn javax.annotation.Nullable
|
||||
-dontwarn javax.annotation.ParametersAreNonnullByDefault
|
||||
-dontwarn javax.annotation.**
|
||||
|
||||
#如果用到Gson解析包的,直接添加下面这几行就能成功混淆,不然会报错
|
||||
-keepattributes Signature
|
||||
-keep class com.google.gson.stream.** { *; }
|
||||
-keepattributes EnclosingMethod
|
||||
-keep class org.xz_sale.entity.**{*;}
|
||||
-keep class com.google.gson.** {*;}
|
||||
-keep class com.google.**{*;}
|
||||
-keep class sun.misc.Unsafe { *; }
|
||||
-keep class com.google.gson.stream.** { *; }
|
||||
-keep class com.google.gson.examples.android.model.** { *; }
|
||||
|
||||
# Glide
|
||||
-keep public class * implements com.bumptech.glide.module.GlideModule
|
||||
-keep public class * extends com.bumptech.glide.module.AppGlideModule
|
||||
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
|
||||
**[] $VALUES;
|
||||
public *;
|
||||
}
|
||||
|
||||
# Retrofit
|
||||
-dontwarn retrofit2.**
|
||||
-keep class retrofit2.** { *; }
|
||||
-keepattributes Exceptions
|
||||
|
||||
# RxJava RxAndroid
|
||||
-dontwarn sun.misc.**
|
||||
-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
|
||||
long producerIndex;
|
||||
long consumerIndex;
|
||||
}
|
||||
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
|
||||
rx.internal.util.atomic.LinkedQueueNode producerNode;
|
||||
}
|
||||
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
|
||||
rx.internal.util.atomic.LinkedQueueNode consumerNode;
|
||||
}
|
||||
|
||||
-dontwarn okio.**
|
||||
-dontwarn javax.annotation.Nullable
|
||||
-dontwarn javax.annotation.ParametersAreNonnullByDefault
|
||||
-dontwarn javax.annotation.**
|
||||
|
||||
# fastjson
|
||||
-dontwarn com.alibaba.fastjson.**
|
||||
-keep class com.alibaba.fastjson.** { *; }
|
||||
-keepattributes Signature
|
||||
|
||||
# xpage
|
||||
-keep class com.xuexiang.xpage.annotation.** { *; }
|
||||
-keep class com.xuexiang.xpage.config.** { *; }
|
||||
|
||||
# xaop
|
||||
-keep @com.xuexiang.xaop.annotation.* class * {*;}
|
||||
-keep @org.aspectj.lang.annotation.* class * {*;}
|
||||
-keep class * {
|
||||
@com.xuexiang.xaop.annotation.* <fields>;
|
||||
@org.aspectj.lang.annotation.* <fields>;
|
||||
}
|
||||
-keepclassmembers class * {
|
||||
@com.xuexiang.xaop.annotation.* <methods>;
|
||||
@org.aspectj.lang.annotation.* <methods>;
|
||||
}
|
||||
|
||||
# xrouter
|
||||
-keep public class com.xuexiang.xrouter.routes.**{*;}
|
||||
-keep class * implements com.xuexiang.xrouter.facade.template.ISyringe{*;}
|
||||
# 如果使用了 byType 的方式获取 Service,需添加下面规则,保护接口
|
||||
-keep interface * implements com.xuexiang.xrouter.facade.template.IProvider
|
||||
# 如果使用了 单类注入,即不定义接口实现 IProvider,需添加下面规则,保护实现
|
||||
-keep class * implements com.xuexiang.xrouter.facade.template.IProvider
|
||||
|
||||
# xupdate
|
||||
-keep class com.xuexiang.xupdate.entity.** { *; }
|
||||
|
||||
# xvideo
|
||||
-keep class com.xuexiang.xvideo.jniinterface.** { *; }
|
||||
|
||||
# xipc
|
||||
-keep @com.xuexiang.xipc.annotation.* class * {*;}
|
||||
-keep class * {
|
||||
@com.xuexiang.xipc.annotation.* <fields>;
|
||||
}
|
||||
-keepclassmembers class * {
|
||||
@com.xuexiang.xipc.annotation.* <methods>;
|
||||
}
|
||||
|
||||
# umeng统计
|
||||
-keep class com.umeng.** {*;}
|
||||
-keepclassmembers class * {
|
||||
public <init> (org.json.JSONObject);
|
||||
}
|
||||
-keepclassmembers enum * {
|
||||
public static **[] values();
|
||||
public static ** valueOf(java.lang.String);
|
||||
}
|
||||
|
||||
-keep class com.xuexiang.xui.widget.edittext.materialedittext.** { *; }
|
||||
|
||||
## 接口请求使用了gson序列化的对象
|
||||
-keep class com.kerwin.wumei.entity.** { *; }
|
||||
-keep class com.kerwin.wumei.entity.vo.** { *; }
|
||||
-keep class com.kerwin.wumei.entity.bo.** { *; }
|
||||
-keep class com.kerwin.wumei.http.request.** { *; }
|
||||
-keep class com.kerwin.wumei.http.** { *; }
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented 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() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
|
||||
assertEquals("com.kerwin.wumei", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.kerwin.wumei">
|
||||
|
||||
<!--进程杀死-->
|
||||
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
|
||||
<application
|
||||
android:name="com.kerwin.wumei.MyApp"
|
||||
android:allowBackup="false"
|
||||
android:configChanges="screenSize|keyboardHidden|orientation|keyboard"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme"
|
||||
android:windowSoftInputMode="adjustPan|stateHidden"
|
||||
tools:ignore="LockedOrientationActivity"
|
||||
tools:targetApi="n">
|
||||
|
||||
<activity
|
||||
android:name="com.kerwin.wumei.activity.SplashActivity"
|
||||
android:configChanges="screenSize|keyboardHidden|orientation|keyboard"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.Launch.App"
|
||||
android:windowSoftInputMode="adjustPan|stateHidden">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name="com.kerwin.wumei.activity.MainActivity"
|
||||
android:configChanges="screenSize|keyboardHidden|orientation|keyboard"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme"
|
||||
android:windowSoftInputMode="adjustPan|stateHidden" />
|
||||
<activity
|
||||
android:name="com.kerwin.wumei.activity.LoginActivity"
|
||||
android:configChanges="screenSize|keyboardHidden|orientation|keyboard"
|
||||
android:launchMode="singleInstance"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="adjustPan|stateHidden" />
|
||||
<activity
|
||||
android:name="com.kerwin.wumei.activity.AddDeviceActivity"
|
||||
android:configChanges="screenSize|keyboardHidden|orientation|keyboard"
|
||||
android:screenOrientation="portrait"
|
||||
android:launchMode="singleInstance"
|
||||
android:theme="@style/AppTheme"
|
||||
android:windowSoftInputMode="adjustPan|stateHidden" />
|
||||
|
||||
<!--通用浏览器-->
|
||||
<activity
|
||||
android:name="com.kerwin.wumei.core.webview.AgentWebActivity"
|
||||
android:configChanges="screenSize|keyboardHidden|orientation|keyboard"
|
||||
android:hardwareAccelerated="true"
|
||||
android:label="@string/app_browser_name"
|
||||
android:theme="@style/AppTheme">
|
||||
<!-- Scheme -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="com.xuexiang.xui.applink" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="http" />
|
||||
<data android:scheme="https" />
|
||||
<data android:scheme="about" />
|
||||
<data android:scheme="javascript" />
|
||||
<!-- 设置自己的deeplink -->
|
||||
<!-- <data-->
|
||||
<!-- android:host="xxx.com"-->
|
||||
<!-- android:scheme="xui"/>-->
|
||||
</intent-filter>
|
||||
<!-- AppLink -->
|
||||
<intent-filter
|
||||
android:autoVerify="true"
|
||||
tools:targetApi="m">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
||||
<data android:scheme="http" />
|
||||
<data android:scheme="https" />
|
||||
<data android:scheme="inline" />
|
||||
<data android:mimeType="text/html" />
|
||||
<data android:mimeType="text/plain" />
|
||||
<data android:mimeType="application/xhtml+xml" />
|
||||
<data android:mimeType="application/vnd.wap.xhtml+xml" />
|
||||
<!-- 设置自己的applink -->
|
||||
<!-- <data-->
|
||||
<!-- android:host="xxx.com"-->
|
||||
<!-- android:scheme="http"/>-->
|
||||
<!-- <data-->
|
||||
<!-- android:host="xxx.com"-->
|
||||
<!-- android:scheme="https"/>-->
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!--fragment的页面容器-->
|
||||
<activity
|
||||
android:name="com.kerwin.wumei.core.BaseActivity"
|
||||
android:configChanges="screenSize|keyboardHidden|orientation|keyboard"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="adjustPan|stateHidden" />
|
||||
<!-- 版本更新提示-->
|
||||
<activity
|
||||
android:name="com.kerwin.wumei.utils.update.UpdateTipDialog"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/DialogTheme" />
|
||||
<!-- Webview拦截提示弹窗-->
|
||||
<activity
|
||||
android:name="com.kerwin.wumei.core.webview.WebViewInterceptDialog"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/DialogTheme" />
|
||||
<!-- applink的中转页面 -->
|
||||
<activity
|
||||
android:name="com.kerwin.wumei.core.XPageTransferActivity"
|
||||
android:configChanges="screenSize|keyboardHidden|orientation|keyboard"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="adjustPan|stateHidden" />
|
||||
|
||||
<!--屏幕自适应设计图-->
|
||||
<meta-data
|
||||
android:name="design_width_in_dp"
|
||||
android:value="360" />
|
||||
<meta-data
|
||||
android:name="design_height_in_dp"
|
||||
android:value="640" />
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"Code": 0,
|
||||
"Data": [
|
||||
{
|
||||
"title": "微信公众号",
|
||||
"content": "<a href=\"http://www.wumei.live\">获取更多资讯内容,欢迎微信搜索公众号:「我的Android开源之旅」</a>"
|
||||
},
|
||||
{
|
||||
"title": "关于作者",
|
||||
"content": "点击关注作者,了解最新动态!<br /><a href=\"https://gitee.com/kerwincui/wumei-smart\"><font color=\"#800080\">Gitee</font></a><br />"
|
||||
},
|
||||
{
|
||||
"title": "QQ交流群",
|
||||
"content": "<a href=\"https://qm.qq.com/cgi-bin/qm/qr?k=P_oc91N6KC39zp2PEV_-BY3xMnAokeZ8\">物美智能交流群</a><br />"
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 31 KiB |
@@ -1,115 +0,0 @@
|
||||
package com.kerwin.wumei;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.location.LocationManager;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.multidex.MultiDex;
|
||||
|
||||
import com.kerwin.wumei.utils.sdkinit.ANRWatchDogInit;
|
||||
import com.kerwin.wumei.utils.sdkinit.UMengInit;
|
||||
import com.kerwin.wumei.utils.sdkinit.XBasicLibInit;
|
||||
import com.kerwin.wumei.utils.sdkinit.XUpdateInit;
|
||||
|
||||
/**
|
||||
* @author xuexiang
|
||||
* @since 2018/11/7 下午1:12
|
||||
*/
|
||||
public class MyApp extends Application {
|
||||
|
||||
private static MyApp app;
|
||||
private MutableLiveData<String> mBroadcastData;
|
||||
|
||||
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (action == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
case WifiManager.NETWORK_STATE_CHANGED_ACTION:
|
||||
case LocationManager.PROVIDERS_CHANGED_ACTION:
|
||||
mBroadcastData.setValue(action);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void attachBaseContext(Context base) {
|
||||
super.attachBaseContext(base);
|
||||
//解决4.x运行崩溃的问题
|
||||
MultiDex.install(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
initLibs();
|
||||
app = this;
|
||||
mBroadcastData = new MutableLiveData<>();
|
||||
IntentFilter filter = new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
filter.addAction(LocationManager.PROVIDERS_CHANGED_ACTION);
|
||||
}
|
||||
registerReceiver(mReceiver, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTerminate() {
|
||||
super.onTerminate();
|
||||
unregisterReceiver(mReceiver);
|
||||
}
|
||||
|
||||
public static MyApp getInstance() {
|
||||
return app;
|
||||
}
|
||||
|
||||
public void observeBroadcast(LifecycleOwner owner, Observer<String> observer) {
|
||||
mBroadcastData.observe(owner, observer);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 初始化基础库
|
||||
*/
|
||||
private void initLibs() {
|
||||
XBasicLibInit.init(this);
|
||||
|
||||
XUpdateInit.init(this);
|
||||
|
||||
//运营统计数据运行时不初始化
|
||||
if (!MyApp.isDebug()) {
|
||||
UMengInit.init(this);
|
||||
}
|
||||
|
||||
//ANR监控
|
||||
ANRWatchDogInit.init();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return 当前app是否是调试开发模式
|
||||
*/
|
||||
public static boolean isDebug() {
|
||||
return BuildConfig.DEBUG;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,384 +0,0 @@
|
||||
|
||||
package com.kerwin.wumei.activity;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.location.LocationManager;
|
||||
import android.net.wifi.ScanResult;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.location.LocationManagerCompat;
|
||||
|
||||
import com.espressif.iot.esptouch.EsptouchTask;
|
||||
import com.espressif.iot.esptouch.IEsptouchResult;
|
||||
import com.espressif.iot.esptouch.IEsptouchTask;
|
||||
import com.espressif.iot.esptouch.util.ByteUtil;
|
||||
import com.espressif.iot.esptouch.util.TouchNetUtil;
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.adapter.entity.EspTouchViewModel;
|
||||
import com.kerwin.wumei.core.BaseActivity;
|
||||
import com.kerwin.wumei.fragment.device.AddDeviceFragment;
|
||||
import com.kerwin.wumei.utils.NetUtils;
|
||||
import com.xuexiang.xui.utils.KeyboardUtils;
|
||||
import com.xuexiang.xui.utils.StatusBarUtils;
|
||||
import com.xuexiang.xutil.display.Colors;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class AddDeviceActivity extends BaseActivity {
|
||||
|
||||
// begin esptouch -------------------------------------
|
||||
private static final String TAG = AddDeviceActivity.class.getSimpleName();
|
||||
private static final int REQUEST_PERMISSION = 0x01;
|
||||
private EspTouchViewModel mViewModel;
|
||||
private EsptouchAsyncTask4 mTask;
|
||||
private WifiManager mWifiManager;
|
||||
private List<String> ssids;
|
||||
private String selectedSSID;
|
||||
|
||||
public String GetSelectedSSID(){
|
||||
return selectedSSID;
|
||||
}
|
||||
public List<String> GetSsids(){
|
||||
return ssids;
|
||||
}
|
||||
public EspTouchViewModel GetMViewModel(){
|
||||
return mViewModel;
|
||||
}
|
||||
|
||||
private AddDeviceFragment addDeviceFragment;
|
||||
private IEsptouchTask mEsptouchTask;
|
||||
|
||||
|
||||
public void executeEsptouch() {
|
||||
EspTouchViewModel viewModel = mViewModel;
|
||||
// byte[] ssid = viewModel.ssidBytes == null ? ByteUtil.getBytesByString(viewModel.ssid): viewModel.ssidBytes;
|
||||
CharSequence ssidStr=mViewModel.ssidSpinner.getText();
|
||||
byte[] ssid= ByteUtil.getBytesByString(ssidStr.toString());
|
||||
CharSequence pwdStr = mViewModel.apPasswordEdit.getText();
|
||||
byte[] password = pwdStr == null ? null : ByteUtil.getBytesByString(pwdStr.toString());
|
||||
byte[] bssid = TouchNetUtil.parseBssid2bytes(viewModel.bssid);
|
||||
byte[] broadcast = {(byte) (mViewModel.packageModeGroup.getCheckedRadioButtonId() == R.id.packageBroadcast? 1 : 0)};
|
||||
int count = mViewModel.xsbDeviceCount.getSelectedNumber();
|
||||
byte[] deviceCount = String.valueOf(count).getBytes();
|
||||
if (mTask != null) {
|
||||
mTask.cancelEsptouch();
|
||||
}
|
||||
mTask = new EsptouchAsyncTask4(this);
|
||||
mTask.execute(ssid, bssid, password, deviceCount, broadcast);
|
||||
}
|
||||
|
||||
public void onWifiChanged() {
|
||||
StateResult stateResult = check();
|
||||
mViewModel.message = stateResult.message;
|
||||
mViewModel.ssid = stateResult.ssid;
|
||||
mViewModel.ssidBytes = stateResult.ssidBytes;
|
||||
mViewModel.bssid = stateResult.bssid;
|
||||
mViewModel.confirmEnable = false;
|
||||
if (stateResult.wifiConnected) {
|
||||
mViewModel.confirmEnable = true;
|
||||
if (stateResult.is5G) {
|
||||
mViewModel.message = getString(R.string.esptouch1_wifi_5g_message);
|
||||
}
|
||||
} else {
|
||||
if (mTask != null) {
|
||||
mTask.cancelEsptouch();
|
||||
mTask = null;
|
||||
new AlertDialog.Builder(AddDeviceActivity.this)
|
||||
.setMessage(R.string.esptouch1_configure_wifi_change_message)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
mViewModel.invalidateAll();
|
||||
}
|
||||
|
||||
protected static class StateResult {
|
||||
public CharSequence message = null;
|
||||
public boolean permissionGranted = false;
|
||||
public boolean locationRequirement = false;
|
||||
public boolean wifiConnected = false;
|
||||
public boolean is5G = false;
|
||||
public InetAddress address = null;
|
||||
public String ssid = null;
|
||||
public byte[] ssidBytes = null;
|
||||
public String bssid = null;
|
||||
}
|
||||
|
||||
private StateResult check() {
|
||||
StateResult result = checkPermission();
|
||||
if (!result.permissionGranted) {
|
||||
return result;
|
||||
}
|
||||
result = checkLocation();
|
||||
result.permissionGranted = true;
|
||||
if (result.locationRequirement) {
|
||||
return result;
|
||||
}
|
||||
result = checkWifi();
|
||||
result.permissionGranted = true;
|
||||
result.locationRequirement = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
protected StateResult checkWifi() {
|
||||
StateResult result = new StateResult();
|
||||
result.wifiConnected = false;
|
||||
WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
|
||||
|
||||
// 获取wifi列表
|
||||
mWifiManager.startScan();
|
||||
List<ScanResult> scanWifiList = mWifiManager.getScanResults();
|
||||
List<ScanResult> wifiList = new ArrayList<>();
|
||||
ssids=new ArrayList<>();
|
||||
if (scanWifiList != null && scanWifiList.size() > 0) {
|
||||
HashMap<String, Integer> signalStrength = new HashMap<String, Integer>();
|
||||
for (int i = 0; i < scanWifiList.size(); i++) {
|
||||
ScanResult scanResult = scanWifiList.get(i);
|
||||
Log.e(TAG, "搜索的wifi-ssid:" + scanResult.SSID);
|
||||
if (!scanResult.SSID.isEmpty()) {
|
||||
String key = scanResult.SSID + " " + scanResult.capabilities;
|
||||
if (!signalStrength.containsKey(key)) {
|
||||
signalStrength.put(key, i);
|
||||
wifiList.add(scanResult);
|
||||
ssids.add(scanResult.SSID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean connected = NetUtils.isWifiConnected(mWifiManager);
|
||||
if (!connected) {
|
||||
result.message = getString(R.string.esptouch_message_wifi_connection);
|
||||
return result;
|
||||
}
|
||||
|
||||
String ssid = NetUtils.getSsidString(wifiInfo);
|
||||
selectedSSID=ssid;
|
||||
int ipValue = wifiInfo.getIpAddress();
|
||||
if (ipValue != 0) {
|
||||
result.address = NetUtils.getAddress(wifiInfo.getIpAddress());
|
||||
} else {
|
||||
result.address = NetUtils.getIPv4Address();
|
||||
if (result.address == null) {
|
||||
result.address = NetUtils.getIPv6Address();
|
||||
}
|
||||
}
|
||||
|
||||
result.wifiConnected = true;
|
||||
result.message = "";
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
result.is5G = NetUtils.is5G(wifiInfo.getFrequency());
|
||||
}
|
||||
if (result.is5G) {
|
||||
result.message = getString(R.string.esptouch_message_wifi_frequency);
|
||||
}
|
||||
result.ssid = ssid;
|
||||
result.ssidBytes = NetUtils.getRawSsidBytesOrElse(wifiInfo, ssid.getBytes());
|
||||
result.bssid = wifiInfo.getBSSID();
|
||||
return result;
|
||||
}
|
||||
|
||||
protected StateResult checkLocation() {
|
||||
StateResult result = new StateResult();
|
||||
result.locationRequirement = true;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
LocationManager manager = getSystemService(LocationManager.class);
|
||||
boolean enable = manager != null && LocationManagerCompat.isLocationEnabled(manager);
|
||||
if (!enable) {
|
||||
result.message = getString(R.string.esptouch_message_location);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
result.locationRequirement = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
protected StateResult checkPermission() {
|
||||
StateResult result = new StateResult();
|
||||
result.permissionGranted = false;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
boolean locationGranted = checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
|
||||
== PackageManager.PERMISSION_GRANTED;
|
||||
if (!locationGranted) {
|
||||
String[] splits = getString(R.string.esptouch_message_permission).split("\n");
|
||||
if (splits.length != 2) {
|
||||
throw new IllegalArgumentException("Invalid String @RES esptouch_message_permission");
|
||||
}
|
||||
SpannableStringBuilder ssb = new SpannableStringBuilder(splits[0]);
|
||||
ssb.append('\n');
|
||||
SpannableString clickMsg = new SpannableString(splits[1]);
|
||||
ForegroundColorSpan clickSpan = new ForegroundColorSpan(0xFF0022FF);
|
||||
clickMsg.setSpan(clickSpan, 0, clickMsg.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
ssb.append(clickMsg);
|
||||
result.message = ssb;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
result.permissionGranted = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
if (requestCode == REQUEST_PERMISSION) {
|
||||
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
onWifiChanged();
|
||||
} else {
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle(R.string.esptouch1_location_permission_title)
|
||||
.setMessage(R.string.esptouch1_location_permission_message)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> finish())
|
||||
.show();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
/**
|
||||
* 中断配网任务
|
||||
*/
|
||||
public void interruptEspTouchTask(){
|
||||
if (mEsptouchTask != null) {
|
||||
mEsptouchTask.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
public class EsptouchAsyncTask4 extends AsyncTask<byte[], IEsptouchResult, List<IEsptouchResult>> {
|
||||
private WeakReference<AddDeviceActivity> mActivity;
|
||||
private final Object mLock = new Object();
|
||||
|
||||
|
||||
EsptouchAsyncTask4(AddDeviceActivity activity) {
|
||||
mActivity = new WeakReference<>(activity);
|
||||
}
|
||||
|
||||
public void cancelEsptouch() {
|
||||
cancel(true);
|
||||
if (mEsptouchTask != null) {
|
||||
mEsptouchTask.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
addDeviceFragment = (AddDeviceFragment) getSupportFragmentManager().getFragments().get(0);
|
||||
addDeviceFragment.beginCounter();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onProgressUpdate(IEsptouchResult... values) {
|
||||
Context context = mActivity.get();
|
||||
if (context != null) {
|
||||
IEsptouchResult result = values[0];
|
||||
Log.i(TAG, "EspTouchResult: " + result);
|
||||
String text = result.getBssid() + " is connected to the wifi";
|
||||
Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<IEsptouchResult> doInBackground(byte[]... params) {
|
||||
AddDeviceActivity activity = mActivity.get();
|
||||
int taskResultCount;
|
||||
synchronized (mLock) {
|
||||
byte[] apSsid = params[0];
|
||||
byte[] apBssid = params[1];
|
||||
byte[] apPassword = params[2];
|
||||
byte[] deviceCountData = params[3];
|
||||
byte[] broadcastData = params[4];
|
||||
taskResultCount = deviceCountData.length == 0 ? -1 : Integer.parseInt(new String(deviceCountData));
|
||||
Context context = activity.getApplicationContext();
|
||||
mEsptouchTask = new EsptouchTask(apSsid, apBssid, apPassword, context);
|
||||
mEsptouchTask.setPackageBroadcast(broadcastData[0] == 1);
|
||||
mEsptouchTask.setEsptouchListener(this::publishProgress);
|
||||
}
|
||||
return mEsptouchTask.executeForResults(taskResultCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(List<IEsptouchResult> result) {
|
||||
AddDeviceActivity activity = mActivity.get();
|
||||
activity.mTask = null;
|
||||
if (result == null) {
|
||||
addDeviceFragment.showMessage("建立 EspTouch 任务失败, 端口可能被其他程序占用",false);
|
||||
addDeviceFragment.cancleCounter();
|
||||
return;
|
||||
}
|
||||
|
||||
// check whether the task is cancelled and no results received
|
||||
IEsptouchResult firstResult = result.get(0);
|
||||
if (firstResult.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!firstResult.isSuc()) {
|
||||
addDeviceFragment.showMessage("配网失败",false);
|
||||
addDeviceFragment.cancleCounter();
|
||||
return;
|
||||
}
|
||||
|
||||
String message="";
|
||||
for (IEsptouchResult touchResult : result) {
|
||||
message += "BSSID: "+touchResult.getBssid()+"\n 地址: "+touchResult.getInetAddress().getHostAddress()+"\n";
|
||||
}
|
||||
|
||||
addDeviceFragment.completeCounter();
|
||||
addDeviceFragment.showMessage("完成配网\n"+message,true);
|
||||
}
|
||||
}
|
||||
|
||||
// end esptouch ----------------------------------------
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mWifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
|
||||
mViewModel = new EspTouchViewModel();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSupportSlideBack() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initStatusBarStyle() {
|
||||
StatusBarUtils.initStatusBarStyle(this, false, Colors.WHITE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
return KeyboardUtils.onDisableBackKeyDown(keyCode) && super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
|
||||
package com.kerwin.wumei.activity;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import com.kerwin.wumei.core.BaseActivity;
|
||||
import com.kerwin.wumei.fragment.LoginFragment;
|
||||
import com.kerwin.wumei.fragment.device.DeviceDetailFragment;
|
||||
import com.xuexiang.xui.utils.KeyboardUtils;
|
||||
import com.xuexiang.xui.utils.StatusBarUtils;
|
||||
import com.xuexiang.xutil.display.Colors;
|
||||
|
||||
|
||||
public class LoginActivity extends BaseActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
openPage(LoginFragment.class, getIntent().getExtras());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSupportSlideBack() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initStatusBarStyle() {
|
||||
StatusBarUtils.initStatusBarStyle(this, false, Colors.WHITE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
return KeyboardUtils.onDisableBackKeyDown(keyCode) && super.onKeyDown(keyCode, event);
|
||||
}
|
||||
}
|
||||
@@ -1,380 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.activity;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.location.LocationManager;
|
||||
import android.net.wifi.ScanResult;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.appcompat.app.ActionBarDrawerToggle;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.location.LocationManagerCompat;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.kerwin.wumei.entity.User;
|
||||
import com.kerwin.wumei.fragment.profile.AccountFragment;
|
||||
import com.kerwin.wumei.http.callback.TipRequestCallBack;
|
||||
import com.kerwin.wumei.http.request.UserInfoApiResult;
|
||||
import com.kerwin.wumei.utils.sdkinit.XUpdateInit;
|
||||
|
||||
import com.espressif.iot.esptouch.EsptouchTask;
|
||||
import com.espressif.iot.esptouch.IEsptouchResult;
|
||||
import com.espressif.iot.esptouch.IEsptouchTask;
|
||||
import com.espressif.iot.esptouch.util.ByteUtil;
|
||||
import com.espressif.iot.esptouch.util.TouchNetUtil;
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||
import com.google.android.material.navigation.NavigationView;
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.adapter.entity.EspTouchViewModel;
|
||||
import com.kerwin.wumei.core.BaseActivity;
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.kerwin.wumei.fragment.AboutFragment;
|
||||
import com.kerwin.wumei.fragment.FeedbackFragment;
|
||||
import com.kerwin.wumei.fragment.MessageFragment;
|
||||
import com.kerwin.wumei.fragment.SettingsFragment;
|
||||
import com.kerwin.wumei.fragment.device.AddDeviceFragment;
|
||||
import com.kerwin.wumei.fragment.device.GroupFragment;
|
||||
import com.kerwin.wumei.fragment.device.SceneFragment;
|
||||
import com.kerwin.wumei.fragment.device.ShareDeviceFragment;
|
||||
import com.kerwin.wumei.fragment.news.HomePageFragment;
|
||||
import com.kerwin.wumei.fragment.news.NewsFragment;
|
||||
import com.kerwin.wumei.fragment.profile.ProfileFragment;
|
||||
import com.kerwin.wumei.fragment.device.DeviceFragment;
|
||||
import com.kerwin.wumei.utils.NetUtils;
|
||||
import com.kerwin.wumei.utils.Utils;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.kerwin.wumei.widget.GuideTipsDialog;
|
||||
import com.xuexiang.xaop.annotation.SingleClick;
|
||||
import com.xuexiang.xhttp2.XHttp;
|
||||
import com.xuexiang.xhttp2.callback.CallBackProxy;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xpage.core.PageOption;
|
||||
import com.xuexiang.xpage.enums.CoreAnim;
|
||||
import com.xuexiang.xui.adapter.FragmentAdapter;
|
||||
import com.xuexiang.xui.adapter.simple.AdapterItem;
|
||||
import com.xuexiang.xui.utils.ResUtils;
|
||||
import com.xuexiang.xui.utils.ThemeUtils;
|
||||
import com.xuexiang.xui.widget.imageview.RadiusImageView;
|
||||
import com.xuexiang.xui.widget.popupwindow.popup.XUISimplePopup;
|
||||
import com.xuexiang.xutil.XUtil;
|
||||
import com.xuexiang.xutil.common.ClickUtils;
|
||||
import com.xuexiang.xutil.common.CollectionUtils;
|
||||
import com.xuexiang.xutil.display.Colors;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
import static com.kerwin.wumei.utils.SettingUtils.getServerPath;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.clearToken;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.getToken;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.hasToken;
|
||||
|
||||
public class MainActivity extends BaseActivity implements View.OnClickListener, ViewPager.OnPageChangeListener, BottomNavigationView.OnNavigationItemSelectedListener, ClickUtils.OnClick2ExitListener, Toolbar.OnMenuItemClickListener {
|
||||
|
||||
@BindView(R.id.toolbar)
|
||||
Toolbar toolbar;
|
||||
@BindView(R.id.view_pager)
|
||||
ViewPager viewPager;
|
||||
/**
|
||||
* 底部导航栏
|
||||
*/
|
||||
@BindView(R.id.bottom_navigation)
|
||||
BottomNavigationView bottomNavigation;
|
||||
/**
|
||||
* 侧边栏
|
||||
*/
|
||||
@BindView(R.id.nav_view)
|
||||
NavigationView navView;
|
||||
@BindView(R.id.drawer_layout)
|
||||
DrawerLayout drawerLayout;
|
||||
|
||||
private String[] mTitles;
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_main;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
initViews();
|
||||
// initData();
|
||||
initListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSupportSlideBack() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void initViews() {
|
||||
mTitles = ResUtils.getStringArray(R.array.home_titles);
|
||||
toolbar.setTitle(mTitles[0]);
|
||||
toolbar.inflateMenu(R.menu.menu_main);
|
||||
toolbar.setOnMenuItemClickListener(this);
|
||||
initHeader();
|
||||
|
||||
//主页内容填充
|
||||
BaseFragment[] fragments = new BaseFragment[]{
|
||||
new DeviceFragment(),
|
||||
new SceneFragment(),
|
||||
new HomePageFragment(),
|
||||
new ProfileFragment(),
|
||||
};
|
||||
FragmentAdapter<BaseFragment> adapter = new FragmentAdapter<>(getSupportFragmentManager(), fragments);
|
||||
viewPager.setOffscreenPageLimit(mTitles.length - 1);
|
||||
viewPager.setAdapter(adapter);
|
||||
|
||||
//显示提示
|
||||
// GuideTipsDialog.showTips(this);
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
GuideTipsDialog.showTips(this);
|
||||
XUpdateInit.checkUpdate(this, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 侧边栏头部
|
||||
*/
|
||||
private void initHeader() {
|
||||
navView.setItemIconTintList(null);
|
||||
View headerView = navView.getHeaderView(0);
|
||||
LinearLayout navHeader = headerView.findViewById(R.id.nav_header);
|
||||
RadiusImageView ivAvatar = headerView.findViewById(R.id.iv_avatar);
|
||||
TextView tvAvatar = headerView.findViewById(R.id.tv_avatar);
|
||||
TextView tvSign = headerView.findViewById(R.id.tv_sign);
|
||||
|
||||
if (Utils.isColorDark(ThemeUtils.resolveColor(this, R.attr.colorAccent))) {
|
||||
tvAvatar.setTextColor(Colors.WHITE);
|
||||
tvSign.setTextColor(Colors.WHITE);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
ivAvatar.setImageTintList(ResUtils.getColors(R.color.xui_config_color_white));
|
||||
}
|
||||
} else {
|
||||
tvAvatar.setTextColor(ThemeUtils.resolveColor(this, R.attr.xui_config_color_title_text));
|
||||
tvSign.setTextColor(ThemeUtils.resolveColor(this, R.attr.xui_config_color_explain_text));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
ivAvatar.setImageTintList(ResUtils.getColors(R.color.xui_config_color_gray_3));
|
||||
}
|
||||
}
|
||||
|
||||
// 绑定数据
|
||||
ivAvatar.setImageResource(R.drawable.ic_default_head);
|
||||
tvAvatar.setText("匿名用户");
|
||||
tvSign.setText("物美智能点亮智慧生活...");
|
||||
getUserInfo(tvAvatar,tvSign );
|
||||
navHeader.setOnClickListener(this);
|
||||
}
|
||||
|
||||
protected void initListeners() {
|
||||
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
|
||||
drawerLayout.addDrawerListener(toggle);
|
||||
toggle.syncState();
|
||||
|
||||
//侧边栏点击事件
|
||||
navView.setNavigationItemSelectedListener(menuItem -> {
|
||||
|
||||
switch (menuItem.getItemId()) {
|
||||
case R.id.nav_add_device:
|
||||
PageOption.to(AddDeviceFragment.class) //跳转的fragment
|
||||
.setAnim(CoreAnim.slide) //页面转场动画
|
||||
.setRequestCode(100) //请求码,用于返回结果
|
||||
.setAddToBackStack(true) //是否加入堆栈
|
||||
.setNewActivity(true, AddDeviceActivity.class) //是否使用新的Activity打开
|
||||
.open(this); //打开页面进行跳转
|
||||
break;
|
||||
case R.id.nav_about:
|
||||
openNewPage(AboutFragment.class);
|
||||
break;
|
||||
case R.id.nav_serve_config:
|
||||
drawerLayout.closeDrawers();
|
||||
toolbar.setTitle(menuItem.getTitle());
|
||||
viewPager.setCurrentItem(1, false);
|
||||
break;
|
||||
case R.id.nav_message:
|
||||
openNewPage(MessageFragment.class);
|
||||
break;
|
||||
default:
|
||||
XToastUtils.toast("点击了:" + menuItem.getTitle());
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
//主页事件监听
|
||||
viewPager.addOnPageChangeListener(this);
|
||||
bottomNavigation.setOnNavigationItemSelectedListener(this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.add_device:
|
||||
PageOption.to(AddDeviceFragment.class) //跳转的fragment
|
||||
.setAnim(CoreAnim.slide) //页面转场动画
|
||||
.setRequestCode(100) //请求码,用于返回结果
|
||||
.setAddToBackStack(true) //是否加入堆栈
|
||||
.setNewActivity(true, AddDeviceActivity.class) //是否使用新的Activity打开
|
||||
.open(this); //打开页面进行跳转
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@SingleClick
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.nav_header:
|
||||
openNewPage(AccountFragment.class);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//=============ViewPager===================//
|
||||
|
||||
@Override
|
||||
public void onPageScrolled(int i, float v, int i1) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
MenuItem item = bottomNavigation.getMenu().getItem(position);
|
||||
toolbar.setTitle(item.getTitle());
|
||||
item.setChecked(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int i) {
|
||||
|
||||
}
|
||||
|
||||
//================Navigation================//
|
||||
|
||||
/**
|
||||
* 底部导航栏点击事件
|
||||
*
|
||||
* @param menuItem
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
|
||||
int index = CollectionUtils.arrayIndexOf(mTitles, menuItem.getTitle());
|
||||
if (index != -1) {
|
||||
toolbar.setTitle(menuItem.getTitle());
|
||||
viewPager.setCurrentItem(index, false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 菜单、返回键响应
|
||||
*/
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
ClickUtils.exitBy2Click(2000, this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRetry() {
|
||||
XToastUtils.toast("再按一次退出程序");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExit() {
|
||||
XUtil.exitApp();
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP获取用户信息
|
||||
*/
|
||||
private void getUserInfo(TextView avatar,TextView sign){
|
||||
if(!hasToken()) return;
|
||||
XHttp.get(getServerPath()+"/getInfo")
|
||||
.headers("Authorization","Bearer "+getToken())
|
||||
.execute(new CallBackProxy<UserInfoApiResult<User>, User>(new TipRequestCallBack<User>() {
|
||||
@Override
|
||||
public void onSuccess(User user) throws Throwable {
|
||||
Log.d("user:",user.getNickName());
|
||||
if(user.getNickName()!=null && user.getNickName().length()!=0)
|
||||
{
|
||||
avatar.setText(user.getNickName());
|
||||
}else{
|
||||
avatar.setText(user.getUserName());
|
||||
}
|
||||
sign.setText("物美智能开源项目(wumei-smart)");
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if(e.getCode()==401){
|
||||
XToastUtils.info("匿名登录状态,功能受限");
|
||||
clearToken();
|
||||
}else{
|
||||
XToastUtils.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}){});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package com.kerwin.wumei.activity;
|
||||
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.utils.SettingUtils;
|
||||
import com.kerwin.wumei.utils.TokenUtils;
|
||||
import com.kerwin.wumei.utils.Utils;
|
||||
import com.xuexiang.xui.utils.KeyboardUtils;
|
||||
import com.xuexiang.xui.widget.activity.BaseSplashActivity;
|
||||
import com.xuexiang.xutil.app.ActivityUtils;
|
||||
|
||||
import me.jessyan.autosize.internal.CancelAdapt;
|
||||
|
||||
/**
|
||||
* 启动页【无需适配屏幕大小】
|
||||
*
|
||||
*/
|
||||
public class SplashActivity extends BaseSplashActivity implements CancelAdapt {
|
||||
|
||||
@Override
|
||||
protected long getSplashDurationMillis() {
|
||||
return 500;
|
||||
}
|
||||
|
||||
/**
|
||||
* activity启动后的初始化
|
||||
*/
|
||||
@Override
|
||||
protected void onCreateActivity() {
|
||||
initSplashView(R.drawable.xui_config_bg_splash);
|
||||
startSplash(false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 启动页结束后的动作
|
||||
*/
|
||||
@Override
|
||||
protected void onSplashFinished() {
|
||||
loginOrGoMainPage();
|
||||
// if (SettingUtils.isAgreePrivacy()) {
|
||||
// loginOrGoMainPage();
|
||||
// } else {
|
||||
// Utils.showPrivacyDialog(this, (dialog, which) -> {
|
||||
// dialog.dismiss();
|
||||
// SettingUtils.setIsAgreePrivacy(true);
|
||||
// loginOrGoMainPage();
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
private void loginOrGoMainPage() {
|
||||
if (TokenUtils.hasToken()) {
|
||||
ActivityUtils.startActivity(MainActivity.class);
|
||||
} else {
|
||||
ActivityUtils.startActivity(LoginActivity.class);
|
||||
}
|
||||
finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* 菜单、返回键响应
|
||||
*/
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
return KeyboardUtils.onDisableBackKeyDown(keyCode) && super.onKeyDown(keyCode, event);
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.adapter.base.broccoli;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.xuexiang.xui.adapter.recyclerview.BaseRecyclerAdapter;
|
||||
import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder;
|
||||
import com.xuexiang.xui.adapter.recyclerview.XRecyclerAdapter;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import me.samlss.broccoli.Broccoli;
|
||||
|
||||
/**
|
||||
* 使用Broccoli占位的基础适配器
|
||||
*
|
||||
* @author XUE
|
||||
* @since 2019/4/8 16:33
|
||||
*/
|
||||
public abstract class BroccoliRecyclerAdapter<T> extends BaseRecyclerAdapter<T> {
|
||||
/**
|
||||
* 是否已经加载成功
|
||||
*/
|
||||
private boolean mHasLoad = false;
|
||||
private Map<View, Broccoli> mBroccoliMap = new HashMap<>();
|
||||
|
||||
public BroccoliRecyclerAdapter(Collection<T> collection) {
|
||||
super(collection);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindData(@NonNull RecyclerViewHolder holder, int position, T item) {
|
||||
Broccoli broccoli = mBroccoliMap.get(holder.itemView);
|
||||
if (broccoli == null) {
|
||||
broccoli = new Broccoli();
|
||||
mBroccoliMap.put(holder.itemView, broccoli);
|
||||
}
|
||||
if (mHasLoad) {
|
||||
broccoli.removeAllPlaceholders();
|
||||
|
||||
onBindData(holder, item, position);
|
||||
} else {
|
||||
onBindBroccoli(holder, broccoli);
|
||||
broccoli.show();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定控件
|
||||
*
|
||||
* @param holder
|
||||
* @param model
|
||||
* @param position
|
||||
*/
|
||||
protected abstract void onBindData(RecyclerViewHolder holder, T model, int position);
|
||||
|
||||
/**
|
||||
* 绑定占位控件
|
||||
*
|
||||
* @param broccoli
|
||||
*/
|
||||
protected abstract void onBindBroccoli(RecyclerViewHolder holder, Broccoli broccoli);
|
||||
|
||||
@Override
|
||||
public XRecyclerAdapter refresh(Collection<T> collection) {
|
||||
mHasLoad = true;
|
||||
return super.refresh(collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* 资源释放,防止内存泄漏
|
||||
*/
|
||||
public void recycle() {
|
||||
for (Broccoli broccoli : mBroccoliMap.values()) {
|
||||
broccoli.removeAllPlaceholders();
|
||||
}
|
||||
mBroccoliMap.clear();
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.adapter.base.broccoli;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.alibaba.android.vlayout.LayoutHelper;
|
||||
import com.kerwin.wumei.adapter.base.delegate.SimpleDelegateAdapter;
|
||||
import com.kerwin.wumei.adapter.base.delegate.XDelegateAdapter;
|
||||
import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import me.samlss.broccoli.Broccoli;
|
||||
|
||||
/**
|
||||
* 使用Broccoli占位的基础适配器
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2021/1/9 4:52 PM
|
||||
*/
|
||||
public abstract class BroccoliSimpleDelegateAdapter<T> extends SimpleDelegateAdapter<T> {
|
||||
|
||||
/**
|
||||
* 是否已经加载成功
|
||||
*/
|
||||
private boolean mHasLoad = false;
|
||||
private Map<View, Broccoli> mBroccoliMap = new HashMap<>();
|
||||
|
||||
public BroccoliSimpleDelegateAdapter(int layoutId, LayoutHelper layoutHelper) {
|
||||
super(layoutId, layoutHelper);
|
||||
}
|
||||
|
||||
public BroccoliSimpleDelegateAdapter(int layoutId, LayoutHelper layoutHelper, Collection<T> list) {
|
||||
super(layoutId, layoutHelper, list);
|
||||
}
|
||||
|
||||
public BroccoliSimpleDelegateAdapter(int layoutId, LayoutHelper layoutHelper, T[] data) {
|
||||
super(layoutId, layoutHelper, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindData(@NonNull RecyclerViewHolder holder, int position, T item) {
|
||||
Broccoli broccoli = mBroccoliMap.get(holder.itemView);
|
||||
if (broccoli == null) {
|
||||
broccoli = new Broccoli();
|
||||
mBroccoliMap.put(holder.itemView, broccoli);
|
||||
}
|
||||
if (mHasLoad) {
|
||||
broccoli.removeAllPlaceholders();
|
||||
|
||||
onBindData(holder, item, position);
|
||||
} else {
|
||||
onBindBroccoli(holder, broccoli);
|
||||
broccoli.show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 绑定控件
|
||||
*
|
||||
* @param holder
|
||||
* @param model
|
||||
* @param position
|
||||
*/
|
||||
protected abstract void onBindData(RecyclerViewHolder holder, T model, int position);
|
||||
|
||||
/**
|
||||
* 绑定占位控件
|
||||
*
|
||||
* @param holder
|
||||
* @param broccoli
|
||||
*/
|
||||
protected abstract void onBindBroccoli(RecyclerViewHolder holder, Broccoli broccoli);
|
||||
|
||||
@Override
|
||||
public XDelegateAdapter refresh(Collection<T> collection) {
|
||||
mHasLoad = true;
|
||||
return super.refresh(collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* 资源释放,防止内存泄漏
|
||||
*/
|
||||
public void recycle() {
|
||||
for (Broccoli broccoli : mBroccoliMap.values()) {
|
||||
broccoli.removeAllPlaceholders();
|
||||
}
|
||||
mBroccoliMap.clear();
|
||||
clear();
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.adapter.base.delegate;
|
||||
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 通用的DelegateAdapter适配器
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2020/3/20 12:44 AM
|
||||
*/
|
||||
public abstract class BaseDelegateAdapter<T> extends XDelegateAdapter<T, RecyclerViewHolder> {
|
||||
|
||||
public BaseDelegateAdapter() {
|
||||
super();
|
||||
}
|
||||
|
||||
public BaseDelegateAdapter(Collection<T> list) {
|
||||
super(list);
|
||||
}
|
||||
|
||||
public BaseDelegateAdapter(T[] data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 适配的布局
|
||||
*
|
||||
* @param viewType
|
||||
* @return
|
||||
*/
|
||||
protected abstract int getItemLayoutId(int viewType);
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected RecyclerViewHolder getViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new RecyclerViewHolder(inflateView(parent, getItemLayoutId(viewType)));
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.adapter.base.delegate;
|
||||
|
||||
import com.alibaba.android.vlayout.LayoutHelper;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 简易DelegateAdapter适配器
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2020/3/20 12:55 AM
|
||||
*/
|
||||
public abstract class SimpleDelegateAdapter<T> extends BaseDelegateAdapter<T> {
|
||||
|
||||
private int mLayoutId;
|
||||
|
||||
private LayoutHelper mLayoutHelper;
|
||||
|
||||
public SimpleDelegateAdapter(int layoutId, LayoutHelper layoutHelper) {
|
||||
super();
|
||||
mLayoutId = layoutId;
|
||||
mLayoutHelper = layoutHelper;
|
||||
}
|
||||
|
||||
public SimpleDelegateAdapter(int layoutId, LayoutHelper layoutHelper, Collection<T> list) {
|
||||
super(list);
|
||||
mLayoutId = layoutId;
|
||||
mLayoutHelper = layoutHelper;
|
||||
}
|
||||
|
||||
public SimpleDelegateAdapter(int layoutId, LayoutHelper layoutHelper, T[] data) {
|
||||
super(data);
|
||||
mLayoutId = layoutId;
|
||||
mLayoutHelper = layoutHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getItemLayoutId(int viewType) {
|
||||
return mLayoutId;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public LayoutHelper onCreateLayoutHelper() {
|
||||
return mLayoutHelper;
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.adapter.base.delegate;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.alibaba.android.vlayout.DelegateAdapter;
|
||||
import com.alibaba.android.vlayout.LayoutHelper;
|
||||
import com.alibaba.android.vlayout.layout.SingleLayoutHelper;
|
||||
import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder;
|
||||
|
||||
/**
|
||||
* 单独布局的DelegateAdapter
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2020/3/20 1:04 AM
|
||||
*/
|
||||
public abstract class SingleDelegateAdapter extends DelegateAdapter.Adapter<RecyclerViewHolder> {
|
||||
|
||||
private int mLayoutId;
|
||||
|
||||
public SingleDelegateAdapter(int layoutId) {
|
||||
mLayoutId = layoutId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LayoutHelper onCreateLayoutHelper() {
|
||||
return new SingleLayoutHelper();
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载布局获取控件
|
||||
*
|
||||
* @param parent 父布局
|
||||
* @param layoutId 布局ID
|
||||
* @return
|
||||
*/
|
||||
protected View inflateView(ViewGroup parent, @LayoutRes int layoutId) {
|
||||
return LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new RecyclerViewHolder(inflateView(parent, mLayoutId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1,300 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.adapter.base.delegate;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.alibaba.android.vlayout.DelegateAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 基础DelegateAdapter
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2020/3/20 12:17 AM
|
||||
*/
|
||||
public abstract class XDelegateAdapter<T, V extends RecyclerView.ViewHolder> extends DelegateAdapter.Adapter<V> {
|
||||
/**
|
||||
* 数据源
|
||||
*/
|
||||
protected final List<T> mData = new ArrayList<>();
|
||||
/**
|
||||
* 当前点击的条目
|
||||
*/
|
||||
protected int mSelectPosition = -1;
|
||||
|
||||
public XDelegateAdapter() {
|
||||
|
||||
}
|
||||
|
||||
public XDelegateAdapter(Collection<T> list) {
|
||||
if (list != null) {
|
||||
mData.addAll(list);
|
||||
}
|
||||
}
|
||||
|
||||
public XDelegateAdapter(T[] data) {
|
||||
if (data != null && data.length > 0) {
|
||||
mData.addAll(Arrays.asList(data));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建自定义的ViewHolder
|
||||
*
|
||||
* @param parent
|
||||
* @param viewType
|
||||
* @return
|
||||
*/
|
||||
@NonNull
|
||||
protected abstract V getViewHolder(@NonNull ViewGroup parent, int viewType);
|
||||
|
||||
/**
|
||||
* 绑定数据
|
||||
*
|
||||
* @param holder
|
||||
* @param position 索引
|
||||
* @param item 列表项
|
||||
*/
|
||||
protected abstract void bindData(@NonNull V holder, int position, T item);
|
||||
|
||||
/**
|
||||
* 加载布局获取控件
|
||||
*
|
||||
* @param parent 父布局
|
||||
* @param layoutId 布局ID
|
||||
* @return
|
||||
*/
|
||||
protected View inflateView(ViewGroup parent, @LayoutRes int layoutId) {
|
||||
return LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public V onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return getViewHolder(parent, viewType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull V holder, int position) {
|
||||
bindData(holder, position, mData.get(position));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取列表项
|
||||
*
|
||||
* @param position
|
||||
* @return
|
||||
*/
|
||||
public T getItem(int position) {
|
||||
return checkPosition(position) ? mData.get(position) : null;
|
||||
}
|
||||
|
||||
private boolean checkPosition(int position) {
|
||||
return position >= 0 && position <= mData.size() - 1;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return getItemCount() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mData.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 数据源
|
||||
*/
|
||||
public List<T> getData() {
|
||||
return mData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 给指定位置添加一项
|
||||
*
|
||||
* @param pos
|
||||
* @param item
|
||||
* @return
|
||||
*/
|
||||
public XDelegateAdapter add(int pos, T item) {
|
||||
mData.add(pos, item);
|
||||
notifyItemInserted(pos);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在列表末端增加一项
|
||||
*
|
||||
* @param item
|
||||
* @return
|
||||
*/
|
||||
public XDelegateAdapter add(T item) {
|
||||
mData.add(item);
|
||||
notifyItemInserted(mData.size() - 1);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除列表中指定索引的数据
|
||||
*
|
||||
* @param pos
|
||||
* @return
|
||||
*/
|
||||
public XDelegateAdapter delete(int pos) {
|
||||
mData.remove(pos);
|
||||
notifyItemRemoved(pos);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新列表中指定位置的数据
|
||||
*
|
||||
* @param pos
|
||||
* @param item
|
||||
* @return
|
||||
*/
|
||||
public XDelegateAdapter refresh(int pos, T item) {
|
||||
mData.set(pos, item);
|
||||
notifyItemChanged(pos);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新列表数据
|
||||
*
|
||||
* @param collection
|
||||
* @return
|
||||
*/
|
||||
public XDelegateAdapter refresh(Collection<T> collection) {
|
||||
if (collection != null) {
|
||||
mData.clear();
|
||||
mData.addAll(collection);
|
||||
mSelectPosition = -1;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新列表数据
|
||||
*
|
||||
* @param array
|
||||
* @return
|
||||
*/
|
||||
public XDelegateAdapter refresh(T[] array) {
|
||||
if (array != null && array.length > 0) {
|
||||
mData.clear();
|
||||
mData.addAll(Arrays.asList(array));
|
||||
mSelectPosition = -1;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载更多
|
||||
*
|
||||
* @param collection
|
||||
* @return
|
||||
*/
|
||||
public XDelegateAdapter loadMore(Collection<T> collection) {
|
||||
if (collection != null) {
|
||||
mData.addAll(collection);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载更多
|
||||
*
|
||||
* @param array
|
||||
* @return
|
||||
*/
|
||||
public XDelegateAdapter loadMore(T[] array) {
|
||||
if (array != null && array.length > 0) {
|
||||
mData.addAll(Arrays.asList(array));
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个
|
||||
*
|
||||
* @param item
|
||||
* @return
|
||||
*/
|
||||
public XDelegateAdapter load(T item) {
|
||||
if (item != null) {
|
||||
mData.add(item);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 当前列表的选中项
|
||||
*/
|
||||
public int getSelectPosition() {
|
||||
return mSelectPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置当前列表的选中项
|
||||
*
|
||||
* @param selectPosition
|
||||
* @return
|
||||
*/
|
||||
public XDelegateAdapter setSelectPosition(int selectPosition) {
|
||||
mSelectPosition = selectPosition;
|
||||
notifyDataSetChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前列表选中项
|
||||
*
|
||||
* @return 当前列表选中项
|
||||
*/
|
||||
public T getSelectItem() {
|
||||
return getItem(mSelectPosition);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除数据
|
||||
*/
|
||||
public void clear() {
|
||||
if (!isEmpty()) {
|
||||
mData.clear();
|
||||
mSelectPosition = -1;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package com.kerwin.wumei.adapter.entity;
|
||||
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.RadioGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.xuexiang.xui.widget.picker.XSeekBar;
|
||||
import com.xuexiang.xui.widget.spinner.materialspinner.MaterialSpinner;
|
||||
|
||||
public class EspTouchViewModel {
|
||||
public MaterialSpinner ssidSpinner;
|
||||
public EditText apPasswordEdit;
|
||||
public XSeekBar xsbDeviceCount;
|
||||
public RadioGroup packageModeGroup;
|
||||
public TextView messageView;
|
||||
public Button confirmBtn;
|
||||
|
||||
public String ssid;
|
||||
public byte[] ssidBytes;
|
||||
public String bssid;
|
||||
|
||||
public CharSequence message;
|
||||
|
||||
public boolean confirmEnable;
|
||||
|
||||
public void invalidateAll() {
|
||||
ssidSpinner.setText(ssid);
|
||||
messageView.setText(message);
|
||||
confirmBtn.setEnabled(confirmEnable);
|
||||
}
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
|
||||
package com.kerwin.wumei.adapter.entity;
|
||||
|
||||
/**
|
||||
* 新闻信息
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019/4/7 下午12:07
|
||||
*/
|
||||
public class NewInfo {
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String UserName = "kerwin";
|
||||
/**
|
||||
* 标签
|
||||
*/
|
||||
private String Tag;
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
private String Title;
|
||||
/**
|
||||
* 摘要
|
||||
*/
|
||||
private String Summary;
|
||||
|
||||
/**
|
||||
* 图片
|
||||
*/
|
||||
private String ImageUrl;
|
||||
/**
|
||||
* 点赞数
|
||||
*/
|
||||
private int Praise;
|
||||
/**
|
||||
* 评论数
|
||||
*/
|
||||
private int Comment;
|
||||
/**
|
||||
* 阅读量
|
||||
*/
|
||||
private int Read;
|
||||
/**
|
||||
* 新闻的详情地址
|
||||
*/
|
||||
private String DetailUrl;
|
||||
|
||||
|
||||
public NewInfo() {
|
||||
|
||||
}
|
||||
|
||||
public NewInfo(String userName, String tag, String title, String summary, String imageUrl, int praise, int comment, int read, String detailUrl) {
|
||||
UserName = userName;
|
||||
Tag = tag;
|
||||
Title = title;
|
||||
Summary = summary;
|
||||
ImageUrl = imageUrl;
|
||||
Praise = praise;
|
||||
Comment = comment;
|
||||
Read = read;
|
||||
DetailUrl = detailUrl;
|
||||
}
|
||||
|
||||
|
||||
public NewInfo(String tag, String title, String summary, String imageUrl, String detailUrl) {
|
||||
Tag = tag;
|
||||
Title = title;
|
||||
Summary = summary;
|
||||
ImageUrl = imageUrl;
|
||||
DetailUrl = detailUrl;
|
||||
}
|
||||
|
||||
|
||||
public NewInfo(String tag, String title) {
|
||||
Tag = tag;
|
||||
Title = title;
|
||||
|
||||
Praise = (int) (Math.random() * 100 + 5);
|
||||
Comment = (int) (Math.random() * 50 + 5);
|
||||
Read = (int) (Math.random() * 500 + 50);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getUserName() {
|
||||
return UserName;
|
||||
}
|
||||
|
||||
public NewInfo setUserName(String userName) {
|
||||
UserName = userName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getTag() {
|
||||
return Tag;
|
||||
}
|
||||
|
||||
public NewInfo setTag(String tag) {
|
||||
Tag = tag;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return Title;
|
||||
}
|
||||
|
||||
public NewInfo setTitle(String title) {
|
||||
Title = title;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getSummary() {
|
||||
return Summary;
|
||||
}
|
||||
|
||||
public NewInfo setSummary(String summary) {
|
||||
Summary = summary;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getImageUrl() {
|
||||
return ImageUrl;
|
||||
}
|
||||
|
||||
public NewInfo setImageUrl(String imageUrl) {
|
||||
ImageUrl = imageUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getPraise() {
|
||||
return Praise;
|
||||
}
|
||||
|
||||
public NewInfo setPraise(int praise) {
|
||||
Praise = praise;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getComment() {
|
||||
return Comment;
|
||||
}
|
||||
|
||||
public NewInfo setComment(int comment) {
|
||||
Comment = comment;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getRead() {
|
||||
return Read;
|
||||
}
|
||||
|
||||
public NewInfo setRead(int read) {
|
||||
Read = read;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getDetailUrl() {
|
||||
return DetailUrl;
|
||||
}
|
||||
|
||||
public NewInfo setDetailUrl(String detailUrl) {
|
||||
DetailUrl = detailUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NewInfo{" +
|
||||
"UserName='" + UserName + '\'' +
|
||||
", Tag='" + Tag + '\'' +
|
||||
", Title='" + Title + '\'' +
|
||||
", Summary='" + Summary + '\'' +
|
||||
", ImageUrl='" + ImageUrl + '\'' +
|
||||
", Praise=" + Praise +
|
||||
", Comment=" + Comment +
|
||||
", Read=" + Read +
|
||||
", DetailUrl='" + DetailUrl + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.xuexiang.xpage.base.XPageActivity;
|
||||
import com.xuexiang.xpage.base.XPageFragment;
|
||||
import com.xuexiang.xpage.core.CoreSwitchBean;
|
||||
import com.xuexiang.xrouter.facade.service.SerializationService;
|
||||
import com.xuexiang.xrouter.launcher.XRouter;
|
||||
import com.xuexiang.xui.utils.ResUtils;
|
||||
import com.xuexiang.xui.widget.slideback.SlideBack;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.Unbinder;
|
||||
import io.github.inflationx.viewpump.ViewPumpContextWrapper;
|
||||
|
||||
/**
|
||||
* 基础容器Activity
|
||||
*
|
||||
* @author XUE
|
||||
* @since 2019/3/22 11:21
|
||||
*/
|
||||
public class BaseActivity extends XPageActivity {
|
||||
|
||||
Unbinder mUnbinder;
|
||||
|
||||
@Override
|
||||
protected void attachBaseContext(Context newBase) {
|
||||
//注入字体
|
||||
super.attachBaseContext(ViewPumpContextWrapper.wrap(newBase));
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否支持侧滑返回
|
||||
*/
|
||||
public static final String KEY_SUPPORT_SLIDE_BACK = "key_support_slide_back";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
initStatusBarStyle();
|
||||
super.onCreate(savedInstanceState);
|
||||
mUnbinder = ButterKnife.bind(this);
|
||||
|
||||
registerSlideBack();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化状态栏的样式
|
||||
*/
|
||||
protected void initStatusBarStyle() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开fragment
|
||||
*
|
||||
* @param clazz 页面类
|
||||
* @param addToBackStack 是否添加到栈中
|
||||
* @return 打开的fragment对象
|
||||
*/
|
||||
public <T extends XPageFragment> T openPage(Class<T> clazz, boolean addToBackStack) {
|
||||
CoreSwitchBean page = new CoreSwitchBean(clazz)
|
||||
.setAddToBackStack(addToBackStack);
|
||||
return (T) openPage(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开fragment
|
||||
*
|
||||
* @return 打开的fragment对象
|
||||
*/
|
||||
public <T extends XPageFragment> T openNewPage(Class<T> clazz) {
|
||||
CoreSwitchBean page = new CoreSwitchBean(clazz)
|
||||
.setNewActivity(true);
|
||||
return (T) openPage(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换fragment
|
||||
*
|
||||
* @param clazz 页面类
|
||||
* @return 打开的fragment对象
|
||||
*/
|
||||
public <T extends XPageFragment> T switchPage(Class<T> clazz) {
|
||||
return openPage(clazz, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 序列化对象
|
||||
*
|
||||
* @param object
|
||||
* @return
|
||||
*/
|
||||
public String serializeObject(Object object) {
|
||||
return XRouter.getInstance().navigation(SerializationService.class).object2Json(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRelease() {
|
||||
mUnbinder.unbind();
|
||||
unregisterSlideBack();
|
||||
super.onRelease();
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册侧滑回调
|
||||
*/
|
||||
protected void registerSlideBack() {
|
||||
if (isSupportSlideBack()) {
|
||||
SlideBack.with(this)
|
||||
.haveScroll(true)
|
||||
.edgeMode(ResUtils.isRtl() ? SlideBack.EDGE_RIGHT : SlideBack.EDGE_LEFT)
|
||||
.callBack(this::popPage)
|
||||
.register();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注销侧滑回调
|
||||
*/
|
||||
protected void unregisterSlideBack() {
|
||||
if (isSupportSlideBack()) {
|
||||
SlideBack.unregister(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 是否支持侧滑返回
|
||||
*/
|
||||
protected boolean isSupportSlideBack() {
|
||||
CoreSwitchBean page = getIntent().getParcelableExtra(CoreSwitchBean.KEY_SWITCH_BEAN);
|
||||
return page == null || page.getBundle() == null || page.getBundle().getBoolean(KEY_SUPPORT_SLIDE_BACK, true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
|
||||
import com.umeng.analytics.MobclickAgent;
|
||||
import com.xuexiang.xaop.annotation.SingleClick;
|
||||
import com.xuexiang.xpage.base.XPageContainerListFragment;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.kerwin.wumei.core.SimpleListAdapter.KEY_SUB_TITLE;
|
||||
import static com.kerwin.wumei.core.SimpleListAdapter.KEY_TITLE;
|
||||
|
||||
/**
|
||||
* 修改列表样式为主副标题显示
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2018/11/22 上午11:26
|
||||
*/
|
||||
public abstract class BaseContainerFragment extends XPageContainerListFragment {
|
||||
|
||||
@Override
|
||||
protected void initPage() {
|
||||
initTitle();
|
||||
initViews();
|
||||
initListeners();
|
||||
}
|
||||
|
||||
protected TitleBar initTitle() {
|
||||
return TitleUtils.addTitleBarDynamic((ViewGroup) getRootView(), getPageTitle(), new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
popToBack();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initData() {
|
||||
mSimpleData = initSimpleData(mSimpleData);
|
||||
|
||||
List<Map<String, String>> data = new ArrayList<>();
|
||||
for (String content : mSimpleData) {
|
||||
Map<String, String> item = new HashMap<>();
|
||||
int index = content.indexOf("\n");
|
||||
if (index > 0) {
|
||||
item.put(KEY_TITLE, String.valueOf(content.subSequence(0, index)));
|
||||
item.put(KEY_SUB_TITLE, String.valueOf(content.subSequence(index + 1, content.length())));
|
||||
} else {
|
||||
item.put(KEY_TITLE, content);
|
||||
item.put(KEY_SUB_TITLE, "");
|
||||
}
|
||||
data.add(item);
|
||||
}
|
||||
|
||||
getListView().setAdapter(new SimpleListAdapter(getContext(), data));
|
||||
initSimply();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
|
||||
onItemClick(view, position);
|
||||
}
|
||||
|
||||
@SingleClick
|
||||
private void onItemClick(View view, int position) {
|
||||
onItemClick(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
getListView().setOnItemClickListener(null);
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
//屏幕旋转时刷新一下title
|
||||
super.onConfigurationChanged(newConfig);
|
||||
ViewGroup root = (ViewGroup) getRootView();
|
||||
if (root.getChildAt(0) instanceof TitleBar) {
|
||||
root.removeViewAt(0);
|
||||
initTitle();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
MobclickAgent.onPageStart(getPageName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
MobclickAgent.onPageEnd(getPageName());
|
||||
}
|
||||
}
|
||||
@@ -1,346 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Parcelable;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.umeng.analytics.MobclickAgent;
|
||||
import com.kerwin.wumei.core.http.loader.ProgressLoader;
|
||||
import com.xuexiang.xhttp2.subsciber.impl.IProgressLoader;
|
||||
import com.xuexiang.xpage.base.XPageActivity;
|
||||
import com.xuexiang.xpage.base.XPageFragment;
|
||||
import com.xuexiang.xpage.core.PageOption;
|
||||
import com.xuexiang.xpage.enums.CoreAnim;
|
||||
import com.xuexiang.xpage.utils.Utils;
|
||||
import com.xuexiang.xrouter.facade.service.SerializationService;
|
||||
import com.xuexiang.xrouter.launcher.XRouter;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 基础fragment
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2018/5/25 下午3:44
|
||||
*/
|
||||
public abstract class BaseFragment extends XPageFragment {
|
||||
|
||||
private IProgressLoader mIProgressLoader;
|
||||
|
||||
@Override
|
||||
protected void initPage() {
|
||||
initTitle();
|
||||
initViews();
|
||||
initListeners();
|
||||
}
|
||||
|
||||
protected TitleBar initTitle() {
|
||||
return TitleUtils.addTitleBarDynamic((ViewGroup) getRootView(), getPageTitle(), v -> popToBack());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initListeners() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取进度条加载者
|
||||
*
|
||||
* @return 进度条加载者
|
||||
*/
|
||||
public IProgressLoader getProgressLoader() {
|
||||
if (mIProgressLoader == null) {
|
||||
mIProgressLoader = ProgressLoader.create(getContext());
|
||||
}
|
||||
return mIProgressLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取进度条加载者
|
||||
*
|
||||
* @param message
|
||||
* @return 进度条加载者
|
||||
*/
|
||||
public IProgressLoader getProgressLoader(String message) {
|
||||
if (mIProgressLoader == null) {
|
||||
mIProgressLoader = ProgressLoader.create(getContext(), message);
|
||||
} else {
|
||||
mIProgressLoader.updateMessage(message);
|
||||
}
|
||||
return mIProgressLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(@NonNull Configuration newConfig) {
|
||||
//屏幕旋转时刷新一下title
|
||||
super.onConfigurationChanged(newConfig);
|
||||
ViewGroup root = (ViewGroup) getRootView();
|
||||
if (root.getChildAt(0) instanceof TitleBar) {
|
||||
root.removeViewAt(0);
|
||||
initTitle();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
if (mIProgressLoader != null) {
|
||||
mIProgressLoader.dismissLoading();
|
||||
}
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
MobclickAgent.onPageStart(getPageName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
MobclickAgent.onPageEnd(getPageName());
|
||||
}
|
||||
|
||||
//==============================页面跳转api===================================//
|
||||
|
||||
/**
|
||||
* 打开一个新的页面【建议只在主tab页使用】
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz) {
|
||||
return new PageOption(clazz)
|
||||
.setNewActivity(true)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开一个新的页面【建议只在主tab页使用】
|
||||
*
|
||||
* @param pageName 页面名
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openNewPage(String pageName) {
|
||||
return new PageOption(pageName)
|
||||
.setAnim(CoreAnim.slide)
|
||||
.setNewActivity(true)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 打开一个新的页面【建议只在主tab页使用】
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param containActivityClazz 页面容器
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz, @NonNull Class<? extends XPageActivity> containActivityClazz) {
|
||||
return new PageOption(clazz)
|
||||
.setNewActivity(true)
|
||||
.setContainActivityClazz(containActivityClazz)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开一个新的页面【建议只在主tab页使用】
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz, String key, Object value) {
|
||||
PageOption option = new PageOption(clazz).setNewActivity(true);
|
||||
return openPage(option, key, value);
|
||||
}
|
||||
|
||||
public Fragment openPage(PageOption option, String key, Object value) {
|
||||
if (value instanceof Integer) {
|
||||
option.putInt(key, (Integer) value);
|
||||
} else if (value instanceof Float) {
|
||||
option.putFloat(key, (Float) value);
|
||||
} else if (value instanceof String) {
|
||||
option.putString(key, (String) value);
|
||||
} else if (value instanceof Boolean) {
|
||||
option.putBoolean(key, (Boolean) value);
|
||||
} else if (value instanceof Long) {
|
||||
option.putLong(key, (Long) value);
|
||||
} else if (value instanceof Double) {
|
||||
option.putDouble(key, (Double) value);
|
||||
} else if (value instanceof Parcelable) {
|
||||
option.putParcelable(key, (Parcelable) value);
|
||||
} else if (value instanceof Serializable) {
|
||||
option.putSerializable(key, (Serializable) value);
|
||||
} else {
|
||||
option.putString(key, serializeObject(value));
|
||||
}
|
||||
return option.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param addToBackStack 是否加入回退栈
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPage(Class<T> clazz, boolean addToBackStack, String key, String value) {
|
||||
return new PageOption(clazz)
|
||||
.setAddToBackStack(addToBackStack)
|
||||
.putString(key, value)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPage(Class<T> clazz, String key, Object value) {
|
||||
return openPage(clazz, true, key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param addToBackStack 是否加入回退栈
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPage(Class<T> clazz, boolean addToBackStack, String key, Object value) {
|
||||
PageOption option = new PageOption(clazz).setAddToBackStack(addToBackStack);
|
||||
return openPage(option, key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPage(Class<T> clazz, String key, String value) {
|
||||
return new PageOption(clazz)
|
||||
.putString(key, value)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面,需要结果返回
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param requestCode 请求码
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPageForResult(Class<T> clazz, String key, Object value, int requestCode) {
|
||||
PageOption option = new PageOption(clazz).setRequestCode(requestCode);
|
||||
return openPage(option, key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面,需要结果返回
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param requestCode 请求码
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPageForResult(Class<T> clazz, String key, String value, int requestCode) {
|
||||
return new PageOption(clazz)
|
||||
.setRequestCode(requestCode)
|
||||
.putString(key, value)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面,需要结果返回
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param requestCode 请求码
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPageForResult(Class<T> clazz, int requestCode) {
|
||||
return new PageOption(clazz)
|
||||
.setRequestCode(requestCode)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 序列化对象
|
||||
*
|
||||
* @param object 需要序列化的对象
|
||||
* @return 序列化结果
|
||||
*/
|
||||
public String serializeObject(Object object) {
|
||||
return XRouter.getInstance().navigation(SerializationService.class).object2Json(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* 反序列化对象
|
||||
*
|
||||
* @param input 反序列化的内容
|
||||
* @param clazz 类型
|
||||
* @return 反序列化结果
|
||||
*/
|
||||
public <T> T deserializeObject(String input, Type clazz) {
|
||||
return XRouter.getInstance().navigation(SerializationService.class).parseObject(input, clazz);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void hideCurrentPageSoftInput() {
|
||||
if (getActivity() == null) {
|
||||
return;
|
||||
}
|
||||
// 记住,要在xml的父布局加上android:focusable="true" 和 android:focusableInTouchMode="true"
|
||||
Utils.hideSoftInputClearFocus(getActivity().getCurrentFocus());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,284 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Parcelable;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.umeng.analytics.MobclickAgent;
|
||||
import com.xuexiang.xpage.base.XPageActivity;
|
||||
import com.xuexiang.xpage.base.XPageFragment;
|
||||
import com.xuexiang.xpage.base.XPageSimpleListFragment;
|
||||
import com.xuexiang.xpage.core.PageOption;
|
||||
import com.xuexiang.xpage.enums.CoreAnim;
|
||||
import com.xuexiang.xrouter.facade.service.SerializationService;
|
||||
import com.xuexiang.xrouter.launcher.XRouter;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author xuexiang
|
||||
* @since 2018/12/29 下午12:41
|
||||
*/
|
||||
public abstract class BaseSimpleListFragment extends XPageSimpleListFragment {
|
||||
|
||||
@Override
|
||||
protected void initPage() {
|
||||
initTitle();
|
||||
initViews();
|
||||
initListeners();
|
||||
}
|
||||
|
||||
protected TitleBar initTitle() {
|
||||
return TitleUtils.addTitleBarDynamic((ViewGroup) getRootView(), getPageTitle(), new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
popToBack();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(@NonNull Configuration newConfig) {
|
||||
//屏幕旋转时刷新一下title
|
||||
super.onConfigurationChanged(newConfig);
|
||||
ViewGroup root = (ViewGroup) getRootView();
|
||||
if (root.getChildAt(0) instanceof TitleBar) {
|
||||
root.removeViewAt(0);
|
||||
initTitle();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
MobclickAgent.onPageStart(getPageName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
MobclickAgent.onPageEnd(getPageName());
|
||||
}
|
||||
|
||||
//==============================页面跳转api===================================//
|
||||
|
||||
/**
|
||||
* 打开一个新的页面【建议只在主tab页使用】
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz) {
|
||||
return new PageOption(clazz)
|
||||
.setNewActivity(true)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开一个新的页面【建议只在主tab页使用】
|
||||
*
|
||||
* @param pageName 页面名
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openNewPage(String pageName) {
|
||||
return new PageOption(pageName)
|
||||
.setAnim(CoreAnim.slide)
|
||||
.setNewActivity(true)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 打开一个新的页面【建议只在主tab页使用】
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param containActivityClazz 页面容器
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz, @NonNull Class<? extends XPageActivity> containActivityClazz) {
|
||||
return new PageOption(clazz)
|
||||
.setNewActivity(true)
|
||||
.setContainActivityClazz(containActivityClazz)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开一个新的页面【建议只在主tab页使用】
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openNewPage(Class<T> clazz, String key, Object value) {
|
||||
PageOption option = new PageOption(clazz).setNewActivity(true);
|
||||
return openPage(option, key, value);
|
||||
}
|
||||
|
||||
public Fragment openPage(PageOption option, String key, Object value) {
|
||||
if (value instanceof Integer) {
|
||||
option.putInt(key, (Integer) value);
|
||||
} else if (value instanceof Float) {
|
||||
option.putFloat(key, (Float) value);
|
||||
} else if (value instanceof String) {
|
||||
option.putString(key, (String) value);
|
||||
} else if (value instanceof Boolean) {
|
||||
option.putBoolean(key, (Boolean) value);
|
||||
} else if (value instanceof Long) {
|
||||
option.putLong(key, (Long) value);
|
||||
} else if (value instanceof Double) {
|
||||
option.putDouble(key, (Double) value);
|
||||
} else if (value instanceof Parcelable) {
|
||||
option.putParcelable(key, (Parcelable) value);
|
||||
} else if (value instanceof Serializable) {
|
||||
option.putSerializable(key, (Serializable) value);
|
||||
} else {
|
||||
option.putString(key, serializeObject(value));
|
||||
}
|
||||
return option.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param addToBackStack 是否加入回退栈
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPage(Class<T> clazz, boolean addToBackStack, String key, String value) {
|
||||
return new PageOption(clazz)
|
||||
.setAddToBackStack(addToBackStack)
|
||||
.putString(key, value)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPage(Class<T> clazz, String key, Object value) {
|
||||
return openPage(clazz, true, key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param addToBackStack 是否加入回退栈
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPage(Class<T> clazz, boolean addToBackStack, String key, Object value) {
|
||||
PageOption option = new PageOption(clazz).setAddToBackStack(addToBackStack);
|
||||
return openPage(option, key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPage(Class<T> clazz, String key, String value) {
|
||||
return new PageOption(clazz)
|
||||
.putString(key, value)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面,需要结果返回
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param requestCode 请求码
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPageForResult(Class<T> clazz, String key, Object value, int requestCode) {
|
||||
PageOption option = new PageOption(clazz).setRequestCode(requestCode);
|
||||
return openPage(option, key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面,需要结果返回
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param key 入参的键
|
||||
* @param value 入参的值
|
||||
* @param requestCode 请求码
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPageForResult(Class<T> clazz, String key, String value, int requestCode) {
|
||||
return new PageOption(clazz)
|
||||
.setRequestCode(requestCode)
|
||||
.putString(key, value)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开页面,需要结果返回
|
||||
*
|
||||
* @param clazz 页面的类
|
||||
* @param requestCode 请求码
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T extends XPageFragment> Fragment openPageForResult(Class<T> clazz, int requestCode) {
|
||||
return new PageOption(clazz)
|
||||
.setRequestCode(requestCode)
|
||||
.open(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 序列化对象
|
||||
*
|
||||
* @param object 需要序列化的对象
|
||||
* @return 序列化结果
|
||||
*/
|
||||
public String serializeObject(Object object) {
|
||||
return XRouter.getInstance().navigation(SerializationService.class).object2Json(object);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.kerwin.wumei.R;
|
||||
import com.xuexiang.xui.adapter.listview.BaseListAdapter;
|
||||
import com.xuexiang.xutil.common.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 主副标题显示适配器
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2018/12/19 上午12:19
|
||||
*/
|
||||
public class SimpleListAdapter extends BaseListAdapter<Map<String, String>, SimpleListAdapter.ViewHolder> {
|
||||
|
||||
public static final String KEY_TITLE = "key_title";
|
||||
public static final String KEY_SUB_TITLE = "key_sub_title";
|
||||
|
||||
public SimpleListAdapter(Context context, List<Map<String, String>> data) {
|
||||
super(context, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ViewHolder newViewHolder(View convertView) {
|
||||
ViewHolder holder = new ViewHolder();
|
||||
holder.mTvTitle = convertView.findViewById(R.id.device_item_title);
|
||||
holder.mTvSubTitle = convertView.findViewById(R.id.tv_sub_title);
|
||||
return holder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.adapter_item_simple_list_2;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void convert(ViewHolder holder, Map<String, String> item, int position) {
|
||||
holder.mTvTitle.setText(item.get(KEY_TITLE));
|
||||
if (!StringUtils.isEmpty(item.get(KEY_SUB_TITLE))) {
|
||||
holder.mTvSubTitle.setText(item.get(KEY_SUB_TITLE));
|
||||
holder.mTvSubTitle.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.mTvSubTitle.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ViewHolder {
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
public TextView mTvTitle;
|
||||
/**
|
||||
* 副标题
|
||||
*/
|
||||
public TextView mTvSubTitle;
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.xrouter.annotation.AutoWired;
|
||||
import com.xuexiang.xrouter.annotation.Router;
|
||||
import com.xuexiang.xrouter.launcher.XRouter;
|
||||
import com.xuexiang.xutil.common.StringUtils;
|
||||
|
||||
/**
|
||||
* https://xuexiangjys.club/xpage/transfer?pageName=xxxxx&....
|
||||
* applink的中转
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-07-06 9:37
|
||||
*/
|
||||
@Router(path = "/xpage/transfer")
|
||||
public class XPageTransferActivity extends BaseActivity {
|
||||
|
||||
@AutoWired(name = "pageName")
|
||||
String pageName;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
XRouter.getInstance().inject(this);
|
||||
|
||||
if (!StringUtils.isEmpty(pageName)) {
|
||||
if (openPage(pageName, getIntent().getExtras()) == null) {
|
||||
XToastUtils.error("页面未找到!");
|
||||
finish();
|
||||
}
|
||||
} else {
|
||||
XToastUtils.error("页面未找到!");
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.http.api;
|
||||
|
||||
import com.kerwin.wumei.core.http.entity.TipInfo;
|
||||
import com.xuexiang.xhttp2.model.ApiResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import retrofit2.http.GET;
|
||||
|
||||
/**
|
||||
* @author xuexiang
|
||||
* @since 2021/1/9 7:01 PM
|
||||
*/
|
||||
public class ApiService {
|
||||
|
||||
/**
|
||||
* 使用的是retrofit的接口定义
|
||||
*/
|
||||
public interface IGetService {
|
||||
|
||||
/**
|
||||
* 获得小贴士
|
||||
*/
|
||||
@GET("http://wumei.live/tips.json")
|
||||
Observable<ApiResult<List<TipInfo>>> getTips();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.http.callback;
|
||||
|
||||
import com.xuexiang.xhttp2.callback.SimpleCallBack;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xhttp2.model.XHttpRequest;
|
||||
import com.xuexiang.xutil.common.StringUtils;
|
||||
import com.xuexiang.xutil.common.logger.Logger;
|
||||
|
||||
/**
|
||||
* 不带错误提示的网络请求回调
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-11-18 23:02
|
||||
*/
|
||||
public abstract class NoTipCallBack<T> extends SimpleCallBack<T> {
|
||||
|
||||
/**
|
||||
* 记录一下请求的url,确定出错的请求是哪个请求
|
||||
*/
|
||||
private String mUrl;
|
||||
|
||||
public NoTipCallBack() {
|
||||
|
||||
}
|
||||
|
||||
public NoTipCallBack(XHttpRequest req) {
|
||||
this(req.getUrl());
|
||||
}
|
||||
|
||||
public NoTipCallBack(String url) {
|
||||
mUrl = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if (!StringUtils.isEmpty(mUrl)) {
|
||||
Logger.e("网络请求的url:" + mUrl, e);
|
||||
} else {
|
||||
Logger.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.http.callback;
|
||||
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.xhttp2.callback.SimpleCallBack;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xhttp2.model.XHttpRequest;
|
||||
import com.xuexiang.xutil.common.StringUtils;
|
||||
import com.xuexiang.xutil.common.logger.Logger;
|
||||
|
||||
/**
|
||||
* 带错误toast提示的网络请求回调
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-11-18 23:02
|
||||
*/
|
||||
public abstract class TipCallBack<T> extends SimpleCallBack<T> {
|
||||
|
||||
/**
|
||||
* 记录一下请求的url,确定出错的请求是哪个请求
|
||||
*/
|
||||
private String mUrl;
|
||||
|
||||
public TipCallBack() {
|
||||
|
||||
}
|
||||
|
||||
public TipCallBack(XHttpRequest req) {
|
||||
this(req.getUrl());
|
||||
}
|
||||
|
||||
public TipCallBack(String url) {
|
||||
mUrl = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
XToastUtils.error(e);
|
||||
if (!StringUtils.isEmpty(mUrl)) {
|
||||
Logger.e("网络请求的url:" + mUrl, e);
|
||||
} else {
|
||||
Logger.e(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.http.callback;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.xhttp2.callback.ProgressLoadingCallBack;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xhttp2.model.XHttpRequest;
|
||||
import com.xuexiang.xhttp2.subsciber.impl.IProgressLoader;
|
||||
import com.xuexiang.xutil.common.StringUtils;
|
||||
import com.xuexiang.xutil.common.logger.Logger;
|
||||
|
||||
/**
|
||||
* 带错误toast提示和加载进度条的网络请求回调
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-11-18 23:16
|
||||
*/
|
||||
public abstract class TipProgressLoadingCallBack<T> extends ProgressLoadingCallBack<T> {
|
||||
/**
|
||||
* 记录一下请求的url,确定出错的请求是哪个请求
|
||||
*/
|
||||
private String mUrl;
|
||||
|
||||
public TipProgressLoadingCallBack(BaseFragment fragment) {
|
||||
super(fragment.getProgressLoader());
|
||||
}
|
||||
|
||||
public TipProgressLoadingCallBack(IProgressLoader iProgressLoader) {
|
||||
super(iProgressLoader);
|
||||
}
|
||||
|
||||
public TipProgressLoadingCallBack(@NonNull XHttpRequest req, IProgressLoader iProgressLoader) {
|
||||
this(req.getUrl(), iProgressLoader);
|
||||
}
|
||||
|
||||
public TipProgressLoadingCallBack(String url, IProgressLoader iProgressLoader) {
|
||||
super(iProgressLoader);
|
||||
mUrl = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
super.onError(e);
|
||||
XToastUtils.error(e);
|
||||
if (!StringUtils.isEmpty(mUrl)) {
|
||||
Logger.e("网络请求的url:" + mUrl, e);
|
||||
} else {
|
||||
Logger.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.http.entity;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
|
||||
/**
|
||||
* @author xuexiang
|
||||
* @since 2019-08-28 15:35
|
||||
*/
|
||||
@Keep
|
||||
public class TipInfo {
|
||||
|
||||
/**
|
||||
* title : 小贴士3
|
||||
* content : <p style=";font-family:'Microsoft YaHei';font-size:15px">欢迎关注我的微信公众号:我的Android开源之旅。</p><p><br/></p>
|
||||
*/
|
||||
|
||||
private String title;
|
||||
private String content;
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TipInfo{" +
|
||||
"title='" + title + '\'' +
|
||||
", content='" + content + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.http.loader;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.xuexiang.xhttp2.subsciber.impl.IProgressLoader;
|
||||
|
||||
/**
|
||||
* IProgressLoader的创建工厂实现接口
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-11-18 23:17
|
||||
*/
|
||||
public interface IProgressLoaderFactory {
|
||||
|
||||
|
||||
/**
|
||||
* 创建进度加载者
|
||||
*
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
IProgressLoader create(Context context);
|
||||
|
||||
|
||||
/**
|
||||
* 创建进度加载者
|
||||
*
|
||||
* @param context
|
||||
* @param message 默认提示
|
||||
* @return
|
||||
*/
|
||||
IProgressLoader create(Context context, String message);
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.http.loader;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
|
||||
import com.xuexiang.xhttp2.subsciber.impl.IProgressLoader;
|
||||
import com.xuexiang.xhttp2.subsciber.impl.OnProgressCancelListener;
|
||||
import com.xuexiang.xui.widget.dialog.MiniLoadingDialog;
|
||||
|
||||
/**
|
||||
* 默认进度加载
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-11-18 23:07
|
||||
*/
|
||||
public class MiniLoadingDialogLoader implements IProgressLoader {
|
||||
/**
|
||||
* 进度loading弹窗
|
||||
*/
|
||||
private MiniLoadingDialog mDialog;
|
||||
/**
|
||||
* 进度框取消监听
|
||||
*/
|
||||
private OnProgressCancelListener mOnProgressCancelListener;
|
||||
|
||||
public MiniLoadingDialogLoader(Context context) {
|
||||
this(context, "请求中...");
|
||||
}
|
||||
|
||||
public MiniLoadingDialogLoader(Context context, String msg) {
|
||||
mDialog = new MiniLoadingDialog(context, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoading() {
|
||||
return mDialog != null && mDialog.isShowing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateMessage(String msg) {
|
||||
if (mDialog != null) {
|
||||
mDialog.updateMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showLoading() {
|
||||
if (mDialog != null && !mDialog.isShowing()) {
|
||||
mDialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismissLoading() {
|
||||
if (mDialog != null && mDialog.isShowing()) {
|
||||
mDialog.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelable(boolean flag) {
|
||||
mDialog.setCancelable(flag);
|
||||
if (flag) {
|
||||
mDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialogInterface) {
|
||||
if (mOnProgressCancelListener != null) {
|
||||
mOnProgressCancelListener.onCancelProgress();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnProgressCancelListener(OnProgressCancelListener listener) {
|
||||
mOnProgressCancelListener = listener;
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.http.loader;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.xuexiang.xhttp2.subsciber.impl.IProgressLoader;
|
||||
|
||||
/**
|
||||
* 迷你加载框创建工厂
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-11-18 23:23
|
||||
*/
|
||||
public class MiniProgressLoaderFactory implements IProgressLoaderFactory {
|
||||
|
||||
@Override
|
||||
public IProgressLoader create(Context context) {
|
||||
return new MiniLoadingDialogLoader(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IProgressLoader create(Context context, String message) {
|
||||
return new MiniLoadingDialogLoader(context, message);
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.http.loader;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.xuexiang.xhttp2.subsciber.impl.IProgressLoader;
|
||||
|
||||
/**
|
||||
* 创建进度加载者
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-07-02 12:51
|
||||
*/
|
||||
public final class ProgressLoader {
|
||||
|
||||
private ProgressLoader() {
|
||||
throw new UnsupportedOperationException("u can't instantiate me...");
|
||||
}
|
||||
|
||||
private static IProgressLoaderFactory sIProgressLoaderFactory = new MiniProgressLoaderFactory();
|
||||
|
||||
public static void setIProgressLoaderFactory(IProgressLoaderFactory sIProgressLoaderFactory) {
|
||||
ProgressLoader.sIProgressLoaderFactory = sIProgressLoaderFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建进度加载者
|
||||
*
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
public static IProgressLoader create(Context context) {
|
||||
return sIProgressLoaderFactory.create(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建进度加载者
|
||||
*
|
||||
* @param context
|
||||
* @param message 默认提示信息
|
||||
* @return
|
||||
*/
|
||||
public static IProgressLoader create(Context context, String message) {
|
||||
return sIProgressLoaderFactory.create(context, message);
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.http.subscriber;
|
||||
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xhttp2.model.XHttpRequest;
|
||||
import com.xuexiang.xhttp2.subsciber.BaseSubscriber;
|
||||
import com.xuexiang.xutil.common.StringUtils;
|
||||
import com.xuexiang.xutil.common.logger.Logger;
|
||||
|
||||
/**
|
||||
* 不带错误toast提示的网络请求订阅,只存储错误的日志
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-11-18 23:11
|
||||
*/
|
||||
public abstract class NoTipRequestSubscriber<T> extends BaseSubscriber<T> {
|
||||
|
||||
/**
|
||||
* 记录一下请求的url,确定出错的请求是哪个请求
|
||||
*/
|
||||
private String mUrl;
|
||||
|
||||
public NoTipRequestSubscriber() {
|
||||
|
||||
}
|
||||
|
||||
public NoTipRequestSubscriber(XHttpRequest req) {
|
||||
this(req.getUrl());
|
||||
}
|
||||
|
||||
public NoTipRequestSubscriber(String url) {
|
||||
mUrl = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if (!StringUtils.isEmpty(mUrl)) {
|
||||
Logger.e("网络请求的url:" + mUrl, e);
|
||||
} else {
|
||||
Logger.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.http.subscriber;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xhttp2.model.XHttpRequest;
|
||||
import com.xuexiang.xhttp2.subsciber.ProgressLoadingSubscriber;
|
||||
import com.xuexiang.xhttp2.subsciber.impl.IProgressLoader;
|
||||
import com.xuexiang.xutil.common.StringUtils;
|
||||
import com.xuexiang.xutil.common.logger.Logger;
|
||||
|
||||
/**
|
||||
* 带错误toast提示和加载进度条的网络请求订阅
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-11-18 23:11
|
||||
*/
|
||||
public abstract class TipProgressLoadingSubscriber<T> extends ProgressLoadingSubscriber<T> {
|
||||
|
||||
/**
|
||||
* 记录一下请求的url,确定出错的请求是哪个请求
|
||||
*/
|
||||
private String mUrl;
|
||||
|
||||
public TipProgressLoadingSubscriber() {
|
||||
super();
|
||||
}
|
||||
|
||||
public TipProgressLoadingSubscriber(BaseFragment fragment) {
|
||||
super(fragment.getProgressLoader());
|
||||
}
|
||||
|
||||
public TipProgressLoadingSubscriber(IProgressLoader iProgressLoader) {
|
||||
super(iProgressLoader);
|
||||
}
|
||||
|
||||
public TipProgressLoadingSubscriber(@NonNull XHttpRequest req) {
|
||||
this(req.getUrl());
|
||||
}
|
||||
|
||||
public TipProgressLoadingSubscriber(String url) {
|
||||
super();
|
||||
mUrl = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
super.onError(e);
|
||||
XToastUtils.error(e);
|
||||
if (!StringUtils.isEmpty(mUrl)) {
|
||||
Logger.e("网络请求的url:" + mUrl, e);
|
||||
} else {
|
||||
Logger.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.http.subscriber;
|
||||
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xhttp2.model.XHttpRequest;
|
||||
import com.xuexiang.xhttp2.subsciber.BaseSubscriber;
|
||||
import com.xuexiang.xutil.common.StringUtils;
|
||||
import com.xuexiang.xutil.common.logger.Logger;
|
||||
|
||||
/**
|
||||
* 带错误toast提示的网络请求订阅
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-11-18 23:10
|
||||
*/
|
||||
public abstract class TipRequestSubscriber<T> extends BaseSubscriber<T> {
|
||||
/**
|
||||
* 记录一下请求的url,确定出错的请求是哪个请求
|
||||
*/
|
||||
private String mUrl;
|
||||
|
||||
public TipRequestSubscriber() {
|
||||
|
||||
}
|
||||
|
||||
public TipRequestSubscriber(@NonNull XHttpRequest req) {
|
||||
this(req.getUrl());
|
||||
}
|
||||
|
||||
public TipRequestSubscriber(String url) {
|
||||
mUrl = url;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
XToastUtils.error(e);
|
||||
if (!StringUtils.isEmpty(mUrl)) {
|
||||
Logger.e("网络请求的url:" + mUrl, e);
|
||||
} else {
|
||||
Logger.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.webview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.xrouter.facade.Postcard;
|
||||
import com.xuexiang.xrouter.facade.callback.NavCallback;
|
||||
import com.xuexiang.xrouter.launcher.XRouter;
|
||||
import com.xuexiang.xui.widget.slideback.SlideBack;
|
||||
|
||||
/**
|
||||
* 壳浏览器
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019/1/5 上午12:15
|
||||
*/
|
||||
public class AgentWebActivity extends AppCompatActivity {
|
||||
|
||||
/**
|
||||
* 请求浏览器
|
||||
*
|
||||
* @param url
|
||||
*/
|
||||
public static void goWeb(Context context, final String url) {
|
||||
Intent intent = new Intent(context, AgentWebActivity.class);
|
||||
intent.putExtra(AgentWebFragment.KEY_URL, url);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_agent_web);
|
||||
|
||||
SlideBack.with(this)
|
||||
.haveScroll(true)
|
||||
.callBack(this::finish)
|
||||
.register();
|
||||
|
||||
Uri uri = getIntent().getData();
|
||||
if (uri != null) {
|
||||
XRouter.getInstance().build(uri).navigation(this, new NavCallback() {
|
||||
@Override
|
||||
public void onArrival(Postcard postcard) {
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLost(Postcard postcard) {
|
||||
loadUrl(uri.toString());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
String url = getIntent().getStringExtra(AgentWebFragment.KEY_URL);
|
||||
loadUrl(url);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadUrl(String url) {
|
||||
if (url != null) {
|
||||
openFragment(url);
|
||||
} else {
|
||||
XToastUtils.error("数据出错!");
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
private AgentWebFragment mAgentWebFragment;
|
||||
|
||||
private void openFragment(String url) {
|
||||
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
|
||||
ft.add(R.id.container_frame_layout, mAgentWebFragment = AgentWebFragment.getInstance(url));
|
||||
ft.commit();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
AgentWebFragment agentWebFragment = mAgentWebFragment;
|
||||
if (agentWebFragment != null) {
|
||||
if (((FragmentKeyDown) agentWebFragment).onFragmentKeyDown(keyCode, event)) {
|
||||
return true;
|
||||
} else {
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
SlideBack.unregister(this);
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
@@ -1,658 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.webview;
|
||||
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebResourceError;
|
||||
import android.webkit.WebResourceRequest;
|
||||
import android.webkit.WebResourceResponse;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.appcompat.widget.PopupMenu;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.just.agentweb.action.PermissionInterceptor;
|
||||
import com.just.agentweb.core.AgentWeb;
|
||||
import com.just.agentweb.core.client.MiddlewareWebChromeBase;
|
||||
import com.just.agentweb.core.client.MiddlewareWebClientBase;
|
||||
import com.just.agentweb.core.client.WebListenerManager;
|
||||
import com.just.agentweb.core.web.AbsAgentWebSettings;
|
||||
import com.just.agentweb.core.web.AgentWebConfig;
|
||||
import com.just.agentweb.core.web.IAgentWebSettings;
|
||||
import com.just.agentweb.download.AgentWebDownloader;
|
||||
import com.just.agentweb.download.DefaultDownloadImpl;
|
||||
import com.just.agentweb.download.DownloadListenerAdapter;
|
||||
import com.just.agentweb.download.DownloadingService;
|
||||
import com.just.agentweb.utils.LogUtils;
|
||||
import com.just.agentweb.widget.IWebLayout;
|
||||
import com.kerwin.wumei.MyApp;
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.xutil.net.JsonUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* 通用WebView页面
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019/1/4 下午11:13
|
||||
*/
|
||||
public class AgentWebFragment extends Fragment implements FragmentKeyDown {
|
||||
public static final String KEY_URL = "com.xuexiang.xuidemo.base.webview.key_url";
|
||||
|
||||
private ImageView mBackImageView;
|
||||
private View mLineView;
|
||||
private ImageView mFinishImageView;
|
||||
private TextView mTitleTextView;
|
||||
private AgentWeb mAgentWeb;
|
||||
private ImageView mMoreImageView;
|
||||
private PopupMenu mPopupMenu;
|
||||
public static final String TAG = AgentWebFragment.class.getSimpleName();
|
||||
private DownloadingService mDownloadingService;
|
||||
|
||||
public static AgentWebFragment getInstance(String url) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(KEY_URL, url);
|
||||
return getInstance(bundle);
|
||||
}
|
||||
|
||||
public static AgentWebFragment getInstance(Bundle bundle) {
|
||||
AgentWebFragment fragment = new AgentWebFragment();
|
||||
if (bundle != null) {
|
||||
fragment.setArguments(bundle);
|
||||
}
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_agentweb, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
mAgentWeb = AgentWeb.with(this)
|
||||
//传入AgentWeb的父控件。
|
||||
.setAgentWebParent((LinearLayout) view, -1, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT))
|
||||
//设置进度条颜色与高度,-1为默认值,高度为2,单位为dp。
|
||||
.useDefaultIndicator(-1, 3)
|
||||
//设置 IAgentWebSettings。
|
||||
.setAgentWebWebSettings(getSettings())
|
||||
//WebViewClient , 与 WebView 使用一致 ,但是请勿获取WebView调用setWebViewClient(xx)方法了,会覆盖AgentWeb DefaultWebClient,同时相应的中间件也会失效。
|
||||
.setWebViewClient(mWebViewClient)
|
||||
//WebChromeClient
|
||||
.setWebChromeClient(mWebChromeClient)
|
||||
//设置WebChromeClient中间件,支持多个WebChromeClient,AgentWeb 3.0.0 加入。
|
||||
.useMiddlewareWebChrome(getMiddlewareWebChrome())
|
||||
//设置WebViewClient中间件,支持多个WebViewClient, AgentWeb 3.0.0 加入。
|
||||
.useMiddlewareWebClient(getMiddlewareWebClient())
|
||||
//权限拦截 2.0.0 加入。
|
||||
.setPermissionInterceptor(mPermissionInterceptor)
|
||||
//严格模式 Android 4.2.2 以下会放弃注入对象 ,使用AgentWebView没影响。
|
||||
.setSecurityType(AgentWeb.SecurityType.STRICT_CHECK)
|
||||
//自定义UI AgentWeb3.0.0 加入。
|
||||
.setAgentWebUIController(new UIController(getActivity()))
|
||||
//参数1是错误显示的布局,参数2点击刷新控件ID -1表示点击整个布局都刷新, AgentWeb 3.0.0 加入。
|
||||
.setMainFrameErrorView(R.layout.agentweb_error_page, -1)
|
||||
.setWebLayout(getWebLayout())
|
||||
.interceptUnkownUrl()
|
||||
//创建AgentWeb。
|
||||
.createAgentWeb()
|
||||
.ready()//设置 WebSettings。
|
||||
//WebView载入该url地址的页面并显示。
|
||||
.go(getUrl());
|
||||
|
||||
if (MyApp.isDebug()) {
|
||||
AgentWebConfig.debug();
|
||||
}
|
||||
|
||||
// 得到 AgentWeb 最底层的控件
|
||||
addBackgroundChild(mAgentWeb.getWebCreator().getWebParentLayout());
|
||||
|
||||
initView(view);
|
||||
|
||||
// AgentWeb 没有把WebView的功能全面覆盖 ,所以某些设置 AgentWeb 没有提供,请从WebView方面入手设置。
|
||||
mAgentWeb.getWebCreator().getWebView().setOverScrollMode(WebView.OVER_SCROLL_NEVER);
|
||||
}
|
||||
|
||||
protected IWebLayout getWebLayout() {
|
||||
return new WebLayout(getActivity());
|
||||
}
|
||||
|
||||
protected void initView(View view) {
|
||||
mBackImageView = view.findViewById(R.id.iv_back);
|
||||
mLineView = view.findViewById(R.id.view_line);
|
||||
mFinishImageView = view.findViewById(R.id.iv_finish);
|
||||
mTitleTextView = view.findViewById(R.id.toolbar_title);
|
||||
mBackImageView.setOnClickListener(mOnClickListener);
|
||||
mFinishImageView.setOnClickListener(mOnClickListener);
|
||||
mMoreImageView = view.findViewById(R.id.iv_more);
|
||||
mMoreImageView.setOnClickListener(mOnClickListener);
|
||||
pageNavigator(View.GONE);
|
||||
}
|
||||
|
||||
protected void addBackgroundChild(FrameLayout frameLayout) {
|
||||
TextView textView = new TextView(frameLayout.getContext());
|
||||
textView.setText("技术由 AgentWeb 提供");
|
||||
textView.setTextSize(16);
|
||||
textView.setTextColor(Color.parseColor("#727779"));
|
||||
frameLayout.setBackgroundColor(Color.parseColor("#272b2d"));
|
||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(-2, -2);
|
||||
params.gravity = Gravity.CENTER_HORIZONTAL;
|
||||
final float scale = frameLayout.getContext().getResources().getDisplayMetrics().density;
|
||||
params.topMargin = (int) (15 * scale + 0.5f);
|
||||
frameLayout.addView(textView, 0, params);
|
||||
}
|
||||
|
||||
|
||||
private void pageNavigator(int tag) {
|
||||
mBackImageView.setVisibility(tag);
|
||||
mLineView.setVisibility(tag);
|
||||
}
|
||||
|
||||
private View.OnClickListener mOnClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.iv_back:
|
||||
// true表示AgentWeb处理了该事件
|
||||
if (!mAgentWeb.back()) {
|
||||
AgentWebFragment.this.getActivity().finish();
|
||||
}
|
||||
break;
|
||||
case R.id.iv_finish:
|
||||
AgentWebFragment.this.getActivity().finish();
|
||||
break;
|
||||
case R.id.iv_more:
|
||||
showPoPup(v);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//========================================//
|
||||
|
||||
/**
|
||||
* 权限申请拦截器
|
||||
*/
|
||||
protected PermissionInterceptor mPermissionInterceptor = new PermissionInterceptor() {
|
||||
/**
|
||||
* PermissionInterceptor 能达到 url1 允许授权, url2 拒绝授权的效果。
|
||||
* @param url
|
||||
* @param permissions
|
||||
* @param action
|
||||
* @return true 该Url对应页面请求权限进行拦截 ,false 表示不拦截。
|
||||
*/
|
||||
@Override
|
||||
public boolean intercept(String url, String[] permissions, String action) {
|
||||
Log.i(TAG, "mUrl:" + url + " permission:" + JsonUtil.toJson(permissions) + " action:" + action);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
//=====================下载============================//
|
||||
|
||||
/**
|
||||
* 更新于 AgentWeb 4.0.0,下载监听
|
||||
*/
|
||||
protected DownloadListenerAdapter mDownloadListenerAdapter = new DownloadListenerAdapter() {
|
||||
/**
|
||||
*
|
||||
* @param url 下载链接
|
||||
* @param userAgent UserAgent
|
||||
* @param contentDisposition ContentDisposition
|
||||
* @param mimetype 资源的媒体类型
|
||||
* @param contentLength 文件长度
|
||||
* @param extra 下载配置 , 用户可以通过 Extra 修改下载icon , 关闭进度条 , 是否强制下载。
|
||||
* @return true 表示用户处理了该下载事件 , false 交给 AgentWeb 下载
|
||||
*/
|
||||
@Override
|
||||
public boolean onStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength, AgentWebDownloader.Extra extra) {
|
||||
LogUtils.i(TAG, "onStart:" + url);
|
||||
// 是否开启断点续传
|
||||
extra.setOpenBreakPointDownload(true)
|
||||
//下载通知的icon
|
||||
.setIcon(R.drawable.ic_file_download_black_24dp)
|
||||
// 连接的超时时间
|
||||
.setConnectTimeOut(6000)
|
||||
// 以8KB位单位,默认60s ,如果60s内无法从网络流中读满8KB数据,则抛出异常
|
||||
.setBlockMaxTime(10 * 60 * 1000)
|
||||
// 下载的超时时间
|
||||
.setDownloadTimeOut(Long.MAX_VALUE)
|
||||
// 串行下载更节省资源哦
|
||||
.setParallelDownload(false)
|
||||
// false 关闭进度通知
|
||||
.setEnableIndicator(true)
|
||||
// 自定义请求头
|
||||
.addHeader("Cookie", "xx")
|
||||
// 下载完成自动打开
|
||||
.setAutoOpen(true)
|
||||
// 强制下载,不管网络网络类型
|
||||
.setForceDownload(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 不需要暂停或者停止下载该方法可以不必实现
|
||||
* @param url
|
||||
* @param downloadingService 用户可以通过 DownloadingService#shutdownNow 终止下载
|
||||
*/
|
||||
@Override
|
||||
public void onBindService(String url, DownloadingService downloadingService) {
|
||||
super.onBindService(url, downloadingService);
|
||||
mDownloadingService = downloadingService;
|
||||
LogUtils.i(TAG, "onBindService:" + url + " DownloadingService:" + downloadingService);
|
||||
}
|
||||
|
||||
/**
|
||||
* 回调onUnbindService方法,让用户释放掉 DownloadingService。
|
||||
* @param url
|
||||
* @param downloadingService
|
||||
*/
|
||||
@Override
|
||||
public void onUnbindService(String url, DownloadingService downloadingService) {
|
||||
super.onUnbindService(url, downloadingService);
|
||||
mDownloadingService = null;
|
||||
LogUtils.i(TAG, "onUnbindService:" + url);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param url 下载链接
|
||||
* @param loaded 已经下载的长度
|
||||
* @param length 文件的总大小
|
||||
* @param usedTime 耗时 ,单位ms
|
||||
* 注意该方法回调在子线程 ,线程名 AsyncTask #XX 或者 AgentWeb # XX
|
||||
*/
|
||||
@Override
|
||||
public void onProgress(String url, long loaded, long length, long usedTime) {
|
||||
int mProgress = (int) ((loaded) / Float.valueOf(length) * 100);
|
||||
LogUtils.i(TAG, "onProgress:" + mProgress);
|
||||
super.onProgress(url, loaded, length, usedTime);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param path 文件的绝对路径
|
||||
* @param url 下载地址
|
||||
* @param throwable 如果异常,返回给用户异常
|
||||
* @return true 表示用户处理了下载完成后续的事件 ,false 默认交给AgentWeb 处理
|
||||
*/
|
||||
@Override
|
||||
public boolean onResult(String path, String url, Throwable throwable) {
|
||||
//下载成功
|
||||
if (null == throwable) {
|
||||
//do you work
|
||||
} else {//下载失败
|
||||
|
||||
}
|
||||
// true 不会发出下载完成的通知 , 或者打开文件
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @return IAgentWebSettings
|
||||
*/
|
||||
public IAgentWebSettings getSettings() {
|
||||
return new AbsAgentWebSettings() {
|
||||
private AgentWeb mAgentWeb;
|
||||
|
||||
@Override
|
||||
protected void bindAgentWebSupport(AgentWeb agentWeb) {
|
||||
this.mAgentWeb = agentWeb;
|
||||
}
|
||||
|
||||
/**
|
||||
* AgentWeb 4.0.0 内部删除了 DownloadListener 监听 ,以及相关API ,将 Download 部分完全抽离出来独立一个库,
|
||||
* 如果你需要使用 AgentWeb Download 部分 , 请依赖上 compile 'com.just.agentweb:download:4.0.0 ,
|
||||
* 如果你需要监听下载结果,请自定义 AgentWebSetting , New 出 DefaultDownloadImpl,传入DownloadListenerAdapter
|
||||
* 实现进度或者结果监听,例如下面这个例子,如果你不需要监听进度,或者下载结果,下面 setDownloader 的例子可以忽略。
|
||||
* @param webView
|
||||
* @param downloadListener
|
||||
* @return WebListenerManager
|
||||
*/
|
||||
@Override
|
||||
public WebListenerManager setDownloader(WebView webView, android.webkit.DownloadListener downloadListener) {
|
||||
return super.setDownloader(webView,
|
||||
DefaultDownloadImpl
|
||||
.create(getActivity(),
|
||||
webView,
|
||||
mDownloadListenerAdapter,
|
||||
mDownloadListenerAdapter,
|
||||
this.mAgentWeb.getPermissionInterceptor()));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//===================WebChromeClient 和 WebViewClient===========================//
|
||||
/**
|
||||
* 页面空白,请检查scheme是否加上, scheme://host:port/path?query&query 。
|
||||
*
|
||||
* @return mUrl
|
||||
*/
|
||||
public String getUrl() {
|
||||
String target = "";
|
||||
Bundle bundle = getArguments();
|
||||
if (bundle != null) {
|
||||
target = bundle.getString(KEY_URL);
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(target)) {
|
||||
target = "https://github.com/xuexiangjys";
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
protected WebChromeClient mWebChromeClient = new WebChromeClient() {
|
||||
@Override
|
||||
public void onProgressChanged(WebView view, int newProgress) {
|
||||
Log.i(TAG, "onProgressChanged:" + newProgress + " view:" + view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedTitle(WebView view, String title) {
|
||||
super.onReceivedTitle(view, title);
|
||||
if (mTitleTextView != null && !TextUtils.isEmpty(title)) {
|
||||
if (title.length() > 10) {
|
||||
title = title.substring(0, 10).concat("...");
|
||||
}
|
||||
mTitleTextView.setText(title);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
protected WebViewClient mWebViewClient = new WebViewClient() {
|
||||
|
||||
private HashMap<String, Long> timer = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
|
||||
super.onReceivedError(view, request, error);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
|
||||
return shouldOverrideUrlLoading(view, request.getUrl() + "");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
|
||||
return super.shouldInterceptRequest(view, request);
|
||||
}
|
||||
|
||||
//
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(final WebView view, String url) {
|
||||
//intent:// scheme的处理 如果返回false , 则交给 DefaultWebClient 处理 , 默认会打开该Activity , 如果Activity不存在则跳到应用市场上去. true 表示拦截
|
||||
//例如优酷视频播放 ,intent://play?...package=com.youku.phone;end;
|
||||
//优酷想唤起自己应用播放该视频 , 下面拦截地址返回 true 则会在应用内 H5 播放 ,禁止优酷唤起播放该视频, 如果返回 false , DefaultWebClient 会根据intent 协议处理 该地址 , 首先匹配该应用存不存在 ,如果存在 , 唤起该应用播放 , 如果不存在 , 则跳到应用市场下载该应用 .
|
||||
if (url.startsWith("intent://") && url.contains("com.youku.phone")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageStarted(WebView view, String url, Bitmap favicon) {
|
||||
Log.i(TAG, "mUrl:" + url + " onPageStarted target:" + getUrl());
|
||||
timer.put(url, System.currentTimeMillis());
|
||||
if (url.equals(getUrl())) {
|
||||
pageNavigator(View.GONE);
|
||||
} else {
|
||||
pageNavigator(View.VISIBLE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
super.onPageFinished(view, url);
|
||||
|
||||
if (timer.get(url) != null) {
|
||||
long overTime = System.currentTimeMillis();
|
||||
Long startTime = timer.get(url);
|
||||
Log.i(TAG, " page mUrl:" + url + " used time:" + (overTime - startTime));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
|
||||
super.onReceivedHttpError(view, request, errorResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
|
||||
super.onReceivedError(view, errorCode, description, failingUrl);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
|
||||
//========================菜单功能================================//
|
||||
|
||||
/**
|
||||
* 打开浏览器
|
||||
*
|
||||
* @param targetUrl 外部浏览器打开的地址
|
||||
*/
|
||||
private void openBrowser(String targetUrl) {
|
||||
if (TextUtils.isEmpty(targetUrl) || targetUrl.startsWith("file://")) {
|
||||
XToastUtils.toast(targetUrl + " 该链接无法使用浏览器打开。");
|
||||
return;
|
||||
}
|
||||
Intent intent = new Intent();
|
||||
intent.setAction("android.intent.action.VIEW");
|
||||
Uri uri = Uri.parse(targetUrl);
|
||||
intent.setData(uri);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 显示更多菜单
|
||||
*
|
||||
* @param view 菜单依附在该View下面
|
||||
*/
|
||||
private void showPoPup(View view) {
|
||||
if (mPopupMenu == null) {
|
||||
mPopupMenu = new PopupMenu(getContext(), view);
|
||||
mPopupMenu.inflate(R.menu.menu_toolbar_web);
|
||||
mPopupMenu.setOnMenuItemClickListener(mOnMenuItemClickListener);
|
||||
}
|
||||
mPopupMenu.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* 菜单事件
|
||||
*/
|
||||
private PopupMenu.OnMenuItemClickListener mOnMenuItemClickListener = new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.refresh:
|
||||
if (mAgentWeb != null) {
|
||||
mAgentWeb.getUrlLoader().reload(); // 刷新
|
||||
}
|
||||
return true;
|
||||
|
||||
case R.id.copy:
|
||||
if (mAgentWeb != null) {
|
||||
toCopy(getContext(), mAgentWeb.getWebCreator().getWebView().getUrl());
|
||||
}
|
||||
return true;
|
||||
case R.id.default_browser:
|
||||
if (mAgentWeb != null) {
|
||||
openBrowser(mAgentWeb.getWebCreator().getWebView().getUrl());
|
||||
}
|
||||
return true;
|
||||
case R.id.share:
|
||||
if (mAgentWeb != null) {
|
||||
shareWebUrl(mAgentWeb.getWebCreator().getWebView().getUrl());
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 分享网页链接
|
||||
*
|
||||
* @param url 网页链接
|
||||
*/
|
||||
private void shareWebUrl(String url) {
|
||||
Intent shareIntent = new Intent();
|
||||
shareIntent.setAction(Intent.ACTION_SEND);
|
||||
shareIntent.putExtra(Intent.EXTRA_TEXT, url);
|
||||
shareIntent.setType("text/plain");
|
||||
//设置分享列表的标题,并且每次都显示分享列表
|
||||
startActivity(Intent.createChooser(shareIntent, "分享到"));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 复制字符串
|
||||
*
|
||||
* @param context
|
||||
* @param text
|
||||
*/
|
||||
private void toCopy(Context context, String text) {
|
||||
ClipboardManager manager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
if (manager == null) {
|
||||
return;
|
||||
}
|
||||
manager.setPrimaryClip(ClipData.newPlainText(null, text));
|
||||
}
|
||||
|
||||
//===================生命周期管理===========================//
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
mAgentWeb.getWebLifeCycle().onResume();//恢复
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
mAgentWeb.getWebLifeCycle().onPause(); //暂停应用内所有WebView , 调用mWebView.resumeTimers();/mAgentWeb.getWebLifeCycle().onResume(); 恢复。
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onFragmentKeyDown(int keyCode, KeyEvent event) {
|
||||
return mAgentWeb.handleKeyEvent(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
mAgentWeb.getWebLifeCycle().onDestroy();
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
//===================中间键===========================//
|
||||
|
||||
|
||||
/**
|
||||
* MiddlewareWebClientBase 是 AgentWeb 3.0.0 提供一个强大的功能,
|
||||
* 如果用户需要使用 AgentWeb 提供的功能, 不想重写 WebClientView方
|
||||
* 法覆盖AgentWeb提供的功能,那么 MiddlewareWebClientBase 是一个
|
||||
* 不错的选择 。
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected MiddlewareWebClientBase getMiddlewareWebClient() {
|
||||
return new MiddlewareWebViewClient() {
|
||||
/**
|
||||
*
|
||||
* @param view
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
// 拦截 url,不执行 DefaultWebClient#shouldOverrideUrlLoading
|
||||
if (url.startsWith("agentweb")) {
|
||||
Log.i(TAG, "agentweb scheme ~");
|
||||
return true;
|
||||
}
|
||||
// 执行 DefaultWebClient#shouldOverrideUrlLoading
|
||||
if (super.shouldOverrideUrlLoading(view, url)) {
|
||||
return true;
|
||||
}
|
||||
// do you work
|
||||
return false;
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
|
||||
return super.shouldOverrideUrlLoading(view, request);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected MiddlewareWebChromeBase getMiddlewareWebChrome() {
|
||||
return new MiddlewareChromeClient() {
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.webview;
|
||||
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import com.just.agentweb.core.AgentWeb;
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
|
||||
/**
|
||||
* 基础web
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019/5/28 10:22
|
||||
*/
|
||||
public abstract class BaseWebViewFragment extends BaseFragment {
|
||||
|
||||
protected AgentWeb mAgentWeb;
|
||||
|
||||
//===================生命周期管理===========================//
|
||||
@Override
|
||||
public void onResume() {
|
||||
if (mAgentWeb != null) {
|
||||
//恢复
|
||||
mAgentWeb.getWebLifeCycle().onResume();
|
||||
}
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
if (mAgentWeb != null) {
|
||||
//暂停应用内所有WebView , 调用mWebView.resumeTimers();/mAgentWeb.getWebLifeCycle().onResume(); 恢复。
|
||||
mAgentWeb.getWebLifeCycle().onPause();
|
||||
}
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
return mAgentWeb != null && mAgentWeb.handleKeyEvent(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
if (mAgentWeb != null) {
|
||||
mAgentWeb.destroy();
|
||||
}
|
||||
super.onDestroyView();
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.webview;
|
||||
|
||||
import android.view.KeyEvent;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019/1/4 下午11:32
|
||||
*/
|
||||
public interface FragmentKeyDown {
|
||||
|
||||
/**
|
||||
* fragment按键监听
|
||||
* @param keyCode
|
||||
* @param event
|
||||
* @return
|
||||
*/
|
||||
boolean onFragmentKeyDown(int keyCode, KeyEvent event);
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.webview;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.webkit.WebView;
|
||||
|
||||
/**
|
||||
* 修复 Android 5.0 & 5.1 打开 WebView 闪退问题:
|
||||
* 参阅 https://stackoverflow.com/questions/41025200/android-view-inflateexception-error-inflating-class-android-webkit-webview
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class LollipopFixedWebView extends WebView {
|
||||
public LollipopFixedWebView(Context context) {
|
||||
super(getFixedContext(context));
|
||||
}
|
||||
|
||||
public LollipopFixedWebView(Context context, AttributeSet attrs) {
|
||||
super(getFixedContext(context), attrs);
|
||||
}
|
||||
|
||||
public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(getFixedContext(context), attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(getFixedContext(context), attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
public LollipopFixedWebView(Context context, AttributeSet attrs, int defStyleAttr, boolean privateBrowsing) {
|
||||
super(getFixedContext(context), attrs, defStyleAttr, privateBrowsing);
|
||||
}
|
||||
|
||||
public static Context getFixedContext(Context context) {
|
||||
if (isLollipopWebViewBug()) {
|
||||
// Avoid crashing on Android 5 and 6 (API level 21 to 23)
|
||||
return context.createConfigurationContext(new Configuration());
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
public static boolean isLollipopWebViewBug() {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Build.VERSION.SDK_INT < Build.VERSION_CODES.M;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.webview;
|
||||
|
||||
import android.util.Log;
|
||||
import android.webkit.JsResult;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import com.just.agentweb.core.client.MiddlewareWebChromeBase;
|
||||
|
||||
/**
|
||||
* WebChrome(WebChromeClient主要辅助WebView处理JavaScript的对话框、网站图片、网站title、加载进度等)中间件
|
||||
* 【浏览器】
|
||||
* @author xuexiang
|
||||
* @since 2019/1/4 下午11:31
|
||||
*/
|
||||
public class MiddlewareChromeClient extends MiddlewareWebChromeBase {
|
||||
|
||||
public MiddlewareChromeClient() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
|
||||
Log.i("Info", "onJsAlert:" + url);
|
||||
return super.onJsAlert(view, url, message, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(WebView view, int newProgress) {
|
||||
super.onProgressChanged(view, newProgress);
|
||||
Log.i("Info", "onProgressChanged:");
|
||||
}
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.webview;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.webkit.WebResourceRequest;
|
||||
import android.webkit.WebResourceResponse;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.just.agentweb.core.client.MiddlewareWebClientBase;
|
||||
import com.kerwin.wumei.R;
|
||||
import com.xuexiang.xui.utils.ResUtils;
|
||||
|
||||
/**
|
||||
* 【网络请求、加载】
|
||||
* WebClient(WebViewClient 这个类主要帮助WebView处理各种通知、url加载,请求时间的)中间件
|
||||
* <p>
|
||||
* <p>
|
||||
* 方法的执行顺序,例如下面用了7个中间件一个 WebViewClient
|
||||
* <p>
|
||||
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 1
|
||||
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 2
|
||||
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 3
|
||||
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 4
|
||||
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 5
|
||||
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 6
|
||||
* .useMiddlewareWebClient(getMiddlewareWebClient()) // 7
|
||||
* DefaultWebClient // 8
|
||||
* .setWebViewClient(mWebViewClient) // 9
|
||||
* <p>
|
||||
* <p>
|
||||
* 典型的洋葱模型
|
||||
* 对象内部的方法执行顺序: 1->2->3->4->5->6->7->8->9->8->7->6->5->4->3->2->1
|
||||
* <p>
|
||||
* <p>
|
||||
* 中断中间件的执行, 删除super.methodName(...) 这行即可
|
||||
* <p>
|
||||
* 这里主要是做去广告的工作
|
||||
*/
|
||||
public class MiddlewareWebViewClient extends MiddlewareWebClientBase {
|
||||
|
||||
public MiddlewareWebViewClient() {
|
||||
}
|
||||
|
||||
private static int count = 1;
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
|
||||
Log.i("Info", "MiddlewareWebViewClient -- > shouldOverrideUrlLoading:" + request.getUrl().toString() + " c:" + (count++));
|
||||
if (shouldOverrideUrlLoadingByApp(view, request.getUrl().toString())) {
|
||||
return true;
|
||||
}
|
||||
return super.shouldOverrideUrlLoading(view, request);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
Log.i("Info", "MiddlewareWebViewClient -- > shouldOverrideUrlLoading:" + url + " c:" + (count++));
|
||||
if (shouldOverrideUrlLoadingByApp(view, url)) {
|
||||
return true;
|
||||
}
|
||||
return super.shouldOverrideUrlLoading(view, url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
|
||||
url = url.toLowerCase();
|
||||
if (!hasAdUrl(url)) {
|
||||
//正常加载
|
||||
return super.shouldInterceptRequest(view, url);
|
||||
} else {
|
||||
//含有广告资源屏蔽请求
|
||||
return new WebResourceResponse(null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
|
||||
String url = request.getUrl().toString().toLowerCase();
|
||||
if (!hasAdUrl(url)) {
|
||||
//正常加载
|
||||
return super.shouldInterceptRequest(view, request);
|
||||
} else {
|
||||
//含有广告资源屏蔽请求
|
||||
return new WebResourceResponse(null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否存在广告的链接
|
||||
*
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
private static boolean hasAdUrl(String url) {
|
||||
String[] adUrls = ResUtils.getStringArray(R.array.adBlockUrl);
|
||||
for (String adUrl : adUrls) {
|
||||
if (url.contains(adUrl)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据url的scheme处理跳转第三方app的业务,true代表拦截,false代表不拦截
|
||||
*/
|
||||
private boolean shouldOverrideUrlLoadingByApp(WebView webView, final String url) {
|
||||
if (url.startsWith("http") || url.startsWith("https") || url.startsWith("ftp")) {
|
||||
//不拦截http, https, ftp的请求
|
||||
Uri uri = Uri.parse(url);
|
||||
if (uri != null && !(WebViewInterceptDialog.APP_LINK_HOST.equals(uri.getHost())
|
||||
//防止xui官网被拦截
|
||||
&& url.contains("xpage"))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
WebViewInterceptDialog.show(url);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.webview;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import com.just.agentweb.core.web.AgentWebUIControllerImplBase;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* 如果你需要修改某一个AgentWeb 内部的某一个弹窗 ,请看下面的例子
|
||||
* 注意写法一定要参照 DefaultUIController 的写法 ,因为UI自由定制,但是回调的方式是固定的,并且一定要回调。
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-10-30 23:18
|
||||
*/
|
||||
public class UIController extends AgentWebUIControllerImplBase {
|
||||
|
||||
private WeakReference<Activity> mActivity;
|
||||
|
||||
public UIController(Activity activity) {
|
||||
mActivity = new WeakReference<>(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShowMessage(String message, String from) {
|
||||
super.onShowMessage(message, from);
|
||||
Log.i(TAG, "message:" + message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectItemsPrompt(WebView view, String url, String[] items, Handler.Callback callback) {
|
||||
// 使用默认的UI
|
||||
super.onSelectItemsPrompt(view, url, items, callback);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.webview;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.just.agentweb.widget.IWebLayout;
|
||||
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
|
||||
import com.kerwin.wumei.R;
|
||||
|
||||
/**
|
||||
* 定义支持下来回弹的WebView
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019/1/5 上午2:01
|
||||
*/
|
||||
public class WebLayout implements IWebLayout {
|
||||
|
||||
private final SmartRefreshLayout mSmartRefreshLayout;
|
||||
private WebView mWebView;
|
||||
|
||||
public WebLayout(Activity activity) {
|
||||
mSmartRefreshLayout = (SmartRefreshLayout) LayoutInflater.from(activity).inflate(R.layout.fragment_pulldown_web, null);
|
||||
mWebView = mSmartRefreshLayout.findViewById(R.id.webView);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewGroup getLayout() {
|
||||
return mSmartRefreshLayout;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public WebView getWebView() {
|
||||
return mWebView;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.webview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.xui.utils.ResUtils;
|
||||
import com.xuexiang.xui.widget.dialog.DialogLoader;
|
||||
import com.xuexiang.xutil.XUtil;
|
||||
import com.xuexiang.xutil.app.ActivityUtils;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
/**
|
||||
* WebView拦截提示
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-10-21 9:51
|
||||
*/
|
||||
public class WebViewInterceptDialog extends AppCompatActivity implements DialogInterface.OnDismissListener {
|
||||
|
||||
private static final String KEY_INTERCEPT_URL = "key_intercept_url";
|
||||
|
||||
// TODO: 2019-10-30 这里修改你的applink
|
||||
public static final String APP_LINK_HOST = "xuexiangjys.club";
|
||||
public static final String APP_LINK_ACTION = "com.xuexiang.xui.applink";
|
||||
|
||||
|
||||
/**
|
||||
* 显示WebView拦截提示
|
||||
*
|
||||
* @param url 需要拦截处理的url
|
||||
*/
|
||||
public static void show(String url) {
|
||||
ActivityUtils.startActivity(WebViewInterceptDialog.class, KEY_INTERCEPT_URL, url);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
String url = getIntent().getStringExtra(KEY_INTERCEPT_URL);
|
||||
|
||||
DialogLoader.getInstance().showConfirmDialog(
|
||||
this,
|
||||
getOpenTitle(url),
|
||||
ResUtils.getString(R.string.lab_yes),
|
||||
(dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
if (isAppLink(url)) {
|
||||
openAppLink(this, url);
|
||||
} else {
|
||||
openApp(url);
|
||||
}
|
||||
},
|
||||
ResUtils.getString(R.string.lab_no),
|
||||
(dialog, which) -> dialog.dismiss()
|
||||
).setOnDismissListener(this);
|
||||
|
||||
}
|
||||
|
||||
private String getOpenTitle(String url) {
|
||||
String scheme = getScheme(url);
|
||||
if ("mqqopensdkapi".equals(scheme)) {
|
||||
return "是否允许页面打开\"QQ\"?";
|
||||
} else {
|
||||
return ResUtils.getString(R.string.lab_open_third_app);
|
||||
}
|
||||
}
|
||||
|
||||
private String getScheme(String url) {
|
||||
try {
|
||||
Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
|
||||
return intent.getScheme();
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private boolean isAppLink(String url) {
|
||||
Uri uri = Uri.parse(url);
|
||||
return uri != null
|
||||
&& APP_LINK_HOST.equals(uri.getHost())
|
||||
&& (url.startsWith("http") || url.startsWith("https"));
|
||||
}
|
||||
|
||||
|
||||
private void openApp(String url) {
|
||||
Intent intent;
|
||||
try {
|
||||
intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
XUtil.getContext().startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
XToastUtils.error("您所打开的第三方App未安装!");
|
||||
}
|
||||
}
|
||||
|
||||
private void openAppLink(Context context, String url) {
|
||||
try {
|
||||
Intent intent = new Intent(APP_LINK_ACTION);
|
||||
intent.setData(Uri.parse(url));
|
||||
context.startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
XToastUtils.error("您所打开的第三方App未安装!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismiss(DialogInterface dialog) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
@@ -1,677 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.core.webview;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebResourceError;
|
||||
import android.webkit.WebResourceRequest;
|
||||
import android.webkit.WebResourceResponse;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
import androidx.appcompat.widget.PopupMenu;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.just.agentweb.action.PermissionInterceptor;
|
||||
import com.just.agentweb.core.AgentWeb;
|
||||
import com.just.agentweb.core.client.DefaultWebClient;
|
||||
import com.just.agentweb.core.client.MiddlewareWebChromeBase;
|
||||
import com.just.agentweb.core.client.MiddlewareWebClientBase;
|
||||
import com.just.agentweb.core.client.WebListenerManager;
|
||||
import com.just.agentweb.core.web.AbsAgentWebSettings;
|
||||
import com.just.agentweb.core.web.AgentWebConfig;
|
||||
import com.just.agentweb.core.web.IAgentWebSettings;
|
||||
import com.just.agentweb.download.AgentWebDownloader;
|
||||
import com.just.agentweb.download.DefaultDownloadImpl;
|
||||
import com.just.agentweb.download.DownloadListenerAdapter;
|
||||
import com.just.agentweb.download.DownloadingService;
|
||||
import com.just.agentweb.widget.IWebLayout;
|
||||
import com.kerwin.wumei.MyApp;
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.xaop.annotation.SingleClick;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xpage.base.XPageActivity;
|
||||
import com.xuexiang.xpage.base.XPageFragment;
|
||||
import com.xuexiang.xpage.core.PageOption;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xutil.common.logger.Logger;
|
||||
import com.xuexiang.xutil.net.JsonUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
|
||||
/**
|
||||
* 使用XPageFragment
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-05-26 18:15
|
||||
*/
|
||||
@Page(params = {AgentWebFragment.KEY_URL})
|
||||
public class XPageWebViewFragment extends BaseFragment {
|
||||
|
||||
@BindView(R.id.iv_back)
|
||||
AppCompatImageView mIvBack;
|
||||
@BindView(R.id.view_line)
|
||||
View mLineView;
|
||||
@BindView(R.id.toolbar_title)
|
||||
TextView mTvTitle;
|
||||
|
||||
protected AgentWeb mAgentWeb;
|
||||
private PopupMenu mPopupMenu;
|
||||
|
||||
private DownloadingService mDownloadingService;
|
||||
|
||||
/**
|
||||
* 打开网页
|
||||
*
|
||||
* @param xPageActivity
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
public static Fragment openUrl(XPageActivity xPageActivity, String url) {
|
||||
return PageOption.to(XPageWebViewFragment.class)
|
||||
.putString(AgentWebFragment.KEY_URL, url)
|
||||
.open(xPageActivity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开网页
|
||||
*
|
||||
* @param fragment
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
public static Fragment openUrl(XPageFragment fragment, String url) {
|
||||
return PageOption.to(XPageWebViewFragment.class)
|
||||
.setNewActivity(true)
|
||||
.putString(AgentWebFragment.KEY_URL, url)
|
||||
.open(fragment);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TitleBar initTitle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 布局的资源id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_agentweb;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
@Override
|
||||
protected void initViews() {
|
||||
mAgentWeb = AgentWeb.with(this)
|
||||
//传入AgentWeb的父控件。
|
||||
.setAgentWebParent((LinearLayout) getRootView(), -1, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT))
|
||||
//设置进度条颜色与高度,-1为默认值,高度为2,单位为dp。
|
||||
.useDefaultIndicator(-1, 3)
|
||||
//设置 IAgentWebSettings。
|
||||
.setAgentWebWebSettings(getSettings())
|
||||
//WebViewClient , 与 WebView 使用一致 ,但是请勿获取WebView调用setWebViewClient(xx)方法了,会覆盖AgentWeb DefaultWebClient,同时相应的中间件也会失效。
|
||||
.setWebViewClient(mWebViewClient)
|
||||
//WebChromeClient
|
||||
.setWebChromeClient(mWebChromeClient)
|
||||
//设置WebChromeClient中间件,支持多个WebChromeClient,AgentWeb 3.0.0 加入。
|
||||
.useMiddlewareWebChrome(getMiddlewareWebChrome())
|
||||
//设置WebViewClient中间件,支持多个WebViewClient, AgentWeb 3.0.0 加入。
|
||||
.useMiddlewareWebClient(getMiddlewareWebClient())
|
||||
//权限拦截 2.0.0 加入。
|
||||
.setPermissionInterceptor(mPermissionInterceptor)
|
||||
//严格模式 Android 4.2.2 以下会放弃注入对象 ,使用AgentWebView没影响。
|
||||
.setSecurityType(AgentWeb.SecurityType.STRICT_CHECK)
|
||||
//自定义UI AgentWeb3.0.0 加入。
|
||||
.setAgentWebUIController(new UIController(getActivity()))
|
||||
//参数1是错误显示的布局,参数2点击刷新控件ID -1表示点击整个布局都刷新, AgentWeb 3.0.0 加入。
|
||||
.setMainFrameErrorView(R.layout.agentweb_error_page, -1)
|
||||
.setWebLayout(getWebLayout())
|
||||
//打开其他页面时,弹窗质询用户前往其他应用 AgentWeb 3.0.0 加入。
|
||||
.setOpenOtherPageWays(DefaultWebClient.OpenOtherPageWays.DISALLOW)
|
||||
//拦截找不到相关页面的Url AgentWeb 3.0.0 加入。
|
||||
.interceptUnkownUrl()
|
||||
//创建AgentWeb。
|
||||
.createAgentWeb()
|
||||
.ready()//设置 WebSettings。
|
||||
//WebView载入该url地址的页面并显示。
|
||||
.go(getUrl());
|
||||
|
||||
if (MyApp.isDebug()) {
|
||||
AgentWebConfig.debug();
|
||||
}
|
||||
|
||||
pageNavigator(View.GONE);
|
||||
// 得到 AgentWeb 最底层的控件
|
||||
addBackgroundChild(mAgentWeb.getWebCreator().getWebParentLayout());
|
||||
|
||||
// AgentWeb 没有把WebView的功能全面覆盖 ,所以某些设置 AgentWeb 没有提供,请从WebView方面入手设置。
|
||||
mAgentWeb.getWebCreator().getWebView().setOverScrollMode(WebView.OVER_SCROLL_NEVER);
|
||||
}
|
||||
|
||||
protected IWebLayout getWebLayout() {
|
||||
return new WebLayout(getActivity());
|
||||
}
|
||||
|
||||
protected void addBackgroundChild(FrameLayout frameLayout) {
|
||||
TextView textView = new TextView(frameLayout.getContext());
|
||||
textView.setText("技术由 AgentWeb 提供");
|
||||
textView.setTextSize(16);
|
||||
textView.setTextColor(Color.parseColor("#727779"));
|
||||
frameLayout.setBackgroundColor(Color.parseColor("#272b2d"));
|
||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(-2, -2);
|
||||
params.gravity = Gravity.CENTER_HORIZONTAL;
|
||||
final float scale = frameLayout.getContext().getResources().getDisplayMetrics().density;
|
||||
params.topMargin = (int) (15 * scale + 0.5f);
|
||||
frameLayout.addView(textView, 0, params);
|
||||
}
|
||||
|
||||
|
||||
private void pageNavigator(int tag) {
|
||||
//返回的导航按钮
|
||||
mIvBack.setVisibility(tag);
|
||||
mLineView.setVisibility(tag);
|
||||
}
|
||||
|
||||
@SingleClick
|
||||
@OnClick({R.id.iv_back, R.id.iv_finish, R.id.iv_more})
|
||||
public void onViewClicked(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.iv_back:
|
||||
// true表示AgentWeb处理了该事件
|
||||
if (!mAgentWeb.back()) {
|
||||
popToBack();
|
||||
}
|
||||
break;
|
||||
case R.id.iv_finish:
|
||||
popToBack();
|
||||
break;
|
||||
case R.id.iv_more:
|
||||
showPoPup(view);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//=====================下载============================//
|
||||
|
||||
/**
|
||||
* 更新于 AgentWeb 4.0.0,下载监听
|
||||
*/
|
||||
protected DownloadListenerAdapter mDownloadListenerAdapter = new DownloadListenerAdapter() {
|
||||
/**
|
||||
*
|
||||
* @param url 下载链接
|
||||
* @param userAgent UserAgent
|
||||
* @param contentDisposition ContentDisposition
|
||||
* @param mimeType 资源的媒体类型
|
||||
* @param contentLength 文件长度
|
||||
* @param extra 下载配置 , 用户可以通过 Extra 修改下载icon , 关闭进度条 , 是否强制下载。
|
||||
* @return true 表示用户处理了该下载事件 , false 交给 AgentWeb 下载
|
||||
*/
|
||||
@Override
|
||||
public boolean onStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength, AgentWebDownloader.Extra extra) {
|
||||
Logger.i("onStart:" + url);
|
||||
// 是否开启断点续传
|
||||
extra.setOpenBreakPointDownload(true)
|
||||
//下载通知的icon
|
||||
.setIcon(R.drawable.ic_file_download_black_24dp)
|
||||
// 连接的超时时间
|
||||
.setConnectTimeOut(6000)
|
||||
// 以8KB位单位,默认60s ,如果60s内无法从网络流中读满8KB数据,则抛出异常
|
||||
.setBlockMaxTime(10 * 60 * 1000)
|
||||
// 下载的超时时间
|
||||
.setDownloadTimeOut(Long.MAX_VALUE)
|
||||
// 串行下载更节省资源哦
|
||||
.setParallelDownload(false)
|
||||
// false 关闭进度通知
|
||||
.setEnableIndicator(true)
|
||||
// 自定义请求头
|
||||
.addHeader("Cookie", "xx")
|
||||
// 下载完成自动打开
|
||||
.setAutoOpen(true)
|
||||
// 强制下载,不管网络网络类型
|
||||
.setForceDownload(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 不需要暂停或者停止下载该方法可以不必实现
|
||||
* @param url
|
||||
* @param downloadingService 用户可以通过 DownloadingService#shutdownNow 终止下载
|
||||
*/
|
||||
@Override
|
||||
public void onBindService(String url, DownloadingService downloadingService) {
|
||||
super.onBindService(url, downloadingService);
|
||||
mDownloadingService = downloadingService;
|
||||
Logger.i("onBindService:" + url + " DownloadingService:" + downloadingService);
|
||||
}
|
||||
|
||||
/**
|
||||
* 回调onUnbindService方法,让用户释放掉 DownloadingService。
|
||||
* @param url
|
||||
* @param downloadingService
|
||||
*/
|
||||
@Override
|
||||
public void onUnbindService(String url, DownloadingService downloadingService) {
|
||||
super.onUnbindService(url, downloadingService);
|
||||
mDownloadingService = null;
|
||||
Logger.i("onUnbindService:" + url);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param url 下载链接
|
||||
* @param loaded 已经下载的长度
|
||||
* @param length 文件的总大小
|
||||
* @param usedTime 耗时 ,单位ms
|
||||
* 注意该方法回调在子线程 ,线程名 AsyncTask #XX 或者 AgentWeb # XX
|
||||
*/
|
||||
@Override
|
||||
public void onProgress(String url, long loaded, long length, long usedTime) {
|
||||
int mProgress = (int) ((loaded) / (float) length * 100);
|
||||
Logger.i("onProgress:" + mProgress);
|
||||
super.onProgress(url, loaded, length, usedTime);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param path 文件的绝对路径
|
||||
* @param url 下载地址
|
||||
* @param throwable 如果异常,返回给用户异常
|
||||
* @return true 表示用户处理了下载完成后续的事件 ,false 默认交给AgentWeb 处理
|
||||
*/
|
||||
@Override
|
||||
public boolean onResult(String path, String url, Throwable throwable) {
|
||||
//下载成功
|
||||
if (null == throwable) {
|
||||
//do you work
|
||||
} else {//下载失败
|
||||
|
||||
}
|
||||
// true 不会发出下载完成的通知 , 或者打开文件
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 下载服务设置
|
||||
*
|
||||
* @return IAgentWebSettings
|
||||
*/
|
||||
public IAgentWebSettings getSettings() {
|
||||
return new AbsAgentWebSettings() {
|
||||
private AgentWeb mAgentWeb;
|
||||
|
||||
@Override
|
||||
protected void bindAgentWebSupport(AgentWeb agentWeb) {
|
||||
this.mAgentWeb = agentWeb;
|
||||
}
|
||||
|
||||
/**
|
||||
* AgentWeb 4.0.0 内部删除了 DownloadListener 监听 ,以及相关API ,将 Download 部分完全抽离出来独立一个库,
|
||||
* 如果你需要使用 AgentWeb Download 部分 , 请依赖上 compile 'com.just.agentweb:download:4.0.0 ,
|
||||
* 如果你需要监听下载结果,请自定义 AgentWebSetting , New 出 DefaultDownloadImpl,传入DownloadListenerAdapter
|
||||
* 实现进度或者结果监听,例如下面这个例子,如果你不需要监听进度,或者下载结果,下面 setDownloader 的例子可以忽略。
|
||||
* @param webView
|
||||
* @param downloadListener
|
||||
* @return WebListenerManager
|
||||
*/
|
||||
@Override
|
||||
public WebListenerManager setDownloader(WebView webView, android.webkit.DownloadListener downloadListener) {
|
||||
return super.setDownloader(webView,
|
||||
DefaultDownloadImpl
|
||||
.create(getActivity(),
|
||||
webView,
|
||||
mDownloadListenerAdapter,
|
||||
mDownloadListenerAdapter,
|
||||
mAgentWeb.getPermissionInterceptor()));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//===================WebChromeClient 和 WebViewClient===========================//
|
||||
|
||||
/**
|
||||
* 页面空白,请检查scheme是否加上, scheme://host:port/path?query&query 。
|
||||
*
|
||||
* @return mUrl
|
||||
*/
|
||||
public String getUrl() {
|
||||
String target = "";
|
||||
Bundle bundle = getArguments();
|
||||
if (bundle != null) {
|
||||
target = bundle.getString(AgentWebFragment.KEY_URL);
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(target)) {
|
||||
target = "https://github.com/xuexiangjys";
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* 和浏览器相关,包括和JS的交互
|
||||
*/
|
||||
protected WebChromeClient mWebChromeClient = new WebChromeClient() {
|
||||
@Override
|
||||
public void onProgressChanged(WebView view, int newProgress) {
|
||||
super.onProgressChanged(view, newProgress);
|
||||
//网页加载进度
|
||||
}
|
||||
@Override
|
||||
public void onReceivedTitle(WebView view, String title) {
|
||||
super.onReceivedTitle(view, title);
|
||||
if (mTvTitle != null && !TextUtils.isEmpty(title)) {
|
||||
if (title.length() > 10) {
|
||||
title = title.substring(0, 10).concat("...");
|
||||
}
|
||||
mTvTitle.setText(title);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 和网页url加载相关,统计加载时间
|
||||
*/
|
||||
protected WebViewClient mWebViewClient = new WebViewClient() {
|
||||
private HashMap<String, Long> mTimer = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
|
||||
super.onReceivedError(view, request, error);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
|
||||
return shouldOverrideUrlLoading(view, request.getUrl() + "");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
|
||||
return super.shouldInterceptRequest(view, request);
|
||||
}
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(final WebView view, String url) {
|
||||
//intent:// scheme的处理 如果返回false , 则交给 DefaultWebClient 处理 , 默认会打开该Activity , 如果Activity不存在则跳到应用市场上去. true 表示拦截
|
||||
//例如优酷视频播放 ,intent://play?...package=com.youku.phone;end;
|
||||
//优酷想唤起自己应用播放该视频 , 下面拦截地址返回 true 则会在应用内 H5 播放 ,禁止优酷唤起播放该视频, 如果返回 false , DefaultWebClient 会根据intent 协议处理 该地址 , 首先匹配该应用存不存在 ,如果存在 , 唤起该应用播放 , 如果不存在 , 则跳到应用市场下载该应用 .
|
||||
if (url.startsWith("intent://") && url.contains("com.youku.phone")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageStarted(WebView view, String url, Bitmap favicon) {
|
||||
mTimer.put(url, System.currentTimeMillis());
|
||||
if (url.equals(getUrl())) {
|
||||
pageNavigator(View.GONE);
|
||||
} else {
|
||||
pageNavigator(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
super.onPageFinished(view, url);
|
||||
if (mTimer.get(url) != null) {
|
||||
long overTime = System.currentTimeMillis();
|
||||
Long startTime = mTimer.get(url);
|
||||
//统计页面的使用时长
|
||||
Logger.i(" page mUrl:" + url + " used time:" + (overTime - startTime));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
|
||||
super.onReceivedHttpError(view, request, errorResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
|
||||
super.onReceivedError(view, errorCode, description, failingUrl);
|
||||
}
|
||||
};
|
||||
|
||||
//=====================菜单========================//
|
||||
|
||||
/**
|
||||
* 显示更多菜单
|
||||
*
|
||||
* @param view 菜单依附在该View下面
|
||||
*/
|
||||
private void showPoPup(View view) {
|
||||
if (mPopupMenu == null) {
|
||||
mPopupMenu = new PopupMenu(getContext(), view);
|
||||
mPopupMenu.inflate(R.menu.menu_toolbar_web);
|
||||
mPopupMenu.setOnMenuItemClickListener(mOnMenuItemClickListener);
|
||||
}
|
||||
mPopupMenu.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* 菜单事件
|
||||
*/
|
||||
private PopupMenu.OnMenuItemClickListener mOnMenuItemClickListener = new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.refresh:
|
||||
if (mAgentWeb != null) {
|
||||
mAgentWeb.getUrlLoader().reload(); // 刷新
|
||||
}
|
||||
return true;
|
||||
case R.id.copy:
|
||||
if (mAgentWeb != null) {
|
||||
toCopy(getContext(), mAgentWeb.getWebCreator().getWebView().getUrl());
|
||||
}
|
||||
return true;
|
||||
case R.id.default_browser:
|
||||
if (mAgentWeb != null) {
|
||||
openBrowser(mAgentWeb.getWebCreator().getWebView().getUrl());
|
||||
}
|
||||
return true;
|
||||
case R.id.share:
|
||||
if (mAgentWeb != null) {
|
||||
shareWebUrl(mAgentWeb.getWebCreator().getWebView().getUrl());
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 打开浏览器
|
||||
*
|
||||
* @param targetUrl 外部浏览器打开的地址
|
||||
*/
|
||||
private void openBrowser(String targetUrl) {
|
||||
if (TextUtils.isEmpty(targetUrl) || targetUrl.startsWith("file://")) {
|
||||
XToastUtils.toast(targetUrl + " 该链接无法使用浏览器打开。");
|
||||
return;
|
||||
}
|
||||
Intent intent = new Intent();
|
||||
intent.setAction("android.intent.action.VIEW");
|
||||
Uri uri = Uri.parse(targetUrl);
|
||||
intent.setData(uri);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分享网页链接
|
||||
*
|
||||
* @param url 网页链接
|
||||
*/
|
||||
private void shareWebUrl(String url) {
|
||||
Intent shareIntent = new Intent();
|
||||
shareIntent.setAction(Intent.ACTION_SEND);
|
||||
shareIntent.putExtra(Intent.EXTRA_TEXT, url);
|
||||
shareIntent.setType("text/plain");
|
||||
//设置分享列表的标题,并且每次都显示分享列表
|
||||
startActivity(Intent.createChooser(shareIntent, "分享到"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制字符串
|
||||
*
|
||||
* @param context
|
||||
* @param text
|
||||
*/
|
||||
private void toCopy(Context context, String text) {
|
||||
ClipboardManager manager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
if (manager == null) {
|
||||
return;
|
||||
}
|
||||
manager.setPrimaryClip(ClipData.newPlainText(null, text));
|
||||
}
|
||||
|
||||
//===================生命周期管理===========================//
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
if (mAgentWeb != null) {
|
||||
mAgentWeb.getWebLifeCycle().onResume();//恢复
|
||||
}
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
if (mAgentWeb != null) {
|
||||
mAgentWeb.getWebLifeCycle().onPause(); //暂停应用内所有WebView , 调用mWebView.resumeTimers();/mAgentWeb.getWebLifeCycle().onResume(); 恢复。
|
||||
}
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
return mAgentWeb != null && mAgentWeb.handleKeyEvent(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
if (mAgentWeb != null) {
|
||||
mAgentWeb.destroy();
|
||||
}
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
|
||||
//===================中间键===========================//
|
||||
|
||||
|
||||
/**
|
||||
* MiddlewareWebClientBase 是 AgentWeb 3.0.0 提供一个强大的功能,
|
||||
* 如果用户需要使用 AgentWeb 提供的功能, 不想重写 WebClientView方
|
||||
* 法覆盖AgentWeb提供的功能,那么 MiddlewareWebClientBase 是一个
|
||||
* 不错的选择 。
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected MiddlewareWebClientBase getMiddlewareWebClient() {
|
||||
return new MiddlewareWebViewClient() {
|
||||
/**
|
||||
*
|
||||
* @param view
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
// 拦截 url,不执行 DefaultWebClient#shouldOverrideUrlLoading
|
||||
if (url.startsWith("agentweb")) {
|
||||
return true;
|
||||
}
|
||||
// 执行 DefaultWebClient#shouldOverrideUrlLoading
|
||||
if (super.shouldOverrideUrlLoading(view, url)) {
|
||||
return true;
|
||||
}
|
||||
// do you work
|
||||
return false;
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
|
||||
return super.shouldOverrideUrlLoading(view, request);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected MiddlewareWebChromeBase getMiddlewareWebChrome() {
|
||||
return new MiddlewareChromeClient() {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限申请拦截器
|
||||
*/
|
||||
protected PermissionInterceptor mPermissionInterceptor = new PermissionInterceptor() {
|
||||
/**
|
||||
* PermissionInterceptor 能达到 url1 允许授权, url2 拒绝授权的效果。
|
||||
* @param url
|
||||
* @param permissions
|
||||
* @param action
|
||||
* @return true 该Url对应页面请求权限进行拦截 ,false 表示不拦截。
|
||||
*/
|
||||
@Override
|
||||
public boolean intercept(String url, String[] permissions, String action) {
|
||||
Logger.i("mUrl:" + url + " permission:" + JsonUtil.toJson(permissions) + " action:" + action);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
|
||||
package com.kerwin.wumei.entity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Dept {
|
||||
private String remark;
|
||||
|
||||
private int deptId;
|
||||
|
||||
private int parentId;
|
||||
|
||||
private String ancestors;
|
||||
|
||||
private String deptName;
|
||||
|
||||
private String orderNum;
|
||||
|
||||
private String leader;
|
||||
|
||||
private String phone;
|
||||
|
||||
private String email;
|
||||
|
||||
private String status;
|
||||
|
||||
private String delFlag;
|
||||
|
||||
private String parentName;
|
||||
|
||||
private List<Dept> children ;
|
||||
|
||||
public void setRemark(String remark){
|
||||
this.remark = remark;
|
||||
}
|
||||
public String getRemark(){
|
||||
return this.remark;
|
||||
}
|
||||
public void setDeptId(int deptId){
|
||||
this.deptId = deptId;
|
||||
}
|
||||
public int getDeptId(){
|
||||
return this.deptId;
|
||||
}
|
||||
public void setParentId(int parentId){
|
||||
this.parentId = parentId;
|
||||
}
|
||||
public int getParentId(){
|
||||
return this.parentId;
|
||||
}
|
||||
public void setAncestors(String ancestors){
|
||||
this.ancestors = ancestors;
|
||||
}
|
||||
public String getAncestors(){
|
||||
return this.ancestors;
|
||||
}
|
||||
public void setDeptName(String deptName){
|
||||
this.deptName = deptName;
|
||||
}
|
||||
public String getDeptName(){
|
||||
return this.deptName;
|
||||
}
|
||||
public void setOrderNum(String orderNum){
|
||||
this.orderNum = orderNum;
|
||||
}
|
||||
public String getOrderNum(){
|
||||
return this.orderNum;
|
||||
}
|
||||
public void setLeader(String leader){
|
||||
this.leader = leader;
|
||||
}
|
||||
public String getLeader(){
|
||||
return this.leader;
|
||||
}
|
||||
public void setPhone(String phone){
|
||||
this.phone = phone;
|
||||
}
|
||||
public String getPhone(){
|
||||
return this.phone;
|
||||
}
|
||||
public void setEmail(String email){
|
||||
this.email = email;
|
||||
}
|
||||
public String getEmail(){
|
||||
return this.email;
|
||||
}
|
||||
public void setStatus(String status){
|
||||
this.status = status;
|
||||
}
|
||||
public String getStatus(){
|
||||
return this.status;
|
||||
}
|
||||
public void setDelFlag(String delFlag){
|
||||
this.delFlag = delFlag;
|
||||
}
|
||||
public String getDelFlag(){
|
||||
return this.delFlag;
|
||||
}
|
||||
public void setParentName(String parentName){
|
||||
this.parentName = parentName;
|
||||
}
|
||||
public String getParentName(){
|
||||
return this.parentName;
|
||||
}
|
||||
public void setChildren(List<Dept> children){
|
||||
this.children = children;
|
||||
}
|
||||
public List<Dept> getChildren(){
|
||||
return this.children;
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
|
||||
package com.kerwin.wumei.entity;
|
||||
|
||||
public class DictData {
|
||||
|
||||
/** 字典标签 */
|
||||
private String dictLabel;
|
||||
|
||||
/** 字典键值 */
|
||||
private Integer dictValue;
|
||||
|
||||
/** 字典编码 */
|
||||
private Long dictCode;
|
||||
|
||||
/** 字典类型 */
|
||||
private String dictType;
|
||||
|
||||
|
||||
public Long getDictCode()
|
||||
{
|
||||
return dictCode;
|
||||
}
|
||||
public void setDictCode(Long dictCode)
|
||||
{
|
||||
this.dictCode = dictCode;
|
||||
}
|
||||
|
||||
public String getDictLabel()
|
||||
{
|
||||
return dictLabel;
|
||||
}
|
||||
public void setDictLabel(String dictLabel)
|
||||
{
|
||||
this.dictLabel = dictLabel;
|
||||
}
|
||||
|
||||
public Integer getDictValue()
|
||||
{
|
||||
return dictValue;
|
||||
}
|
||||
public void setDictValue(Integer dictValue)
|
||||
{
|
||||
this.dictValue = dictValue;
|
||||
}
|
||||
|
||||
public String getDictType()
|
||||
{
|
||||
return dictType;
|
||||
}
|
||||
public void setDictType(String dictType)
|
||||
{
|
||||
this.dictType = dictType;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
|
||||
package com.kerwin.wumei.entity;
|
||||
|
||||
public class IotCategory {
|
||||
/** 序号 */
|
||||
private Long categoryId;
|
||||
|
||||
/** 分类名称 */
|
||||
private String categoryName;
|
||||
|
||||
public void setCategoryId(Long categoryId)
|
||||
{
|
||||
this.categoryId = categoryId;
|
||||
}
|
||||
public Long getCategoryId()
|
||||
{
|
||||
return categoryId;
|
||||
}
|
||||
|
||||
public void setCategoryName(String categoryName)
|
||||
{
|
||||
this.categoryName = categoryName;
|
||||
}
|
||||
public String getCategoryName()
|
||||
{
|
||||
return categoryName;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
|
||||
package com.kerwin.wumei.entity;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
public class IotDevice {
|
||||
/** 序号 */
|
||||
private Long deviceId;
|
||||
|
||||
/** 编号 */
|
||||
private String deviceNum;
|
||||
|
||||
/** 分类 */
|
||||
private String categoryName;
|
||||
|
||||
/** 名称 */
|
||||
private String deviceName;
|
||||
|
||||
/** 固件版本 */
|
||||
private String firmwareVersion;
|
||||
|
||||
/** 用户 */
|
||||
private String ownerId;
|
||||
|
||||
/** 备注 */
|
||||
private String remark;
|
||||
|
||||
/** 设备温度 */
|
||||
private String deviceTemp;
|
||||
|
||||
/** 创建时间 */
|
||||
private String createTime;
|
||||
|
||||
public void setDeviceId(Long deviceId)
|
||||
{
|
||||
this.deviceId = deviceId;
|
||||
}
|
||||
|
||||
public Long getDeviceId()
|
||||
{
|
||||
return deviceId;
|
||||
}
|
||||
public void setDeviceNum(String deviceNum)
|
||||
{
|
||||
this.deviceNum = deviceNum;
|
||||
}
|
||||
|
||||
public String getDeviceNum()
|
||||
{
|
||||
return deviceNum;
|
||||
}
|
||||
public void setCategoryId(String categoryId)
|
||||
{
|
||||
this.categoryName = categoryName;
|
||||
}
|
||||
|
||||
public String getCategoryName()
|
||||
{
|
||||
return categoryName;
|
||||
}
|
||||
public void setDeviceName(String deviceName)
|
||||
{
|
||||
this.deviceName = deviceName;
|
||||
}
|
||||
|
||||
public String getDeviceName()
|
||||
{
|
||||
return deviceName;
|
||||
}
|
||||
public void setFirmwareVersion(String firmwareVersion)
|
||||
{
|
||||
this.firmwareVersion = firmwareVersion;
|
||||
}
|
||||
|
||||
public String getFirmwareVersion()
|
||||
{
|
||||
return firmwareVersion;
|
||||
}
|
||||
public void setOwnerId(String ownerId)
|
||||
{
|
||||
this.ownerId = ownerId;
|
||||
}
|
||||
|
||||
public String getOwnerId()
|
||||
{
|
||||
return ownerId;
|
||||
}
|
||||
|
||||
public void setRemark(String remark)
|
||||
{
|
||||
this.remark = remark;
|
||||
}
|
||||
public String getRemark()
|
||||
{
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setDeviceTemp(String deviceTemperature)
|
||||
{
|
||||
this.deviceTemp = deviceTemperature;
|
||||
}
|
||||
public String getDeviceTemp()
|
||||
{
|
||||
return deviceTemp;
|
||||
}
|
||||
|
||||
public void setCreateTime(String createTime)
|
||||
{
|
||||
this.createTime = createTime;
|
||||
}
|
||||
public String getCreateTime()
|
||||
{
|
||||
return createTime;
|
||||
}
|
||||
}
|
||||
@@ -1,282 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
|
||||
package com.kerwin.wumei.entity;
|
||||
|
||||
public class IotDeviceSet {
|
||||
/** 序号 */
|
||||
private Long deviceSetId;
|
||||
|
||||
/** 设备 */
|
||||
private Long deviceId;
|
||||
|
||||
/** 设备编号 */
|
||||
private String deviceNum;
|
||||
|
||||
/** 报警 */
|
||||
private Integer isAlarm;
|
||||
|
||||
/** 雷达感应 */
|
||||
private Integer isRadar;
|
||||
|
||||
/** 托管 */
|
||||
private Integer isHost;
|
||||
|
||||
/** 重启 */
|
||||
private Integer isReset;
|
||||
|
||||
/** 打开AP */
|
||||
private Integer isAp;
|
||||
|
||||
/** 是否离线使用 */
|
||||
private Integer isWifiOffline;
|
||||
|
||||
/** 是否使用证书 */
|
||||
private Integer isOpenCertifi;
|
||||
|
||||
/** 智能配网 */
|
||||
private Integer isSmartConfig;
|
||||
|
||||
/** 射频遥控 */
|
||||
private Integer isRfControl;
|
||||
|
||||
/** 遥控配对 */
|
||||
private Integer isRfLearn;
|
||||
|
||||
/** 遥控清码 */
|
||||
private Integer isRfClear;
|
||||
|
||||
/** 按键一 */
|
||||
private Integer rfOneFunc;
|
||||
|
||||
/** 按键二 */
|
||||
private Integer rfTwoFunc;
|
||||
|
||||
/** 按键三 */
|
||||
private Integer rfThreeFunc;
|
||||
|
||||
/** 按键四 */
|
||||
private Integer rfFourFunc;
|
||||
|
||||
/** 用户 */
|
||||
private String ownerId;
|
||||
|
||||
/** 配网地址 */
|
||||
private String networkAddress;
|
||||
|
||||
/** 配网IP */
|
||||
private String networkIp;
|
||||
|
||||
/** 雷达感应间隔 */
|
||||
private Integer radarInterval;
|
||||
|
||||
public void setDeviceSetId(Long deviceSetId)
|
||||
{
|
||||
this.deviceSetId = deviceSetId;
|
||||
}
|
||||
|
||||
public Long getDeviceSetId()
|
||||
{
|
||||
return deviceSetId;
|
||||
}
|
||||
public void setDeviceId(Long deviceId)
|
||||
{
|
||||
this.deviceId = deviceId;
|
||||
}
|
||||
|
||||
public Long getDeviceId()
|
||||
{
|
||||
return deviceId;
|
||||
}
|
||||
public void setDeviceNum(String deviceNum)
|
||||
{
|
||||
this.deviceNum = deviceNum;
|
||||
}
|
||||
|
||||
public String getDeviceNum()
|
||||
{
|
||||
return deviceNum;
|
||||
}
|
||||
public void setIsAlarm(Integer isAlarm)
|
||||
{
|
||||
this.isAlarm = isAlarm;
|
||||
}
|
||||
|
||||
public Integer getIsAlarm()
|
||||
{
|
||||
return isAlarm;
|
||||
}
|
||||
public void setIsRadar(Integer isRadar)
|
||||
{
|
||||
this.isRadar = isRadar;
|
||||
}
|
||||
|
||||
public Integer getIsRadar()
|
||||
{
|
||||
return isRadar;
|
||||
}
|
||||
public void setIsHost(Integer isHost)
|
||||
{
|
||||
this.isHost = isHost;
|
||||
}
|
||||
|
||||
public Integer getIsHost()
|
||||
{
|
||||
return isHost;
|
||||
}
|
||||
public void setIsReset(Integer isReset)
|
||||
{
|
||||
this.isReset = isReset;
|
||||
}
|
||||
|
||||
public Integer getIsReset()
|
||||
{
|
||||
return isReset;
|
||||
}
|
||||
|
||||
public void setIsAp(Integer isAp)
|
||||
{
|
||||
this.isAp = isAp;
|
||||
}
|
||||
public Integer getIsAp()
|
||||
{
|
||||
return isAp;
|
||||
}
|
||||
|
||||
public void setIsWifiOffline(Integer isWifiOffline)
|
||||
{
|
||||
this.isWifiOffline = isWifiOffline;
|
||||
}
|
||||
public Integer getIsWifiOffline()
|
||||
{
|
||||
return isWifiOffline;
|
||||
}
|
||||
|
||||
public void setIsOpenCertifi(Integer isOpenCertifi)
|
||||
{
|
||||
this.isOpenCertifi = isOpenCertifi;
|
||||
}
|
||||
public Integer getIsOpenCertifi()
|
||||
{
|
||||
return isOpenCertifi;
|
||||
}
|
||||
|
||||
public void setIsSmartConfig(Integer isSmartConfig)
|
||||
{
|
||||
this.isSmartConfig = isSmartConfig;
|
||||
}
|
||||
|
||||
public Integer getIsSmartConfig()
|
||||
{
|
||||
return isSmartConfig;
|
||||
}
|
||||
public void setIsRfControl(Integer isRfControl)
|
||||
{
|
||||
this.isRfControl = isRfControl;
|
||||
}
|
||||
|
||||
public Integer getIsRfControl()
|
||||
{
|
||||
return isRfControl;
|
||||
}
|
||||
public void setIsRfLearn(Integer isRfLearn)
|
||||
{
|
||||
this.isRfLearn = isRfLearn;
|
||||
}
|
||||
|
||||
public Integer getIsRfLearn()
|
||||
{
|
||||
return isRfLearn;
|
||||
}
|
||||
public void setIsRfClear(Integer isRfClear)
|
||||
{
|
||||
this.isRfClear = isRfClear;
|
||||
}
|
||||
|
||||
public Integer getIsRfClear()
|
||||
{
|
||||
return isRfClear;
|
||||
}
|
||||
public void setRfOneFunc(Integer rfOneFunc)
|
||||
{
|
||||
this.rfOneFunc = rfOneFunc;
|
||||
}
|
||||
|
||||
public Integer getRfOneFunc()
|
||||
{
|
||||
return rfOneFunc;
|
||||
}
|
||||
public void setRfTwoFunc(Integer rfTwoFunc)
|
||||
{
|
||||
this.rfTwoFunc = rfTwoFunc;
|
||||
}
|
||||
|
||||
public Integer getRfTwoFunc()
|
||||
{
|
||||
return rfTwoFunc;
|
||||
}
|
||||
public void setRfThreeFunc(Integer rfThreeFunc)
|
||||
{
|
||||
this.rfThreeFunc = rfThreeFunc;
|
||||
}
|
||||
|
||||
public Integer getRfThreeFunc()
|
||||
{
|
||||
return rfThreeFunc;
|
||||
}
|
||||
public void setRfFourFunc(Integer rfFourFunc)
|
||||
{
|
||||
this.rfFourFunc = rfFourFunc;
|
||||
}
|
||||
|
||||
public Integer getRfFourFunc()
|
||||
{
|
||||
return rfFourFunc;
|
||||
}
|
||||
public void setOwnerId(String ownerId)
|
||||
{
|
||||
this.ownerId = ownerId;
|
||||
}
|
||||
|
||||
public String getOwnerId()
|
||||
{
|
||||
return ownerId;
|
||||
}
|
||||
public void setNetworkAddress(String networkAddress)
|
||||
{
|
||||
this.networkAddress = networkAddress;
|
||||
}
|
||||
|
||||
public String getNetworkAddress()
|
||||
{
|
||||
return networkAddress;
|
||||
}
|
||||
public void setNetworkIp(String networkIp)
|
||||
{
|
||||
this.networkIp = networkIp;
|
||||
}
|
||||
|
||||
public String getNetworkIp()
|
||||
{
|
||||
return networkIp;
|
||||
}
|
||||
|
||||
public void setRadarInterval(Integer radarInterval)
|
||||
{
|
||||
this.radarInterval = radarInterval;
|
||||
}
|
||||
|
||||
public Integer getRadarInterval()
|
||||
{
|
||||
return radarInterval;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,234 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
|
||||
package com.kerwin.wumei.entity;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public class IotDeviceStatus {
|
||||
/** 序号 */
|
||||
private Long deviceStatusId;
|
||||
|
||||
/** 设备 */
|
||||
private Long deviceId;
|
||||
|
||||
/** 设备编号 */
|
||||
private String deviceNum;
|
||||
|
||||
/** 继电器 */
|
||||
private Integer relayStatus;
|
||||
|
||||
/** 灯状态 */
|
||||
private Integer lightStatus;
|
||||
|
||||
/** 在线 */
|
||||
private Integer isOnline;
|
||||
|
||||
/** 设备温度 */
|
||||
private BigDecimal deviceTemperature;
|
||||
|
||||
/** 设备湿度 */
|
||||
private Integer rssi;
|
||||
|
||||
/** 空气温度 */
|
||||
private BigDecimal airTemperature;
|
||||
|
||||
/** 空气湿度 */
|
||||
private BigDecimal airHumidity;
|
||||
|
||||
/** 触发源 */
|
||||
private Integer triggerSource;
|
||||
|
||||
/** 彩灯亮度 */
|
||||
private Integer brightness;
|
||||
|
||||
/** 渐变间隔 */
|
||||
private Integer lightInterval;
|
||||
|
||||
/** 彩灯模式 */
|
||||
private Integer lightMode;
|
||||
|
||||
/** 灯渐变时间 */
|
||||
private Integer fadeTime;
|
||||
|
||||
/** 红灯 */
|
||||
private Integer red;
|
||||
|
||||
/** 绿灯 */
|
||||
private Integer green;
|
||||
|
||||
/** 蓝灯 */
|
||||
private Integer blue;
|
||||
|
||||
public void setDeviceStatusId(Long deviceStatusId)
|
||||
{
|
||||
this.deviceStatusId = deviceStatusId;
|
||||
}
|
||||
|
||||
public Long getDeviceStatusId()
|
||||
{
|
||||
return deviceStatusId;
|
||||
}
|
||||
public void setDeviceId(Long deviceId)
|
||||
{
|
||||
this.deviceId = deviceId;
|
||||
}
|
||||
|
||||
public Long getDeviceId()
|
||||
{
|
||||
return deviceId;
|
||||
}
|
||||
public void setDeviceNum(String deviceNum)
|
||||
{
|
||||
this.deviceNum = deviceNum;
|
||||
}
|
||||
|
||||
public String getDeviceNum()
|
||||
{
|
||||
return deviceNum;
|
||||
}
|
||||
public void setRelayStatus(Integer relayStatus)
|
||||
{
|
||||
this.relayStatus = relayStatus;
|
||||
}
|
||||
|
||||
public Integer getRelayStatus()
|
||||
{
|
||||
return relayStatus;
|
||||
}
|
||||
public void setLightStatus(Integer lightStatus)
|
||||
{
|
||||
this.lightStatus = lightStatus;
|
||||
}
|
||||
|
||||
public Integer getLightStatus()
|
||||
{
|
||||
return lightStatus;
|
||||
}
|
||||
public void setIsOnline(Integer isOnline)
|
||||
{
|
||||
this.isOnline = isOnline;
|
||||
}
|
||||
|
||||
public Integer getIsOnline()
|
||||
{
|
||||
return isOnline;
|
||||
}
|
||||
public void setDeviceTemperature(BigDecimal deviceTemperature)
|
||||
{
|
||||
this.deviceTemperature = deviceTemperature;
|
||||
}
|
||||
|
||||
public BigDecimal getDeviceTemperature()
|
||||
{
|
||||
return deviceTemperature;
|
||||
}
|
||||
public void setRssi(Integer rssi)
|
||||
{
|
||||
this.rssi = rssi;
|
||||
}
|
||||
|
||||
public Integer getRssi()
|
||||
{
|
||||
return rssi;
|
||||
}
|
||||
public void setAirTemperature(BigDecimal airTemperature)
|
||||
{
|
||||
this.airTemperature = airTemperature;
|
||||
}
|
||||
|
||||
public BigDecimal getAirTemperature()
|
||||
{
|
||||
return airTemperature;
|
||||
}
|
||||
public void setAirHumidity(BigDecimal airHumidity)
|
||||
{
|
||||
this.airHumidity = airHumidity;
|
||||
}
|
||||
|
||||
public BigDecimal getAirHumidity()
|
||||
{
|
||||
return airHumidity;
|
||||
}
|
||||
public void setTriggerSource(Integer triggerSource)
|
||||
{
|
||||
this.triggerSource = triggerSource;
|
||||
}
|
||||
|
||||
public Integer getTriggerSource()
|
||||
{
|
||||
return triggerSource;
|
||||
}
|
||||
public void setBrightness(Integer brightness)
|
||||
{
|
||||
this.brightness = brightness;
|
||||
}
|
||||
|
||||
public Integer getBrightness()
|
||||
{
|
||||
return brightness;
|
||||
}
|
||||
public void setLightInterval(Integer lightInterval)
|
||||
{
|
||||
this.lightInterval = lightInterval;
|
||||
}
|
||||
|
||||
public Integer getLightInterval()
|
||||
{
|
||||
return lightInterval;
|
||||
}
|
||||
public void setLightMode(Integer lightMode)
|
||||
{
|
||||
this.lightMode = lightMode;
|
||||
}
|
||||
|
||||
public Integer getLightMode()
|
||||
{
|
||||
return lightMode;
|
||||
}
|
||||
public void setRed(Integer red)
|
||||
{
|
||||
this.red = red;
|
||||
}
|
||||
|
||||
public Integer getRed()
|
||||
{
|
||||
return red;
|
||||
}
|
||||
public void setGreen(Integer green)
|
||||
{
|
||||
this.green = green;
|
||||
}
|
||||
|
||||
public Integer getGreen()
|
||||
{
|
||||
return green;
|
||||
}
|
||||
public void setBlue(Integer blue)
|
||||
{
|
||||
this.blue = blue;
|
||||
}
|
||||
|
||||
public Integer getBlue()
|
||||
{
|
||||
return blue;
|
||||
}
|
||||
|
||||
public void setFadeTime(Integer fadeTime)
|
||||
{
|
||||
this.fadeTime = fadeTime;
|
||||
}
|
||||
public Integer getFadeTime()
|
||||
{
|
||||
return fadeTime;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
|
||||
package com.kerwin.wumei.entity;
|
||||
|
||||
public class IotGroup {
|
||||
/** 设备分组 */
|
||||
private Long groupId;
|
||||
|
||||
/** 用户 */
|
||||
private Long userId;
|
||||
|
||||
/** 分组名称 */
|
||||
private String groupName;
|
||||
|
||||
/** 排序 */
|
||||
private Integer groupOrder;
|
||||
|
||||
public void setGroupId(Long groupId)
|
||||
{
|
||||
this.groupId = groupId;
|
||||
}
|
||||
|
||||
public Long getGroupId()
|
||||
{
|
||||
return groupId;
|
||||
}
|
||||
public void setUserId(Long userId)
|
||||
{
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public Long getUserId()
|
||||
{
|
||||
return userId;
|
||||
}
|
||||
public void setGroupName(String groupName)
|
||||
{
|
||||
this.groupName = groupName;
|
||||
}
|
||||
|
||||
public String getGroupName()
|
||||
{
|
||||
return groupName;
|
||||
}
|
||||
public void setGroupOrder(Integer groupOrder)
|
||||
{
|
||||
this.groupOrder = groupOrder;
|
||||
}
|
||||
|
||||
public Integer getGroupOrder()
|
||||
{
|
||||
return groupOrder;
|
||||
}
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
|
||||
package com.kerwin.wumei.entity;
|
||||
|
||||
public class Roles {
|
||||
private String remark;
|
||||
|
||||
private int roleId;
|
||||
|
||||
private String roleName;
|
||||
|
||||
private String roleKey;
|
||||
|
||||
private String roleSort;
|
||||
|
||||
private String dataScope;
|
||||
|
||||
private boolean menuCheckStrictly;
|
||||
|
||||
private boolean deptCheckStrictly;
|
||||
|
||||
private String status;
|
||||
|
||||
private boolean flag;
|
||||
|
||||
private String menuIds;
|
||||
|
||||
private String deptIds;
|
||||
|
||||
private boolean admin;
|
||||
|
||||
public void setRemark(String remark){
|
||||
this.remark = remark;
|
||||
}
|
||||
public String getRemark(){
|
||||
return this.remark;
|
||||
}
|
||||
public void setRoleId(int roleId){
|
||||
this.roleId = roleId;
|
||||
}
|
||||
public int getRoleId(){
|
||||
return this.roleId;
|
||||
}
|
||||
public void setRoleName(String roleName){
|
||||
this.roleName = roleName;
|
||||
}
|
||||
public String getRoleName(){
|
||||
return this.roleName;
|
||||
}
|
||||
public void setRoleKey(String roleKey){
|
||||
this.roleKey = roleKey;
|
||||
}
|
||||
public String getRoleKey(){
|
||||
return this.roleKey;
|
||||
}
|
||||
public void setRoleSort(String roleSort){
|
||||
this.roleSort = roleSort;
|
||||
}
|
||||
public String getRoleSort(){
|
||||
return this.roleSort;
|
||||
}
|
||||
public void setDataScope(String dataScope){
|
||||
this.dataScope = dataScope;
|
||||
}
|
||||
public String getDataScope(){
|
||||
return this.dataScope;
|
||||
}
|
||||
public void setMenuCheckStrictly(boolean menuCheckStrictly){
|
||||
this.menuCheckStrictly = menuCheckStrictly;
|
||||
}
|
||||
public boolean getMenuCheckStrictly(){
|
||||
return this.menuCheckStrictly;
|
||||
}
|
||||
public void setDeptCheckStrictly(boolean deptCheckStrictly){
|
||||
this.deptCheckStrictly = deptCheckStrictly;
|
||||
}
|
||||
public boolean getDeptCheckStrictly(){
|
||||
return this.deptCheckStrictly;
|
||||
}
|
||||
public void setStatus(String status){
|
||||
this.status = status;
|
||||
}
|
||||
public String getStatus(){
|
||||
return this.status;
|
||||
}
|
||||
public void setFlag(boolean flag){
|
||||
this.flag = flag;
|
||||
}
|
||||
public boolean getFlag(){
|
||||
return this.flag;
|
||||
}
|
||||
public void setMenuIds(String menuIds){
|
||||
this.menuIds = menuIds;
|
||||
}
|
||||
public String getMenuIds(){
|
||||
return this.menuIds;
|
||||
}
|
||||
public void setDeptIds(String deptIds){
|
||||
this.deptIds = deptIds;
|
||||
}
|
||||
public String getDeptIds(){
|
||||
return this.deptIds;
|
||||
}
|
||||
public void setAdmin(boolean admin){
|
||||
this.admin = admin;
|
||||
}
|
||||
public boolean getAdmin(){
|
||||
return this.admin;
|
||||
}
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
|
||||
package com.kerwin.wumei.entity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class User {
|
||||
|
||||
private String remark;
|
||||
|
||||
private int userId;
|
||||
|
||||
private int deptId;
|
||||
|
||||
private String userName;
|
||||
|
||||
private String nickName;
|
||||
|
||||
private String email;
|
||||
|
||||
private String phonenumber;
|
||||
|
||||
private String sex;
|
||||
|
||||
private String avatar;
|
||||
|
||||
private String status;
|
||||
|
||||
private String loginIp;
|
||||
|
||||
private String loginDate;
|
||||
|
||||
private Dept dept;
|
||||
|
||||
private List<Roles> roles ;
|
||||
|
||||
private String roleIds;
|
||||
|
||||
private String postIds;
|
||||
|
||||
private boolean admin;
|
||||
|
||||
private String createTime;
|
||||
|
||||
public void setRemark(String remark){
|
||||
this.remark = remark;
|
||||
}
|
||||
public String getRemark(){
|
||||
return this.remark;
|
||||
}
|
||||
public void setUserId(int userId){
|
||||
this.userId = userId;
|
||||
}
|
||||
public int getUserId(){
|
||||
return this.userId;
|
||||
}
|
||||
public void setDeptId(int deptId){
|
||||
this.deptId = deptId;
|
||||
}
|
||||
public int getDeptId(){
|
||||
return this.deptId;
|
||||
}
|
||||
public void setUserName(String userName){
|
||||
this.userName = userName;
|
||||
}
|
||||
public String getUserName(){
|
||||
return this.userName;
|
||||
}
|
||||
public void setNickName(String nickName){
|
||||
this.nickName = nickName;
|
||||
}
|
||||
public String getNickName(){
|
||||
return this.nickName;
|
||||
}
|
||||
public void setEmail(String email){
|
||||
this.email = email;
|
||||
}
|
||||
public String getEmail(){
|
||||
return this.email;
|
||||
}
|
||||
public void setPhonenumber(String phonenumber){
|
||||
this.phonenumber = phonenumber;
|
||||
}
|
||||
public String getPhonenumber(){
|
||||
return this.phonenumber;
|
||||
}
|
||||
public void setSex(String sex){
|
||||
this.sex = sex;
|
||||
}
|
||||
public String getSex(){
|
||||
return this.sex;
|
||||
}
|
||||
public void setAvatar(String avatar){
|
||||
this.avatar = avatar;
|
||||
}
|
||||
public String getAvatar(){
|
||||
return this.avatar;
|
||||
}
|
||||
public void setStatus(String status){
|
||||
this.status = status;
|
||||
}
|
||||
public String getStatus(){
|
||||
return this.status;
|
||||
}
|
||||
public void setLoginIp(String loginIp){
|
||||
this.loginIp = loginIp;
|
||||
}
|
||||
public String getLoginIp(){
|
||||
return this.loginIp;
|
||||
}
|
||||
public void setLoginDate(String loginDate){
|
||||
this.loginDate = loginDate;
|
||||
}
|
||||
public String getLoginDate(){
|
||||
return this.loginDate;
|
||||
}
|
||||
public void setDept(Dept dept){
|
||||
this.dept = dept;
|
||||
}
|
||||
public Dept getDept(){
|
||||
return this.dept;
|
||||
}
|
||||
public void setRoles(List<Roles> roles){
|
||||
this.roles = roles;
|
||||
}
|
||||
public List<Roles> getRoles(){
|
||||
return this.roles;
|
||||
}
|
||||
public void setRoleIds(String roleIds){
|
||||
this.roleIds = roleIds;
|
||||
}
|
||||
public String getRoleIds(){
|
||||
return this.roleIds;
|
||||
}
|
||||
public void setPostIds(String postIds){
|
||||
this.postIds = postIds;
|
||||
}
|
||||
public String getPostIds(){
|
||||
return this.postIds;
|
||||
}
|
||||
public void setAdmin(boolean admin){
|
||||
this.admin = admin;
|
||||
}
|
||||
public boolean getAdmin(){
|
||||
return this.admin;
|
||||
}
|
||||
public void setCreateTime(String createTime){
|
||||
this.createTime = createTime;
|
||||
}
|
||||
public String getCreateTime(){
|
||||
return this.createTime;
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
|
||||
package com.kerwin.wumei.entity.bo;
|
||||
|
||||
public class CaptureImage {
|
||||
private String uuid;
|
||||
|
||||
private String img;
|
||||
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
public void setUuid(String uuid) {
|
||||
this.uuid = uuid ;
|
||||
}
|
||||
|
||||
public String getImg() {
|
||||
return img;
|
||||
}
|
||||
public void setImg(String img) {
|
||||
this.img = img ;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,222 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
|
||||
package com.kerwin.wumei.entity.vo;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public class IotDeviceVo {
|
||||
private Long deviceId;
|
||||
|
||||
/** 编号 */
|
||||
private String deviceNum;
|
||||
|
||||
/** 分类 */
|
||||
private Long categoryId;
|
||||
|
||||
/** 分类名称 */
|
||||
private String categoryName;
|
||||
|
||||
/** 名称 */
|
||||
private String deviceName;
|
||||
|
||||
/** 固件版本 */
|
||||
private String firmwareVersion;
|
||||
|
||||
/** 用户 */
|
||||
private String ownerId;
|
||||
|
||||
private String nickName;
|
||||
|
||||
/** 删除标志(0代表存在 2代表删除) */
|
||||
private String delFlag;
|
||||
|
||||
/** 报警 */
|
||||
private Integer isAlarm;
|
||||
|
||||
/** 雷达感应 */
|
||||
private Integer isRadar;
|
||||
|
||||
/** 射频遥控 */
|
||||
private Integer isRfControl;
|
||||
|
||||
/** 配网地址 */
|
||||
private String networkAddress;
|
||||
|
||||
/** 配网IP */
|
||||
private String networkIp;
|
||||
|
||||
/** 继电器 */
|
||||
private Integer relayStatus;
|
||||
|
||||
/** 灯状态 */
|
||||
private Integer lightStatus;
|
||||
|
||||
/** 在线 */
|
||||
private Integer isOnline;
|
||||
|
||||
/** 设备温度 */
|
||||
private BigDecimal deviceTemperature;
|
||||
|
||||
/** 设备湿度 */
|
||||
private Integer rssi;
|
||||
|
||||
|
||||
|
||||
public void setDeviceId(Long deviceId)
|
||||
{
|
||||
this.deviceId = deviceId;
|
||||
}
|
||||
public Long getDeviceId()
|
||||
{
|
||||
return deviceId;
|
||||
}
|
||||
public void setDeviceNum(String deviceNum)
|
||||
{
|
||||
this.deviceNum = deviceNum;
|
||||
}
|
||||
public String getDeviceNum()
|
||||
{
|
||||
return deviceNum;
|
||||
}
|
||||
public void setCategoryId(Long categoryId)
|
||||
{
|
||||
this.categoryId = categoryId;
|
||||
}
|
||||
public Long getCategoryId()
|
||||
{
|
||||
return categoryId;
|
||||
}
|
||||
public void setCategoryName(String categoryName)
|
||||
{
|
||||
this.categoryName = categoryName;
|
||||
}
|
||||
public String getCategoryName()
|
||||
{
|
||||
return categoryName;
|
||||
}
|
||||
public void setDeviceName(String deviceName)
|
||||
{
|
||||
this.deviceName = deviceName;
|
||||
}
|
||||
public String getDeviceName()
|
||||
{
|
||||
return deviceName;
|
||||
}
|
||||
public void setFirmwareVersion(String firmwareVersion) { this.firmwareVersion = firmwareVersion; }
|
||||
public String getFirmwareVersion()
|
||||
{
|
||||
return firmwareVersion;
|
||||
}
|
||||
public void setOwnerId(String ownerId)
|
||||
{
|
||||
this.ownerId = ownerId;
|
||||
}
|
||||
public String getOwnerId()
|
||||
{
|
||||
return ownerId;
|
||||
}
|
||||
public void setNickName(String nickName)
|
||||
{
|
||||
this.nickName = nickName;
|
||||
}
|
||||
public String getNickName()
|
||||
{
|
||||
return nickName;
|
||||
}
|
||||
public void setDelFlag(String delFlag)
|
||||
{
|
||||
this.delFlag = delFlag;
|
||||
}
|
||||
public String getDelFlag()
|
||||
{
|
||||
return delFlag;
|
||||
}
|
||||
|
||||
public void setIsAlarm(Integer isAlarm)
|
||||
{
|
||||
this.isAlarm = isAlarm;
|
||||
}
|
||||
public Integer getIsAlarm()
|
||||
{
|
||||
return isAlarm;
|
||||
}
|
||||
public void setIsRadar(Integer isRadar)
|
||||
{
|
||||
this.isRadar = isRadar;
|
||||
}
|
||||
public Integer getIsRadar()
|
||||
{
|
||||
return isRadar;
|
||||
}
|
||||
public void setIsRfControl(Integer isRfControl)
|
||||
{
|
||||
this.isRfControl = isRfControl;
|
||||
}
|
||||
public Integer getIsRfControl()
|
||||
{
|
||||
return isRfControl;
|
||||
}
|
||||
public void setNetworkAddress(String networkAddress)
|
||||
{
|
||||
this.networkAddress = networkAddress;
|
||||
}
|
||||
public String getNetworkAddress()
|
||||
{
|
||||
return networkAddress;
|
||||
}
|
||||
public void setNetworkIp(String networkIp)
|
||||
{
|
||||
this.networkIp = networkIp;
|
||||
}
|
||||
public String getNetworkIp()
|
||||
{
|
||||
return networkIp;
|
||||
}
|
||||
|
||||
public void setRelayStatus(Integer relayStatus)
|
||||
{
|
||||
this.relayStatus = relayStatus;
|
||||
}
|
||||
public Integer getRelayStatus()
|
||||
{
|
||||
return relayStatus;
|
||||
}
|
||||
public void setLightStatus(Integer lightStatus)
|
||||
{
|
||||
this.lightStatus = lightStatus;
|
||||
}
|
||||
public Integer getLightStatus()
|
||||
{
|
||||
return lightStatus;
|
||||
}
|
||||
public void setIsOnline(Integer isOnline)
|
||||
{
|
||||
this.isOnline = isOnline;
|
||||
}
|
||||
public Integer getIsOnline()
|
||||
{
|
||||
return isOnline;
|
||||
}
|
||||
public void setDeviceTemperature(BigDecimal deviceTemperature) { this.deviceTemperature = deviceTemperature; }
|
||||
public BigDecimal getDeviceTemperature()
|
||||
{
|
||||
return deviceTemperature;
|
||||
}
|
||||
public void setRssi(Integer rssi)
|
||||
{
|
||||
this.rssi = rssi;
|
||||
}
|
||||
public Integer getRssi()
|
||||
{
|
||||
return rssi;
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
|
||||
package com.kerwin.wumei.fragment;
|
||||
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.kerwin.wumei.core.webview.AgentWebActivity;
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.grouplist.XUIGroupListView;
|
||||
import com.xuexiang.xutil.app.AppUtils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
|
||||
@Page(name = "关于")
|
||||
public class AboutFragment extends BaseFragment {
|
||||
@BindView(R.id.titlebar_min)
|
||||
TitleBar titleBarMin;
|
||||
|
||||
@BindView(R.id.tv_version)
|
||||
TextView mVersionTextView;
|
||||
@BindView(R.id.about_list)
|
||||
XUIGroupListView mAboutGroupListView;
|
||||
@BindView(R.id.tv_copyright)
|
||||
TextView mCopyrightTextView;
|
||||
@BindView(R.id.tv_autho)
|
||||
TextView tvAutho;
|
||||
|
||||
@Override
|
||||
protected TitleBar initTitle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_about;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initViews() {
|
||||
titleBarMin.setLeftClickListener(v -> popToBack());
|
||||
|
||||
mVersionTextView.setText(String.format("版本号:%s", AppUtils.getAppVersionName()));
|
||||
tvAutho.setText("Author:kerwinci Website:www.wumei.live");
|
||||
|
||||
XUIGroupListView.newSection(getContext())
|
||||
.addItemView(mAboutGroupListView.createItemView(getResources().getString(R.string.about_item_homepage)), v -> AgentWebActivity.goWeb(getContext(), getString(R.string.url_project_github)))
|
||||
.addItemView(mAboutGroupListView.createItemView(getResources().getString(R.string.about_item_author_github)), v -> AgentWebActivity.goWeb(getContext(), getString(R.string.url_author_github)))
|
||||
.addItemView(mAboutGroupListView.createItemView(getResources().getString(R.string.about_item_add_qq_group)), v -> AgentWebActivity.goWeb(getContext(), getString(R.string.url_add_qq_group)))
|
||||
.addTo(mAboutGroupListView);
|
||||
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy", Locale.CHINA);
|
||||
String currentYear = dateFormat.format(new Date());
|
||||
mCopyrightTextView.setText(String.format(getResources().getString(R.string.about_copyright), currentYear));
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
package com.kerwin.wumei.fragment;
|
||||
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.kerwin.wumei.core.webview.AgentWebActivity;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xui.widget.grouplist.XUIGroupListView;
|
||||
import com.xuexiang.xutil.app.AppUtils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
@Page(name = "意见反馈")
|
||||
public class FeedbackFragment extends BaseFragment {
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_feedback;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initViews() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,213 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
|
||||
package com.kerwin.wumei.fragment;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.kerwin.wumei.activity.LoginActivity;
|
||||
import com.kerwin.wumei.activity.MainActivity;
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.entity.IotGroup;
|
||||
import com.kerwin.wumei.entity.bo.CaptureImage;
|
||||
import com.kerwin.wumei.entity.User;
|
||||
import com.kerwin.wumei.http.callback.TipRequestCallBack;
|
||||
import com.kerwin.wumei.http.request.CaptchaImageApiResult;
|
||||
import com.kerwin.wumei.http.request.ListApiResult;
|
||||
import com.kerwin.wumei.http.request.TokenApiResult;
|
||||
import com.kerwin.wumei.http.request.UserInfoApiResult;
|
||||
import com.kerwin.wumei.utils.MMKVUtils;
|
||||
import com.kerwin.wumei.utils.SettingUtils;
|
||||
import com.kerwin.wumei.utils.TokenUtils;
|
||||
import com.kerwin.wumei.utils.Utils;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.xaop.annotation.SingleClick;
|
||||
import com.xuexiang.xhttp2.XHttp;
|
||||
import com.xuexiang.xhttp2.callback.CallBackProxy;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xpage.enums.CoreAnim;
|
||||
import com.xuexiang.xui.utils.ResUtils;
|
||||
import com.xuexiang.xui.utils.ThemeUtils;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.button.roundbutton.RoundButton;
|
||||
import com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText;
|
||||
import com.xuexiang.xutil.app.ActivityUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
|
||||
import static com.kerwin.wumei.utils.SettingUtils.getServerPath;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.clearToken;
|
||||
|
||||
|
||||
/**
|
||||
* 登录页面
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2019-11-17 22:15
|
||||
*/
|
||||
@Page(anim = CoreAnim.none)
|
||||
public class LoginFragment extends BaseFragment {
|
||||
|
||||
@BindView(R.id.et_phone_number)
|
||||
MaterialEditText etPhoneNumber;
|
||||
@BindView(R.id.et_password)
|
||||
MaterialEditText etPassword;
|
||||
@BindView(R.id.et_verify_code)
|
||||
MaterialEditText etVerifyCode;
|
||||
@BindView(R.id.iv_code)
|
||||
ImageView imgVertifyCode;
|
||||
@BindView(R.id.btn_clear)
|
||||
RoundButton btnClear;
|
||||
|
||||
private String uuid="";
|
||||
private String token="";
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_login;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TitleBar initTitle() {
|
||||
TitleBar titleBar = super.initTitle()
|
||||
.setImmersive(true);
|
||||
titleBar.setBackgroundColor(Color.TRANSPARENT);
|
||||
titleBar.setTitle("");
|
||||
titleBar.setLeftImageDrawable(ResUtils.getVectorDrawable(getContext(), R.drawable.ic_login_close));
|
||||
titleBar.setActionTextColor(ThemeUtils.resolveColor(getContext(), R.attr.colorAccent));
|
||||
titleBar.addAction(new TitleBar.TextAction(R.string.title_jump_login) {
|
||||
@Override
|
||||
public void performAction(View view) {
|
||||
clearToken();
|
||||
onLoginSuccess();
|
||||
}
|
||||
});
|
||||
return titleBar;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initViews() {
|
||||
//隐私政策弹窗
|
||||
// if (!SettingUtils.isAgreePrivacy()) {
|
||||
// Utils.showPrivacyDialog(getContext(), (dialog, which) -> {
|
||||
// dialog.dismiss();
|
||||
// SettingUtils.setIsAgreePrivacy(true);
|
||||
// });
|
||||
// }
|
||||
getCatpureImage();
|
||||
getLocalAccount();
|
||||
}
|
||||
|
||||
@SingleClick
|
||||
@OnClick({ R.id.btn_login,R.id.iv_code,R.id.btn_clear})
|
||||
public void onViewClicked(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.btn_clear:
|
||||
SettingUtils.clearPassword();
|
||||
etPassword.clear();
|
||||
break;
|
||||
case R.id.iv_code:
|
||||
getCatpureImage();
|
||||
break;
|
||||
case R.id.btn_login:
|
||||
if(etPhoneNumber.getEditValue().length()==0 || etPassword.getEditValue().length()==0 || etVerifyCode.getEditValue().length()==0){
|
||||
XToastUtils.error("请正确填写账号、密码和验证码");
|
||||
}else {
|
||||
loginByVerifyCode(etPhoneNumber.getEditValue(), etPassword.getEditValue(), etVerifyCode.getEditValue());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录成功的处理
|
||||
*/
|
||||
private void onLoginSuccess() {
|
||||
TokenUtils.handleLoginSuccess(token);
|
||||
popToBack();
|
||||
ActivityUtils.startActivity(MainActivity.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取本地存储的账号
|
||||
*/
|
||||
private void getLocalAccount(){
|
||||
etPhoneNumber.setText(SettingUtils.getUserName());
|
||||
etPassword.setText(SettingUtils.getPassword());
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP获取验证码
|
||||
*/
|
||||
private void getCatpureImage(){
|
||||
XHttp.get(getServerPath()+"/captchaImage")
|
||||
.execute(new CallBackProxy<CaptchaImageApiResult<CaptureImage>, CaptureImage>(new TipRequestCallBack<CaptureImage>() {
|
||||
@Override
|
||||
public void onSuccess(CaptureImage image) throws Throwable {
|
||||
uuid=image.getUuid();
|
||||
byte[] decode = Base64.decode(image.getImg(), Base64.DEFAULT);
|
||||
Bitmap bitmap = BitmapFactory.decodeByteArray(decode, 0, decode.length);
|
||||
imgVertifyCode.setImageBitmap(bitmap);
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
XToastUtils.error(e.getMessage());
|
||||
}
|
||||
}){});
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP登录
|
||||
*
|
||||
* @param phoneNumber 手机号
|
||||
* @param verifyCode 验证码
|
||||
*/
|
||||
private void loginByVerifyCode(String phoneNumber,String password, String verifyCode) {
|
||||
XHttp.post(getServerPath()+ "/login")
|
||||
.upJson("{\"username\":\""+phoneNumber+"\",\"password\":\""+password+"\",\"code\":\""+verifyCode+"\",\"uuid\":\""+uuid+"\"}")
|
||||
.execute(new CallBackProxy<TokenApiResult<String>, String>(new TipRequestCallBack<String>() {
|
||||
@Override
|
||||
public void onSuccess(String tokenResult) throws Throwable {
|
||||
SettingUtils.setAccount(etPhoneNumber.getEditValue(),etPassword.getEditValue());
|
||||
token=tokenResult;
|
||||
onLoginSuccess();
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
clearToken();
|
||||
XToastUtils.error(e.getMessage());
|
||||
}
|
||||
}){});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
package com.kerwin.wumei.fragment;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.kerwin.wumei.core.webview.AgentWebActivity;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.xaop.annotation.SingleClick;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.grouplist.XUIGroupListView;
|
||||
import com.xuexiang.xutil.app.AppUtils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
|
||||
@Page(name = "消息")
|
||||
public class MessageFragment extends BaseFragment {
|
||||
@BindView(R.id.titlebar_min)
|
||||
TitleBar titleBarMin;
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_message;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TitleBar initTitle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initViews() {
|
||||
titleBarMin.setLeftClickListener(v -> popToBack());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
|
||||
package com.kerwin.wumei.fragment;
|
||||
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.http.callback.TipRequestCallBack;
|
||||
import com.kerwin.wumei.http.request.NoDataApiResult;
|
||||
import com.kerwin.wumei.http.request.TokenApiResult;
|
||||
import com.kerwin.wumei.utils.TokenUtils;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.xaop.annotation.SingleClick;
|
||||
import com.xuexiang.xhttp2.XHttp;
|
||||
import com.xuexiang.xhttp2.callback.CallBackProxy;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xui.widget.dialog.DialogLoader;
|
||||
import com.xuexiang.xui.widget.textview.supertextview.SuperTextView;
|
||||
import com.xuexiang.xutil.XUtil;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
import static com.kerwin.wumei.utils.SettingUtils.getServerPath;
|
||||
|
||||
/**
|
||||
* @author xuexiang
|
||||
* @since 2019-10-15 22:38
|
||||
*/
|
||||
@Page(name = "设置")
|
||||
public class SettingsFragment extends BaseFragment implements SuperTextView.OnSuperTextViewClickListener {
|
||||
|
||||
@BindView(R.id.menu_common)
|
||||
SuperTextView menuCommon;
|
||||
@BindView(R.id.menu_privacy)
|
||||
SuperTextView menuPrivacy;
|
||||
@BindView(R.id.menu_push)
|
||||
SuperTextView menuPush;
|
||||
@BindView(R.id.menu_helper)
|
||||
SuperTextView menuHelper;
|
||||
@BindView(R.id.menu_change_account)
|
||||
SuperTextView menuChangeAccount;
|
||||
@BindView(R.id.menu_logout)
|
||||
SuperTextView menuLogout;
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initViews() {
|
||||
menuCommon.setOnSuperTextViewClickListener(this);
|
||||
menuPrivacy.setOnSuperTextViewClickListener(this);
|
||||
menuPush.setOnSuperTextViewClickListener(this);
|
||||
menuHelper.setOnSuperTextViewClickListener(this);
|
||||
menuChangeAccount.setOnSuperTextViewClickListener(this);
|
||||
menuLogout.setOnSuperTextViewClickListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP退出登录
|
||||
*/
|
||||
private void logout(){
|
||||
XHttp.post(getServerPath()+"/logout")
|
||||
.execute(new CallBackProxy<NoDataApiResult<String>, String>(new TipRequestCallBack<String>() {
|
||||
@Override
|
||||
public void onSuccess(String tokenResult) throws Throwable {
|
||||
XToastUtils.success("登出成功" );
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
|
||||
}
|
||||
}){});
|
||||
}
|
||||
|
||||
@SingleClick
|
||||
@Override
|
||||
public void onClick(SuperTextView superTextView) {
|
||||
switch (superTextView.getId()) {
|
||||
case R.id.menu_common:
|
||||
case R.id.menu_privacy:
|
||||
case R.id.menu_push:
|
||||
case R.id.menu_helper:
|
||||
XToastUtils.toast(superTextView.getLeftString());
|
||||
break;
|
||||
case R.id.menu_change_account:
|
||||
XToastUtils.toast(superTextView.getCenterString());
|
||||
break;
|
||||
case R.id.menu_logout:
|
||||
DialogLoader.getInstance().showConfirmDialog(
|
||||
getContext(),
|
||||
getString(R.string.lab_logout_confirm),
|
||||
getString(R.string.lab_yes),
|
||||
(dialog, which) -> {
|
||||
logout();
|
||||
dialog.dismiss();
|
||||
XUtil.getActivityLifecycleHelper().exit();
|
||||
TokenUtils.handleLogoutSuccess();
|
||||
},
|
||||
getString(R.string.lab_no),
|
||||
(dialog, which) -> dialog.dismiss()
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,303 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
*****************************************************************************/
|
||||
package com.kerwin.wumei.fragment.device;
|
||||
|
||||
import android.Manifest;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.text.method.HideReturnsTransformationMethod;
|
||||
import android.text.method.PasswordTransformationMethod;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
|
||||
import com.kerwin.wumei.MyApp;
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.activity.AddDeviceActivity;
|
||||
import com.kerwin.wumei.adapter.entity.EspTouchViewModel;
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.king.view.circleprogressview.CircleProgressView;
|
||||
|
||||
import com.xuexiang.xui.widget.textview.supertextview.SuperButton;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
import static com.kerwin.wumei.utils.SettingUtils.getWifiPassword;
|
||||
import static com.kerwin.wumei.utils.SettingUtils.setWifiPassword;
|
||||
|
||||
|
||||
@Page(name = "智能配网")
|
||||
public class AddDeviceFragment extends BaseFragment {
|
||||
@BindView(R.id.advance_frame_layout)
|
||||
FrameLayout advanceFrameLayout;
|
||||
@BindView(R.id.advance_linear_layout)
|
||||
LinearLayout advanceLinearLayout;
|
||||
@BindView(R.id.advance_icon)
|
||||
AppCompatImageView advanceIcon;
|
||||
@BindView(R.id.wifi_password_icon)
|
||||
AppCompatImageView wifiPasswordIcon;
|
||||
// @BindView(R.id.progressView_circle_main)
|
||||
// CircleProgressView progressViewCircleMain;
|
||||
@BindView(R.id.progress_text_main)
|
||||
TextView progressTextMain;
|
||||
@BindView(R.id.btn_config_cancle)
|
||||
SuperButton btnConfigCancle;
|
||||
@BindView(R.id.btn_return)
|
||||
SuperButton btnReturn;
|
||||
@BindView(R.id.chk_remeber)
|
||||
CheckBox chk_remeber;
|
||||
@BindView(R.id.circleProgressView)
|
||||
CircleProgressView circleProgressView;
|
||||
|
||||
private static final String TAG = AddDeviceFragment.class.getSimpleName();
|
||||
private static final int REQUEST_PERMISSION = 0x01;
|
||||
private EspTouchViewModel mViewModel;
|
||||
|
||||
private boolean bStart=false;
|
||||
|
||||
private Handler mHander=new Handler();
|
||||
private int mCount=0;
|
||||
|
||||
/**
|
||||
* 布局的资源id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_add_device;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
@Override
|
||||
protected void initViews() {
|
||||
//智能配网
|
||||
mViewModel = ((AddDeviceActivity)this.getActivity()).GetMViewModel();
|
||||
|
||||
mViewModel.apPasswordEdit = findViewById(R.id.wifi_password_txt);
|
||||
mViewModel.apPasswordEdit.setText(getWifiPassword());
|
||||
|
||||
mViewModel.ssidSpinner = findViewById(R.id.ssid_spinner);
|
||||
mViewModel.packageModeGroup = findViewById(R.id.packageModeGroup);
|
||||
mViewModel.messageView = findViewById(R.id.txt_config_message);
|
||||
mViewModel.messageView.setText("");
|
||||
|
||||
mViewModel.xsbDeviceCount = findViewById(R.id.xsb_device_count);
|
||||
mViewModel.xsbDeviceCount.setDefaultValue(1);
|
||||
|
||||
mViewModel.confirmBtn = findViewById(R.id.btn_begin);
|
||||
mViewModel.confirmBtn.setOnClickListener(v ->
|
||||
{
|
||||
|
||||
((AddDeviceActivity)this.getActivity()).executeEsptouch();
|
||||
|
||||
//存储wifi密码
|
||||
if(chk_remeber.isChecked()){
|
||||
setWifiPassword(mViewModel.apPasswordEdit.getText().toString());
|
||||
}else{
|
||||
setWifiPassword("");
|
||||
}
|
||||
|
||||
// PageOption.to(AddDeviceTwoFragment.class) //跳转的fragment
|
||||
// .setAnim(CoreAnim.slide) //页面转场动画
|
||||
// .setRequestCode(100) //请求码,用于返回结果
|
||||
// .setAddToBackStack(true) //是否加入堆栈
|
||||
// .putString("device_mac","0908070605040306")
|
||||
// .open(this); //打开页面进行跳转
|
||||
});
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION};
|
||||
requestPermissions(permissions, REQUEST_PERMISSION);
|
||||
}
|
||||
|
||||
MyApp.getInstance().observeBroadcast(this, broadcast -> {
|
||||
Log.d(TAG, "onCreate: Broadcast=" + broadcast);
|
||||
((AddDeviceActivity)this.getActivity()).onWifiChanged();
|
||||
|
||||
List<String> ssids=((AddDeviceActivity)this.getActivity()).GetSsids();
|
||||
if(ssids!=null && ssids.size()>0){
|
||||
Log.e(TAG, "进入数据绑定 " );
|
||||
mViewModel.ssidSpinner.setItems(ssids);
|
||||
// ssidSpinner.setOnItemSelectedListener((spinner, position, id, item) -> SnackbarUtils.Long(spinner, "Clicked " + item).show());
|
||||
// ssidSpinner.setOnNothingSelectedListener(spinner -> SnackbarUtils.Long(spinner, "Nothing selected").show());
|
||||
String ssid=((AddDeviceActivity)this.getActivity()).GetSelectedSSID();
|
||||
if(ssid!=null && ssid.length()>0 && ssids.contains(ssid)) {
|
||||
mViewModel.ssidSpinner.setSelectedItem(ssid);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initListeners() {
|
||||
//单击高级设置项
|
||||
advanceFrameLayout.setOnClickListener(new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
int visible=advanceLinearLayout.getVisibility();
|
||||
if(visible!=0) {
|
||||
advanceLinearLayout.setVisibility(View.VISIBLE);
|
||||
advanceIcon.setImageDrawable(getResources().getDrawable((R.drawable.up)));
|
||||
}else{
|
||||
advanceLinearLayout.setVisibility(View.GONE);
|
||||
advanceIcon.setImageDrawable(getResources().getDrawable((R.drawable.down)));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//显示和隐藏密码
|
||||
wifiPasswordIcon.setOnClickListener(new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick(View view){
|
||||
if(wifiPasswordIcon.getTag()==null) return;
|
||||
if(wifiPasswordIcon.getTag().toString().equals("show")){
|
||||
wifiPasswordIcon.setImageDrawable(getResources().getDrawable((R.drawable.hide)));
|
||||
wifiPasswordIcon.setTag("hide");
|
||||
mViewModel.apPasswordEdit.setTransformationMethod(PasswordTransformationMethod.getInstance());
|
||||
}else{
|
||||
wifiPasswordIcon.setImageDrawable(getResources().getDrawable((R.drawable.show)));
|
||||
wifiPasswordIcon.setTag("show");
|
||||
mViewModel.apPasswordEdit.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
btnConfigCancle.setOnClickListener(new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick(View view){
|
||||
((AddDeviceActivity)getActivity()).interruptEspTouchTask();
|
||||
cancleCounter();
|
||||
}
|
||||
});
|
||||
|
||||
btnReturn.setOnClickListener(new View.OnClickListener(){
|
||||
@Override
|
||||
public void onClick(View view){
|
||||
popToBack();
|
||||
cancleCounter();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
cancleCounter();
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开计时器
|
||||
*/
|
||||
public void beginCounter(){
|
||||
mViewModel.confirmBtn.setEnabled(false);
|
||||
btnConfigCancle.setEnabled(true);
|
||||
showMessage("配网中...",true);
|
||||
mHander.post(mCounter);
|
||||
|
||||
//显示进度动画,进度,动画时长
|
||||
circleProgressView.showAnimation(100,3000);
|
||||
//设置进度改变监听
|
||||
circleProgressView.setOnChangeListener(new CircleProgressView.OnChangeListener() {
|
||||
@Override
|
||||
public void onProgressChanged(float progress, float max) {
|
||||
if(progress==100){
|
||||
circleProgressView.setProgress(0);
|
||||
circleProgressView.showAnimation(100);
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 计时器完成
|
||||
*/
|
||||
public void completeCounter(){
|
||||
mCount=0;
|
||||
mHander.removeCallbacks(mCounter);
|
||||
progressTextMain.setText("100");
|
||||
circleProgressView.setOnChangeListener(null);
|
||||
circleProgressView.showAppendAnimation(100);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭计时器
|
||||
*/
|
||||
public void cancleCounter(){
|
||||
mViewModel.confirmBtn.setEnabled(true);
|
||||
btnConfigCancle.setEnabled(false);
|
||||
showMessage("",true);
|
||||
|
||||
mCount=0;
|
||||
mHander.removeCallbacks(mCounter);
|
||||
progressTextMain.setText("0");
|
||||
circleProgressView.setOnChangeListener(null);
|
||||
circleProgressView.showAppendAnimation(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计时器
|
||||
*/
|
||||
private Runnable mCounter=new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int delay=300;
|
||||
if(mCount<30){
|
||||
mCount++;
|
||||
}else if(mCount<50){
|
||||
mCount++;
|
||||
delay=500;
|
||||
}else if(mCount<80){
|
||||
mCount++;
|
||||
delay=1000;
|
||||
}else if(mCount<90){
|
||||
mCount++;
|
||||
delay=3000;
|
||||
}else if(mCount<98){
|
||||
mCount++;
|
||||
delay=10000;
|
||||
}
|
||||
progressTextMain.setText(mCount + "");
|
||||
mHander.postDelayed(this, delay);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 消息提示
|
||||
* @param message
|
||||
* @param isSuccess
|
||||
*/
|
||||
public void showMessage(String message,boolean isSuccess){
|
||||
if(isSuccess){
|
||||
mViewModel.messageView.setTextColor(Color.argb(255, 103, 194, 58)); // 绿色
|
||||
}else{
|
||||
mViewModel.messageView.setTextColor(Color.argb(255, 245, 108, 108)); //红色
|
||||
}
|
||||
mViewModel.messageView.setText(message);
|
||||
mViewModel.messageView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/***************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
***************************************************************************/
|
||||
package com.kerwin.wumei.fragment.device;
|
||||
|
||||
import android.Manifest;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.method.HideReturnsTransformationMethod;
|
||||
import android.text.method.PasswordTransformationMethod;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
|
||||
import com.kerwin.wumei.MyApp;
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.activity.AddDeviceActivity;
|
||||
import com.kerwin.wumei.activity.MainActivity;
|
||||
import com.kerwin.wumei.adapter.entity.EspTouchViewModel;
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xui.widget.spinner.materialspinner.MaterialSpinner;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
|
||||
@Page(name = "设备信息")
|
||||
public class AddDeviceTwoFragment extends BaseFragment {
|
||||
|
||||
|
||||
/**
|
||||
* 布局的资源id
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_add_device_two;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
@Override
|
||||
protected void initViews() {
|
||||
|
||||
Bundle arguments = getArguments();
|
||||
String mac = arguments.getString("device_mac");
|
||||
XToastUtils.toast("设备MAC:" + mac);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initListeners() {
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
|
||||
package com.kerwin.wumei.fragment.device;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.kerwin.wumei.core.webview.AgentWebActivity;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xui.adapter.FragmentAdapter;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.grouplist.XUIGroupListView;
|
||||
import com.xuexiang.xui.widget.tabbar.TabSegment;
|
||||
import com.xuexiang.xutil.app.AppUtils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
|
||||
@Page(name = "设备详情")
|
||||
public class DeviceDetailFragment extends BaseFragment {
|
||||
@BindView(R.id.titlebar_min)
|
||||
TitleBar titleBarMin;
|
||||
@BindView(R.id.tabSegment)
|
||||
TabSegment tabSegment;
|
||||
@BindView(R.id.contentViewPager)
|
||||
ViewPager contentViewPager;
|
||||
|
||||
@Override
|
||||
protected TitleBar initTitle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_device_detail;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initViews() {
|
||||
titleBarMin.setLeftClickListener(v -> popToBack());
|
||||
|
||||
Bundle arguments = getArguments();
|
||||
Long device_id = arguments.getLong("device_id");
|
||||
String device_num=arguments.getString("device_num");
|
||||
tabSegment.addTab(new TabSegment.Tab("设备"));
|
||||
tabSegment.addTab(new TabSegment.Tab("状态"));
|
||||
tabSegment.addTab(new TabSegment.Tab("配置"));
|
||||
|
||||
FragmentAdapter<BaseFragment> adapter = new FragmentAdapter<>(getChildFragmentManager());
|
||||
adapter.addFragment(new DeviceEditFragment(device_id,device_num), "");
|
||||
adapter.addFragment(new DeviceStatusFragment(device_id,device_num), "");
|
||||
adapter.addFragment(new DeviceSetFragment(device_id,device_num), "");
|
||||
|
||||
contentViewPager.setAdapter(adapter);
|
||||
contentViewPager.setCurrentItem(0, false);
|
||||
tabSegment.setupWithViewPager(contentViewPager, false);
|
||||
tabSegment.setMode(TabSegment.MODE_FIXED);
|
||||
}
|
||||
}
|
||||
@@ -1,244 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
package com.kerwin.wumei.fragment.device;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.kerwin.wumei.entity.DictData;
|
||||
import com.kerwin.wumei.entity.IotDevice;
|
||||
import com.kerwin.wumei.entity.IotDeviceStatus;
|
||||
import com.kerwin.wumei.http.callback.TipRequestCallBack;
|
||||
import com.kerwin.wumei.http.request.NoDataApiResult;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.rxutil2.rxjava.RxJavaUtils;
|
||||
import com.xuexiang.xaop.annotation.SingleClick;
|
||||
import com.xuexiang.xhttp2.XHttp;
|
||||
import com.xuexiang.xhttp2.callback.CallBackProxy;
|
||||
import com.xuexiang.xhttp2.callback.SimpleCallBack;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText;
|
||||
import com.xuexiang.xui.widget.textview.supertextview.SuperButton;
|
||||
import com.xuexiang.xui.widget.toast.XToast;
|
||||
import com.xuexiang.xutil.net.JsonUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
|
||||
import static com.kerwin.wumei.utils.SettingUtils.getServerPath;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.clearToken;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.getToken;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.hasToken;
|
||||
|
||||
@Page(name = "编辑设备")
|
||||
public class DeviceEditFragment extends BaseFragment {
|
||||
|
||||
@BindView(R.id.et_device_name)
|
||||
MaterialEditText et_device_name;
|
||||
@BindView(R.id.et_device_remark)
|
||||
MaterialEditText et_device_remark;
|
||||
@BindView(R.id.txt_device_num)
|
||||
TextView txt_device_num;
|
||||
@BindView(R.id.txt_device_category)
|
||||
TextView txt_device_category;
|
||||
@BindView(R.id.txt_firmware_version)
|
||||
TextView txt_firmware_version;
|
||||
@BindView(R.id.txt_create_time)
|
||||
TextView txt_create_time;
|
||||
@BindView(R.id.sp_device_temperature)
|
||||
SuperButton sp_device_temperature;
|
||||
@BindView(R.id.update_device_temp_icon)
|
||||
AppCompatImageView update_temp_icon;
|
||||
@BindView(R.id.sp_upgrade)
|
||||
SuperButton sp_upgrade;
|
||||
|
||||
private Long deviceId=0L;
|
||||
private String deviceNum="";
|
||||
|
||||
public DeviceEditFragment(Long device_id,String device_num){
|
||||
deviceId=device_id;
|
||||
deviceNum=device_num;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 返回为 null意为不需要导航栏
|
||||
*/
|
||||
@Override
|
||||
protected TitleBar initTitle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 布局的资源id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_device_edit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
@Override
|
||||
protected void initViews() {
|
||||
getDevice(deviceId);
|
||||
}
|
||||
|
||||
@SingleClick
|
||||
@OnClick({ R.id.btn_save,R.id.btn_cancle_edit,R.id.update_device_temp_icon,R.id.sp_upgrade})
|
||||
public void onViewClicked(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.btn_save:
|
||||
updateDevice(buildDevice());
|
||||
break;
|
||||
case R.id.btn_cancle_edit:
|
||||
popToBack();
|
||||
break;
|
||||
case R.id.update_device_temp_icon:
|
||||
getNewStatusData();
|
||||
update_temp_icon.setVisibility(View.GONE);
|
||||
break;
|
||||
case R.id.sp_upgrade:
|
||||
XToastUtils.success("固件已经是最新版本");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 构建设备数据
|
||||
*/
|
||||
private IotDevice buildDevice(){
|
||||
IotDevice device=new IotDevice();
|
||||
device.setDeviceId(deviceId);
|
||||
device.setDeviceNum((String) txt_device_num.getText());
|
||||
device.setDeviceName(et_device_name.getEditValue());
|
||||
device.setRemark(et_device_remark.getEditValue());
|
||||
return device;
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP获取最新设备信息
|
||||
*/
|
||||
private void getNewStatusData(){
|
||||
XHttp.get(getServerPath()+"/system/status/getStatus/"+deviceNum)
|
||||
.headers("Authorization","Bearer "+getToken())
|
||||
.execute(new CallBackProxy<NoDataApiResult<String>, String>(new TipRequestCallBack<String>() {
|
||||
@Override
|
||||
public void onSuccess(String response) {
|
||||
getDeviceStatus(deviceId);
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if(e.getCode()==401){
|
||||
XToastUtils.info("匿名登录状态,功能受限");
|
||||
clearToken();
|
||||
}else{
|
||||
XToastUtils.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}){});
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP获取设备状态
|
||||
*/
|
||||
private void getDeviceStatus(Long device_id){
|
||||
XHttp.get(getServerPath()+"/system/status/new/"+device_id)
|
||||
.headers("Authorization","Bearer "+getToken())
|
||||
.execute(new SimpleCallBack<IotDeviceStatus>() {
|
||||
@Override
|
||||
public void onSuccess(IotDeviceStatus status) throws Throwable {
|
||||
//更新温度
|
||||
sp_device_temperature.setText(status.getDeviceTemperature()+"℃");
|
||||
update_temp_icon.setVisibility(View.VISIBLE);
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if(e.getCode()==401){
|
||||
XToastUtils.info("匿名登录状态,功能受限");
|
||||
clearToken();
|
||||
}else{
|
||||
XToastUtils.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP获取设备信息
|
||||
*/
|
||||
private void getDevice(Long device_id){
|
||||
XHttp.get(getServerPath()+"/system/device/"+device_id)
|
||||
.headers("Authorization","Bearer "+getToken())
|
||||
.execute(new SimpleCallBack<IotDevice>() {
|
||||
@Override
|
||||
public void onSuccess(IotDevice device) throws Throwable {
|
||||
//绑定数据
|
||||
Log.d("deviceName:",device.getDeviceName());
|
||||
et_device_name.setText(device.getDeviceName());
|
||||
et_device_remark.setText(device.getRemark());
|
||||
txt_device_num.setText(device.getDeviceNum());
|
||||
txt_device_category.setText(device.getCategoryName());
|
||||
txt_firmware_version.setText("v"+(device.getFirmwareVersion()==null || device.getFirmwareVersion().length()==0? "1.0" : device.getFirmwareVersion()));
|
||||
txt_create_time.setText(device.getCreateTime());
|
||||
sp_device_temperature.setText(device.getDeviceTemp()==null?0+"℃":device.getDeviceTemp()+"℃");
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if(e.getCode()==401){
|
||||
XToastUtils.info("匿名登录状态,功能受限");
|
||||
clearToken();
|
||||
}else{
|
||||
XToastUtils.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP更新设备信息
|
||||
*/
|
||||
private void updateDevice(IotDevice device){
|
||||
if(!hasToken()) return;
|
||||
XHttp.put(getServerPath()+"/system/device")
|
||||
.upJson(JsonUtil.toJson(device))
|
||||
.headers("Authorization","Bearer "+getToken())
|
||||
.execute(new CallBackProxy<NoDataApiResult<String>, String>(new TipRequestCallBack<String>() {
|
||||
@Override
|
||||
public void onSuccess(String response) throws Throwable {
|
||||
Log.d("response:",response);
|
||||
XToastUtils.success("数据保存成功");
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if(e.getCode()==401){
|
||||
XToastUtils.info("匿名登录状态,功能受限");
|
||||
clearToken();
|
||||
}else{
|
||||
XToastUtils.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}){});
|
||||
}
|
||||
}
|
||||
@@ -1,307 +0,0 @@
|
||||
/****************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
****************************************************************************/
|
||||
package com.kerwin.wumei.fragment.device;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.google.android.material.tabs.TabLayoutMediator;
|
||||
import com.kerwin.wumei.activity.LoginActivity;
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.entity.DictData;
|
||||
import com.kerwin.wumei.entity.IotCategory;
|
||||
import com.kerwin.wumei.entity.IotDevice;
|
||||
import com.kerwin.wumei.entity.IotDeviceSet;
|
||||
import com.kerwin.wumei.entity.IotDeviceStatus;
|
||||
import com.kerwin.wumei.entity.IotGroup;
|
||||
import com.kerwin.wumei.fragment.LoginFragment;
|
||||
import com.kerwin.wumei.http.callback.TipRequestCallBack;
|
||||
import com.kerwin.wumei.http.request.ListApiResult;
|
||||
import com.kerwin.wumei.http.request.NoDataApiResult;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.xhttp2.XHttp;
|
||||
import com.xuexiang.xhttp2.callback.CallBackProxy;
|
||||
import com.xuexiang.xhttp2.callback.SimpleCallBack;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xui.utils.WidgetUtils;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.toast.XToast;
|
||||
import com.xuexiang.xutil.app.ActivityUtils;
|
||||
import com.xuexiang.xutil.net.JsonUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
import static com.google.android.material.tabs.TabLayout.MODE_SCROLLABLE;
|
||||
import static com.kerwin.wumei.utils.SettingUtils.getServerPath;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.clearToken;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.getToken;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.hasToken;
|
||||
|
||||
@Page(name = "设备")
|
||||
public class DeviceFragment extends BaseFragment implements TabLayout.OnTabSelectedListener{
|
||||
|
||||
@BindView(R.id.tab_layout)
|
||||
TabLayout tabLayout;
|
||||
@BindView(R.id.view_pager)
|
||||
ViewPager2 viewPager;
|
||||
|
||||
private boolean mIsShowNavigationView;
|
||||
private FragmentStateViewPager2Adapter mAdapter;
|
||||
|
||||
/**
|
||||
* @return 返回为 null意为不需要导航栏
|
||||
*/
|
||||
@Override
|
||||
protected TitleBar initTitle() {
|
||||
// mAdapter.addFragment(2, SimpleTabFragment.newInstance("动态加入"), "动态加入");
|
||||
// mAdapter.removeFragment(2);
|
||||
// mAdapter.notifyDataSetChanged();
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 布局的资源id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_device;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
@Override
|
||||
protected void initViews() {
|
||||
//获取分组列表
|
||||
getGroupList(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(TabLayout.Tab tab) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(TabLayout.Tab tab) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化设备列表
|
||||
* @param listener
|
||||
* @param groupList
|
||||
*/
|
||||
private void initDeviceListView(@NonNull TabLayout.OnTabSelectedListener listener,List<IotGroup> groupList){
|
||||
mAdapter = new FragmentStateViewPager2Adapter((Fragment) listener);
|
||||
tabLayout.setTabMode(MODE_SCROLLABLE);
|
||||
tabLayout.addOnTabSelectedListener(listener);
|
||||
viewPager.setAdapter(mAdapter);
|
||||
// 设置缓存的数量
|
||||
viewPager.setOffscreenPageLimit(10);
|
||||
new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> tab.setText(mAdapter.getPageTitle(position))).attach();
|
||||
|
||||
// 动态加载选项卡内容
|
||||
for (IotGroup group: groupList) {
|
||||
mAdapter.addFragment(SimpleTabFragment.newInstance(group.getGroupId()), group.getGroupName());
|
||||
}
|
||||
mAdapter.notifyDataSetChanged();
|
||||
viewPager.setCurrentItem(0, false);
|
||||
WidgetUtils.setTabLayoutTextFont(tabLayout);
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP获取分组列表
|
||||
*/
|
||||
private void getGroupList(@NonNull TabLayout.OnTabSelectedListener listener){
|
||||
XHttp.get(getServerPath()+"/system/group/list?pageNum=1&pageSize=100")
|
||||
.headers("Authorization","Bearer "+getToken())
|
||||
.execute(new CallBackProxy<ListApiResult<List<IotGroup>>, List<IotGroup>>(new TipRequestCallBack<List<IotGroup>>() {
|
||||
@Override
|
||||
public void onSuccess(List<IotGroup> list) throws Throwable {
|
||||
List<IotGroup> groupList=list;
|
||||
IotGroup iotGroup=new IotGroup();
|
||||
iotGroup.setGroupId(0L);
|
||||
iotGroup.setGroupName("全部");
|
||||
iotGroup.setGroupOrder(0);
|
||||
groupList.add(0,iotGroup);
|
||||
|
||||
initDeviceListView(listener,groupList);
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if(e.getCode()==401){
|
||||
List<IotGroup> groupList=new ArrayList<IotGroup>();
|
||||
IotGroup group=new IotGroup();
|
||||
group.setGroupId(0L);
|
||||
group.setGroupName("全部");
|
||||
groupList.add(group);
|
||||
initDeviceListView(listener,groupList);
|
||||
XToastUtils.info("匿名登录状态,功能受限");
|
||||
clearToken();
|
||||
}else{
|
||||
XToastUtils.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}){});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* HTTP获取触发源字典列表
|
||||
*/
|
||||
private void getTriggerSourceDic(){
|
||||
XHttp.get(getServerPath()+"/system/dict/data/type/iot_trigger_source")
|
||||
.headers("Authorization","Bearer "+getToken())
|
||||
.execute(new SimpleCallBack<List<DictData>>() {
|
||||
@Override
|
||||
public void onSuccess(List<DictData> response) {
|
||||
Log.d("group name:",response.get(0).getDictLabel());
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if(e.getCode()==401){
|
||||
XToastUtils.info("匿名登录状态,功能受限");
|
||||
clearToken();
|
||||
}else{
|
||||
XToastUtils.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* HTTP获取分组详情
|
||||
*/
|
||||
private void getGroup(Long groupId){
|
||||
if(!hasToken()) return;
|
||||
XHttp.get(getServerPath()+"/system/group/"+groupId)
|
||||
.headers("Authorization","Bearer "+getToken())
|
||||
.execute(new SimpleCallBack<IotGroup>(){
|
||||
@Override
|
||||
public void onSuccess(IotGroup response) throws Throwable {
|
||||
|
||||
Log.d("response:","response");
|
||||
XToastUtils.info("response");
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if(e.getCode()==401){
|
||||
XToastUtils.info("匿名登录状态,功能受限");
|
||||
clearToken();
|
||||
}else{
|
||||
XToastUtils.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP新增分组
|
||||
*/
|
||||
private void addGroup(IotGroup group){
|
||||
if(!hasToken()) return;
|
||||
XHttp.post(getServerPath()+"/system/group")
|
||||
.upJson(JsonUtil.toJson(group))
|
||||
.headers("Authorization","Bearer "+getToken())
|
||||
.execute(new CallBackProxy<NoDataApiResult<String>, String>(new TipRequestCallBack<String>() {
|
||||
@Override
|
||||
public void onSuccess(String response) throws Throwable {
|
||||
|
||||
Log.d("response:","response");
|
||||
XToastUtils.info("response");
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if(e.getCode()==401){
|
||||
XToastUtils.info("匿名登录状态,功能受限");
|
||||
clearToken();
|
||||
}else{
|
||||
XToastUtils.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}){});
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP编辑分组
|
||||
*/
|
||||
private void editGroup(IotGroup group){
|
||||
if(!hasToken()) return;
|
||||
XHttp.put(getServerPath()+"/system/group")
|
||||
.upJson(JsonUtil.toJson(group))
|
||||
.headers("Authorization","Bearer "+getToken())
|
||||
.execute(new CallBackProxy<NoDataApiResult<String>, String>(new TipRequestCallBack<String>() {
|
||||
@Override
|
||||
public void onSuccess(String response) throws Throwable {
|
||||
Log.d("response:","response");
|
||||
XToastUtils.info("response");
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if(e.getCode()==401){
|
||||
XToastUtils.info("匿名登录状态,功能受限");
|
||||
clearToken();
|
||||
}else{
|
||||
XToastUtils.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}){});
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP删除分组
|
||||
*/
|
||||
private void deleteGroup(Long groupId){
|
||||
if(!hasToken()) return;
|
||||
XHttp.delete(getServerPath()+"/system/group/"+groupId)
|
||||
.headers("Authorization","Bearer "+getToken())
|
||||
.execute(new CallBackProxy<NoDataApiResult<String>, String>(new TipRequestCallBack<String>() {
|
||||
@Override
|
||||
public void onSuccess(String response) throws Throwable {
|
||||
Log.d("response:","response");
|
||||
XToastUtils.info("response");
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if(e.getCode()==401){
|
||||
XToastUtils.info("匿名登录状态,功能受限");
|
||||
clearToken();
|
||||
}else{
|
||||
XToastUtils.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}){});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,269 +0,0 @@
|
||||
/***************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
***************************************************************************/
|
||||
package com.kerwin.wumei.fragment.device;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Spinner;
|
||||
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.kerwin.wumei.entity.DictData;
|
||||
import com.kerwin.wumei.entity.IotDevice;
|
||||
import com.kerwin.wumei.entity.IotDeviceSet;
|
||||
import com.kerwin.wumei.http.callback.TipRequestCallBack;
|
||||
import com.kerwin.wumei.http.request.ListApiResult;
|
||||
import com.kerwin.wumei.http.request.NoDataApiResult;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.xaop.annotation.SingleClick;
|
||||
import com.xuexiang.xhttp2.XHttp;
|
||||
import com.xuexiang.xhttp2.callback.CallBackProxy;
|
||||
import com.xuexiang.xhttp2.callback.SimpleCallBack;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xui.utils.WidgetUtils;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.button.switchbutton.SwitchButton;
|
||||
import com.xuexiang.xui.widget.picker.XSeekBar;
|
||||
import com.xuexiang.xutil.net.JsonUtil;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
|
||||
import static com.kerwin.wumei.utils.SettingUtils.getServerPath;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.clearToken;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.getToken;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.hasToken;
|
||||
|
||||
@Page(name = "编辑设备配置")
|
||||
public class DeviceSetFragment extends BaseFragment {
|
||||
|
||||
@BindView(R.id.sb_radar)
|
||||
SwitchButton sb_radar;
|
||||
@BindView(R.id.sb_alarm)
|
||||
SwitchButton sb_alarm;
|
||||
@BindView(R.id.sb_rf_control)
|
||||
SwitchButton sb_rf_control;
|
||||
@BindView(R.id.sb_rf_learn)
|
||||
SwitchButton sb_rf_learn;
|
||||
@BindView(R.id.sb_rf_clear)
|
||||
SwitchButton sb_rf_clear;
|
||||
@BindView(R.id.sb_reset)
|
||||
SwitchButton sb_reset;
|
||||
@BindView(R.id.sb_open_ap)
|
||||
SwitchButton sb_open_ap;
|
||||
|
||||
@BindView(R.id.spinner_rf_func_one)
|
||||
Spinner spinner_rf_func_one;
|
||||
@BindView(R.id.spinner_rf_func_two)
|
||||
Spinner spinner_rf_func_two;
|
||||
@BindView(R.id.spinner_rf_func_three)
|
||||
Spinner spinner_rf_func_three;
|
||||
@BindView(R.id.spinner_rf_func_four)
|
||||
Spinner spinner_rf_func_four;
|
||||
|
||||
@BindView(R.id.xsb_radar_interval)
|
||||
XSeekBar xsb_radar_interval;
|
||||
|
||||
private Long deviceId=0L;
|
||||
private String deviceNum="";
|
||||
private List<DictData> rfFunctionList;
|
||||
private String[] rfFunctionStrings;
|
||||
|
||||
public DeviceSetFragment(Long device_id,String device_num){
|
||||
deviceId=device_id;
|
||||
deviceNum=device_num;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 返回为 null意为不需要导航栏
|
||||
*/
|
||||
@Override
|
||||
protected TitleBar initTitle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 布局的资源id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_device_set;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
@Override
|
||||
protected void initViews() {
|
||||
getRFFunctionDic();
|
||||
|
||||
}
|
||||
|
||||
@SingleClick
|
||||
@OnClick({ R.id.btn_apply_set,R.id.btn_cancle_set})
|
||||
public void onViewClicked(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.btn_apply_set:
|
||||
updateDeviceSet(buildDeviceSet());
|
||||
break;
|
||||
case R.id.btn_cancle_set:
|
||||
popToBack();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建设备配置数据
|
||||
*/
|
||||
private IotDeviceSet buildDeviceSet(){
|
||||
IotDeviceSet deviceSet=new IotDeviceSet();
|
||||
deviceSet.setDeviceId(deviceId);
|
||||
deviceSet.setDeviceNum(deviceNum);
|
||||
deviceSet.setIsHost(0); //不托管
|
||||
deviceSet.setIsRadar(sb_radar.isChecked()==true?1:0);
|
||||
deviceSet.setIsAlarm(sb_alarm.isChecked()==true?1:0);
|
||||
deviceSet.setIsRfLearn(sb_rf_learn.isChecked()==true?1:0);
|
||||
deviceSet.setIsRfClear(sb_rf_clear.isChecked()==true?1:0);
|
||||
deviceSet.setIsAp(sb_open_ap.isChecked()==true?1:0);
|
||||
deviceSet.setIsReset(sb_reset.isChecked()==true?1:0);
|
||||
deviceSet.setIsRfControl(sb_rf_control.isChecked()==true?1:0);
|
||||
deviceSet.setRadarInterval(xsb_radar_interval.getSelectedNumber());
|
||||
deviceSet.setRfOneFunc(getValueByDicString(spinner_rf_func_one.getSelectedItem().toString()));
|
||||
deviceSet.setRfTwoFunc(getValueByDicString(spinner_rf_func_two.getSelectedItem().toString()));
|
||||
deviceSet.setRfThreeFunc(getValueByDicString(spinner_rf_func_three.getSelectedItem().toString()));
|
||||
deviceSet.setRfFourFunc(getValueByDicString(spinner_rf_func_four.getSelectedItem().toString()));
|
||||
return deviceSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典标签获取字典值
|
||||
* @param label
|
||||
* @return
|
||||
*/
|
||||
private int getValueByDicString(String label){
|
||||
for(DictData dict:rfFunctionList){
|
||||
if(dict.getDictLabel().equals(label)){
|
||||
return dict.getDictValue();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典值获取索引
|
||||
*/
|
||||
private int getIndexByDicValue(int value){
|
||||
for(int i=0;i<rfFunctionList.size();i++)
|
||||
{
|
||||
if(rfFunctionList.get(i).getDictValue()==value){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP获取遥控按键功能字典列表
|
||||
*/
|
||||
private void getRFFunctionDic(){
|
||||
XHttp.get(getServerPath()+"/system/dict/data/type/rf_function")
|
||||
.headers("Authorization","Bearer "+getToken())
|
||||
.execute(new SimpleCallBack<List<DictData>>() {
|
||||
@Override
|
||||
public void onSuccess(List<DictData> list) {
|
||||
//绑定数据
|
||||
rfFunctionList=list;
|
||||
rfFunctionStrings=new String[rfFunctionList.size()];
|
||||
for(int i=0;i<rfFunctionList.size();i++){
|
||||
rfFunctionStrings[i]=rfFunctionList.get(i).getDictLabel();
|
||||
}
|
||||
WidgetUtils.initSpinnerStyle(spinner_rf_func_one, rfFunctionStrings);
|
||||
WidgetUtils.initSpinnerStyle(spinner_rf_func_two, rfFunctionStrings);
|
||||
WidgetUtils.initSpinnerStyle(spinner_rf_func_three, rfFunctionStrings);
|
||||
WidgetUtils.initSpinnerStyle(spinner_rf_func_four, rfFunctionStrings);
|
||||
//获取设备配置
|
||||
getDeviceSet(deviceId);
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP获取设备配置
|
||||
*/
|
||||
private void getDeviceSet(Long device_id){
|
||||
XHttp.get(getServerPath()+"/system/set/new/"+device_id)
|
||||
.headers("Authorization","Bearer "+getToken())
|
||||
.execute(new SimpleCallBack<IotDeviceSet>() {
|
||||
@Override
|
||||
public void onSuccess(IotDeviceSet set) throws Throwable {
|
||||
//绑定数据
|
||||
Log.d("device num:",set.getDeviceNum());
|
||||
sb_radar.setChecked(set.getIsRadar()==1);
|
||||
sb_alarm.setChecked(set.getIsAlarm()==1);
|
||||
sb_rf_control.setChecked(set.getIsRfControl()==1);
|
||||
xsb_radar_interval.setDefaultValue(set.getRadarInterval());
|
||||
spinner_rf_func_one.setSelection(getIndexByDicValue(set.getRfOneFunc()));
|
||||
spinner_rf_func_two.setSelection(getIndexByDicValue(set.getRfTwoFunc()));
|
||||
spinner_rf_func_three.setSelection(getIndexByDicValue(set.getRfThreeFunc()));
|
||||
spinner_rf_func_four.setSelection(getIndexByDicValue(set.getRfFourFunc()));
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if(e.getCode()==401){
|
||||
XToastUtils.info("匿名登录状态,功能受限");
|
||||
clearToken();
|
||||
}else{
|
||||
XToastUtils.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP更新设备配置
|
||||
*/
|
||||
private void updateDeviceSet(IotDeviceSet deviceSet){
|
||||
if(!hasToken()) return;
|
||||
XHttp.put(getServerPath()+"/system/set")
|
||||
.upJson(JsonUtil.toJson(deviceSet))
|
||||
.headers("Authorization","Bearer "+getToken())
|
||||
.execute(new CallBackProxy<NoDataApiResult<String>, String>(new TipRequestCallBack<String>() {
|
||||
@Override
|
||||
public void onSuccess(String response) throws Throwable {
|
||||
Log.d("response:",response);
|
||||
XToastUtils.success("设备配置更新成功");
|
||||
sb_reset.setChecked(false);
|
||||
sb_open_ap.setChecked(false);
|
||||
sb_rf_clear.setChecked(false);
|
||||
sb_rf_learn.setChecked(false);
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if(e.getCode()==401){
|
||||
XToastUtils.info("匿名登录状态,功能受限");
|
||||
clearToken();
|
||||
}else{
|
||||
XToastUtils.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}){});
|
||||
}
|
||||
}
|
||||
@@ -1,308 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
*****************************************************************************/
|
||||
package com.kerwin.wumei.fragment.device;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.Spinner;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.kerwin.wumei.entity.DictData;
|
||||
import com.kerwin.wumei.entity.IotDeviceStatus;
|
||||
import com.kerwin.wumei.http.callback.TipRequestCallBack;
|
||||
import com.kerwin.wumei.http.request.NoDataApiResult;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.rxutil2.rxjava.RxJavaUtils;
|
||||
import com.xuexiang.xaop.annotation.SingleClick;
|
||||
import com.xuexiang.xhttp2.XHttp;
|
||||
import com.xuexiang.xhttp2.callback.CallBackProxy;
|
||||
import com.xuexiang.xhttp2.callback.SimpleCallBack;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xui.utils.WidgetUtils;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.button.switchbutton.SwitchButton;
|
||||
import com.xuexiang.xui.widget.dialog.MiniLoadingDialog;
|
||||
import com.xuexiang.xui.widget.picker.XSeekBar;
|
||||
import com.xuexiang.xui.widget.textview.supertextview.SuperButton;
|
||||
import com.xuexiang.xutil.net.JsonUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
|
||||
import static android.R.layout.simple_spinner_item;
|
||||
import static com.kerwin.wumei.utils.SettingUtils.getServerPath;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.clearToken;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.getToken;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.hasToken;
|
||||
|
||||
@Page(name = "编辑设备状态")
|
||||
public class DeviceStatusFragment extends BaseFragment implements CompoundButton.OnCheckedChangeListener {
|
||||
|
||||
@BindView(R.id.sb_relay)
|
||||
SwitchButton sb_relay;
|
||||
@BindView(R.id.sb_light)
|
||||
SwitchButton sb_light;
|
||||
@BindView(R.id.spinner_light_mode)
|
||||
Spinner spinner_light_mode;
|
||||
@BindView(R.id.xsb_fade_interval)
|
||||
XSeekBar xsb_fade_interval;
|
||||
@BindView(R.id.xsb_fade_time)
|
||||
XSeekBar xsb_fade_time;
|
||||
@BindView(R.id.xsb_brightness)
|
||||
XSeekBar xsb_brightness;
|
||||
@BindView(R.id.xsb_red)
|
||||
XSeekBar xsb_red;
|
||||
@BindView(R.id.xsb_green)
|
||||
XSeekBar xsb_green;
|
||||
@BindView(R.id.xsb_blue)
|
||||
XSeekBar xsb_blue;
|
||||
@BindView(R.id.sp_temperature)
|
||||
SuperButton sp_temperature;
|
||||
@BindView(R.id.sp_humidity)
|
||||
SuperButton sp_humidity;
|
||||
@BindView(R.id.frame_layout_loading_status)
|
||||
FrameLayout frame_layout_loading_status;
|
||||
|
||||
private Long deviceId=0L;
|
||||
private String deviceNum="";
|
||||
private List<DictData> lightModeList;
|
||||
private String[] lightModeStrings;
|
||||
|
||||
public DeviceStatusFragment(Long device_id,String device_num){
|
||||
deviceId=device_id;
|
||||
deviceNum=device_num;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 返回为 null意为不需要导航栏
|
||||
*/
|
||||
@Override
|
||||
protected TitleBar initTitle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 布局的资源id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_device_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
@Override
|
||||
protected void initViews() {
|
||||
getLightModeDic();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化监听
|
||||
*/
|
||||
@Override
|
||||
protected void initListeners() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
XToastUtils.toast("isChecked:" + isChecked);
|
||||
}
|
||||
|
||||
@SingleClick
|
||||
@OnClick({ R.id.btn_apply_status,R.id.btn_cancle_status,R.id.frame_layout_loading_status})
|
||||
public void onViewClicked(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.btn_apply_status:
|
||||
updateDeviceStatus(buildDeviceStatus());
|
||||
break;
|
||||
case R.id.btn_cancle_status:
|
||||
popToBack();
|
||||
break;
|
||||
case R.id.frame_layout_loading_status:
|
||||
getNewStatusData();
|
||||
frame_layout_loading_status.setVisibility(View.INVISIBLE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建设备状态数据
|
||||
*/
|
||||
private IotDeviceStatus buildDeviceStatus(){
|
||||
IotDeviceStatus deviceStatus=new IotDeviceStatus();
|
||||
deviceStatus.setDeviceId(deviceId);
|
||||
deviceStatus.setDeviceNum(deviceNum);
|
||||
deviceStatus.setRelayStatus(sb_relay.isChecked()==true?1:0);
|
||||
deviceStatus.setLightStatus(sb_light.isChecked()==true?1:0);
|
||||
deviceStatus.setLightMode(getValueByDicString(spinner_light_mode.getSelectedItem().toString()));
|
||||
deviceStatus.setLightInterval(xsb_fade_interval.getSelectedNumber());
|
||||
deviceStatus.setFadeTime(xsb_fade_time.getSelectedNumber());
|
||||
deviceStatus.setBrightness(xsb_brightness.getSelectedNumber());
|
||||
deviceStatus.setRed(xsb_red.getSelectedNumber());
|
||||
deviceStatus.setBlue(xsb_blue.getSelectedNumber());
|
||||
deviceStatus.setGreen(xsb_green.getSelectedNumber());
|
||||
deviceStatus.setTriggerSource(1); //0-无、1-按键、2.手机、3-浏览器、4-射频遥控、5-雷达、6-报警、7-定时
|
||||
return deviceStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典标签获取字典值
|
||||
*/
|
||||
private int getValueByDicString(String label){
|
||||
for(DictData dict:lightModeList){
|
||||
if(dict.getDictLabel().equals(label)){
|
||||
return dict.getDictValue();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字典值获取索引
|
||||
*/
|
||||
private int getIndexByDicValue(int value){
|
||||
for(int i=0;i<lightModeList.size();i++)
|
||||
{
|
||||
if(lightModeList.get(i).getDictValue()==value){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP获取最新设备信息
|
||||
*/
|
||||
private void getNewStatusData(){
|
||||
XHttp.get(getServerPath()+"/system/status/getStatus/"+deviceNum)
|
||||
.headers("Authorization","Bearer "+getToken())
|
||||
.execute(new CallBackProxy<NoDataApiResult<String>, String>(new TipRequestCallBack<String>() {
|
||||
@Override
|
||||
public void onSuccess(String response) {
|
||||
getDeviceStatus(deviceId);
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if(e.getCode()==401){
|
||||
XToastUtils.info("匿名登录状态,功能受限");
|
||||
clearToken();
|
||||
}else{
|
||||
XToastUtils.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}){});
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP获取灯模式字典列表
|
||||
*/
|
||||
private void getLightModeDic(){
|
||||
XHttp.get(getServerPath()+"/system/dict/data/type/light_mode")
|
||||
.headers("Authorization","Bearer "+getToken())
|
||||
.execute(new SimpleCallBack<List<DictData>>() {
|
||||
@Override
|
||||
public void onSuccess(List<DictData> list) {
|
||||
lightModeList=list;
|
||||
lightModeStrings=new String[lightModeList.size()];
|
||||
for (int i=0;i<lightModeList.size();i++) {
|
||||
lightModeStrings[i]=lightModeList.get(i).getDictLabel();
|
||||
}
|
||||
WidgetUtils.initSpinnerStyle(spinner_light_mode, lightModeStrings);
|
||||
//获取设备状态
|
||||
getDeviceStatus(deviceId);
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP获取设备状态
|
||||
*/
|
||||
private void getDeviceStatus(Long device_id){
|
||||
XHttp.get(getServerPath()+"/system/status/new/"+device_id)
|
||||
.headers("Authorization","Bearer "+getToken())
|
||||
.execute(new SimpleCallBack<IotDeviceStatus>() {
|
||||
@Override
|
||||
public void onSuccess(IotDeviceStatus status) throws Throwable {
|
||||
//绑定数据
|
||||
Log.d("device num:",status.getDeviceNum());
|
||||
sb_relay.setChecked(status.getRelayStatus()==1);
|
||||
sb_light.setChecked(status.getLightStatus()==1);
|
||||
xsb_fade_interval.setDefaultValue(status.getLightInterval());
|
||||
xsb_fade_time.setDefaultValue(status.getFadeTime());
|
||||
xsb_red.setDefaultValue(status.getRed());
|
||||
xsb_green.setDefaultValue(status.getGreen());
|
||||
xsb_blue.setDefaultValue(status.getBlue());
|
||||
xsb_blue.setDefaultValue(status.getBrightness());
|
||||
sp_temperature.setText(status.getAirTemperature()+"℃");
|
||||
sp_humidity.setText(status.getAirHumidity()+"RH%");
|
||||
spinner_light_mode.setSelection(getIndexByDicValue(status.getLightMode()));
|
||||
frame_layout_loading_status.setVisibility(View.VISIBLE);
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if(e.getCode()==401){
|
||||
XToastUtils.info("匿名登录状态,功能受限");
|
||||
clearToken();
|
||||
}else{
|
||||
XToastUtils.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP更新设备状态
|
||||
*/
|
||||
private void updateDeviceStatus(IotDeviceStatus deviceStatus){
|
||||
if(!hasToken()) return;
|
||||
XHttp.put(getServerPath()+"/system/status")
|
||||
.upJson(JsonUtil.toJson(deviceStatus))
|
||||
.headers("Authorization","Bearer "+getToken())
|
||||
.execute(new CallBackProxy<NoDataApiResult<String>, String>(new TipRequestCallBack<String>() {
|
||||
@Override
|
||||
public void onSuccess(String response) throws Throwable {
|
||||
Log.d("response:",response);
|
||||
XToastUtils.success("设备状态更新成功");
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if(e.getCode()==401){
|
||||
XToastUtils.info("匿名登录状态,功能受限");
|
||||
clearToken();
|
||||
}else{
|
||||
XToastUtils.error(e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
}){});
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package com.kerwin.wumei.fragment.device;
|
||||
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
|
||||
@Page(name = "分享设备")
|
||||
public class EditDeviceFragment extends BaseFragment {
|
||||
|
||||
/**
|
||||
* 布局的资源id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_edit_device;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
@Override
|
||||
protected void initViews() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
*****************************************************************************/
|
||||
package com.kerwin.wumei.fragment.device;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* @author xuexiang
|
||||
* @since 2020/5/21 1:27 AM
|
||||
*/
|
||||
public class FragmentStateViewPager2Adapter extends FragmentStateAdapter {
|
||||
|
||||
private List<Fragment> mFragmentList = new ArrayList<>();
|
||||
|
||||
private List<String> mTitleList = new ArrayList<>();
|
||||
|
||||
private List<Long> mIds = new ArrayList<>();
|
||||
|
||||
private AtomicLong mAtomicLong = new AtomicLong(0);
|
||||
|
||||
public FragmentStateViewPager2Adapter(@NonNull Fragment fragment) {
|
||||
super(fragment);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment createFragment(int position) {
|
||||
return mFragmentList.get(position);
|
||||
}
|
||||
|
||||
public FragmentStateViewPager2Adapter addFragment(Fragment fragment, String title) {
|
||||
if (fragment != null) {
|
||||
mFragmentList.add(fragment);
|
||||
mTitleList.add(title);
|
||||
mIds.add(getAtomicGeneratedId());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public FragmentStateViewPager2Adapter addFragment(int index, Fragment fragment, String title) {
|
||||
if (fragment != null && index >= 0 && index <= mFragmentList.size()) {
|
||||
mFragmentList.add(index, fragment);
|
||||
mTitleList.add(index, title);
|
||||
mIds.add(index, getAtomicGeneratedId());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public FragmentStateViewPager2Adapter removeFragment(int index) {
|
||||
if (index >= 0 && index < mFragmentList.size()) {
|
||||
mFragmentList.remove(index);
|
||||
mTitleList.remove(index);
|
||||
mIds.remove(index);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private long getAtomicGeneratedId() {
|
||||
return mAtomicLong.incrementAndGet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mFragmentList.size();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
mFragmentList.clear();
|
||||
mTitleList.clear();
|
||||
mIds.clear();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public CharSequence getPageTitle(int position) {
|
||||
return mTitleList.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return mIds.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsItem(long itemId) {
|
||||
return mIds.contains(itemId);
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
package com.kerwin.wumei.fragment.device;
|
||||
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
|
||||
@Page(name = "分组管理")
|
||||
public class GroupFragment extends BaseFragment {
|
||||
|
||||
/**
|
||||
* 布局的资源id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_group;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
@Override
|
||||
protected void initViews() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package com.kerwin.wumei.fragment.device;/*
|
||||
|
||||
|
||||
/**
|
||||
* @author xuexiang
|
||||
* @since 2018/12/26 下午11:49
|
||||
*/
|
||||
public enum MultiPage {
|
||||
|
||||
全部(0),
|
||||
浇灌(1),
|
||||
一楼(2),
|
||||
二楼(3),
|
||||
三楼(4),
|
||||
走廊(5);
|
||||
|
||||
private final int position;
|
||||
|
||||
MultiPage(int pos) {
|
||||
position = pos;
|
||||
}
|
||||
|
||||
public static MultiPage getPage(int position) {
|
||||
return MultiPage.values()[position];
|
||||
}
|
||||
|
||||
public static int size() {
|
||||
return MultiPage.values().length;
|
||||
}
|
||||
|
||||
public static String[] getPageNames() {
|
||||
MultiPage[] pages = MultiPage.values();
|
||||
String[] pageNames = new String[pages.length];
|
||||
for (int i = 0; i < pages.length; i++) {
|
||||
pageNames[i] = pages[i].name();
|
||||
}
|
||||
return pageNames;
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
package com.kerwin.wumei.fragment.device;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.kerwin.wumei.core.webview.AgentWebActivity;
|
||||
import com.kerwin.wumei.entity.bo.CaptureImage;
|
||||
import com.kerwin.wumei.http.callback.TipRequestCallBack;
|
||||
import com.kerwin.wumei.http.request.CaptchaImageApiResult;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.xaop.annotation.SingleClick;
|
||||
import com.xuexiang.xhttp2.XHttp;
|
||||
import com.xuexiang.xhttp2.callback.CallBackProxy;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xpage.enums.CoreAnim;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.button.switchbutton.SwitchButton;
|
||||
import com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText;
|
||||
import com.xuexiang.xui.widget.textview.supertextview.SuperButton;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
|
||||
import static com.kerwin.wumei.utils.SettingUtils.getApIp;
|
||||
import static com.kerwin.wumei.utils.SettingUtils.getServerAddress;
|
||||
import static com.kerwin.wumei.utils.SettingUtils.getServerPath;
|
||||
import static com.kerwin.wumei.utils.SettingUtils.setAccount;
|
||||
import static com.kerwin.wumei.utils.SettingUtils.setApIp;
|
||||
import static com.kerwin.wumei.utils.SettingUtils.setServeAddress;
|
||||
import static com.kerwin.wumei.utils.SettingUtils.setServePath;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.clearToken;
|
||||
|
||||
|
||||
@Page(name = "用户信息")
|
||||
public class SceneFragment extends BaseFragment {
|
||||
|
||||
@BindView(R.id.btn_connect_test)
|
||||
SuperButton btn_connect_test;
|
||||
@BindView(R.id.btn_save_serve)
|
||||
SuperButton btn_save_serve;
|
||||
@BindView(R.id.txt_message)
|
||||
TextView txt_message;
|
||||
@BindView(R.id.et_serve)
|
||||
MaterialEditText et_serve_address;
|
||||
@BindView(R.id.et_path)
|
||||
MaterialEditText et_serve_path;
|
||||
@BindView(R.id.et_ap_address)
|
||||
MaterialEditText et_ap_address;
|
||||
|
||||
/**
|
||||
* @return 返回为 null意为不需要导航栏
|
||||
*/
|
||||
@Override
|
||||
protected TitleBar initTitle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 布局的资源id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_scene;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
@Override
|
||||
protected void initViews() {
|
||||
et_serve_address.setText(getServerAddress());
|
||||
et_serve_path.setText(getServerPath());
|
||||
et_ap_address.setText(getApIp());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initListeners() { }
|
||||
|
||||
@SingleClick
|
||||
@OnClick({ R.id.btn_save_serve,R.id.btn_connect_test,R.id.btn_open_ap})
|
||||
public void onViewClicked(View view) {
|
||||
if(et_serve_address.getEditValue().length()==0)
|
||||
{
|
||||
showMessage("接口地址不能为空",false);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (view.getId()) {
|
||||
case R.id.btn_save_serve:
|
||||
setServeAddress(et_serve_address.getEditValue());
|
||||
setServePath(et_serve_path.getEditValue());
|
||||
clearToken();
|
||||
setAccount("","");
|
||||
showMessage("服务端地址信息存储成功,请重新启动APP!",true);
|
||||
break;
|
||||
case R.id.btn_connect_test:
|
||||
getCatpureImage();
|
||||
break;
|
||||
case R.id.btn_open_ap:
|
||||
if(et_ap_address.getEditValue()==null || et_ap_address.getEditValue().length()==0){
|
||||
XToastUtils.error("AP的地址不能为空");
|
||||
}else {
|
||||
AgentWebActivity.goWeb(getContext(), et_ap_address.getEditValue());
|
||||
setApIp(et_ap_address.getEditValue());
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* HTTP获取验证码(用于连接测试)
|
||||
*/
|
||||
private void getCatpureImage(){
|
||||
String address=et_serve_address.getEditValue();
|
||||
String path=et_serve_path.getEditValue();
|
||||
if(path==null || path.length()==0){
|
||||
Log.d("地址", address.substring(address.length()-1));
|
||||
if(address.substring(address.length()-1).equals("/")){
|
||||
address=address.substring(0,address.length()-1);
|
||||
}
|
||||
}
|
||||
String fullPath=address+path;
|
||||
XHttp.get(fullPath+ "/captchaImage")
|
||||
.execute(new CallBackProxy<CaptchaImageApiResult<CaptureImage>, CaptureImage>(new TipRequestCallBack<CaptureImage>() {
|
||||
@Override
|
||||
public void onSuccess(CaptureImage image) throws Throwable {
|
||||
String uuid=image.getUuid();
|
||||
showMessage("服务端连接成功",true);
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
showMessage("服务端连接失败\n"+"地址:"+et_serve_address.getEditValue()+et_serve_path.getEditValue()+"\n错误提示:"+e.getMessage(),false);
|
||||
}
|
||||
}){});
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示提示
|
||||
* @param message
|
||||
* @param isSuccess
|
||||
*/
|
||||
private void showMessage(String message,boolean isSuccess){
|
||||
if(isSuccess){
|
||||
txt_message.setTextColor(Color.argb(255, 103, 194, 58)); // 绿色
|
||||
}else{
|
||||
txt_message.setTextColor(Color.argb(255, 245, 108, 108)); //红色
|
||||
}
|
||||
txt_message.setText(message);
|
||||
txt_message.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
package com.kerwin.wumei.fragment.device;
|
||||
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xpage.enums.CoreAnim;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
|
||||
@Page(name = "分享设备")
|
||||
public class ShareDeviceFragment extends BaseFragment {
|
||||
|
||||
/**
|
||||
* 布局的资源id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_share_device;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
@Override
|
||||
protected void initViews() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,386 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
package com.kerwin.wumei.fragment.device;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.os.Vibrator;
|
||||
import android.util.Log;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
import androidx.cardview.widget.CardView;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.alibaba.android.vlayout.DelegateAdapter;
|
||||
import com.alibaba.android.vlayout.VirtualLayoutManager;
|
||||
import com.alibaba.android.vlayout.layout.StaggeredGridLayoutHelper;
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.adapter.base.broccoli.BroccoliSimpleDelegateAdapter;
|
||||
import com.kerwin.wumei.adapter.base.delegate.SimpleDelegateAdapter;
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.kerwin.wumei.entity.IotCategory;
|
||||
import com.kerwin.wumei.entity.IotDeviceStatus;
|
||||
import com.kerwin.wumei.entity.vo.IotDeviceVo;
|
||||
import com.kerwin.wumei.http.callback.TipRequestCallBack;
|
||||
import com.kerwin.wumei.http.request.ListApiResult;
|
||||
import com.kerwin.wumei.http.request.NoDataApiResult;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
|
||||
import com.xuexiang.xhttp2.XHttp;
|
||||
import com.xuexiang.xhttp2.callback.CallBackProxy;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xpage.base.XPageFragment;
|
||||
import com.xuexiang.xpage.core.PageOption;
|
||||
import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.button.SwitchIconView;
|
||||
import com.xuexiang.xutil.net.JsonUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import me.samlss.broccoli.Broccoli;
|
||||
|
||||
import static com.kerwin.wumei.utils.SettingUtils.getServerPath;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.clearToken;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.getToken;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.hasToken;
|
||||
|
||||
@Page(name = "设备")
|
||||
public class SimpleTabFragment extends BaseFragment {
|
||||
private static final String TAG = "SimpleTabFragment";
|
||||
|
||||
|
||||
@BindView(R.id.recyclerView)
|
||||
RecyclerView recyclerView;
|
||||
@BindView(R.id.refreshLayout)
|
||||
SmartRefreshLayout refreshLayout;
|
||||
|
||||
private SimpleDelegateAdapter<IotDeviceVo> deviceAdapter;
|
||||
private List<IotDeviceVo> devices=new ArrayList<IotDeviceVo>() {};
|
||||
private int pageNum=1;
|
||||
private int pageSize=10;
|
||||
private Long groupId=0L;
|
||||
|
||||
|
||||
public static SimpleTabFragment newInstance(Long groupId) {
|
||||
SimpleTabFragment fragment = new SimpleTabFragment();
|
||||
fragment.groupId=groupId;
|
||||
return fragment;
|
||||
}
|
||||
|
||||
/**
|
||||
* 布局的资源id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_simple_tab;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 返回为 null意为不需要导航栏
|
||||
*/
|
||||
@Override
|
||||
protected TitleBar initTitle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
@Override
|
||||
protected void initViews() {
|
||||
initView();
|
||||
//Http获取设备列表
|
||||
getDeviceList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(@NonNull Context context) {
|
||||
super.onAttach(context);
|
||||
Log.e(TAG, "onAttach:" + groupId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
Log.e(TAG, "onDetach:" + groupId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
Log.e(TAG, "onResume:" + groupId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
Log.e(TAG, "onStop:" + groupId);
|
||||
}
|
||||
|
||||
|
||||
private void initView() {
|
||||
|
||||
VirtualLayoutManager virtualLayoutManager = new VirtualLayoutManager(getContext());
|
||||
recyclerView.setLayoutManager(virtualLayoutManager);
|
||||
RecyclerView.RecycledViewPool viewPool = new RecyclerView.RecycledViewPool();
|
||||
recyclerView.setRecycledViewPool(viewPool);
|
||||
viewPool.setMaxRecycledViews(0, 10);
|
||||
|
||||
// 设备
|
||||
FragmentActivity activity=this.getActivity();
|
||||
XPageFragment fragment= this;
|
||||
deviceAdapter = new BroccoliSimpleDelegateAdapter<IotDeviceVo>(R.layout.adapter_device_card_view_list_item, new StaggeredGridLayoutHelper(2,0), devices) {
|
||||
@SuppressLint("ResourceType")
|
||||
@Override
|
||||
protected void onBindData(RecyclerViewHolder holder, IotDeviceVo device, int position) {
|
||||
if (device == null) {return;}
|
||||
|
||||
//设置item宽度,适配屏幕分辨率
|
||||
// CardView view=holder.findViewById(R.id.device_item_card_view);
|
||||
// int widthPixels = getScreenWidth(activity);
|
||||
// int space=dip2px(40); //间隙=左边距+右边距+中间间隔
|
||||
// ViewGroup.LayoutParams cardViewParams=view.getLayoutParams();
|
||||
// cardViewParams.width=(widthPixels-space)/2;
|
||||
|
||||
holder.text(R.id.device_item_title, device.getDeviceName());
|
||||
holder.text(R.id.device_item_temp, device.getDeviceTemperature()==null? 0+"℃":device.getDeviceTemperature()+"℃");
|
||||
holder.text(R.id.device_item_category, device.getCategoryName());
|
||||
|
||||
//状态图标
|
||||
SwitchIconView radarView=holder.findViewById(R.id.device_item_radar_icon);
|
||||
SwitchIconView alarmView=holder.findViewById(R.id.device_item_alarm_icon);
|
||||
SwitchIconView switchIconView=holder.findViewById(R.id.device_item_switch_button);
|
||||
SwitchIconView lightIconView=holder.findViewById(R.id.device_item_light_button);
|
||||
radarView.setIconEnabled(device.getIsRadar()!=null && device.getIsRadar()==1 && device.getIsOnline()==1?true:false);
|
||||
alarmView.setIconEnabled(device.getIsAlarm()!=null && device.getIsAlarm()==1 && device.getIsOnline()==1?true:false);
|
||||
switchIconView.setIconEnabled(device.getRelayStatus()!=null && device.getRelayStatus()==1 && device.getIsOnline()==1?true:false);
|
||||
lightIconView.setIconEnabled(device.getLightStatus()!=null && device.getLightStatus()==1 && device.getIsOnline()==1?true:false);
|
||||
|
||||
//显示网络信号:wifi信号强度(信号极好4格[-55—— 0],信号好3格[-70—— -55),信号一般2格[-85—— -70),信号差1格[-100—— -85))
|
||||
AppCompatImageView wifiView=holder.findViewById(R.id.device_item_wifi_icon);
|
||||
if(device.getIsOnline()!=null && device.getRssi()!=null) {
|
||||
if (device.getIsOnline() == 1 && device.getRssi() >= -55) {
|
||||
wifiView.setImageDrawable(getResources().getDrawable((R.drawable.wifi_4)));
|
||||
} else if (device.getIsOnline() == 1 && device.getRssi() >= 70) {
|
||||
wifiView.setImageDrawable(getResources().getDrawable((R.drawable.wifi_3)));
|
||||
} else if (device.getIsOnline() == 1 && device.getRssi() >= -85) {
|
||||
wifiView.setImageDrawable(getResources().getDrawable((R.drawable.wifi_2)));
|
||||
} else if (device.getIsOnline() == 1 && device.getRssi() >= -100) {
|
||||
wifiView.setImageDrawable(getResources().getDrawable((R.drawable.wifi_1)));
|
||||
}
|
||||
}
|
||||
|
||||
//其他文字、标题和图片
|
||||
FrameLayout flTitle=holder.findViewById(R.id.device_item_fl_title);
|
||||
if(device.getIsOnline()!=null && device.getIsOnline()==1){
|
||||
holder.text(R.id.device_item_wifi, "在线");
|
||||
flTitle.setBackgroundColor(Color.argb(255, 63, 208, 173));
|
||||
}else{
|
||||
holder.text(R.id.device_item_wifi, "离线");
|
||||
flTitle.setBackgroundColor(Color.argb(255, 220, 220, 220));
|
||||
//显示图标
|
||||
AppCompatImageView categoryIcon=holder.findViewById(R.id.device_item_category_icon);
|
||||
AppCompatImageView temp=holder.findViewById(R.id.device_item_temp_icon);
|
||||
categoryIcon.setColorFilter(Color.parseColor("#909399"));
|
||||
temp.setColorFilter(Color.parseColor("#909399"));
|
||||
}
|
||||
|
||||
holder.click(R.id.device_item_light_button, v -> {
|
||||
if(device.getIsOnline()==null || device.getIsOnline()==0) return;
|
||||
//震动
|
||||
Vibrator vibrator = (Vibrator) activity.getSystemService(activity.VIBRATOR_SERVICE);
|
||||
vibrator.vibrate(100);
|
||||
// 更新灯状态
|
||||
updateDeviceStatus(
|
||||
buildDeviceLightStatus(device.getDeviceId(), device.getDeviceNum(),lightIconView.isIconEnabled()==true?0:1)
|
||||
, lightIconView);
|
||||
});
|
||||
holder.click(R.id.device_item_switch_button, v -> {
|
||||
if(device.getIsOnline()==null || device.getIsOnline()==0) return;
|
||||
//震动
|
||||
Vibrator vibrator = (Vibrator) activity.getSystemService(activity.VIBRATOR_SERVICE);
|
||||
vibrator.vibrate(100);
|
||||
// 更新继电器状态
|
||||
updateDeviceStatus(
|
||||
buildDeviceRelayStatus(device.getDeviceId(),device.getDeviceNum(),switchIconView.isIconEnabled()==true?0:1)
|
||||
, switchIconView);
|
||||
});
|
||||
holder.click(R.id.device_item_card_view, v -> {
|
||||
|
||||
PageOption.to(DeviceDetailFragment.class) //跳转的fragment
|
||||
.setAddToBackStack(true) //是否加入堆栈
|
||||
.putLong("device_id", device.getDeviceId()) //传递的参数
|
||||
.putString("device_num",device.getDeviceNum())
|
||||
.setNewActivity(true)
|
||||
.open(fragment); //打开页面进行跳转
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindBroccoli(RecyclerViewHolder holder, Broccoli broccoli) {
|
||||
broccoli.addPlaceholders(
|
||||
holder.findView(R.id.device_item_title),
|
||||
holder.findView(R.id.update_device_temp_icon),
|
||||
holder.findView(R.id.device_item_category),
|
||||
holder.findView(R.id.device_item_category_icon),
|
||||
holder.findView(R.id.device_item_wifi),
|
||||
holder.findView(R.id.device_item_wifi_icon),
|
||||
holder.findView(R.id.device_item_temp),
|
||||
holder.findView(R.id.device_item_temp_icon),
|
||||
holder.findView(R.id.device_item_alarm_icon),
|
||||
holder.findView(R.id.device_item_alarm),
|
||||
holder.findView(R.id.device_item_radar),
|
||||
holder.findView(R.id.device_item_radar_icon),
|
||||
holder.findView(R.id.device_item_switch_button),
|
||||
holder.findView(R.id.device_item_light_button)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
DelegateAdapter delegateAdapter = new DelegateAdapter(virtualLayoutManager);
|
||||
delegateAdapter.addAdapter(deviceAdapter);
|
||||
recyclerView.setAdapter(delegateAdapter);
|
||||
|
||||
//下拉刷新
|
||||
refreshLayout.setOnRefreshListener(refreshLayout -> {
|
||||
refreshLayout.getLayout().postDelayed(() -> {
|
||||
pageNum=1;
|
||||
getDeviceList();
|
||||
}, 1000);
|
||||
});
|
||||
//上拉加载
|
||||
refreshLayout.setOnLoadMoreListener(refreshLayout -> {
|
||||
refreshLayout.getLayout().postDelayed(() -> {
|
||||
pageNum=pageNum+1;
|
||||
getDeviceList();
|
||||
}, 1000);
|
||||
});
|
||||
// refreshLayout.autoRefresh();//第一次进入触发自动刷新
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建设备状态数据
|
||||
*/
|
||||
private IotDeviceStatus buildDeviceLightStatus(Long deviceId,String deviceNum,int lightStatus){
|
||||
IotDeviceStatus deviceStatus=new IotDeviceStatus();
|
||||
deviceStatus.setDeviceId(deviceId);
|
||||
deviceStatus.setDeviceNum(deviceNum);
|
||||
deviceStatus.setLightStatus(lightStatus);
|
||||
deviceStatus.setTriggerSource(1); //0-无、1-按键、2.手机、3-浏览器、4-射频遥控、5-雷达、6-报警、7-定时
|
||||
return deviceStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建设备状态数据
|
||||
*/
|
||||
private IotDeviceStatus buildDeviceRelayStatus(Long deviceId,String deviceNum,int relayStatus){
|
||||
IotDeviceStatus deviceStatus=new IotDeviceStatus();
|
||||
deviceStatus.setDeviceId(deviceId);
|
||||
deviceStatus.setDeviceNum(deviceNum);
|
||||
deviceStatus.setRelayStatus(relayStatus);
|
||||
deviceStatus.setTriggerSource(1); //0-无、1-按键、2.手机、3-浏览器、4-射频遥控、5-雷达、6-报警、7-定时
|
||||
return deviceStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP更新设备状态
|
||||
*/
|
||||
private void updateDeviceStatus(IotDeviceStatus deviceStatus,SwitchIconView iconView){
|
||||
if(!hasToken()) return;
|
||||
XHttp.put(getServerPath()+"/system/status")
|
||||
.upJson(JsonUtil.toJson(deviceStatus))
|
||||
.headers("Authorization","Bearer "+getToken())
|
||||
.execute(new CallBackProxy<NoDataApiResult<String>, String>(new TipRequestCallBack<String>() {
|
||||
@Override
|
||||
public void onSuccess(String response) throws Throwable {
|
||||
Log.d("response:",response);
|
||||
iconView.switchState(true);
|
||||
XToastUtils.success("设备状态更新成功");
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if(e.getCode()==401){
|
||||
XToastUtils.info("匿名登录状态,功能受限");
|
||||
clearToken();
|
||||
}else{
|
||||
XToastUtils.error(e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
}){});
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP获取设备列表
|
||||
*/
|
||||
private void getDeviceList(){
|
||||
XHttp.get(getServerPath()+"/system/device/list?"+"pageNum="+pageNum+"&pageSize="+pageSize+"&groupId="+groupId)
|
||||
.headers("Authorization","Bearer "+getToken())
|
||||
.execute(new CallBackProxy<ListApiResult<List<IotDeviceVo>>, List<IotDeviceVo>>(new TipRequestCallBack<List<IotDeviceVo>>() {
|
||||
@Override
|
||||
public void onSuccess(List<IotDeviceVo> list) throws Throwable {
|
||||
if(pageNum==1) {
|
||||
deviceAdapter.refresh(list);
|
||||
refreshLayout.finishRefresh();
|
||||
}else {
|
||||
deviceAdapter.loadMore(list);
|
||||
refreshLayout.finishLoadMore();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if(e.getCode()==401){
|
||||
XToastUtils.info("匿名登录状态,功能受限");
|
||||
clearToken();
|
||||
}else{
|
||||
XToastUtils.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}){});
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP获取分类列表
|
||||
*/
|
||||
private void getCategoryList(){
|
||||
XHttp.get(getServerPath()+"/system/category/list?pageNum=1&pageSize=100")
|
||||
.headers("Authorization","Bearer "+getToken())
|
||||
.execute(new CallBackProxy<ListApiResult<List<IotCategory>>, List<IotCategory>>(new TipRequestCallBack<List<IotCategory>>() {
|
||||
@Override
|
||||
public void onSuccess(List<IotCategory> list) throws Throwable {
|
||||
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if(e.getCode()==401){
|
||||
XToastUtils.info("匿名登录状态,功能受限");
|
||||
clearToken();
|
||||
}else{
|
||||
XToastUtils.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}){});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
package com.kerwin.wumei.fragment.news;
|
||||
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.alibaba.android.vlayout.DelegateAdapter;
|
||||
import com.alibaba.android.vlayout.VirtualLayoutManager;
|
||||
import com.alibaba.android.vlayout.layout.GridLayoutHelper;
|
||||
import com.alibaba.android.vlayout.layout.LinearLayoutHelper;
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.adapter.base.broccoli.BroccoliSimpleDelegateAdapter;
|
||||
import com.kerwin.wumei.adapter.base.delegate.SimpleDelegateAdapter;
|
||||
import com.kerwin.wumei.adapter.base.delegate.SingleDelegateAdapter;
|
||||
import com.kerwin.wumei.adapter.entity.NewInfo;
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.kerwin.wumei.utils.DemoDataProvider;
|
||||
import com.kerwin.wumei.utils.Utils;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xpage.enums.CoreAnim;
|
||||
import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder;
|
||||
import com.xuexiang.xui.adapter.simple.AdapterItem;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.banner.widget.banner.SimpleImageBanner;
|
||||
import com.xuexiang.xui.widget.imageview.ImageLoader;
|
||||
import com.xuexiang.xui.widget.imageview.RadiusImageView;
|
||||
|
||||
import butterknife.BindView;
|
||||
import me.samlss.broccoli.Broccoli;
|
||||
|
||||
@Page(anim = CoreAnim.none)
|
||||
public class HomePageFragment extends BaseFragment {
|
||||
|
||||
@BindView(R.id.webview_home)
|
||||
WebView webView;
|
||||
@BindView(R.id.refreshLayout)
|
||||
SmartRefreshLayout refreshLayout;
|
||||
|
||||
private SimpleDelegateAdapter<NewInfo> mNewsAdapter;
|
||||
|
||||
/**
|
||||
* @return 返回为 null意为不需要导航栏
|
||||
*/
|
||||
@Override
|
||||
protected TitleBar initTitle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 布局的资源id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_home_page;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
@Override
|
||||
protected void initViews() {
|
||||
webView.loadUrl("http://wumei.live");
|
||||
//系统默认会通过手机浏览器打开网页,为了能够直接通过WebView显示网页,则必须设置
|
||||
webView.setWebViewClient(new WebViewClient(){
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
//使用WebView加载显示url
|
||||
view.loadUrl(url);
|
||||
//返回true
|
||||
return true;
|
||||
}
|
||||
});
|
||||
// 支持js中alert弹窗提示
|
||||
webView.setWebChromeClient(new WebChromeClient());
|
||||
|
||||
//声明WebSettings子类
|
||||
WebSettings webSettings = webView.getSettings();
|
||||
//如果访问的页面中要与Javascript交互,则webview必须设置支持Javascript
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //关闭webview中缓存
|
||||
webSettings.setLoadsImagesAutomatically(true); //支持自动加载图片
|
||||
webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initListeners() {
|
||||
//下拉刷新
|
||||
refreshLayout.setOnRefreshListener(refreshLayout -> {
|
||||
refreshLayout.getLayout().postDelayed(() -> {
|
||||
webView.reload();
|
||||
refreshLayout.finishRefresh();
|
||||
}, 1000);
|
||||
});
|
||||
//上拉加载
|
||||
refreshLayout.setOnLoadMoreListener(refreshLayout -> {
|
||||
// TODO: 2020-02-25 这里只是模拟了网络请求
|
||||
refreshLayout.getLayout().postDelayed(() -> {
|
||||
webView.reload();
|
||||
refreshLayout.finishLoadMore();
|
||||
}, 1000);
|
||||
});
|
||||
refreshLayout.autoRefresh();//第一次进入触发自动刷新,演示效果
|
||||
}
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
package com.kerwin.wumei.fragment.news;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.alibaba.android.vlayout.DelegateAdapter;
|
||||
import com.alibaba.android.vlayout.VirtualLayoutManager;
|
||||
import com.alibaba.android.vlayout.layout.GridLayoutHelper;
|
||||
import com.alibaba.android.vlayout.layout.LinearLayoutHelper;
|
||||
import com.kerwin.wumei.adapter.base.broccoli.BroccoliSimpleDelegateAdapter;
|
||||
import com.kerwin.wumei.adapter.base.delegate.SimpleDelegateAdapter;
|
||||
import com.kerwin.wumei.adapter.base.delegate.SingleDelegateAdapter;
|
||||
import com.kerwin.wumei.adapter.entity.NewInfo;
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.utils.DemoDataProvider;
|
||||
import com.kerwin.wumei.utils.Utils;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xpage.enums.CoreAnim;
|
||||
import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder;
|
||||
import com.xuexiang.xui.adapter.simple.AdapterItem;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.banner.widget.banner.SimpleImageBanner;
|
||||
import com.xuexiang.xui.widget.imageview.ImageLoader;
|
||||
import com.xuexiang.xui.widget.imageview.RadiusImageView;
|
||||
|
||||
import butterknife.BindView;
|
||||
import me.samlss.broccoli.Broccoli;
|
||||
|
||||
@Page(anim = CoreAnim.none)
|
||||
public class NewsFragment extends BaseFragment {
|
||||
|
||||
@BindView(R.id.recyclerView)
|
||||
RecyclerView recyclerView;
|
||||
@BindView(R.id.refreshLayout)
|
||||
SmartRefreshLayout refreshLayout;
|
||||
|
||||
private SimpleDelegateAdapter<NewInfo> mNewsAdapter;
|
||||
|
||||
/**
|
||||
* @return 返回为 null意为不需要导航栏
|
||||
*/
|
||||
@Override
|
||||
protected TitleBar initTitle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 布局的资源id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_news;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
@Override
|
||||
protected void initViews() {
|
||||
VirtualLayoutManager virtualLayoutManager = new VirtualLayoutManager(getContext());
|
||||
recyclerView.setLayoutManager(virtualLayoutManager);
|
||||
RecyclerView.RecycledViewPool viewPool = new RecyclerView.RecycledViewPool();
|
||||
recyclerView.setRecycledViewPool(viewPool);
|
||||
viewPool.setMaxRecycledViews(0, 10);
|
||||
|
||||
//轮播条
|
||||
SingleDelegateAdapter bannerAdapter = new SingleDelegateAdapter(R.layout.include_head_view_banner) {
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerViewHolder holder, int position) {
|
||||
SimpleImageBanner banner = holder.findViewById(R.id.sib_simple_usage);
|
||||
banner.setSource(DemoDataProvider.getBannerList())
|
||||
.setOnItemClickListener((view, item, position1) -> XToastUtils.toast("headBanner position--->" + position1)).startScroll();
|
||||
}
|
||||
};
|
||||
|
||||
//九宫格菜单
|
||||
GridLayoutHelper gridLayoutHelper = new GridLayoutHelper(4);
|
||||
gridLayoutHelper.setPadding(0, 16, 0, 0);
|
||||
gridLayoutHelper.setVGap(10);
|
||||
gridLayoutHelper.setHGap(0);
|
||||
SimpleDelegateAdapter<AdapterItem> commonAdapter = new SimpleDelegateAdapter<AdapterItem>(R.layout.adapter_common_grid_item, gridLayoutHelper, DemoDataProvider.getGridItems(getContext())) {
|
||||
@Override
|
||||
protected void bindData(@NonNull RecyclerViewHolder holder, int position, AdapterItem item) {
|
||||
if (item != null) {
|
||||
RadiusImageView imageView = holder.findViewById(R.id.riv_item);
|
||||
imageView.setCircle(true);
|
||||
ImageLoader.get().loadImage(imageView, item.getIcon());
|
||||
holder.text(R.id.device_item_title, item.getTitle().toString().substring(0, 1));
|
||||
holder.text(R.id.tv_sub_title, item.getTitle());
|
||||
|
||||
holder.click(R.id.ll_container, v -> XToastUtils.toast("点击了:" + item.getTitle()));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//动态的标题
|
||||
SingleDelegateAdapter titleAdapter = new SingleDelegateAdapter(R.layout.adapter_title_item) {
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerViewHolder holder, int position) {
|
||||
holder.text(R.id.device_item_title, "动态");
|
||||
holder.text(R.id.tv_action, "更多");
|
||||
holder.click(R.id.tv_action, v -> XToastUtils.toast("更多"));
|
||||
}
|
||||
};
|
||||
|
||||
// 动态
|
||||
mNewsAdapter = new BroccoliSimpleDelegateAdapter<NewInfo>(R.layout.adapter_news_card_view_list_item, new LinearLayoutHelper(), DemoDataProvider.getEmptyNewInfo()) {
|
||||
@Override
|
||||
protected void onBindData(RecyclerViewHolder holder, NewInfo model, int position) {
|
||||
if (model != null) {
|
||||
holder.text(R.id.tv_user_name, model.getUserName());
|
||||
holder.text(R.id.tv_tag, model.getTag());
|
||||
holder.text(R.id.device_item_title, model.getTitle());
|
||||
holder.text(R.id.tv_summary, model.getSummary());
|
||||
holder.text(R.id.tv_praise, model.getPraise() == 0 ? "点赞" : String.valueOf(model.getPraise()));
|
||||
holder.text(R.id.tv_comment, model.getComment() == 0 ? "评论" : String.valueOf(model.getComment()));
|
||||
holder.text(R.id.tv_read, "阅读量 " + model.getRead());
|
||||
holder.image(R.id.iv_image, model.getImageUrl());
|
||||
|
||||
holder.click(R.id.card_view, v -> Utils.goWeb(getContext(), model.getDetailUrl()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindBroccoli(RecyclerViewHolder holder, Broccoli broccoli) {
|
||||
broccoli.addPlaceholders(
|
||||
holder.findView(R.id.tv_user_name),
|
||||
holder.findView(R.id.tv_tag),
|
||||
holder.findView(R.id.device_item_title),
|
||||
holder.findView(R.id.tv_summary),
|
||||
holder.findView(R.id.tv_praise),
|
||||
holder.findView(R.id.tv_comment),
|
||||
holder.findView(R.id.tv_read),
|
||||
holder.findView(R.id.iv_image)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
DelegateAdapter delegateAdapter = new DelegateAdapter(virtualLayoutManager);
|
||||
delegateAdapter.addAdapter(bannerAdapter);
|
||||
delegateAdapter.addAdapter(commonAdapter);
|
||||
delegateAdapter.addAdapter(titleAdapter);
|
||||
delegateAdapter.addAdapter(mNewsAdapter);
|
||||
|
||||
recyclerView.setAdapter(delegateAdapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initListeners() {
|
||||
//下拉刷新
|
||||
refreshLayout.setOnRefreshListener(refreshLayout -> {
|
||||
// TODO: 2020-02-25 这里只是模拟了网络请求
|
||||
refreshLayout.getLayout().postDelayed(() -> {
|
||||
mNewsAdapter.refresh(DemoDataProvider.getDemoNewInfos());
|
||||
refreshLayout.finishRefresh();
|
||||
}, 1000);
|
||||
});
|
||||
//上拉加载
|
||||
refreshLayout.setOnLoadMoreListener(refreshLayout -> {
|
||||
// TODO: 2020-02-25 这里只是模拟了网络请求
|
||||
refreshLayout.getLayout().postDelayed(() -> {
|
||||
mNewsAdapter.loadMore(DemoDataProvider.getDemoNewInfos());
|
||||
refreshLayout.finishLoadMore();
|
||||
}, 1000);
|
||||
});
|
||||
refreshLayout.autoRefresh();//第一次进入触发自动刷新,演示效果
|
||||
}
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
package com.kerwin.wumei.fragment.profile;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.kerwin.wumei.entity.User;
|
||||
import com.kerwin.wumei.entity.bo.CaptureImage;
|
||||
import com.kerwin.wumei.http.callback.TipRequestCallBack;
|
||||
import com.kerwin.wumei.http.request.CaptchaImageApiResult;
|
||||
import com.kerwin.wumei.http.request.UserInfoApiResult;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.xaop.annotation.SingleClick;
|
||||
import com.xuexiang.xhttp2.XHttp;
|
||||
import com.xuexiang.xhttp2.callback.CallBackProxy;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xpage.enums.CoreAnim;
|
||||
import com.xuexiang.xui.utils.ResUtils;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.button.switchbutton.SwitchButton;
|
||||
import com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText;
|
||||
import com.xuexiang.xui.widget.imageview.RadiusImageView;
|
||||
import com.xuexiang.xui.widget.textview.supertextview.SuperButton;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
|
||||
import static com.kerwin.wumei.utils.SettingUtils.getServerPath;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.clearToken;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.getToken;
|
||||
import static com.kerwin.wumei.utils.TokenUtils.hasToken;
|
||||
|
||||
|
||||
@Page(name = "账户信息")
|
||||
public class AccountFragment extends BaseFragment {
|
||||
@BindView(R.id.titlebar_min)
|
||||
TitleBar titleBarMin;
|
||||
|
||||
@BindView(R.id.txt_user_name)
|
||||
TextView txt_user_name;
|
||||
@BindView(R.id.txt_nick_name)
|
||||
TextView txt_nick_name;
|
||||
@BindView(R.id.txt_email)
|
||||
TextView txt_email;
|
||||
@BindView(R.id.txt_phone_num)
|
||||
TextView txt_phone_num;
|
||||
@BindView(R.id.txt_create_time)
|
||||
TextView txt_create_time;
|
||||
@BindView(R.id.txt_remark)
|
||||
TextView txt_remark;
|
||||
|
||||
@Override
|
||||
protected TitleBar initTitle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 布局的资源id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_account;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
@Override
|
||||
protected void initViews() {
|
||||
titleBarMin.setLeftClickListener(v -> popToBack());
|
||||
getUserInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initListeners() { }
|
||||
|
||||
@SingleClick
|
||||
@OnClick({ R.id.btn_confirm})
|
||||
public void onViewClicked(View view) {
|
||||
popToBack();
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP获取用户信息
|
||||
*/
|
||||
private void getUserInfo(){
|
||||
if(!hasToken()) return;
|
||||
XHttp.get(getServerPath()+"/getInfo")
|
||||
.headers("Authorization","Bearer "+getToken())
|
||||
.execute(new CallBackProxy<UserInfoApiResult<User>, User>(new TipRequestCallBack<User>() {
|
||||
@Override
|
||||
public void onSuccess(User user) throws Throwable {
|
||||
txt_user_name.setText(user.getUserName());
|
||||
txt_nick_name.setText(user.getNickName());
|
||||
txt_email.setText(user.getEmail());
|
||||
txt_phone_num.setText(user.getPhonenumber());
|
||||
txt_remark.setText(user.getRemark());
|
||||
txt_create_time.setText(user.getCreateTime());
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if(e.getCode()==401){
|
||||
XToastUtils.info("匿名登录状态,功能受限");
|
||||
clearToken();
|
||||
}else{
|
||||
XToastUtils.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}){});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
package com.kerwin.wumei.fragment.profile;
|
||||
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.kerwin.wumei.core.BaseFragment;
|
||||
import com.kerwin.wumei.R;
|
||||
import com.kerwin.wumei.core.webview.AgentWebActivity;
|
||||
import com.kerwin.wumei.fragment.AboutFragment;
|
||||
import com.kerwin.wumei.fragment.FeedbackFragment;
|
||||
import com.kerwin.wumei.fragment.MessageFragment;
|
||||
import com.kerwin.wumei.fragment.SettingsFragment;
|
||||
import com.kerwin.wumei.http.callback.TipRequestCallBack;
|
||||
import com.kerwin.wumei.http.request.NoDataApiResult;
|
||||
import com.kerwin.wumei.utils.TokenUtils;
|
||||
import com.kerwin.wumei.utils.XToastUtils;
|
||||
import com.xuexiang.xaop.annotation.SingleClick;
|
||||
import com.xuexiang.xhttp2.XHttp;
|
||||
import com.xuexiang.xhttp2.callback.CallBackProxy;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xpage.annotation.Page;
|
||||
import com.xuexiang.xpage.enums.CoreAnim;
|
||||
import com.xuexiang.xpage.utils.Utils;
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar;
|
||||
import com.xuexiang.xui.widget.dialog.DialogLoader;
|
||||
import com.xuexiang.xui.widget.grouplist.XUIGroupListView;
|
||||
import com.xuexiang.xui.widget.imageview.RadiusImageView;
|
||||
import com.xuexiang.xui.widget.textview.supertextview.SuperTextView;
|
||||
import com.xuexiang.xutil.XUtil;
|
||||
import com.xuexiang.xutil.app.AppUtils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
import static com.kerwin.wumei.utils.SettingUtils.getServerPath;
|
||||
|
||||
@Page(anim = CoreAnim.none)
|
||||
public class ProfileFragment extends BaseFragment implements SuperTextView.OnSuperTextViewClickListener {
|
||||
@BindView(R.id.riv_head_pic)
|
||||
RadiusImageView rivHeadPic;
|
||||
@BindView(R.id.menu_message)
|
||||
SuperTextView menuMessage;
|
||||
@BindView(R.id.menu_logout)
|
||||
SuperTextView menuLogout;
|
||||
@BindView(R.id.control_list)
|
||||
XUIGroupListView mControlGroupListView;
|
||||
@BindView(R.id.tv_copyright)
|
||||
TextView mCopyrightTextView;
|
||||
@BindView(R.id.menu_account)
|
||||
SuperTextView menuAccount;
|
||||
|
||||
/**
|
||||
* @return 返回为 null意为不需要导航栏
|
||||
*/
|
||||
@Override
|
||||
protected TitleBar initTitle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 布局的资源id
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
@Override
|
||||
protected void initViews() {
|
||||
XUIGroupListView.newSection(getContext())
|
||||
.addItemView(mControlGroupListView.createItemView(getResources().getString(R.string.about_item_add_qq_group)), v -> AgentWebActivity.goWeb(getContext(), getString(R.string.url_add_qq_group)))
|
||||
.addItemView(mControlGroupListView.createItemView("应用版本 - V" + AppUtils.getAppVersionName()), v -> XToastUtils.toast("官网下载最新版本"))
|
||||
.addTo(mControlGroupListView);
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy", Locale.CHINA);
|
||||
String currentYear = dateFormat.format(new Date());
|
||||
mCopyrightTextView.setText(String.format(getResources().getString(R.string.about_copyright), currentYear));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initListeners() {
|
||||
menuMessage.setOnSuperTextViewClickListener(this);
|
||||
menuLogout.setOnSuperTextViewClickListener(this);
|
||||
menuAccount.setOnSuperTextViewClickListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP退出登录
|
||||
*/
|
||||
private void logout(){
|
||||
XHttp.post(getServerPath()+"/logout")
|
||||
.execute(new CallBackProxy<NoDataApiResult<String>, String>(new TipRequestCallBack<String>() {
|
||||
@Override
|
||||
public void onSuccess(String tokenResult) throws Throwable {
|
||||
XToastUtils.success("登出成功" );
|
||||
}
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
|
||||
}
|
||||
}){});
|
||||
}
|
||||
|
||||
@SingleClick
|
||||
@Override
|
||||
public void onClick(SuperTextView view) {
|
||||
switch(view.getId()) {
|
||||
case R.id.menu_message:
|
||||
openNewPage(MessageFragment.class);
|
||||
break;
|
||||
case R.id.menu_account:
|
||||
openNewPage(AccountFragment.class);
|
||||
break;
|
||||
case R.id.menu_logout:
|
||||
DialogLoader.getInstance().showConfirmDialog(
|
||||
getContext(),
|
||||
getString(R.string.lab_logout_confirm),
|
||||
getString(R.string.lab_yes),
|
||||
(dialog, which) -> {
|
||||
logout();
|
||||
dialog.dismiss();
|
||||
XUtil.getActivityLifecycleHelper().exit();
|
||||
TokenUtils.handleLogoutSuccess();
|
||||
},
|
||||
getString(R.string.lab_no),
|
||||
(dialog, which) -> dialog.dismiss()
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.http.callback;
|
||||
|
||||
import com.xuexiang.xhttp2.callback.SimpleCallBack;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xhttp2.model.XHttpRequest;
|
||||
import com.xuexiang.xutil.common.StringUtils;
|
||||
import com.xuexiang.xutil.common.logger.Logger;
|
||||
|
||||
/**
|
||||
* @author xuexiang
|
||||
* @since 2018/8/8 上午10:23
|
||||
*/
|
||||
public abstract class NoTipRequestCallBack<T> extends SimpleCallBack<T> {
|
||||
/**
|
||||
* 记录一下请求的url,确定出错的请求是哪个请求
|
||||
*/
|
||||
private String mUrl;
|
||||
|
||||
public NoTipRequestCallBack() {
|
||||
|
||||
}
|
||||
|
||||
public NoTipRequestCallBack(XHttpRequest req) {
|
||||
this(req.getUrl());
|
||||
}
|
||||
|
||||
public NoTipRequestCallBack(String url) {
|
||||
mUrl = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
if (!StringUtils.isEmpty(mUrl)) {
|
||||
Logger.e("网络请求的url:" + mUrl, e);
|
||||
} else {
|
||||
Logger.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.http.callback;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.xuexiang.xhttp2.callback.SimpleCallBack;
|
||||
import com.xuexiang.xhttp2.exception.ApiException;
|
||||
import com.xuexiang.xhttp2.model.XHttpRequest;
|
||||
import com.xuexiang.xutil.common.StringUtils;
|
||||
import com.xuexiang.xutil.common.logger.Logger;
|
||||
import com.xuexiang.xutil.tip.ToastUtils;
|
||||
|
||||
/**
|
||||
* @author xuexiang
|
||||
* @since 2018/8/8 上午10:20
|
||||
*/
|
||||
public abstract class TipRequestCallBack<T> extends SimpleCallBack<T> {
|
||||
|
||||
/**
|
||||
* 记录一下请求的url,确定出错的请求是哪个请求
|
||||
*/
|
||||
private String mUrl;
|
||||
|
||||
public TipRequestCallBack() {
|
||||
|
||||
}
|
||||
|
||||
public TipRequestCallBack(@NonNull XHttpRequest req) {
|
||||
this(req.getUrl());
|
||||
}
|
||||
|
||||
public TipRequestCallBack(String url) {
|
||||
mUrl = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ApiException e) {
|
||||
ToastUtils.toast(e.getDisplayMessage());
|
||||
if (!StringUtils.isEmpty(mUrl)) {
|
||||
Logger.e("网络请求的url:" + mUrl, e);
|
||||
} else {
|
||||
Logger.e(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 xuexiangjys(xuexiangjys@163.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.kerwin.wumei.http.interceptor;
|
||||
|
||||
import com.xuexiang.xhttp2.interceptor.HttpLoggingInterceptor;
|
||||
import com.xuexiang.xhttp2.utils.HttpUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import okhttp3.Connection;
|
||||
import okhttp3.Protocol;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
import okhttp3.internal.http.HttpHeaders;
|
||||
|
||||
/**
|
||||
* 自定义日志拦截器【简单打印入参和出参】
|
||||
*
|
||||
* @author xuexiang
|
||||
* @since 2018/8/6 上午11:53
|
||||
*/
|
||||
public class CustomLoggingInterceptor extends HttpLoggingInterceptor {
|
||||
|
||||
public CustomLoggingInterceptor() {
|
||||
super("custom");
|
||||
setLevel(Level.PARAM);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void logForRequest(Request request, Connection connection) throws IOException {
|
||||
RequestBody requestBody = request.body();
|
||||
boolean hasRequestBody = requestBody != null;
|
||||
Protocol protocol = connection != null ? connection.protocol() : Protocol.HTTP_1_1;
|
||||
|
||||
StringBuilder logBuilder = new StringBuilder();
|
||||
try {
|
||||
logBuilder.append("--> ")
|
||||
.append(request.method())
|
||||
.append(' ')
|
||||
.append(request.url())
|
||||
.append(' ')
|
||||
.append(protocol)
|
||||
.append("\r\n");
|
||||
if (hasRequestBody) {
|
||||
logBuilder.append("入参:");
|
||||
if (HttpUtils.isPlaintext(requestBody.contentType())) {
|
||||
logBuilder.append(bodyToString(request));
|
||||
} else {
|
||||
logBuilder.append("maybe [file part] , too large too print , ignored!");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
log(logBuilder.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Response logForResponse(Response response, long tookMs) {
|
||||
Response clone = response.newBuilder().build();
|
||||
ResponseBody responseBody = clone.body();
|
||||
log("<-- " + clone.code() + ' ' + clone.message() + ' ' + clone.request().url() + " (" + tookMs + "ms)");
|
||||
try {
|
||||
if (HttpHeaders.hasBody(clone)) {
|
||||
if (responseBody == null) {
|
||||
return response;
|
||||
}
|
||||
if (HttpUtils.isPlaintext(responseBody.contentType())) {
|
||||
String body = responseBody.string();
|
||||
log("\t出参:" + body);
|
||||
responseBody = ResponseBody.create(responseBody.contentType(), body);
|
||||
return response.newBuilder().body(responseBody).build();
|
||||
} else {
|
||||
log("\t出参: maybe [file part] , too large too print , ignored!");
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
/******************************************************************************
|
||||
* 作者:kerwincui
|
||||
* 时间:2021-06-08
|
||||
* 邮箱:164770707@qq.com
|
||||
* 源码地址:https://gitee.com/kerwincui/wumei-smart
|
||||
* author: kerwincui
|
||||
* create: 2021-06-08
|
||||
* email:164770707@qq.com
|
||||
* source:https://github.com/kerwincui/wumei-smart
|
||||
******************************************************************************/
|
||||
|
||||
package com.kerwin.wumei.http.request;
|
||||
|
||||
import com.kerwin.wumei.entity.bo.CaptureImage;
|
||||
import com.xuexiang.xhttp2.model.ApiResult;
|
||||
|
||||
|
||||
public class CaptchaImageApiResult<T> extends ApiResult<T> {
|
||||
private String uuid;
|
||||
private String img;
|
||||
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
public CaptchaImageApiResult<T> setUuid(String uuid) {
|
||||
this.uuid = uuid;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getImg() {
|
||||
return img;
|
||||
}
|
||||
public CaptchaImageApiResult<T> setImg(String img) {
|
||||
this.img = img;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isSuccess() {
|
||||
return getCode()==200;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getData() {
|
||||
CaptureImage image=new CaptureImage();
|
||||
image.setImg(getImg());
|
||||
image.setUuid(getUuid());
|
||||
return (T) image;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ApiResult{" +
|
||||
"code='" + CODE + '\'' +
|
||||
", msg='" + MSG + '\'' +
|
||||
", uuid='" + uuid + '\'' +
|
||||
", img=" + img +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user