Compare commits
453 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c5fa250331 | ||
![]() |
a51588ddd2 | ||
![]() |
b066c40176 | ||
![]() |
bbc2c6b35a | ||
![]() |
42b0b576d1 | ||
![]() |
39f680bb24 | ||
![]() |
19ffd2b491 | ||
![]() |
a8efa1ac07 | ||
![]() |
240b7af585 | ||
![]() |
345915cdf4 | ||
![]() |
d7fb1e0044 | ||
![]() |
0d8018b10e | ||
![]() |
d9b443429d | ||
![]() |
e698f4f8a3 | ||
![]() |
c27e1a697e | ||
![]() |
d549fb905d | ||
![]() |
c758cb60d9 | ||
![]() |
eab5ef59b9 | ||
![]() |
c0a699e21e | ||
![]() |
242662d02a | ||
![]() |
e1ca1552f7 | ||
![]() |
93a160b40d | ||
![]() |
5fad229dbe | ||
![]() |
43a809490c | ||
![]() |
a02ba42cf9 | ||
![]() |
3ca9d47aae | ||
![]() |
c3e81e0f45 | ||
![]() |
c7fd1f186b | ||
![]() |
ed2b119f33 | ||
![]() |
465e92f8bc | ||
![]() |
09c7b21fd8 | ||
![]() |
6671683d08 | ||
![]() |
9e6d931e3b | ||
![]() |
64c349e39a | ||
![]() |
bea8b77538 | ||
![]() |
480e98144d | ||
![]() |
7037bc3e9c | ||
![]() |
4e241f9b1b | ||
![]() |
79ea0a08c3 | ||
![]() |
e02b8cd80e | ||
![]() |
ba56933e87 | ||
![]() |
45ad90bfbc | ||
![]() |
35f6e25d18 | ||
![]() |
b031cf3d07 | ||
![]() |
3821b9e6d6 | ||
![]() |
21354b76ff | ||
![]() |
602c203495 | ||
![]() |
0ead57926c | ||
![]() |
002b01823e | ||
![]() |
45ed83501e | ||
![]() |
2c69c5ccf3 | ||
![]() |
e52b8a27d6 | ||
![]() |
2dc8deca59 | ||
![]() |
25392dd8bd | ||
![]() |
60a8eccb5f | ||
![]() |
6cf9e9d105 | ||
![]() |
5489f0a089 | ||
![]() |
cc12359ba6 | ||
![]() |
173aa6792a | ||
![]() |
72c0c6f4a6 | ||
![]() |
5e8948b534 | ||
![]() |
19b7b57b43 | ||
![]() |
ae37d587d4 | ||
![]() |
0f635d6e80 | ||
![]() |
eeb5f5f2ec | ||
![]() |
4342d87b37 | ||
![]() |
27ddf42897 | ||
![]() |
b642b14d5a | ||
![]() |
b2a9854e1a | ||
![]() |
9d738f0d9d | ||
![]() |
d32d866393 | ||
![]() |
f09434869e | ||
![]() |
f12f6694c4 | ||
![]() |
6a3d989778 | ||
![]() |
de1b05d307 | ||
![]() |
16ab3672cd | ||
![]() |
108b9e4bf4 | ||
![]() |
82d1fe8815 | ||
![]() |
ecc017845d | ||
![]() |
6b2157fc1c | ||
![]() |
b8b4da7ac9 | ||
![]() |
0b3edc812c | ||
![]() |
30521f00cd | ||
![]() |
4eea2cb4e1 | ||
![]() |
aa2537eb6d | ||
![]() |
1747a0a737 | ||
![]() |
60c41783cc | ||
![]() |
3d53b22e37 | ||
![]() |
719a599c41 | ||
![]() |
10111b2beb | ||
![]() |
1fd3b308e9 | ||
![]() |
ee5c2b6632 | ||
![]() |
6155bdbe20 | ||
![]() |
8ffbd0b44d | ||
![]() |
a5d678b72e | ||
![]() |
e48c49ce0c | ||
![]() |
7993b04cf4 | ||
![]() |
ca54511cf6 | ||
![]() |
fc463810f6 | ||
![]() |
a1369cdd67 | ||
![]() |
3178624b4b | ||
![]() |
2530487483 | ||
![]() |
03c16e3f1b | ||
![]() |
fee35fe285 | ||
![]() |
b310032cf5 | ||
![]() |
07aae0674f | ||
![]() |
cbea1539f8 | ||
![]() |
90d514ac6a | ||
![]() |
97bc77b03a | ||
![]() |
02ee182508 | ||
![]() |
6e2b258eee | ||
![]() |
5a183d27d1 | ||
![]() |
b52c7ca39a | ||
![]() |
e677d815d4 | ||
![]() |
471d2b86c7 | ||
![]() |
aaf08fea0c | ||
![]() |
37275e2c7c | ||
![]() |
723a4996fb | ||
![]() |
cb53c8bbd6 | ||
![]() |
cc37dab980 | ||
![]() |
24ed554b1d | ||
![]() |
deea4bd696 | ||
![]() |
7db4456aae | ||
![]() |
98c204e74e | ||
![]() |
028d5f5a4f | ||
![]() |
4716e77e6d | ||
![]() |
c1f8862128 | ||
![]() |
05564afdec | ||
![]() |
b1856022c6 | ||
![]() |
b201a4ed0c | ||
![]() |
a34c6e316b | ||
![]() |
f6a630c5c9 | ||
![]() |
6bc82c3cff | ||
![]() |
a0e33276b6 | ||
![]() |
42754339db | ||
![]() |
a8a6dfc802 | ||
![]() |
29c608b176 | ||
![]() |
2be3c0509b | ||
![]() |
86f0891321 | ||
![]() |
72757fd653 | ||
![]() |
a534f37efb | ||
![]() |
246936ede7 | ||
![]() |
dd69feac52 | ||
![]() |
36fc7a4eed | ||
![]() |
fb5c273c8e | ||
![]() |
d8f9aa7bd7 | ||
![]() |
5b2af1b0c8 | ||
![]() |
97ee9bf5fe | ||
![]() |
4f789c560d | ||
![]() |
aca7faa3fa | ||
![]() |
422bba662f | ||
![]() |
b2687ca1d6 | ||
![]() |
edff08c3c2 | ||
![]() |
e7014bf7ac | ||
![]() |
5c8c46f3ad | ||
![]() |
6b73ed74ed | ||
![]() |
7912f12cf5 | ||
![]() |
001a337994 | ||
![]() |
f7895cea87 | ||
![]() |
f91728b081 | ||
![]() |
c9fbb97018 | ||
![]() |
18a43ac471 | ||
![]() |
908921e978 | ||
![]() |
8773d6205c | ||
![]() |
a505850110 | ||
![]() |
d9a86d4c16 | ||
![]() |
5acc87c405 | ||
![]() |
f39fc1386a | ||
![]() |
1758c2c9f1 | ||
![]() |
35cc9bce42 | ||
![]() |
cf94cfb543 | ||
![]() |
9d5af90c61 | ||
![]() |
755588202f | ||
![]() |
5af693265f | ||
![]() |
1cd02f02e0 | ||
![]() |
4bf168eedd | ||
![]() |
04ab3aefa4 | ||
![]() |
f8f48e1be4 | ||
![]() |
b5ab4eb978 | ||
![]() |
1a1a06b499 | ||
![]() |
96cf03b277 | ||
![]() |
528eecb63c | ||
![]() |
6f91a60cb2 | ||
![]() |
98b3b74610 | ||
![]() |
4817ec1411 | ||
![]() |
6443b9fecf | ||
![]() |
9419f9d943 | ||
![]() |
4bdc45b105 | ||
![]() |
54712a10b4 | ||
![]() |
46da689cda | ||
![]() |
b5fc3e07e0 | ||
![]() |
477024c79e | ||
![]() |
8fd6d0a4fb | ||
![]() |
ababe82a37 | ||
![]() |
548fe432a7 | ||
![]() |
3e372bc9f9 | ||
![]() |
21303adb27 | ||
![]() |
e7eba5f332 | ||
![]() |
0f91aff535 | ||
![]() |
f850c9b73d | ||
![]() |
8666eabde8 | ||
![]() |
f051b710df | ||
![]() |
dc39730c0b | ||
![]() |
6ecf410f6f | ||
![]() |
3555f18de1 | ||
![]() |
149ae6aa95 | ||
![]() |
f423a04f08 | ||
![]() |
86613d08d5 | ||
![]() |
afb6928bb1 | ||
![]() |
826852b729 | ||
![]() |
e7f4e8b8d3 | ||
![]() |
d6e4645d08 | ||
![]() |
28a88172f3 | ||
![]() |
b3dcaf2721 | ||
![]() |
98442b6938 | ||
![]() |
3ee4823354 | ||
![]() |
a4027e0f73 | ||
![]() |
437db5fab3 | ||
![]() |
dbdc8e38d5 | ||
![]() |
6ab33ce442 | ||
![]() |
06620d6c52 | ||
![]() |
dfa6edf9ed | ||
![]() |
9f54ff09f8 | ||
![]() |
c843950e5f | ||
![]() |
6fa6e5710b | ||
![]() |
58130712e6 | ||
![]() |
3d84a1f488 | ||
![]() |
1d0e533643 | ||
![]() |
1b218c8515 | ||
![]() |
7391dbbf64 | ||
![]() |
17d9aeabeb | ||
![]() |
aca17d551c | ||
![]() |
e69a7f7556 | ||
![]() |
d49653cb33 | ||
![]() |
5aafe23c7a | ||
![]() |
5b14043201 | ||
![]() |
9c0141345f | ||
![]() |
ba794c1116 | ||
![]() |
904a7ef3ac | ||
![]() |
909cedba75 | ||
![]() |
70c7d6dace | ||
![]() |
2fa0ac280c | ||
![]() |
7c3cf560bc | ||
![]() |
4bd129f1d3 | ||
![]() |
6a8a9fd323 | ||
![]() |
d2728ea23e | ||
![]() |
e256cf9892 | ||
![]() |
70ca7b184e | ||
![]() |
29f5d0c8b3 | ||
![]() |
96637c71e6 | ||
![]() |
1f570e38d9 | ||
![]() |
49e69c9ec1 | ||
![]() |
d7ace10735 | ||
![]() |
41094bdaf3 | ||
![]() |
bcbc1940bf | ||
![]() |
17cceab5a1 | ||
![]() |
51eaaf6c94 | ||
![]() |
82b9f21fc0 | ||
![]() |
191b3e5eab | ||
![]() |
a7a6679573 | ||
![]() |
09614a75ea | ||
![]() |
9c2d061283 | ||
![]() |
b97f1f7955 | ||
![]() |
6d14eb4562 | ||
![]() |
ce4375f7c7 | ||
![]() |
1e090e2440 | ||
![]() |
c1d8b944b3 | ||
![]() |
f0ddc16aea | ||
![]() |
8e8a7c0b74 | ||
![]() |
d558d396ed | ||
![]() |
a207798f5c | ||
![]() |
d1e80bb067 | ||
![]() |
1b594fa830 | ||
![]() |
b5d59349f3 | ||
![]() |
e9bdbb2662 | ||
![]() |
363f5baf39 | ||
![]() |
ee606b84a5 | ||
![]() |
7318d500ba | ||
![]() |
e010f2324c | ||
![]() |
5af3f54272 | ||
![]() |
03eef2d0c0 | ||
![]() |
bdd84a74f1 | ||
![]() |
857540cf8b | ||
![]() |
ea15f8ef97 | ||
![]() |
2685c3de52 | ||
![]() |
12ebb865fc | ||
![]() |
d3be7d692d | ||
![]() |
ce7d241196 | ||
![]() |
eb6ab1ec0a | ||
![]() |
fc8321de17 | ||
![]() |
2a31b0dc61 | ||
![]() |
5fe5754a2d | ||
![]() |
2d9d0c30b1 | ||
![]() |
bde60282f1 | ||
![]() |
6710b74477 | ||
![]() |
bb8fce0272 | ||
![]() |
08b45d3518 | ||
![]() |
1d99cc0f7e | ||
![]() |
8b21c7c1fe | ||
![]() |
fa827e4edb | ||
![]() |
a34216e39f | ||
![]() |
3c3a9c92d4 | ||
![]() |
1a787fe502 | ||
![]() |
509f975fcb | ||
![]() |
9e222c77e0 | ||
![]() |
06863bd8f0 | ||
![]() |
4d19ac29da | ||
![]() |
2bf5f6830f | ||
![]() |
b8d39c9a50 | ||
![]() |
0bc06daa5d | ||
![]() |
d0f64fd44d | ||
![]() |
59c4422ba3 | ||
![]() |
4eaf98c3f0 | ||
![]() |
7cb7b93ccc | ||
![]() |
72a972aa25 | ||
![]() |
161f4248c8 | ||
![]() |
7ca8939889 | ||
![]() |
ef4d1c616f | ||
![]() |
ac35df82ca | ||
![]() |
e4326c12b4 | ||
![]() |
e5205358b4 | ||
![]() |
0bcb7e6bca | ||
![]() |
cd76e5816b | ||
![]() |
679b0f05a7 | ||
![]() |
64470b3991 | ||
![]() |
d85a26c89e | ||
![]() |
825f5f09b5 | ||
![]() |
4a6db7c6b0 | ||
![]() |
0435f6b89c | ||
![]() |
06b3de011e | ||
![]() |
e20f11d528 | ||
![]() |
33ea00507b | ||
![]() |
295fe1793f | ||
![]() |
f8fbc37083 | ||
![]() |
a700b09e53 | ||
![]() |
9b9ead6301 | ||
![]() |
3b6255d8a4 | ||
![]() |
75d43f13b8 | ||
![]() |
51bad7d319 | ||
![]() |
71c7ba4b80 | ||
![]() |
e3c22ca370 | ||
![]() |
6ea5204a22 | ||
![]() |
63ecaf5e04 | ||
![]() |
b80efee952 | ||
![]() |
0eea69d785 | ||
![]() |
a33c6eeb2d | ||
![]() |
0b5883bacb | ||
![]() |
24570a5538 | ||
![]() |
7965f95940 | ||
![]() |
438aea3400 | ||
![]() |
57e4dc8757 | ||
![]() |
9c92916b2b | ||
![]() |
089abd8d6d | ||
![]() |
8cb1522033 | ||
![]() |
4cf206e7e9 | ||
![]() |
d1a2873f3d | ||
![]() |
3adf7ab0fb | ||
![]() |
a6a5e3cc9b | ||
![]() |
6e95bbe380 | ||
![]() |
b21dbb8646 | ||
![]() |
b6c439e0f9 | ||
![]() |
19349ea032 | ||
![]() |
8c2fa955ce | ||
![]() |
6fa5ff6608 | ||
![]() |
292d3219d6 | ||
![]() |
3c22024d94 | ||
![]() |
3afd269a9c | ||
![]() |
4662c0bdaa | ||
![]() |
2975d4c09f | ||
![]() |
018e3221a7 | ||
![]() |
38e4b05e56 | ||
![]() |
a1827f6266 | ||
![]() |
725c82c1b0 | ||
![]() |
30b6c28a52 | ||
![]() |
ed86a2fb4f | ||
![]() |
ee1a794680 | ||
![]() |
dc314963f9 | ||
![]() |
47e8e43318 | ||
![]() |
efe757be07 | ||
![]() |
69fc823beb | ||
![]() |
3a36bb5c2e | ||
![]() |
64e99cf90f | ||
![]() |
611974ecbf | ||
![]() |
36cb4e8a4c | ||
![]() |
a6a4147005 | ||
![]() |
8c8c79d68a | ||
![]() |
857bc5c29e | ||
![]() |
a4e66540c2 | ||
![]() |
801682500a | ||
![]() |
5d24061cfd | ||
![]() |
8ddc28524f | ||
![]() |
7743588f35 | ||
![]() |
e526f67228 | ||
![]() |
6f81c482c6 | ||
![]() |
7f9f1d771b | ||
![]() |
e4f44025f1 | ||
![]() |
20cccf4832 | ||
![]() |
91909a887c | ||
![]() |
04b69a9e2b | ||
![]() |
3d4055d1e8 | ||
![]() |
0e38288705 | ||
![]() |
22cffbb0d8 | ||
![]() |
a0c809f0ad | ||
![]() |
be9b6515cd | ||
![]() |
2a4c9f0fcb | ||
![]() |
e9b03e5a2a | ||
![]() |
f38450fc19 | ||
![]() |
1c8a56e314 | ||
![]() |
c3c31ed033 | ||
![]() |
646f2c8e9f | ||
![]() |
9c3176852e | ||
![]() |
8856f19277 | ||
![]() |
d96dda0519 | ||
![]() |
a81140be47 | ||
![]() |
3cb6cc747b | ||
![]() |
5187b88a08 | ||
![]() |
8cd82e0287 | ||
![]() |
4caab6a135 | ||
![]() |
b9efb143be | ||
![]() |
c927f37013 | ||
![]() |
bdbb95110b | ||
![]() |
5c7be1e852 | ||
![]() |
a11d214039 | ||
![]() |
cb1b4330ef | ||
![]() |
57cee93647 | ||
![]() |
19215db243 | ||
![]() |
3d9a68c1e3 | ||
![]() |
e35335d59c | ||
![]() |
fbbf78dcf8 | ||
![]() |
e757c14148 | ||
![]() |
4737b32a60 | ||
![]() |
2086f50d05 | ||
![]() |
e2979f632d | ||
![]() |
34b24a5b60 | ||
![]() |
e95e99018a | ||
![]() |
e6819e7f12 | ||
![]() |
8f64b45e79 | ||
![]() |
9eba243092 | ||
![]() |
06dbd048af | ||
![]() |
2e10c7ba03 | ||
![]() |
fa7e7fccdc | ||
![]() |
ab8e7935b0 | ||
![]() |
7c81b1ad15 | ||
![]() |
df66d127c2 | ||
![]() |
c72a315872 | ||
![]() |
83b7d7ff67 | ||
![]() |
c5056a8167 | ||
![]() |
c697501f8f | ||
![]() |
06b6f8794f | ||
![]() |
474bbdfdbd | ||
![]() |
69b845c34f | ||
![]() |
99a5262730 | ||
![]() |
97aaf5a067 |
102
.gitlab-ci.yml
@ -1,26 +1,36 @@
|
|||||||
image: registry.gitlab.com/fdroid/ci-images-client:latest
|
|
||||||
|
|
||||||
cache:
|
|
||||||
paths:
|
|
||||||
- .gradle/wrapper
|
|
||||||
- .gradle/caches
|
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- test
|
- test
|
||||||
- deploy
|
- deploy
|
||||||
|
|
||||||
before_script:
|
.base:
|
||||||
- export GRADLE_USER_HOME=$PWD/.gradle
|
image: registry.gitlab.com/fdroid/ci-images-client:latest
|
||||||
- export ANDROID_COMPILE_SDK=`sed -n 's,.*compileSdkVersion\s*\([0-9][0-9]*\).*,\1,p' app/build.gradle`
|
before_script:
|
||||||
- alias sdkmanager="sdkmanager --no_https"
|
- export GRADLE_USER_HOME=$PWD/.gradle
|
||||||
- echo y | sdkmanager "platforms;android-${ANDROID_COMPILE_SDK}" > /dev/null
|
- export ANDROID_COMPILE_SDK=`sed -n 's,.*compileSdkVersion\s*\([0-9][0-9]*\).*,\1,p' app/build.gradle`
|
||||||
|
- alias sdkmanager="sdkmanager --no_https"
|
||||||
|
- echo y | sdkmanager "platforms;android-${ANDROID_COMPILE_SDK}" > /dev/null
|
||||||
|
# limit RAM usage for all gradle runs
|
||||||
|
- export maxmem=$(expr $(sed -n 's,^MemAvailable:[^0-9]*\([0-9][0-9]*\)[^0-9]*$,\1,p' /proc/meminfo) / 1024 / 2 / 1024 \* 1024)
|
||||||
|
- printf "\norg.gradle.jvmargs=-Xmx${maxmem}m -XX:MaxPermSize=${maxmem}m\norg.gradle.daemon=false\norg.gradle.parallel=false\n" >> gradle.properties
|
||||||
|
after_script:
|
||||||
|
# this file changes every time but should not be cached
|
||||||
|
- rm -f $GRADLE_USER_HOME/caches/modules-2/modules-2.lock
|
||||||
|
- rm -fr $GRADLE_USER_HOME/caches/*/plugin-resolution/
|
||||||
|
cache:
|
||||||
|
paths:
|
||||||
|
- .gradle/wrapper
|
||||||
|
- .gradle/caches
|
||||||
|
|
||||||
.test-template: &test-template
|
.test-template: &test-template
|
||||||
|
extends: .base
|
||||||
stage: test
|
stage: test
|
||||||
artifacts:
|
artifacts:
|
||||||
name: "${CI_PROJECT_PATH}_${CI_JOB_STAGE}_${CI_COMMIT_REF_NAME}_${CI_COMMIT_SHA}"
|
name: "${CI_PROJECT_PATH}_${CI_JOB_STAGE}_${CI_COMMIT_REF_NAME}_${CI_COMMIT_SHA}"
|
||||||
paths:
|
paths:
|
||||||
|
- kernel.log
|
||||||
- logcat.txt
|
- logcat.txt
|
||||||
|
- app/core*
|
||||||
|
- app/*.log
|
||||||
- app/build/reports
|
- app/build/reports
|
||||||
- app/build/outputs/*ml
|
- app/build/outputs/*ml
|
||||||
- app/build/outputs/apk
|
- app/build/outputs/apk
|
||||||
@ -35,29 +45,40 @@ test_lint_pmd_checkstyle:
|
|||||||
<<: *test-template
|
<<: *test-template
|
||||||
script:
|
script:
|
||||||
- export EXITVALUE=0
|
- export EXITVALUE=0
|
||||||
|
- function set_error() { export EXITVALUE=1; printf "\x1b[31mERROR `history|tail -2|head -1|cut -b 6-500`\x1b[0m\n"; }
|
||||||
- ./gradlew assemble
|
- ./gradlew assemble
|
||||||
# always report on lint errors to the build log
|
# always report on lint errors to the build log
|
||||||
- sed -i -e 's,textReport .*,textReport true,' app/build.gradle
|
- sed -i -e 's,textReport .*,textReport true,' app/build.gradle
|
||||||
- ./gradlew testFullDebugUnitTest
|
- ./gradlew testFullDebugUnitTest || set_error
|
||||||
- ./gradlew lint
|
- ./gradlew lint || set_error
|
||||||
- ./gradlew pmd || (export EXITVALUE=1; echo ERROR !!)
|
- ./gradlew pmd || set_error
|
||||||
- ./gradlew checkstyle || (export EXITVALUE=1; echo ERROR !!)
|
- ./gradlew checkstyle || set_error
|
||||||
- ./tools/check-format-strings.py || (export EXITVALUE=1; echo ERROR !!)
|
- ./tools/check-format-strings.py || set_error
|
||||||
- ./tools/check-fastlane-whitespace.py || (export EXITVALUE=1; echo ERROR !!)
|
- ./tools/check-fastlane-whitespace.py || set_error
|
||||||
- ./tools/remove-unused-and-blank-translations.py || (export EXITVALUE=1; echo ERROR !!)
|
- ./tools/remove-unused-and-blank-translations.py || set_error
|
||||||
- echo "These are unused or blank translations that should be removed:"
|
- echo "These are unused or blank translations that should be removed:"
|
||||||
- git --no-pager diff --ignore-all-space --name-only --exit-code app/src/*/res/values*/strings.xml || (export EXITVALUE=1; echo ERROR !!)
|
- git --no-pager diff --ignore-all-space --name-only --exit-code app/src/*/res/values*/strings.xml || set_error
|
||||||
- exit $EXITVALUE
|
- exit $EXITVALUE
|
||||||
|
|
||||||
errorprone:
|
errorprone:
|
||||||
|
extends: .base
|
||||||
stage: test
|
stage: test
|
||||||
script:
|
script:
|
||||||
|
- apt-get update
|
||||||
|
- apt-get install -t stretch-backports openjdk-11-jdk-headless
|
||||||
|
- update-java-alternatives --set java-1.11.0-openjdk-amd64
|
||||||
|
- export JAVA_HOME=/usr/lib/jvm/java-1.11.0-openjdk-amd64
|
||||||
- cat config/errorprone.gradle >> app/build.gradle
|
- cat config/errorprone.gradle >> app/build.gradle
|
||||||
- ./gradlew -Dorg.gradle.dependency.verification=lenient assembleDebug
|
- ./gradlew -Dorg.gradle.dependency.verification=lenient assembleDebug
|
||||||
|
|
||||||
|
# Run the tests in the emulator. Each step is broken out to run on
|
||||||
|
# its own since the CI runner can have limited RAM, and the emulator
|
||||||
|
# can take a while to start.
|
||||||
|
#
|
||||||
# once these prove stable, the task should be switched to
|
# once these prove stable, the task should be switched to
|
||||||
# connectedCheck to test all the build flavors
|
# connectedCheck to test all the build flavors
|
||||||
.connected-template: &connected-template
|
.connected-template: &connected-template
|
||||||
|
extends: .base
|
||||||
script:
|
script:
|
||||||
- ./gradlew assembleFullDebug
|
- ./gradlew assembleFullDebug
|
||||||
- export AVD_SDK=`echo $CI_JOB_NAME | awk '{print $2}'`
|
- export AVD_SDK=`echo $CI_JOB_NAME | awk '{print $2}'`
|
||||||
@ -74,16 +95,14 @@ errorprone:
|
|||||||
- wait-for-emulator
|
- wait-for-emulator
|
||||||
- adb devices
|
- adb devices
|
||||||
- adb shell input keyevent 82 &
|
- adb shell input keyevent 82 &
|
||||||
|
- ./gradlew installFullDebug
|
||||||
|
- adb shell am start -n org.fdroid.fdroid.debug/org.fdroid.fdroid.views.main.MainActivity
|
||||||
- if [ $AVD_SDK -lt 25 ] || ! emulator -accel-check; then
|
- if [ $AVD_SDK -lt 25 ] || ! emulator -accel-check; then
|
||||||
export FLAG=-Pandroid.testInstrumentationRunnerArguments.notAnnotation=android.support.test.filters.LargeTest;
|
export FLAG=-Pandroid.testInstrumentationRunnerArguments.notAnnotation=androidx.test.filters.LargeTest;
|
||||||
fi
|
fi
|
||||||
- ./gradlew connectedFullDebugAndroidTest $FLAG
|
- ./gradlew connectedFullDebugAndroidTest $FLAG
|
||||||
|| ./gradlew connectedFullDebugAndroidTest $FLAG
|
|
||||||
|| ./gradlew connectedFullDebugAndroidTest $FLAG
|
|
||||||
|| (adb -e logcat -d > logcat.txt; exit 1)
|
|
||||||
|
|
||||||
connected 22 default armeabi-v7a:
|
no-accel 22 default x86:
|
||||||
retry: 1
|
|
||||||
<<: *test-template
|
<<: *test-template
|
||||||
<<: *connected-template
|
<<: *connected-template
|
||||||
|
|
||||||
@ -91,35 +110,17 @@ connected 22 default armeabi-v7a:
|
|||||||
tags:
|
tags:
|
||||||
- fdroid
|
- fdroid
|
||||||
- kvm
|
- kvm
|
||||||
allow_failure: true
|
|
||||||
only:
|
only:
|
||||||
- branches@eighthave/fdroidclient
|
variables:
|
||||||
|
- $RUN_KVM_JOBS
|
||||||
<<: *test-template
|
<<: *test-template
|
||||||
<<: *connected-template
|
<<: *connected-template
|
||||||
|
|
||||||
connected 23 default x86:
|
kvm 29 microg x86_64:
|
||||||
<<: *kvm-template
|
<<: *kvm-template
|
||||||
|
|
||||||
connected 25 default x86:
|
|
||||||
<<: *kvm-template
|
|
||||||
|
|
||||||
connected 26 google_apis x86:
|
|
||||||
<<: *kvm-template
|
|
||||||
only:
|
|
||||||
- branches@fdroid/fdroidclient
|
|
||||||
- branches@eighthave/fdroidclient
|
|
||||||
|
|
||||||
connected 27 google_apis_playstore x86:
|
|
||||||
<<: *kvm-template
|
|
||||||
|
|
||||||
connected 28 default x86_64:
|
|
||||||
<<: *kvm-template
|
|
||||||
|
|
||||||
connected 29 default x86_64:
|
|
||||||
<<: *kvm-template
|
|
||||||
|
|
||||||
|
|
||||||
deploy_nightly:
|
deploy_nightly:
|
||||||
|
extends: .base
|
||||||
stage: deploy
|
stage: deploy
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
@ -139,8 +140,3 @@ deploy_nightly:
|
|||||||
# build the APKs!
|
# build the APKs!
|
||||||
- ./gradlew assembleDebug
|
- ./gradlew assembleDebug
|
||||||
- fdroid nightly -v
|
- fdroid nightly -v
|
||||||
|
|
||||||
after_script:
|
|
||||||
# this file changes every time but should not be cached
|
|
||||||
- rm -f $GRADLE_USER_HOME/caches/modules-2/modules-2.lock
|
|
||||||
- rm -fr $GRADLE_USER_HOME/caches/*/plugin-resolution/
|
|
||||||
|
63
CHANGELOG.md
@ -1,3 +1,66 @@
|
|||||||
|
### 1.13-alpha1 (2021-06-02)
|
||||||
|
|
||||||
|
* Stop repeated updates of Trichrome Library
|
||||||
|
|
||||||
|
* More changes to follow Material Design (@proletarius101)
|
||||||
|
|
||||||
|
* Improve OpenCollective badge (@ConnyDuck)
|
||||||
|
|
||||||
|
### 1.13-alpha0 (2021-04-22)
|
||||||
|
|
||||||
|
* Theme support tied to built-in Android themes (@proletarius101)
|
||||||
|
|
||||||
|
* New top banner notifications: "No Internet" and "No Data or WiFi enabled"
|
||||||
|
|
||||||
|
* Improved handling of USB-OTG and SD Card repos and mirrors
|
||||||
|
|
||||||
|
### 1.12.1 (2021-04-12)
|
||||||
|
|
||||||
|
* Fix trove4j verification error
|
||||||
|
|
||||||
|
### 1.12 (2021-04-06)
|
||||||
|
|
||||||
|
* Sync translations
|
||||||
|
|
||||||
|
### 1.12-alpha3 (2021-03-10)
|
||||||
|
|
||||||
|
* Opt-in F-Droid Metrics
|
||||||
|
|
||||||
|
### 1.12-alpha2 (2021-03-03)
|
||||||
|
|
||||||
|
* Overhaul clean up of cached files
|
||||||
|
|
||||||
|
* Support updating "shared library packages" like Trichrome (@uldiniad)
|
||||||
|
|
||||||
|
### 1.12-alpha1 (2021-02-25)
|
||||||
|
|
||||||
|
* Add extra sanitation to search terms to prevent vulnerabilities.
|
||||||
|
|
||||||
|
* Fix Nearby Swap's close button (@proletarius101)
|
||||||
|
|
||||||
|
* Bump to compileSdkVersion 29 to support Java8
|
||||||
|
|
||||||
|
* Set up WorkManager on demand to avoid slowing down starts
|
||||||
|
|
||||||
|
* Prefer system keys when APKs are signed by them (@glennmen)
|
||||||
|
|
||||||
|
### 1.12-alpha0 (2021-02-08)
|
||||||
|
|
||||||
|
* App description localization now fully respects lists of languages in Android
|
||||||
|
Language Settings
|
||||||
|
|
||||||
|
* Latest Tab lists results based on the Language Settings
|
||||||
|
|
||||||
|
* Latest Tab now shows results ordered newest first (@TheLastProject @IzzySoft)
|
||||||
|
|
||||||
|
* Theme support modernized and tied to the built-in Android themes (@proletarius101)
|
||||||
|
|
||||||
|
* Search results greatly improved (@Tvax @gcbrown76)
|
||||||
|
|
||||||
|
* Let Android efficiently schedule background cache cleanup operations (@Isira-Seneviratne)
|
||||||
|
|
||||||
|
* Overhaul repo URL parsing for reliable repo adding (@projectgus)
|
||||||
|
|
||||||
### 1.11 (2020-12-29)
|
### 1.11 (2020-12-29)
|
||||||
|
|
||||||
* Improved linkifying of URLs in app descriptions
|
* Improved linkifying of URLs in app descriptions
|
||||||
|
@ -26,14 +26,16 @@ track of modifications and fuzzy translations. Applying translations manually
|
|||||||
skips all of the fixes and checks, and overrides the fuzzy state of strings.
|
skips all of the fixes and checks, and overrides the fuzzy state of strings.
|
||||||
|
|
||||||
Note that you cannot change the English strings on Weblate. If you have any
|
Note that you cannot change the English strings on Weblate. If you have any
|
||||||
suggestions on how to improve them, open a merge request like you would if you
|
suggestions on how to improve them, open an issue or merge request like you
|
||||||
were making code changes. This way the changes can be reviewed before the
|
would if you were making code changes. This way the changes can be reviewed
|
||||||
source strings on Weblate are changed.
|
before the source strings on Weblate are changed.
|
||||||
|
|
||||||
|
|
||||||
## Code Style
|
## Code Style
|
||||||
|
|
||||||
We follow the [Android Java style](https://source.android.com/source/code-style.html).
|
We follow the default Android Studio code formatter (e.g. `Ctrl-Alt-L`). This
|
||||||
Some key points:
|
should be more or less the same as [Android Java
|
||||||
|
style](https://source.android.com/source/code-style.html). Some key points:
|
||||||
|
|
||||||
* Four space indentation
|
* Four space indentation
|
||||||
* UTF-8 source files
|
* UTF-8 source files
|
||||||
@ -45,76 +47,35 @@ Some key points:
|
|||||||
* Braces are always used after if, for and while
|
* Braces are always used after if, for and while
|
||||||
|
|
||||||
The current code base doesn't follow it entirely, but new code should follow
|
The current code base doesn't follow it entirely, but new code should follow
|
||||||
it. We enforce some of these, but not all, via checkstyle.
|
it. We enforce some of these, but not all, via `./gradlew checkstyle`.
|
||||||
|
|
||||||
## Debugging
|
|
||||||
|
|
||||||
To get all the logcat messages by F-Droid, you can run:
|
|
||||||
|
|
||||||
adb logcat | grep `adb shell ps | grep org.fdroid.fdroid | cut -c10-15`
|
|
||||||
|
|
||||||
## Building tips
|
|
||||||
|
|
||||||
* Use gradle with `--daemon` if you are going to build F-Droid multiple times.
|
|
||||||
* If you get a message like `Could not find com.android.support:support-...`,
|
|
||||||
make sure that you have the latest Android support maven repository.
|
|
||||||
* When building as part of AOSP with `Android.mk`, make sure you have a
|
|
||||||
recent version of Gradle installed as `gradlew` will not be used.
|
|
||||||
|
|
||||||
## Running the test suite
|
## Running the test suite
|
||||||
|
|
||||||
|
Before pushing commits to a merge request, make sure this passes:
|
||||||
|
|
||||||
|
./gradlew checkstyle pmd lint
|
||||||
|
|
||||||
In order to run the F-Droid test suite, you will need to have either a real device
|
In order to run the F-Droid test suite, you will need to have either a real device
|
||||||
connected via `adb`, or an emulator running. Then, execute the following from the
|
connected via `adb`, or an emulator running. Then, execute the following from the
|
||||||
command line:
|
command line:
|
||||||
|
|
||||||
./gradlew check
|
./gradlew check
|
||||||
|
|
||||||
Note that the CI already runs the tests on an emulator, so you don't
|
Many important tests require a device or emulator, but do not work in GitLab CI.
|
||||||
necessarily have to do this yourself if you open a merge request as the tests
|
That mean they need to be run locally, and that is usually easiest in Android
|
||||||
will get run.
|
Studio rather than the command line.
|
||||||
|
|
||||||
### Running tests in Android Studio
|
For a quick way to run a specific JUnit/Robolectric test:
|
||||||
|
|
||||||
Later versions of Android Studio require tests to be run with a "Working directory"
|
./gradlew testFullDebugUnitTest --tests *LocaleSelectionTest*
|
||||||
of `$MODULE_DIR$`.
|
|
||||||
[To make this the default behaviour](https://code.google.com/p/android/issues/detail?id=158015#c11),
|
|
||||||
close any projects to get the Welcome dialog. Then choose _Configure > Project Defaults >
|
|
||||||
Run Configurations > Defaults > Android JUnit_, and change "Working directory"
|
|
||||||
to `$MODULE_DIR$`. If you already have a project setup in Android Studio, you
|
|
||||||
may also need to change the default in _Run > Edit Configurations... > Defaults >
|
|
||||||
Android JUnit_.
|
|
||||||
|
|
||||||
## Versioning
|
For a quick way to run a specific emulator test:
|
||||||
|
|
||||||
Each stable version follows the `X.Y` pattern. Hotfix releases - i.e. when a
|
./gradlew connectedFullDebugAndroidTest \
|
||||||
stable has an important bug that needs immediate fixing - will follow the
|
-Pandroid.testInstrumentationRunnerArguments.class=org.fdroid.fdroid.MainActivityExpressoTest
|
||||||
`X.Y.Z` pattern.
|
|
||||||
|
|
||||||
Before each stable release, a number of alpha releases will be released. They
|
|
||||||
will follow the pattern `X.Y-alphaN`, where `N` is the current alpha number.
|
|
||||||
These will usually include changes and new features that have not been tested
|
|
||||||
enough for a stable release, so use at your own risk. Testers and reporters
|
|
||||||
are very welcome.
|
|
||||||
|
|
||||||
The version codes use a number of digits per each of these keys: `XXXYYYZNN`.
|
## Making releases
|
||||||
So for example, 1.3.1 would be `1003150` and 0.95-alpha13 would be `95013`
|
|
||||||
(leading zeros are omitted).
|
|
||||||
|
|
||||||
Note that we use a trailing `50` for actual stable releases, so alphas are
|
See https://gitlab.com/fdroid/wiki/-/wikis/Internal/Release-Process#fdroidclient
|
||||||
limited to `-alpha49`.
|
|
||||||
|
|
||||||
This is an example of a release process for **0.95**:
|
|
||||||
|
|
||||||
* We are currently at stable **0.94**
|
|
||||||
* **0.95-alpha1** is released
|
|
||||||
* **0.95-alpha2** is released
|
|
||||||
* **0.95-alpha3** is released
|
|
||||||
* `stable-v0.95` is branched and frozen
|
|
||||||
* **0.95** is released
|
|
||||||
* A bug is reported on the stable release and fixed
|
|
||||||
* **0.95.1** is released with only that fix
|
|
||||||
|
|
||||||
As soon as a stable is tagged, master will move on to `-alpha0` on the next
|
|
||||||
version. This is a temporary measure - until `-alpha1` is released - so that
|
|
||||||
moving from stable to master doesn't require a downgrade. `-alpha0` versions
|
|
||||||
will not be tagged nor released.
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# F-Droid Client
|
# F-Droid Client
|
||||||
|
|
||||||
[](https://gitlab.com/fdroid/fdroidclient/builds)
|
[](https://gitlab.com/fdroid/fdroidclient/-/jobs)
|
||||||
[](https://hosted.weblate.org/engage/f-droid/)
|
[](https://hosted.weblate.org/engage/f-droid/)
|
||||||
|
|
||||||
Client for [F-Droid](https://f-droid.org), the Free Software repository system
|
Client for [F-Droid](https://f-droid.org), the Free Software repository system
|
||||||
|
@ -21,16 +21,16 @@ def basicApplicationId = "org.fdroid.basic"
|
|||||||
def privilegedExtensionApplicationId = '"org.fdroid.fdroid.privileged"'
|
def privilegedExtensionApplicationId = '"org.fdroid.fdroid.privileged"'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 28
|
compileSdkVersion 30
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
versionCode 1011050
|
versionCode 1013001
|
||||||
versionName getVersionName()
|
versionName getVersionName()
|
||||||
|
|
||||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||||
minSdkVersion 14
|
minSdkVersion 24
|
||||||
//noinspection ExpiredTargetSdkVersion
|
//noinspection ExpiredTargetSdkVersion
|
||||||
targetSdkVersion 25
|
targetSdkVersion 28
|
||||||
/*
|
/*
|
||||||
The Android Testing Support Library collects analytics to continuously improve the testing
|
The Android Testing Support Library collects analytics to continuously improve the testing
|
||||||
experience. More specifically, it uploads a hash of the package name of the application
|
experience. More specifically, it uploads a hash of the package name of the application
|
||||||
@ -38,6 +38,7 @@ android {
|
|||||||
passing the following argument to the test runner: disableAnalytics "true".
|
passing the following argument to the test runner: disableAnalytics "true".
|
||||||
*/
|
*/
|
||||||
testInstrumentationRunnerArguments disableAnalytics: 'true'
|
testInstrumentationRunnerArguments disableAnalytics: 'true'
|
||||||
|
vectorDrawables.useSupportLibrary = true
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
@ -75,6 +76,8 @@ android {
|
|||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
compileOptions.encoding = "UTF-8"
|
compileOptions.encoding = "UTF-8"
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
}
|
}
|
||||||
|
|
||||||
aaptOptions {
|
aaptOptions {
|
||||||
@ -99,6 +102,10 @@ android {
|
|||||||
events "skipped", "failed", "standardOut", "standardError"
|
events "skipped", "failed", "standardOut", "standardError"
|
||||||
showStandardStreams = true
|
showStandardStreams = true
|
||||||
}
|
}
|
||||||
|
systemProperty 'robolectric.dependency.repo.url', 'https://repo1.maven.org/maven2'
|
||||||
|
|
||||||
|
// hack to avoid memory leak crashes
|
||||||
|
forkEvery = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -135,28 +142,29 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
implementation 'androidx.appcompat:appcompat:1.3.0'
|
||||||
implementation 'androidx.preference:preference:1.1.1'
|
implementation 'androidx.preference:preference:1.1.1'
|
||||||
implementation 'androidx.gridlayout:gridlayout:1.0.0'
|
implementation 'androidx.gridlayout:gridlayout:1.0.0'
|
||||||
implementation 'androidx.annotation:annotation:1.1.0'
|
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
||||||
implementation 'androidx.cardview:cardview:1.0.0'
|
implementation 'androidx.cardview:cardview:1.0.0'
|
||||||
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
|
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||||
implementation 'androidx.palette:palette:1.0.0'
|
implementation 'androidx.palette:palette:1.0.0'
|
||||||
|
implementation 'androidx.work:work-runtime:2.4.0'
|
||||||
|
|
||||||
implementation 'com.google.android.material:material:1.1.0'
|
implementation 'com.google.android.material:material:1.3.0'
|
||||||
|
|
||||||
implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
|
implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
|
||||||
implementation 'com.google.zxing:core:3.3.3'
|
implementation 'com.google.zxing:core:3.3.3'
|
||||||
implementation 'info.guardianproject.netcipher:netcipher:2.0.0-beta1'
|
implementation 'info.guardianproject.netcipher:netcipher:2.2.0-alpha'
|
||||||
implementation 'info.guardianproject.panic:panic:1.0'
|
implementation 'info.guardianproject.panic:panic:1.0'
|
||||||
implementation 'commons-io:commons-io:2.6'
|
implementation 'commons-io:commons-io:2.6'
|
||||||
implementation 'commons-net:commons-net:3.6'
|
implementation 'commons-net:commons-net:3.6'
|
||||||
implementation 'ch.acra:acra:4.9.1'
|
implementation 'ch.acra:acra:4.9.1'
|
||||||
implementation 'io.reactivex:rxjava:1.1.0'
|
|
||||||
implementation 'com.hannesdorfmann:adapterdelegates3:3.0.1'
|
implementation 'com.hannesdorfmann:adapterdelegates3:3.0.1'
|
||||||
implementation 'com.ashokvarma.android:bottom-navigation-bar:2.0.5'
|
|
||||||
|
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
|
||||||
|
implementation 'io.reactivex.rxjava3:rxjava:3.0.9'
|
||||||
|
|
||||||
implementation 'com.fasterxml.jackson.core:jackson-core:2.11.1'
|
implementation 'com.fasterxml.jackson.core:jackson-core:2.11.1'
|
||||||
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.11.1'
|
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.11.1'
|
||||||
@ -168,20 +176,22 @@ dependencies {
|
|||||||
fullImplementation 'org.jmdns:jmdns:3.5.5'
|
fullImplementation 'org.jmdns:jmdns:3.5.5'
|
||||||
fullImplementation 'org.nanohttpd:nanohttpd:2.3.1'
|
fullImplementation 'org.nanohttpd:nanohttpd:2.3.1'
|
||||||
|
|
||||||
testImplementation 'androidx.test:core:1.2.0'
|
testImplementation 'androidx.test:core:1.3.0'
|
||||||
testImplementation 'junit:junit:4.13'
|
testImplementation 'junit:junit:4.13.1'
|
||||||
testImplementation 'org.robolectric:robolectric:4.3'
|
testImplementation 'org.robolectric:robolectric:4.3'
|
||||||
testImplementation 'org.mockito:mockito-core:3.3.3'
|
testImplementation 'org.mockito:mockito-core:3.3.3'
|
||||||
testImplementation 'org.hamcrest:hamcrest:2.2'
|
testImplementation 'org.hamcrest:hamcrest:2.2'
|
||||||
testImplementation 'org.bouncycastle:bcprov-jdk15on:1.65'
|
testImplementation 'org.bouncycastle:bcprov-jdk15on:1.65'
|
||||||
|
|
||||||
androidTestImplementation 'androidx.test:core:1.2.0'
|
androidTestImplementation 'androidx.arch.core:core-testing:2.1.0'
|
||||||
androidTestImplementation 'androidx.test:runner:1.2.0'
|
androidTestImplementation 'androidx.test:core:1.3.0'
|
||||||
androidTestImplementation 'androidx.test:rules:1.2.0'
|
androidTestImplementation 'androidx.test:runner:1.3.0'
|
||||||
androidTestImplementation 'androidx.test:monitor:1.2.0'
|
androidTestImplementation 'androidx.test:rules:1.3.0'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
androidTestImplementation 'androidx.test:monitor:1.3.0'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||||
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||||
androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
|
androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
|
||||||
|
androidTestImplementation 'androidx.work:work-testing:2.4.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
checkstyle {
|
checkstyle {
|
||||||
|
14
app/proguard-rules.pro
vendored
@ -4,13 +4,11 @@
|
|||||||
-keep class org.fdroid.fdroid.** {*;}
|
-keep class org.fdroid.fdroid.** {*;}
|
||||||
-dontskipnonpubliclibraryclassmembers
|
-dontskipnonpubliclibraryclassmembers
|
||||||
-dontwarn android.test.**
|
-dontwarn android.test.**
|
||||||
-dontwarn com.android.support.test.**
|
|
||||||
|
|
||||||
-dontwarn javax.naming.**
|
-dontwarn javax.naming.**
|
||||||
-dontwarn org.slf4j.**
|
-dontwarn org.slf4j.**
|
||||||
-dontnote org.apache.http.**
|
-dontnote org.apache.http.**
|
||||||
-dontnote android.net.http.**
|
-dontnote android.net.http.**
|
||||||
-dontnote android.support.**
|
|
||||||
-dontnote **ILicensingService
|
-dontnote **ILicensingService
|
||||||
|
|
||||||
# Needed for espresso https://stackoverflow.com/a/21706087
|
# Needed for espresso https://stackoverflow.com/a/21706087
|
||||||
@ -33,13 +31,6 @@
|
|||||||
public *;
|
public *;
|
||||||
}
|
}
|
||||||
|
|
||||||
# The rxjava library depends on sun.misc.Unsafe, which is unavailable on Android
|
|
||||||
# The rxjava team is aware of this, and mention in the docs that they only use
|
|
||||||
# the unsafe functionality if the platform supports it.
|
|
||||||
# - https://github.com/ReactiveX/RxJava/issues/1415#issuecomment-48390883
|
|
||||||
# - https://github.com/ReactiveX/RxJava/blob/1.x/src/main/java/rx/internal/util/unsafe/UnsafeAccess.java#L23
|
|
||||||
-dontwarn rx.internal.util.**
|
|
||||||
|
|
||||||
-keepattributes *Annotation*,EnclosingMethod,Signature
|
-keepattributes *Annotation*,EnclosingMethod,Signature
|
||||||
-keepnames class com.fasterxml.jackson.** { *; }
|
-keepnames class com.fasterxml.jackson.** { *; }
|
||||||
-dontwarn com.fasterxml.jackson.databind.ext.**
|
-dontwarn com.fasterxml.jackson.databind.ext.**
|
||||||
@ -48,4 +39,9 @@
|
|||||||
public static final org.codehaus.jackson.annotate.JsonAutoDetect$Visibility *; }
|
public static final org.codehaus.jackson.annotate.JsonAutoDetect$Visibility *; }
|
||||||
-keep public class your.class.** {
|
-keep public class your.class.** {
|
||||||
*;
|
*;
|
||||||
|
}
|
||||||
|
|
||||||
|
# This is necessary so that RemoteWorkManager can be initialized (also marked with @Keep)
|
||||||
|
-keep class androidx.work.multiprocess.RemoteWorkManagerClient {
|
||||||
|
public <init>(...);
|
||||||
}
|
}
|
@ -1,18 +1,24 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
|
<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="org.fdroid.fdroid.tests"
|
package="org.fdroid.fdroid.tests"
|
||||||
android:versionCode="1"
|
android:versionCode="1"
|
||||||
android:versionName="1.0">
|
android:versionName="1.0">
|
||||||
|
|
||||||
<uses-sdk tools:overrideLibrary="android_libs.ub_uiautomator" />
|
<uses-sdk tools:overrideLibrary="android_libs.ub_uiautomator" />
|
||||||
|
|
||||||
<!-- We add an application tag here just so that we can indicate that
|
<!-- We add an application tag here just so that we can indicate that
|
||||||
this package needs to link against the android.test library,
|
this package needs to link against the android.test library,
|
||||||
which is needed when building test cases. -->
|
which is needed when building test cases. -->
|
||||||
<application>
|
<application>
|
||||||
<uses-library android:name="android.test.runner"
|
<uses-library
|
||||||
|
android:name="android.test.runner"
|
||||||
android:required="false" />
|
android:required="false" />
|
||||||
</application>
|
</application>
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
package org.fdroid.fdroid;
|
|
||||||
|
|
||||||
import android.app.Instrumentation;
|
|
||||||
import androidx.test.platform.app.InstrumentationRegistry;
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
|
||||||
import org.fdroid.fdroid.compat.FileCompatTest;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
|
||||||
public class CleanCacheServiceTest {
|
|
||||||
|
|
||||||
public static final String TAG = "CleanCacheServiceTest";
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testClearOldFiles() throws IOException, InterruptedException {
|
|
||||||
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
|
|
||||||
File tempDir = FileCompatTest.getWriteableDir(instrumentation);
|
|
||||||
assertTrue(tempDir.isDirectory());
|
|
||||||
assertTrue(tempDir.canWrite());
|
|
||||||
|
|
||||||
File dir = new File(tempDir, "F-Droid-test.clearOldFiles");
|
|
||||||
FileUtils.deleteQuietly(dir);
|
|
||||||
assertTrue(dir.mkdirs());
|
|
||||||
assertTrue(dir.isDirectory());
|
|
||||||
|
|
||||||
File first = new File(dir, "first");
|
|
||||||
first.deleteOnExit();
|
|
||||||
|
|
||||||
File second = new File(dir, "second");
|
|
||||||
second.deleteOnExit();
|
|
||||||
|
|
||||||
assertFalse(first.exists());
|
|
||||||
assertFalse(second.exists());
|
|
||||||
|
|
||||||
assertTrue(first.createNewFile());
|
|
||||||
assertTrue(first.exists());
|
|
||||||
|
|
||||||
Thread.sleep(7000);
|
|
||||||
assertTrue(second.createNewFile());
|
|
||||||
assertTrue(second.exists());
|
|
||||||
|
|
||||||
CleanCacheService.clearOldFiles(dir, 3000); // check all in dir
|
|
||||||
assertFalse(first.exists());
|
|
||||||
assertTrue(second.exists());
|
|
||||||
|
|
||||||
Thread.sleep(7000);
|
|
||||||
CleanCacheService.clearOldFiles(second, 3000); // check just second file
|
|
||||||
assertFalse(first.exists());
|
|
||||||
assertFalse(second.exists());
|
|
||||||
|
|
||||||
// make sure it doesn't freak out on a non-existent file
|
|
||||||
File nonexistent = new File(tempDir, "nonexistent");
|
|
||||||
CleanCacheService.clearOldFiles(nonexistent, 1);
|
|
||||||
CleanCacheService.clearOldFiles(null, 1);
|
|
||||||
}
|
|
||||||
}
|
|
@ -21,7 +21,7 @@ import androidx.test.uiautomator.UiObjectNotFoundException;
|
|||||||
import androidx.test.uiautomator.UiSelector;
|
import androidx.test.uiautomator.UiSelector;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import org.fdroid.fdroid.views.BannerUpdatingRepos;
|
import org.fdroid.fdroid.views.StatusBanner;
|
||||||
import org.fdroid.fdroid.views.main.MainActivity;
|
import org.fdroid.fdroid.views.main.MainActivity;
|
||||||
import org.hamcrest.Matchers;
|
import org.hamcrest.Matchers;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
@ -177,6 +177,7 @@ public class MainActivityEspressoTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@LargeTest
|
@LargeTest
|
||||||
|
@Test
|
||||||
public void showSettings() {
|
public void showSettings() {
|
||||||
ViewInteraction settingsBottonNavButton = onView(
|
ViewInteraction settingsBottonNavButton = onView(
|
||||||
allOf(withText(R.string.menu_settings), isDisplayed()));
|
allOf(withText(R.string.menu_settings), isDisplayed()));
|
||||||
@ -211,6 +212,7 @@ public class MainActivityEspressoTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@LargeTest
|
@LargeTest
|
||||||
|
@Test
|
||||||
public void showUpdates() {
|
public void showUpdates() {
|
||||||
ViewInteraction updatesBottonNavButton = onView(allOf(withText(R.string.main_menu__updates), isDisplayed()));
|
ViewInteraction updatesBottonNavButton = onView(allOf(withText(R.string.main_menu__updates), isDisplayed()));
|
||||||
updatesBottonNavButton.perform(click());
|
updatesBottonNavButton.perform(click());
|
||||||
@ -218,6 +220,7 @@ public class MainActivityEspressoTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@LargeTest
|
@LargeTest
|
||||||
|
@Test
|
||||||
public void startSwap() {
|
public void startSwap() {
|
||||||
if (!BuildConfig.FLAVOR.startsWith("full")) {
|
if (!BuildConfig.FLAVOR.startsWith("full")) {
|
||||||
return;
|
return;
|
||||||
@ -233,6 +236,7 @@ public class MainActivityEspressoTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@LargeTest
|
@LargeTest
|
||||||
|
@Test
|
||||||
public void showCategories() {
|
public void showCategories() {
|
||||||
if (!BuildConfig.FLAVOR.startsWith("full")) {
|
if (!BuildConfig.FLAVOR.startsWith("full")) {
|
||||||
return;
|
return;
|
||||||
@ -258,11 +262,12 @@ public class MainActivityEspressoTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@LargeTest
|
@LargeTest
|
||||||
|
@Test
|
||||||
public void showLatest() {
|
public void showLatest() {
|
||||||
if (!BuildConfig.FLAVOR.startsWith("full")) {
|
if (!BuildConfig.FLAVOR.startsWith("full")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
onView(Matchers.<View>instanceOf(BannerUpdatingRepos.class)).check(matches(not(isDisplayed())));
|
onView(Matchers.<View>instanceOf(StatusBanner.class)).check(matches(not(isDisplayed())));
|
||||||
onView(allOf(withText(R.string.menu_settings), isDisplayed())).perform(click());
|
onView(allOf(withText(R.string.menu_settings), isDisplayed())).perform(click());
|
||||||
onView(allOf(withText(R.string.main_menu__latest_apps), isDisplayed())).perform(click());
|
onView(allOf(withText(R.string.main_menu__latest_apps), isDisplayed())).perform(click());
|
||||||
onView(allOf(withId(R.id.swipe_to_refresh), isDisplayed()))
|
onView(allOf(withId(R.id.swipe_to_refresh), isDisplayed()))
|
||||||
@ -280,6 +285,7 @@ public class MainActivityEspressoTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@LargeTest
|
@LargeTest
|
||||||
|
@Test
|
||||||
public void showSearch() {
|
public void showSearch() {
|
||||||
onView(allOf(withText(R.string.menu_settings), isDisplayed())).perform(click());
|
onView(allOf(withText(R.string.menu_settings), isDisplayed())).perform(click());
|
||||||
onView(withId(R.id.fab_search)).check(doesNotExist());
|
onView(withId(R.id.fab_search)).check(doesNotExist());
|
||||||
|
@ -0,0 +1,110 @@
|
|||||||
|
package org.fdroid.fdroid.work;
|
||||||
|
|
||||||
|
import android.app.Instrumentation;
|
||||||
|
import androidx.arch.core.executor.testing.InstantTaskExecutorRule;
|
||||||
|
import androidx.test.filters.LargeTest;
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
|
import androidx.work.OneTimeWorkRequest;
|
||||||
|
import androidx.work.WorkInfo;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.fdroid.fdroid.compat.FileCompatTest;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test cannot run on Robolectric unfortunately since it does not support
|
||||||
|
* getting the timestamps from the files completely.
|
||||||
|
* <p>
|
||||||
|
* This is marked with {@link LargeTest} because it always fails on the emulator
|
||||||
|
* tests on GitLab CI. That excludes it from the test run there.
|
||||||
|
*/
|
||||||
|
@LargeTest
|
||||||
|
public class CleanCacheWorkerTest {
|
||||||
|
public static final String TAG = "CleanCacheWorkerEmulatorTest";
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public InstantTaskExecutorRule instantTaskExecutorRule = new InstantTaskExecutorRule();
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public WorkManagerTestRule workManagerTestRule = new WorkManagerTestRule();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWorkRequest() throws ExecutionException, InterruptedException {
|
||||||
|
OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(CleanCacheWorker.class).build();
|
||||||
|
workManagerTestRule.workManager.enqueue(request).getResult();
|
||||||
|
ListenableFuture<WorkInfo> workInfo = workManagerTestRule.workManager.getWorkInfoById(request.getId());
|
||||||
|
assertEquals(WorkInfo.State.SUCCEEDED, workInfo.get().getState());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClearOldFiles() throws IOException, InterruptedException {
|
||||||
|
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
|
||||||
|
File tempDir = FileCompatTest.getWriteableDir(instrumentation);
|
||||||
|
assertTrue(tempDir.isDirectory());
|
||||||
|
assertTrue(tempDir.canWrite());
|
||||||
|
|
||||||
|
File dir = new File(tempDir, "F-Droid-test.clearOldFiles");
|
||||||
|
FileUtils.deleteQuietly(dir);
|
||||||
|
assertTrue(dir.mkdirs());
|
||||||
|
assertTrue(dir.isDirectory());
|
||||||
|
|
||||||
|
File first = new File(dir, "first");
|
||||||
|
first.deleteOnExit();
|
||||||
|
|
||||||
|
File second = new File(dir, "second");
|
||||||
|
second.deleteOnExit();
|
||||||
|
|
||||||
|
assertFalse(first.exists());
|
||||||
|
assertFalse(second.exists());
|
||||||
|
|
||||||
|
assertTrue(first.createNewFile());
|
||||||
|
assertTrue(first.exists());
|
||||||
|
|
||||||
|
Thread.sleep(7000);
|
||||||
|
assertTrue(second.createNewFile());
|
||||||
|
assertTrue(second.exists());
|
||||||
|
|
||||||
|
CleanCacheWorker.clearOldFiles(dir, 3000); // check all in dir
|
||||||
|
assertFalse(first.exists());
|
||||||
|
assertTrue(second.exists());
|
||||||
|
|
||||||
|
Thread.sleep(7000);
|
||||||
|
CleanCacheWorker.clearOldFiles(second, 3000); // check just second file
|
||||||
|
assertFalse(first.exists());
|
||||||
|
assertFalse(second.exists());
|
||||||
|
|
||||||
|
// make sure it doesn't freak out on a non-existent file
|
||||||
|
File nonexistent = new File(tempDir, "nonexistent");
|
||||||
|
CleanCacheWorker.clearOldFiles(nonexistent, 1);
|
||||||
|
CleanCacheWorker.clearOldFiles(null, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// TODO enable this once getImageCacheDir() can be mocked or provide a writable dir in the test
|
||||||
|
@Test
|
||||||
|
public void testDeleteOldIcons() throws IOException {
|
||||||
|
Context context = InstrumentationRegistry.getInstrumentation().getContext();
|
||||||
|
File imageCacheDir = Utils.getImageCacheDir(context);
|
||||||
|
imageCacheDir.mkdirs();
|
||||||
|
assertTrue(imageCacheDir.isDirectory());
|
||||||
|
File oldIcon = new File(imageCacheDir, "old.png");
|
||||||
|
assertTrue(oldIcon.createNewFile());
|
||||||
|
Assume.assumeTrue("test environment must be able to set LastModified time",
|
||||||
|
oldIcon.setLastModified(System.currentTimeMillis() - (DateUtils.DAY_IN_MILLIS * 370)));
|
||||||
|
File currentIcon = new File(imageCacheDir, "current.png");
|
||||||
|
assertTrue(currentIcon.createNewFile());
|
||||||
|
CleanCacheWorker.deleteOldIcons(context);
|
||||||
|
assertTrue(currentIcon.exists());
|
||||||
|
assertFalse(oldIcon.exists());
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Hans-Christoph Steiner <hans@eds.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.fdroid.fdroid.work;
|
||||||
|
|
||||||
|
import androidx.arch.core.executor.testing.InstantTaskExecutorRule;
|
||||||
|
import androidx.test.filters.LargeTest;
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
|
import androidx.work.OneTimeWorkRequest;
|
||||||
|
import androidx.work.WorkInfo;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This actually runs {@link FDroidMetricsWorker} on a device/emulator and
|
||||||
|
* submits a report to https://metrics.cleaninsights.org
|
||||||
|
* <p>
|
||||||
|
* This is marked with {@link LargeTest} to exclude it from running on GitLab CI
|
||||||
|
* because it always fails on the emulator tests there. Also, it actually submits
|
||||||
|
* a report.
|
||||||
|
*/
|
||||||
|
@LargeTest
|
||||||
|
public class FDroidMetricsWorkerTest {
|
||||||
|
public static final String TAG = "FDroidMetricsWorkerTest";
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public InstantTaskExecutorRule instantTaskExecutorRule = new InstantTaskExecutorRule();
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public WorkManagerTestRule workManagerTestRule = new WorkManagerTestRule();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A test for easy manual testing.
|
||||||
|
*/
|
||||||
|
@Ignore
|
||||||
|
@Test
|
||||||
|
public void testGenerateReport() throws IOException {
|
||||||
|
String json = FDroidMetricsWorker.generateReport(
|
||||||
|
InstrumentationRegistry.getInstrumentation().getTargetContext());
|
||||||
|
System.out.println(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWorkRequest() throws ExecutionException, InterruptedException {
|
||||||
|
OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(FDroidMetricsWorker.class).build();
|
||||||
|
workManagerTestRule.workManager.enqueue(request).getResult();
|
||||||
|
ListenableFuture<WorkInfo> workInfo = workManagerTestRule.workManager.getWorkInfoById(request.getId());
|
||||||
|
assertEquals(WorkInfo.State.SUCCEEDED, workInfo.get().getState());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package org.fdroid.fdroid.work;
|
||||||
|
|
||||||
|
import android.app.Instrumentation;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
|
import androidx.work.Configuration;
|
||||||
|
import androidx.work.WorkManager;
|
||||||
|
import androidx.work.testing.SynchronousExecutor;
|
||||||
|
import androidx.work.testing.WorkManagerTestInitHelper;
|
||||||
|
import org.junit.rules.TestWatcher;
|
||||||
|
import org.junit.runner.Description;
|
||||||
|
|
||||||
|
public class WorkManagerTestRule extends TestWatcher {
|
||||||
|
Context targetContext;
|
||||||
|
Context testContext;
|
||||||
|
Configuration configuration;
|
||||||
|
WorkManager workManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void starting(Description description) {
|
||||||
|
final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
|
||||||
|
targetContext = instrumentation.getTargetContext();
|
||||||
|
testContext = instrumentation.getContext();
|
||||||
|
configuration = new Configuration.Builder()
|
||||||
|
.setMinimumLoggingLevel(Log.DEBUG)
|
||||||
|
.setExecutor(new SynchronousExecutor())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
WorkManagerTestInitHelper.initializeTestWorkManager(targetContext, configuration);
|
||||||
|
workManager = WorkManager.getInstance(targetContext);
|
||||||
|
}
|
||||||
|
}
|
9
app/src/androidTest/proguard-rules.pro
vendored
@ -1,3 +1,7 @@
|
|||||||
|
-dontoptimize
|
||||||
|
-dontwarn
|
||||||
|
-dontobfuscate
|
||||||
|
|
||||||
-dontwarn android.test.**
|
-dontwarn android.test.**
|
||||||
-dontwarn android.support.test.**
|
-dontwarn android.support.test.**
|
||||||
-dontnote junit.framework.**
|
-dontnote junit.framework.**
|
||||||
@ -14,3 +18,8 @@
|
|||||||
|
|
||||||
-keep class junit.** { *; }
|
-keep class junit.** { *; }
|
||||||
-dontwarn junit.**
|
-dontwarn junit.**
|
||||||
|
|
||||||
|
# This is necessary so that RemoteWorkManager can be initialized (also marked with @Keep)
|
||||||
|
-keep class androidx.work.multiprocess.RemoteWorkManagerClient {
|
||||||
|
public <init>(...);
|
||||||
|
}
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
package org.fdroid.fdroid.nearby;
|
||||||
|
|
||||||
|
public class LocalRepoManager {
|
||||||
|
public static final String[] WEB_ROOT_ASSET_FILES = {};
|
||||||
|
}
|
@ -19,14 +19,14 @@
|
|||||||
|
|
||||||
package org.fdroid.fdroid.nearby;
|
package org.fdroid.fdroid.nearby;
|
||||||
|
|
||||||
import android.app.Activity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dummy version for basic app flavor.
|
* Dummy version for basic app flavor.
|
||||||
*/
|
*/
|
||||||
public class TreeUriScannerIntentService {
|
public class TreeUriScannerIntentService {
|
||||||
public static void onActivityResult(Activity activity, Intent intent) {
|
public static void onActivityResult(AppCompatActivity activity, Intent intent) {
|
||||||
throw new IllegalStateException("unimplemented");
|
throw new IllegalStateException("unimplemented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,11 @@
|
|||||||
|
|
||||||
package org.fdroid.fdroid.views.main;
|
package org.fdroid.fdroid.views.main;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.views.PreferencesFragment;
|
import org.fdroid.fdroid.views.PreferencesFragment;
|
||||||
import org.fdroid.fdroid.views.updates.UpdatesViewBinder;
|
import org.fdroid.fdroid.views.updates.UpdatesViewBinder;
|
||||||
@ -49,10 +49,10 @@ class MainViewController extends RecyclerView.ViewHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see WhatsNewViewBinder
|
* @see LatestViewBinder
|
||||||
*/
|
*/
|
||||||
public void bindWhatsNewView() {
|
public void bindLatestView() {
|
||||||
new WhatsNewViewBinder(activity, frame);
|
new LatestViewBinder(activity, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 65 KiB |
@ -6,7 +6,7 @@
|
|||||||
<!-- android:title and android:icon are set dynamically in MainActivity -->
|
<!-- android:title and android:icon are set dynamically in MainActivity -->
|
||||||
<item
|
<item
|
||||||
app:showAsAction="ifRoom|withText"
|
app:showAsAction="ifRoom|withText"
|
||||||
android:id="@+id/whats_new"/>
|
android:id="@+id/latest"/>
|
||||||
<item
|
<item
|
||||||
app:showAsAction="ifRoom|withText"
|
app:showAsAction="ifRoom|withText"
|
||||||
android:id="@+id/updates"/>
|
android:id="@+id/updates"/>
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<PreferenceScreen
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<PreferenceScreen android:title="@string/about_title">
|
<PreferenceScreen android:title="@string/about_title"
|
||||||
<intent
|
android:key="pref_about" />
|
||||||
android:action="android.intent.action.MAIN"
|
|
||||||
android:targetPackage="@string/applicationId"
|
|
||||||
android:targetClass="org.fdroid.fdroid.AboutActivity"/>
|
|
||||||
</PreferenceScreen>
|
|
||||||
|
|
||||||
<PreferenceCategory android:title="@string/preference_category__my_apps">
|
<PreferenceCategory android:title="@string/preference_category__my_apps">
|
||||||
<PreferenceScreen android:title="@string/preference_manage_installed_apps">
|
<PreferenceScreen android:title="@string/preference_manage_installed_apps">
|
||||||
@ -47,7 +42,7 @@
|
|||||||
android:title="@string/over_data"
|
android:title="@string/over_data"
|
||||||
android:defaultValue="@integer/defaultOverData"
|
android:defaultValue="@integer/defaultOverData"
|
||||||
android:layout="@layout/preference_seekbar"/>
|
android:layout="@layout/preference_seekbar"/>
|
||||||
<SwitchPreference
|
<SwitchPreferenceCompat
|
||||||
android:title="@string/update_auto_download"
|
android:title="@string/update_auto_download"
|
||||||
android:summary="@string/update_auto_download_summary"
|
android:summary="@string/update_auto_download_summary"
|
||||||
android:key="updateAutoDownload"/>
|
android:key="updateAutoDownload"/>
|
||||||
@ -56,7 +51,7 @@
|
|||||||
android:title="@string/update_interval"
|
android:title="@string/update_interval"
|
||||||
android:defaultValue="@integer/defaultUpdateInterval"
|
android:defaultValue="@integer/defaultUpdateInterval"
|
||||||
android:layout="@layout/preference_seekbar"/>
|
android:layout="@layout/preference_seekbar"/>
|
||||||
<SwitchPreference
|
<SwitchPreferenceCompat
|
||||||
android:title="@string/notify"
|
android:title="@string/notify"
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
android:key="updateNotify"/>
|
android:key="updateNotify"/>
|
||||||
@ -77,26 +72,26 @@
|
|||||||
|
|
||||||
<PreferenceCategory android:title="@string/appcompatibility"
|
<PreferenceCategory android:title="@string/appcompatibility"
|
||||||
android:key="pref_category_appcompatibility">
|
android:key="pref_category_appcompatibility">
|
||||||
<SwitchPreference
|
<SwitchPreferenceCompat
|
||||||
android:title="@string/show_incompat_versions"
|
android:title="@string/show_incompat_versions"
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="incompatibleVersions"/>
|
android:key="incompatibleVersions"/>
|
||||||
<SwitchPreference
|
<SwitchPreferenceCompat
|
||||||
android:title="@string/show_anti_feature_apps"
|
android:title="@string/show_anti_feature_apps"
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="showAntiFeatureApps"/>
|
android:key="showAntiFeatureApps"/>
|
||||||
<SwitchPreference
|
<SwitchPreferenceCompat
|
||||||
android:title="@string/force_touch_apps"
|
android:title="@string/force_touch_apps"
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="ignoreTouchscreen"/>
|
android:key="ignoreTouchscreen"/>
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory android:title="@string/proxy">
|
<PreferenceCategory android:title="@string/proxy">
|
||||||
<SwitchPreference
|
<SwitchPreferenceCompat
|
||||||
android:key="useTor"
|
android:key="useTor"
|
||||||
android:summary="@string/useTorSummary"
|
android:summary="@string/useTorSummary"
|
||||||
android:title="@string/useTor"/>
|
android:title="@string/useTor"/>
|
||||||
<SwitchPreference
|
<SwitchPreferenceCompat
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="enableProxy"
|
android:key="enableProxy"
|
||||||
android:title="@string/enable_proxy_title"
|
android:title="@string/enable_proxy_title"
|
||||||
@ -116,12 +111,12 @@
|
|||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="pref_category_privacy"
|
android:key="pref_category_privacy"
|
||||||
android:title="@string/privacy">
|
android:title="@string/privacy">
|
||||||
<SwitchPreference
|
<SwitchPreferenceCompat
|
||||||
android:key="promptToSendCrashReports"
|
android:key="promptToSendCrashReports"
|
||||||
android:title="@string/prompt_to_send_crash_reports"
|
android:title="@string/prompt_to_send_crash_reports"
|
||||||
android:summary="@string/prompt_to_send_crash_reports_summary"
|
android:summary="@string/prompt_to_send_crash_reports_summary"
|
||||||
android:defaultValue="true"/>
|
android:defaultValue="true"/>
|
||||||
<SwitchPreference
|
<SwitchPreferenceCompat
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="preventScreenshots"
|
android:key="preventScreenshots"
|
||||||
android:summary="@string/preventScreenshots_summary"
|
android:summary="@string/preventScreenshots_summary"
|
||||||
@ -137,7 +132,7 @@
|
|||||||
android:defaultValue="86400000"
|
android:defaultValue="86400000"
|
||||||
android:entries="@array/keepCacheNames"
|
android:entries="@array/keepCacheNames"
|
||||||
android:entryValues="@array/keepCacheValues"/>
|
android:entryValues="@array/keepCacheValues"/>
|
||||||
<SwitchPreference
|
<SwitchPreferenceCompat
|
||||||
android:title="@string/expert"
|
android:title="@string/expert"
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="expert"/>
|
android:key="expert"/>
|
||||||
@ -153,6 +148,12 @@
|
|||||||
android:summary="@string/keep_install_history_summary"
|
android:summary="@string/keep_install_history_summary"
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:dependency="expert"/>
|
android:dependency="expert"/>
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:key="sendToFdroidMetrics"
|
||||||
|
android:title="@string/send_to_fdroid_metrics"
|
||||||
|
android:summary="@string/send_to_fdroid_metrics_summary"
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:dependency="expert"/>
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:key="hideAllNotifications"
|
android:key="hideAllNotifications"
|
||||||
android:title="@string/hide_all_notifications"
|
android:title="@string/hide_all_notifications"
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<!-- This file should be outside of release manifest (in this case app/src/mock/Manifest.xml -->
|
<!-- This file should be outside of release manifest (in this case app/src/mock/Manifest.xml -->
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<!--required to enable/disable system animations from the app itself during Espresso test runs-->
|
<!--required to enable/disable system animations from the app itself during Espresso test runs-->
|
||||||
<uses-permission android:name="android.permission.SET_ANIMATION_SCALE"/>
|
<uses-permission android:name="android.permission.SET_ANIMATION_SCALE" />
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
* Copyright (C) 2010-2012 Ciaran Gultnieks
|
* Copyright (C) 2010-2012 Ciaran Gultnieks
|
||||||
* Copyright (C) 2013-2017 Peter Serwylo
|
* Copyright (C) 2013-2017 Peter Serwylo
|
||||||
@ -23,91 +24,128 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
-->
|
-->
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="org.fdroid.fdroid"
|
package="org.fdroid.fdroid"
|
||||||
android:installLocation="auto">
|
android:installLocation="auto">
|
||||||
|
|
||||||
<uses-feature android:name="android.hardware.nfc" android:required="false"/>
|
<uses-feature
|
||||||
<uses-feature android:name="android.hardware.bluetooth" android:required="false"/>
|
android:name="android.hardware.nfc"
|
||||||
<uses-feature android:name="android.hardware.usb.host" android:required="false"/>
|
android:required="false" />
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.bluetooth"
|
||||||
|
android:required="false" />
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-feature
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
android:name="android.hardware.usb.host"
|
||||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
android:required="false" />
|
||||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
|
|
||||||
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
|
|
||||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH"/>
|
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
|
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
|
||||||
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
|
|
||||||
<uses-permission android:name="android.permission.NFC"/>
|
|
||||||
<uses-permission android:name="android.permission.USB_PERMISSION"
|
|
||||||
android:maxSdkVersion="22"/> <!-- maybe unnecessary -->
|
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
|
||||||
|
|
||||||
<uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||||
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
|
||||||
|
<uses-permission android:name="android.permission.NFC" />
|
||||||
|
<uses-permission
|
||||||
|
android:name="android.permission.USB_PERMISSION"
|
||||||
|
android:maxSdkVersion="22" /><!-- maybe unnecessary -->
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
|
||||||
|
<uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
|
|
||||||
<application>
|
<application>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:label="@string/swap"
|
android:name=".nearby.SwapWorkflowActivity"
|
||||||
android:name=".nearby.SwapWorkflowActivity"
|
android:configChanges="orientation|keyboardHidden"
|
||||||
android:parentActivityName=".views.main.MainActivity"
|
android:label="@string/swap"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:theme="@style/SwapTheme.Wizard"
|
android:parentActivityName=".views.main.MainActivity"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait">
|
||||||
android:configChanges="orientation|keyboardHidden">
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".views.main.MainActivity"/>
|
android:value=".views.main.MainActivity" />
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".panic.PanicPreferencesActivity"
|
||||||
|
android:label="@string/panic_settings"
|
||||||
|
android:parentActivityName=".views.main.MainActivity">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="info.guardianproject.panic.action.CONNECT" />
|
||||||
|
<action android:name="info.guardianproject.panic.action.DISCONNECT" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
|
android:value=".views.main.MainActivity" />
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".panic.SelectInstalledAppsActivity"
|
||||||
|
android:parentActivityName=".panic.PanicPreferencesActivity" />
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".panic.PanicResponderActivity"
|
||||||
|
android:noHistory="true"
|
||||||
|
android:theme="@android:style/Theme.NoDisplay">
|
||||||
|
|
||||||
|
<!-- this can never have launchMode singleTask or singleInstance! -->
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="info.guardianproject.panic.action.TRIGGER" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name=".panic.ExitActivity"
|
||||||
|
android:theme="@android:style/Theme.NoDisplay" />
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".panic.CalculatorActivity"
|
||||||
|
android:enabled="false"
|
||||||
|
android:icon="@mipmap/ic_calculator_launcher"
|
||||||
|
android:label="@string/hiding_calculator">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
<receiver android:name=".nearby.WifiStateChangeReceiver">
|
<receiver android:name=".nearby.WifiStateChangeReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.net.wifi.STATE_CHANGE"/>
|
<action android:name="android.net.wifi.STATE_CHANGE" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<receiver android:name=".receiver.DeviceStorageReceiver">
|
<receiver android:name=".receiver.DeviceStorageReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.DEVICE_STORAGE_LOW"/>
|
<action android:name="android.intent.action.DEVICE_STORAGE_LOW" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<service
|
<receiver android:name=".nearby.UsbDeviceAttachedReceiver">
|
||||||
android:name=".nearby.WifiStateChangeService"
|
|
||||||
android:exported="false"/>
|
|
||||||
<service android:name=".nearby.SwapService"/>
|
|
||||||
|
|
||||||
<service
|
|
||||||
android:name=".nearby.LocalRepoService"
|
|
||||||
android:exported="false"/>
|
|
||||||
<service
|
|
||||||
android:name=".nearby.TreeUriScannerIntentService"
|
|
||||||
android:exported="false"/>
|
|
||||||
<service
|
|
||||||
android:name=".nearby.SDCardScannerService"
|
|
||||||
android:exported="false"/>
|
|
||||||
|
|
||||||
<receiver
|
|
||||||
android:name=".nearby.UsbDeviceAttachedReceiver">
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"/>
|
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
|
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
|
||||||
android:resource="@xml/device_filter"/>
|
android:resource="@xml/device_filter" />
|
||||||
</receiver>
|
</receiver>
|
||||||
<receiver
|
<receiver android:name=".nearby.UsbDeviceDetachedReceiver">
|
||||||
android:name=".nearby.UsbDeviceDetachedReceiver">
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED"/>
|
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.hardware.usb.action.USB_DEVICE_DETACHED"
|
android:name="android.hardware.usb.action.USB_DEVICE_DETACHED"
|
||||||
android:resource="@xml/device_filter"/>
|
android:resource="@xml/device_filter" />
|
||||||
</receiver>
|
</receiver>
|
||||||
<receiver android:name=".nearby.UsbDeviceMediaMountedReceiver">
|
<receiver android:name=".nearby.UsbDeviceMediaMountedReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@ -121,52 +159,20 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<activity
|
<service
|
||||||
android:name=".panic.PanicPreferencesActivity"
|
android:name=".nearby.WifiStateChangeService"
|
||||||
android:label="@string/panic_settings"
|
android:exported="false" />
|
||||||
android:parentActivityName=".views.main.MainActivity">
|
<service android:name=".nearby.SwapService" />
|
||||||
<meta-data
|
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
|
||||||
android:value=".views.main.MainActivity"/>
|
|
||||||
|
|
||||||
<intent-filter>
|
<service
|
||||||
<action android:name="info.guardianproject.panic.action.CONNECT"/>
|
android:name=".nearby.LocalRepoService"
|
||||||
<action android:name="info.guardianproject.panic.action.DISCONNECT"/>
|
android:exported="false" />
|
||||||
|
<service
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
android:name=".nearby.TreeUriScannerIntentService"
|
||||||
</intent-filter>
|
android:exported="false" />
|
||||||
</activity>
|
<service
|
||||||
<activity
|
android:name=".nearby.SDCardScannerService"
|
||||||
android:name=".panic.SelectInstalledAppsActivity"
|
android:exported="false" />
|
||||||
android:parentActivityName=".panic.PanicPreferencesActivity"/>
|
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name=".panic.PanicResponderActivity"
|
|
||||||
android:noHistory="true"
|
|
||||||
android:theme="@android:style/Theme.NoDisplay">
|
|
||||||
|
|
||||||
<!-- this can never have launchMode singleTask or singleInstance! -->
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="info.guardianproject.panic.action.TRIGGER"/>
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
<activity
|
|
||||||
android:name=".panic.ExitActivity"
|
|
||||||
android:theme="@android:style/Theme.NoDisplay"/>
|
|
||||||
<activity
|
|
||||||
android:name=".panic.CalculatorActivity"
|
|
||||||
android:enabled="false"
|
|
||||||
android:icon="@mipmap/ic_calculator_launcher"
|
|
||||||
android:label="@string/hiding_calculator"
|
|
||||||
android:theme="@style/AppThemeLight">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
|
@ -4,12 +4,13 @@ import android.os.Parcel;
|
|||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import javax.jmdns.ServiceInfo;
|
|
||||||
import javax.jmdns.impl.util.ByteWrangler;
|
|
||||||
import java.net.Inet4Address;
|
import java.net.Inet4Address;
|
||||||
import java.net.Inet6Address;
|
import java.net.Inet6Address;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
|
import javax.jmdns.ServiceInfo;
|
||||||
|
import javax.jmdns.impl.util.ByteWrangler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ServiceInfo class needs to be serialized in order to be sent as an Android broadcast.
|
* The ServiceInfo class needs to be serialized in order to be sent as an Android broadcast.
|
||||||
* In order to make it Parcelable (or Serializable for that matter), there are some package-scope
|
* In order to make it Parcelable (or Serializable for that matter), there are some package-scope
|
||||||
|
@ -10,15 +10,17 @@ import android.os.Handler;
|
|||||||
import android.os.HandlerThread;
|
import android.os.HandlerThread;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
import org.fdroid.fdroid.nearby.peers.BluetoothPeer;
|
import org.fdroid.fdroid.nearby.peers.BluetoothPeer;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manage the {@link android.bluetooth.BluetoothAdapter}in a {@link HandlerThread}.
|
* Manage the {@link android.bluetooth.BluetoothAdapter}in a {@link HandlerThread}.
|
||||||
* The start process is in {@link HandlerThread#onLooperPrepared()} so that it is
|
* The start process is in {@link HandlerThread#onLooperPrepared()} so that it is
|
||||||
|
@ -5,7 +5,7 @@ import android.bluetooth.BluetoothServerSocket;
|
|||||||
import android.bluetooth.BluetoothSocket;
|
import android.bluetooth.BluetoothSocket;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.webkit.MimeTypeMap;
|
import android.webkit.MimeTypeMap;
|
||||||
import fi.iki.elonen.NanoHTTPD;
|
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
import org.fdroid.fdroid.nearby.httpish.Request;
|
import org.fdroid.fdroid.nearby.httpish.Request;
|
||||||
import org.fdroid.fdroid.nearby.httpish.Response;
|
import org.fdroid.fdroid.nearby.httpish.Response;
|
||||||
@ -20,6 +20,8 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import fi.iki.elonen.NanoHTTPD;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Act as a layer on top of LocalHTTPD server, by forwarding requests served
|
* Act as a layer on top of LocalHTTPD server, by forwarding requests served
|
||||||
* over bluetooth to that server.
|
* over bluetooth to that server.
|
||||||
|
@ -10,9 +10,6 @@ import android.os.Process;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|
||||||
|
|
||||||
import org.fdroid.fdroid.FDroidApp;
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
import org.fdroid.fdroid.Preferences;
|
import org.fdroid.fdroid.Preferences;
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
@ -28,6 +25,9 @@ import javax.jmdns.ServiceEvent;
|
|||||||
import javax.jmdns.ServiceInfo;
|
import javax.jmdns.ServiceInfo;
|
||||||
import javax.jmdns.ServiceListener;
|
import javax.jmdns.ServiceListener;
|
||||||
|
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manage {@link JmDNS} in a {@link HandlerThread}. The start process is in
|
* Manage {@link JmDNS} in a {@link HandlerThread}. The start process is in
|
||||||
* {@link HandlerThread#onLooperPrepared()} so that it is always started before
|
* {@link HandlerThread#onLooperPrepared()} so that it is always started before
|
||||||
|
@ -35,11 +35,9 @@ package org.fdroid.fdroid.nearby;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import fi.iki.elonen.NanoHTTPD;
|
|
||||||
import fi.iki.elonen.NanoHTTPD.Response.IStatus;
|
|
||||||
import org.fdroid.fdroid.BuildConfig;
|
import org.fdroid.fdroid.BuildConfig;
|
||||||
|
|
||||||
import javax.net.ssl.SSLServerSocketFactory;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
@ -62,6 +60,11 @@ import java.util.Map;
|
|||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLServerSocketFactory;
|
||||||
|
|
||||||
|
import fi.iki.elonen.NanoHTTPD;
|
||||||
|
import fi.iki.elonen.NanoHTTPD.Response.IStatus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A HTTP server for serving the files that are being swapped via WiFi, etc.
|
* A HTTP server for serving the files that are being swapped via WiFi, etc.
|
||||||
* The only changes were to remove unneeded extras like {@code main()}, the
|
* The only changes were to remove unneeded extras like {@code main()}, the
|
||||||
|
@ -6,8 +6,8 @@ import android.os.Handler;
|
|||||||
import android.os.HandlerThread;
|
import android.os.HandlerThread;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.fdroid.fdroid.FDroidApp;
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
import org.fdroid.fdroid.Preferences;
|
import org.fdroid.fdroid.Preferences;
|
||||||
|
|
||||||
@ -15,6 +15,8 @@ import java.io.IOException;
|
|||||||
import java.net.BindException;
|
import java.net.BindException;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manage {@link LocalHTTPD} in a {@link HandlerThread};
|
* Manage {@link LocalHTTPD} in a {@link HandlerThread};
|
||||||
*/
|
*/
|
||||||
|
@ -2,7 +2,7 @@ package org.fdroid.fdroid.nearby;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import kellinwood.security.zipsigner.ZipSigner;
|
|
||||||
import org.bouncycastle.asn1.ASN1Sequence;
|
import org.bouncycastle.asn1.ASN1Sequence;
|
||||||
import org.bouncycastle.asn1.x500.X500Name;
|
import org.bouncycastle.asn1.x500.X500Name;
|
||||||
import org.bouncycastle.asn1.x509.GeneralName;
|
import org.bouncycastle.asn1.x509.GeneralName;
|
||||||
@ -19,9 +19,6 @@ import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
|
|||||||
import org.fdroid.fdroid.FDroidApp;
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
|
|
||||||
import javax.net.ssl.KeyManager;
|
|
||||||
import javax.net.ssl.KeyManagerFactory;
|
|
||||||
import javax.net.ssl.X509KeyManager;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
@ -49,6 +46,12 @@ import java.util.Date;
|
|||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import javax.net.ssl.KeyManager;
|
||||||
|
import javax.net.ssl.KeyManagerFactory;
|
||||||
|
import javax.net.ssl.X509KeyManager;
|
||||||
|
|
||||||
|
import kellinwood.security.zipsigner.ZipSigner;
|
||||||
|
|
||||||
// TODO Address exception handling in a uniform way throughout
|
// TODO Address exception handling in a uniform way throughout
|
||||||
|
|
||||||
@SuppressWarnings("LineLength")
|
@SuppressWarnings("LineLength")
|
||||||
|
@ -10,10 +10,9 @@ import android.graphics.Bitmap.Config;
|
|||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.fdroid.fdroid.FDroidApp;
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
import org.fdroid.fdroid.Hasher;
|
import org.fdroid.fdroid.Hasher;
|
||||||
import org.fdroid.fdroid.IndexUpdater;
|
import org.fdroid.fdroid.IndexUpdater;
|
||||||
@ -50,13 +49,15 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.jar.JarOutputStream;
|
import java.util.jar.JarOutputStream;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link SwapService} deals with managing the entire workflow from selecting apps to
|
* The {@link SwapService} deals with managing the entire workflow from selecting apps to
|
||||||
* swap, to invoking this class to prepare the webroot, to enabling various communication protocols.
|
* swap, to invoking this class to prepare the webroot, to enabling various communication protocols.
|
||||||
* This class deals specifically with the webroot side of things, ensuring we have a valid index.jar
|
* This class deals specifically with the webroot side of things, ensuring we have a valid index.jar
|
||||||
* and the relevant .apk and icon files available.
|
* and the relevant .apk and icon files available.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("LineLength")
|
|
||||||
public final class LocalRepoManager {
|
public final class LocalRepoManager {
|
||||||
private static final String TAG = "LocalRepoManager";
|
private static final String TAG = "LocalRepoManager";
|
||||||
|
|
||||||
@ -65,7 +66,7 @@ public final class LocalRepoManager {
|
|||||||
private final AssetManager assetManager;
|
private final AssetManager assetManager;
|
||||||
private final String fdroidPackageName;
|
private final String fdroidPackageName;
|
||||||
|
|
||||||
private static final String[] WEB_ROOT_ASSET_FILES = {
|
public static final String[] WEB_ROOT_ASSET_FILES = {
|
||||||
"swap-icon.png",
|
"swap-icon.png",
|
||||||
"swap-tick-done.png",
|
"swap-tick-done.png",
|
||||||
"swap-tick-not-done.png",
|
"swap-tick-not-done.png",
|
||||||
@ -348,7 +349,8 @@ public final class LocalRepoManager {
|
|||||||
serializer = XmlPullParserFactory.newInstance().newSerializer();
|
serializer = XmlPullParserFactory.newInstance().newSerializer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void build(Context context, Map<String, App> apps, OutputStream output) throws IOException, LocalRepoKeyStore.InitException {
|
public void build(Context context, Map<String, App> apps, OutputStream output)
|
||||||
|
throws IOException, LocalRepoKeyStore.InitException {
|
||||||
serializer.setOutput(output, "UTF-8");
|
serializer.setOutput(output, "UTF-8");
|
||||||
serializer.startDocument(null, null);
|
serializer.startDocument(null, null);
|
||||||
serializer.startTag("", "fdroid");
|
serializer.startTag("", "fdroid");
|
||||||
@ -356,12 +358,14 @@ public final class LocalRepoManager {
|
|||||||
// <repo> block
|
// <repo> block
|
||||||
serializer.startTag("", "repo");
|
serializer.startTag("", "repo");
|
||||||
serializer.attribute("", "icon", "blah.png");
|
serializer.attribute("", "icon", "blah.png");
|
||||||
serializer.attribute("", "name", Preferences.get().getLocalRepoName() + " on " + FDroidApp.ipAddressString);
|
serializer.attribute("", "name", Preferences.get().getLocalRepoName()
|
||||||
|
+ " on " + FDroidApp.ipAddressString);
|
||||||
serializer.attribute("", "pubkey", Hasher.hex(LocalRepoKeyStore.get(context).getCertificate()));
|
serializer.attribute("", "pubkey", Hasher.hex(LocalRepoKeyStore.get(context).getCertificate()));
|
||||||
long timestamp = System.currentTimeMillis() / 1000L;
|
long timestamp = System.currentTimeMillis() / 1000L;
|
||||||
serializer.attribute("", "timestamp", String.valueOf(timestamp));
|
serializer.attribute("", "timestamp", String.valueOf(timestamp));
|
||||||
serializer.attribute("", "version", "10");
|
serializer.attribute("", "version", "10");
|
||||||
tag("description", "A local FDroid repo generated from apps installed on " + Preferences.get().getLocalRepoName());
|
tag("description", "A local FDroid repo generated from apps installed on "
|
||||||
|
+ Preferences.get().getLocalRepoName());
|
||||||
serializer.endTag("", "repo");
|
serializer.endTag("", "repo");
|
||||||
|
|
||||||
// <application> blocks
|
// <application> blocks
|
||||||
|
@ -4,7 +4,7 @@ import android.app.IntentService;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|
||||||
import org.fdroid.fdroid.FDroidApp;
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
@ -15,6 +15,8 @@ import java.util.Arrays;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles setting up and generating the local repo used to swap apps, including
|
* Handles setting up and generating the local repo used to swap apps, including
|
||||||
* the {@code index.jar}, the symlinks to the shared APKs, etc.
|
* the {@code index.jar}, the symlinks to the shared APKs, etc.
|
||||||
|
@ -29,7 +29,7 @@ import android.os.Build;
|
|||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import org.fdroid.fdroid.IndexUpdater;
|
import org.fdroid.fdroid.IndexUpdater;
|
||||||
import org.fdroid.fdroid.IndexV1Updater;
|
import org.fdroid.fdroid.IndexV1Updater;
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
@ -44,6 +44,8 @@ import java.util.Collections;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link IntentService} subclass for scanning removable "external storage"
|
* An {@link IntentService} subclass for scanning removable "external storage"
|
||||||
* for F-Droid package repos, e.g. SD Cards. This is intended to support
|
* for F-Droid package repos, e.g. SD Cards. This is intended to support
|
||||||
|
@ -4,7 +4,6 @@ import android.annotation.TargetApi;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.graphics.PorterDuff;
|
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -21,6 +20,10 @@ import android.widget.ImageView;
|
|||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.fdroid.fdroid.R;
|
||||||
|
import org.fdroid.fdroid.data.InstalledAppProvider;
|
||||||
|
import org.fdroid.fdroid.data.Schema.InstalledAppTable;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
@ -29,10 +32,6 @@ import androidx.loader.app.LoaderManager;
|
|||||||
import androidx.loader.content.CursorLoader;
|
import androidx.loader.content.CursorLoader;
|
||||||
import androidx.loader.content.Loader;
|
import androidx.loader.content.Loader;
|
||||||
|
|
||||||
import org.fdroid.fdroid.R;
|
|
||||||
import org.fdroid.fdroid.data.InstalledAppProvider;
|
|
||||||
import org.fdroid.fdroid.data.Schema.InstalledAppTable;
|
|
||||||
|
|
||||||
public class SelectAppsView extends SwapView implements LoaderManager.LoaderCallbacks<Cursor> {
|
public class SelectAppsView extends SwapView implements LoaderManager.LoaderCallbacks<Cursor> {
|
||||||
|
|
||||||
public SelectAppsView(Context context) {
|
public SelectAppsView(Context context) {
|
||||||
@ -200,8 +199,6 @@ public class SelectAppsView extends SwapView implements LoaderManager.LoaderCall
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
updateCheckedIndicatorView(view, listView.isItemChecked(listPosition));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateCheckedIndicatorView(int position, boolean checked) {
|
public void updateCheckedIndicatorView(int position, boolean checked) {
|
||||||
@ -210,24 +207,6 @@ public class SelectAppsView extends SwapView implements LoaderManager.LoaderCall
|
|||||||
|
|
||||||
if (position >= firstListItemPosition && position <= lastListItemPosition) {
|
if (position >= firstListItemPosition && position <= lastListItemPosition) {
|
||||||
final int childIndex = position - firstListItemPosition;
|
final int childIndex = position - firstListItemPosition;
|
||||||
updateCheckedIndicatorView(listView.getChildAt(childIndex), checked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateCheckedIndicatorView(View view, boolean checked) {
|
|
||||||
ImageView imageView = (ImageView) view.findViewById(R.id.checked);
|
|
||||||
if (imageView != null) {
|
|
||||||
int resource;
|
|
||||||
int colour;
|
|
||||||
if (checked) {
|
|
||||||
resource = R.drawable.ic_check_circle;
|
|
||||||
colour = ContextCompat.getColor(getContext(), R.color.swap_bright_blue);
|
|
||||||
} else {
|
|
||||||
resource = R.drawable.ic_add_circle_outline;
|
|
||||||
colour = 0xFFD0D0D4;
|
|
||||||
}
|
|
||||||
imageView.setImageDrawable(ContextCompat.getDrawable(getContext(), resource));
|
|
||||||
imageView.setColorFilter(colour, PorterDuff.Mode.MULTIPLY);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,6 @@ import android.widget.ListView;
|
|||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.widget.SwitchCompat;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|
||||||
|
|
||||||
import org.fdroid.fdroid.FDroidApp;
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
@ -32,6 +27,10 @@ import org.fdroid.fdroid.nearby.peers.Peer;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import com.google.android.material.switchmaterial.SwitchMaterial;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||||
import cc.mvdan.accesspoint.WifiApControl;
|
import cc.mvdan.accesspoint.WifiApControl;
|
||||||
|
|
||||||
@SuppressWarnings("LineLength")
|
@SuppressWarnings("LineLength")
|
||||||
@ -80,7 +79,7 @@ public class StartSwapView extends SwapView {
|
|||||||
@Nullable /* Emulators typically don't have bluetooth adapters */
|
@Nullable /* Emulators typically don't have bluetooth adapters */
|
||||||
private final BluetoothAdapter bluetooth = BluetoothAdapter.getDefaultAdapter();
|
private final BluetoothAdapter bluetooth = BluetoothAdapter.getDefaultAdapter();
|
||||||
|
|
||||||
private SwitchCompat bluetoothSwitch;
|
private SwitchMaterial bluetoothSwitch;
|
||||||
private TextView viewBluetoothId;
|
private TextView viewBluetoothId;
|
||||||
private TextView textBluetoothVisible;
|
private TextView textBluetoothVisible;
|
||||||
private TextView viewWifiId;
|
private TextView viewWifiId;
|
||||||
@ -176,7 +175,7 @@ public class StartSwapView extends SwapView {
|
|||||||
|
|
||||||
textBluetoothVisible = findViewById(R.id.bluetooth_visible);
|
textBluetoothVisible = findViewById(R.id.bluetooth_visible);
|
||||||
|
|
||||||
bluetoothSwitch = (SwitchCompat) findViewById(R.id.switch_bluetooth);
|
bluetoothSwitch = (SwitchMaterial) findViewById(R.id.switch_bluetooth);
|
||||||
bluetoothSwitch.setOnCheckedChangeListener(onBluetoothSwitchToggled);
|
bluetoothSwitch.setOnCheckedChangeListener(onBluetoothSwitchToggled);
|
||||||
bluetoothSwitch.setChecked(SwapService.getBluetoothVisibleUserPreference());
|
bluetoothSwitch.setChecked(SwapService.getBluetoothVisibleUserPreference());
|
||||||
bluetoothSwitch.setEnabled(true);
|
bluetoothSwitch.setEnabled(true);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package org.fdroid.fdroid.nearby;
|
package org.fdroid.fdroid.nearby;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
@ -13,7 +12,6 @@ import android.content.IntentFilter;
|
|||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -37,7 +35,6 @@ import org.fdroid.fdroid.data.Schema;
|
|||||||
import org.fdroid.fdroid.nearby.peers.Peer;
|
import org.fdroid.fdroid.nearby.peers.Peer;
|
||||||
import org.fdroid.fdroid.net.Downloader;
|
import org.fdroid.fdroid.net.Downloader;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
@ -49,6 +46,10 @@ import java.util.Timer;
|
|||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
|
||||||
import cc.mvdan.accesspoint.WifiApControl;
|
import cc.mvdan.accesspoint.WifiApControl;
|
||||||
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.rxjava3.core.Completable;
|
||||||
|
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||||
|
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Central service which manages all of the different moving parts of swap which are required
|
* Central service which manages all of the different moving parts of swap which are required
|
||||||
@ -110,46 +111,6 @@ public class SwapService extends Service {
|
|||||||
UpdateService.updateRepoNow(this, peer.getRepoAddress());
|
UpdateService.updateRepoNow(this, peer.getRepoAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("StaticFieldLeak")
|
|
||||||
private void askServerToSwapWithUs(final Repo repo) {
|
|
||||||
new AsyncTask<Void, Void, Void>() {
|
|
||||||
@Override
|
|
||||||
protected Void doInBackground(Void... args) {
|
|
||||||
String swapBackUri = Utils.getLocalRepoUri(FDroidApp.repo).toString();
|
|
||||||
HttpURLConnection conn = null;
|
|
||||||
try {
|
|
||||||
URL url = new URL(repo.address.replace("/fdroid/repo", "/request-swap"));
|
|
||||||
conn = (HttpURLConnection) url.openConnection();
|
|
||||||
conn.setRequestMethod("POST");
|
|
||||||
conn.setDoInput(true);
|
|
||||||
conn.setDoOutput(true);
|
|
||||||
|
|
||||||
OutputStream outputStream = conn.getOutputStream();
|
|
||||||
OutputStreamWriter writer = new OutputStreamWriter(outputStream);
|
|
||||||
writer.write("repo=" + swapBackUri);
|
|
||||||
writer.flush();
|
|
||||||
writer.close();
|
|
||||||
outputStream.close();
|
|
||||||
|
|
||||||
int responseCode = conn.getResponseCode();
|
|
||||||
Utils.debugLog(TAG, "Asking server at " + repo.address + " to swap with us in return (by " +
|
|
||||||
"POSTing to \"/request-swap\" with repo \"" + swapBackUri + "\"): " + responseCode);
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(TAG, "Error while asking server to swap with us", e);
|
|
||||||
Intent intent = new Intent(Downloader.ACTION_INTERRUPTED);
|
|
||||||
intent.setData(Uri.parse(repo.address));
|
|
||||||
intent.putExtra(Downloader.EXTRA_ERROR_MESSAGE, e.getLocalizedMessage());
|
|
||||||
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
|
|
||||||
} finally {
|
|
||||||
if (conn != null) {
|
|
||||||
conn.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Repo ensureRepoExists(@NonNull Peer peer) {
|
private Repo ensureRepoExists(@NonNull Peer peer) {
|
||||||
// TODO: newRepoConfig.getParsedUri() will include a fingerprint, which may not match with
|
// TODO: newRepoConfig.getParsedUri() will include a fingerprint, which may not match with
|
||||||
// the repos address in the database. Not sure on best behaviour in this situation.
|
// the repos address in the database. Not sure on best behaviour in this situation.
|
||||||
@ -343,12 +304,15 @@ public class SwapService extends Service {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private Timer timer;
|
private Timer timer;
|
||||||
|
|
||||||
|
private final CompositeDisposable compositeDisposable = new CompositeDisposable();
|
||||||
|
|
||||||
public class Binder extends android.os.Binder {
|
public class Binder extends android.os.Binder {
|
||||||
public SwapService getService() {
|
public SwapService getService() {
|
||||||
return SwapService.this;
|
return SwapService.this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
startForeground(NOTIFICATION, createNotification());
|
startForeground(NOTIFICATION, createNotification());
|
||||||
@ -398,6 +362,45 @@ public class SwapService extends Service {
|
|||||||
BonjourManager.setVisible(this, getWifiVisibleUserPreference() || getHotspotActivatedUserPreference());
|
BonjourManager.setVisible(this, getWifiVisibleUserPreference() || getHotspotActivatedUserPreference());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void askServerToSwapWithUs(final Repo repo) {
|
||||||
|
compositeDisposable.add(
|
||||||
|
Completable.fromAction(() -> {
|
||||||
|
String swapBackUri = Utils.getLocalRepoUri(FDroidApp.repo).toString();
|
||||||
|
HttpURLConnection conn = null;
|
||||||
|
try {
|
||||||
|
URL url = new URL(repo.address.replace("/fdroid/repo", "/request-swap"));
|
||||||
|
conn = (HttpURLConnection) url.openConnection();
|
||||||
|
conn.setRequestMethod("POST");
|
||||||
|
conn.setDoInput(true);
|
||||||
|
conn.setDoOutput(true);
|
||||||
|
|
||||||
|
try (OutputStream outputStream = conn.getOutputStream();
|
||||||
|
OutputStreamWriter writer = new OutputStreamWriter(outputStream)) {
|
||||||
|
writer.write("repo=" + swapBackUri);
|
||||||
|
writer.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
int responseCode = conn.getResponseCode();
|
||||||
|
Utils.debugLog(TAG, "Asking server at " + repo.address + " to swap with us in return (by " +
|
||||||
|
"POSTing to \"/request-swap\" with repo \"" + swapBackUri + "\"): " + responseCode);
|
||||||
|
} finally {
|
||||||
|
if (conn != null) {
|
||||||
|
conn.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.doOnError(e -> {
|
||||||
|
Intent intent = new Intent(Downloader.ACTION_INTERRUPTED);
|
||||||
|
intent.setData(Uri.parse(repo.address));
|
||||||
|
intent.putExtra(Downloader.EXTRA_ERROR_MESSAGE, e.getLocalizedMessage());
|
||||||
|
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
|
||||||
|
})
|
||||||
|
.subscribe()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is for setting things up for when the {@code SwapService} was
|
* This is for setting things up for when the {@code SwapService} was
|
||||||
* started by the user clicking on the initial start button. The things
|
* started by the user clicking on the initial start button. The things
|
||||||
@ -421,6 +424,8 @@ public class SwapService extends Service {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
|
compositeDisposable.dispose();
|
||||||
|
|
||||||
Utils.debugLog(TAG, "Destroying service, will disable swapping if required, and unregister listeners.");
|
Utils.debugLog(TAG, "Destroying service, will disable swapping if required, and unregister listeners.");
|
||||||
Preferences.get().unregisterLocalRepoHttpsListeners(httpsEnabledListener);
|
Preferences.get().unregisterLocalRepoHttpsListeners(httpsEnabledListener);
|
||||||
localBroadcastManager.unregisterReceiver(onWifiChange);
|
localBroadcastManager.unregisterReceiver(onWifiChange);
|
||||||
@ -429,7 +434,9 @@ public class SwapService extends Service {
|
|||||||
localBroadcastManager.unregisterReceiver(bonjourPeerFound);
|
localBroadcastManager.unregisterReceiver(bonjourPeerFound);
|
||||||
localBroadcastManager.unregisterReceiver(bonjourPeerRemoved);
|
localBroadcastManager.unregisterReceiver(bonjourPeerRemoved);
|
||||||
|
|
||||||
unregisterReceiver(bluetoothScanModeChanged);
|
if (bluetoothAdapter != null) {
|
||||||
|
unregisterReceiver(bluetoothScanModeChanged);
|
||||||
|
}
|
||||||
|
|
||||||
BluetoothManager.stop(this);
|
BluetoothManager.stop(this);
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package org.fdroid.fdroid.nearby;
|
package org.fdroid.fdroid.nearby;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -12,14 +11,6 @@ import android.database.Cursor;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.loader.app.LoaderManager;
|
|
||||||
import androidx.loader.content.CursorLoader;
|
|
||||||
import androidx.loader.content.Loader;
|
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|
||||||
import androidx.cursoradapter.widget.CursorAdapter;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -32,7 +23,9 @@ import android.widget.ListView;
|
|||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
|
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.UpdateService;
|
import org.fdroid.fdroid.UpdateService;
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
@ -49,6 +42,16 @@ import org.fdroid.fdroid.net.DownloaderService;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.cursoradapter.widget.CursorAdapter;
|
||||||
|
import androidx.loader.app.LoaderManager;
|
||||||
|
import androidx.loader.content.CursorLoader;
|
||||||
|
import androidx.loader.content.Loader;
|
||||||
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a view that shows a listing of all apps in the swap repo that this
|
* This is a view that shows a listing of all apps in the swap repo that this
|
||||||
* just connected to. The app listing and search should be replaced by
|
* just connected to. The app listing and search should be replaced by
|
||||||
@ -195,7 +198,7 @@ public class SwapSuccessView extends SwapView implements LoaderManager.LoaderCal
|
|||||||
private final ContentObserver appObserver = new ContentObserver(new Handler()) {
|
private final ContentObserver appObserver = new ContentObserver(new Handler()) {
|
||||||
@Override
|
@Override
|
||||||
public void onChange(boolean selfChange) {
|
public void onChange(boolean selfChange) {
|
||||||
Activity activity = getActivity();
|
AppCompatActivity activity = getActivity();
|
||||||
if (activity != null && app != null) {
|
if (activity != null && app != null) {
|
||||||
app = AppProvider.Helper.findSpecificApp(
|
app = AppProvider.Helper.findSpecificApp(
|
||||||
activity.getContentResolver(),
|
activity.getContentResolver(),
|
||||||
|
@ -6,12 +6,12 @@ import android.content.res.TypedArray;
|
|||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
|
|
||||||
|
import org.fdroid.fdroid.R;
|
||||||
|
|
||||||
import androidx.annotation.ColorInt;
|
import androidx.annotation.ColorInt;
|
||||||
import androidx.annotation.LayoutRes;
|
import androidx.annotation.LayoutRes;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
import org.fdroid.fdroid.R;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link android.view.View} that registers to handle the swap events from
|
* A {@link android.view.View} that registers to handle the swap events from
|
||||||
* {@link SwapService}.
|
* {@link SwapService}.
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package org.fdroid.fdroid.nearby;
|
package org.fdroid.fdroid.nearby;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.app.Activity;
|
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
@ -42,11 +41,11 @@ import androidx.annotation.StringRes;
|
|||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.appcompat.widget.SearchView;
|
import androidx.appcompat.widget.SearchView;
|
||||||
import androidx.appcompat.widget.SwitchCompat;
|
|
||||||
import androidx.appcompat.widget.Toolbar;
|
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||||
|
|
||||||
|
import com.google.android.material.appbar.MaterialToolbar;
|
||||||
|
import com.google.android.material.switchmaterial.SwitchMaterial;
|
||||||
import com.google.zxing.integration.android.IntentIntegrator;
|
import com.google.zxing.integration.android.IntentIntegrator;
|
||||||
import com.google.zxing.integration.android.IntentResult;
|
import com.google.zxing.integration.android.IntentResult;
|
||||||
|
|
||||||
@ -66,7 +65,6 @@ import org.fdroid.fdroid.net.BluetoothDownloader;
|
|||||||
import org.fdroid.fdroid.net.Downloader;
|
import org.fdroid.fdroid.net.Downloader;
|
||||||
import org.fdroid.fdroid.net.HttpDownloader;
|
import org.fdroid.fdroid.net.HttpDownloader;
|
||||||
import org.fdroid.fdroid.qr.CameraCharacteristicsChecker;
|
import org.fdroid.fdroid.qr.CameraCharacteristicsChecker;
|
||||||
import org.fdroid.fdroid.qr.QrGenAsyncTask;
|
|
||||||
import org.fdroid.fdroid.views.main.MainActivity;
|
import org.fdroid.fdroid.views.main.MainActivity;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@ -78,6 +76,7 @@ import java.util.Timer;
|
|||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
|
||||||
import cc.mvdan.accesspoint.WifiApControl;
|
import cc.mvdan.accesspoint.WifiApControl;
|
||||||
|
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||||
|
|
||||||
import static org.fdroid.fdroid.views.main.MainActivity.ACTION_REQUEST_SWAP;
|
import static org.fdroid.fdroid.views.main.MainActivity.ACTION_REQUEST_SWAP;
|
||||||
|
|
||||||
@ -107,7 +106,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
|||||||
private static final int REQUEST_WRITE_SETTINGS_PERMISSION = 5;
|
private static final int REQUEST_WRITE_SETTINGS_PERMISSION = 5;
|
||||||
private static final int STEP_INTRO = 1; // TODO remove this special case, only use layoutResIds
|
private static final int STEP_INTRO = 1; // TODO remove this special case, only use layoutResIds
|
||||||
|
|
||||||
private Toolbar toolbar;
|
private MaterialToolbar toolbar;
|
||||||
private SwapView currentView;
|
private SwapView currentView;
|
||||||
private boolean hasPreparedLocalRepo;
|
private boolean hasPreparedLocalRepo;
|
||||||
private boolean newIntent;
|
private boolean newIntent;
|
||||||
@ -120,6 +119,8 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
|||||||
@LayoutRes
|
@LayoutRes
|
||||||
private int currentSwapViewLayoutRes = STEP_INTRO;
|
private int currentSwapViewLayoutRes = STEP_INTRO;
|
||||||
|
|
||||||
|
private final CompositeDisposable compositeDisposable = new CompositeDisposable();
|
||||||
|
|
||||||
public static void requestSwap(Context context, String repo) {
|
public static void requestSwap(Context context, String repo) {
|
||||||
requestSwap(context, Uri.parse(repo));
|
requestSwap(context, Uri.parse(repo));
|
||||||
}
|
}
|
||||||
@ -201,7 +202,11 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
((FDroidApp) getApplication()).setSecureWindow(this);
|
FDroidApp fdroidApp = (FDroidApp) getApplication();
|
||||||
|
fdroidApp.setSecureWindow(this);
|
||||||
|
|
||||||
|
fdroidApp.applyPureBlackBackgroundInDarkTheme(this);
|
||||||
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
currentView = new SwapView(this); // dummy placeholder to avoid NullPointerExceptions;
|
currentView = new SwapView(this); // dummy placeholder to avoid NullPointerExceptions;
|
||||||
@ -214,8 +219,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
setContentView(R.layout.swap_activity);
|
setContentView(R.layout.swap_activity);
|
||||||
|
|
||||||
toolbar = (Toolbar) findViewById(R.id.toolbar);
|
toolbar = findViewById(R.id.toolbar);
|
||||||
toolbar.setTitleTextAppearance(getApplicationContext(), R.style.SwapTheme_Wizard_Text_Toolbar);
|
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
|
|
||||||
container = (ViewGroup) findViewById(R.id.container);
|
container = (ViewGroup) findViewById(R.id.container);
|
||||||
@ -234,6 +238,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDestroy() {
|
protected void onDestroy() {
|
||||||
|
compositeDisposable.dispose();
|
||||||
localBroadcastManager.unregisterReceiver(downloaderInterruptedReceiver);
|
localBroadcastManager.unregisterReceiver(downloaderInterruptedReceiver);
|
||||||
unbindService(serviceConnection);
|
unbindService(serviceConnection);
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
@ -494,9 +499,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
|||||||
currentView.setLayoutResId(viewRes);
|
currentView.setLayoutResId(viewRes);
|
||||||
currentSwapViewLayoutRes = viewRes;
|
currentSwapViewLayoutRes = viewRes;
|
||||||
|
|
||||||
toolbar.setBackgroundColor(currentView.getToolbarColour());
|
|
||||||
toolbar.setTitle(currentView.getToolbarTitle());
|
toolbar.setTitle(currentView.getToolbarTitle());
|
||||||
toolbar.setNavigationIcon(R.drawable.ic_close_white_24dp);
|
|
||||||
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
|
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
@ -594,7 +597,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void sendFDroidApk() {
|
private void sendFDroidApk() {
|
||||||
((FDroidApp) getApplication()).sendViaBluetooth(this, Activity.RESULT_OK, BuildConfig.APPLICATION_ID);
|
((FDroidApp) getApplication()).sendViaBluetooth(this, AppCompatActivity.RESULT_OK, BuildConfig.APPLICATION_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -776,7 +779,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
|||||||
private final BroadcastReceiver bluetoothScanModeChanged = new BroadcastReceiver() {
|
private final BroadcastReceiver bluetoothScanModeChanged = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
SwitchCompat bluetoothSwitch = container.findViewById(R.id.switch_bluetooth);
|
SwitchMaterial bluetoothSwitch = container.findViewById(R.id.switch_bluetooth);
|
||||||
TextView textBluetoothVisible = container.findViewById(R.id.bluetooth_visible);
|
TextView textBluetoothVisible = container.findViewById(R.id.bluetooth_visible);
|
||||||
if (bluetoothSwitch == null || textBluetoothVisible == null
|
if (bluetoothSwitch == null || textBluetoothVisible == null
|
||||||
|| !BluetoothManager.ACTION_STATUS.equals(intent.getAction())) {
|
|| !BluetoothManager.ACTION_STATUS.equals(intent.getAction())) {
|
||||||
@ -930,18 +933,23 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
|||||||
ImageView qrImage = container.findViewById(R.id.wifi_qr_code);
|
ImageView qrImage = container.findViewById(R.id.wifi_qr_code);
|
||||||
if (qrUriString != null && qrImage != null) {
|
if (qrUriString != null && qrImage != null) {
|
||||||
Utils.debugLog(TAG, "Encoded swap URI in QR Code: " + qrUriString);
|
Utils.debugLog(TAG, "Encoded swap URI in QR Code: " + qrUriString);
|
||||||
new QrGenAsyncTask(SwapWorkflowActivity.this, R.id.wifi_qr_code).execute(qrUriString);
|
|
||||||
|
|
||||||
// Replace all blacks with the background blue.
|
compositeDisposable.add(Utils.generateQrBitmap(this, qrUriString)
|
||||||
qrImage.setColorFilter(new LightingColorFilter(0xffffffff, ContextCompat.getColor(this,
|
.subscribe(qrBitmap -> {
|
||||||
R.color.swap_blue)));
|
qrImage.setImageBitmap(qrBitmap);
|
||||||
|
|
||||||
final View qrWarningMessage = container.findViewById(R.id.warning_qr_scanner);
|
// Replace all blacks with the background blue.
|
||||||
if (CameraCharacteristicsChecker.getInstance(this).hasAutofocus()) {
|
qrImage.setColorFilter(new LightingColorFilter(0xffffffff,
|
||||||
qrWarningMessage.setVisibility(View.GONE);
|
ContextCompat.getColor(this, R.color.swap_blue)));
|
||||||
} else {
|
|
||||||
qrWarningMessage.setVisibility(View.VISIBLE);
|
final View qrWarningMessage = container.findViewById(R.id.warning_qr_scanner);
|
||||||
}
|
if (CameraCharacteristicsChecker.getInstance(this).hasAutofocus()) {
|
||||||
|
qrWarningMessage.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
qrWarningMessage.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -988,7 +996,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
SwitchCompat wifiSwitch = findViewById(R.id.switch_wifi);
|
SwitchMaterial wifiSwitch = findViewById(R.id.switch_wifi);
|
||||||
wifiSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
wifiSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||||
@ -1112,7 +1120,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
|
|||||||
private final BroadcastReceiver bluetoothStatus = new BroadcastReceiver() {
|
private final BroadcastReceiver bluetoothStatus = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
SwitchCompat bluetoothSwitch = container.findViewById(R.id.switch_bluetooth);
|
SwitchMaterial bluetoothSwitch = container.findViewById(R.id.switch_bluetooth);
|
||||||
TextView textBluetoothVisible = container.findViewById(R.id.bluetooth_visible);
|
TextView textBluetoothVisible = container.findViewById(R.id.bluetooth_visible);
|
||||||
TextView textDeviceIdBluetooth = container.findViewById(R.id.device_id_bluetooth);
|
TextView textDeviceIdBluetooth = container.findViewById(R.id.device_id_bluetooth);
|
||||||
TextView peopleNearbyText = container.findViewById(R.id.text_people_nearby);
|
TextView peopleNearbyText = container.findViewById(R.id.text_people_nearby);
|
||||||
|
@ -29,7 +29,7 @@ import android.os.Build;
|
|||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import androidx.documentfile.provider.DocumentFile;
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.fdroid.fdroid.AddRepoIntentService;
|
import org.fdroid.fdroid.AddRepoIntentService;
|
||||||
@ -49,6 +49,8 @@ import java.util.jar.JarEntry;
|
|||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
import java.util.jar.JarInputStream;
|
import java.util.jar.JarInputStream;
|
||||||
|
|
||||||
|
import androidx.documentfile.provider.DocumentFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link IntentService} subclass for handling asynchronous scanning of a
|
* An {@link IntentService} subclass for handling asynchronous scanning of a
|
||||||
* removable storage device like an SD Card or USB OTG thumb drive using the
|
* removable storage device like an SD Card or USB OTG thumb drive using the
|
||||||
|
@ -8,13 +8,13 @@ import android.os.Build;
|
|||||||
import android.os.storage.StorageManager;
|
import android.os.storage.StorageManager;
|
||||||
import android.provider.DocumentsContract;
|
import android.provider.DocumentsContract;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see <a href="https://stackoverflow.com/a/36162691">Android 5.0 DocumentFile from tree URI</a>
|
* @see <a href="https://stackoverflow.com/a/36162691">Android 5.0 DocumentFile from tree URI</a>
|
||||||
|
@ -31,9 +31,11 @@ import android.os.Build;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
import org.fdroid.fdroid.views.main.NearbyViewBinder;
|
import org.fdroid.fdroid.views.main.NearbyViewBinder;
|
||||||
|
|
||||||
|
import androidx.annotation.RequiresApi;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is just a shim to receive {@link UsbManager#ACTION_USB_ACCESSORY_ATTACHED}
|
* This is just a shim to receive {@link UsbManager#ACTION_USB_ACCESSORY_ATTACHED}
|
||||||
|
@ -29,11 +29,13 @@ import android.net.Uri;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
import org.fdroid.fdroid.views.main.NearbyViewBinder;
|
import org.fdroid.fdroid.views.main.NearbyViewBinder;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import androidx.annotation.RequiresApi;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is just a shim to receive {@link UsbManager#ACTION_USB_DEVICE_DETACHED}
|
* This is just a shim to receive {@link UsbManager#ACTION_USB_DEVICE_DETACHED}
|
||||||
* events.
|
* events.
|
||||||
|
@ -4,6 +4,7 @@ import android.content.BroadcastReceiver;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
|
|
||||||
import org.fdroid.fdroid.views.main.NearbyViewBinder;
|
import org.fdroid.fdroid.views.main.NearbyViewBinder;
|
||||||
|
|
||||||
public class UsbDeviceMediaMountedReceiver extends BroadcastReceiver {
|
public class UsbDeviceMediaMountedReceiver extends BroadcastReceiver {
|
||||||
|
@ -4,6 +4,7 @@ import android.content.BroadcastReceiver;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
|
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
|
|
||||||
public class WifiStateChangeReceiver extends BroadcastReceiver {
|
public class WifiStateChangeReceiver extends BroadcastReceiver {
|
||||||
|
@ -10,12 +10,13 @@ import android.net.wifi.WifiConfiguration;
|
|||||||
import android.net.wifi.WifiInfo;
|
import android.net.wifi.WifiInfo;
|
||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Log;
|
|
||||||
import cc.mvdan.accesspoint.WifiApControl;
|
|
||||||
import org.apache.commons.net.util.SubnetUtils;
|
import org.apache.commons.net.util.SubnetUtils;
|
||||||
import org.fdroid.fdroid.BuildConfig;
|
import org.fdroid.fdroid.BuildConfig;
|
||||||
import org.fdroid.fdroid.FDroidApp;
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
@ -34,6 +35,9 @@ import java.security.cert.Certificate;
|
|||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import cc.mvdan.accesspoint.WifiApControl;
|
||||||
|
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle state changes to the device's wifi, storing the required bits.
|
* Handle state changes to the device's wifi, storing the required bits.
|
||||||
* The {@link Intent} that starts it either has no extras included,
|
* The {@link Intent} that starts it either has no extras included,
|
||||||
@ -68,6 +72,8 @@ public class WifiStateChangeService extends IntentService {
|
|||||||
private static int previousWifiState = Integer.MIN_VALUE;
|
private static int previousWifiState = Integer.MIN_VALUE;
|
||||||
private static int wifiState;
|
private static int wifiState;
|
||||||
|
|
||||||
|
private final CompositeDisposable compositeDisposable = new CompositeDisposable();
|
||||||
|
|
||||||
public WifiStateChangeService() {
|
public WifiStateChangeService() {
|
||||||
super("WifiStateChangeService");
|
super("WifiStateChangeService");
|
||||||
}
|
}
|
||||||
@ -80,6 +86,12 @@ public class WifiStateChangeService extends IntentService {
|
|||||||
context.startService(intent);
|
context.startService(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
compositeDisposable.dispose();
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onHandleIntent(Intent intent) {
|
protected void onHandleIntent(Intent intent) {
|
||||||
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_LOWEST);
|
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_LOWEST);
|
||||||
@ -107,7 +119,7 @@ public class WifiStateChangeService extends IntentService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT < 21 && wifiState == WifiManager.WIFI_STATE_ENABLED) {
|
if (Build.VERSION.SDK_INT < 21 && wifiState == WifiManager.WIFI_STATE_ENABLED) {
|
||||||
UpdateService.scheduleIfStillOnWifi(this);
|
compositeDisposable.add(UpdateService.scheduleIfStillOnWifi(this).subscribe());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,10 @@ import android.bluetooth.BluetoothDevice;
|
|||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
public class BluetoothPeer implements Peer {
|
public class BluetoothPeer implements Peer {
|
||||||
|
|
||||||
private static final String BLUETOOTH_NAME_TAG = "FDroid:";
|
private static final String BLUETOOTH_NAME_TAG = "FDroid:";
|
||||||
|
@ -2,13 +2,15 @@ package org.fdroid.fdroid.nearby.peers;
|
|||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import org.fdroid.fdroid.FDroidApp;
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
|
|
||||||
import javax.jmdns.ServiceInfo;
|
import javax.jmdns.ServiceInfo;
|
||||||
import javax.jmdns.impl.FDroidServiceInfo;
|
import javax.jmdns.impl.FDroidServiceInfo;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
public class BonjourPeer extends WifiPeer {
|
public class BonjourPeer extends WifiPeer {
|
||||||
private static final String TAG = "BonjourPeer";
|
private static final String TAG = "BonjourPeer";
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.fdroid.fdroid.nearby.peers;
|
package org.fdroid.fdroid.nearby.peers;
|
||||||
|
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes;
|
import androidx.annotation.DrawableRes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,7 +63,7 @@ public class WifiPeer implements Peer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getIcon() {
|
public int getIcon() {
|
||||||
return R.drawable.ic_network_wifi;
|
return R.drawable.ic_wifi;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,17 +1,21 @@
|
|||||||
package org.fdroid.fdroid.panic;
|
package org.fdroid.fdroid.panic;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.appcompat.widget.Toolbar;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.google.android.material.appbar.MaterialToolbar;
|
||||||
|
|
||||||
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A very hacky calculator which is barely functional.
|
* A very hacky calculator which is barely functional.
|
||||||
* It is just meant to pass a very casual inspection.
|
* It is just meant to pass a very casual inspection.
|
||||||
@ -35,10 +39,13 @@ public class CalculatorActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
FDroidApp fdroidApp = (FDroidApp) getApplication();
|
||||||
|
fdroidApp.applyPureBlackBackgroundInDarkTheme(this);
|
||||||
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_calculator);
|
setContentView(R.layout.activity_calculator);
|
||||||
|
|
||||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
MaterialToolbar toolbar = findViewById(R.id.toolbar);
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
|
|
||||||
textView = (TextView) findViewById(R.id.textView);
|
textView = (TextView) findViewById(R.id.textView);
|
||||||
|
@ -3,13 +3,13 @@ package org.fdroid.fdroid.panic;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
|
import org.fdroid.fdroid.R;
|
||||||
|
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.preference.CheckBoxPreference;
|
import androidx.preference.CheckBoxPreference;
|
||||||
import androidx.preference.PreferenceViewHolder;
|
import androidx.preference.PreferenceViewHolder;
|
||||||
|
|
||||||
import org.fdroid.fdroid.FDroidApp;
|
|
||||||
import org.fdroid.fdroid.R;
|
|
||||||
|
|
||||||
public class DestructiveCheckBoxPreference extends CheckBoxPreference {
|
public class DestructiveCheckBoxPreference extends CheckBoxPreference {
|
||||||
public DestructiveCheckBoxPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
public DestructiveCheckBoxPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
super(context, attrs, defStyleAttr);
|
super(context, attrs, defStyleAttr);
|
||||||
|
@ -3,13 +3,13 @@ package org.fdroid.fdroid.panic;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
|
import org.fdroid.fdroid.R;
|
||||||
|
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.PreferenceViewHolder;
|
import androidx.preference.PreferenceViewHolder;
|
||||||
|
|
||||||
import org.fdroid.fdroid.FDroidApp;
|
|
||||||
import org.fdroid.fdroid.R;
|
|
||||||
|
|
||||||
public class DestructivePreference extends Preference {
|
public class DestructivePreference extends Preference {
|
||||||
public DestructivePreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
public DestructivePreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
super(context, attrs, defStyleAttr);
|
super(context, attrs, defStyleAttr);
|
||||||
|
@ -3,6 +3,7 @@ package org.fdroid.fdroid.panic;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
public class ExitActivity extends AppCompatActivity {
|
public class ExitActivity extends AppCompatActivity {
|
||||||
|
@ -7,12 +7,14 @@ import android.content.Intent;
|
|||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ServiceInfo;
|
import android.content.pm.ServiceInfo;
|
||||||
import androidx.core.app.NotificationManagerCompat;
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import org.fdroid.fdroid.BuildConfig;
|
import org.fdroid.fdroid.BuildConfig;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.views.main.MainActivity;
|
import org.fdroid.fdroid.views.main.MainActivity;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.core.app.NotificationManagerCompat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is encapsulating all methods related to hiding the app from the launcher
|
* This class is encapsulating all methods related to hiding the app from the launcher
|
||||||
* and restoring it.
|
* and restoring it.
|
||||||
|
@ -1,37 +1,32 @@
|
|||||||
package org.fdroid.fdroid.panic;
|
package org.fdroid.fdroid.panic;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import androidx.appcompat.app.ActionBar;
|
import android.view.View;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import com.google.android.material.appbar.MaterialToolbar;
|
||||||
import android.view.MenuItem;
|
|
||||||
import org.fdroid.fdroid.FDroidApp;
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
public class PanicPreferencesActivity extends AppCompatActivity {
|
public class PanicPreferencesActivity extends AppCompatActivity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle bundle) {
|
public void onCreate(Bundle bundle) {
|
||||||
((FDroidApp) getApplication()).applyTheme(this);
|
FDroidApp fdroidApp = (FDroidApp) getApplication();
|
||||||
|
fdroidApp.applyPureBlackBackgroundInDarkTheme(this);
|
||||||
|
|
||||||
super.onCreate(bundle);
|
super.onCreate(bundle);
|
||||||
setContentView(R.layout.activity_panic_settings);
|
setContentView(R.layout.activity_panic_settings);
|
||||||
|
|
||||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
MaterialToolbar toolbar = findViewById(R.id.toolbar);
|
||||||
setSupportActionBar(toolbar);
|
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
|
||||||
ActionBar ab = getSupportActionBar();
|
@Override
|
||||||
if (ab != null) {
|
public void onClick(View view) {
|
||||||
ab.setDisplayShowHomeEnabled(true);
|
// Handle navigation icon press
|
||||||
ab.setDisplayHomeAsUpEnabled(true);
|
onBackPressed();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
if (item.getItemId() == android.R.id.home) {
|
|
||||||
onBackPressed();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package org.fdroid.fdroid.panic;
|
package org.fdroid.fdroid.panic;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@ -16,16 +15,6 @@ import android.os.Bundle;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
|
|
||||||
import androidx.annotation.ColorInt;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.preference.CheckBoxPreference;
|
|
||||||
import androidx.preference.ListPreference;
|
|
||||||
import androidx.preference.Preference;
|
|
||||||
import androidx.preference.PreferenceCategory;
|
|
||||||
import androidx.preference.PreferenceFragmentCompat;
|
|
||||||
|
|
||||||
import org.fdroid.fdroid.Preferences;
|
import org.fdroid.fdroid.Preferences;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.installer.PrivilegedInstaller;
|
import org.fdroid.fdroid.installer.PrivilegedInstaller;
|
||||||
@ -33,6 +22,16 @@ import org.fdroid.fdroid.installer.PrivilegedInstaller;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import androidx.annotation.ColorInt;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.preference.CheckBoxPreference;
|
||||||
|
import androidx.preference.ListPreference;
|
||||||
|
import androidx.preference.Preference;
|
||||||
|
import androidx.preference.PreferenceCategory;
|
||||||
|
import androidx.preference.PreferenceFragmentCompat;
|
||||||
import info.guardianproject.panic.Panic;
|
import info.guardianproject.panic.Panic;
|
||||||
import info.guardianproject.panic.PanicResponder;
|
import info.guardianproject.panic.PanicResponder;
|
||||||
|
|
||||||
@ -83,7 +82,7 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
|||||||
prefHide.setEnabled(false);
|
prefHide.setEnabled(false);
|
||||||
prefResetRepos.setChecked(false);
|
prefResetRepos.setChecked(false);
|
||||||
prefResetRepos.setEnabled(false);
|
prefResetRepos.setEnabled(false);
|
||||||
getActivity().setResult(Activity.RESULT_CANCELED);
|
getActivity().setResult(AppCompatActivity.RESULT_CANCELED);
|
||||||
} else {
|
} else {
|
||||||
prefHide.setEnabled(true);
|
prefHide.setEnabled(true);
|
||||||
prefResetRepos.setEnabled(true);
|
prefResetRepos.setEnabled(true);
|
||||||
@ -235,13 +234,13 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
|
|||||||
public void onClick(DialogInterface dialogInterface, int i) {
|
public void onClick(DialogInterface dialogInterface, int i) {
|
||||||
PanicResponder.setTriggerPackageName(getActivity());
|
PanicResponder.setTriggerPackageName(getActivity());
|
||||||
showPanicApp(PanicResponder.getTriggerPackageName(getActivity()));
|
showPanicApp(PanicResponder.getTriggerPackageName(getActivity()));
|
||||||
getActivity().setResult(Activity.RESULT_OK);
|
getActivity().setResult(AppCompatActivity.RESULT_OK);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
DialogInterface.OnClickListener cancelListener = new DialogInterface.OnClickListener() {
|
DialogInterface.OnClickListener cancelListener = new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialogInterface, int i) {
|
public void onClick(DialogInterface dialogInterface, int i) {
|
||||||
getActivity().setResult(Activity.RESULT_CANCELED);
|
getActivity().setResult(AppCompatActivity.RESULT_CANCELED);
|
||||||
getActivity().finish();
|
getActivity().finish();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,17 +1,13 @@
|
|||||||
package org.fdroid.fdroid.panic;
|
package org.fdroid.fdroid.panic;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import info.guardianproject.panic.Panic;
|
|
||||||
import info.guardianproject.panic.PanicResponder;
|
|
||||||
import org.fdroid.fdroid.Preferences;
|
import org.fdroid.fdroid.Preferences;
|
||||||
import org.fdroid.fdroid.data.Apk;
|
import org.fdroid.fdroid.data.Apk;
|
||||||
import org.fdroid.fdroid.data.DBHelper;
|
import org.fdroid.fdroid.data.DBHelper;
|
||||||
@ -31,16 +27,21 @@ import java.util.List;
|
|||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||||
|
import info.guardianproject.panic.Panic;
|
||||||
|
import info.guardianproject.panic.PanicResponder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This {@link Activity} is purely to run events in response to a panic trigger.
|
* This {@link AppCompatActivity} is purely to run events in response to a panic trigger.
|
||||||
* It needs to be an {@code Activity} rather than a {@link android.app.Service}
|
* It needs to be an {@code AppCompatActivity} rather than a {@link android.app.Service}
|
||||||
* so that it can fetch some of the required information about what sent the
|
* so that it can fetch some of the required information about what sent the
|
||||||
* {@link Intent}. This is therefore an {@code Activity} without any UI, which
|
* {@link Intent}. This is therefore an {@code AppCompatActivity} without any UI, which
|
||||||
* is a special case in Android. All the code must be in
|
* is a special case in Android. All the code must be in
|
||||||
* {@link #onCreate(Bundle)} and {@link #finish()} must be called at the end of
|
* {@link #onCreate(Bundle)} and {@link #finish()} must be called at the end of
|
||||||
* that method.
|
* that method.
|
||||||
*
|
*
|
||||||
* @see PanicResponder#receivedTriggerFromConnectedApp(Activity)
|
* @see PanicResponder#receivedTriggerFromConnectedApp(AppCompatActivity)
|
||||||
*/
|
*/
|
||||||
public class PanicResponderActivity extends AppCompatActivity {
|
public class PanicResponderActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
package org.fdroid.fdroid.panic;
|
package org.fdroid.fdroid.panic;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import org.fdroid.fdroid.Preferences;
|
import org.fdroid.fdroid.Preferences;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.views.installed.InstalledAppListAdapter;
|
import org.fdroid.fdroid.views.installed.InstalledAppListAdapter;
|
||||||
@ -11,10 +10,13 @@ import org.fdroid.fdroid.views.installed.InstalledAppListItemController;
|
|||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
public class SelectInstalledAppListAdapter extends InstalledAppListAdapter {
|
public class SelectInstalledAppListAdapter extends InstalledAppListAdapter {
|
||||||
private final Set<String> selectedApps;
|
private final Set<String> selectedApps;
|
||||||
|
|
||||||
SelectInstalledAppListAdapter(Activity activity) {
|
SelectInstalledAppListAdapter(AppCompatActivity activity) {
|
||||||
super(activity);
|
super(activity);
|
||||||
Preferences prefs = Preferences.get();
|
Preferences prefs = Preferences.get();
|
||||||
selectedApps = prefs.getPanicWipeSet();
|
selectedApps = prefs.getPanicWipeSet();
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
package org.fdroid.fdroid.panic;
|
package org.fdroid.fdroid.panic;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import org.fdroid.fdroid.AppUpdateStatusManager;
|
import org.fdroid.fdroid.AppUpdateStatusManager;
|
||||||
import org.fdroid.fdroid.data.App;
|
import org.fdroid.fdroid.data.App;
|
||||||
import org.fdroid.fdroid.views.apps.AppListItemState;
|
import org.fdroid.fdroid.views.apps.AppListItemState;
|
||||||
@ -11,6 +9,10 @@ import org.fdroid.fdroid.views.installed.InstalledAppListItemController;
|
|||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the currently installed apps as a selectable list.
|
* Shows the currently installed apps as a selectable list.
|
||||||
*/
|
*/
|
||||||
@ -18,7 +20,7 @@ public class SelectInstalledAppListItemController extends InstalledAppListItemCo
|
|||||||
|
|
||||||
private final Set<String> selectedApps;
|
private final Set<String> selectedApps;
|
||||||
|
|
||||||
public SelectInstalledAppListItemController(Activity activity, View itemView, Set<String> selectedApps) {
|
public SelectInstalledAppListItemController(AppCompatActivity activity, View itemView, Set<String> selectedApps) {
|
||||||
super(activity, itemView);
|
super(activity, itemView);
|
||||||
this.selectedApps = selectedApps;
|
this.selectedApps = selectedApps;
|
||||||
}
|
}
|
||||||
|
@ -21,23 +21,13 @@ package org.fdroid.fdroid.panic;
|
|||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.graphics.LightingColorFilter;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import com.google.android.material.appbar.MaterialToolbar;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.appcompat.widget.Toolbar;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.loader.app.LoaderManager;
|
|
||||||
import androidx.loader.content.CursorLoader;
|
|
||||||
import androidx.loader.content.Loader;
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import org.fdroid.fdroid.FDroidApp;
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
import org.fdroid.fdroid.Preferences;
|
import org.fdroid.fdroid.Preferences;
|
||||||
@ -45,6 +35,14 @@ import org.fdroid.fdroid.R;
|
|||||||
import org.fdroid.fdroid.data.InstalledAppProvider;
|
import org.fdroid.fdroid.data.InstalledAppProvider;
|
||||||
import org.fdroid.fdroid.views.installed.InstalledAppListAdapter;
|
import org.fdroid.fdroid.views.installed.InstalledAppListAdapter;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.loader.app.LoaderManager;
|
||||||
|
import androidx.loader.content.CursorLoader;
|
||||||
|
import androidx.loader.content.Loader;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
public class SelectInstalledAppsActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> {
|
public class SelectInstalledAppsActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> {
|
||||||
|
|
||||||
private InstalledAppListAdapter adapter;
|
private InstalledAppListAdapter adapter;
|
||||||
@ -56,13 +54,14 @@ public class SelectInstalledAppsActivity extends AppCompatActivity implements Lo
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
FDroidApp fdroidApp = (FDroidApp) getApplication();
|
||||||
|
fdroidApp.applyPureBlackBackgroundInDarkTheme(this);
|
||||||
|
|
||||||
((FDroidApp) getApplication()).applyTheme(this);
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
setContentView(R.layout.installed_apps_layout);
|
setContentView(R.layout.installed_apps_layout);
|
||||||
|
|
||||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
MaterialToolbar toolbar = findViewById(R.id.toolbar);
|
||||||
toolbar.setTitle(getString(R.string.panic_add_apps_to_uninstall));
|
toolbar.setTitle(getString(R.string.panic_add_apps_to_uninstall));
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
@ -117,14 +116,7 @@ public class SelectInstalledAppsActivity extends AppCompatActivity implements Lo
|
|||||||
MenuItem menuItem = menu.add(R.string.menu_select_for_wipe);
|
MenuItem menuItem = menu.add(R.string.menu_select_for_wipe);
|
||||||
menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||||
checkId = menuItem.getItemId();
|
checkId = menuItem.getItemId();
|
||||||
if (FDroidApp.isAppThemeLight()) {
|
menuItem.setIcon(R.drawable.check);
|
||||||
Drawable icon = ContextCompat.getDrawable(this, R.drawable.check);
|
|
||||||
icon.setColorFilter(new LightingColorFilter(0xffffffff, ContextCompat.getColor(this,
|
|
||||||
android.R.color.white)));
|
|
||||||
menuItem.setIcon(icon);
|
|
||||||
} else {
|
|
||||||
menuItem.setIcon(R.drawable.check);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,40 +3,44 @@ package org.fdroid.fdroid.views.main;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
|
||||||
import androidx.loader.app.LoaderManager;
|
|
||||||
import androidx.loader.content.CursorLoader;
|
|
||||||
import androidx.loader.content.Loader;
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||||
|
|
||||||
import org.fdroid.fdroid.Preferences;
|
import org.fdroid.fdroid.Preferences;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.UpdateService;
|
import org.fdroid.fdroid.UpdateService;
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
import org.fdroid.fdroid.data.CategoryProvider;
|
import org.fdroid.fdroid.data.CategoryProvider;
|
||||||
import org.fdroid.fdroid.data.Schema;
|
import org.fdroid.fdroid.data.Schema;
|
||||||
|
import org.fdroid.fdroid.panic.HidingManager;
|
||||||
import org.fdroid.fdroid.views.apps.AppListActivity;
|
import org.fdroid.fdroid.views.apps.AppListActivity;
|
||||||
import org.fdroid.fdroid.views.categories.CategoryAdapter;
|
import org.fdroid.fdroid.views.categories.CategoryAdapter;
|
||||||
import org.fdroid.fdroid.views.categories.CategoryController;
|
import org.fdroid.fdroid.views.categories.CategoryController;
|
||||||
import org.fdroid.fdroid.panic.HidingManager;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.loader.app.LoaderManager;
|
||||||
|
import androidx.loader.content.CursorLoader;
|
||||||
|
import androidx.loader.content.Loader;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responsible for ensuring that the categories view is inflated and then populated correctly.
|
* Responsible for ensuring that the categories view is inflated and then populated correctly.
|
||||||
* Will start a loader to get the list of categories from the database and populate a recycler
|
* Will start a loader to get the list of categories from the database and populate a recycler
|
||||||
* view with relevant info about each.
|
* view with relevant info about each.
|
||||||
*/
|
*/
|
||||||
class CategoriesViewBinder implements LoaderManager.LoaderCallbacks<Cursor> {
|
class CategoriesViewBinder implements LoaderManager.LoaderCallbacks<Cursor> {
|
||||||
|
public static final String TAG = "CategoriesViewBinder";
|
||||||
|
|
||||||
private static final int LOADER_ID = 429820532;
|
private static final int LOADER_ID = 429820532;
|
||||||
|
|
||||||
@ -92,10 +96,11 @@ class CategoriesViewBinder implements LoaderManager.LoaderCallbacks<Cursor> {
|
|||||||
activity.getSupportLoaderManager().restartLoader(LOADER_ID, null, this);
|
activity.getSupportLoaderManager().restartLoader(LOADER_ID, null, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
||||||
if (id != LOADER_ID) {
|
if (id != LOADER_ID) {
|
||||||
return null;
|
throw new IllegalArgumentException("id != LOADER_ID");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CursorLoader(
|
return new CursorLoader(
|
||||||
@ -110,7 +115,7 @@ class CategoriesViewBinder implements LoaderManager.LoaderCallbacks<Cursor> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads all categories from the cursor and stores them in memory to provide to the {@link CategoryAdapter}.
|
* Reads all categories from the cursor and stores them in memory to provide to the {@link CategoryAdapter}.
|
||||||
*
|
* <p>
|
||||||
* It does this so it is easier to deal with localized/unlocalized categories without having
|
* It does this so it is easier to deal with localized/unlocalized categories without having
|
||||||
* to store the localized version in the database. It is not expected that the list of categories
|
* to store the localized version in the database. It is not expected that the list of categories
|
||||||
* will grow so large as to make this a performance concern. If it does in the future, the
|
* will grow so large as to make this a performance concern. If it does in the future, the
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
package org.fdroid.fdroid.views.main;
|
package org.fdroid.fdroid.views.main;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.views.PreferencesFragment;
|
import org.fdroid.fdroid.views.PreferencesFragment;
|
||||||
import org.fdroid.fdroid.views.updates.UpdatesViewBinder;
|
import org.fdroid.fdroid.views.updates.UpdatesViewBinder;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decides which view on the main screen to attach to a given {@link FrameLayout}. This class
|
* Decides which view on the main screen to attach to a given {@link FrameLayout}. This class
|
||||||
* doesn't know which view it will be rendering at the time it is constructed. Rather, at some
|
* doesn't know which view it will be rendering at the time it is constructed. Rather, at some
|
||||||
@ -30,10 +32,10 @@ class MainViewController extends RecyclerView.ViewHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see WhatsNewViewBinder
|
* @see LatestViewBinder
|
||||||
*/
|
*/
|
||||||
public void bindWhatsNewView() {
|
public void bindLatestView() {
|
||||||
new WhatsNewViewBinder(activity, frame);
|
new LatestViewBinder(activity, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package org.fdroid.fdroid.views.main;
|
package org.fdroid.fdroid.views.main;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.UriPermission;
|
import android.content.UriPermission;
|
||||||
@ -22,9 +21,7 @@ import android.widget.FrameLayout;
|
|||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
import androidx.core.app.ActivityCompat;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
import org.fdroid.fdroid.nearby.SDCardScannerService;
|
import org.fdroid.fdroid.nearby.SDCardScannerService;
|
||||||
@ -34,6 +31,11 @@ import org.fdroid.fdroid.nearby.TreeUriScannerIntentService;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import androidx.annotation.RequiresApi;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.core.app.ActivityCompat;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A splash screen encouraging people to start the swap process. The swap
|
* A splash screen encouraging people to start the swap process. The swap
|
||||||
* process is quite heavy duty in that it fires up Bluetooth and/or WiFi
|
* process is quite heavy duty in that it fires up Bluetooth and/or WiFi
|
||||||
@ -69,7 +71,7 @@ public class NearbyViewBinder {
|
|||||||
private static File externalStorage = null;
|
private static File externalStorage = null;
|
||||||
private static View swapView;
|
private static View swapView;
|
||||||
|
|
||||||
NearbyViewBinder(final Activity activity, FrameLayout parent) {
|
NearbyViewBinder(final AppCompatActivity activity, FrameLayout parent) {
|
||||||
swapView = activity.getLayoutInflater().inflate(R.layout.main_tab_swap, parent, true);
|
swapView = activity.getLayoutInflater().inflate(R.layout.main_tab_swap, parent, true);
|
||||||
|
|
||||||
TextView subtext = swapView.findViewById(R.id.both_parties_need_fdroid_text);
|
TextView subtext = swapView.findViewById(R.id.both_parties_need_fdroid_text);
|
||||||
@ -213,11 +215,11 @@ public class NearbyViewBinder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Activity activity = null;
|
AppCompatActivity activity = null;
|
||||||
if (context instanceof Activity) {
|
if (context instanceof AppCompatActivity) {
|
||||||
activity = (Activity) context;
|
activity = (AppCompatActivity) context;
|
||||||
} else if (swapView != null && swapView.getContext() instanceof Activity) {
|
} else if (swapView != null && swapView.getContext() instanceof AppCompatActivity) {
|
||||||
activity = (Activity) swapView.getContext();
|
activity = (AppCompatActivity) swapView.getContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activity != null) {
|
if (activity != null) {
|
||||||
|
Before Width: | Height: | Size: 480 B |
Before Width: | Height: | Size: 111 B |
Before Width: | Height: | Size: 167 B |
Before Width: | Height: | Size: 377 B |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 3.0 KiB |
@ -1,8 +1,9 @@
|
|||||||
<!-- drawable/check.xml -->
|
<!-- drawable/check.xml -->
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24"
|
||||||
<path android:fillColor="#000" android:pathData="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z" />
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path android:fillColor="#000" android:pathData="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z" />
|
||||||
</vector>
|
</vector>
|
@ -1,5 +1,10 @@
|
|||||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:viewportHeight="24" android:viewportWidth="24"
|
android:width="24dp"
|
||||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
android:height="24dp"
|
||||||
<path android:fillColor="#FFFFFF" android:pathData="M13,7h-2v4L7,11v2h4v4h2v-4h4v-2h-4L13,7zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M12,7c-0.55,0 -1,0.45 -1,1v3L8,11c-0.55,0 -1,0.45 -1,1s0.45,1 1,1h3v3c0,0.55 0.45,1 1,1s1,-0.45 1,-1v-3h3c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1h-3L13,8c0,-0.55 -0.45,-1 -1,-1zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
<vector android:height="24dp" android:tint="?attr/colorControlNormal"
|
||||||
android:viewportHeight="24" android:viewportWidth="24"
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<path android:fillColor="#FFFFFF" android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z"/>
|
<path android:fillColor="#FFFFFF" android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z"/>
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:viewportHeight="24" android:viewportWidth="24"
|
android:width="24dp"
|
||||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
android:height="24dp"
|
||||||
<path android:fillColor="#FFFFFF" android:pathData="M17.71,7.71L12,2h-1v7.59L6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 11,14.41L11,22h1l5.71,-5.71 -4.3,-4.29 4.3,-4.29zM13,5.83l1.88,1.88L13,9.59L13,5.83zM14.88,16.29L13,18.17v-3.76l1.88,1.88z"/>
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M17,7l-4.29,-4.29c-0.63,-0.63 -1.71,-0.19 -1.71,0.7v6.18L7.11,5.7c-0.39,-0.39 -1.02,-0.39 -1.41,0 -0.39,0.39 -0.39,1.02 0,1.41L10.59,12 5.7,16.89c-0.39,0.39 -0.39,1.02 0,1.41 0.39,0.39 1.02,0.39 1.41,0L11,14.41v6.18c0,0.89 1.08,1.34 1.71,0.71L17,17c0.39,-0.39 0.39,-1.02 0,-1.41L13.41,12 17,8.42c0.39,-0.39 0.39,-1.03 0,-1.42zM13,5.83l1.88,1.88L13,9.59L13,5.83zM14.88,16.29L13,18.17v-3.76l1.88,1.88z"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
10
app/src/full/res/drawable/ic_bluetooth_searching.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M15.98,10.28l-1.38,1.38c-0.2,0.2 -0.2,0.51 0,0.71l1.38,1.38c0.28,0.28 0.75,0.15 0.85,-0.23 0.11,-0.5 0.17,-1 0.17,-1.52 0,-0.51 -0.06,-1.01 -0.18,-1.48 -0.09,-0.38 -0.56,-0.52 -0.84,-0.24zM20.1,7.78c-0.25,-0.55 -0.98,-0.67 -1.4,-0.24 -0.26,0.26 -0.31,0.64 -0.17,0.98 0.46,1.07 0.72,2.24 0.72,3.47 0,1.24 -0.26,2.42 -0.73,3.49 -0.14,0.32 -0.09,0.69 0.16,0.94 0.41,0.41 1.1,0.29 1.35,-0.23 0.63,-1.3 0.98,-2.76 0.98,-4.3 -0.01,-1.45 -0.33,-2.85 -0.91,-4.11zM11.41,12L15,8.42c0.39,-0.39 0.39,-1.02 0,-1.42l-4.29,-4.29c-0.63,-0.63 -1.71,-0.19 -1.71,0.7v6.18L5.11,5.7c-0.39,-0.39 -1.02,-0.39 -1.41,0 -0.39,0.39 -0.39,1.02 0,1.41L8.59,12 3.7,16.89c-0.39,0.39 -0.39,1.02 0,1.41 0.39,0.39 1.02,0.39 1.41,0L9,14.41v6.18c0,0.89 1.08,1.34 1.71,0.71L15,17c0.39,-0.39 0.39,-1.02 0,-1.42L11.41,12zM11,5.83l1.88,1.88L11,9.59L11,5.83zM11,18.17v-3.76l1.88,1.88L11,18.17z"/>
|
||||||
|
</vector>
|
@ -1,5 +0,0 @@
|
|||||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
|
||||||
android:viewportHeight="24" android:viewportWidth="24"
|
|
||||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<path android:fillColor="#FFFFFF" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"/>
|
|
||||||
</vector>
|
|
@ -1,18 +1,33 @@
|
|||||||
<vector android:height="24dp" android:viewportHeight="48.0"
|
<vector android:height="24dp"
|
||||||
android:viewportWidth="48.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
android:viewportHeight="48.0"
|
||||||
<path android:fillColor="#ffffff"
|
android:tint="?attr/colorControlNormal"
|
||||||
|
android:viewportWidth="48.0"
|
||||||
|
android:width="24dp"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
android:pathData="m22.75,12.78c-6.19,0 -11.22,5.03 -11.22,11.22 0,0.55 0.05,1.08 0.13,1.61 1.71,0.27 3.29,0.93 4.64,1.91 -0.57,-1.05 -0.9,-2.24 -0.9,-3.52 0,-4.05 3.3,-7.35 7.35,-7.35 4.05,0 7.35,3.3 7.35,7.35 0,4.05 -3.3,7.35 -7.35,7.35 -1.38,0 -2.66,-0.39 -3.77,-1.05 0.92,1.39 1.53,2.99 1.73,4.73 0.66,0.12 1.34,0.2 2.04,0.2 6.19,0 11.22,-5.03 11.22,-11.22 0,-6.19 -5.03,-11.22 -11.22,-11.22"
|
android:pathData="m22.75,12.78c-6.19,0 -11.22,5.03 -11.22,11.22 0,0.55 0.05,1.08 0.13,1.61 1.71,0.27 3.29,0.93 4.64,1.91 -0.57,-1.05 -0.9,-2.24 -0.9,-3.52 0,-4.05 3.3,-7.35 7.35,-7.35 4.05,0 7.35,3.3 7.35,7.35 0,4.05 -3.3,7.35 -7.35,7.35 -1.38,0 -2.66,-0.39 -3.77,-1.05 0.92,1.39 1.53,2.99 1.73,4.73 0.66,0.12 1.34,0.2 2.04,0.2 6.19,0 11.22,-5.03 11.22,-11.22 0,-6.19 -5.03,-11.22 -11.22,-11.22"
|
||||||
android:strokeColor="#00000000" android:strokeWidth="1"/>
|
android:strokeColor="#00000000"
|
||||||
<path android:fillColor="#ffffff"
|
android:strokeWidth="1" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
android:pathData="m42.28,25.4c-0.36,0 -0.71,-0.02 -1.06,-0.06 -0.69,9.6 -8.71,17.2 -18.48,17.2 -1.28,0 -2.53,-0.13 -3.74,-0.38 -0.83,1.26 -1.91,2.33 -3.18,3.15 2.18,0.71 4.5,1.1 6.91,1.1 12.03,0 21.87,-9.54 22.38,-21.45 -0.9,0.29 -1.85,0.44 -2.84,0.44"
|
android:pathData="m42.28,25.4c-0.36,0 -0.71,-0.02 -1.06,-0.06 -0.69,9.6 -8.71,17.2 -18.48,17.2 -1.28,0 -2.53,-0.13 -3.74,-0.38 -0.83,1.26 -1.91,2.33 -3.18,3.15 2.18,0.71 4.5,1.1 6.91,1.1 12.03,0 21.87,-9.54 22.38,-21.45 -0.9,0.29 -1.85,0.44 -2.84,0.44"
|
||||||
android:strokeColor="#00000000" android:strokeWidth="1"/>
|
android:strokeColor="#00000000"
|
||||||
<path android:fillColor="#ffffff"
|
android:strokeWidth="1" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
android:pathData="m42.28,10.64c-2.96,0 -5.36,2.41 -5.36,5.36 0,2.96 2.41,5.36 5.36,5.36 2.96,0 5.36,-2.41 5.36,-5.36 0,-2.96 -2.41,-5.36 -5.36,-5.36"
|
android:pathData="m42.28,10.64c-2.96,0 -5.36,2.41 -5.36,5.36 0,2.96 2.41,5.36 5.36,5.36 2.96,0 5.36,-2.41 5.36,-5.36 0,-2.96 -2.41,-5.36 -5.36,-5.36"
|
||||||
android:strokeColor="#00000000" android:strokeWidth="1"/>
|
android:strokeColor="#00000000"
|
||||||
<path android:fillColor="#ffffff"
|
android:strokeWidth="1" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
android:pathData="m10,29.5c-3.72,0 -6.75,3.03 -6.75,6.75 0,3.72 3.03,6.75 6.75,6.75 3.72,0 6.75,-3.03 6.75,-6.75 0,-3.72 -3.03,-6.75 -6.75,-6.75"
|
android:pathData="m10,29.5c-3.72,0 -6.75,3.03 -6.75,6.75 0,3.72 3.03,6.75 6.75,6.75 3.72,0 6.75,-3.03 6.75,-6.75 0,-3.72 -3.03,-6.75 -6.75,-6.75"
|
||||||
android:strokeColor="#00000000" android:strokeWidth="1"/>
|
android:strokeColor="#00000000"
|
||||||
<path android:fillAlpha="1" android:fillColor="#ffffff"
|
android:strokeWidth="1" />
|
||||||
|
<path
|
||||||
|
android:fillAlpha="1"
|
||||||
|
android:fillColor="#ffffff"
|
||||||
android:pathData="m4.47,27.01c-0.16,-0.98 -0.25,-1.98 -0.25,-3.01 0,-10.22 8.31,-18.53 18.53,-18.53 4.68,0 8.97,1.75 12.23,4.63C35.81,9.08 36.85,8.24 38.03,7.64 34.02,3.9 28.65,1.6 22.75,1.6 10.4,1.6 0.35,11.65 0.35,24c0,2.1 0.3,4.13 0.84,6.05 0.87,-1.23 1.99,-2.27 3.28,-3.04"
|
android:pathData="m4.47,27.01c-0.16,-0.98 -0.25,-1.98 -0.25,-3.01 0,-10.22 8.31,-18.53 18.53,-18.53 4.68,0 8.97,1.75 12.23,4.63C35.81,9.08 36.85,8.24 38.03,7.64 34.02,3.9 28.65,1.6 22.75,1.6 10.4,1.6 0.35,11.65 0.35,24c0,2.1 0.3,4.13 0.84,6.05 0.87,-1.23 1.99,-2.27 3.28,-3.04"
|
||||||
android:strokeColor="#00000000" android:strokeWidth="1"/>
|
android:strokeColor="#00000000"
|
||||||
|
android:strokeWidth="1" />
|
||||||
</vector>
|
</vector>
|
@ -1,5 +0,0 @@
|
|||||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
|
||||||
android:viewportHeight="24" android:viewportWidth="24"
|
|
||||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<path android:fillColor="#FFFFFF" android:pathData="M12.01,21.49L23.64,7c-0.45,-0.34 -4.93,-4 -11.64,-4C5.28,3 0.81,6.66 0.36,7l11.63,14.49 0.01,0.01 0.01,-0.01z"/>
|
|
||||||
</vector>
|
|
40
app/src/full/res/drawable/ic_qr_code.xml
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M5,11h4c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2H5C3.9,3 3,3.9 3,5v4C3,10.1 3.9,11 5,11zM5,5h4v4H5V5z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M5,21h4c1.1,0 2,-0.9 2,-2v-4c0,-1.1 -0.9,-2 -2,-2H5c-1.1,0 -2,0.9 -2,2v4C3,20.1 3.9,21 5,21zM5,15h4v4H5V15z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M13,5v4c0,1.1 0.9,2 2,2h4c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2h-4C13.9,3 13,3.9 13,5zM19,9h-4V5h4V9z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M21,20.5v-1c0,-0.28 -0.22,-0.5 -0.5,-0.5h-1c-0.28,0 -0.5,0.22 -0.5,0.5v1c0,0.28 0.22,0.5 0.5,0.5h1C20.78,21 21,20.78 21,20.5z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M13,13.5v1c0,0.28 0.22,0.5 0.5,0.5h1c0.28,0 0.5,-0.22 0.5,-0.5v-1c0,-0.28 -0.22,-0.5 -0.5,-0.5h-1C13.22,13 13,13.22 13,13.5z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M16.5,15h-1c-0.28,0 -0.5,0.22 -0.5,0.5v1c0,0.28 0.22,0.5 0.5,0.5h1c0.28,0 0.5,-0.22 0.5,-0.5v-1C17,15.22 16.78,15 16.5,15z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M13,17.5v1c0,0.28 0.22,0.5 0.5,0.5h1c0.28,0 0.5,-0.22 0.5,-0.5v-1c0,-0.28 -0.22,-0.5 -0.5,-0.5h-1C13.22,17 13,17.22 13,17.5z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M15.5,21h1c0.28,0 0.5,-0.22 0.5,-0.5v-1c0,-0.28 -0.22,-0.5 -0.5,-0.5h-1c-0.28,0 -0.5,0.22 -0.5,0.5v1C15,20.78 15.22,21 15.5,21z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M17.5,19h1c0.28,0 0.5,-0.22 0.5,-0.5v-1c0,-0.28 -0.22,-0.5 -0.5,-0.5h-1c-0.28,0 -0.5,0.22 -0.5,0.5v1C17,18.78 17.22,19 17.5,19z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M18.5,13h-1c-0.28,0 -0.5,0.22 -0.5,0.5v1c0,0.28 0.22,0.5 0.5,0.5h1c0.28,0 0.5,-0.22 0.5,-0.5v-1C19,13.22 18.78,13 18.5,13z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M19.5,17h1c0.28,0 0.5,-0.22 0.5,-0.5v-1c0,-0.28 -0.22,-0.5 -0.5,-0.5h-1c-0.28,0 -0.5,0.22 -0.5,0.5v1C19,16.78 19.22,17 19.5,17z"/>
|
||||||
|
</vector>
|
@ -1,5 +1,10 @@
|
|||||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:viewportHeight="24" android:viewportWidth="24"
|
android:width="24dp"
|
||||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
android:height="24dp"
|
||||||
<path android:fillColor="#FFFFFF" android:pathData="M1,9l2,2c4.97,-4.97 13.03,-4.97 18,0l2,-2C16.93,2.93 7.08,2.93 1,9zM9,17l3,3 3,-3c-1.65,-1.66 -4.34,-1.66 -6,0zM5,13l2,2c2.76,-2.76 7.24,-2.76 10,0l2,-2C15.14,9.14 8.87,9.14 5,13z"/>
|
android:tint="?attr/colorControlNormal"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M2.06,10.06c0.51,0.51 1.32,0.56 1.87,0.1 4.67,-3.84 11.45,-3.84 16.13,-0.01 0.56,0.46 1.38,0.42 1.89,-0.09 0.59,-0.59 0.55,-1.57 -0.1,-2.1 -5.71,-4.67 -13.97,-4.67 -19.69,0 -0.65,0.52 -0.7,1.5 -0.1,2.1zM9.82,17.82l1.47,1.47c0.39,0.39 1.02,0.39 1.41,0l1.47,-1.47c0.47,-0.47 0.37,-1.28 -0.23,-1.59 -1.22,-0.63 -2.68,-0.63 -3.91,0 -0.57,0.31 -0.68,1.12 -0.21,1.59zM6.09,14.09c0.49,0.49 1.26,0.54 1.83,0.13 2.44,-1.73 5.72,-1.73 8.16,0 0.57,0.4 1.34,0.36 1.83,-0.13l0.01,-0.01c0.6,-0.6 0.56,-1.62 -0.13,-2.11 -3.44,-2.49 -8.13,-2.49 -11.58,0 -0.69,0.5 -0.73,1.51 -0.12,2.12z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:viewportHeight="24" android:viewportWidth="24"
|
android:width="24dp"
|
||||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
android:height="24dp"
|
||||||
<path android:fillColor="#FFFFFF" android:pathData="M12,11c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM18,13c0,-3.31 -2.69,-6 -6,-6s-6,2.69 -6,6c0,2.22 1.21,4.15 3,5.19l1,-1.74c-1.19,-0.7 -2,-1.97 -2,-3.45 0,-2.21 1.79,-4 4,-4s4,1.79 4,4c0,1.48 -0.81,2.75 -2,3.45l1,1.74c1.79,-1.04 3,-2.97 3,-5.19zM12,3C6.48,3 2,7.48 2,13c0,3.7 2.01,6.92 4.99,8.65l1,-1.73C5.61,18.53 4,15.96 4,13c0,-4.42 3.58,-8 8,-8s8,3.58 8,8c0,2.96 -1.61,5.53 -4,6.92l1,1.73c2.99,-1.73 5,-4.95 5,-8.65 0,-5.52 -4.48,-10 -10,-10z"/>
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M12,11c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM18,13c0,-3.56 -3.11,-6.4 -6.75,-5.95 -2.62,0.32 -4.78,2.41 -5.18,5.02 -0.33,2.15 0.49,4.11 1.93,5.4 0.48,0.43 1.23,0.33 1.56,-0.23l0.01,-0.01c0.24,-0.42 0.14,-0.93 -0.22,-1.26 -1.03,-0.93 -1.59,-2.37 -1.22,-3.94 0.33,-1.42 1.48,-2.57 2.9,-2.91C13.65,8.49 16,10.47 16,13c0,1.18 -0.52,2.23 -1.33,2.96 -0.36,0.32 -0.47,0.84 -0.23,1.26l0.01,0.01c0.31,0.53 1.03,0.69 1.5,0.28C17.2,16.41 18,14.8 18,13zM10.83,3.07c-4.62,0.52 -8.35,4.33 -8.78,8.96 -0.35,3.7 1.32,7.02 4.02,9.01 0.48,0.35 1.16,0.2 1.46,-0.31 0.25,-0.43 0.14,-0.99 -0.26,-1.29 -2.28,-1.69 -3.65,-4.55 -3.16,-7.7 0.54,-3.5 3.46,-6.29 6.98,-6.68C15.91,4.51 20,8.28 20,13c0,2.65 -1.29,4.98 -3.27,6.44 -0.4,0.3 -0.51,0.85 -0.26,1.29 0.3,0.52 0.98,0.66 1.46,0.31C20.4,19.22 22,16.3 22,13c0,-5.91 -5.13,-10.62 -11.17,-9.93z"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/header"
|
android:id="@+id/header"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="130dp"
|
android:layout_height="130dp"
|
||||||
@ -12,7 +13,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
android:src="@drawable/swap_start_header"/>
|
app:srcCompat="@drawable/swap_start_header"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -1,78 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
Copyright (C) 2010 The Android Open Source Project
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
|
||||||
android:paddingBottom="2dip"
|
|
||||||
android:paddingTop="2dip">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@android:id/icon"
|
|
||||||
android:layout_width="48dip"
|
|
||||||
android:layout_height="48dip"
|
|
||||||
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
|
|
||||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
|
||||||
android:layout_marginTop="6dip"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
tools:src="@drawable/ic_launcher"
|
|
||||||
tools:ignore="ContentDescription" />
|
|
||||||
|
|
||||||
<!-- Suppress InconsistentLayout because the lower API levels use a checkbox rather than this -->
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/checked"
|
|
||||||
android:layout_width="32dip"
|
|
||||||
android:layout_height="32dip"
|
|
||||||
android:layout_marginRight="?attr/listPreferredItemPaddingLeft"
|
|
||||||
android:layout_marginEnd="?android:attr/listPreferredItemPaddingStart"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
tools:suppress="InconsistentLayout"
|
|
||||||
android:src="@drawable/ic_add_circle_outline" />
|
|
||||||
|
|
||||||
<TwoLineListItem
|
|
||||||
android:layout_toRightOf="@android:id/icon"
|
|
||||||
android:layout_toEndOf="@android:id/icon"
|
|
||||||
android:layout_toLeftOf="@id/checked"
|
|
||||||
android:layout_toStartOf="@id/checked"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:mode="twoLine" >
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/application_label"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
|
|
||||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
|
||||||
android:layout_marginTop="6dip"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
|
||||||
tools:text="F-Droid" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/package_name"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignStart="@+id/application_label"
|
|
||||||
android:layout_alignLeft="@+id/application_label"
|
|
||||||
android:layout_below="@+id/application_label"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
|
||||||
tools:text="Application Manager" />
|
|
||||||
</TwoLineListItem>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
@ -1,70 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
Copyright (C) 2010 The Android Open Source Project
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
|
||||||
android:paddingBottom="2dip"
|
|
||||||
android:paddingTop="2dip">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@android:id/icon"
|
|
||||||
android:layout_width="48dip"
|
|
||||||
android:layout_height="48dip"
|
|
||||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
|
||||||
android:layout_marginTop="6dip"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
tools:src="@drawable/ic_launcher"
|
|
||||||
tools:ignore="ContentDescription" />
|
|
||||||
|
|
||||||
<!-- Suppress InconsistentLayout because the lower API levels use a checkbox rather than this -->
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/checked"
|
|
||||||
android:layout_width="32dip"
|
|
||||||
android:layout_height="32dip"
|
|
||||||
android:layout_marginEnd="?android:attr/listPreferredItemPaddingStart"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
tools:suppress="InconsistentLayout"
|
|
||||||
android:src="@drawable/ic_add_circle_outline" />
|
|
||||||
|
|
||||||
<TwoLineListItem
|
|
||||||
android:layout_toEndOf="@android:id/icon"
|
|
||||||
android:layout_toStartOf="@id/checked"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:mode="twoLine" >
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/application_label"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
|
||||||
android:layout_marginTop="6dip"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
|
||||||
tools:text="F-Droid" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/package_name"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignStart="@+id/application_label"
|
|
||||||
android:layout_below="@+id/application_label"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
|
||||||
tools:text="Application Manager" />
|
|
||||||
</TwoLineListItem>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
@ -1,291 +1,302 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_height="match_parent"
|
|
||||||
tools:context=".panic.CalculatorActivity">
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
|
||||||
android:id="@+id/toolbar"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:background="?attr/colorPrimary"
|
tools:context=".panic.CalculatorActivity"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
android:fitsSystemWindows="true">
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
app:theme="?attr/actionBarTheme" />
|
android:id="@+id/topAppBarLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
app:liftOnScroll="true"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
app:navigationIcon="@drawable/ic_back"
|
||||||
|
style="@style/Widget.MaterialComponents.Toolbar.PrimarySurface" />
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/textView"
|
android:id="@+id/textView"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:gravity="bottom|end"
|
android:gravity="bottom|end"
|
||||||
android:padding="5dp"
|
android:padding="5dp"
|
||||||
android:textAlignment="textEnd"
|
android:textAlignment="textEnd"
|
||||||
android:textSize="22sp"
|
android:textSize="22sp"
|
||||||
android:typeface="monospace"
|
android:typeface="monospace"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/ce"
|
app:layout_constraintBottom_toTopOf="@+id/ce"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/toolbar"
|
app:layout_constraintTop_toBottomOf="@+id/topAppBarLayout"
|
||||||
tools:text="1337+42" />
|
tools:text="1337+42" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/times"
|
android:id="@+id/times"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:onClick="op"
|
android:onClick="op"
|
||||||
android:text="×"
|
android:text="×"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/seven"
|
app:layout_constraintBottom_toTopOf="@+id/seven"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/divided"
|
android:id="@+id/divided"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:onClick="op"
|
android:onClick="op"
|
||||||
android:text="÷"
|
android:text="÷"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/eight"
|
app:layout_constraintBottom_toTopOf="@+id/eight"
|
||||||
app:layout_constraintStart_toEndOf="@+id/times"
|
app:layout_constraintStart_toEndOf="@+id/times"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/c"
|
android:id="@+id/c"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:onClick="c"
|
android:onClick="c"
|
||||||
android:text="C"
|
android:text="C"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/nine"
|
app:layout_constraintBottom_toTopOf="@+id/nine"
|
||||||
app:layout_constraintStart_toEndOf="@+id/divided"
|
app:layout_constraintStart_toEndOf="@+id/divided"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/seven"
|
android:id="@+id/seven"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:onClick="number"
|
android:onClick="number"
|
||||||
android:text="7"
|
android:text="7"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/four"
|
app:layout_constraintBottom_toTopOf="@+id/four"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/eight"
|
android:id="@+id/eight"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:onClick="number"
|
android:onClick="number"
|
||||||
android:text="8"
|
android:text="8"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/five"
|
app:layout_constraintBottom_toTopOf="@+id/five"
|
||||||
app:layout_constraintStart_toEndOf="@+id/seven"
|
app:layout_constraintStart_toEndOf="@+id/seven"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/nine"
|
android:id="@+id/nine"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:onClick="number"
|
android:onClick="number"
|
||||||
android:text="9"
|
android:text="9"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/six"
|
app:layout_constraintBottom_toTopOf="@+id/six"
|
||||||
app:layout_constraintStart_toEndOf="@+id/eight"
|
app:layout_constraintStart_toEndOf="@+id/eight"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/ce"
|
android:id="@+id/ce"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:onClick="ce"
|
android:onClick="ce"
|
||||||
android:text="CE"
|
android:text="CE"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/plus"
|
app:layout_constraintBottom_toTopOf="@+id/plus"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/nine"
|
app:layout_constraintStart_toEndOf="@+id/nine"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/four"
|
android:id="@+id/four"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:onClick="number"
|
android:onClick="number"
|
||||||
android:text="4"
|
android:text="4"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/one"
|
app:layout_constraintBottom_toTopOf="@+id/one"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/five"
|
android:id="@+id/five"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:onClick="number"
|
android:onClick="number"
|
||||||
android:text="5"
|
android:text="5"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/two"
|
app:layout_constraintBottom_toTopOf="@+id/two"
|
||||||
app:layout_constraintStart_toEndOf="@+id/four"
|
app:layout_constraintStart_toEndOf="@+id/four"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/six"
|
android:id="@+id/six"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:onClick="number"
|
android:onClick="number"
|
||||||
android:text="6"
|
android:text="6"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/three"
|
app:layout_constraintBottom_toTopOf="@+id/three"
|
||||||
app:layout_constraintStart_toEndOf="@+id/five"
|
app:layout_constraintStart_toEndOf="@+id/five"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/plus"
|
android:id="@+id/plus"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:onClick="op"
|
android:onClick="op"
|
||||||
android:text="+"
|
android:text="+"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/minus"
|
app:layout_constraintBottom_toTopOf="@+id/minus"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/six"
|
app:layout_constraintStart_toEndOf="@+id/six"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/minus"
|
android:id="@+id/minus"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:onClick="op"
|
android:onClick="op"
|
||||||
android:text="-"
|
android:text="-"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/equals"
|
app:layout_constraintBottom_toTopOf="@+id/equals"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/three"
|
app:layout_constraintStart_toEndOf="@+id/three"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/one"
|
android:id="@+id/one"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:onClick="number"
|
android:onClick="number"
|
||||||
android:text="1"
|
android:text="1"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/zero"
|
app:layout_constraintBottom_toTopOf="@+id/zero"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/two"
|
android:id="@+id/two"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:onClick="number"
|
android:onClick="number"
|
||||||
android:text="2"
|
android:text="2"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/comma"
|
app:layout_constraintBottom_toTopOf="@+id/comma"
|
||||||
app:layout_constraintStart_toEndOf="@+id/one"
|
app:layout_constraintStart_toEndOf="@+id/one"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/three"
|
android:id="@+id/three"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:onClick="number"
|
android:onClick="number"
|
||||||
android:text="3"
|
android:text="3"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/percent"
|
app:layout_constraintBottom_toTopOf="@+id/percent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/two"
|
app:layout_constraintStart_toEndOf="@+id/two"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/zero"
|
android:id="@+id/zero"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:onClick="number"
|
android:onClick="number"
|
||||||
android:text="0"
|
android:text="0"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/comma"
|
android:id="@+id/comma"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:onClick="number"
|
android:onClick="number"
|
||||||
android:text="."
|
android:text="."
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/zero"
|
app:layout_constraintStart_toEndOf="@+id/zero"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/percent"
|
android:id="@+id/percent"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:onClick="op"
|
android:onClick="op"
|
||||||
android:text="%"
|
android:text="%"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/comma"
|
app:layout_constraintStart_toEndOf="@+id/comma"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/equals"
|
android:id="@+id/equals"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:onClick="op"
|
android:onClick="op"
|
||||||
android:text="="
|
android:text="="
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintHorizontal_bias="0.0"
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
app:layout_constraintStart_toEndOf="@+id/three"
|
app:layout_constraintStart_toEndOf="@+id/three"
|
||||||
app:layout_constraintTop_toTopOf="@+id/three"
|
app:layout_constraintTop_toTopOf="@+id/three"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
@ -1,21 +1,32 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
|
||||||
android:id="@+id/toolbar"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:background="?attr/colorPrimary"
|
android:orientation="vertical"
|
||||||
app:theme="?attr/actionBarTheme" />
|
android:fitsSystemWindows="true">
|
||||||
|
|
||||||
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
android:id="@+id/fragment_container"
|
android:layout_width="match_parent"
|
||||||
class="org.fdroid.fdroid.panic.PanicPreferencesFragment"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="match_parent"
|
android:fitsSystemWindows="true"
|
||||||
android:layout_height="match_parent" />
|
app:liftOnScroll="true">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
app:title="@string/panic_settings"
|
||||||
|
app:navigationIcon="@drawable/ic_back"
|
||||||
|
style="@style/Widget.MaterialComponents.Toolbar.PrimarySurface" />
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/fragment_container"
|
||||||
|
class="org.fdroid.fdroid.panic.PanicPreferencesFragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:fitsSystemWindows="true">
|
||||||
|
|
||||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -16,7 +17,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<org.fdroid.fdroid.views.BannerUpdatingRepos
|
<org.fdroid.fdroid.views.StatusBanner
|
||||||
android:id="@+id/banner_updating_repos"
|
android:id="@+id/banner_updating_repos"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -11,14 +11,14 @@
|
|||||||
android:id="@+id/image"
|
android:id="@+id/image"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:src="@drawable/nearby_splash"
|
app:srcCompat="@drawable/nearby_splash"
|
||||||
android:importantForAccessibility="no"
|
android:importantForAccessibility="no"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/both_parties_need_fdroid_text"
|
app:layout_constraintTop_toBottomOf="@+id/both_parties_need_fdroid_text"
|
||||||
android:layout_marginTop="36dp"
|
android:layout_marginTop="36dp"
|
||||||
android:tint="?attr/mainTabSwapSplashTint"
|
app:tint="?attr/mainTabSwapSplashTint"
|
||||||
android:scaleType="fitXY"
|
android:scaleType="fitXY"
|
||||||
tools:targetApi="jelly_bean"/>
|
tools:targetApi="jelly_bean"/>
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
android:minHeight="?attr/listPreferredItemHeight"
|
||||||
android:paddingBottom="2dip"
|
android:paddingBottom="2dip"
|
||||||
android:paddingTop="2dip">
|
android:paddingTop="2dip">
|
||||||
|
|
||||||
@ -25,10 +25,9 @@
|
|||||||
android:layout_width="48dip"
|
android:layout_width="48dip"
|
||||||
android:layout_height="48dip"
|
android:layout_height="48dip"
|
||||||
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
|
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
|
||||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
android:layout_marginStart="?attr/listPreferredItemPaddingStart"
|
||||||
android:layout_marginTop="6dip"
|
android:layout_marginTop="6dip"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
tools:src="@drawable/ic_launcher"
|
tools:src="@drawable/ic_launcher"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
@ -37,15 +36,13 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
|
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
|
||||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
android:layout_marginStart="?attr/listPreferredItemPaddingStart"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
android:layout_centerVertical="true" />
|
android:layout_centerVertical="true" />
|
||||||
|
|
||||||
<TwoLineListItem
|
<TwoLineListItem
|
||||||
android:layout_toRightOf="@android:id/icon"
|
|
||||||
android:layout_toEndOf="@android:id/icon"
|
android:layout_toEndOf="@android:id/icon"
|
||||||
android:layout_toLeftOf="@id/checkbox"
|
|
||||||
android:layout_toStartOf="@id/checkbox"
|
android:layout_toStartOf="@id/checkbox"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -56,7 +53,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
|
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
|
||||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
android:layout_marginStart="?attr/listPreferredItemPaddingStart"
|
||||||
android:layout_marginTop="6dip"
|
android:layout_marginTop="6dip"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
tools:text="F-Droid" />
|
tools:text="F-Droid" />
|
||||||
@ -66,7 +63,6 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignStart="@+id/application_label"
|
android:layout_alignStart="@+id/application_label"
|
||||||
android:layout_alignLeft="@+id/application_label"
|
|
||||||
android:layout_below="@+id/application_label"
|
android:layout_below="@+id/application_label"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
tools:text="Application Manager" />
|
tools:text="Application Manager" />
|
||||||
|
@ -1,24 +1,29 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:orientation="vertical"
|
||||||
<androidx.appcompat.widget.Toolbar
|
android:fitsSystemWindows="true">
|
||||||
android:id="@+id/toolbar"
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:titleTextAppearance="@style/SwapTheme.Wizard.Text"
|
android:layout_height="wrap_content"
|
||||||
titleTextAppearance="@style/SwapTheme.Wizard.Text"
|
android:fitsSystemWindows="true"
|
||||||
android:minHeight="?attr/actionBarSize"
|
app:liftOnScroll="true">
|
||||||
android:background="?attr/colorPrimary"
|
|
||||||
tools:ignore="UnusedAttribute"/>
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
app:navigationIcon="@drawable/ic_back"
|
||||||
|
style="@style/Widget.MaterialComponents.Toolbar.PrimarySurface" />
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/container"
|
android:id="@+id/container"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="fill_parent"/>
|
android:layout_height="fill_parent" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
@ -4,7 +4,7 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
android:minHeight="?attr/listPreferredItemHeight"
|
||||||
android:paddingBottom="2dip"
|
android:paddingBottom="2dip"
|
||||||
android:paddingTop="2dip">
|
android:paddingTop="2dip">
|
||||||
|
|
||||||
@ -12,7 +12,7 @@
|
|||||||
android:id="@android:id/icon"
|
android:id="@android:id/icon"
|
||||||
android:layout_width="48dip"
|
android:layout_width="48dip"
|
||||||
android:layout_height="48dip"
|
android:layout_height="48dip"
|
||||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
android:layout_marginStart="?attr/listPreferredItemPaddingStart"
|
||||||
android:layout_marginLeft="10dp"
|
android:layout_marginLeft="10dp"
|
||||||
android:layout_marginTop="6dip"
|
android:layout_marginTop="6dip"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
@ -28,7 +28,7 @@
|
|||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:gravity="end"
|
android:gravity="end"
|
||||||
android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
|
android:layout_marginEnd="?attr/listPreferredItemPaddingEnd"
|
||||||
android:layout_marginRight="10dp">
|
android:layout_marginRight="10dp">
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
@ -68,7 +68,7 @@
|
|||||||
android:layout_toLeftOf="@+id/button_or_text"
|
android:layout_toLeftOf="@+id/button_or_text"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
android:layout_marginStart="?attr/listPreferredItemPaddingStart"
|
||||||
android:layout_marginLeft="10dp"
|
android:layout_marginLeft="10dp"
|
||||||
android:layout_marginTop="6dip"
|
android:layout_marginTop="6dip"
|
||||||
android:layout_marginBottom="6dip"
|
android:layout_marginBottom="6dip"
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/icon"
|
android:id="@+id/icon"
|
||||||
android:src="@drawable/ic_launcher"
|
swap:srcCompat="@drawable/ic_launcher"
|
||||||
android:contentDescription="@string/icon"
|
android:contentDescription="@string/icon"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_width="117.6dp"
|
android:layout_width="117.6dp"
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/wifi_icon"
|
android:id="@+id/wifi_icon"
|
||||||
android:src="@drawable/ic_wifi"
|
swap:srcCompat="@drawable/ic_wifi"
|
||||||
android:layout_below="@+id/text_description"
|
android:layout_below="@+id/text_description"
|
||||||
android:layout_centerHorizontal="true"/>
|
android:layout_centerHorizontal="true"/>
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/icon_nfc"
|
android:id="@+id/icon_nfc"
|
||||||
android:src="@drawable/nfc_touch"
|
swap:srcCompat="@drawable/nfc_touch"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_centerHorizontal="true"/>
|
android:layout_centerHorizontal="true"/>
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/listPreferredItemHeight"
|
android:layout_height="?attr/listPreferredItemHeight"
|
||||||
@ -13,14 +14,14 @@
|
|||||||
android:layout_width="32dp"
|
android:layout_width="32dp"
|
||||||
android:layout_height="32dp"
|
android:layout_height="32dp"
|
||||||
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
|
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
|
||||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
android:layout_marginStart="?attr/listPreferredItemPaddingStart"
|
||||||
android:layout_gravity="center_vertical">
|
android:layout_gravity="center_vertical">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:src="@drawable/circle"
|
app:srcCompat="@drawable/circle"
|
||||||
android:tint="@color/swap_light_grey_icon"/>
|
app:tint="@color/swap_light_grey_icon"/>
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/icon"
|
android:id="@+id/icon"
|
||||||
@ -37,7 +38,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
|
android:layout_marginLeft="?attr/listPreferredItemPaddingLeft"
|
||||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
android:layout_marginStart="?attr/listPreferredItemPaddingStart"
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
tools:text="Nexus 4"/>
|
tools:text="Nexus 4"/>
|
||||||
|
@ -25,9 +25,8 @@
|
|||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:tint="@color/swap_grey_icon"
|
|
||||||
android:contentDescription="@string/use_bluetooth"
|
android:contentDescription="@string/use_bluetooth"
|
||||||
android:src="@drawable/ic_bluetooth"/>
|
swap:srcCompat="@drawable/ic_bluetooth_searching"/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
@ -54,7 +53,7 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<androidx.appcompat.widget.SwitchCompat
|
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:enabled="false"
|
android:enabled="false"
|
||||||
@ -74,9 +73,8 @@
|
|||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:tint="@color/swap_grey_icon"
|
|
||||||
android:contentDescription="@string/wifi"
|
android:contentDescription="@string/wifi"
|
||||||
android:src="@drawable/ic_network_wifi"/>
|
swap:srcCompat="@drawable/ic_wifi"/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
@ -112,7 +110,7 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<androidx.appcompat.widget.SwitchCompat
|
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/switch_wifi"/>
|
android:id="@+id/switch_wifi"/>
|
||||||
@ -156,32 +154,20 @@
|
|||||||
android:layout_alignParentBottom="true">
|
android:layout_alignParentBottom="true">
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/btn_send_fdroid"
|
android:id="@+id/btn_send_fdroid"
|
||||||
android:layout_width="wrap_content"
|
style="@style/Widget.App.Button.TextButton"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:drawableLeft="@drawable/ic_fdroid_grey"
|
swap:icon="@drawable/ic_fdroid_grey"
|
||||||
android:drawableStart="@drawable/ic_fdroid_grey"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/swap_send_fdroid"
|
android:text="@string/swap_send_fdroid" />
|
||||||
android:drawablePadding="10dp"
|
|
||||||
android:paddingLeft="25dp"
|
|
||||||
android:paddingRight="25dp"
|
|
||||||
android:paddingStart="25dp"
|
|
||||||
android:paddingEnd="25dp"
|
|
||||||
android:background="@android:color/transparent"/>
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/btn_scan_qr"
|
android:id="@+id/btn_scan_qr"
|
||||||
android:layout_width="wrap_content"
|
style="@style/Widget.App.Button.TextButton"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:drawableLeft="@drawable/ic_qr_grey"
|
android:layout_height="wrap_content"
|
||||||
android:drawableStart="@drawable/ic_qr_grey"
|
android:text="@string/swap_scan_qr"
|
||||||
android:text="@string/swap_scan_qr"
|
swap:icon="@drawable/ic_qr_code" />
|
||||||
android:drawablePadding="10dp"
|
|
||||||
android:paddingLeft="25dp"
|
|
||||||
android:paddingRight="25dp"
|
|
||||||
android:paddingStart="25dp"
|
|
||||||
android:paddingEnd="25dp"
|
|
||||||
android:background="@android:color/transparent"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -1,22 +1,42 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
tools:ignore="MenuTitle">
|
tools:ignore="MenuTitle">
|
||||||
<!-- android:title and android:icon are set dynamically in MainActivity -->
|
<!-- android:title and android:icon are set dynamically in MainActivity -->
|
||||||
<item
|
<item
|
||||||
app:showAsAction="ifRoom|withText"
|
android:id="@+id/latest"
|
||||||
android:id="@+id/whats_new"/>
|
android:enabled="true"
|
||||||
|
android:icon="@drawable/ic_latest"
|
||||||
|
android:orderInCategory="0"
|
||||||
|
android:title="@string/main_menu__latest_apps"
|
||||||
|
app:showAsAction="ifRoom|withText" />
|
||||||
<item
|
<item
|
||||||
app:showAsAction="ifRoom|withText"
|
android:id="@+id/categories"
|
||||||
android:id="@+id/categories"/>
|
android:enabled="true"
|
||||||
|
android:icon="@drawable/ic_categories"
|
||||||
|
android:orderInCategory="1"
|
||||||
|
android:title="@string/main_menu__categories"
|
||||||
|
app:showAsAction="ifRoom|withText" />
|
||||||
<item
|
<item
|
||||||
app:showAsAction="ifRoom|withText"
|
android:id="@+id/nearby"
|
||||||
android:id="@+id/nearby"/>
|
android:enabled="true"
|
||||||
|
android:icon="@drawable/ic_nearby"
|
||||||
|
android:orderInCategory="2"
|
||||||
|
android:title="@string/main_menu__swap_nearby"
|
||||||
|
app:showAsAction="ifRoom|withText" />
|
||||||
<item
|
<item
|
||||||
app:showAsAction="ifRoom|withText"
|
android:id="@+id/updates"
|
||||||
android:id="@+id/updates"/>
|
android:enabled="true"
|
||||||
|
android:icon="@drawable/ic_updates"
|
||||||
|
android:orderInCategory="3"
|
||||||
|
android:title="@string/main_menu__updates"
|
||||||
|
app:showAsAction="ifRoom|withText" />
|
||||||
<item
|
<item
|
||||||
app:showAsAction="ifRoom|withText"
|
android:id="@+id/settings"
|
||||||
android:id="@+id/settings"/>
|
android:enabled="true"
|
||||||
|
android:icon="@drawable/ic_settings"
|
||||||
|
android:orderInCategory="4"
|
||||||
|
android:title="@string/menu_settings"
|
||||||
|
app:showAsAction="ifRoom|withText" />
|
||||||
</menu>
|
</menu>
|