Compare commits
859 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
bbb6f939ba | ||
|
edbf7d74e9 | ||
|
a93d1ce4bc | ||
|
733727c478 | ||
|
a2b4715f5c | ||
|
8a6d42477e | ||
|
7cd8d5f66f | ||
|
57302f6689 | ||
|
d34c0474b8 | ||
|
2144f32b65 | ||
|
a83ffff1e0 | ||
|
3c37a8a22f | ||
|
46f56742cd | ||
|
33a1b5542e | ||
|
8a0c8bb569 | ||
|
7b7e55853d | ||
|
7c41ec2e42 | ||
|
e5f96a7a9e | ||
|
e773058e6a | ||
|
44773ffc75 | ||
|
edfbc5a77a | ||
|
7d677a9fe2 | ||
|
5ea03be8d6 | ||
|
4c7dd797f2 | ||
|
cd45e0ba95 | ||
|
679e39c019 | ||
|
5a975b2843 | ||
|
cdcb26b2de | ||
|
3c889b8727 | ||
|
0fcd5e1b90 | ||
|
874444e8eb | ||
|
b9a78a0262 | ||
|
a8479b59bf | ||
|
fa56c85969 | ||
|
fd592fb39e | ||
|
ba24fa7fed | ||
|
d4cd898a05 | ||
|
cda7c306c8 | ||
|
989946263d | ||
|
3233007191 | ||
|
6364bccfba | ||
|
130b45a901 | ||
|
90358e07f7 | ||
|
2b18901a97 | ||
|
3834633d78 | ||
|
74b74d1265 | ||
|
18982eed14 | ||
|
8f7ce34a02 | ||
|
8f6cec4501 | ||
|
b5f144cb16 | ||
|
802fc1b68d | ||
|
8765a0bbbf | ||
|
e60e1d5805 | ||
|
904c9fe870 | ||
|
eb58db193d | ||
|
cc49a6e828 | ||
|
c5cd46cdef | ||
|
4da04c6cb3 | ||
|
f16702b7c2 | ||
|
c2a2afaa88 | ||
|
02967d3640 | ||
|
9be7af764d | ||
|
14063ef66a | ||
|
769425ab94 | ||
|
8566985222 | ||
|
8e91e061ef | ||
|
fb19382fd2 | ||
|
68ea2f80a3 | ||
|
8d2a1bab74 | ||
|
a5a9c7967d | ||
|
2bae3bcc93 | ||
|
f25b6ea1e3 | ||
|
c652d1a6e6 | ||
|
2450a74c32 | ||
|
10cbe87f51 | ||
|
c0a6f565c7 | ||
|
eac20f4094 | ||
|
873678d1ec | ||
|
7a446f3243 | ||
|
c7605ede18 | ||
|
1a1a88bd44 | ||
|
010db03f37 | ||
|
24f3bba827 | ||
|
fbfb72acdf | ||
|
237c695922 | ||
|
22218bb556 | ||
|
c25ebc819a | ||
|
8d29a90222 | ||
|
a056d07cdc | ||
|
b0353c3de9 | ||
|
577ac531ee | ||
|
a373de0b5d | ||
|
72ff4c0d21 | ||
|
18b3380cdc | ||
|
c1aa168642 | ||
|
534d4b5a3f | ||
|
9e8733e4f6 | ||
|
e000f06939 | ||
|
2658f9ca62 | ||
|
083fc202c7 | ||
|
0c36ff37ac | ||
|
106b615201 | ||
|
8040bd9b43 | ||
|
ddc837e580 | ||
|
e19b1048c5 | ||
|
30cfebaf87 | ||
|
95e6c294ae | ||
|
10acdd47f8 | ||
|
fe052f0fdc | ||
|
63b8c9c512 | ||
|
98698068b1 | ||
|
7101e5e714 | ||
|
7d8867da60 | ||
|
df68852fd5 | ||
|
72bb1858a6 | ||
|
6f56028b00 | ||
|
7a851a1684 | ||
|
527c6f535c | ||
|
1cb7a81a47 | ||
|
93f83c216a | ||
|
80ec02b767 | ||
|
5309e46d58 | ||
|
b61d82fe1e | ||
|
0c6d16063c | ||
|
74dd4b33a4 | ||
|
f0d6588c07 | ||
|
8302493940 | ||
|
fc5241d6f9 | ||
|
65e3c246d7 | ||
|
5ddf363b20 | ||
|
dbe2543fcf | ||
|
3dd9acddc7 | ||
|
0a9d1cc191 | ||
|
643203c874 | ||
|
5fe15716ee | ||
|
599fe53515 | ||
|
8a87e4d63a | ||
|
ffd5119c98 | ||
|
11409cbead | ||
|
78f3d79630 | ||
|
6687f92346 | ||
|
2836ac6869 | ||
|
59acbd9ef5 | ||
|
fcbaf713f3 | ||
|
e515419d63 | ||
|
17374d2183 | ||
|
915617d79a | ||
|
786ee2b842 | ||
|
a3d804325f | ||
|
991bde7231 | ||
|
58205cc06c | ||
|
c07dabf789 | ||
|
bd8b23f1e0 | ||
|
3b682e25d6 | ||
|
ea17951c0a | ||
|
b7e5690a81 | ||
|
eabab3be02 | ||
|
710e471811 | ||
|
7c2eef2e88 | ||
|
477e3f8319 | ||
|
f49f575971 | ||
|
0ceb01b2bd | ||
|
a240c1cbef | ||
|
29ff6635f2 | ||
|
a63d9599e1 | ||
|
5261961673 | ||
|
8adc71c413 | ||
|
3a0601d217 | ||
|
cb1c6fb71a | ||
|
2e287d4dcb | ||
|
64e26551a6 | ||
|
4ecf711a65 | ||
|
8e6e5b64e4 | ||
|
86ac855e9a | ||
|
aa530a204c | ||
|
bd0c9c0c97 | ||
|
00c2c6e8ea | ||
|
18650d4d7b | ||
|
3b23a320bc | ||
|
1a18eb48a1 | ||
|
4d17c9c5af | ||
|
07fb0e7a87 | ||
|
e2c8f185f5 | ||
|
c88c9bb5be | ||
|
dc04f5997b | ||
|
5e9bcc88ca | ||
|
b99951c444 | ||
|
353145693d | ||
|
c57f5237ed | ||
|
be3a183633 | ||
|
511e11e454 | ||
|
837a3effb1 | ||
|
739ac51931 | ||
|
1b58f45a9f | ||
|
e5f6719d22 | ||
|
151b1488d4 | ||
|
171890e507 | ||
|
6a4c2363e7 | ||
|
598f3413cf | ||
|
ec9729ebeb | ||
|
ab60df2369 | ||
|
e11bed3f31 | ||
|
02375e41c5 | ||
|
05380b2d39 | ||
|
c19248555d | ||
|
b0785093a9 | ||
|
5d244ca55a | ||
|
46327119f8 | ||
|
f682438980 | ||
|
dd09e43818 | ||
|
150284e27b | ||
|
f8b9665963 | ||
|
2aacbb13b5 | ||
|
e43a172079 | ||
|
d96b8a7875 | ||
|
478e3718fb | ||
|
3c19e328a2 | ||
|
c9ed554c6d | ||
|
5bc84f9e7f | ||
|
a6ee12a195 | ||
|
86d2dce73b | ||
|
236d348aba | ||
|
98daefe3df | ||
|
abce140b8f | ||
|
548e0d871f | ||
|
633901ea99 | ||
|
889e365e03 | ||
|
b1688dbfed | ||
|
93c954ec7c | ||
|
a7d74d4686 | ||
|
961c731f60 | ||
|
72702ab53e | ||
|
c199f6f60d | ||
|
dc41bf3798 | ||
|
53d9431c15 | ||
|
4d00647cc1 | ||
|
8130af570f | ||
|
fee8902acb | ||
|
333a31b056 | ||
|
48dca0fbb4 | ||
|
6c63d8f89b | ||
|
9bca7b4ca2 | ||
|
79a56e2ada | ||
|
859147b69b | ||
|
00850485e9 | ||
|
7bf6b842a0 | ||
|
6ad684b650 | ||
|
6554f343ae | ||
|
4fc26ff2d4 | ||
|
d15945c1ca | ||
|
8bf4ab7c93 | ||
|
600cb29c9c | ||
|
6840c982ca | ||
|
04b35c398d | ||
|
070a53167a | ||
|
badb5aaaa1 | ||
|
7e73e2336b | ||
|
598f1fcf9a | ||
|
13f164b867 | ||
|
0c5290118f | ||
|
58a4a7bc4e | ||
|
5bfbb005a5 | ||
|
ad2f7c10f7 | ||
|
82f43a885f | ||
|
76f2388f02 | ||
|
e6e1f1a721 | ||
|
961a760234 | ||
|
5ea297104c | ||
|
855de0f86e | ||
|
191fabbca4 | ||
|
d5149f729b | ||
|
5f5cc55259 | ||
|
50d4de987e | ||
|
584524a1c9 | ||
|
1730a48f23 | ||
|
9f4219bd68 | ||
|
3cdf1337f8 | ||
|
9a1f187058 | ||
|
b09f60cc4e | ||
|
9e5297f2aa | ||
|
080ad35048 | ||
|
c64745d885 | ||
|
f66e101e76 | ||
|
33a62654cb | ||
|
dc13d4a21c | ||
|
bbef52e03a | ||
|
812c801042 | ||
|
926182f997 | ||
|
f75a6d40f1 | ||
|
b3aca1c6b3 | ||
|
5a02dfa045 | ||
|
76f901c81f | ||
|
6a13d7ac83 | ||
|
f1e5df9e02 | ||
|
6bbd5da44f | ||
|
523603c1e3 | ||
|
f953e6cd09 | ||
|
123ce0adb3 | ||
|
7c14bff700 | ||
|
d92ed7d4b1 | ||
|
4f265773b8 | ||
|
da0082ccac | ||
|
363248f580 | ||
|
13a44da126 | ||
|
9409ca64e2 | ||
|
27942004b5 | ||
|
15aa29910d | ||
|
6ceee7b012 | ||
|
b5957f0c06 | ||
|
d4d7fce3e8 | ||
|
a7b33e58ac | ||
|
7d8db76067 | ||
|
5106432c2b | ||
|
42a2a55cae | ||
|
a9cf377063 | ||
|
bccfbae82c | ||
|
cfb605928d | ||
|
5cae31082b | ||
|
0cda521540 | ||
|
d26712cd89 | ||
|
a05a30b0e2 | ||
|
d9ca696db0 | ||
|
a81c5ad464 | ||
|
dc593807d4 | ||
|
3e5f5705d2 | ||
|
8a10e28a1a | ||
|
2e0ce0706d | ||
|
484c25dabe | ||
|
5fc47f03e8 | ||
|
b012971a8c | ||
|
816e975ca0 | ||
|
649c97d31e | ||
|
4f139906a5 | ||
|
1e206b55c8 | ||
|
5b184b0490 | ||
|
9847559732 | ||
|
ceea85925f | ||
|
e81ed347e7 | ||
|
32d6864e7c | ||
|
50683049fd | ||
|
edb117a020 | ||
|
1a89b1d5f1 | ||
|
67f60015ec | ||
|
90b651f3f1 | ||
|
55e17986a9 | ||
|
2b4a1ecf9a | ||
|
77ab787db7 | ||
|
d88836e7d2 | ||
|
f5147e1bc0 | ||
|
6bd1ce5ae9 | ||
|
58a753c921 | ||
|
3668bbff51 | ||
|
990de7450b | ||
|
6b9c825ed9 | ||
|
c4598208ac | ||
|
03d18ae1e2 | ||
|
3bb087663a | ||
|
a43e3f410c | ||
|
a836408cae | ||
|
e2e7ff783d | ||
|
201da17578 | ||
|
6e8a2d10b9 | ||
|
dfc9f81695 | ||
|
8d6b6b20e8 | ||
|
261da28edb | ||
|
7d00089898 | ||
|
ceefd6c5d7 | ||
|
54ba895d1d | ||
|
75eb21fb4a | ||
|
3243292a66 | ||
|
bc7d23970e | ||
|
28cfd0ce2a | ||
|
c50ce0e89c | ||
|
6594fee930 | ||
|
753505141f | ||
|
c2cbee5cef | ||
|
cf3c7da645 | ||
|
b500d02695 | ||
|
e5573e7f56 | ||
|
397a766663 | ||
|
b06b50a8be | ||
|
8a628abb29 | ||
|
cb2a8835d3 | ||
|
7b9f035cd0 | ||
|
96cdeaa2f0 | ||
|
92ef7cf592 | ||
|
3b8f63d419 | ||
|
c1fc5571bf | ||
|
f76798cb9e | ||
|
9ff749182b | ||
|
94818906ae | ||
|
9e597fb58c | ||
|
4a526730fa | ||
|
0bed763021 | ||
|
5c8ba4b370 | ||
|
77dd567593 | ||
|
7d017c9919 | ||
|
79cb5983a2 | ||
|
e1fad991a8 | ||
|
160688d06f | ||
|
449a6b2a81 | ||
|
15c9617a2b | ||
|
7af398786e | ||
|
99560474fb | ||
|
9a1b28cb6d | ||
|
ae910f363b | ||
|
dd9be98ac8 | ||
|
b1ab14f2b0 | ||
|
cf7611999c | ||
|
60ac0afbea | ||
|
a1db1d3c03 | ||
|
1451943e68 | ||
|
6d82702a8d | ||
|
f2348d0a46 | ||
|
95d2bfe8f9 | ||
|
61ed3d2791 | ||
|
8ad3b251b0 | ||
|
db2cc05a3a | ||
|
1f26787983 | ||
|
5d0b5d377b | ||
|
d57810b5d8 | ||
|
5317dc4fd9 | ||
|
62747ae33e | ||
|
a8fad0bd3f | ||
|
f099ca95d2 | ||
|
314016b5ca | ||
|
a7917c0b45 | ||
|
da2a42ba91 | ||
|
108c619fe7 | ||
|
59db354042 | ||
|
92930ec758 | ||
|
b877807f76 | ||
|
8acf838b88 | ||
|
3d27756f02 | ||
|
c90d3c0fc2 | ||
|
5b2c22e4ba | ||
|
14916aa092 | ||
|
1553bc2e0e | ||
|
98f24bdf78 | ||
|
3a04abe2d7 | ||
|
89bf53de39 | ||
|
d12bd8b835 | ||
|
56857c16d4 | ||
|
011b78ba30 | ||
|
7ede7bb350 | ||
|
f5b605c5f6 | ||
|
33349000d4 | ||
|
5f337bd8b0 | ||
|
290312e4c9 | ||
|
2fbb0e6ca5 | ||
|
580d4c1588 | ||
|
141dfa40ed | ||
|
ff845bc079 | ||
|
05d1355b76 | ||
|
32ab866e55 | ||
|
3514305b60 | ||
|
f4b20b5873 | ||
|
84134671be | ||
|
7ca2dbe089 | ||
|
3ff9208004 | ||
|
94856096ed | ||
|
395142b6b0 | ||
|
2efc7d1436 | ||
|
9f31d3ae53 | ||
|
08aba120e8 | ||
|
fe2a27f4cb | ||
|
37c8f29f1e | ||
|
cda995fb57 | ||
|
abe6d6b40a | ||
|
62df914e95 | ||
|
a17bffb68c | ||
|
5cb6c63f16 | ||
|
605fbf5ad7 | ||
|
d2e7621b88 | ||
|
c08e0fbd51 | ||
|
5c0eb4ca14 | ||
|
1701065643 | ||
|
d8855fd2c6 | ||
|
8e15e18b09 | ||
|
8d0ba298ed | ||
|
eae84dadfb | ||
|
a72583894e | ||
|
ad70ad4100 | ||
|
2da06bb1a9 | ||
|
46650c4660 | ||
|
87538e3518 | ||
|
94a57138a4 | ||
|
81b60c4bd8 | ||
|
7ddca6ee33 | ||
|
1a57f78b5c | ||
|
35bc4f0017 | ||
|
395f368052 | ||
|
db86583571 | ||
|
6ea0b5d317 | ||
|
ee5929e9eb | ||
|
70c2d6ba34 | ||
|
8bb64db9ed | ||
|
587099dba7 | ||
|
47abfac7c3 | ||
|
b47a36dd99 | ||
|
3edd898d7d | ||
|
bd2e70c7e7 | ||
|
3986e12313 | ||
|
fe67a6e012 | ||
|
56eecb98bc | ||
|
0407f719ef | ||
|
ebfd1ccfbf | ||
|
d950fc73ed | ||
|
d092ba4a4d | ||
|
38e529e3f6 | ||
|
e037a1c9b2 | ||
|
139e5644eb | ||
|
b216dc3ebb | ||
|
11bbed02b8 | ||
|
5e6a1fc28e | ||
|
47c2923d0e | ||
|
c52168c939 | ||
|
c1abafc72c | ||
|
c716107c3b | ||
|
1986b941a6 | ||
|
0a785692b4 | ||
|
7303534911 | ||
|
7c38679287 | ||
|
4aa0d0a500 | ||
|
cd3b6bb02b | ||
|
6c0de1ddef | ||
|
70ed3a30c6 | ||
|
8e27201e7f | ||
|
941654684b | ||
|
33152d3152 | ||
|
94fffc2af3 | ||
|
b0f97b3243 | ||
|
c12acea373 | ||
|
923a10b137 | ||
|
155da3c368 | ||
|
8b944550e0 | ||
|
c5e6bf4f15 | ||
|
23d2aae40f | ||
|
e20de7ef54 | ||
|
2bef4c1576 | ||
|
4f56b9249f | ||
|
f665aea164 | ||
|
e76d92daa8 | ||
|
4a04a506e9 | ||
|
7cd99f04b8 | ||
|
179774d34c | ||
|
e1bc4d443c | ||
|
5c2194e8cb | ||
|
8b9dc8204a | ||
|
9701637007 | ||
|
21db9c38f3 | ||
|
97eb626795 | ||
|
11361dfac9 | ||
|
8f79d11e53 | ||
|
c125201c4b | ||
|
4f3a5d85dd | ||
|
0eb1af2da8 | ||
|
1d45d0a318 | ||
|
ceba0324e1 | ||
|
697a02bfed | ||
|
35297c3d2a | ||
|
c03e7f3f4b | ||
|
24ce187e95 | ||
|
af15291bcd | ||
|
75c3f70dbc | ||
|
53472e8a05 | ||
|
ebba06ce79 | ||
|
ec7dea1c3c | ||
|
d4904797f7 | ||
|
a5a03dbfcd | ||
|
e2c65cf867 | ||
|
e46a7bccf2 | ||
|
ffa033ee95 | ||
|
4b02caf75a | ||
|
55db7a3340 | ||
|
f67174b55a | ||
|
559026ca82 | ||
|
349f87a888 | ||
|
d617dade24 | ||
|
4c5a43c336 | ||
|
f48c09f5ec | ||
|
b681967b6a | ||
|
c682d7fd0d | ||
|
bc9f36d80b | ||
|
fddef1167b | ||
|
fafb8c7388 | ||
|
c67370ac17 | ||
|
201b463904 | ||
|
d20292a137 | ||
|
ed592a187b | ||
|
dabc11bb75 | ||
|
3def96b8bb | ||
|
aaf64a7eb9 | ||
|
e943ed86d2 | ||
|
a6bb55450b | ||
|
3781d2f029 | ||
|
5fbc7d2664 | ||
|
49933a65cd | ||
|
5d7fbb6d8a | ||
|
6ed75c90f3 | ||
|
f250ebb4a8 | ||
|
349fbe0f97 | ||
|
f072484ea5 | ||
|
f89ebdc70e | ||
|
e891f70f79 | ||
|
3303942782 | ||
|
bd5824395e | ||
|
15e16237f1 | ||
|
afa0fc2fac | ||
|
f83eebe4dd | ||
|
0bc671901e | ||
|
9351c7e65c | ||
|
40c4ea4543 | ||
|
6214c0f92d | ||
|
a72175252a | ||
|
cc62030de2 | ||
|
d3985b1c92 | ||
|
f2ed7e0558 | ||
|
f6684138eb | ||
|
0bcefdc30f | ||
|
f2f5597b63 | ||
|
9f71d7fe9e | ||
|
2495c97a35 | ||
|
4a62335d52 | ||
|
6c90218d69 | ||
|
181fa7f46a | ||
|
5a15fea9bf | ||
|
0e152ae380 | ||
|
d8aff2dd92 | ||
|
5d55417531 | ||
|
1981c44988 | ||
|
96cc3d6bdd | ||
|
b7b07c3bbe | ||
|
f7718a9343 | ||
|
77589f9ae5 | ||
|
c9c2701355 | ||
|
e76b459f75 | ||
|
3afa30cb79 | ||
|
86b909472f | ||
|
60ad4f5fa5 | ||
|
2da14a0bdd | ||
|
c79faeb279 | ||
|
f9d4025193 | ||
|
32475e72e6 | ||
|
d64b702fbb | ||
|
5785c44484 | ||
|
8b482f51c4 | ||
|
82d1de3463 | ||
|
dccfee4377 | ||
|
90d758bb4a | ||
|
ef1922494b | ||
|
bcefc1fdf2 | ||
|
f1188819f2 | ||
|
e831b91f44 | ||
|
28a28907a8 | ||
|
6b5e809f55 | ||
|
14a3cb1a3b | ||
|
c3232dca60 | ||
|
1257de1a0a | ||
|
62ad5b1d34 | ||
|
f0ec0f8b9f | ||
|
25e2d13409 | ||
|
f2082e5215 | ||
|
03d7ac2b3e | ||
|
87fa2b70bb | ||
|
54f67e5200 | ||
|
4de4230dbb | ||
|
1bb93a5068 | ||
|
819fa4543d | ||
|
9bb0a7d2f2 | ||
|
13ad6237fe | ||
|
184d2e12fd | ||
|
b13e98e2dc | ||
|
09ab64044d | ||
|
e06377d64b | ||
|
45d7352c32 | ||
|
52e7fa109b | ||
|
f05eabe94b | ||
|
80a91635dd | ||
|
f76de90a6e | ||
|
a3088e7718 | ||
|
65c2b9b99f | ||
|
ce88024258 | ||
|
36fb1e8164 | ||
|
8395ac5bb4 | ||
|
8212ef63aa | ||
|
e8ce83a232 | ||
|
fbe817b0f3 | ||
|
3a4ea1713f | ||
|
fda38cf855 | ||
|
92713ded76 | ||
|
792b6137fd | ||
|
19e564213b | ||
|
b0d6c830e3 | ||
|
6f26634744 | ||
|
a4f016f069 | ||
|
d598602cba | ||
|
523a78c029 | ||
|
4f509d5419 | ||
|
929c4d2f76 | ||
|
c934f0deeb | ||
|
08b54f8aa0 | ||
|
783ed1dc00 | ||
|
00000e84c6 | ||
|
0e71ca5fa1 | ||
|
58ef25883c | ||
|
ba672a2ab9 | ||
|
72f6c8d6b1 | ||
|
2acfb6655d | ||
|
678fe0b720 | ||
|
38c933477f | ||
|
6203b8b989 | ||
|
c27a57eda4 | ||
|
77e16e67c1 | ||
|
8da4611b37 | ||
|
50b045e01a | ||
|
7c75034e84 | ||
|
c5519c1dd0 | ||
|
8da282db98 | ||
|
eb7786de0b | ||
|
3f3fe0d239 | ||
|
3978801374 | ||
|
b3be3130b3 | ||
|
6759409188 | ||
|
d7e1ec729f | ||
|
1fbb1525c6 | ||
|
7cf4bc8920 | ||
|
8805869542 | ||
|
c5549e735f | ||
|
e994dc1026 | ||
|
ea27e85d94 | ||
|
1cced8b2e4 | ||
|
42e12a2081 | ||
|
114cc84ce6 | ||
|
1cdeac34e8 | ||
|
09ada641e5 | ||
|
f88dc16fa4 | ||
|
d0802a0cce | ||
|
db8ddfaac6 | ||
|
dd34248aa5 | ||
|
533c7ae3c0 | ||
|
c01df1b64a | ||
|
6239f8b2d4 | ||
|
4e2b10cbb0 | ||
|
c3152ae6b0 | ||
|
cfced904b7 | ||
|
39992b8bf0 | ||
|
d11e149814 | ||
|
eebe9c5917 | ||
|
c49a098961 | ||
|
5d60cf0157 | ||
|
253ad880d8 | ||
|
c8f37561cf | ||
|
4ea1875dd5 | ||
|
f3e7258f9a | ||
|
6b184406ee | ||
|
a022533543 | ||
|
b5ab5feac3 | ||
|
bb1c01cf41 | ||
|
7566419b9d | ||
|
700ce423b8 | ||
|
af2f8d86e0 | ||
|
8b52f814ed | ||
|
b42595c888 | ||
|
ff3a957bda | ||
|
a7ad4f9bfb | ||
|
bee1163c44 | ||
|
7a0ff98658 | ||
|
6405e23d08 | ||
|
b98758cff3 | ||
|
7e87253d5f | ||
|
b1d2093563 | ||
|
bbfeb66a02 | ||
|
717e97f321 | ||
|
b8c67f4c19 | ||
|
651cde0441 | ||
|
e6e0a97bef | ||
|
05b267a498 | ||
|
c132837aac | ||
|
3895b8cf0b | ||
|
b3f43ce1f5 | ||
|
99a750b98d | ||
|
22f0790f2e | ||
|
ac239f1f71 | ||
|
facdd5032f | ||
|
c30e7173ae | ||
|
eed1c9ec45 | ||
|
64b580bcd3 | ||
|
c72a897f81 | ||
|
9d61d6c732 | ||
|
2576ca7468 | ||
|
8bdaa2a42e | ||
|
5f71c2803b | ||
|
40a40f800d | ||
|
1a6feec7ee | ||
|
8e96526e3c | ||
|
cc14488a88 | ||
|
f7dcb8e51c | ||
|
b937c4ebdd | ||
|
6ee249ca7e | ||
|
c733997aaa | ||
|
d0bd844c48 | ||
|
fd7abccb42 | ||
|
597044cdc8 | ||
|
9bbd6d7632 | ||
|
44840583b7 | ||
|
6e875efe28 | ||
|
f59b3e9c5e | ||
|
9ba7054d14 | ||
|
af171ce788 | ||
|
3b7351db79 | ||
|
9c60469658 | ||
|
0277d9eb65 | ||
|
1483b9d516 | ||
|
8e4c07f924 | ||
|
9d2d76a606 | ||
|
31a8a5b968 | ||
|
f120a92489 | ||
|
a8b3eed9c8 | ||
|
1606568e79 | ||
|
fc818ac6a3 | ||
|
6dfb2cac10 | ||
|
21c10614e2 | ||
|
d39e314707 | ||
|
88a45634a2 | ||
|
a22b5c3318 | ||
|
64459acb85 | ||
|
140f27f8c3 | ||
|
9d3c9e93a0 | ||
|
b7e9f63e10 | ||
|
ed4941f9e3 | ||
|
6ea71a7e61 | ||
|
7ef707a8ca | ||
|
e88ec7a9ff | ||
|
58b9ed61ff | ||
|
29e67d1109 | ||
|
134e6db6f2 | ||
|
bc720e96bb | ||
|
95053325bc | ||
|
1a0e887179 | ||
|
7b03ecb31f | ||
|
6a88796d85 | ||
|
bd26728bb5 | ||
|
24f72073a4 | ||
|
810567c237 | ||
|
ae7749701a | ||
|
4b4ff0e8f6 | ||
|
b8506fffd1 | ||
|
c75c4436f8 | ||
|
a658bf1b0a | ||
|
449385e4fd | ||
|
d13503ae29 | ||
|
ffd6a2cffc | ||
|
c61310c59f | ||
|
0ef354d423 | ||
|
48ec96f41b | ||
|
73fa4e8ad9 | ||
|
f98822c8ed | ||
|
18f6f87909 |
9
.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/bin/
|
||||||
|
ownCloudSMS.iml
|
||||||
|
/build/
|
||||||
|
ownCloudSMS-release.apk
|
||||||
|
lint.xml
|
||||||
|
.gradle/
|
||||||
|
.idea/
|
||||||
|
local.properties
|
||||||
|
ownCloud-SMS-App.iml
|
231
.idea/codeStyleSettings.xml
generated
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectCodeStyleSettingsManager">
|
||||||
|
<option name="PER_PROJECT_SETTINGS">
|
||||||
|
<value>
|
||||||
|
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
|
||||||
|
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
|
||||||
|
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
|
||||||
|
<value />
|
||||||
|
</option>
|
||||||
|
<option name="IMPORT_LAYOUT_TABLE">
|
||||||
|
<value>
|
||||||
|
<package name="android" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="com" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="junit" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="net" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="org" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="java" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="javax" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="" withSubpackages="true" static="false" />
|
||||||
|
<emptyLine />
|
||||||
|
<package name="" withSubpackages="true" static="true" />
|
||||||
|
<emptyLine />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="RIGHT_MARGIN" value="100" />
|
||||||
|
<AndroidXmlCodeStyleSettings>
|
||||||
|
<option name="USE_CUSTOM_SETTINGS" value="true" />
|
||||||
|
</AndroidXmlCodeStyleSettings>
|
||||||
|
<Objective-C-extensions>
|
||||||
|
<option name="GENERATE_INSTANCE_VARIABLES_FOR_PROPERTIES" value="ASK" />
|
||||||
|
<option name="RELEASE_STYLE" value="IVAR" />
|
||||||
|
<option name="TYPE_QUALIFIERS_PLACEMENT" value="BEFORE" />
|
||||||
|
<file>
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
|
||||||
|
</file>
|
||||||
|
<class>
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
|
||||||
|
</class>
|
||||||
|
<extensions>
|
||||||
|
<pair source="cpp" header="h" />
|
||||||
|
<pair source="c" header="h" />
|
||||||
|
</extensions>
|
||||||
|
</Objective-C-extensions>
|
||||||
|
<XML>
|
||||||
|
<option name="XML_KEEP_LINE_BREAKS" value="false" />
|
||||||
|
<option name="XML_ALIGN_ATTRIBUTES" value="false" />
|
||||||
|
<option name="XML_SPACE_INSIDE_EMPTY_TAG" value="true" />
|
||||||
|
</XML>
|
||||||
|
<codeStyleSettings language="XML">
|
||||||
|
<option name="FORCE_REARRANGE_MODE" value="1" />
|
||||||
|
<indentOptions>
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||||
|
</indentOptions>
|
||||||
|
<arrangement>
|
||||||
|
<rules>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>xmlns:android</NAME>
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>xmlns:.*</NAME>
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:id</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:name</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>name</NAME>
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>style</NAME>
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*</NAME>
|
||||||
|
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:layout_width</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:layout_height</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:layout_.*</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:width</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*:height</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*</NAME>
|
||||||
|
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<rule>
|
||||||
|
<match>
|
||||||
|
<AND>
|
||||||
|
<NAME>.*</NAME>
|
||||||
|
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
||||||
|
</AND>
|
||||||
|
</match>
|
||||||
|
<order>BY_NAME</order>
|
||||||
|
</rule>
|
||||||
|
</section>
|
||||||
|
</rules>
|
||||||
|
</arrangement>
|
||||||
|
</codeStyleSettings>
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default (1)" />
|
||||||
|
</component>
|
||||||
|
</project>
|
28
.travis.yml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
language: android
|
||||||
|
before_cache:
|
||||||
|
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
|
||||||
|
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- $HOME/.gradle/caches/
|
||||||
|
- $HOME/.gradle/wrapper/
|
||||||
|
|
||||||
|
jdk:
|
||||||
|
- oraclejdk8
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- yes | sdkmanager "platforms;android-28"
|
||||||
|
|
||||||
|
android:
|
||||||
|
components:
|
||||||
|
- tools
|
||||||
|
- platform-tools
|
||||||
|
- extra
|
||||||
|
- build-tools-28.0.3
|
||||||
|
- android-28
|
||||||
|
licenses:
|
||||||
|
- 'android-sdk-license-.+'
|
||||||
|
- 'google-gdk-license-.+'
|
||||||
|
- 'android-sdk-preview-license-.+'
|
||||||
|
- 'android-.*'
|
17
.tx/config
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
[main]
|
||||||
|
host = https://www.transifex.com
|
||||||
|
|
||||||
|
[o:nextcloud:p:nextcloud:r:android-sms]
|
||||||
|
file_filter = src/main/res/values-<lang>/strings.xml
|
||||||
|
source_file = src/main/res/values/strings.xml
|
||||||
|
source_lang = en
|
||||||
|
type = ANDROID
|
||||||
|
lang_map = ar_EG: ar-rEG, ar_KW: ar-rKW, da_DK: da-rDK, hu_HU: hu-rHU, lb_LU: lb-rLU, tzm_DZ: tzm-rDZ, ar_DZ: ar-rDZ, ar_SA: ar-rSA, arn_CL: arn-rCL, de_LI: de-rLI, fr_MC: fr-rMC, se_FI: se-rFI, ta_LK: ta-rLK, tt_RU: tt-rRU, xh_ZA: xh-rZA, co_FR: co-rFR, cy_GB: cy-rGB, en_SG: en-rSG, es_PA: es-rPA, es_UY: es-rUY, ku_IQ: ku-rIQ, rm_CH: rm-rCH, smj_SE: smj-rSE, sq_AL: sq-rAL, tr_TR: tr-rTR, uz_UZ: uz-rUZ, en_AU: en-rAU, ar_OM: ar-rOM, el_GR: el-rGR, es_EC: es-rEC, ha_NG: ha-rNG, hr_HR: hr-rHR, or_IN: or-rIN, pt_BR: pt-rBR, se_NO: se-rNO, am_ET: am-rET, en_US: en-rUS, es_PE: es-rPE, fa_IR: fa-rIR, fr_CA: fr-rCA, fy_NL: fy-rNL, hr_BA: hr-rBA, hy_AM: hy-rAM, lt_LT: lt-rLT, ar_SY: ar-rSY, ca_ES: ca-rES, en_JM: en-rJM, es_AR: es-rAR, es_PY: es-rPY, it_CH: it-rCH, kk_KZ: kk-rKZ, vi_VN: vi-rVN, es_MX: es-rMX, pt_PT: pt-rPT, uk_UA: uk-rUA, zh_CN.GB2312: zh-rBG, zu_ZA: zu-rZA, bs_BA: bs-rBA, is_IS: is-rIS, my_MM: my, quz_PE: quz-rPE, ur_PK: ur-rPK, ar_AE: ar-rAE, ar_LY: ar-rLY, ar_QA: ar-rQA, ja_JP: ja-rJP, nl_BE: nl-rBE, nso_ZA: nso-rZA, rw_RW: rw-rRW, sr_BA: sr-rBA, te_IN: te-rIN, de_AT: de-rAT, dv_MV: dv-rMV, ro_RO: ro-rRO, sv_SE: sv-rSE, fr_FR: fr-rFR, he_IL: he-rIL, ne_NP: ne-rNP, sms_FI: sms-rFI, ar_TN: ar-rTN, az_AZ: az-rAZ, de_LU: de-rLU, es_CO: es-rCO, es_NI: es-rNI, id_ID: id-rID, quz_BO: quz-rBO, sr@latin: sr-rSP, en_GB: en-rGB, es_PR: es-rPR, es_SV: es-rSV, kn_IN: kn-rIN, ar_MA: ar-rMA, bo_CN: bo-rCN, dsb_DE: dsb-rDE, ig_NG: ig-rNG, mn_CN: mn-rCN, moh_CA: moh-rCA, pa_IN: pa-rIN, ps_AF: ps-rAF, smn_FI: smn-rFI, zh_MO: zh-rMO, en@pirate: en-rpirate, gl_ES: gl-rES, th_TH: th-rTH, fr_BE: fr-rBE, nb_NO: nb-rNO, prs_AF: prs-rAF, qut_GT: qut-rGT, en_ZW: en-rZW, eu_ES: eu-rES, hsb_DE: hsb-rDE, lo_LA: lo-rLA, mk_MK: mk-rMK, sk_SK: sk-rSK, sma_SE: sma-rSE, zh_HK: zh-rHK, as_IN: as-rIN, en_MY: en-rMY, en_NZ: en-rNZ, es_GT: es-rGT, es_HN: es-rHN, hi_IN: hi-rIN, mt_MT: mt-rMT, oc_FR: oc-rFR, sa_IN: sa-rIN, tk_TM: tk-rTM, ba_RU: ba-rRU, be_BY: be-rBY, kl_GL: kl-rGL, lv_LV: lv-rLV, sah_RU: sah-rRU, yo_NG: yo-rNG, de_DE: de-rDE, es_VE: es-rVE, gd_GB: gd-rGB, ko_KR: ko-rKR, sl_SI: sl-rSI, ug_CN: ug-rCN, ar_YE: ar-rYE, en_IN: en-rIN, es_BO: es-rBO, fr_LU: fr-rLU, bn_BD: bn-rBD, bn_IN: bn-rIN, gu_IN: gu-rIN, mr_IN: mr-rIN, ar_IQ: ar-rIQ, en_CA: en-rCA, es_CR: es-rCR, es_ES: es-rES, ga_IE: ga-rIE, gsw_FR: gsw-rFR, mn_MN: mn-rMN, ru_RU: ru-rRU, sr_CS: sr-rCS, tg_TJ: tg-rTJ, bg_BG: bg-rBG, iu_CA: iu-rCA, nl_NL: nl-rNL, quz_EC: quz-rEC, sma_NO: sma-rNO, sv_FI: sv-rFI, en_IE: en-rIE, fr_CH: fr-rCH, zh_TW: zh-rTW, ar_LB: ar-rLB, br_FR: br-rFR, cs_CZ: cs-rCZ, en_BZ: en-rBZ, en_TT: en-rTT, et_EE: et-rEE, fi_FI: fi-rFI, ii_CN: ii-rCN, km_KH: km-rKH, kok_IN: kok-rIN, ml_IN: ml-rIN, se_SE: se-rSE, syr_SY: syr-rSY, af_ZA: af-rZA, en_ZA: en-rZA, es_CL: es-rCL, mi_NZ: mi-rNZ, smj_NO: smj-rNO, wo_SN: wo-rSN, ar_BH: ar-rBH, fo_FO: fo-rFO, ky_KG: ky-rKG, ms_BN: ms-rBN, nn_NO: nn-rNO, zh_SG: zh-rSG, ar_JO: ar-rJO, en_PH: en-rPH, es_DO: es-rDO, ms_MY: ms-rMY, pl_PL: pl-rPL, sr_RS: sr-rRS, zh_CN: zh-rCN, es_419: es-rUS, it_IT: it-rIT, ka_GE: ka-rGE, si_LK: si-rLK, tn_ZA: tn-rZA, de_CH: de-rCH, fil_PH: fil-rPH, sr_ME: sr-rME, sw_KE: sw-rKE, ta_IN: ta-rIN
|
||||||
|
|
||||||
|
[o:nextcloud:p:nextcloud:r:android-sms-playstore]
|
||||||
|
file_filter = src/main/res/values-<lang>/google_playstore_strings.xml
|
||||||
|
source_file = src/main/res/values/google_playstore_strings.xml
|
||||||
|
source_lang = en
|
||||||
|
type = ANDROID
|
||||||
|
lang_map = ka_GE: ka-rGE, kn_IN: kn-rIN, sr_CS: sr-rCS, tr_TR: tr-rTR, bs_BA: bs-rBA, es_VE: es-rVE, gd_GB: gd-rGB, es_BO: es-rBO, es_HN: es-rHN, es_PE: es-rPE, eu_ES: eu-rES, rw_RW: rw-rRW, de_CH: de-rCH, de_DE: de-rDE, en_GB: en-rGB, sk_SK: sk-rSK, smj_NO: smj-rNO, zu_ZA: zu-rZA, es_ES: es-rES, mn_MN: mn-rMN, sa_IN: sa-rIN, ta_LK: ta-rLK, uk_UA: uk-rUA, fil_PH: fil-rPH, hr_BA: hr-rBA, ml_IN: ml-rIN, tg_TJ: tg-rTJ, uz_UZ: uz-rUZ, ar_LY: ar-rLY, ar_YE: ar-rYE, my_MM: my, ar_KW: ar-rKW, en_ZW: en-rZW, es_PA: es-rPA, it_CH: it-rCH, ku_IQ: ku-rIQ, ar_AE: ar-rAE, ar_BH: ar-rBH, ar_DZ: ar-rDZ, prs_AF: prs-rAF, pt_BR: pt-rBR, ug_CN: ug-rCN, oc_FR: oc-rFR, sma_NO: sma-rNO, es_PY: es-rPY, ms_MY: ms-rMY, mt_MT: mt-rMT, es_CR: es-rCR, fr_BE: fr-rBE, or_IN: or-rIN, quz_EC: quz-rEC, sr@latin: sr-rSP, zh_HK: zh-rHK, ar_JO: ar-rJO, ar_MA: ar-rMA, bn_BD: bn-rBD, en_ZA: en-rZA, it_IT: it-rIT, ko_KR: ko-rKR, mk_MK: mk-rMK, bo_CN: bo-rCN, co_FR: co-rFR, dsb_DE: dsb-rDE, nl_NL: nl-rNL, sah_RU: sah-rRU, se_SE: se-rSE, zh_CN.GB2312: zh-rBG, zh_TW: zh-rTW, az_AZ: az-rAZ, cy_GB: cy-rGB, nb_NO: nb-rNO, es_UY: es-rUY, fo_FO: fo-rFO, ig_NG: ig-rNG, lo_LA: lo-rLA, mi_NZ: mi-rNZ, en_MY: en-rMY, en_TT: en-rTT, es_SV: es-rSV, nso_ZA: nso-rZA, th_TH: th-rTH, ms_BN: ms-rBN, en_SG: en-rSG, es_EC: es-rEC, id_ID: id-rID, nl_BE: nl-rBE, fr_CH: fr-rCH, hi_IN: hi-rIN, is_IS: is-rIS, en_AU: en-rAU, et_EE: et-rEE, pt_PT: pt-rPT, hy_AM: hy-rAM, lv_LV: lv-rLV, tk_TM: tk-rTM, ur_PK: ur-rPK, en_NZ: en-rNZ, es_DO: es-rDO, es_GT: es-rGT, sv_FI: sv-rFI, tzm_DZ: tzm-rDZ, vi_VN: vi-rVN, ar_OM: ar-rOM, fa_IR: fa-rIR, hu_HU: hu-rHU, de_AT: de-rAT, en_IN: en-rIN, iu_CA: iu-rCA, qut_GT: qut-rGT, smj_SE: smj-rSE, ar_SY: ar-rSY, ar_TN: ar-rTN, cs_CZ: cs-rCZ, te_IN: te-rIN, zh_MO: zh-rMO, quz_BO: quz-rBO, ta_IN: ta-rIN, zh_CN: zh-rCN, de_LI: de-rLI, en_BZ: en-rBZ, ga_IE: ga-rIE, fy_NL: fy-rNL, ha_NG: ha-rNG, kk_KZ: kk-rKZ, rm_CH: rm-rCH, ro_RO: ro-rRO, ar_SA: ar-rSA, en_PH: en-rPH, es_419: es-rUS, hr_HR: hr-rHR, pa_IN: pa-rIN, pl_PL: pl-rPL, sma_SE: sma-rSE, xh_ZA: xh-rZA, dv_MV: dv-rMV, fi_FI: fi-rFI, fr_FR: fr-rFR, zh_SG: zh-rSG, ne_NP: ne-rNP, da_DK: da-rDK, gu_IN: gu-rIN, km_KH: km-rKH, mr_IN: mr-rIN, smn_FI: smn-rFI, el_GR: el-rGR, es_CL: es-rCL, ky_KG: ky-rKG, ps_AF: ps-rAF, ru_RU: ru-rRU, sms_FI: sms-rFI, sq_AL: sq-rAL, arn_CL: arn-rCL, es_AR: es-rAR, fr_LU: fr-rLU, sr_ME: sr-rME, sr_RS: sr-rRS, sw_KE: sw-rKE, yo_NG: yo-rNG, be_BY: be-rBY, es_MX: es-rMX, es_NI: es-rNI, ii_CN: ii-rCN, si_LK: si-rLK, sl_SI: sl-rSI, tn_ZA: tn-rZA, ar_EG: ar-rEG, ar_IQ: ar-rIQ, fr_MC: fr-rMC, moh_CA: moh-rCA, se_NO: se-rNO, en_CA: en-rCA, fr_CA: fr-rCA, kl_GL: kl-rGL, en_IE: en-rIE, en_JM: en-rJM, gl_ES: gl-rES, hsb_DE: hsb-rDE, lb_LU: lb-rLU, af_ZA: af-rZA, ba_RU: ba-rRU, bn_IN: bn-rIN, sv_SE: sv-rSE, wo_SN: wo-rSN, es_CO: es-rCO, br_FR: br-rFR, he_IL: he-rIL, ja_JP: ja-rJP, lt_LT: lt-rLT, tt_RU: tt-rRU, ar_LB: ar-rLB, ar_QA: ar-rQA, as_IN: as-rIN, de_LU: de-rLU, es_PR: es-rPR, gsw_FR: gsw-rFR, kok_IN: kok-rIN, mn_CN: mn-rCN, am_ET: am-rET, bg_BG: bg-rBG, ca_ES: ca-rES, quz_PE: quz-rPE, se_FI: se-rFI, sr_BA: sr-rBA, syr_SY: syr-rSY, en_US: en-rUS, en@pirate: en-rpirate, nn_NO: nn-rNO
|
||||||
|
|
@ -1,128 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
package="fr.unix_experience.owncloud_sms"
|
|
||||||
android:versionCode="18"
|
|
||||||
android:versionName="0.17.0">
|
|
||||||
|
|
||||||
<!-- From Android 4.0 to 5.0 -->
|
|
||||||
<uses-sdk
|
|
||||||
android:maxSdkVersion="21"
|
|
||||||
android:minSdkVersion="14"
|
|
||||||
android:targetSdkVersion="21" />
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.READ_SMS" />
|
|
||||||
<!-- For SMS Broadcaster -->
|
|
||||||
<uses-permission android:name="android.permission.RECEIVE_SMS" />
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
|
||||||
|
|
||||||
<!-- For syncer -->
|
|
||||||
<uses-permission android:name="android.permission.READ_SYNC_STATS" />
|
|
||||||
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
|
|
||||||
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
|
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
|
||||||
|
|
||||||
<!-- For account management -->
|
|
||||||
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
|
||||||
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
|
|
||||||
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
|
|
||||||
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
|
|
||||||
|
|
||||||
<application
|
|
||||||
android:allowBackup="true"
|
|
||||||
android:icon="@drawable/ic_launcher"
|
|
||||||
android:label="@string/app_name"
|
|
||||||
android:theme="@style/OcSmsTheme" >
|
|
||||||
|
|
||||||
<!-- Related to periodic sync -->
|
|
||||||
<service
|
|
||||||
android:name=".observers.SmsObserverService"
|
|
||||||
android:exported="false" />
|
|
||||||
<service
|
|
||||||
android:name=".sync_adapters.SmsSyncService"
|
|
||||||
android:exported="true"
|
|
||||||
android:process=":sync" >
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.content.SyncAdapter" />
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
<meta-data
|
|
||||||
android:name="android.content.SyncAdapter"
|
|
||||||
android:resource="@xml/sync_adapter" />
|
|
||||||
</service>
|
|
||||||
|
|
||||||
<provider
|
|
||||||
android:name=".providers.SmsDataProvider"
|
|
||||||
android:authorities="@string/account_authority"
|
|
||||||
android:label="@string/pref_title_sync" >
|
|
||||||
</provider>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
<service
|
|
||||||
android:name=".sync_adapters.SmsSlowSyncService"
|
|
||||||
android:exported="true"
|
|
||||||
android:process=":sync">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.content.SyncAdapter" />
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
<meta-data
|
|
||||||
android:name="android.content.SyncAdapter"
|
|
||||||
android:resource="@xml/slow_sync_adapter" />
|
|
||||||
</service>
|
|
||||||
|
|
||||||
<provider
|
|
||||||
android:name=".providers.SmsDataProvider"
|
|
||||||
android:label="@string/pref_title_slow_sync"
|
|
||||||
android:authorities="@string/slowsync_account_authority">
|
|
||||||
</provider>
|
|
||||||
-->
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Related to Login -->
|
|
||||||
<service android:name=".authenticators.OwnCloudAuthenticatorService" >
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.accounts.AccountAuthenticator" />
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
<meta-data
|
|
||||||
android:name="android.accounts.AccountAuthenticator"
|
|
||||||
android:resource="@xml/owncloud_account_authenticator" />
|
|
||||||
</service>
|
|
||||||
|
|
||||||
<receiver android:name=".broadcast_receivers.IncomingSms" >
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
|
|
||||||
</intent-filter>
|
|
||||||
</receiver>
|
|
||||||
<receiver android:name=".broadcast_receivers.ConnectivityChanged" >
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
|
|
||||||
</intent-filter>
|
|
||||||
</receiver>
|
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name=".activities.LoginActivity"
|
|
||||||
android:label="@string/title_activity_login" >
|
|
||||||
</activity>
|
|
||||||
<activity
|
|
||||||
android:name=".activities.GeneralSettingsActivity"
|
|
||||||
android:label="@string/title_activity_general_settings" >
|
|
||||||
</activity>
|
|
||||||
<activity
|
|
||||||
android:name=".activities.MainActivity"
|
|
||||||
android:label="@string/app_name" >
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN" />
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
<activity
|
|
||||||
android:name=".MainActivity2"
|
|
||||||
android:label="@string/title_activity_main_activity2" >
|
|
||||||
</activity>
|
|
||||||
</application>
|
|
||||||
|
|
||||||
</manifest>
|
|
20
PRIVACY_POLICY.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Overview
|
||||||
|
|
||||||
|
Nextcloud SMS is a free software developed by its contributors. This privacy policy
|
||||||
|
is intended to inform you about data gathered by this application."
|
||||||
|
|
||||||
|
# Information we collect
|
||||||
|
|
||||||
|
Only SMS and call log are collected by the application.
|
||||||
|
|
||||||
|
# Where information is sent.
|
||||||
|
|
||||||
|
Information is neither sent to Nextcloud team servers nor Nextcloud SMS team servers nor
|
||||||
|
any government nor another entity you don't want.
|
||||||
|
|
||||||
|
When you configure a Nextcloud account in the application, you agree with the Nextcloud
|
||||||
|
instance owner that your SMS and call log data will be stored in his infrastructure
|
||||||
|
under his responsibility.
|
||||||
|
|
||||||
|
We __don't__ recommend to use a public or a company Nextcloud instance account. Your privacy
|
||||||
|
must be under your control on your own Nextcloud instance.
|
83
README.md
@ -1,58 +1,45 @@
|
|||||||
# ownCloud SMS Android Application Offical Repository
|
# Nextcloud SMS (Android)
|
||||||
|
|
||||||
## Introduction
|
[](https://codebeat.co/projects/github-com-nerzhul-owncloud-sms-app-master)
|
||||||
|
|
||||||
ownCloud SMS app push your Android devices conversation into your ownCloud instance, using ocsms app.
|
Nextcloud SMS app pushes your Android devices conversation into your Nextcloud instance, using [ocsms app](https://github.com/nerzhul/ocsms).
|
||||||
|
|
||||||
Android download link: https://play.google.com/store/apps/details?id=fr.unix_experience.owncloud_sms
|
## :arrow_forward: Access
|
||||||
|
|
||||||
ocsms app sources are available here: https://github.com/nerzhul/ocsms/
|
[](https://f-droid.org/repository/browse/?fdid=fr.unix_experience.owncloud_sms)
|
||||||
|
|
||||||
## Application documentation
|
ocsms app sources are available here: https://github.com/nextcloud/ocsms
|
||||||
|
|
||||||
You can found application documentation here: https://github.com/nerzhul/ownCloud-SMS-App/wiki
|
## :notebook: Application documentation
|
||||||
|
|
||||||
## Licence
|
You can find the application documentation here: https://github.com/nerzhul/ncsms-android/wiki
|
||||||
|
|
||||||
ownCloud SMS Android Application licence is in reflexion, then sources are partial.
|
## :link: Requirements
|
||||||
|
- [Nextcloud](https://nextcloud.com/) instance running
|
||||||
|
- [ocsms](https://github.com/nextcloud/ocsms) app enabled
|
||||||
|
|
||||||
- App locales and layouts are under BSD 2 clause licence
|
## :exclamation: Reporting issues
|
||||||
|
|
||||||
|
- **Client:** https://github.com/nerzhul/ncsms-android/issues
|
||||||
|
- **Server:** https://github.com/nextcloud/ocsms/issues
|
||||||
|
|
||||||
|
## :rocket: Contributions
|
||||||
|
|
||||||
|
- We are searching for **translations** into others languages. To contribute please download `res/values/strings.xml` and `res/values/google_playstore_strings.xml` and provide a Pull Request with a translated version!
|
||||||
|
- You can also contribute by adding **patches** in Java code or cleanups.
|
||||||
|
- Application uses a [GoMobile AAR](https://gitlab.com/nerzhul/ncsmsgo) to have the best performance on phones with modern technologies like HTTP/2.0
|
||||||
|
|
||||||
|
### Build requirements
|
||||||
|
- gradle
|
||||||
|
|
||||||
|
### Coding guidelines
|
||||||
|
|
||||||
|
- No empty lines at EOF
|
||||||
|
- No trailing whitespaces
|
||||||
|
|
||||||
|
## :notebook: License
|
||||||
|
|
||||||
|
Nextcloud SMS Android Application license is in reflexion, then sources are partial.
|
||||||
|
|
||||||
|
- App locales and layouts are under BSD 2 clause license
|
||||||
- App DataProviders are under AGPLv3
|
- App DataProviders are under AGPLv3
|
||||||
|
|
||||||
## Contributions
|
|
||||||
|
|
||||||
We are searching for translations in others langs
|
|
||||||
|
|
||||||
To contribute please download res/values/strings.xml and res/values/google_playstore_strings.xml and give us a translated version !
|
|
||||||
|
|
||||||
You can also contribute by adding patches in Java code or cleanups.
|
|
||||||
|
|
||||||
## Requirements
|
|
||||||
- An ownCloud instance with ocsms app
|
|
||||||
|
|
||||||
|
|
||||||
## Issue template
|
|
||||||
|
|
||||||
Server
|
|
||||||
- ownCloud version: X.X.X
|
|
||||||
- PHP version: X.X
|
|
||||||
- HTTPd server: <apache|nginx...>
|
|
||||||
- HTTPS: <yes|no>
|
|
||||||
|
|
||||||
Client
|
|
||||||
- Android version: X.X.X
|
|
||||||
- Phone: <phone-model>
|
|
||||||
- ownCloud SMS app version: X.X.X
|
|
||||||
|
|
||||||
|
|
||||||
Please create your issues for the client here:
|
|
||||||
|
|
||||||
https://github.com/nerzhul/ownCloud-SMS-App/issues
|
|
||||||
|
|
||||||
And for the server app here:
|
|
||||||
|
|
||||||
https://github.com/nerzhul/ocsms/issues
|
|
||||||
|
|
||||||
## Developpers
|
|
||||||
|
|
||||||
You can found our continuous integration here: http://jenkins.unix-experience.fr/job/ownCloud%20SMS%20%28Android%29/
|
|
||||||
|
71
build.gradle
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
jcenter()
|
||||||
|
google()
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.android.tools.build:gradle:3.2.1'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
repositories {
|
||||||
|
jcenter()
|
||||||
|
google()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 28
|
||||||
|
buildToolsVersion "28.0.3"
|
||||||
|
|
||||||
|
lintOptions {
|
||||||
|
abortOnError false
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
applicationId "fr.unix_experience.owncloud_sms"
|
||||||
|
versionCode 70
|
||||||
|
versionName "2.0.6"
|
||||||
|
minSdkVersion 16
|
||||||
|
targetSdkVersion 28
|
||||||
|
maxSdkVersion 28
|
||||||
|
ndk {
|
||||||
|
// Specifies the ABI configurations of your native
|
||||||
|
// libraries Gradle should build and package with your APK.
|
||||||
|
abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a',
|
||||||
|
'arm64-v8a', 'mips', 'mips64'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
packagingOptions {
|
||||||
|
exclude 'META-INF/LICENSE.txt'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
url "https://jitpack.io"
|
||||||
|
}
|
||||||
|
mavenCentral()
|
||||||
|
google()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'com.android.support:support-v13:28.0.0'
|
||||||
|
implementation 'com.android.support:appcompat-v7:28.0.0'
|
||||||
|
implementation 'com.android.support:design:28.0.0'
|
||||||
|
implementation 'in.srain.cube:ultra-ptr:1.0.11'
|
||||||
|
implementation 'com.github.dmytrodanylyk.android-process-button:library:1.0.4'
|
||||||
|
implementation 'com.android.support:support-v4:28.0.0'
|
||||||
|
implementation project(':ncsmsgo')
|
||||||
|
}
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
6
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#Sat Dec 22 18:14:31 CET 2018
|
||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
164
gradlew
vendored
Executable file
@ -0,0 +1,164 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS=""
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn ( ) {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die ( ) {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
||||||
|
if $cygwin ; then
|
||||||
|
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >&-
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >&-
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
if $cygwin ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=$((i+1))
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
(0) set -- ;;
|
||||||
|
(1) set -- "$args0" ;;
|
||||||
|
(2) set -- "$args0" "$args1" ;;
|
||||||
|
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||||
|
function splitJvmOpts() {
|
||||||
|
JVM_OPTS=("$@")
|
||||||
|
}
|
||||||
|
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||||
|
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||||
|
|
||||||
|
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
90
gradlew.bat
vendored
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
@if "%DEBUG%" == "" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS=
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if "%ERRORLEVEL%" == "0" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:init
|
||||||
|
@rem Get command-line arguments, handling Windowz variants
|
||||||
|
|
||||||
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
|
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||||
|
|
||||||
|
:win9xME_args
|
||||||
|
@rem Slurp the command line arguments.
|
||||||
|
set CMD_LINE_ARGS=
|
||||||
|
set _SKIP=2
|
||||||
|
|
||||||
|
:win9xME_args_slurp
|
||||||
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
|
set CMD_LINE_ARGS=%*
|
||||||
|
goto execute
|
||||||
|
|
||||||
|
:4NT_args
|
||||||
|
@rem Get arguments from the 4NT Shell from JP Software
|
||||||
|
set CMD_LINE_ARGS=%$
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
Before Width: | Height: | Size: 82 KiB |
56
ic_launcher.svg
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
enable-background="new 0 0 595.275 311.111"
|
||||||
|
xml:space="preserve"
|
||||||
|
height="512"
|
||||||
|
width="512"
|
||||||
|
version="1.1"
|
||||||
|
y="0px"
|
||||||
|
x="0px"
|
||||||
|
id="svg2"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
inkscape:version="0.91 r13725"
|
||||||
|
sodipodi:docname="ic_launcher.svg"><metadata
|
||||||
|
id="metadata10"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||||
|
id="defs8" /><sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1148"
|
||||||
|
id="namedview6"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="0.73698733"
|
||||||
|
inkscape:cx="8.4791339"
|
||||||
|
inkscape:cy="91.823077"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg2" /><rect
|
||||||
|
rx="70"
|
||||||
|
ry="70"
|
||||||
|
height="448"
|
||||||
|
width="448"
|
||||||
|
y="32"
|
||||||
|
x="32"
|
||||||
|
id="rect4"
|
||||||
|
style="fill:#0082C9" /><path
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.25007507;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0"
|
||||||
|
d="m 122.44396,89.125042 c -18.45887,0 -33.318923,14.115008 -33.318923,31.647818 l 0,143.74017 c 0,17.53283 14.860053,31.64784 33.318923,31.64784 l 38.24891,0 152.52844,126.43415 -49.39316,-126.43415 125.72788,0 c 18.45889,0 33.31893,-14.11501 33.31893,-31.64784 l 0,-143.74017 c 0,-17.53281 -14.86004,-31.647818 -33.31893,-31.647818 z m 9.05472,27.207518 249.00265,0 c 9.08866,0 16.40549,5.85418 16.40549,13.12558 l 0,8.53918 c 0,7.27142 -7.31683,13.12389 -16.40549,13.12389 l -249.00265,0 c -9.08867,0 -16.40551,-5.85247 -16.40551,-13.12389 l 0,-8.53918 c 0,-7.2714 7.31684,-13.12558 16.40551,-13.12558 z m 0,60.50813 249.00265,0 c 9.08866,0 16.40549,5.85418 16.40549,13.12559 l 0,8.53748 c 0,7.27141 -7.31683,13.12559 -16.40549,13.12559 l -249.00265,0 c -9.08867,0 -16.40551,-5.85418 -16.40551,-13.12559 l 0,-8.53748 c 0,-7.27141 7.31684,-13.12559 16.40551,-13.12559 z m 0,60.01043 89.95439,0 c 9.08866,0 16.40548,7.9877 16.40548,15.25911 l 0,6.40397 c 0,7.27139 -7.31682,13.12558 -16.40548,13.12558 l -89.95439,0 c -9.08867,0 -16.40551,-5.85419 -16.40551,-13.12558 l 0,-6.40397 c 0,-7.27141 7.31684,-15.25911 16.40551,-15.25911 z"
|
||||||
|
id="rect3350"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="sssscccssssssssssssssssssssssssssssssss" /></svg>
|
After Width: | Height: | Size: 3.0 KiB |
45
issue_template.md
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<!--
|
||||||
|
Thanks for reporting issues back to us!
|
||||||
|
|
||||||
|
To make it possible for us to help you please fill out below information carefully.
|
||||||
|
-->
|
||||||
|
|
||||||
|
### Steps to reproduce
|
||||||
|
1.
|
||||||
|
2.
|
||||||
|
3.
|
||||||
|
|
||||||
|
### Expected behaviour
|
||||||
|
Tell us what should happen
|
||||||
|
|
||||||
|
### Actual behaviour
|
||||||
|
Tell us what happens instead
|
||||||
|
|
||||||
|
### Server configuration
|
||||||
|
|
||||||
|
**Nextcloud version:**
|
||||||
|
|
||||||
|
**PHP version:**
|
||||||
|
|
||||||
|
**Webserver:**
|
||||||
|
|
||||||
|
**HTTPS:**
|
||||||
|
|
||||||
|
### Client configuration
|
||||||
|
|
||||||
|
**Android version:**
|
||||||
|
|
||||||
|
**Phone:**
|
||||||
|
|
||||||
|
**Nextcloud SMS app version:**
|
||||||
|
|
||||||
|
### Logs
|
||||||
|
|
||||||
|
```
|
||||||
|
Insert your log here
|
||||||
|
```
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
<!--
|
||||||
|
Upload your screenshots here if any
|
||||||
|
-->
|
2
ncsmsgo/build.gradle
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
configurations.maybeCreate("default")
|
||||||
|
artifacts.add("default", file('ncsmsgo.aar'))
|
BIN
ncsmsgo/ncsmsgo.aar
Normal file
25
ncsmsgo/ncsmsgo.iml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module external.linked.project.id=":ncsmsgo" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" type="JAVA_MODULE" version="4">
|
||||||
|
<component name="FacetManager">
|
||||||
|
<facet type="android-gradle" name="Android-Gradle">
|
||||||
|
<configuration>
|
||||||
|
<option name="GRADLE_PROJECT_PATH" value=":ncsmsgo" />
|
||||||
|
</configuration>
|
||||||
|
</facet>
|
||||||
|
<facet type="java-gradle" name="Java-Gradle">
|
||||||
|
<configuration>
|
||||||
|
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
|
||||||
|
<option name="BUILDABLE" value="false" />
|
||||||
|
</configuration>
|
||||||
|
</facet>
|
||||||
|
</component>
|
||||||
|
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
51
notification_icon.svg
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
enable-background="new 0 0 595.275 311.111"
|
||||||
|
xml:space="preserve"
|
||||||
|
height="546.13336"
|
||||||
|
width="546.13336"
|
||||||
|
version="1.1"
|
||||||
|
y="0px"
|
||||||
|
x="0px"
|
||||||
|
id="svg2"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
inkscape:version="0.92.1 r15371"
|
||||||
|
sodipodi:docname="notification_icon.svg"
|
||||||
|
inkscape:export-filename="C:\DEV\src\Android\Nextcloud\ownCloud-SMS-App\src\main\res\drawable-xxxhdpi\notification_icon.png"
|
||||||
|
inkscape:export-xdpi="16.879999"
|
||||||
|
inkscape:export-ydpi="16.879999"><metadata
|
||||||
|
id="metadata10"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||||
|
id="defs8" /><sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1005"
|
||||||
|
id="namedview6"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="1.4739747"
|
||||||
|
inkscape:cx="140.31712"
|
||||||
|
inkscape:cy="253.09893"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg2" /><path
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.30745259;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0"
|
||||||
|
d="m 76.647972,90.431718 c -24.788364,0 -44.743887,15.887432 -44.743887,35.621852 v 161.78969 c 0,19.73444 19.955523,35.62188 44.743887,35.62188 H 128.01232 L 332.84234,465.77569 266.5124,323.46514 h 168.83961 c 24.7884,0 44.7439,-15.88744 44.7439,-35.62188 V 126.05357 c 0,-19.73442 -19.9555,-35.621852 -44.7439,-35.621852 z M 88.80753,121.0557 h 334.38495 c 12.20514,0 22.03089,6.58929 22.03089,14.77376 v 9.61145 c 0,8.1845 -9.82575,14.77187 -22.03089,14.77187 H 88.80753 c -12.205149,0 -22.030913,-6.58737 -22.030913,-14.77187 v -9.61145 c 0,-8.18447 9.825764,-14.77376 22.030913,-14.77376 z m 0,68.10616 h 334.38495 c 12.20514,0 22.03089,6.5893 22.03089,14.77378 v 9.60954 c 0,8.18448 -9.82575,14.77377 -22.03089,14.77377 H 88.80753 c -12.205149,0 -22.030913,-6.58929 -22.030913,-14.77377 v -9.60954 c 0,-8.18448 9.825764,-14.77378 22.030913,-14.77378 z m 0,67.54597 h 120.79949 c 12.20514,0 22.03088,8.99072 22.03088,17.17521 v 7.20812 c 0,8.18446 -9.82574,14.77376 -22.03088,14.77376 H 88.80753 c -12.205149,0 -22.030913,-6.5893 -22.030913,-14.77376 v -7.20812 c 0,-8.18449 9.825764,-17.17521 22.030913,-17.17521 z"
|
||||||
|
id="rect3350"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="sssscccssssssssssssssssssssssssssssssss" /></svg>
|
After Width: | Height: | Size: 3.1 KiB |
@ -1,15 +0,0 @@
|
|||||||
# This file is automatically generated by Android Tools.
|
|
||||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
|
||||||
#
|
|
||||||
# This file must be checked in Version Control Systems.
|
|
||||||
#
|
|
||||||
# To customize properties used by the Ant build system edit
|
|
||||||
# "ant.properties", and override values to adapt the script to your
|
|
||||||
# project structure.
|
|
||||||
#
|
|
||||||
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
|
||||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
|
||||||
|
|
||||||
# Project target.
|
|
||||||
target=android-21
|
|
||||||
android.library.reference.1=../Owncloud-Android-Library
|
|
Before Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 9.2 KiB |
Before Width: | Height: | Size: 30 KiB |
@ -1,122 +0,0 @@
|
|||||||
<!--
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
* All rights reserved.
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
-->
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
|
||||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
|
||||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
|
||||||
android:paddingTop="@dimen/activity_vertical_margin"
|
|
||||||
tools:context="fr.unix_experience.owncloud_sms.activities.LoginActivity" >
|
|
||||||
|
|
||||||
<!-- Login progress -->
|
|
||||||
|
|
||||||
<ProgressBar
|
|
||||||
android:id="@+id/login_progress"
|
|
||||||
style="?android:attr/progressBarStyleLarge"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:visibility="gone" />
|
|
||||||
|
|
||||||
<ScrollView
|
|
||||||
android:id="@+id/login_form"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent" >
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/email_login_form"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical" >
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/ocsms_logo"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:src="@drawable/login_logo"
|
|
||||||
android:contentDescription="@string/login_logo" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<Spinner
|
|
||||||
android:id="@+id/oc_protocol"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:entries="@array/protocol_array">
|
|
||||||
</Spinner>
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/oc_server"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="@string/prompt_serverURI"
|
|
||||||
android:inputType="textUri" >
|
|
||||||
<requestFocus />
|
|
||||||
</EditText>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<AutoCompleteTextView
|
|
||||||
android:id="@+id/oc_login"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="@string/prompt_login"
|
|
||||||
android:inputType="textEmailAddress"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:singleLine="true" />
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/oc_password"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="@string/prompt_password"
|
|
||||||
android:imeActionId="@+id/oc_login"
|
|
||||||
android:imeActionLabel="@string/action_sign_in_short"
|
|
||||||
android:imeOptions="actionUnspecified"
|
|
||||||
android:inputType="textPassword"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:singleLine="true" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/oc_signin_button"
|
|
||||||
style="?android:textAppearanceSmall"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:text="@string/action_sign_in_short"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
</LinearLayout>
|
|
||||||
</ScrollView>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@ -1,73 +0,0 @@
|
|||||||
<!--
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
* All rights reserved.
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
-->
|
|
||||||
<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="match_parent"
|
|
||||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
|
||||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
|
||||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
|
||||||
android:paddingTop="@dimen/activity_vertical_margin"
|
|
||||||
tools:context="fr.unix_experience.owncloud_sms.MainActivity$PlaceholderFragment" >
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/section_label"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/main_title_welcome"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_alignParentTop="true"
|
|
||||||
android:text="@string/ma_title_welcome"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceLarge" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/main_tv_welcome"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignLeft="@+id/section_label"
|
|
||||||
android:layout_alignStart="@+id/section_label"
|
|
||||||
android:layout_below="@+id/section_label"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:text="@string/ma_content_welcome"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/imageView1"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentBottom="true"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:maxHeight="@dimen/arrow_max_height"
|
|
||||||
android:src="@drawable/next_arrow" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
@ -1,93 +0,0 @@
|
|||||||
<!--
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
* All rights reserved.
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
-->
|
|
||||||
|
|
||||||
<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="match_parent"
|
|
||||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
|
||||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
|
||||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
|
||||||
android:paddingTop="@dimen/activity_vertical_margin"
|
|
||||||
tools:context="fr.unix_experience.owncloud_sms.MainActivity$PlaceholderFragment" >
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_title_thanksto"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_alignParentTop="true"
|
|
||||||
android:text="@string/ma_button_thanksto"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceLarge" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_thankspeople"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_below="@+id/tv_title_thanksto"
|
|
||||||
android:layout_marginTop="15dp"
|
|
||||||
android:text="@string/ma_thanksto_people"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/button_rateus"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@+id/tv_rateUs"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:layout_marginTop="15dp"
|
|
||||||
android:minHeight="36dp"
|
|
||||||
android:text="@string/ma_button_rate_us"
|
|
||||||
android:onClick="openGooglePlayStore"
|
|
||||||
android:background="@drawable/standard_button"
|
|
||||||
style="@style/StandardButton"
|
|
||||||
android:textAlignment="center" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/ma_title_rateus"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignLeft="@+id/tv_thankspeople"
|
|
||||||
android:layout_alignStart="@+id/tv_rateUs"
|
|
||||||
android:layout_below="@+id/tv_thankspeople"
|
|
||||||
android:layout_marginTop="25dp"
|
|
||||||
android:text="@string/ma_title_rate_us"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceLarge" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_rateUs"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="15dp"
|
|
||||||
android:layout_below="@+id/ma_title_rateus"
|
|
||||||
android:text="@string/ma_content_rate_us"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
@ -1,146 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2014, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
* All rights reserved.
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
-->
|
|
||||||
<resources>
|
|
||||||
|
|
||||||
<!-- Translation version, reference for translators -->
|
|
||||||
<string name="translation_version">3</string>
|
|
||||||
|
|
||||||
<!-- Translations must begin there -->
|
|
||||||
<!-- Preferences -->
|
|
||||||
<string name="pref_title_sync">SMS - rychle</string>
|
|
||||||
<string name="pref_title_sync_frequency">Frekvence rychlé synchronizace</string>
|
|
||||||
<string name="pref_title_slow_sync">SMS - pomalu a bezpečně</string>
|
|
||||||
<string name="pref_title_slow_sync_frequency">Frekvence bezpečné pomalé synchronizace</string>
|
|
||||||
<string name="action_settings">Nastavení</string>
|
|
||||||
<string name="sync_now">Synchronizovat teď</string>
|
|
||||||
<string name="pref_category_sync">Synchronizace</string>
|
|
||||||
<string name="title_global_pref_to_general_prefs">Všeobecné možnosti</string>
|
|
||||||
<string name="summary_global_pref_to_general_prefs">Možnosti synchronizace</string>
|
|
||||||
<string name="summary_notif_prefs">Upozornění</string>
|
|
||||||
<string name="pref_header_data_sync">Data a synchronizace</string>
|
|
||||||
<string name="title_activity_general_settings">Hlavní nastavení</string>
|
|
||||||
|
|
||||||
<string-array name="pref_sync_frequency_titles">
|
|
||||||
<item>5 minut</item>
|
|
||||||
<item>15 minut</item>
|
|
||||||
<item>30 minut</item>
|
|
||||||
<item>1 hodina</item>
|
|
||||||
<item>3 hodiny</item>
|
|
||||||
<item>6 hodin</item>
|
|
||||||
<item>12 hodin</item>
|
|
||||||
<item>24 hodin</item>
|
|
||||||
<item>Nikdy</item>
|
|
||||||
</string-array>
|
|
||||||
<string-array name="pref_sync_frequency_values">
|
|
||||||
<item>5</item>
|
|
||||||
<item>15</item>
|
|
||||||
<item>30</item>
|
|
||||||
<item>60</item>
|
|
||||||
<item>180</item>
|
|
||||||
<item>360</item>
|
|
||||||
<item>720</item>
|
|
||||||
<item>1440</item>
|
|
||||||
<item>-1</item>
|
|
||||||
</string-array>
|
|
||||||
<string-array name="pref_slow_sync_frequency_titles">
|
|
||||||
<item>1 hodina</item>
|
|
||||||
<item>3 hodiny</item>
|
|
||||||
<item>6 hodin</item>
|
|
||||||
<item>12 hodin</item>
|
|
||||||
<item>24 hodin</item>
|
|
||||||
<item>Nikdy</item>
|
|
||||||
</string-array>
|
|
||||||
<string-array name="pref_slow_sync_frequency_values">
|
|
||||||
<item>60</item>
|
|
||||||
<item>180</item>
|
|
||||||
<item>360</item>
|
|
||||||
<item>720</item>
|
|
||||||
<item>1440</item>
|
|
||||||
<item>-1</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<string name="title_activity_login">Přihlášení</string>
|
|
||||||
|
|
||||||
<!-- Login -->
|
|
||||||
<string name="prompt_login">Login</string>
|
|
||||||
<string name="prompt_password">Heslo</string>
|
|
||||||
<string name="action_sign_in">Přihlásit se nebo registrovat</string>
|
|
||||||
<string name="action_sign_in_short">Přihlášení</string>
|
|
||||||
<string name="error_invalid_login">Nesprávné jméno nebo heslo</string>
|
|
||||||
<string name="error_invalid_password">Toto heslo je příliš krátké</string>
|
|
||||||
<string name="error_field_required">Toto pole je vyžadováno</string>
|
|
||||||
<string name="prompt_serverURI">Adresa serveru</string>
|
|
||||||
<string name="error_invalid_server_address">Neplatná adresa serveru</string>
|
|
||||||
<string name="error_connection_failed">Připojení selhalo, ujistěte se, že máte správný server</string>
|
|
||||||
<string name="error_http_connection_failed">Nelze provést připojení přes HTTP. Ujistěte se, že je webový server dostupný</string>
|
|
||||||
|
|
||||||
<string-array name="protocol_array">
|
|
||||||
<item>https://</item>
|
|
||||||
<item>http://</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<!-- Main activity -->
|
|
||||||
<string name="ma_button_rate_us">Ohodnoťit!</string>
|
|
||||||
<string name="ma_button_thanksto">Poděkování</string>
|
|
||||||
<string name="ma_title_rate_us">Ohodnoťit!</string>
|
|
||||||
<string name="ma_content_rate_us">Pokud se vám tato aplikace líbí, ohodnoťte ji v Obchodě Google Play</string>
|
|
||||||
<string name="ma_title_add_account">Přidat účet</string>
|
|
||||||
<string name="ma_button_goto_sync">Přejít na Účty a synchronizaci</string>
|
|
||||||
<string name="ma_title_change_settings">Změnit nastavení aplikace</string>
|
|
||||||
<string name="ma_button_goto_settings">Přejít do Nastavení</string>
|
|
||||||
<string name="ma_title_welcome">Vítejte</string>
|
|
||||||
<string name="ma_content_welcome">Vítejte v aplikaci ownCloud SMS. Tato aplikace umožnuje sychronizovat SMS do vašeho účtu na serveru ownCloud. </string>
|
|
||||||
|
|
||||||
<!-- Notifications -->
|
|
||||||
<string name="sync_title">Proces synchronizace</string>
|
|
||||||
<string name="sync_inprogress">Probíhá synchronizace...</string>
|
|
||||||
<string name="fatal_error">Chyba !</string>
|
|
||||||
|
|
||||||
<!-- Errors -->
|
|
||||||
<string name="err_sync_get_smslist">Chyba #1: Přijata neplatná data ze serveru při přijímání předchozích zpráv</string>
|
|
||||||
<string name="err_sync_craft_http_request">Chyba #2: Chyba při vytváření HTTP požadavku</string>
|
|
||||||
<string name="err_sync_push_request">Chyba #3: Požadavek Push selhal</string>
|
|
||||||
<string name="err_sync_push_request_resp">Chyba #4: Přijata neplatná data ze serveru při jejich odesílání</string>
|
|
||||||
<string name="err_sync_create_json_null_smslist">Chyba #5: NULL Sms List</string>
|
|
||||||
<string name="err_sync_create_json_put_smslist">Chyba #6: Chyba při vytváření Push požadavku</string>
|
|
||||||
<string name="err_sync_create_json_request_encoding">Chyba #7: Nepodporované kódování při vytváření požadavku</string>
|
|
||||||
<string name="err_sync_auth_failed">Chyba #8: Ověření selhalo</string>
|
|
||||||
<string name="err_sync_http_request_returncode_unhandled">Chyba #9: Server nastavil neznámý HTTP kód odpovědi</string>
|
|
||||||
<string name="err_sync_http_request_connect">Chyba #11: Nelze se připojit k ownCloud serveru</string>
|
|
||||||
<string name="err_sync_http_request_httpexception">Chyba #12: Nelze se připojit k ownCloud serveru</string>
|
|
||||||
<string name="err_sync_http_request_ioexception">Chyba #13: Nelze se připojit k ownCloud serveru</string>
|
|
||||||
<string name="err_sync_http_request_resp">Chyba #14: Nelze zpracovat odpověď serveru</string>
|
|
||||||
<string name="err_sync_http_request_parse_resp">Chyba #15: Nelze zpracovat odpověď serveru</string>
|
|
||||||
<string name="err_sync_no_connection_available">Chyba #16: Není dostupné datové připojení</string>
|
|
||||||
<string name="title_activity_main">MainActivity</string>
|
|
||||||
<string name="title_section1">Sekce 1</string>
|
|
||||||
<string name="title_section2">Sekce 2</string>
|
|
||||||
<string name="title_section3">Sekce 3</string>
|
|
||||||
<string name="hello_world">Hello world!</string>
|
|
||||||
|
|
||||||
</resources>
|
|
@ -1,133 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2014, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
* All rights reserved.
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
-->
|
|
||||||
<resources>
|
|
||||||
<!-- Translation version, reference for translators -->
|
|
||||||
<string name="translation_version">2</string>
|
|
||||||
|
|
||||||
<!-- Translations must begin there -->
|
|
||||||
<!-- Preferences -->
|
|
||||||
<string name="pref_title_sync">SMS - Schnell</string>
|
|
||||||
<string name="pref_title_sync_frequency">Schnelle Sync-Frequenz</string>
|
|
||||||
<string name="pref_title_slow_sync">SMS - Langsam & Sicher</string>
|
|
||||||
<string name="pref_title_slow_sync_frequency">Langsame Sync-Frequenz</string>
|
|
||||||
<string name="action_settings">Einstellungen</string>
|
|
||||||
<string name="sync_now">Jetzt synchronisieren</string>
|
|
||||||
<string name="pref_category_sync">Synchronisierung</string>
|
|
||||||
|
|
||||||
<string name="title_global_pref_to_general_prefs">Allg. Einstellungen</string>
|
|
||||||
<string name="summary_global_pref_to_general_prefs">Sync-Einstellungen</string>
|
|
||||||
<string name="summary_notif_prefs">Benachrichtigungen</string>
|
|
||||||
|
|
||||||
<string name="pref_header_data_sync">Daten & Sync</string>
|
|
||||||
|
|
||||||
<string name="title_activity_general_settings">Allg. Einstellungen</string>
|
|
||||||
|
|
||||||
<string-array name="pref_sync_frequency_titles">
|
|
||||||
<item>5 Minuten</item>
|
|
||||||
<item>15 Minuten</item>
|
|
||||||
<item>30 Minuten</item>
|
|
||||||
<item>1 Stunde</item>
|
|
||||||
<item>3 Stunden</item>
|
|
||||||
<item>6 Stunden</item>
|
|
||||||
<item>12 Stunden</item>
|
|
||||||
<item>24 Stunden</item>
|
|
||||||
<item>Nie</item>
|
|
||||||
</string-array>
|
|
||||||
<string-array name="pref_sync_frequency_values">
|
|
||||||
<item>5</item>
|
|
||||||
<item>15</item>
|
|
||||||
<item>30</item>
|
|
||||||
<item>60</item>
|
|
||||||
<item>180</item>
|
|
||||||
<item>360</item>
|
|
||||||
<item>720</item>
|
|
||||||
<item>1440</item>
|
|
||||||
<item>-1</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<string-array name="pref_slow_sync_frequency_titles">
|
|
||||||
<item>1 Stunde</item>
|
|
||||||
<item>3 Stunden</item>
|
|
||||||
<item>6 Stunden</item>
|
|
||||||
<item>12 Stunden</item>
|
|
||||||
<item>24 Stunden</item>
|
|
||||||
<item>Nie</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<string-array name="pref_slow_sync_frequency_values">
|
|
||||||
<item>60</item>
|
|
||||||
<item>180</item>
|
|
||||||
<item>360</item>
|
|
||||||
<item>720</item>
|
|
||||||
<item>1440</item>
|
|
||||||
<item>-1</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<string name="title_activity_login">Einloggen</string>
|
|
||||||
|
|
||||||
<!-- Login -->
|
|
||||||
<string name="prompt_login">Login</string>
|
|
||||||
<string name="prompt_password">Passwort</string>
|
|
||||||
<string name="action_sign_in">Einloggen oder Registrieren</string>
|
|
||||||
<string name="action_sign_in_short">Einloggen</string>
|
|
||||||
<string name="error_invalid_login">Falscher Benutzername oder Passwort</string>
|
|
||||||
<string name="error_invalid_password">Dieses Passwort ist zu kurz</string>
|
|
||||||
<string name="error_field_required">Pflichtfeld</string>
|
|
||||||
<string name="prompt_serverURI">Server-Adresse</string>
|
|
||||||
<string name="error_invalid_server_address">Ungültige Serveradresse</string>
|
|
||||||
<string name="error_connection_failed">Verbindung fehlgeschlagen, ist dies der richtige Server?</string>
|
|
||||||
<string name="error_http_connection_failed">Kann keine HTTP-Verbindung aufbauen. Läuft der Webserver unter dieser Adresse?</string>
|
|
||||||
|
|
||||||
<string-array name="protocol_array">
|
|
||||||
<item>https://</item>
|
|
||||||
<item>http://</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<!-- Notifications -->
|
|
||||||
<string name="sync_title">Synchronisation</string>
|
|
||||||
<string name="sync_inprogress">Sychronisation läuft...</string>
|
|
||||||
<string name="fatal_error">Kritischer Fehler!</string>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Errors -->
|
|
||||||
<string name="err_sync_get_smslist">Fehler #1: Bei vorherigen Nachrichten ungültige Serverdaten empfangen</string>
|
|
||||||
<string name="err_sync_craft_http_request">Fehler #2: Fehler bei der Erstellung des HTTP-Requests</string>
|
|
||||||
<string name="err_sync_push_request">Fehler #3: Push-Request fehlgeschlagen</string>
|
|
||||||
<string name="err_sync_push_request_resp">Fehler #4: Beim Pushen von Daten ungültige Serverdaten empfangen</string>
|
|
||||||
<string name="err_sync_create_json_null_smslist">Fehler #5: SMS-Liste gab NULL zurück</string>
|
|
||||||
<string name="err_sync_create_json_put_smslist">Fehler #6: Fehler bei der Erstellung des Push-Requests</string>
|
|
||||||
<string name="err_sync_create_json_request_encoding">Fehler #7: Ungültige Zeichenkodierung bei der Erstellung des Requests</string>
|
|
||||||
<string name="err_sync_auth_failed">Fehler #8: Anmeldung fehlgeschlagen</string>
|
|
||||||
<string name="err_sync_http_request_returncode_unhandled">Fehler #9: Unbekannter HTTP-Antwortcode vom Server</string>
|
|
||||||
<string name="err_sync_http_request_connect">Fehler #11: Konnte nicht mit der ownCloud-Instanz verbinden (HTTP-Request)</string>
|
|
||||||
<string name="err_sync_http_request_httpexception">Fehler #12: Konnte nicht mit der ownCloud-Instanz verbinden (HTTP-Ausnahme)</string>
|
|
||||||
<string name="err_sync_http_request_ioexception">Fehler #13: Konnte nicht mit der ownCloud-Instanz verbinden (IO-Fehler)</string>
|
|
||||||
<string name="err_sync_http_request_resp">Fehler #14: Konnte Server-Antwort nicht parsen</string>
|
|
||||||
<string name="err_sync_http_request_parse_resp">Fehler #15: Konnte Server-Antwort nicht parsen</string>
|
|
||||||
|
|
||||||
</resources>
|
|
@ -1,151 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2014, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
* All rights reserved.
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
-->
|
|
||||||
<resources>
|
|
||||||
<!-- Translation version, reference for translators -->
|
|
||||||
<string name="translation_version">5</string>
|
|
||||||
|
|
||||||
<!-- Translations must begin there -->
|
|
||||||
<!-- Preferences -->
|
|
||||||
<string name="pref_title_sync">Fast Sync</string>
|
|
||||||
<string name="pref_title_sync_frequency">Fast Sync frequency</string>
|
|
||||||
<string name="pref_title_slow_sync">Secure Slow Sync</string>
|
|
||||||
<string name="pref_title_slow_sync_frequency">Secure Slow Sync frequency</string>
|
|
||||||
|
|
||||||
<string name="action_settings">Settings</string>
|
|
||||||
<string name="sync_now">Synchronize now</string>
|
|
||||||
<string name="pref_category_sync">Synchronization</string>
|
|
||||||
|
|
||||||
<string name="title_global_pref_to_general_prefs">General preferences</string>
|
|
||||||
<string name="summary_global_pref_to_general_prefs">Sync options</string>
|
|
||||||
<string name="summary_notif_prefs">Notifications</string>
|
|
||||||
|
|
||||||
<string name="pref_header_data_sync">Data & sync</string>
|
|
||||||
|
|
||||||
<string name="title_activity_general_settings">General Settings</string>
|
|
||||||
|
|
||||||
<string-array name="pref_sync_frequency_titles">
|
|
||||||
<item>5 minutes</item>
|
|
||||||
<item>15 minutes</item>
|
|
||||||
<item>30 minutes</item>
|
|
||||||
<item>1 hour</item>
|
|
||||||
<item>3 hours</item>
|
|
||||||
<item>6 hours</item>
|
|
||||||
<item>12 hours</item>
|
|
||||||
<item>24 hours</item>
|
|
||||||
<item>Never</item>
|
|
||||||
</string-array>
|
|
||||||
<string-array name="pref_sync_frequency_values">
|
|
||||||
<item>5</item>
|
|
||||||
<item>15</item>
|
|
||||||
<item>30</item>
|
|
||||||
<item>60</item>
|
|
||||||
<item>180</item>
|
|
||||||
<item>360</item>
|
|
||||||
<item>720</item>
|
|
||||||
<item>1440</item>
|
|
||||||
<item>-1</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<string-array name="pref_slow_sync_frequency_titles">
|
|
||||||
<item>1 minute</item>
|
|
||||||
<item>1 hour</item>
|
|
||||||
<item>3 hours</item>
|
|
||||||
<item>6 hours</item>
|
|
||||||
<item>12 hours</item>
|
|
||||||
<item>24 hours</item>
|
|
||||||
<item>Never</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<string-array name="pref_slow_sync_frequency_values">
|
|
||||||
<item>1</item>
|
|
||||||
<item>60</item>
|
|
||||||
<item>180</item>
|
|
||||||
<item>360</item>
|
|
||||||
<item>720</item>
|
|
||||||
<item>1440</item>
|
|
||||||
<item>-1</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<string name="title_activity_login">Sign in</string>
|
|
||||||
|
|
||||||
<!-- Login -->
|
|
||||||
<string name="prompt_login">Login</string>
|
|
||||||
<string name="prompt_password">Password </string>
|
|
||||||
<string name="action_sign_in">Sign in or register</string>
|
|
||||||
<string name="action_sign_in_short">Sign in</string>
|
|
||||||
<string name="error_invalid_login">Login or password incorrect</string>
|
|
||||||
<string name="error_invalid_password">This password is too short</string>
|
|
||||||
<string name="error_field_required">This field is required</string>
|
|
||||||
<string name="prompt_serverURI">Server address</string>
|
|
||||||
<string name="error_invalid_server_address">Invalid server address</string>
|
|
||||||
<string name="error_connection_failed">Connection failed, ensure this is the right server</string>
|
|
||||||
<string name="error_http_connection_failed">Unable to perform a HTTP connection. Please ensure there is a web server</string>
|
|
||||||
|
|
||||||
<string-array name="protocol_array">
|
|
||||||
<item>https://</item>
|
|
||||||
<item>http://</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<!-- Main activity -->
|
|
||||||
<string name="ma_button_rate_us">Rate us !</string>
|
|
||||||
<string name="ma_button_thanksto">Thanks to</string>
|
|
||||||
<string name="ma_title_rate_us">Rate us !</string>
|
|
||||||
<string name="ma_content_rate_us">If you like this application, please give rate us on Google Play Store</string>
|
|
||||||
<string name="ma_title_add_account">Add an account</string>
|
|
||||||
<string name="ma_button_goto_sync">Go to Accounts and Sync</string>
|
|
||||||
<string name="ma_title_change_settings">Change app settings</string>
|
|
||||||
<string name="ma_button_goto_settings">Go to Settings</string>
|
|
||||||
<string name="ma_title_welcome">Welcome</string>
|
|
||||||
<string name="ma_content_welcome">Welcome to ownCloud SMS application. This application let you synchronize your SMS to your ownCloud instance using SMS app.</string>
|
|
||||||
<string name="ma_thanksto_people">ownCloud developers\n\
|
|
||||||
Contributors and issue\'s reporters</string>
|
|
||||||
|
|
||||||
<!-- Notifications -->
|
|
||||||
<string name="sync_title">Sync process</string>
|
|
||||||
<string name="sync_inprogress">Sync in progress...</string>
|
|
||||||
<string name="fatal_error">Fatal error ! </string>
|
|
||||||
|
|
||||||
<!-- Errors -->
|
|
||||||
<string name="err_sync_get_smslist">Error #1: Invalid data received from server when getting previous messages</string>
|
|
||||||
<string name="err_sync_craft_http_request">Error #2: Error while crafting HTTP request</string>
|
|
||||||
<string name="err_sync_push_request">Error #3: Push request failed</string>
|
|
||||||
<string name="err_sync_push_request_resp">Error #4: Invalid datas received from server when pushing datas</string>
|
|
||||||
<string name="err_sync_create_json_null_smslist">Error #5: NULL Sms List</string>
|
|
||||||
<string name="err_sync_create_json_put_smslist">Error #6: Error while crafting push request</string>
|
|
||||||
<string name="err_sync_create_json_request_encoding">Error #7: Unsupported encoding when generating request</string>
|
|
||||||
<string name="err_sync_auth_failed">Error #8: Authentication failed</string>
|
|
||||||
<string name="err_sync_http_request_returncode_unhandled">Error #9: Server set unhandled HTTP return code</string>
|
|
||||||
<string name="err_sync_http_request_connect">Error #11: Unable to perform a connection to ownCloud instance</string>
|
|
||||||
<string name="err_sync_http_request_httpexception">Error #12: Unable to perform a connection to ownCloud instance</string>
|
|
||||||
<string name="err_sync_http_request_ioexception">Error #13: Unable to perform a connection to ownCloud instance</string>
|
|
||||||
<string name="err_sync_http_request_resp">Error #14: Unable to parse server response</string>
|
|
||||||
<string name="err_sync_http_request_parse_resp">Error #15: Unable to parse server response</string>
|
|
||||||
<string name="err_sync_no_connection_available">Error #16: No data connection available</string>
|
|
||||||
<string name="err_sync_account_unparsable">Error #17: malformed account. Please reconfigure it</string>
|
|
||||||
|
|
||||||
</resources>
|
|
@ -1,94 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2014, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
* All rights reserved.
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
-->
|
|
||||||
|
|
||||||
<resources>
|
|
||||||
<!-- Translation version, reference for translators -->
|
|
||||||
<string name="translation_version">1</string>
|
|
||||||
|
|
||||||
<!-- Translations must begin there -->
|
|
||||||
<!-- Preferences -->
|
|
||||||
<string name="pref_title_sync_frequency">Frecuencia de sincronización</string>
|
|
||||||
<string name="action_settings">Configuración</string>
|
|
||||||
<string name="sync_now">Sincronizar ahora</string>
|
|
||||||
<string name="pref_category_sync">Sincronización</string>
|
|
||||||
|
|
||||||
<string name="title_global_pref_to_general_prefs">Preferencias generales</string>
|
|
||||||
<string name="summary_global_pref_to_general_prefs">Opciones de sincronización</string>
|
|
||||||
<string name="summary_notif_prefs">Notificaciones</string>
|
|
||||||
|
|
||||||
<string name="pref_header_data_sync">Sincronizar & datos</string>
|
|
||||||
|
|
||||||
<string name="title_activity_general_settings">Configuración general</string>
|
|
||||||
|
|
||||||
<string-array name="pref_sync_frequency_titles">
|
|
||||||
<item>15 minutos</item>
|
|
||||||
<item>30 minutos</item>
|
|
||||||
<item>1 hora</item>
|
|
||||||
<item>3 horas</item>
|
|
||||||
<item>6 horas</item>
|
|
||||||
<item>12 horas</item>
|
|
||||||
<item>24 horas</item>
|
|
||||||
<item>Nunca</item>
|
|
||||||
</string-array>
|
|
||||||
<string-array name="pref_sync_frequency_values">
|
|
||||||
<item>15</item>
|
|
||||||
<item>30</item>
|
|
||||||
<item>60</item>
|
|
||||||
<item>180</item>
|
|
||||||
<item>360</item>
|
|
||||||
<item>720</item>
|
|
||||||
<item>1440</item>
|
|
||||||
<item>-1</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<string name="title_activity_login">Unirse</string>
|
|
||||||
|
|
||||||
<!-- Login -->
|
|
||||||
<string name="prompt_login">Usuario</string>
|
|
||||||
<string name="prompt_password">Contraseña</string>
|
|
||||||
<string name="action_sign_in">Unirse o registrarse</string>
|
|
||||||
<string name="action_sign_in_short">Unirse</string>
|
|
||||||
<string name="error_invalid_login">Usuario o contraseña incorrecto</string>
|
|
||||||
<string name="error_invalid_password">Contraseña demasiado corta</string>
|
|
||||||
<string name="error_field_required">Campo requerido</string>
|
|
||||||
<string name="prompt_serverURI">Dirección del servidor</string>
|
|
||||||
<string name="error_invalid_server_address">Dirección inválida</string>
|
|
||||||
<string name="error_connection_failed">Imposible conectar al servidor. Por favor asegúrese que la dirección del servidor es correcta</string>
|
|
||||||
<string name="error_http_connection_failed">Imposible establecer una conexión HTTP. Por favor asegúrese que el servidor HTTP esta ejecutándose</string>
|
|
||||||
|
|
||||||
<string-array name="protocol_array">
|
|
||||||
<item>https://</item>
|
|
||||||
<item>http://</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<!-- Notifications -->
|
|
||||||
<string name="sync_title">Proceso de sincronización</string>
|
|
||||||
<string name="sync_inprogress">Sincronización en progreso...</string>
|
|
||||||
<string name="fatal_error">Error Fatal ! </string>
|
|
||||||
</resources>
|
|
@ -1,110 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2014, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
* All rights reserved.
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
-->
|
|
||||||
<resources>
|
|
||||||
<!-- Translation version, reference for translators -->
|
|
||||||
<string name="translation_version">3</string>
|
|
||||||
|
|
||||||
<!-- Translations must begin there -->
|
|
||||||
|
|
||||||
<string name="app_name">ownCloud-SMS</string>
|
|
||||||
<string name="action_settings">Paramètres</string>
|
|
||||||
<string name="sync_now">Synchroniser maintenant</string>
|
|
||||||
|
|
||||||
<!-- Preferences -->
|
|
||||||
<string name="pref_category_sync">Synchronisation</string>
|
|
||||||
|
|
||||||
<string name="title_global_pref_to_general_prefs">Préférences générales</string>
|
|
||||||
<string name="summary_global_pref_to_general_prefs">Options de synchronisation</string>
|
|
||||||
<string name="summary_notif_prefs">Notifications</string>
|
|
||||||
|
|
||||||
<string name="pref_header_data_sync">Données & synchronisation</string>
|
|
||||||
<string name="pref_title_sync_frequency">Fréquence de synchronisation</string>
|
|
||||||
<string name="pref_title_sync">SMS - Méthode rapide</string>
|
|
||||||
<string name="pref_title_slow_sync">SMS - Méthode lente (sécurisée)</string>
|
|
||||||
<string name="pref_title_slow_sync_frequency">Fréquence de la synchronisation lente</string>
|
|
||||||
|
|
||||||
<string name="title_activity_general_settings">Préférences générales</string>
|
|
||||||
|
|
||||||
<string-array name="pref_sync_frequency_titles">
|
|
||||||
<item>15 minutes</item>
|
|
||||||
<item>30 minutes</item>
|
|
||||||
<item>1 heure</item>
|
|
||||||
<item>3 heures</item>
|
|
||||||
<item>6 heures</item>
|
|
||||||
<item>12 heures</item>
|
|
||||||
<item>24 heures</item>
|
|
||||||
<item>Jamais</item>
|
|
||||||
</string-array>
|
|
||||||
<string-array name="pref_sync_frequency_values">
|
|
||||||
<item>15</item>
|
|
||||||
<item>30</item>
|
|
||||||
<item>60</item>
|
|
||||||
<item>180</item>
|
|
||||||
<item>360</item>
|
|
||||||
<item>720</item>
|
|
||||||
<item>1440</item>
|
|
||||||
<item>-1</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<string name="title_activity_login">Connexion</string>
|
|
||||||
|
|
||||||
<!-- Login -->
|
|
||||||
<string name="prompt_login">Identifiant</string>
|
|
||||||
<string name="prompt_password">Mot de passe </string>
|
|
||||||
<string name="action_sign_in">S\'enregistrer ou se connecter</string>
|
|
||||||
<string name="action_sign_in_short">Se connecter</string>
|
|
||||||
<string name="error_invalid_login">Identifiant ou mot de passe incorrect</string>
|
|
||||||
<string name="error_invalid_password">Ce mot de passe est trop court</string>
|
|
||||||
<string name="error_field_required">Ce champ est requis</string>
|
|
||||||
<string name="prompt_serverURI">Adresse du serveur</string>
|
|
||||||
<string name="error_invalid_server_address">Adresse invalide</string>
|
|
||||||
<string name="error_connection_failed">Echec de connexion, assurer vous qu\'il s\'agit du bon serveur</string>
|
|
||||||
<string name="error_http_connection_failed">Impossible d\'effectuer la connexion HTTP. Assurez vous qu\'il s\'agit d\'un serveur HTTP</string>
|
|
||||||
|
|
||||||
<!-- Main activity -->
|
|
||||||
<string name="ma_button_rate_us">Notez nous !</string>
|
|
||||||
<string name="ma_button_thanksto">Remerciements</string>
|
|
||||||
<string name="ma_title_rate_us">Notez nous !</string>
|
|
||||||
<string name="ma_content_rate_us">Si vous aimez cette application, n\'hésitez pas à nous noter sur le Google Play Store</string>
|
|
||||||
<string name="ma_title_add_account">Ajouter un compte</string>
|
|
||||||
<string name="ma_button_goto_sync">Ouvrir comptes et synchronisation</string>
|
|
||||||
<string name="ma_title_change_settings">Changer les paramètres de l\'application</string>
|
|
||||||
<string name="ma_button_goto_settings">Aller dans les paramètres</string>
|
|
||||||
<string name="ma_title_welcome">Bienvenue</string>
|
|
||||||
<string name="ma_content_welcome">Bienvenue sur l\'application ownCloud SMS. Cette application va vous permettre de synchroniser vos SMS au sein de votre instance ownCloud en utilisant l\'application dédiée.</string>
|
|
||||||
<string name="ma_thanksto_people">L\'équipe de développement ownCloud\n\
|
|
||||||
Les contributeurs et rapporteurs de bugs</string>
|
|
||||||
|
|
||||||
<!-- Notifications -->
|
|
||||||
<string name="sync_title">Processus de synchronisation</string>
|
|
||||||
<string name="sync_inprogress">Synchonisation en cours...</string>
|
|
||||||
<string name="fatal_error">Erreur fatale ! </string>
|
|
||||||
|
|
||||||
<string name="err_sync_no_connection_available">Erreur #16: Aucune connexion data disponible</string>
|
|
||||||
<string name="err_sync_account_unparsable">Error #17: Compte mal configuré. Merci de bien vouloir le reconfigurer.</string>
|
|
||||||
</resources>
|
|
@ -1,8 +0,0 @@
|
|||||||
<resources>
|
|
||||||
|
|
||||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
|
||||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
|
||||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
|
||||||
<dimen name="arrow_max_height">22dp</dimen>
|
|
||||||
|
|
||||||
</resources>
|
|
@ -1,161 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
* All rights reserved.
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
-->
|
|
||||||
<resources>
|
|
||||||
|
|
||||||
<!-- Translation version, reference for translators -->
|
|
||||||
<string name="translation_version">5</string>
|
|
||||||
|
|
||||||
<!-- System strings, do not translate -->
|
|
||||||
<string name="app_name">ownCloud-SMS</string>
|
|
||||||
<string name="account_type">fr.unix_experience.owncloud_sms</string>
|
|
||||||
<string name="account_authority">fr.unix_experience.owncloud_sms.datasync.provider</string>
|
|
||||||
<string name="slowsync_account_authority">fr.unix_experience.owncloud_sms.datasync.slowsync_provider</string>
|
|
||||||
<string name="target_package">fr.unix_experience.owncloud_sms</string>
|
|
||||||
<string name="login_logo">Login logo</string>
|
|
||||||
|
|
||||||
<!-- System strings: preferences -->
|
|
||||||
<string name="shared_preference_file">ownCloudSMSPrefs</string>
|
|
||||||
<string name="pref_lastmsgdate">last_message_date</string>
|
|
||||||
|
|
||||||
<!-- Translations must begin there -->
|
|
||||||
<!-- Preferences -->
|
|
||||||
<string name="pref_title_sync">SMS - Fast</string>
|
|
||||||
<string name="pref_title_sync_frequency">Fast Sync frequency</string>
|
|
||||||
<string name="pref_title_slow_sync">SMS - Slow and Secure</string>
|
|
||||||
<string name="pref_title_slow_sync_frequency">Secure Slow Sync frequency</string>
|
|
||||||
<string name="action_settings">Settings</string>
|
|
||||||
<string name="sync_now">Synchronize now</string>
|
|
||||||
<string name="pref_category_sync">Synchronization</string>
|
|
||||||
<string name="title_global_pref_to_general_prefs">General preferences</string>
|
|
||||||
<string name="summary_global_pref_to_general_prefs">Sync options</string>
|
|
||||||
<string name="summary_notif_prefs">Notifications</string>
|
|
||||||
<string name="pref_header_data_sync">Data & sync</string>
|
|
||||||
<string name="title_activity_general_settings">General Settings</string>
|
|
||||||
|
|
||||||
<string-array name="pref_sync_frequency_titles">
|
|
||||||
<item>5 minutes</item>
|
|
||||||
<item>15 minutes</item>
|
|
||||||
<item>30 minutes</item>
|
|
||||||
<item>1 hour</item>
|
|
||||||
<item>3 hours</item>
|
|
||||||
<item>6 hours</item>
|
|
||||||
<item>12 hours</item>
|
|
||||||
<item>24 hours</item>
|
|
||||||
<item>Never</item>
|
|
||||||
</string-array>
|
|
||||||
<string-array name="pref_sync_frequency_values">
|
|
||||||
<item>5</item>
|
|
||||||
<item>15</item>
|
|
||||||
<item>30</item>
|
|
||||||
<item>60</item>
|
|
||||||
<item>180</item>
|
|
||||||
<item>360</item>
|
|
||||||
<item>720</item>
|
|
||||||
<item>1440</item>
|
|
||||||
<item>-1</item>
|
|
||||||
</string-array>
|
|
||||||
<string-array name="pref_slow_sync_frequency_titles">
|
|
||||||
<item>1 hour</item>
|
|
||||||
<item>3 hours</item>
|
|
||||||
<item>6 hours</item>
|
|
||||||
<item>12 hours</item>
|
|
||||||
<item>24 hours</item>
|
|
||||||
<item>Never</item>
|
|
||||||
</string-array>
|
|
||||||
<string-array name="pref_slow_sync_frequency_values">
|
|
||||||
<item>60</item>
|
|
||||||
<item>180</item>
|
|
||||||
<item>360</item>
|
|
||||||
<item>720</item>
|
|
||||||
<item>1440</item>
|
|
||||||
<item>-1</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<string name="title_activity_login">Sign in</string>
|
|
||||||
|
|
||||||
<!-- Login -->
|
|
||||||
<string name="prompt_login">Login</string>
|
|
||||||
<string name="prompt_password">Password </string>
|
|
||||||
<string name="action_sign_in">Sign in or register</string>
|
|
||||||
<string name="action_sign_in_short">Sign in</string>
|
|
||||||
<string name="error_invalid_login">Login or password incorrect</string>
|
|
||||||
<string name="error_invalid_password">This password is too short</string>
|
|
||||||
<string name="error_field_required">This field is required</string>
|
|
||||||
<string name="prompt_serverURI">Server address</string>
|
|
||||||
<string name="error_invalid_server_address">Invalid server address</string>
|
|
||||||
<string name="error_connection_failed">Connection failed, ensure this is the right server</string>
|
|
||||||
<string name="error_http_connection_failed">Unable to perform a HTTP connection. Please ensure there is a web server</string>
|
|
||||||
|
|
||||||
<string-array name="protocol_array">
|
|
||||||
<item>https://</item>
|
|
||||||
<item>http://</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<!-- Main activity -->
|
|
||||||
<string name="ma_button_rate_us">Rate us !</string>
|
|
||||||
<string name="ma_button_thanksto">Thanks to</string>
|
|
||||||
<string name="ma_title_rate_us">Rate us !</string>
|
|
||||||
<string name="ma_content_rate_us">If you like this application, please give rate us on Google Play Store</string>
|
|
||||||
<string name="ma_title_add_account">Add an account</string>
|
|
||||||
<string name="ma_button_goto_sync">Go to Accounts and Sync</string>
|
|
||||||
<string name="ma_title_change_settings">Change app settings</string>
|
|
||||||
<string name="ma_button_goto_settings">Go to Settings</string>
|
|
||||||
<string name="ma_title_welcome">Welcome</string>
|
|
||||||
<string name="ma_content_welcome">Welcome to ownCloud SMS application. This application let you synchronize your SMS to your ownCloud instance using SMS app.</string>
|
|
||||||
<string name="ma_thanksto_people">ownCloud developers\n\
|
|
||||||
Contributors and issue\'s reporters</string>
|
|
||||||
|
|
||||||
<!-- Notifications -->
|
|
||||||
<string name="sync_title">Sync process</string>
|
|
||||||
<string name="sync_inprogress">Sync in progress...</string>
|
|
||||||
<string name="fatal_error">Fatal error ! </string>
|
|
||||||
|
|
||||||
<!-- Errors -->
|
|
||||||
<string name="err_sync_get_smslist">Error #1: Invalid data received from server when getting previous messages</string>
|
|
||||||
<string name="err_sync_craft_http_request">Error #2: Error while crafting HTTP request</string>
|
|
||||||
<string name="err_sync_push_request">Error #3: Push request failed</string>
|
|
||||||
<string name="err_sync_push_request_resp">Error #4: Invalid datas received from server when pushing datas</string>
|
|
||||||
<string name="err_sync_create_json_null_smslist">Error #5: NULL SMS List</string>
|
|
||||||
<string name="err_sync_create_json_put_smslist">Error #6: Error while crafting push request</string>
|
|
||||||
<string name="err_sync_create_json_request_encoding">Error #7: Unsupported encoding when generating request</string>
|
|
||||||
<string name="err_sync_auth_failed">Error #8: Authentication failed</string>
|
|
||||||
<string name="err_sync_http_request_returncode_unhandled">Error #9: Server set unhandled HTTP return code</string>
|
|
||||||
<string name="err_sync_http_request_connect">Error #11: Unable to perform a connection to ownCloud instance</string>
|
|
||||||
<string name="err_sync_http_request_httpexception">Error #12: Unable to perform a connection to ownCloud instance</string>
|
|
||||||
<string name="err_sync_http_request_ioexception">Error #13: Unable to perform a connection to ownCloud instance</string>
|
|
||||||
<string name="err_sync_http_request_resp">Error #14: Unable to parse server response</string>
|
|
||||||
<string name="err_sync_http_request_parse_resp">Error #15: Unable to parse server response</string>
|
|
||||||
<string name="err_sync_no_connection_available">Error #16: No data connection available</string>
|
|
||||||
<string name="err_sync_account_unparsable">Error #17: malformed account. Please reconfigure it</string>
|
|
||||||
<string name="title_activity_main">MainActivity</string>
|
|
||||||
<string name="title_section1">Section 1</string>
|
|
||||||
<string name="title_section2">Section 2</string>
|
|
||||||
<string name="title_section3">Section 3</string>
|
|
||||||
<string name="title_activity_main_activity2">MainActivity2</string>
|
|
||||||
|
|
||||||
</resources>
|
|
@ -1,13 +0,0 @@
|
|||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
|
|
||||||
<PreferenceCategory
|
|
||||||
android:title="@string/summary_global_pref_to_general_prefs">
|
|
||||||
<ListPreference
|
|
||||||
android:defaultValue="10"
|
|
||||||
android:entries="@array/pref_sync_frequency_titles"
|
|
||||||
android:entryValues="@array/pref_sync_frequency_values"
|
|
||||||
android:key="sync_frequency"
|
|
||||||
android:negativeButtonText="@null"
|
|
||||||
android:positiveButtonText="@null"
|
|
||||||
android:title="@string/pref_title_sync_frequency" />
|
|
||||||
</PreferenceCategory>
|
|
||||||
</PreferenceScreen>
|
|
BIN
screenshots/login.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
screenshots/settings.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
screenshots/settings2.png
Normal file
After Width: | Height: | Size: 45 KiB |
1
settings.gradle
Normal file
@ -0,0 +1 @@
|
|||||||
|
include ':ncsmsgo'
|
@ -1,240 +0,0 @@
|
|||||||
package fr.unix_experience.owncloud_sms.activities;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as
|
|
||||||
* published by the Free Software Foundation, either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import android.accounts.Account;
|
|
||||||
import android.accounts.AccountManager;
|
|
||||||
import android.annotation.TargetApi;
|
|
||||||
import android.content.ContentResolver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.PeriodicSync;
|
|
||||||
import android.content.res.Configuration;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.preference.ListPreference;
|
|
||||||
import android.preference.Preference;
|
|
||||||
import android.preference.PreferenceActivity;
|
|
||||||
import android.preference.PreferenceFragment;
|
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import fr.unix_experience.owncloud_sms.R;
|
|
||||||
|
|
||||||
public class GeneralSettingsActivity extends PreferenceActivity {
|
|
||||||
private static final boolean ALWAYS_SIMPLE_PREFS = false;
|
|
||||||
static AccountManager mAccountMgr;
|
|
||||||
static String mAccountAuthority;
|
|
||||||
static String mSlowSyncAccountAuthority;
|
|
||||||
static String mAccountType;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostCreate(Bundle savedInstanceState) {
|
|
||||||
super.onPostCreate(savedInstanceState);
|
|
||||||
|
|
||||||
mAccountMgr = AccountManager.get(getBaseContext());
|
|
||||||
mAccountAuthority = getString(R.string.account_authority);
|
|
||||||
mSlowSyncAccountAuthority = getString(R.string.slowsync_account_authority);
|
|
||||||
mAccountType = getString(R.string.account_type);
|
|
||||||
setupSimplePreferencesScreen();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows the simplified settings UI if the device configuration if the
|
|
||||||
* device configuration dictates that a simplified, single-pane UI should be
|
|
||||||
* shown.
|
|
||||||
*/
|
|
||||||
private void setupSimplePreferencesScreen() {
|
|
||||||
if (!isSimplePreferences(this)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// In the simplified UI, fragments are not used at all and we instead
|
|
||||||
// use the older PreferenceActivity APIs.
|
|
||||||
addPreferencesFromResource(R.xml.pref_data_sync);
|
|
||||||
|
|
||||||
// Bind the summaries of EditText/List/Dialog/Ringtone preferences to
|
|
||||||
// their values. When their values change, their summaries are updated
|
|
||||||
// to reflect the new value, per the Android Design guidelines.
|
|
||||||
bindPreferenceSummaryToValue(findPreference("sync_frequency"));
|
|
||||||
//bindPreferenceSummaryToValue(findPreference("slow_sync_frequency"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
public boolean onIsMultiPane() {
|
|
||||||
return isXLargeTablet(this) && !isSimplePreferences(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method to determine if the device has an extra-large screen. For
|
|
||||||
* example, 10" tablets are extra-large.
|
|
||||||
*/
|
|
||||||
private static boolean isXLargeTablet(Context context) {
|
|
||||||
return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines whether the simplified settings UI should be shown. This is
|
|
||||||
* true if this is forced via {@link #ALWAYS_SIMPLE_PREFS}, or the device
|
|
||||||
* doesn't have newer APIs like {@link PreferenceFragment}, or the device
|
|
||||||
* doesn't have an extra-large screen. In these cases, a single-pane
|
|
||||||
* "simplified" settings UI should be shown.
|
|
||||||
*/
|
|
||||||
private static boolean isSimplePreferences(Context context) {
|
|
||||||
return ALWAYS_SIMPLE_PREFS
|
|
||||||
|| Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB
|
|
||||||
|| !isXLargeTablet(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A preference value change listener that updates the preference's summary
|
|
||||||
* to reflect its new value.
|
|
||||||
*/
|
|
||||||
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceChange(Preference preference, Object value) {
|
|
||||||
String stringValue = value.toString();
|
|
||||||
|
|
||||||
if (preference instanceof ListPreference) {
|
|
||||||
// For list preferences, look up the correct display value in
|
|
||||||
// the preference's 'entries' list.
|
|
||||||
ListPreference listPreference = (ListPreference) preference;
|
|
||||||
int index = listPreference.findIndexOfValue(stringValue);
|
|
||||||
|
|
||||||
// Set the summary to reflect the new value.
|
|
||||||
preference
|
|
||||||
.setSummary(index >= 0 ? listPreference.getEntries()[index]
|
|
||||||
: null);
|
|
||||||
|
|
||||||
|
|
||||||
String prefKey = preference.getKey();
|
|
||||||
|
|
||||||
// Handle sync frequency change
|
|
||||||
if (prefKey.equals(new String("sync_frequency"))) {
|
|
||||||
long syncFreq = Long.parseLong((String)value);
|
|
||||||
|
|
||||||
// Get ownCloud SMS account list
|
|
||||||
Account[] myAccountList = mAccountMgr.getAccountsByType(mAccountType);
|
|
||||||
for (int i = 0; i < myAccountList.length; i++) {
|
|
||||||
// And get all authorities for this account
|
|
||||||
List<PeriodicSync> syncList = ContentResolver.getPeriodicSyncs(myAccountList[i], mAccountAuthority);
|
|
||||||
|
|
||||||
boolean foundSameSyncCycle = false;
|
|
||||||
for (int j = 0; j < syncList.size(); j++) {
|
|
||||||
PeriodicSync ps = syncList.get(i);
|
|
||||||
|
|
||||||
if (ps.period == syncFreq && ps.extras.getInt("synctype") == 1) {
|
|
||||||
foundSameSyncCycle = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (foundSameSyncCycle == false) {
|
|
||||||
Bundle b = new Bundle();
|
|
||||||
b.putInt("synctype", 1);
|
|
||||||
|
|
||||||
ContentResolver.removePeriodicSync(myAccountList[i],
|
|
||||||
mAccountAuthority, b);
|
|
||||||
ContentResolver.addPeriodicSync(myAccountList[i],
|
|
||||||
mAccountAuthority, b, syncFreq * 60);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Slow Sync frequency
|
|
||||||
} /*else if (prefKey.equals(new String("slow_sync_frequency"))) {
|
|
||||||
long syncFreq = Long.parseLong((String)value);
|
|
||||||
|
|
||||||
// Get ownCloud SMS account list
|
|
||||||
Account[] myAccountList = mAccountMgr.getAccountsByType(mAccountType);
|
|
||||||
for (int i = 0; i < myAccountList.length; i++) {
|
|
||||||
// And get all authorities for this account
|
|
||||||
List<PeriodicSync> syncList = ContentResolver.getPeriodicSyncs(myAccountList[i], mSlowSyncAccountAuthority);
|
|
||||||
|
|
||||||
boolean foundSameSyncCycle = false;
|
|
||||||
for (int j = 0; j < syncList.size(); j++) {
|
|
||||||
PeriodicSync ps = syncList.get(i);
|
|
||||||
|
|
||||||
if (ps.period == syncFreq && ps.extras.getInt("synctype") == 2) {
|
|
||||||
foundSameSyncCycle = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (foundSameSyncCycle == false) {
|
|
||||||
Bundle b = new Bundle();
|
|
||||||
b.putInt("synctype", 2);
|
|
||||||
|
|
||||||
ContentResolver.removePeriodicSync(myAccountList[i],
|
|
||||||
mSlowSyncAccountAuthority, b);
|
|
||||||
ContentResolver.addPeriodicSync(myAccountList[i],
|
|
||||||
mSlowSyncAccountAuthority, b, syncFreq * 60);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
} else {
|
|
||||||
// For all other preferences, set the summary to the value's
|
|
||||||
// simple string representation.
|
|
||||||
preference.setSummary(stringValue);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Binds a preference's summary to its value. More specifically, when the
|
|
||||||
* preference's value is changed, its summary (line of text below the
|
|
||||||
* preference title) is updated to reflect the value. The summary is also
|
|
||||||
* immediately updated upon calling this method. The exact display format is
|
|
||||||
* dependent on the type of preference.
|
|
||||||
*
|
|
||||||
* @see #sBindPreferenceSummaryToValueListener
|
|
||||||
*/
|
|
||||||
private static void bindPreferenceSummaryToValue(Preference preference) {
|
|
||||||
// Set the listener to watch for value changes.
|
|
||||||
preference
|
|
||||||
.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
|
|
||||||
|
|
||||||
// Trigger the listener immediately with the preference's
|
|
||||||
// current value.
|
|
||||||
sBindPreferenceSummaryToValueListener.onPreferenceChange(
|
|
||||||
preference,
|
|
||||||
PreferenceManager.getDefaultSharedPreferences(
|
|
||||||
preference.getContext()).getString(
|
|
||||||
preference.getKey(),
|
|
||||||
""
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This fragment shows data and sync preferences only. It is used when the
|
|
||||||
* activity is showing a two-pane settings UI.
|
|
||||||
*/
|
|
||||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
|
||||||
public static class DataSyncPreferenceFragment extends PreferenceFragment {
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
addPreferencesFromResource(R.xml.pref_data_sync);
|
|
||||||
|
|
||||||
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
|
|
||||||
// to their values. When their values change, their summaries are
|
|
||||||
// updated to reflect the new value, per the Android Design
|
|
||||||
// guidelines.
|
|
||||||
bindPreferenceSummaryToValue(findPreference("sync_frequency"));
|
|
||||||
//bindPreferenceSummaryToValue(findPreference("slow_sync_frequency"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,166 +0,0 @@
|
|||||||
package fr.unix_experience.owncloud_sms.activities;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
* All rights reserved.
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
import fr.unix_experience.owncloud_sms.R;
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.Fragment;
|
|
||||||
import android.app.FragmentManager;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.provider.Settings;
|
|
||||||
import android.support.v13.app.FragmentPagerAdapter;
|
|
||||||
import android.support.v4.view.PagerAdapter;
|
|
||||||
import android.support.v4.view.ViewPager;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
public class MainActivity extends Activity {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The {@link android.support.v4.view.PagerAdapter} that will provide
|
|
||||||
* fragments for each of the sections. We use a {@link FragmentPagerAdapter}
|
|
||||||
* derivative, which will keep every loaded fragment in memory. If this
|
|
||||||
* becomes too memory intensive, it may be best to switch to a
|
|
||||||
* {@link android.support.v4.app.FragmentStatePagerAdapter}.
|
|
||||||
*/
|
|
||||||
PagerAdapter mPagerAdapter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The {@link ViewPager} that will host the section contents.
|
|
||||||
*/
|
|
||||||
ViewPager mViewPager;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.activity_main);
|
|
||||||
|
|
||||||
// Create the adapter that will return a fragment for each of the three
|
|
||||||
// primary sections of the activity.
|
|
||||||
|
|
||||||
List<Fragment> fragments = new Vector<Fragment>();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Add the Main tabs here
|
|
||||||
*/
|
|
||||||
|
|
||||||
fragments.add(Fragment.instantiate(this,StarterFragment.class.getName()));
|
|
||||||
fragments.add(Fragment.instantiate(this,SecondTestFragment.class.getName()));
|
|
||||||
fragments.add(Fragment.instantiate(this,ThanksAndRateFragment.class.getName()));
|
|
||||||
|
|
||||||
mPagerAdapter = new MainPagerAdapter(getFragmentManager(), fragments);
|
|
||||||
|
|
||||||
// Set up the ViewPager with the sections adapter.
|
|
||||||
mViewPager = (ViewPager) findViewById(R.id.pager);
|
|
||||||
mViewPager.setAdapter(mPagerAdapter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to
|
|
||||||
* one of the sections/tabs/pages.
|
|
||||||
*/
|
|
||||||
public class MainPagerAdapter extends FragmentPagerAdapter {
|
|
||||||
|
|
||||||
private final List<Fragment> mFragments;
|
|
||||||
|
|
||||||
public MainPagerAdapter(FragmentManager fragmentManager, List<Fragment> fragments) {
|
|
||||||
super(fragmentManager);
|
|
||||||
mFragments = fragments;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Fragment getItem(int position) {
|
|
||||||
// getItem is called to instantiate the fragment for the given page.
|
|
||||||
// Return a PlaceholderFragment (defined as a static inner class
|
|
||||||
// below).
|
|
||||||
return mFragments.get(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCount() {
|
|
||||||
// Show 3 total pages.
|
|
||||||
return mFragments.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fragments for activity must be there
|
|
||||||
*/
|
|
||||||
public static class StarterFragment extends Fragment {
|
|
||||||
@Override
|
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
||||||
Bundle savedInstanceState) {
|
|
||||||
View rootView = inflater.inflate(R.layout.fragment_mainactivity_main, container,
|
|
||||||
false);
|
|
||||||
return rootView;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class SecondTestFragment extends Fragment {
|
|
||||||
@Override
|
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
||||||
Bundle savedInstanceState) {
|
|
||||||
View rootView = inflater.inflate(R.layout.fragment_mainactivity_gotosettings, container,
|
|
||||||
false);
|
|
||||||
return rootView;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ThanksAndRateFragment extends Fragment {
|
|
||||||
@Override
|
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
||||||
Bundle savedInstanceState) {
|
|
||||||
View rootView = inflater.inflate(R.layout.fragment_mainactivity_thanks_note, container,
|
|
||||||
false);
|
|
||||||
return rootView;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void openAppSettings(View view) {
|
|
||||||
startActivity(new Intent(this, GeneralSettingsActivity.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void openAddAccount(View view) {
|
|
||||||
startActivity(new Intent(Settings.ACTION_ADD_ACCOUNT));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void openGooglePlayStore(View view) {
|
|
||||||
Intent intent;
|
|
||||||
try {
|
|
||||||
intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + getPackageName()));
|
|
||||||
|
|
||||||
} catch (android.content.ActivityNotFoundException anfe) {
|
|
||||||
intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + getPackageName()));
|
|
||||||
}
|
|
||||||
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
package fr.unix_experience.owncloud_sms.broadcast_receivers;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as
|
|
||||||
* published by the Free Software Foundation, either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
|
|
||||||
import fr.unix_experience.owncloud_sms.engine.ASyncTask;
|
|
||||||
import fr.unix_experience.owncloud_sms.engine.ConnectivityMonitor;
|
|
||||||
import fr.unix_experience.owncloud_sms.engine.SmsFetcher;
|
|
||||||
import fr.unix_experience.owncloud_sms.prefs.OCSMSSharedPrefs;
|
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
public class ConnectivityChanged extends BroadcastReceiver implements ASyncTask {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
ConnectivityMonitor cMon = new ConnectivityMonitor(context);
|
|
||||||
// If data is available and previous dataConnectionState was false, then we need to sync
|
|
||||||
if (cMon.isValid() && dataConnectionAvailable == false) {
|
|
||||||
dataConnectionAvailable = true;
|
|
||||||
Log.d(TAG,"ConnectivityChanged.onReceive, data conn available");
|
|
||||||
checkMessagesToSent(context);
|
|
||||||
}
|
|
||||||
// No data available and previous dataConnectionState was true
|
|
||||||
else if (dataConnectionAvailable == true && !cMon.isValid()) {
|
|
||||||
dataConnectionAvailable = false;
|
|
||||||
Log.d(TAG,"ConnectivityChanges.onReceive: data conn is off");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkMessagesToSent(Context context) {
|
|
||||||
// Get last message synced from preferences
|
|
||||||
Long lastMessageSynced = (new OCSMSSharedPrefs(context)).getLastMessageDate();
|
|
||||||
Log.d(TAG,"Synced Last:" + lastMessageSynced);
|
|
||||||
|
|
||||||
// Now fetch messages since last stored date
|
|
||||||
JSONArray smsList = new SmsFetcher(context).bufferizeMessagesSinceDate(lastMessageSynced);
|
|
||||||
|
|
||||||
if (smsList != null) {
|
|
||||||
new SyncTask(context, smsList).execute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean dataConnectionAvailable = false;
|
|
||||||
|
|
||||||
private static final String TAG = ConnectivityChanged.class.getSimpleName();
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
package fr.unix_experience.owncloud_sms.engine;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as
|
|
||||||
* published by the Free Software Foundation, either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
|
|
||||||
import android.accounts.Account;
|
|
||||||
import android.accounts.AccountManager;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.util.Log;
|
|
||||||
import fr.unix_experience.owncloud_sms.R;
|
|
||||||
import fr.unix_experience.owncloud_sms.exceptions.OCSyncException;
|
|
||||||
|
|
||||||
public interface ASyncTask {
|
|
||||||
class SyncTask extends AsyncTask<Void, Void, Void>{
|
|
||||||
public SyncTask(Context context, JSONArray smsList) {
|
|
||||||
_context = context;
|
|
||||||
_smsList = smsList;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Void doInBackground(Void... params) {
|
|
||||||
// Get ownCloud SMS account list
|
|
||||||
AccountManager _accountMgr = AccountManager.get(_context);
|
|
||||||
|
|
||||||
Account[] myAccountList = _accountMgr.getAccountsByType(_context.getString(R.string.account_type));
|
|
||||||
for (int i = 0; i < myAccountList.length; i++) {
|
|
||||||
Uri serverURI = Uri.parse(_accountMgr.getUserData(myAccountList[i], "ocURI"));
|
|
||||||
|
|
||||||
OCSMSOwnCloudClient _client = new OCSMSOwnCloudClient(_context,
|
|
||||||
serverURI, _accountMgr.getUserData(myAccountList[i], "ocLogin"),
|
|
||||||
_accountMgr.getPassword(myAccountList[i]));
|
|
||||||
|
|
||||||
try {
|
|
||||||
_client.doPushRequest(_smsList);
|
|
||||||
} catch (OCSyncException e) {
|
|
||||||
Log.e(TAG, _context.getString(e.getErrorId()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Context _context;
|
|
||||||
private JSONArray _smsList;
|
|
||||||
}
|
|
||||||
|
|
||||||
static final String TAG = ASyncTask.class.getSimpleName();
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
package fr.unix_experience.owncloud_sms.engine;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as
|
|
||||||
* published by the Free Software Foundation, either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
*/
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.net.ConnectivityManager;
|
|
||||||
|
|
||||||
public class ConnectivityMonitor {
|
|
||||||
public ConnectivityMonitor(Context context) {
|
|
||||||
_context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Valid connection = WiFi or Mobile data
|
|
||||||
public boolean isValid() {
|
|
||||||
if (_cMgr == null) {
|
|
||||||
_cMgr = (ConnectivityManager) _context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
|
||||||
}
|
|
||||||
|
|
||||||
final android.net.NetworkInfo niWiFi = _cMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
|
|
||||||
final android.net.NetworkInfo niMobile = _cMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
|
|
||||||
|
|
||||||
if (niWiFi.isAvailable() || niMobile.isAvailable()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ConnectivityManager _cMgr;
|
|
||||||
private Context _context;
|
|
||||||
}
|
|
@ -1,386 +0,0 @@
|
|||||||
package fr.unix_experience.owncloud_sms.engine;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as
|
|
||||||
* published by the Free Software Foundation, either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.ConnectException;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.HttpException;
|
|
||||||
import org.apache.commons.httpclient.HttpMethod;
|
|
||||||
import org.apache.commons.httpclient.methods.GetMethod;
|
|
||||||
import org.apache.commons.httpclient.methods.PostMethod;
|
|
||||||
import org.apache.commons.httpclient.methods.StringRequestEntity;
|
|
||||||
import org.apache.http.HttpStatus;
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClientFactory;
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudCredentialsFactory;
|
|
||||||
|
|
||||||
import fr.unix_experience.owncloud_sms.R;
|
|
||||||
import fr.unix_experience.owncloud_sms.enums.OCSyncErrorType;
|
|
||||||
import fr.unix_experience.owncloud_sms.exceptions.OCSyncException;
|
|
||||||
import fr.unix_experience.owncloud_sms.prefs.OCSMSSharedPrefs;
|
|
||||||
|
|
||||||
public class OCSMSOwnCloudClient {
|
|
||||||
|
|
||||||
public OCSMSOwnCloudClient(Context context, Uri serverURI, String accountName, String accountPassword) {
|
|
||||||
_context = context;
|
|
||||||
|
|
||||||
_ocClient = OwnCloudClientFactory.createOwnCloudClient(
|
|
||||||
serverURI, _context, true);
|
|
||||||
|
|
||||||
// Set basic credentials
|
|
||||||
_ocClient.setCredentials(
|
|
||||||
OwnCloudCredentialsFactory.newBasicCredentials(accountName, accountPassword)
|
|
||||||
);
|
|
||||||
|
|
||||||
_serverAPIVersion = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getServerAPIVersion() throws OCSyncException {
|
|
||||||
GetMethod get = createGetVersionRequest();
|
|
||||||
JSONObject obj = doHttpRequest(get, true);
|
|
||||||
if (obj == null) {
|
|
||||||
// Return default version
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
_serverAPIVersion = obj.getInt("version");
|
|
||||||
}
|
|
||||||
catch (JSONException e) {
|
|
||||||
Log.e(TAG, "No version received from server, assuming version 1", e);
|
|
||||||
_serverAPIVersion = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _serverAPIVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doPushRequest(JSONArray smsList) throws OCSyncException {
|
|
||||||
/**
|
|
||||||
* If we need other API push, set it here
|
|
||||||
*/
|
|
||||||
switch (_serverAPIVersion) {
|
|
||||||
case 2: doPushRequestV2(smsList); break;
|
|
||||||
case 1:
|
|
||||||
default: doPushRequestV1(smsList); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doPushRequestV1(JSONArray smsList) throws OCSyncException {
|
|
||||||
// We need to save this date as a step for connectivity change
|
|
||||||
Long lastMsgDate = (long) 0;
|
|
||||||
|
|
||||||
if (smsList == null) {
|
|
||||||
GetMethod get = createGetSmsIdListRequest();
|
|
||||||
JSONObject smsGetObj = doHttpRequest(get);
|
|
||||||
if (smsGetObj == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONObject smsBoxes = new JSONObject();
|
|
||||||
JSONArray inboxSmsList = null, sentSmsList = null, draftsSmsList = null;
|
|
||||||
try {
|
|
||||||
smsBoxes = smsGetObj.getJSONObject("smslist");
|
|
||||||
} catch (JSONException e) {
|
|
||||||
try {
|
|
||||||
smsGetObj.getJSONArray("smslist");
|
|
||||||
} catch (JSONException e2) {
|
|
||||||
Log.e(TAG, "Invalid datas received from server (doPushRequest, get SMS list)", e);
|
|
||||||
throw new OCSyncException(R.string.err_sync_get_smslist, OCSyncErrorType.PARSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
inboxSmsList = smsBoxes.getJSONArray("inbox");
|
|
||||||
} catch (JSONException e) {
|
|
||||||
Log.d(TAG, "No inbox Sms received from server (doPushRequest, get SMS list)");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
sentSmsList = smsBoxes.getJSONArray("sent");
|
|
||||||
} catch (JSONException e) {
|
|
||||||
Log.d(TAG, "No sent Sms received from server (doPushRequest, get SMS list)");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
draftsSmsList = smsBoxes.getJSONArray("drafts");
|
|
||||||
} catch (JSONException e) {
|
|
||||||
Log.d(TAG, "No drafts Sms received from server (doPushRequest, get SMS list)");
|
|
||||||
}
|
|
||||||
|
|
||||||
SmsFetcher fetcher = new SmsFetcher(_context);
|
|
||||||
fetcher.setExistingInboxMessages(inboxSmsList);
|
|
||||||
fetcher.setExistingSentMessages(sentSmsList);
|
|
||||||
fetcher.setExistingDraftsMessages(draftsSmsList);
|
|
||||||
|
|
||||||
smsList = fetcher.fetchAllMessages();
|
|
||||||
|
|
||||||
// Get maximum message date present in smsList to keep a step when connectivity changes
|
|
||||||
lastMsgDate = fetcher.getLastMessageDate();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (smsList.length() == 0) {
|
|
||||||
Log.d(TAG, "No new SMS to sync, sync done");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PostMethod post = createPushRequest(smsList);
|
|
||||||
if (post == null) {
|
|
||||||
Log.e(TAG,"Push request for POST is null");
|
|
||||||
throw new OCSyncException(R.string.err_sync_craft_http_request, OCSyncErrorType.IO);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONObject obj = doHttpRequest(post);
|
|
||||||
if (obj == null) {
|
|
||||||
Log.e(TAG,"Request failed. It doesn't return a valid JSON Object");
|
|
||||||
throw new OCSyncException(R.string.err_sync_push_request, OCSyncErrorType.IO);
|
|
||||||
}
|
|
||||||
|
|
||||||
Boolean pushStatus;
|
|
||||||
String pushMessage;
|
|
||||||
try {
|
|
||||||
pushStatus = obj.getBoolean("status");
|
|
||||||
pushMessage = obj.getString("msg");
|
|
||||||
}
|
|
||||||
catch (JSONException e) {
|
|
||||||
Log.e(TAG, "Invalid datas received from server", e);
|
|
||||||
throw new OCSyncException(R.string.err_sync_push_request_resp, OCSyncErrorType.PARSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push was OK, we can save the lastMessageDate which was saved to server
|
|
||||||
(new OCSMSSharedPrefs(_context)).setLastMessageDate(lastMsgDate);
|
|
||||||
|
|
||||||
Log.d(TAG, "SMS Push request said: status " + pushStatus + " - " + pushMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doPushRequestV2(JSONArray smsList) throws OCSyncException {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public GetMethod createGetVersionRequest() {
|
|
||||||
return createGetRequest(OC_GET_VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
public GetMethod createGetSmsIdListRequest() {
|
|
||||||
return createGetRequest(OC_GET_ALL_SMS_IDS);
|
|
||||||
}
|
|
||||||
|
|
||||||
public GetMethod createGetSmsIdListWithStateRequest() {
|
|
||||||
return createGetRequest(OC_GET_ALL_SMS_IDS_WITH_STATUS);
|
|
||||||
}
|
|
||||||
|
|
||||||
public GetMethod createGetLastSmsTimestampRequest() {
|
|
||||||
return createGetRequest(OC_GET_LAST_MSG_TIMESTAMP);
|
|
||||||
}
|
|
||||||
|
|
||||||
private GetMethod createGetRequest(String oc_call) {
|
|
||||||
GetMethod get = new GetMethod(_ocClient.getBaseUri() + oc_call);
|
|
||||||
get.addRequestHeader("OCS-APIREQUEST", "true");
|
|
||||||
return get;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PostMethod createPushRequest() throws OCSyncException {
|
|
||||||
SmsFetcher fetcher = new SmsFetcher(_context);
|
|
||||||
JSONArray smsList = fetcher.fetchAllMessages();
|
|
||||||
return createPushRequest(smsList);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PostMethod createPushRequest(JSONArray smsList) throws OCSyncException {
|
|
||||||
JSONObject obj = createPushJSONObject(smsList);
|
|
||||||
if (obj == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringRequestEntity ent = createJSONRequestEntity(obj);
|
|
||||||
if (ent == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
PostMethod post = new PostMethod(_ocClient.getBaseUri() + OC_PUSH_ROUTE);
|
|
||||||
post.addRequestHeader("OCS-APIREQUEST", "true");
|
|
||||||
post.setRequestEntity(ent);
|
|
||||||
|
|
||||||
return post;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JSONObject createPushJSONObject(JSONArray smsList) throws OCSyncException {
|
|
||||||
if (smsList == null) {
|
|
||||||
Log.e(TAG,"NULL SMS List");
|
|
||||||
throw new OCSyncException(R.string.err_sync_create_json_null_smslist, OCSyncErrorType.IO);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONObject reqJSON = new JSONObject();
|
|
||||||
|
|
||||||
try {
|
|
||||||
reqJSON.put("smsDatas", smsList);
|
|
||||||
reqJSON.put("smsCount", smsList == null ? 0 : smsList.length());
|
|
||||||
} catch (JSONException e) {
|
|
||||||
Log.e(TAG,"JSON Exception when creating JSON request object");
|
|
||||||
throw new OCSyncException(R.string.err_sync_create_json_put_smslist, OCSyncErrorType.PARSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return reqJSON;
|
|
||||||
}
|
|
||||||
|
|
||||||
private StringRequestEntity createJSONRequestEntity(JSONObject obj) throws OCSyncException {
|
|
||||||
StringRequestEntity requestEntity;
|
|
||||||
try {
|
|
||||||
requestEntity = new StringRequestEntity(
|
|
||||||
obj.toString(),
|
|
||||||
"application/json",
|
|
||||||
"UTF-8");
|
|
||||||
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
Log.e(TAG,"Unsupported encoding when generating request");
|
|
||||||
throw new OCSyncException(R.string.err_sync_create_json_request_encoding, OCSyncErrorType.PARSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return requestEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JSONObject doHttpRequest(HttpMethod req) throws OCSyncException {
|
|
||||||
return doHttpRequest(req, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// skipError permit to skip invalid JSON datas
|
|
||||||
private JSONObject doHttpRequest(HttpMethod req, Boolean skipError) throws OCSyncException {
|
|
||||||
JSONObject respJSON = null;
|
|
||||||
int status = 0;
|
|
||||||
|
|
||||||
// We try maximumHttpReqTries because sometimes network is slow or unstable
|
|
||||||
int tryNb = 0;
|
|
||||||
ConnectivityMonitor cMon = new ConnectivityMonitor(_context);
|
|
||||||
|
|
||||||
while (tryNb < maximumHttpReqTries) {
|
|
||||||
tryNb++;
|
|
||||||
|
|
||||||
if (!cMon.isValid()) {
|
|
||||||
if (tryNb == maximumHttpReqTries) {
|
|
||||||
req.releaseConnection();
|
|
||||||
throw new OCSyncException(R.string.err_sync_no_connection_available, OCSyncErrorType.IO);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
status = _ocClient.executeMethod(req);
|
|
||||||
|
|
||||||
Log.d(TAG, "HTTP Request done at try " + tryNb);
|
|
||||||
|
|
||||||
// Force loop exit
|
|
||||||
tryNb = maximumHttpReqTries;
|
|
||||||
} catch (ConnectException e) {
|
|
||||||
Log.e(TAG, "Unable to perform a connection to ownCloud instance", e);
|
|
||||||
|
|
||||||
// If it's the last try
|
|
||||||
if (tryNb == maximumHttpReqTries) {
|
|
||||||
req.releaseConnection();
|
|
||||||
throw new OCSyncException(R.string.err_sync_http_request_connect, OCSyncErrorType.IO);
|
|
||||||
}
|
|
||||||
} catch (HttpException e) {
|
|
||||||
Log.e(TAG, "Unable to perform a connection to ownCloud instance", e);
|
|
||||||
|
|
||||||
// If it's the last try
|
|
||||||
if (tryNb == maximumHttpReqTries) {
|
|
||||||
req.releaseConnection();
|
|
||||||
throw new OCSyncException(R.string.err_sync_http_request_httpexception, OCSyncErrorType.IO);
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(TAG, "Unable to perform a connection to ownCloud instance", e);
|
|
||||||
|
|
||||||
// If it's the last try
|
|
||||||
if (tryNb == maximumHttpReqTries) {
|
|
||||||
req.releaseConnection();
|
|
||||||
throw new OCSyncException(R.string.err_sync_http_request_ioexception, OCSyncErrorType.IO);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(status == HttpStatus.SC_OK) {
|
|
||||||
String response = null;
|
|
||||||
try {
|
|
||||||
response = req.getResponseBodyAsString();
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(TAG, "Unable to parse server response", e);
|
|
||||||
throw new OCSyncException(R.string.err_sync_http_request_resp, OCSyncErrorType.IO);
|
|
||||||
}
|
|
||||||
//Log.d(TAG, "Successful response: " + response);
|
|
||||||
|
|
||||||
// Parse the response
|
|
||||||
try {
|
|
||||||
respJSON = new JSONObject(response);
|
|
||||||
} catch (JSONException e) {
|
|
||||||
if (skipError == false) {
|
|
||||||
Log.e(TAG, "Unable to parse server response", e);
|
|
||||||
throw new OCSyncException(R.string.err_sync_http_request_parse_resp, OCSyncErrorType.PARSE);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (status == HttpStatus.SC_FORBIDDEN) {
|
|
||||||
// Authentication failed
|
|
||||||
throw new OCSyncException(R.string.err_sync_auth_failed, OCSyncErrorType.AUTH);
|
|
||||||
} else {
|
|
||||||
// Unk error
|
|
||||||
String response = null;
|
|
||||||
try {
|
|
||||||
response = req.getResponseBodyAsString();
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(TAG, "Unable to parse server response", e);
|
|
||||||
throw new OCSyncException(R.string.err_sync_http_request_resp, OCSyncErrorType.PARSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.e(TAG, "Server set unhandled HTTP return code " + status);
|
|
||||||
if (response != null) {
|
|
||||||
Log.e(TAG, "Status code: " + status + ". Response message: " + response);
|
|
||||||
} else {
|
|
||||||
Log.e(TAG, "Status code: " + status);
|
|
||||||
}
|
|
||||||
throw new OCSyncException(R.string.err_sync_http_request_returncode_unhandled, OCSyncErrorType.SERVER_ERROR);
|
|
||||||
}
|
|
||||||
return respJSON;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OwnCloudClient getOCClient() { return _ocClient; }
|
|
||||||
|
|
||||||
private static int maximumHttpReqTries = 3;
|
|
||||||
|
|
||||||
private OwnCloudClient _ocClient;
|
|
||||||
private Context _context;
|
|
||||||
|
|
||||||
private Integer _serverAPIVersion;
|
|
||||||
|
|
||||||
private static String OC_GET_VERSION = "/index.php/apps/ocsms/get/apiversion?format=json";
|
|
||||||
private static String OC_GET_ALL_SMS_IDS = "/index.php/apps/ocsms/get/smsidlist?format=json";
|
|
||||||
private static String OC_GET_ALL_SMS_IDS_WITH_STATUS = "/index.php/apps/ocsms/get/smsidstate?format=json";
|
|
||||||
private static String OC_GET_LAST_MSG_TIMESTAMP = "/index.php/apps/ocsms/get/lastmsgtime?format=json";
|
|
||||||
private static String OC_PUSH_ROUTE = "/index.php/apps/ocsms/push?format=json";
|
|
||||||
|
|
||||||
private static final String TAG = OCSMSOwnCloudClient.class.getSimpleName();
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,325 +0,0 @@
|
|||||||
package fr.unix_experience.owncloud_sms.engine;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as
|
|
||||||
* published by the Free Software Foundation, either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import fr.unix_experience.owncloud_sms.enums.MailboxID;
|
|
||||||
import fr.unix_experience.owncloud_sms.providers.SmsDataProvider;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
public class SmsFetcher {
|
|
||||||
public SmsFetcher(Context ct) {
|
|
||||||
_lastMsgDate = (long) 0;
|
|
||||||
_context = ct;
|
|
||||||
|
|
||||||
_existingInboxMessages = null;
|
|
||||||
_existingSentMessages = null;
|
|
||||||
_existingDraftsMessages = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JSONArray fetchAllMessages() {
|
|
||||||
_jsonDataDump = new JSONArray();
|
|
||||||
bufferizeMailboxMessages(MailboxID.INBOX);
|
|
||||||
bufferizeMailboxMessages(MailboxID.SENT);
|
|
||||||
bufferizeMailboxMessages(MailboxID.DRAFTS);
|
|
||||||
return _jsonDataDump;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void bufferizeMailboxMessages(MailboxID mbID) {
|
|
||||||
String mbURI = mapMailboxIDToURI(mbID);
|
|
||||||
|
|
||||||
if (_context == null || mbURI == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mbID != MailboxID.INBOX && mbID != MailboxID.SENT &&
|
|
||||||
mbID != MailboxID.DRAFTS) {
|
|
||||||
Log.e(TAG,"Unhandled MailboxID " + mbID.ordinal());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We generate a ID list for this message box
|
|
||||||
String existingIDs = buildExistingMessagesString(mbID);
|
|
||||||
|
|
||||||
Cursor c = null;
|
|
||||||
if (existingIDs.length() > 0) {
|
|
||||||
c = (new SmsDataProvider(_context)).query(mbURI, "_id NOT IN (" + existingIDs + ")");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
c = (new SmsDataProvider(_context)).query(mbURI);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reading mailbox
|
|
||||||
if (c != null && c.getCount() > 0) {
|
|
||||||
c.moveToFirst();
|
|
||||||
do {
|
|
||||||
JSONObject entry = new JSONObject();
|
|
||||||
|
|
||||||
try {
|
|
||||||
for(int idx=0;idx<c.getColumnCount();idx++) {
|
|
||||||
String colName = c.getColumnName(idx);
|
|
||||||
|
|
||||||
// Id column is must be an integer
|
|
||||||
if (colName.equals(new String("_id")) ||
|
|
||||||
colName.equals(new String("type"))) {
|
|
||||||
entry.put(colName, c.getInt(idx));
|
|
||||||
|
|
||||||
// bufferize Id for future use
|
|
||||||
if (colName.equals(new String("_id"))) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Seen and read must be pseudo boolean
|
|
||||||
else if (colName.equals(new String("read")) ||
|
|
||||||
colName.equals(new String("seen"))) {
|
|
||||||
entry.put(colName, c.getInt(idx) > 0 ? "true" : "false");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Special case for date, we need to record last without searching
|
|
||||||
if (colName.equals(new String("date"))) {
|
|
||||||
final Long tmpDate = c.getLong(idx);
|
|
||||||
if (tmpDate > _lastMsgDate) {
|
|
||||||
_lastMsgDate = tmpDate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
entry.put(colName, c.getString(idx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mailbox ID is required by server
|
|
||||||
entry.put("mbox", mbID.ordinal());
|
|
||||||
|
|
||||||
_jsonDataDump.put(entry);
|
|
||||||
|
|
||||||
} catch (JSONException e) {
|
|
||||||
Log.e(TAG, "JSON Exception when reading SMS Mailbox", e);
|
|
||||||
c.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while(c.moveToNext());
|
|
||||||
|
|
||||||
Log.d(TAG, c.getCount() + " messages read from " + mbURI);
|
|
||||||
|
|
||||||
c.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used by Content Observer
|
|
||||||
public JSONArray getLastMessage(MailboxID mbID) {
|
|
||||||
String mbURI = mapMailboxIDToURI(mbID);
|
|
||||||
|
|
||||||
if (_context == null || mbURI == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch Sent SMS Message from Built-in Content Provider
|
|
||||||
Cursor c = (new SmsDataProvider(_context)).query(mbURI);
|
|
||||||
|
|
||||||
c.moveToNext();
|
|
||||||
|
|
||||||
// We create a list of strings to store results
|
|
||||||
JSONArray results = new JSONArray();
|
|
||||||
|
|
||||||
JSONObject entry = new JSONObject();
|
|
||||||
|
|
||||||
try {
|
|
||||||
for(int idx=0;idx<c.getColumnCount();idx++) {
|
|
||||||
String colName = c.getColumnName(idx);
|
|
||||||
|
|
||||||
// Id column is must be an integer
|
|
||||||
if (colName.equals(new String("_id")) ||
|
|
||||||
colName.equals(new String("type"))) {
|
|
||||||
entry.put(colName, c.getInt(idx));
|
|
||||||
|
|
||||||
// bufferize Id for future use
|
|
||||||
if (colName.equals(new String("_id"))) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Seen and read must be pseudo boolean
|
|
||||||
else if (colName.equals(new String("read")) ||
|
|
||||||
colName.equals(new String("seen"))) {
|
|
||||||
entry.put(colName, c.getInt(idx) > 0 ? "true" : "false");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
entry.put(colName, c.getString(idx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mailbox ID is required by server
|
|
||||||
entry.put("mbox", mbID.ordinal());
|
|
||||||
|
|
||||||
results.put(entry);
|
|
||||||
} catch (JSONException e) {
|
|
||||||
Log.e(TAG, "JSON Exception when reading SMS Mailbox", e);
|
|
||||||
c.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
c.close();
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used by ConnectivityChanged Event
|
|
||||||
public JSONArray bufferizeMessagesSinceDate(Long sinceDate) {
|
|
||||||
_jsonDataDump = new JSONArray();
|
|
||||||
bufferizeMessagesSinceDate(MailboxID.INBOX, sinceDate);
|
|
||||||
bufferizeMessagesSinceDate(MailboxID.SENT, sinceDate);
|
|
||||||
bufferizeMessagesSinceDate(MailboxID.DRAFTS, sinceDate);
|
|
||||||
return _jsonDataDump;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used by ConnectivityChanged Event
|
|
||||||
public void bufferizeMessagesSinceDate(MailboxID mbID, Long sinceDate) {
|
|
||||||
String mbURI = mapMailboxIDToURI(mbID);
|
|
||||||
|
|
||||||
if (_context == null || mbURI == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Cursor c = new SmsDataProvider(_context).query(mbURI, "date > ?", new String[] { sinceDate.toString() });
|
|
||||||
|
|
||||||
// Reading mailbox
|
|
||||||
if (c != null && c.getCount() > 0) {
|
|
||||||
c.moveToFirst();
|
|
||||||
do {
|
|
||||||
JSONObject entry = new JSONObject();
|
|
||||||
|
|
||||||
try {
|
|
||||||
for(int idx=0;idx<c.getColumnCount();idx++) {
|
|
||||||
String colName = c.getColumnName(idx);
|
|
||||||
|
|
||||||
// Id column is must be an integer
|
|
||||||
if (colName.equals(new String("_id")) ||
|
|
||||||
colName.equals(new String("type"))) {
|
|
||||||
entry.put(colName, c.getInt(idx));
|
|
||||||
|
|
||||||
// bufferize Id for future use
|
|
||||||
if (colName.equals(new String("_id"))) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Seen and read must be pseudo boolean
|
|
||||||
else if (colName.equals(new String("read")) ||
|
|
||||||
colName.equals(new String("seen"))) {
|
|
||||||
entry.put(colName, c.getInt(idx) > 0 ? "true" : "false");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Special case for date, we need to record last without searching
|
|
||||||
if (colName.equals(new String("date"))) {
|
|
||||||
final Long tmpDate = c.getLong(idx);
|
|
||||||
if (tmpDate > _lastMsgDate) {
|
|
||||||
_lastMsgDate = tmpDate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
entry.put(colName, c.getString(idx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mailbox ID is required by server
|
|
||||||
entry.put("mbox", mbID.ordinal());
|
|
||||||
|
|
||||||
_jsonDataDump.put(entry);
|
|
||||||
|
|
||||||
} catch (JSONException e) {
|
|
||||||
Log.e(TAG, "JSON Exception when reading SMS Mailbox", e);
|
|
||||||
c.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while(c.moveToNext());
|
|
||||||
|
|
||||||
Log.d(TAG, c.getCount() + " messages read from " + mbURI);
|
|
||||||
|
|
||||||
c.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String mapMailboxIDToURI(MailboxID mbID) {
|
|
||||||
if (mbID == MailboxID.INBOX) {
|
|
||||||
return "content://sms/inbox";
|
|
||||||
}
|
|
||||||
else if (mbID == MailboxID.DRAFTS) {
|
|
||||||
return "content://sms/drafts";
|
|
||||||
}
|
|
||||||
else if (mbID == MailboxID.SENT) {
|
|
||||||
return "content://sms/sent";
|
|
||||||
}
|
|
||||||
else if (mbID == MailboxID.ALL) {
|
|
||||||
return "content://sms";
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String buildExistingMessagesString(MailboxID _mbID) {
|
|
||||||
JSONArray existingMessages = null;
|
|
||||||
if (_mbID == MailboxID.INBOX) {
|
|
||||||
existingMessages = _existingInboxMessages;
|
|
||||||
} else if (_mbID == MailboxID.DRAFTS) {
|
|
||||||
existingMessages = _existingDraftsMessages;
|
|
||||||
} else if (_mbID == MailboxID.SENT) {
|
|
||||||
existingMessages = _existingSentMessages;
|
|
||||||
}
|
|
||||||
// Note: The default case isn't possible, we check the mailbox before
|
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
if (existingMessages != null) {
|
|
||||||
int len = existingMessages.length();
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
try {
|
|
||||||
if (sb.length() > 0) {
|
|
||||||
sb.append(",");
|
|
||||||
}
|
|
||||||
sb.append(existingMessages.getInt(i));
|
|
||||||
} catch (JSONException e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExistingInboxMessages(JSONArray inboxMessages) {
|
|
||||||
_existingInboxMessages = inboxMessages;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExistingSentMessages(JSONArray sentMessages) {
|
|
||||||
_existingSentMessages = sentMessages;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExistingDraftsMessages(JSONArray draftMessages) {
|
|
||||||
_existingDraftsMessages = draftMessages;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getLastMessageDate() {
|
|
||||||
return _lastMsgDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Context _context;
|
|
||||||
private JSONArray _jsonDataDump;
|
|
||||||
private JSONArray _existingInboxMessages;
|
|
||||||
private JSONArray _existingSentMessages;
|
|
||||||
private JSONArray _existingDraftsMessages;
|
|
||||||
|
|
||||||
private Long _lastMsgDate;
|
|
||||||
|
|
||||||
private static final String TAG = SmsFetcher.class.getSimpleName();
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
package fr.unix_experience.owncloud_sms.notifications;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as
|
|
||||||
* published by the Free Software Foundation, either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import fr.unix_experience.owncloud_sms.R;
|
|
||||||
import fr.unix_experience.owncloud_sms.enums.OCSMSNotificationType;
|
|
||||||
import android.annotation.TargetApi;
|
|
||||||
import android.app.Notification;
|
|
||||||
import android.app.Notification.Builder;
|
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Build;
|
|
||||||
|
|
||||||
public class OCSMSNotification {
|
|
||||||
public OCSMSNotification(Context ct) {
|
|
||||||
_ct = ct;
|
|
||||||
}
|
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
|
||||||
public boolean createNotify(OCSMSNotificationType nType, String nTitle, String nText) {
|
|
||||||
if (_ct == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
NotificationManager notificationManager = (NotificationManager)_ct.getSystemService(Context.NOTIFICATION_SERVICE);
|
|
||||||
|
|
||||||
Builder mBuilder = new Notification.Builder(_ct)
|
|
||||||
.setContentText(nText)
|
|
||||||
.setContentTitle(nTitle)
|
|
||||||
.setSmallIcon(R.drawable.ic_launcher);
|
|
||||||
|
|
||||||
notificationManager.notify(nType.ordinal(), mBuilder.build());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
|
||||||
public void cancelNotify(OCSMSNotificationType nType) {
|
|
||||||
NotificationManager notificationManager = (NotificationManager)_ct.getSystemService(Context.NOTIFICATION_SERVICE);
|
|
||||||
notificationManager.cancel(nType.ordinal());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Context _ct;
|
|
||||||
}
|
|
@ -1,66 +0,0 @@
|
|||||||
package fr.unix_experience.owncloud_sms.notifications;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as
|
|
||||||
* published by the Free Software Foundation, either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import fr.unix_experience.owncloud_sms.R;
|
|
||||||
import fr.unix_experience.owncloud_sms.enums.OCSMSNotificationType;
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
public class OCSMSNotificationManager {
|
|
||||||
|
|
||||||
public OCSMSNotificationManager(Context context) {
|
|
||||||
_context = context;
|
|
||||||
_notification = new OCSMSNotification(_context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSyncProcessMsg() {
|
|
||||||
createNotificationIfPossible(OCSMSNotificationType.SYNC,
|
|
||||||
_context.getString(R.string.sync_title),
|
|
||||||
_context.getString(R.string.sync_inprogress)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void dropSyncProcessMsg() {
|
|
||||||
_notification.cancelNotify(OCSMSNotificationType.SYNC);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSyncErrorMsg(String errMsg) {
|
|
||||||
createNotificationIfPossible(OCSMSNotificationType.SYNC_FAILED,
|
|
||||||
_context.getString(R.string.sync_title),
|
|
||||||
_context.getString(R.string.fatal_error) + "\n" + errMsg
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void dropSyncErrorMsg() {
|
|
||||||
_notification.cancelNotify(OCSMSNotificationType.SYNC_FAILED);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDebugMsg(String errMsg) {
|
|
||||||
createNotificationIfPossible(OCSMSNotificationType.DEBUG,
|
|
||||||
"DEBUG", errMsg
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createNotificationIfPossible(OCSMSNotificationType nType, String nTitle, String nMsg) {
|
|
||||||
_notification.createNotify(nType, nTitle, nMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Context _context;
|
|
||||||
private OCSMSNotification _notification;
|
|
||||||
|
|
||||||
}
|
|
@ -1,98 +0,0 @@
|
|||||||
package fr.unix_experience.owncloud_sms.providers;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as
|
|
||||||
* published by the Free Software Foundation, either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import android.content.ContentProvider;
|
|
||||||
import android.content.ContentValues;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.net.Uri;
|
|
||||||
|
|
||||||
public class SmsDataProvider extends ContentProvider {
|
|
||||||
public SmsDataProvider () {}
|
|
||||||
|
|
||||||
public SmsDataProvider (Context ct) {
|
|
||||||
super();
|
|
||||||
_context = ct;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCreate() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Cursor query(String mailBox) {
|
|
||||||
return query(Uri.parse(mailBox),
|
|
||||||
new String[] { "read", "date", "address", "seen", "body", "_id", "type", },
|
|
||||||
null, null, null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Cursor query(String mailBox, String selection) {
|
|
||||||
return query(Uri.parse(mailBox),
|
|
||||||
new String[] { "read", "date", "address", "seen", "body", "_id", "type", },
|
|
||||||
selection, null, null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Cursor query(String mailBox, String selection, String[] selectionArgs) {
|
|
||||||
return query(Uri.parse(mailBox),
|
|
||||||
new String[] { "read", "date", "address", "seen", "body", "_id", "type", },
|
|
||||||
selection, selectionArgs, null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Cursor query(Uri uri, String[] projection, String selection,
|
|
||||||
String[] selectionArgs, String sortOrder) {
|
|
||||||
if (_context != null && _context.getContentResolver() != null) {
|
|
||||||
return _context.getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getType(Uri uri) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Uri insert(Uri uri, ContentValues values) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int delete(Uri uri, String selection, String[] selectionArgs) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int update(Uri uri, ContentValues values, String selection,
|
|
||||||
String[] selectionArgs) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Context _context;
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
package fr.unix_experience.owncloud_sms.sync_adapters;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
|
||||||
* All rights reserved.
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import android.app.Service;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.IBinder;
|
|
||||||
|
|
||||||
public class SmsSlowSyncService extends Service {
|
|
||||||
// Storage for an instance of the sync adapter
|
|
||||||
private static SmsSyncAdapter _adapter = null;
|
|
||||||
// Object to use as a thread-safe lock
|
|
||||||
private static final Object sSyncAdapterLock = new Object();
|
|
||||||
/*
|
|
||||||
* Instantiate the sync adapter object.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
/*
|
|
||||||
* Create the sync adapter as a singleton.
|
|
||||||
* Set the sync adapter as syncable
|
|
||||||
* Disallow parallel syncs
|
|
||||||
*/
|
|
||||||
synchronized (sSyncAdapterLock) {
|
|
||||||
if (_adapter == null) {
|
|
||||||
_adapter = new SmsSyncAdapter(getApplicationContext(), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Return an object that allows the system to invoke
|
|
||||||
* the sync adapter.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public IBinder onBind(Intent intent) {
|
|
||||||
/*
|
|
||||||
* Get the object that allows external processes
|
|
||||||
* to call onPerformSync(). The object is created
|
|
||||||
* in the base class code when the SyncAdapter
|
|
||||||
* constructors call super()
|
|
||||||
*/
|
|
||||||
return _adapter.getSyncAdapterBinder();
|
|
||||||
}
|
|
||||||
}
|
|
167
src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
package="fr.unix_experience.owncloud_sms"> <!-- From Android 4.1 to O -->
|
||||||
|
<uses-sdk android:maxSdkVersion="26" />
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.READ_SMS" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_SMS" />
|
||||||
|
|
||||||
|
<!-- For SMS Restore & Sending -->
|
||||||
|
<uses-permission android:name="android.permission.SEND_SMS" />
|
||||||
|
|
||||||
|
<!-- For SMS Broadcaster -->
|
||||||
|
<uses-permission android:name="android.permission.RECEIVE_SMS" />
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
|
||||||
|
<!-- For syncer -->
|
||||||
|
<uses-permission android:name="android.permission.READ_SYNC_STATS" />
|
||||||
|
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
|
|
||||||
|
<!-- For account management -->
|
||||||
|
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
||||||
|
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
|
||||||
|
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
|
||||||
|
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
|
||||||
|
|
||||||
|
<!-- For backup restauration -->
|
||||||
|
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||||
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
|
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
|
android:theme="@style/OcSmsTheme">
|
||||||
|
|
||||||
|
<!-- Related to periodic sync -->
|
||||||
|
<service
|
||||||
|
android:name=".sync_adapters.SmsSyncService"
|
||||||
|
android:exported="true"
|
||||||
|
android:process=":sync">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.content.SyncAdapter" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="android.content.SyncAdapter"
|
||||||
|
android:resource="@xml/sync_adapter" />
|
||||||
|
</service>
|
||||||
|
|
||||||
|
<provider
|
||||||
|
android:name=".providers.SmsDataProvider"
|
||||||
|
android:authorities="@string/account_authority"
|
||||||
|
android:label="@string/pref_title_sync"></provider>
|
||||||
|
|
||||||
|
<!-- Related to Login -->
|
||||||
|
<service android:name=".authenticators.OwnCloudAuthenticatorService">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.accounts.AccountAuthenticator" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="android.accounts.AccountAuthenticator"
|
||||||
|
android:resource="@xml/owncloud_account_authenticator" />
|
||||||
|
</service>
|
||||||
|
|
||||||
|
<receiver
|
||||||
|
android:name=".broadcast_receivers.IncomingSms"
|
||||||
|
android:permission="android.permission.BROADCAST_SMS">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
|
||||||
|
<action android:name="android.provider.Telephony.SMS_DELIVER" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<!-- BroadcastReceiver that listens for incoming MMS messages. Note: useless class, used only for restoring SMS -->
|
||||||
|
<receiver
|
||||||
|
android:name=".misc.MmsReceiver"
|
||||||
|
android:permission="android.permission.BROADCAST_WAP_PUSH">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
|
||||||
|
|
||||||
|
<data android:mimeType="application/vnd.wap.mms-message" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<!-- Activity that allows the user to send new SMS/MMS messages Note: useless class, used only for restoring SMS -->
|
||||||
|
<activity android:name=".misc.ComposeSmsActivity">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.SEND" />
|
||||||
|
<action android:name="android.intent.action.SENDTO" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
|
<data android:scheme="sms" />
|
||||||
|
<data android:scheme="smsto" />
|
||||||
|
<data android:scheme="mms" />
|
||||||
|
<data android:scheme="mmsto" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<!-- Service that delivers messages from the phone "quick response" Note: useless class, used only for restoring SMS -->
|
||||||
|
<service
|
||||||
|
android:name=".misc.HeadlessSmsSendService"
|
||||||
|
android:exported="true"
|
||||||
|
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
|
||||||
|
<data android:scheme="sms" />
|
||||||
|
<data android:scheme="smsto" />
|
||||||
|
<data android:scheme="mms" />
|
||||||
|
<data android:scheme="mmsto" />
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
|
||||||
|
<receiver android:name=".broadcast_receivers.ConnectivityChanged">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".activities.LoginActivity"
|
||||||
|
android:label="@string/title_activity_login"
|
||||||
|
android:theme="@style/OcSmsTheme.Login"></activity>
|
||||||
|
<activity
|
||||||
|
android:name=".activities.remote_account.AccountListActivity"
|
||||||
|
android:label="@string/title_activity_select_account"></activity>
|
||||||
|
<activity
|
||||||
|
android:name=".activities.OCSMSSettingsActivity"
|
||||||
|
android:label="@string/title_activity_general_settings"></activity>
|
||||||
|
<activity
|
||||||
|
android:name=".activities.MainActivity"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:theme="@style/OcSmsTheme.Drawer">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name=".activities.remote_account.ContactListActivity"
|
||||||
|
android:label="@string/title_activity_select_contact"></activity>
|
||||||
|
<activity
|
||||||
|
android:name=".activities.remote_account.AccountActionsActivity"
|
||||||
|
android:label="@string/account_actions"></activity>
|
||||||
|
<activity
|
||||||
|
android:name=".activities.remote_account.RestoreMessagesActivity"
|
||||||
|
android:label="@string/restore_all_messages"></activity>
|
||||||
|
<activity
|
||||||
|
android:name=".activities.PrivacyPolicyActivity"
|
||||||
|
android:label="@string/action_appinfo_privacy_policy"
|
||||||
|
android:theme="@style/OcSmsTheme.NoActionBar"></activity>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
BIN
src/main/ic_launcher-web.png
Normal file
After Width: | Height: | Size: 37 KiB |
@ -0,0 +1,292 @@
|
|||||||
|
package fr.unix_experience.android_lib;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.ListAdapter;
|
||||||
|
import android.widget.ListView;
|
||||||
|
|
||||||
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An activity that displays a list of items by binding to a data source such as
|
||||||
|
* an array or Cursor, and exposes event handlers when the user selects an item.
|
||||||
|
* <p>
|
||||||
|
* ListActivity hosts a {@link android.widget.ListView ListView} object that can
|
||||||
|
* be bound to different data sources, typically either an array or a Cursor
|
||||||
|
* holding query results. Binding, screen layout, and row layout are discussed
|
||||||
|
* in the following sections.
|
||||||
|
* <p>
|
||||||
|
* <strong>Screen Layout</strong>
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* ListActivity has a default layout that consists of a single, full-screen list
|
||||||
|
* in the center of the screen. However, if you desire, you can customize the
|
||||||
|
* screen layout by setting your own view layout with setContentView() in
|
||||||
|
* onCreate(). To do this, your own view MUST contain a ListView object with the
|
||||||
|
* id "@android:id/list" (or {@link android.R.id#list} if it's in code)
|
||||||
|
* <p>
|
||||||
|
* Optionally, your custom view can contain another view object of any type to
|
||||||
|
* display when the list view is empty. This "empty list" notifier must have an
|
||||||
|
* id "android:id/empty". Note that when an empty view is present, the list view
|
||||||
|
* will be hidden when there is no data to display.
|
||||||
|
* <p>
|
||||||
|
* The following code demonstrates an (ugly) custom screen layout. It has a list
|
||||||
|
* with a green background, and an alternate red "no data" message.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* <?xml version="1.0" encoding="utf-8"?>
|
||||||
|
* <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
* android:orientation="vertical"
|
||||||
|
* android:layout_width="match_parent"
|
||||||
|
* android:layout_height="match_parent"
|
||||||
|
* android:paddingLeft="8dp"
|
||||||
|
* android:paddingRight="8dp">
|
||||||
|
*
|
||||||
|
* <ListView android:id="@android:id/list"
|
||||||
|
* android:layout_width="match_parent"
|
||||||
|
* android:layout_height="match_parent"
|
||||||
|
* android:background="#00FF00"
|
||||||
|
* android:layout_weight="1"
|
||||||
|
* android:drawSelectorOnTop="false"/>
|
||||||
|
*
|
||||||
|
* <TextView android:id="@android:id/empty"
|
||||||
|
* android:layout_width="match_parent"
|
||||||
|
* android:layout_height="match_parent"
|
||||||
|
* android:background="#FF0000"
|
||||||
|
* android:text="No data"/>
|
||||||
|
* </LinearLayout>
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* <strong>Row Layout</strong>
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* You can specify the layout of individual rows in the list. You do this by
|
||||||
|
* specifying a layout resource in the ListAdapter object hosted by the activity
|
||||||
|
* (the ListAdapter binds the ListView to the data; more on this later).
|
||||||
|
* <p>
|
||||||
|
* A ListAdapter constructor takes a parameter that specifies a layout resource
|
||||||
|
* for each row. It also has two additional parameters that let you specify
|
||||||
|
* which data field to associate with which object in the row layout resource.
|
||||||
|
* These two parameters are typically parallel arrays.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Android provides some standard row layout resources. These are in the
|
||||||
|
* {@link android.R.layout} class, and have names such as simple_list_item_1,
|
||||||
|
* simple_list_item_2, and two_line_list_item. The following layout XML is the
|
||||||
|
* source for the resource two_line_list_item, which displays two data
|
||||||
|
* fields,one above the other, for each list row.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* <?xml version="1.0" encoding="utf-8"?>
|
||||||
|
* <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
* android:layout_width="match_parent"
|
||||||
|
* android:layout_height="wrap_content"
|
||||||
|
* android:orientation="vertical">
|
||||||
|
*
|
||||||
|
* <TextView android:id="@+id/text1"
|
||||||
|
* android:textSize="16sp"
|
||||||
|
* android:textStyle="bold"
|
||||||
|
* android:layout_width="match_parent"
|
||||||
|
* android:layout_height="wrap_content"/>
|
||||||
|
*
|
||||||
|
* <TextView android:id="@+id/text2"
|
||||||
|
* android:textSize="16sp"
|
||||||
|
* android:layout_width="match_parent"
|
||||||
|
* android:layout_height="wrap_content"/>
|
||||||
|
* </LinearLayout>
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* You must identify the data bound to each TextView object in this layout. The
|
||||||
|
* syntax for this is discussed in the next section.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* <strong>Binding to Data</strong>
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* You bind the ListActivity's ListView object to data using a class that
|
||||||
|
* implements the {@link android.widget.ListAdapter ListAdapter} interface.
|
||||||
|
* Android provides two standard list adapters:
|
||||||
|
* {@link android.widget.SimpleAdapter SimpleAdapter} for static data (Maps),
|
||||||
|
* and {@link android.widget.SimpleCursorAdapter SimpleCursorAdapter} for Cursor
|
||||||
|
* query results.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* The following code from a custom ListActivity demonstrates querying the
|
||||||
|
* Contacts provider for all contacts, then binding the Name and Company fields
|
||||||
|
* to a two line row layout in the activity's ListView.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* public class MyListAdapter extends ListActivity {
|
||||||
|
*
|
||||||
|
* @Override
|
||||||
|
* protected void onCreate(Bundle savedInstanceState){
|
||||||
|
* super.onCreate(savedInstanceState);
|
||||||
|
*
|
||||||
|
* // We'll define a custom screen layout here (the one shown above), but
|
||||||
|
* // typically, you could just use the standard ListActivity layout.
|
||||||
|
* setContentView(R.layout.custom_list_activity_view);
|
||||||
|
*
|
||||||
|
* // Query for all people contacts using the {@link android.provider.Contacts.People} convenience class.
|
||||||
|
* // Put a managed wrapper around the retrieved cursor so we don't have to worry about
|
||||||
|
* // requerying or closing it as the activity changes state.
|
||||||
|
* mCursor = this.getContentResolver().query(People.CONTENT_URI, null, null, null, null);
|
||||||
|
* startManagingCursor(mCursor);
|
||||||
|
*
|
||||||
|
* // Now create a new list adapter bound to the cursor.
|
||||||
|
* // SimpleListAdapter is designed for binding to a Cursor.
|
||||||
|
* ListAdapter adapter = new SimpleCursorAdapter(
|
||||||
|
* this, // Context.
|
||||||
|
* android.R.layout.two_line_list_item, // Specify the row template to use (here, two columns bound to the two retrieved cursor
|
||||||
|
* rows).
|
||||||
|
* mCursor, // Pass in the cursor to bind to.
|
||||||
|
* new String[] {People.NAME, People.COMPANY}, // Array of cursor columns to bind to.
|
||||||
|
* new int[] {android.R.id.text1, android.R.id.text2}); // Parallel array of which template objects to bind to those columns.
|
||||||
|
*
|
||||||
|
* // Bind to our new adapter.
|
||||||
|
* setListAdapter(adapter);
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @see #setListAdapter
|
||||||
|
* @see android.widget.ListView
|
||||||
|
*/
|
||||||
|
public class AppCompatListActivity extends AppCompatActivity {
|
||||||
|
protected ListAdapter mAdapter;
|
||||||
|
protected ListView mList;
|
||||||
|
|
||||||
|
private Handler mHandler = new Handler();
|
||||||
|
private boolean mFinishedStart = false;
|
||||||
|
|
||||||
|
private Runnable mRequestFocus = new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
mList.focusableViewAvailable(mList);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures the list view has been created before Activity restores all
|
||||||
|
* of the view states.
|
||||||
|
*
|
||||||
|
*@see Activity#onRestoreInstanceState(Bundle)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void onRestoreInstanceState(Bundle state) {
|
||||||
|
ensureList();
|
||||||
|
super.onRestoreInstanceState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Activity#onDestroy()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
mHandler.removeCallbacks(mRequestFocus);
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the screen state (current list and other views) when the
|
||||||
|
* content changes.
|
||||||
|
*
|
||||||
|
* @see Activity#onContentChanged()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onContentChanged() {
|
||||||
|
super.onContentChanged();
|
||||||
|
|
||||||
|
View emptyView = findViewById(R.id.empty);
|
||||||
|
mList = findViewById(R.id.list);
|
||||||
|
if (mList == null) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"Your content must have a ListView whose id attribute is " +
|
||||||
|
"'android.R.id.list'");
|
||||||
|
}
|
||||||
|
if (emptyView != null) {
|
||||||
|
mList.setEmptyView(emptyView);
|
||||||
|
}
|
||||||
|
mList.setOnItemClickListener(mOnClickListener);
|
||||||
|
if (mFinishedStart) {
|
||||||
|
setListAdapter(mAdapter);
|
||||||
|
}
|
||||||
|
mHandler.post(mRequestFocus);
|
||||||
|
mFinishedStart = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide the cursor for the list view.
|
||||||
|
*/
|
||||||
|
public void setListAdapter(ListAdapter adapter) {
|
||||||
|
synchronized (this) {
|
||||||
|
ensureList();
|
||||||
|
mAdapter = adapter;
|
||||||
|
mList.setAdapter(adapter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the currently selected list item to the specified
|
||||||
|
* position with the adapter's data
|
||||||
|
*
|
||||||
|
* @param position
|
||||||
|
*/
|
||||||
|
public void setSelection(int position) {
|
||||||
|
mList.setSelection(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the position of the currently selected list item.
|
||||||
|
*/
|
||||||
|
public int getSelectedItemPosition() {
|
||||||
|
return mList.getSelectedItemPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the cursor row ID of the currently selected list item.
|
||||||
|
*/
|
||||||
|
public long getSelectedItemId() {
|
||||||
|
return mList.getSelectedItemId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the activity's list view widget.
|
||||||
|
*/
|
||||||
|
public ListView getListView() {
|
||||||
|
ensureList();
|
||||||
|
return mList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the ListAdapter associated with this activity's ListView.
|
||||||
|
*/
|
||||||
|
public ListAdapter getListAdapter() {
|
||||||
|
return mAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureList() {
|
||||||
|
if (mList != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setContentView(R.layout.default_list);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private AdapterView.OnItemClickListener mOnClickListener = new AdapterView.OnItemClickListener() {
|
||||||
|
public void onItemClick(AdapterView<?> parent, View v, int position, long id)
|
||||||
|
{
|
||||||
|
onListItemClick((ListView)parent, v, position, id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
@ -22,37 +22,44 @@ import android.accounts.AccountManager;
|
|||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
import android.animation.AnimatorListenerAdapter;
|
import android.animation.AnimatorListenerAdapter;
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
import android.support.v7.app.ActionBar;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.Pair;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.dd.processbutton.iml.ActionProcessButton;
|
||||||
import com.owncloud.android.lib.common.OwnCloudClientFactory;
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudCredentialsFactory;
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
import fr.unix_experience.owncloud_sms.R;
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
import fr.unix_experience.owncloud_sms.authenticators.OwnCloudAuthenticator;
|
import fr.unix_experience.owncloud_sms.defines.DefaultPrefs;
|
||||||
import fr.unix_experience.owncloud_sms.enums.LoginReturnCode;
|
import fr.unix_experience.owncloud_sms.engine.OCHttpClient;
|
||||||
|
import fr.unix_experience.owncloud_sms.exceptions.OCSyncException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A login screen that offers login via email/password.
|
* A login screen that offers login via email/password.
|
||||||
*/
|
*/
|
||||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||||
public class LoginActivity extends Activity {
|
public class LoginActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
private static final String TAG = LoginActivity.class.getCanonicalName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keep track of the login task to ensure we can cancel it if requested.
|
* Keep track of the login task to ensure we can cancel it if requested.
|
||||||
*/
|
*/
|
||||||
@ -63,6 +70,7 @@ public class LoginActivity extends Activity {
|
|||||||
private EditText _loginView;
|
private EditText _loginView;
|
||||||
private EditText _passwordView;
|
private EditText _passwordView;
|
||||||
private EditText _serverView;
|
private EditText _serverView;
|
||||||
|
private ActionProcessButton _signInButton;
|
||||||
private View mProgressView;
|
private View mProgressView;
|
||||||
private View mLoginFormView;
|
private View mLoginFormView;
|
||||||
|
|
||||||
@ -71,18 +79,21 @@ public class LoginActivity extends Activity {
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_login);
|
setContentView(R.layout.activity_login);
|
||||||
|
|
||||||
// Set up the login form.
|
ActionBar actionBar = getSupportActionBar();
|
||||||
_protocolView = (Spinner) findViewById(R.id.oc_protocol);
|
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||||
_serverView = (EditText) findViewById(R.id.oc_server);
|
|
||||||
_loginView = (EditText) findViewById(R.id.oc_login);
|
|
||||||
|
|
||||||
_passwordView = (EditText) findViewById(R.id.oc_password);
|
// Set up the login form.
|
||||||
|
_protocolView = findViewById(R.id.oc_protocol);
|
||||||
|
_serverView = findViewById(R.id.oc_server);
|
||||||
|
_loginView = findViewById(R.id.oc_login);
|
||||||
|
|
||||||
|
_passwordView = findViewById(R.id.oc_password);
|
||||||
_passwordView
|
_passwordView
|
||||||
.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onEditorAction(TextView textView, int id,
|
public boolean onEditorAction(TextView textView, int id,
|
||||||
KeyEvent keyEvent) {
|
KeyEvent keyEvent) {
|
||||||
if (id == R.id.oc_login || id == EditorInfo.IME_NULL) {
|
if ((id == R.id.oc_login) || (id == EditorInfo.IME_NULL)) {
|
||||||
attemptLogin();
|
attemptLogin();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -90,7 +101,7 @@ public class LoginActivity extends Activity {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Button _signInButton = (Button) findViewById(R.id.oc_signin_button);
|
_signInButton = findViewById(R.id.oc_signin_button);
|
||||||
_signInButton.setOnClickListener(new OnClickListener() {
|
_signInButton.setOnClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
@ -102,6 +113,19 @@ public class LoginActivity extends Activity {
|
|||||||
mProgressView = findViewById(R.id.login_progress);
|
mProgressView = findViewById(R.id.login_progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
boolean retval = true;
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case android.R.id.home:
|
||||||
|
finish();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
retval = super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to sign in or register the account specified by the login form.
|
* Attempts to sign in or register the account specified by the login form.
|
||||||
* If there are form errors (invalid email, missing fields, etc.), the
|
* If there are form errors (invalid email, missing fields, etc.), the
|
||||||
@ -124,12 +148,12 @@ public class LoginActivity extends Activity {
|
|||||||
|
|
||||||
boolean cancel = false;
|
boolean cancel = false;
|
||||||
View focusView = null;
|
View focusView = null;
|
||||||
|
|
||||||
// Check for a valid server address.
|
// Check for a valid server address.
|
||||||
if (TextUtils.isEmpty(protocol)) {
|
if (TextUtils.isEmpty(protocol)) {
|
||||||
cancel = true;
|
cancel = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for a valid server address.
|
// Check for a valid server address.
|
||||||
if (TextUtils.isEmpty(serverAddr)) {
|
if (TextUtils.isEmpty(serverAddr)) {
|
||||||
_serverView.setError(getString(R.string.error_field_required));
|
_serverView.setError(getString(R.string.error_field_required));
|
||||||
@ -143,14 +167,14 @@ public class LoginActivity extends Activity {
|
|||||||
focusView = _loginView;
|
focusView = _loginView;
|
||||||
cancel = true;
|
cancel = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for a valid password
|
// Check for a valid password
|
||||||
if (TextUtils.isEmpty(password)) {
|
if (TextUtils.isEmpty(password)) {
|
||||||
_passwordView.setError(getString(R.string.error_field_required));
|
_passwordView.setError(getString(R.string.error_field_required));
|
||||||
focusView = _passwordView;
|
focusView = _passwordView;
|
||||||
cancel = true;
|
cancel = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isPasswordValid(password)) {
|
if (!isPasswordValid(password)) {
|
||||||
_passwordView.setError(getString(R.string.error_invalid_password));
|
_passwordView.setError(getString(R.string.error_invalid_password));
|
||||||
focusView = _passwordView;
|
focusView = _passwordView;
|
||||||
@ -160,14 +184,23 @@ public class LoginActivity extends Activity {
|
|||||||
if (cancel) {
|
if (cancel) {
|
||||||
// There was an error; don't attempt login and focus the first
|
// There was an error; don't attempt login and focus the first
|
||||||
// form field with an error.
|
// form field with an error.
|
||||||
focusView.requestFocus();
|
// reset the button progress
|
||||||
|
_signInButton.setProgress(0);
|
||||||
|
if (focusView != null) {
|
||||||
|
focusView.requestFocus();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Show a progress spinner, and kick off a background task to
|
// Show a progress spinner, and kick off a background task to
|
||||||
// perform the user login attempt.
|
// perform the user login attempt.
|
||||||
|
_signInButton.setProgress(25);
|
||||||
showProgress(true);
|
showProgress(true);
|
||||||
String serverURL = new String(protocol + serverAddr);
|
String serverURL = protocol + serverAddr;
|
||||||
mAuthTask = new UserLoginTask(serverURL, login, password);
|
try {
|
||||||
mAuthTask.execute((Void) null);
|
mAuthTask = new UserLoginTask(serverURL, login, password);
|
||||||
|
mAuthTask.execute((Void) null);
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
Log.e(TAG, "Invalid server URL " + serverURL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,101 +254,118 @@ public class LoginActivity extends Activity {
|
|||||||
* Represents an asynchronous login/registration task used to authenticate
|
* Represents an asynchronous login/registration task used to authenticate
|
||||||
* the user.
|
* the user.
|
||||||
*/
|
*/
|
||||||
public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {
|
public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {
|
||||||
|
|
||||||
UserLoginTask(String serverURI, String login, String password) {
|
UserLoginTask(String serverURL, String login, String password) throws MalformedURLException {
|
||||||
_serverURI = Uri.parse(serverURI);
|
_serverURL = new URL(serverURL);
|
||||||
|
Log.i(TAG, "_serverURL = " + serverURL);
|
||||||
_login = login;
|
_login = login;
|
||||||
_password = password;
|
_password = password;
|
||||||
|
_last_http_error = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Boolean doInBackground(Void... params) {
|
protected Boolean doInBackground(Void... params) {
|
||||||
// Create client object to perform remote operations
|
_returnCode = 0;
|
||||||
OwnCloudClient ocClient = OwnCloudClientFactory.createOwnCloudClient(
|
OCHttpClient http = new OCHttpClient(getBaseContext(), _serverURL, _login, _password);
|
||||||
_serverURI, getBaseContext(),
|
try {
|
||||||
// Activity or Service context
|
Pair<Integer, Integer> vPair = http.getVersion();
|
||||||
true
|
_returnCode = vPair.first;
|
||||||
);
|
} catch (IllegalArgumentException e) {
|
||||||
|
Log.w(TAG, "Failed to getVersion, IllegalArgumentException occured: " + e.getMessage());
|
||||||
// Set basic credentials
|
_returnCode = 597;
|
||||||
ocClient.setCredentials(
|
} catch (OCSyncException e) {
|
||||||
OwnCloudCredentialsFactory.newBasicCredentials(_login, _password)
|
Log.w(TAG, "Failed to login, OCSyncException occured: " + e.getMessage());
|
||||||
);
|
_returnCode = 599;
|
||||||
|
}
|
||||||
// Send an authentication test to ownCloud
|
|
||||||
OwnCloudAuthenticator at = new OwnCloudAuthenticator(getBaseContext());
|
_last_http_error = http.getLastError();
|
||||||
at.setClient(ocClient);
|
return (_returnCode == 200);
|
||||||
|
|
||||||
_returnCode = at.testCredentials();
|
|
||||||
|
|
||||||
return (_returnCode == LoginReturnCode.OK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(final Boolean success) {
|
protected void onPostExecute(Boolean success) {
|
||||||
mAuthTask = null;
|
mAuthTask = null;
|
||||||
showProgress(false);
|
showProgress(false);
|
||||||
|
_signInButton.setProgress(90);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
String accountType = getIntent().getStringExtra(PARAM_AUTHTOKEN_TYPE);
|
_signInButton.setProgress(100);
|
||||||
if (accountType == null) {
|
String accountType = getIntent().getStringExtra(UserLoginTask.PARAM_AUTHTOKEN_TYPE);
|
||||||
accountType = getString(R.string.account_type);
|
if (accountType == null) {
|
||||||
}
|
accountType = getString(R.string.account_type);
|
||||||
|
}
|
||||||
|
|
||||||
// Generate a label
|
// Generate a label
|
||||||
String accountLabel = _login + "@" + _serverURI.getHost();
|
String accountLabel = _login + "@" + _serverURL.getHost();
|
||||||
|
|
||||||
// We create the account
|
// We create the account
|
||||||
final Account account = new Account(accountLabel, accountType);
|
Account account = new Account(accountLabel, accountType);
|
||||||
Bundle accountBundle = new Bundle();
|
Bundle accountBundle = new Bundle();
|
||||||
accountBundle.putString("ocLogin", _login);
|
accountBundle.putString("ocLogin", _login);
|
||||||
accountBundle.putString("ocURI", _serverURI.toString());
|
accountBundle.putString("ocURI", _serverURL.toString());
|
||||||
|
|
||||||
// And we push it to Android
|
// And we push it to Android
|
||||||
AccountManager accMgr = AccountManager.get(getApplicationContext());
|
AccountManager accMgr = AccountManager.get(getApplicationContext());
|
||||||
accMgr.addAccountExplicitly(account, _password, accountBundle);
|
accMgr.addAccountExplicitly(account, _password, accountBundle);
|
||||||
|
|
||||||
// Set sync options
|
// Set sync options
|
||||||
ContentResolver.setSyncAutomatically(account, getString(R.string.account_authority), true);
|
ContentResolver.setSyncAutomatically(account, getString(R.string.account_authority), true);
|
||||||
|
|
||||||
Bundle b = new Bundle();
|
Bundle b = new Bundle();
|
||||||
b.putInt("synctype", 1);
|
b.putInt("synctype", 1);
|
||||||
|
|
||||||
ContentResolver.addPeriodicSync(account, getString(R.string.account_authority), b, 15 * 60);
|
ContentResolver.addPeriodicSync(account, getString(R.string.account_authority), b, DefaultPrefs.syncInterval * 60);
|
||||||
// Then it's finished
|
// Then it's finished
|
||||||
finish();
|
finish();
|
||||||
|
|
||||||
// Start sync settings, we have finished to configure account
|
// Start sync settings, we have finished to configure account
|
||||||
Intent settingsIntent = new Intent(Settings.ACTION_SYNC_SETTINGS);
|
Intent settingsIntent = new Intent(Settings.ACTION_SYNC_SETTINGS);
|
||||||
settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
getApplicationContext().startActivity(settingsIntent);
|
getApplicationContext().startActivity(settingsIntent);
|
||||||
} else {
|
} else {
|
||||||
|
boolean serverViewRequestFocus = true;
|
||||||
switch (_returnCode) {
|
switch (_returnCode) {
|
||||||
case INVALID_ADDR:
|
case 0:
|
||||||
|
if (!_last_http_error.isEmpty()) {
|
||||||
|
_serverView.setError("Low level error: " + _last_http_error);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_serverView.setError("Unknown error");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 404:
|
||||||
|
_serverView.setError(getString(R.string.error_connection_failed_not_found));
|
||||||
|
break;
|
||||||
|
case 597:
|
||||||
_serverView.setError(getString(R.string.error_invalid_server_address));
|
_serverView.setError(getString(R.string.error_invalid_server_address));
|
||||||
_serverView.requestFocus();
|
|
||||||
break;
|
break;
|
||||||
case HTTP_CONN_FAILED:
|
case 400:
|
||||||
_serverView.setError(getString(R.string.error_http_connection_failed));
|
case 598:
|
||||||
_serverView.requestFocus();
|
|
||||||
break;
|
|
||||||
case CONN_FAILED:
|
|
||||||
_serverView.setError(getString(R.string.error_connection_failed));
|
_serverView.setError(getString(R.string.error_connection_failed));
|
||||||
_serverView.requestFocus();
|
|
||||||
break;
|
break;
|
||||||
case INVALID_LOGIN:
|
case 599:
|
||||||
|
_serverView.setError(getString(R.string.error_http_connection_failed));
|
||||||
|
break;
|
||||||
|
case 401:
|
||||||
|
case 403:
|
||||||
_passwordView.setError(getString(R.string.error_invalid_login));
|
_passwordView.setError(getString(R.string.error_invalid_login));
|
||||||
_passwordView.requestFocus();
|
_passwordView.requestFocus();
|
||||||
|
// Warning, there is no break here to disable serverViewRequestFocus too
|
||||||
|
case 200:
|
||||||
|
default:
|
||||||
|
serverViewRequestFocus = false;
|
||||||
break;
|
break;
|
||||||
case UNKNOWN_ERROR:
|
|
||||||
_serverView.setError("UNK");
|
|
||||||
_serverView.requestFocus();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (serverViewRequestFocus) {
|
||||||
|
_serverView.requestFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not ok, reset the progress
|
||||||
|
if (_returnCode != 200) {
|
||||||
|
_signInButton.setProgress(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,13 +374,14 @@ public class LoginActivity extends Activity {
|
|||||||
mAuthTask = null;
|
mAuthTask = null;
|
||||||
showProgress(false);
|
showProgress(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Uri _serverURI;
|
private final URL _serverURL;
|
||||||
private final String _login;
|
private final String _login;
|
||||||
private final String _password;
|
private final String _password;
|
||||||
private LoginReturnCode _returnCode;
|
private String _last_http_error;
|
||||||
|
private int _returnCode;
|
||||||
public static final String PARAM_AUTHTOKEN_TYPE = "auth.token";
|
|
||||||
public static final String PARAM_CREATE = "create";
|
static final String PARAM_AUTHTOKEN_TYPE = "auth.token";
|
||||||
|
private final String TAG = UserLoginTask.class.getCanonicalName();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,279 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.activities;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2016, Loic Blot <loic.blot@unix-experience.fr>
|
||||||
|
* All rights reserved.
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.design.widget.NavigationView;
|
||||||
|
import android.support.v4.view.GravityCompat;
|
||||||
|
import android.support.v4.widget.DrawerLayout;
|
||||||
|
import android.support.v7.app.ActionBarDrawerToggle;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.support.v7.widget.Toolbar;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.Window;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
|
import fr.unix_experience.owncloud_sms.activities.remote_account.AccountListActivity;
|
||||||
|
import fr.unix_experience.owncloud_sms.engine.ASyncSMSSync.SyncTask;
|
||||||
|
import fr.unix_experience.owncloud_sms.engine.ConnectivityMonitor;
|
||||||
|
import fr.unix_experience.owncloud_sms.enums.PermissionID;
|
||||||
|
import fr.unix_experience.owncloud_sms.prefs.PermissionChecker;
|
||||||
|
|
||||||
|
import static fr.unix_experience.owncloud_sms.enums.PermissionID.REQUEST_MAX;
|
||||||
|
import static fr.unix_experience.owncloud_sms.enums.PermissionID.REQUEST_SMS;
|
||||||
|
|
||||||
|
public class MainActivity extends AppCompatActivity
|
||||||
|
implements NavigationView.OnNavigationItemSelectedListener {
|
||||||
|
|
||||||
|
private ConnectivityMonitor _ConnectivityMonitor = null;
|
||||||
|
|
||||||
|
private DrawerLayout drawer;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
if (_ConnectivityMonitor == null) {
|
||||||
|
_ConnectivityMonitor = new ConnectivityMonitor(getApplicationContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||||
|
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_main);
|
||||||
|
|
||||||
|
setupToolbar();
|
||||||
|
if (getSupportActionBar() != null) {
|
||||||
|
getSupportActionBar().setHomeButtonEnabled(true);
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawer = findViewById(R.id.drawer_layout);
|
||||||
|
setupDrawer();
|
||||||
|
drawer.openDrawer(GravityCompat.START);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setupToolbar() {
|
||||||
|
setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupDrawer() {
|
||||||
|
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
|
||||||
|
this, drawer, null, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
|
||||||
|
assert drawer != null;
|
||||||
|
drawer.addDrawerListener(toggle);
|
||||||
|
toggle.syncState();
|
||||||
|
toggle.setDrawerIndicatorEnabled(true);
|
||||||
|
|
||||||
|
NavigationView navigationView = findViewById(R.id.nav_view);
|
||||||
|
assert navigationView != null;
|
||||||
|
navigationView.setNavigationItemSelectedListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks if the drawer exists and is opened.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the drawer is open, else <code>false</code>
|
||||||
|
*/
|
||||||
|
public boolean isDrawerOpen() {
|
||||||
|
return drawer != null && drawer.isDrawerOpen(GravityCompat.START);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* closes the drawer.
|
||||||
|
*/
|
||||||
|
public void closeDrawer() {
|
||||||
|
if (drawer != null) {
|
||||||
|
drawer.closeDrawer(GravityCompat.START);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* opens the drawer.
|
||||||
|
*/
|
||||||
|
public void openDrawer() {
|
||||||
|
if (drawer != null) {
|
||||||
|
drawer.openDrawer(GravityCompat.START);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBackPressed() {
|
||||||
|
if (isDrawerOpen()) {
|
||||||
|
closeDrawer();
|
||||||
|
} else {
|
||||||
|
super.onBackPressed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
boolean retval = true;
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case android.R.id.home: {
|
||||||
|
if (isDrawerOpen()) {
|
||||||
|
closeDrawer();
|
||||||
|
} else {
|
||||||
|
openDrawer();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
retval = super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
|
||||||
|
int id = item.getItemId();
|
||||||
|
boolean res = true;
|
||||||
|
|
||||||
|
switch (id) {
|
||||||
|
case R.id.nav_sync:
|
||||||
|
syncAllMessages();
|
||||||
|
break;
|
||||||
|
case R.id.nav_manage:
|
||||||
|
res = openAppSettings();
|
||||||
|
break;
|
||||||
|
case R.id.nav_rateus:
|
||||||
|
res = openGooglePlayStore();
|
||||||
|
break;
|
||||||
|
case R.id.nav_add_account:
|
||||||
|
res = openAddAccount();
|
||||||
|
break;
|
||||||
|
case R.id.nav_my_accounts:
|
||||||
|
res = openMyAccounts();
|
||||||
|
break;
|
||||||
|
case R.id.nav_appinfo_perms:
|
||||||
|
res = openAppInfos();
|
||||||
|
break;
|
||||||
|
case R.id.nav_appinfo_privacy_policy:
|
||||||
|
res = openPrivacyPolicy();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log.e(TAG, "Unhandled navigation item " + Integer.toString(id));
|
||||||
|
}
|
||||||
|
closeDrawer();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean openAppSettings() {
|
||||||
|
startActivity(new Intent(this, OCSMSSettingsActivity.class));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean openAddAccount() {
|
||||||
|
startActivity(new Intent(Settings.ACTION_ADD_ACCOUNT));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void syncAllMessages() {
|
||||||
|
Log.v(MainActivity.TAG, "Launch syncAllMessages()");
|
||||||
|
if (!PermissionChecker.checkPermission(this, Manifest.permission.READ_SMS,
|
||||||
|
REQUEST_SMS)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context ctx = getApplicationContext();
|
||||||
|
if (!_ConnectivityMonitor.isValid()) {
|
||||||
|
Toast.makeText(ctx, ctx.getString(R.string.err_sync_no_connection_available), Toast.LENGTH_SHORT).show();
|
||||||
|
Log.v(MainActivity.TAG, "Finish syncAllMessages(): invalid connection");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
new SyncTask(this).execute();
|
||||||
|
Log.v(MainActivity.TAG, "Finish syncAllMessages()");
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean openMyAccounts() {
|
||||||
|
startActivity(new Intent(this, AccountListActivity.class));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean openGooglePlayStore() {
|
||||||
|
Intent intent;
|
||||||
|
try {
|
||||||
|
intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + getPackageName()));
|
||||||
|
} catch (android.content.ActivityNotFoundException e) {
|
||||||
|
intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + getPackageName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
startActivity(intent);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean openAppInfos() {
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||||
|
Uri uri = Uri.fromParts("package", getPackageName(), null);
|
||||||
|
intent.setData(uri);
|
||||||
|
startActivity(intent);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean openPrivacyPolicy() {
|
||||||
|
startActivity(new Intent(this, PrivacyPolicyActivity.class));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Permissions
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
|
||||||
|
@NonNull int[] grantResults) {
|
||||||
|
PermissionID requestCodeID = REQUEST_MAX;
|
||||||
|
if ((requestCode > 0) || (requestCode < REQUEST_MAX.ordinal())) {
|
||||||
|
requestCodeID = PermissionID.values()[requestCode];
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (requestCodeID) {
|
||||||
|
case REQUEST_SMS:
|
||||||
|
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
syncAllMessages();
|
||||||
|
} else {
|
||||||
|
// Permission Denied
|
||||||
|
Toast.makeText(this, getString(R.string.err_cannot_read_sms) + " " +
|
||||||
|
getString(R.string.please_fix_it), Toast.LENGTH_SHORT)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String TAG = MainActivity.class.getSimpleName();
|
||||||
|
}
|
@ -0,0 +1,189 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.activities;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2017, Loic Blot <loic.blot@unix-experience.fr>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.accounts.Account;
|
||||||
|
import android.accounts.AccountManager;
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.content.PeriodicSync;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.preference.ListPreference;
|
||||||
|
import android.support.v7.app.ActionBar;
|
||||||
|
import android.support.v7.app.AppCompatDelegate;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.Pair;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
|
import fr.unix_experience.owncloud_sms.activities.virtual.VirtualSettingsActivity;
|
||||||
|
import fr.unix_experience.owncloud_sms.defines.DefaultPrefs;
|
||||||
|
import fr.unix_experience.owncloud_sms.prefs.OCSMSSharedPrefs;
|
||||||
|
import fr.unix_experience.owncloud_sms.prefs.PermissionChecker;
|
||||||
|
|
||||||
|
import static fr.unix_experience.owncloud_sms.enums.PermissionID.REQUEST_ACCOUNTS;
|
||||||
|
|
||||||
|
public class OCSMSSettingsActivity extends VirtualSettingsActivity {
|
||||||
|
private static final String TAG = OCSMSSettingsActivity.class.getSimpleName();
|
||||||
|
|
||||||
|
private static AccountManager _accountMgr;
|
||||||
|
private static String _accountAuthority;
|
||||||
|
private static String _accountType;
|
||||||
|
private static Vector<Pair<Integer, Boolean>> _boolSettings;
|
||||||
|
|
||||||
|
private AppCompatDelegate mDelegate;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
ActionBar actionBar = getSupportActionBar();
|
||||||
|
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AppCompatDelegate getDelegate() {
|
||||||
|
if (mDelegate == null) {
|
||||||
|
mDelegate = AppCompatDelegate.create(this, null);
|
||||||
|
}
|
||||||
|
return mDelegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActionBar getSupportActionBar() {
|
||||||
|
return getDelegate().getSupportActionBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostCreate(Bundle savedInstanceState) {
|
||||||
|
OCSMSSettingsActivity._accountMgr = AccountManager.get(getBaseContext());
|
||||||
|
OCSMSSettingsActivity._accountAuthority = getString(R.string.account_authority);
|
||||||
|
OCSMSSettingsActivity._accountType = getString(R.string.account_type);
|
||||||
|
VirtualSettingsActivity._prefsRessourceFile = R.xml.pref_data_sync;
|
||||||
|
|
||||||
|
// Bind our boolean preferences
|
||||||
|
VirtualSettingsActivity._boolPrefs.add(
|
||||||
|
new BindObjectPref(R.string.setting_push_on_receive, DefaultPrefs.pushOnReceive));
|
||||||
|
VirtualSettingsActivity._boolPrefs.add(
|
||||||
|
new BindObjectPref(R.string.setting_show_sync_notifications, DefaultPrefs.showSyncNotifications));
|
||||||
|
VirtualSettingsActivity._boolPrefs.add(
|
||||||
|
new BindObjectPref(R.string.setting_sync_wifi, DefaultPrefs.syncWifi));
|
||||||
|
VirtualSettingsActivity._boolPrefs.add(
|
||||||
|
new BindObjectPref(R.string.setting_sync_4g, DefaultPrefs.sync4G));
|
||||||
|
VirtualSettingsActivity._boolPrefs.add(
|
||||||
|
new BindObjectPref(R.string.setting_sync_3g, DefaultPrefs.sync3G));
|
||||||
|
VirtualSettingsActivity._boolPrefs.add(
|
||||||
|
new BindObjectPref(R.string.setting_sync_gprs, DefaultPrefs.syncGPRS));
|
||||||
|
VirtualSettingsActivity._boolPrefs.add(
|
||||||
|
new BindObjectPref(R.string.setting_sync_2g, DefaultPrefs.sync2G));
|
||||||
|
VirtualSettingsActivity._boolPrefs.add(
|
||||||
|
new BindObjectPref(R.string.setting_sync_others, DefaultPrefs.syncOthers));
|
||||||
|
|
||||||
|
// Bind our string preferences
|
||||||
|
VirtualSettingsActivity._stringPrefs.add(
|
||||||
|
new BindObjectPref(R.string.setting_sync_frequency, "15"));
|
||||||
|
VirtualSettingsActivity._stringPrefs.add(
|
||||||
|
new BindObjectPref(R.string.setting_sync_bulk_messages, "-1"));
|
||||||
|
VirtualSettingsActivity._stringPrefs.add(
|
||||||
|
new BindObjectPref(R.string.setting_minimum_sync_chars, "1"));
|
||||||
|
|
||||||
|
// Must be at the end, after preference bind
|
||||||
|
super.onPostCreate(savedInstanceState);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleCheckboxPreference(String key, Boolean value) {
|
||||||
|
// Network types allowed for sync
|
||||||
|
if ("push_on_receive".equals(key) || "show_sync_notifications".equals(key) ||
|
||||||
|
"sync_wifi".equals(key) || "sync_2g".equals(key) ||
|
||||||
|
"sync_3g".equals(key) || "sync_gprs".equals(key) ||
|
||||||
|
"sync_4g".equals(key) || "sync_others".equals(key)) {
|
||||||
|
OCSMSSharedPrefs prefs = new OCSMSSharedPrefs(VirtualSettingsActivity._context);
|
||||||
|
Log.i(OCSMSSettingsActivity.TAG, "OCSMSSettingsActivity.handleCheckboxPreference: set " + key + " to "
|
||||||
|
+ value.toString());
|
||||||
|
prefs.putBoolean(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleListPreference(String key, String value,
|
||||||
|
ListPreference preference) {
|
||||||
|
// For list preferences, look up the correct display value in
|
||||||
|
// the preference's 'entries' list.
|
||||||
|
int index = preference.findIndexOfValue(value);
|
||||||
|
|
||||||
|
// Set the summary to reflect the new value.
|
||||||
|
preference.setSummary((index >= 0) ? preference.getEntries()[index] : null);
|
||||||
|
|
||||||
|
Log.i(OCSMSSettingsActivity.TAG, "Modifying listPreference " + key);
|
||||||
|
|
||||||
|
OCSMSSharedPrefs prefs = new OCSMSSharedPrefs(VirtualSettingsActivity._context);
|
||||||
|
|
||||||
|
// Handle sync frequency change
|
||||||
|
if ("sync_frequency".equals(key)) {
|
||||||
|
if (!PermissionChecker.checkPermission(this, Manifest.permission.GET_ACCOUNTS,
|
||||||
|
REQUEST_ACCOUNTS)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Account[] myAccountList = OCSMSSettingsActivity._accountMgr.getAccountsByType(OCSMSSettingsActivity._accountType);
|
||||||
|
long syncFreq = Long.parseLong(value);
|
||||||
|
|
||||||
|
// Get ownCloud SMS account list
|
||||||
|
for (Account acct : myAccountList) {
|
||||||
|
// And get all authorities for this account
|
||||||
|
List<PeriodicSync> syncList = ContentResolver.getPeriodicSyncs(acct, OCSMSSettingsActivity._accountAuthority);
|
||||||
|
|
||||||
|
boolean foundSameSyncCycle = false;
|
||||||
|
for (PeriodicSync ps : syncList) {
|
||||||
|
if ((ps.period == syncFreq) && (ps.extras.getInt("synctype") == 1)) {
|
||||||
|
foundSameSyncCycle = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundSameSyncCycle) {
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
b.putInt("synctype", 1);
|
||||||
|
|
||||||
|
ContentResolver.removePeriodicSync(acct, OCSMSSettingsActivity._accountAuthority, b);
|
||||||
|
if (syncFreq > 0) {
|
||||||
|
ContentResolver.addPeriodicSync(acct, OCSMSSettingsActivity._accountAuthority, b, syncFreq * 60);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prefs.putLong(key, syncFreq);
|
||||||
|
}
|
||||||
|
} else if ("sync_bulk_messages".equals(key) || "minimum_sync_chars".equals(key)) {
|
||||||
|
prefs.putInteger(key, Integer.parseInt(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
||||||
|
super.onMenuItemSelected(featureId, item);
|
||||||
|
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case android.R.id.home:
|
||||||
|
onBackPressed();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.activities;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.design.widget.FloatingActionButton;
|
||||||
|
import android.support.design.widget.Snackbar;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.support.v7.widget.Toolbar;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
|
|
||||||
|
public class PrivacyPolicyActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_privacy_policy);
|
||||||
|
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||||
|
setSupportActionBar(toolbar);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.activities.remote_account;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.app.AlertDialog;
|
||||||
|
import android.support.v7.app.ActionBar;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.ListView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import fr.unix_experience.android_lib.AppCompatListActivity;
|
||||||
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
|
import fr.unix_experience.owncloud_sms.prefs.OCSMSSharedPrefs;
|
||||||
|
|
||||||
|
public class AccountActionsActivity extends AppCompatListActivity {
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
setContentView(R.layout.activity_account_actions);
|
||||||
|
|
||||||
|
ActionBar actionBar = getSupportActionBar();
|
||||||
|
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||||
|
|
||||||
|
ArrayList<String> itemList = new ArrayList<>();
|
||||||
|
ArrayAdapter<String> adp = new ArrayAdapter<>(getBaseContext(),
|
||||||
|
android.R.layout.simple_dropdown_item_1line, itemList);
|
||||||
|
setListAdapter(adp);
|
||||||
|
|
||||||
|
// Create item list
|
||||||
|
itemList.add(getBaseContext().getString(R.string.restore_all_messages));
|
||||||
|
itemList.add(getBaseContext().getString(R.string.reinit_sync_cursor));
|
||||||
|
|
||||||
|
adp.notifyDataSetChanged();
|
||||||
|
|
||||||
|
// Fetch account name from intent
|
||||||
|
_accountName = getIntent().getStringExtra("account");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
boolean retval = true;
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case android.R.id.home:
|
||||||
|
finish();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
retval = super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||||
|
switch (position) {
|
||||||
|
case 0:
|
||||||
|
Intent intent = new Intent(this, RestoreMessagesActivity.class);
|
||||||
|
intent.putExtra("account", _accountName);
|
||||||
|
try {
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
catch (IllegalStateException e) {
|
||||||
|
Log.e(AccountActionsActivity.TAG, e.getMessage());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
final Context me = this;
|
||||||
|
new AlertDialog.Builder(this)
|
||||||
|
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||||
|
.setTitle(R.string.reinit_sync_cursor)
|
||||||
|
.setMessage(R.string.reinit_sync_cursor_confirm)
|
||||||
|
.setPositiveButton(R.string.yes_confirm, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
(new OCSMSSharedPrefs(me)).setLastMessageDate(0L);
|
||||||
|
Log.i(AccountActionsActivity.TAG, "Synchronization cursor reinitialized");
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.no_confirm, null)
|
||||||
|
.show();
|
||||||
|
break;
|
||||||
|
default: break; // Unhandled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String _accountName = "";
|
||||||
|
private static final String TAG = AccountActionsActivity.class.getSimpleName();
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.activities.remote_account;
|
||||||
|
|
||||||
|
import android.accounts.Account;
|
||||||
|
import android.accounts.AccountManager;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import fr.unix_experience.android_lib.AppCompatListActivity;
|
||||||
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
|
import fr.unix_experience.owncloud_sms.adapters.AndroidAccountAdapter;
|
||||||
|
|
||||||
|
public class AccountListActivity extends AppCompatListActivity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle icicle) {
|
||||||
|
super.onCreate(icicle);
|
||||||
|
|
||||||
|
AccountManager _accountMgr = AccountManager.get(getBaseContext());
|
||||||
|
|
||||||
|
setContentView(R.layout.restore_activity_accountlist);
|
||||||
|
|
||||||
|
getSupportActionBar().setHomeButtonEnabled(true);
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
|
||||||
|
ArrayList<Account> itemList = new ArrayList<>();
|
||||||
|
|
||||||
|
AndroidAccountAdapter adapter = new AndroidAccountAdapter(this,
|
||||||
|
android.R.layout.simple_list_item_1,
|
||||||
|
itemList,
|
||||||
|
R.layout.account_list_item,
|
||||||
|
R.id.accountname, AccountActionsActivity.class);
|
||||||
|
setListAdapter(adapter);
|
||||||
|
|
||||||
|
Account[] accountList =
|
||||||
|
_accountMgr.getAccountsByType(getString(R.string.account_type));
|
||||||
|
Collections.addAll(itemList, accountList);
|
||||||
|
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case android.R.id.home:
|
||||||
|
onBackPressed();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,219 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.activities.remote_account;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.accounts.Account;
|
||||||
|
import android.accounts.AccountManager;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.provider.ContactsContract;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.v4.widget.SwipeRefreshLayout;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
|
import fr.unix_experience.owncloud_sms.adapters.ContactListAdapter;
|
||||||
|
import fr.unix_experience.owncloud_sms.adapters.RecoveryPhoneNumberListViewAdapter;
|
||||||
|
import fr.unix_experience.owncloud_sms.engine.ASyncContactLoad;
|
||||||
|
import fr.unix_experience.owncloud_sms.enums.PermissionID;
|
||||||
|
import fr.unix_experience.owncloud_sms.prefs.PermissionChecker;
|
||||||
|
|
||||||
|
import static fr.unix_experience.owncloud_sms.enums.PermissionID.REQUEST_CONTACTS;
|
||||||
|
import static fr.unix_experience.owncloud_sms.enums.PermissionID.REQUEST_MAX;
|
||||||
|
|
||||||
|
public class ContactListActivity extends AppCompatActivity implements ASyncContactLoad {
|
||||||
|
|
||||||
|
static AccountManager mAccountMgr;
|
||||||
|
ContactListAdapter mAdapter = null;
|
||||||
|
SwipeRefreshLayout mLayout = null;
|
||||||
|
LinearLayout mContactInfos = null;
|
||||||
|
ArrayList<String> mObjects;
|
||||||
|
String mFetchedContact;
|
||||||
|
RecoveryPhoneNumberListViewAdapter mContactPhoneListAdapter = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
assert getIntent().getExtras() != null;
|
||||||
|
|
||||||
|
ContactListActivity.mAccountMgr = AccountManager.get(getBaseContext());
|
||||||
|
|
||||||
|
// Init view
|
||||||
|
mObjects = new ArrayList<>();
|
||||||
|
setContentView(R.layout.restore_activity_contactlist);
|
||||||
|
|
||||||
|
mLayout = findViewById(R.id.contactlist_swipe_container);
|
||||||
|
|
||||||
|
mAdapter = new ContactListAdapter(getBaseContext(), mObjects);
|
||||||
|
|
||||||
|
mContactInfos = findViewById(R.id.contactinfos_layout);
|
||||||
|
ListView contactPhoneListView = findViewById(R.id.contact_phonelistView);
|
||||||
|
mContactPhoneListAdapter = new RecoveryPhoneNumberListViewAdapter(getBaseContext());
|
||||||
|
assert contactPhoneListView != null;
|
||||||
|
contactPhoneListView.setAdapter(mContactPhoneListAdapter);
|
||||||
|
|
||||||
|
mContactInfos.setVisibility(View.INVISIBLE);
|
||||||
|
|
||||||
|
initSpinner();
|
||||||
|
createAccountList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createAccountList() {
|
||||||
|
final ProgressBar contactProgressBar = findViewById(R.id.contactlist_pgbar);
|
||||||
|
assert contactProgressBar != null;
|
||||||
|
|
||||||
|
String accountName = getIntent().getExtras().getString("account");
|
||||||
|
assert accountName != null;
|
||||||
|
|
||||||
|
Account[] myAccountList =
|
||||||
|
ContactListActivity.mAccountMgr.getAccountsByType(getString(R.string.account_type));
|
||||||
|
|
||||||
|
for (final Account element : myAccountList) {
|
||||||
|
if (element.name.equals(accountName)) {
|
||||||
|
// Load "contacts"
|
||||||
|
contactProgressBar.setVisibility(View.VISIBLE);
|
||||||
|
new ContactLoadTask(element, getBaseContext(), mAdapter, mObjects, mLayout,
|
||||||
|
contactProgressBar, mContactInfos).execute();
|
||||||
|
|
||||||
|
// Add refresh handler
|
||||||
|
mLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
|
||||||
|
@Override
|
||||||
|
public void onRefresh() {
|
||||||
|
mLayout.setRefreshing(true);
|
||||||
|
mContactInfos.setVisibility(View.INVISIBLE);
|
||||||
|
contactProgressBar.setVisibility(View.VISIBLE);
|
||||||
|
(new Handler()).post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mObjects.clear();
|
||||||
|
mAdapter.notifyDataSetChanged();
|
||||||
|
new ContactLoadTask(element, getBaseContext(), mAdapter, mObjects,
|
||||||
|
mLayout, contactProgressBar, mContactInfos).execute();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initSpinner() {
|
||||||
|
final Spinner sp = findViewById(R.id.contact_spinner);
|
||||||
|
assert sp != null;
|
||||||
|
sp.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
mContactInfos.setVisibility(View.INVISIBLE);
|
||||||
|
mContactPhoneListAdapter.clear();
|
||||||
|
|
||||||
|
mFetchedContact = sp.getSelectedItem().toString();
|
||||||
|
fetchContact(mFetchedContact);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNothingSelected(AdapterView<?> parent) {
|
||||||
|
// Nothing to do there
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
sp.setAdapter(mAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fetchContact(String name) {
|
||||||
|
if (!PermissionChecker.checkPermission(this, Manifest.permission.READ_CONTACTS,
|
||||||
|
REQUEST_CONTACTS)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor people = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
|
||||||
|
null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " = ?",
|
||||||
|
new String[]{name}, null);
|
||||||
|
if (people == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
people.moveToFirst();
|
||||||
|
|
||||||
|
Vector<String> r = new Vector<>();
|
||||||
|
if (people.getCount() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String contactId = people.getString(people.getColumnIndex(ContactsContract.Contacts._ID));
|
||||||
|
|
||||||
|
if ("1".equalsIgnoreCase(people.getString(people.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)))) {
|
||||||
|
Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
|
||||||
|
null,
|
||||||
|
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
|
||||||
|
new String[]{contactId}, null);
|
||||||
|
|
||||||
|
while ((phones != null) && phones.moveToNext()) {
|
||||||
|
r.add(phones.getString(phones.getColumnIndex(
|
||||||
|
ContactsContract.CommonDataKinds.Phone.NUMBER))
|
||||||
|
.replaceAll(" ", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phones != null) {
|
||||||
|
phones.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer smsCount = 0;
|
||||||
|
// @TODO asynctask to load more datas
|
||||||
|
|
||||||
|
if (!r.isEmpty()) {
|
||||||
|
for (String pn: r) {
|
||||||
|
mContactPhoneListAdapter.add(pn);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mContactPhoneListAdapter.add(mFetchedContact);
|
||||||
|
}
|
||||||
|
|
||||||
|
mContactInfos.setVisibility(View.VISIBLE);
|
||||||
|
mContactPhoneListAdapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Permissions
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
|
||||||
|
@NonNull int[] grantResults) {
|
||||||
|
PermissionID requestCodeID = REQUEST_MAX;
|
||||||
|
if ((requestCode > 0) || (requestCode < REQUEST_MAX.ordinal())) {
|
||||||
|
requestCodeID = PermissionID.values()[requestCode];
|
||||||
|
}
|
||||||
|
switch (requestCodeID) {
|
||||||
|
case REQUEST_CONTACTS:
|
||||||
|
for (int grantResult : grantResults) {
|
||||||
|
Log.i("OcSMS", Integer.toString(grantResult));
|
||||||
|
}
|
||||||
|
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
fetchContact(mFetchedContact);
|
||||||
|
} else {
|
||||||
|
// Permission Denied
|
||||||
|
Toast.makeText(this, getString(R.string.err_cannot_read_contacts) + " " +
|
||||||
|
getString(R.string.please_fix_it), Toast.LENGTH_SHORT)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,237 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.activities.remote_account;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2016, Loic Blot <loic.blot@unix-experience.fr>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.accounts.Account;
|
||||||
|
import android.accounts.AccountManager;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.provider.Telephony;
|
||||||
|
import android.support.v4.app.ActivityCompat;
|
||||||
|
import android.support.v7.app.ActionBar;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
|
import fr.unix_experience.owncloud_sms.engine.ASyncSMSRecovery;
|
||||||
|
import fr.unix_experience.owncloud_sms.engine.ConnectivityMonitor;
|
||||||
|
|
||||||
|
public class RestoreMessagesActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
Account _account = null;
|
||||||
|
String _defaultSmsApp;
|
||||||
|
private static final int REQUEST_DEFAULT_SMSAPP = 1;
|
||||||
|
boolean restoreInProgress = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_restore_messages);
|
||||||
|
|
||||||
|
ActionBar actionBar = getSupportActionBar();
|
||||||
|
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||||
|
|
||||||
|
assert getIntent().getExtras() != null;
|
||||||
|
|
||||||
|
String accountName = getIntent().getExtras().getString("account");
|
||||||
|
|
||||||
|
// accountName cannot be null, devel error
|
||||||
|
assert accountName != null;
|
||||||
|
AccountManager accountManager = AccountManager.get(getBaseContext());
|
||||||
|
Account[] accountList = accountManager.getAccountsByType(getString(R.string.account_type));
|
||||||
|
for (Account element : accountList) {
|
||||||
|
if (element.name.equals(accountName)) {
|
||||||
|
_account = element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_account == null) {
|
||||||
|
throw new IllegalStateException(getString(R.string.err_didnt_find_account_restore));
|
||||||
|
}
|
||||||
|
|
||||||
|
initInterface();
|
||||||
|
Button fix_button = findViewById(R.id.button_fix_permissions);
|
||||||
|
final Button launch_restore = findViewById(R.id.button_launch_restore);
|
||||||
|
final ProgressBar pb = findViewById(R.id.progressbar_restore);
|
||||||
|
|
||||||
|
final RestoreMessagesActivity me = this;
|
||||||
|
fix_button.setOnClickListener(new View.OnClickListener() {
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT) {
|
||||||
|
notifyIncompatibleVersion();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!new ConnectivityMonitor(me).isValid()) {
|
||||||
|
notifyNoConnectivity();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.i(RestoreMessagesActivity.TAG, "Ask to change the default SMS app");
|
||||||
|
|
||||||
|
Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
|
||||||
|
intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, getBaseContext().getPackageName());
|
||||||
|
startActivityForResult(intent, REQUEST_DEFAULT_SMSAPP);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
launch_restore.setOnClickListener(new View.OnClickListener() {
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (!new ConnectivityMonitor(me).isValid()) {
|
||||||
|
notifyNoConnectivity();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
launch_restore.setVisibility(View.INVISIBLE);
|
||||||
|
pb.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
// Verify connectivity
|
||||||
|
Log.i(RestoreMessagesActivity.TAG, "Launching restore asynchronously");
|
||||||
|
restoreInProgress = true;
|
||||||
|
new ASyncSMSRecovery.SMSRecoveryTask(me, _account).execute();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
boolean retval = true;
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case android.R.id.home:
|
||||||
|
finish();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
retval = super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initInterface() {
|
||||||
|
TextView tv_error = findViewById(R.id.tv_error_default_smsapp);
|
||||||
|
tv_error.setText(R.string.error_make_default_sms_app);
|
||||||
|
findViewById(R.id.tv_restore_finished).setVisibility(View.INVISIBLE);
|
||||||
|
findViewById(R.id.tv_progress_value).setVisibility(View.INVISIBLE);
|
||||||
|
Button fix_button = findViewById(R.id.button_fix_permissions);
|
||||||
|
Button launch_restore = findViewById(R.id.button_launch_restore);
|
||||||
|
ProgressBar pb = findViewById(R.id.progressbar_restore);
|
||||||
|
pb.setVisibility(View.INVISIBLE);
|
||||||
|
|
||||||
|
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT) {
|
||||||
|
notifyIncompatibleVersion();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_defaultSmsApp = Telephony.Sms.getDefaultSmsPackage(this);
|
||||||
|
if (!Telephony.Sms.getDefaultSmsPackage(this).equals(getPackageName())) {
|
||||||
|
_defaultSmsApp = Telephony.Sms.getDefaultSmsPackage(getBaseContext());
|
||||||
|
tv_error.setVisibility(View.VISIBLE);
|
||||||
|
fix_button.setVisibility(View.VISIBLE);
|
||||||
|
launch_restore.setVisibility(View.INVISIBLE);
|
||||||
|
} else {
|
||||||
|
tv_error.setVisibility(View.INVISIBLE);
|
||||||
|
fix_button.setVisibility(View.INVISIBLE);
|
||||||
|
launch_restore.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void errorNotification(int err) {
|
||||||
|
TextView tv = findViewById(R.id.tv_error_default_smsapp);
|
||||||
|
Button fix_button = findViewById(R.id.button_fix_permissions);
|
||||||
|
Button launch_restore = findViewById(R.id.button_launch_restore);
|
||||||
|
ProgressBar pb = findViewById(R.id.progressbar_restore);
|
||||||
|
tv.setText(err);
|
||||||
|
tv.setVisibility(View.VISIBLE);
|
||||||
|
fix_button.setVisibility(View.INVISIBLE);
|
||||||
|
launch_restore.setVisibility(View.INVISIBLE);
|
||||||
|
pb.setVisibility(View.INVISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyIncompatibleVersion() {
|
||||||
|
errorNotification(R.string.err_kitkat_required);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyNoConnectivity() {
|
||||||
|
errorNotification(R.string.err_no_connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
switch (requestCode) {
|
||||||
|
case RestoreMessagesActivity.REQUEST_DEFAULT_SMSAPP:
|
||||||
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
|
TextView tv = findViewById(R.id.tv_error_default_smsapp);
|
||||||
|
Button fix_button = findViewById(R.id.button_fix_permissions);
|
||||||
|
Button launch_restore = findViewById(R.id.button_launch_restore);
|
||||||
|
tv.setVisibility(View.INVISIBLE);
|
||||||
|
fix_button.setVisibility(View.INVISIBLE);
|
||||||
|
launch_restore.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
if (!new ConnectivityMonitor(this).isValid()) {
|
||||||
|
notifyNoConnectivity();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT) {
|
||||||
|
notifyIncompatibleVersion();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!restoreInProgress) {
|
||||||
|
initInterface();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onRestoreDone() {
|
||||||
|
findViewById(R.id.progressbar_restore).setVisibility(View.INVISIBLE);
|
||||||
|
findViewById(R.id.tv_restore_finished).setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
Intent finalIntent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
|
||||||
|
finalIntent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, _defaultSmsApp);
|
||||||
|
startActivity(finalIntent);
|
||||||
|
|
||||||
|
restoreInProgress = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onProgressUpdate(Integer value) {
|
||||||
|
TextView tv_progress = findViewById(R.id.tv_progress_value);
|
||||||
|
if (tv_progress.getVisibility() == View.INVISIBLE) {
|
||||||
|
tv_progress.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
tv_progress.setText(value.toString() + " " + getString(R.string.x_messages_restored));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String TAG = RestoreMessagesActivity.class.getSimpleName();
|
||||||
|
}
|
@ -0,0 +1,213 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.activities.virtual;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2013-2015, Loic Blot <loic.blot@unix-experience.fr>
|
||||||
|
* All rights reserved.
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are those
|
||||||
|
* of the authors and should not be interpreted as representing official policies,
|
||||||
|
* either expressed or implied, of the FreeBSD Project.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.preference.CheckBoxPreference;
|
||||||
|
import android.preference.ListPreference;
|
||||||
|
import android.preference.Preference;
|
||||||
|
import android.preference.PreferenceActivity;
|
||||||
|
import android.preference.PreferenceFragment;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
public class VirtualSettingsActivity extends PreferenceActivity {
|
||||||
|
private static String TAG = VirtualSettingsActivity.class.getSimpleName();
|
||||||
|
protected static Context _context;
|
||||||
|
protected static int _prefsRessourceFile;
|
||||||
|
protected static Vector<BindObjectPref> _boolPrefs = new Vector<>();
|
||||||
|
protected static Vector<BindObjectPref> _stringPrefs = new Vector<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostCreate(Bundle savedInstanceState) {
|
||||||
|
super.onPostCreate(savedInstanceState);
|
||||||
|
VirtualSettingsActivity._context = getBaseContext();
|
||||||
|
setupSimplePreferencesScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the simplified settings UI if the device configuration if the
|
||||||
|
* device configuration dictates that a simplified, single-pane UI should be
|
||||||
|
* shown.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
private void setupSimplePreferencesScreen() {
|
||||||
|
if (!VirtualSettingsActivity.isSimplePreferences(this)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the simplified UI, fragments are not used at all and we instead
|
||||||
|
// use the older PreferenceActivity APIs.
|
||||||
|
addPreferencesFromResource(VirtualSettingsActivity._prefsRessourceFile);
|
||||||
|
bindPreferences();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
@Override
|
||||||
|
public boolean onIsMultiPane() {
|
||||||
|
return VirtualSettingsActivity.isXLargeTablet(this) && !VirtualSettingsActivity.isSimplePreferences(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to determine if the device has an extra-large screen. For
|
||||||
|
* example, 10" tablets are extra-large.
|
||||||
|
*/
|
||||||
|
private static boolean isXLargeTablet(Context context) {
|
||||||
|
return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether the simplified settings UI should be shown. This is
|
||||||
|
* true if this is forced via the device
|
||||||
|
* doesn't have newer APIs like {@link PreferenceFragment}, or the device
|
||||||
|
* doesn't have an extra-large screen. In these cases, a single-pane
|
||||||
|
* "simplified" settings UI should be shown.
|
||||||
|
*/
|
||||||
|
protected static boolean isSimplePreferences(Context context) {
|
||||||
|
return (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
|
||||||
|
|| !VirtualSettingsActivity.isXLargeTablet(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binds a preference's summary to its value. More specifically, when the
|
||||||
|
* preference's value is changed, its summary (line of text below the
|
||||||
|
* preference title) is updated to reflect the value. The summary is also
|
||||||
|
* immediately updated upon calling this method. The exact display format is
|
||||||
|
* dependent on the type of preference.
|
||||||
|
*
|
||||||
|
* @see #bindPreferenceBooleanToValue
|
||||||
|
*/
|
||||||
|
public void bindPreferenceBooleanToValue(Preference preference, Boolean defValue) {
|
||||||
|
// Set the listener to watch for value changes.
|
||||||
|
preference
|
||||||
|
.setOnPreferenceChangeListener(_bindPreferenceListener);
|
||||||
|
|
||||||
|
// Trigger the listener immediately with the preference's
|
||||||
|
// current value.
|
||||||
|
_bindPreferenceListener.onPreferenceChange(
|
||||||
|
preference,
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(
|
||||||
|
preference.getContext()).getBoolean(
|
||||||
|
preference.getKey(),
|
||||||
|
defValue
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bindPreferenceStringToValue(Preference preference, String defValue) {
|
||||||
|
// Set the listener to watch for value changes.
|
||||||
|
preference
|
||||||
|
.setOnPreferenceChangeListener(_bindPreferenceListener);
|
||||||
|
|
||||||
|
// Trigger the listener immediately with the preference's
|
||||||
|
// current value.
|
||||||
|
_bindPreferenceListener.onPreferenceChange(
|
||||||
|
preference,
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(
|
||||||
|
preference.getContext()).getString(
|
||||||
|
preference.getKey(),
|
||||||
|
defValue
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This fragment shows data and sync preferences only. It is used when the
|
||||||
|
* activity is showing a two-pane settings UI.
|
||||||
|
*/
|
||||||
|
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||||
|
public static class DataSyncPreferenceFragment extends PreferenceFragment {
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
addPreferencesFromResource(VirtualSettingsActivity._prefsRessourceFile);
|
||||||
|
|
||||||
|
VirtualSettingsActivity a = (VirtualSettingsActivity) getActivity();
|
||||||
|
a.bindPreferences();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bindPreferences() {
|
||||||
|
// Bind the summaries of EditText/List/Dialog/Ringtone preferences to
|
||||||
|
// their values. When their values change, their summaries are updated
|
||||||
|
// to reflect the new value, per the Android Design guidelines.
|
||||||
|
for (BindObjectPref pref: VirtualSettingsActivity._stringPrefs) {
|
||||||
|
bindPreferenceStringToValue(findPreference(pref.name),
|
||||||
|
(String) pref.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (BindObjectPref pref: VirtualSettingsActivity._boolPrefs) {
|
||||||
|
bindPreferenceBooleanToValue(findPreference(pref.name),
|
||||||
|
(Boolean) pref.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The preference object, it's only a key value pair
|
||||||
|
protected class BindObjectPref {
|
||||||
|
public String name;
|
||||||
|
Object value;
|
||||||
|
public BindObjectPref(int resId, Object prefVal) {
|
||||||
|
name = getString(resId);
|
||||||
|
value = prefVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A preference value change listener that updates the preference's summary
|
||||||
|
* to reflect its new value.
|
||||||
|
*/
|
||||||
|
private final Preference.OnPreferenceChangeListener _bindPreferenceListener = new Preference.OnPreferenceChangeListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceChange(Preference preference, Object value) {
|
||||||
|
if (preference instanceof ListPreference) {
|
||||||
|
Log.i(TAG, "Changed list preference " + preference.toString() + " value " + value.toString());
|
||||||
|
handleListPreference(preference.getKey(), value.toString(), (ListPreference) preference);
|
||||||
|
|
||||||
|
} else if (preference instanceof CheckBoxPreference) {
|
||||||
|
Log.i(TAG, "Changed checkbox preference " + preference.toString() + " value " + value.toString());
|
||||||
|
handleCheckboxPreference(preference.getKey(), (Boolean) value);
|
||||||
|
} else {
|
||||||
|
// For all other preferences, set the summary to the value's
|
||||||
|
// simple string representation.
|
||||||
|
//preference.setSummary(boolValue);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
protected void handleCheckboxPreference(String key, Boolean value) {}
|
||||||
|
protected void handleListPreference(String key, String value,
|
||||||
|
ListPreference preference) {}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.adapters;
|
||||||
|
|
||||||
|
import android.accounts.Account;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class AndroidAccountAdapter extends ArrayAdapter<Account> {
|
||||||
|
|
||||||
|
private final ArrayList<Account> _accounts;
|
||||||
|
private static int _itemLayout;
|
||||||
|
private static int _accountFieldId;
|
||||||
|
private final Activity _activity;
|
||||||
|
Class<?> _newActivityClass;
|
||||||
|
|
||||||
|
public AndroidAccountAdapter(Activity activity, int resource,
|
||||||
|
ArrayList<Account> objects, int itemLayout,
|
||||||
|
int accountFieldId, Class<?> newActivityClass) {
|
||||||
|
super(activity.getBaseContext(), resource, objects);
|
||||||
|
_accounts = objects;
|
||||||
|
AndroidAccountAdapter._itemLayout = itemLayout;
|
||||||
|
AndroidAccountAdapter._accountFieldId = accountFieldId;
|
||||||
|
_activity = activity;
|
||||||
|
_newActivityClass = newActivityClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
|
View v = convertView;
|
||||||
|
if (v == null) {
|
||||||
|
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
|
v = inflater.inflate(AndroidAccountAdapter._itemLayout, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Account account = _accounts.get(position);
|
||||||
|
|
||||||
|
if (account != null) {
|
||||||
|
TextView label = v.findViewById(AndroidAccountAdapter._accountFieldId);
|
||||||
|
if (label != null) {
|
||||||
|
label.setText(account.name + " >");
|
||||||
|
v.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Intent i = new Intent(_activity, _newActivityClass);
|
||||||
|
i.putExtra("account", account.name);
|
||||||
|
_activity.startActivity(i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.adapters;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
|
|
||||||
|
public class ContactListAdapter extends ArrayAdapter<String> {
|
||||||
|
private final ArrayList<String> _objects;
|
||||||
|
|
||||||
|
// Design
|
||||||
|
private final static int _itemLayout = R.layout.contact_list_item;
|
||||||
|
private final static int _fieldId = R.id.contactname;
|
||||||
|
|
||||||
|
public ContactListAdapter(Context context, ArrayList<String> objects) {
|
||||||
|
super(context, android.R.layout.simple_spinner_item, objects);
|
||||||
|
_objects = objects;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
|
View v = convertView;
|
||||||
|
if (v == null) {
|
||||||
|
LayoutInflater inflater =
|
||||||
|
(LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
|
v = inflater.inflate(ContactListAdapter._itemLayout, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_objects.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String element = _objects.get(position);
|
||||||
|
|
||||||
|
if (element != null) {
|
||||||
|
TextView label = v.findViewById(ContactListAdapter._fieldId);
|
||||||
|
if (label != null) {
|
||||||
|
label.setText(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.adapters;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
|
|
||||||
|
public class RecoveryPhoneNumberListViewAdapter extends ArrayAdapter<String> {
|
||||||
|
private static final String TAG = "RecPhoneNumberListVAdp";
|
||||||
|
private static int _fieldId = R.id.recovery_phone;
|
||||||
|
private static int _itemLayout = R.layout.recovery_phone_list_item;
|
||||||
|
private static int resource = android.R.layout.simple_list_item_2;
|
||||||
|
|
||||||
|
public RecoveryPhoneNumberListViewAdapter(Context context) {
|
||||||
|
super(context, resource, new ArrayList<String>());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
|
View v = convertView;
|
||||||
|
if (v == null) {
|
||||||
|
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
|
v = inflater.inflate(RecoveryPhoneNumberListViewAdapter._itemLayout, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextView label = v.findViewById(RecoveryPhoneNumberListViewAdapter._fieldId);
|
||||||
|
if (label != null) {
|
||||||
|
final String l = getItem(position).toString();
|
||||||
|
label.setText(getItem(position).toString());
|
||||||
|
v.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Log.i(TAG, "Clicked on phone " + l);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
v.setOnLongClickListener(new View.OnLongClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onLongClick(View v) {
|
||||||
|
Log.i(TAG, "Long clicked on phone " + l);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
@ -17,16 +17,6 @@ package fr.unix_experience.owncloud_sms.authenticators;
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import org.apache.commons.httpclient.HttpException;
|
|
||||||
import org.apache.commons.httpclient.methods.GetMethod;
|
|
||||||
import org.apache.http.HttpStatus;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
|
||||||
|
|
||||||
import fr.unix_experience.owncloud_sms.activities.LoginActivity;
|
|
||||||
import fr.unix_experience.owncloud_sms.enums.LoginReturnCode;
|
|
||||||
import android.accounts.AbstractAccountAuthenticator;
|
import android.accounts.AbstractAccountAuthenticator;
|
||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
import android.accounts.AccountAuthenticatorResponse;
|
import android.accounts.AccountAuthenticatorResponse;
|
||||||
@ -35,7 +25,8 @@ import android.accounts.NetworkErrorException;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
|
||||||
|
import fr.unix_experience.owncloud_sms.activities.LoginActivity;
|
||||||
|
|
||||||
public class OwnCloudAuthenticator extends AbstractAccountAuthenticator {
|
public class OwnCloudAuthenticator extends AbstractAccountAuthenticator {
|
||||||
// Simple constructor
|
// Simple constructor
|
||||||
@ -56,8 +47,8 @@ public class OwnCloudAuthenticator extends AbstractAccountAuthenticator {
|
|||||||
String accountType, String authTokenType,
|
String accountType, String authTokenType,
|
||||||
String[] requiredFeatures, Bundle options)
|
String[] requiredFeatures, Bundle options)
|
||||||
throws NetworkErrorException {
|
throws NetworkErrorException {
|
||||||
final Bundle result;
|
Bundle result;
|
||||||
final Intent intent;
|
Intent intent;
|
||||||
|
|
||||||
intent = new Intent(_context, LoginActivity.class);
|
intent = new Intent(_context, LoginActivity.class);
|
||||||
|
|
||||||
@ -101,96 +92,8 @@ public class OwnCloudAuthenticator extends AbstractAccountAuthenticator {
|
|||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Return codes
|
|
||||||
* 1: invalid address
|
|
||||||
* 2: HTTP failed
|
|
||||||
* 3: connexion failed
|
|
||||||
* 4: invalid login
|
|
||||||
* 5: unknown error
|
|
||||||
*/
|
|
||||||
public LoginReturnCode testCredentials() {
|
|
||||||
LoginReturnCode bRet = LoginReturnCode.OK;
|
|
||||||
GetMethod get = null;
|
|
||||||
int status = -1;
|
|
||||||
|
|
||||||
try {
|
|
||||||
get = new GetMethod(_client.getBaseUri() + "/index.php/ocs/cloud/user?format=json");
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
return LoginReturnCode.INVALID_ADDR;
|
|
||||||
}
|
|
||||||
|
|
||||||
get.addRequestHeader("OCS-APIREQUEST", "true");
|
|
||||||
|
|
||||||
try {
|
|
||||||
status = _client.executeMethod(get);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
return LoginReturnCode.INVALID_ADDR;
|
|
||||||
} catch (HttpException e) {
|
|
||||||
return LoginReturnCode.HTTP_CONN_FAILED;
|
|
||||||
} catch (IOException e) {
|
|
||||||
return LoginReturnCode.CONN_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if(isSuccess(status)) {
|
|
||||||
String response = get.getResponseBodyAsString();
|
|
||||||
Log.d(TAG, "Successful response: " + response);
|
|
||||||
|
|
||||||
// Parse the response
|
private final Context _context;
|
||||||
JSONObject respJSON = new JSONObject(response);
|
|
||||||
JSONObject respOCS = respJSON.getJSONObject(NODE_OCS);
|
|
||||||
JSONObject respData = respOCS.getJSONObject(NODE_DATA);
|
|
||||||
String id = respData.getString(NODE_ID);
|
|
||||||
String displayName = respData.getString(NODE_DISPLAY_NAME);
|
|
||||||
String email = respData.getString(NODE_EMAIL);
|
|
||||||
|
|
||||||
Log.d(TAG, "*** Parsed user information: " + id + " - " + displayName + " - " + email);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
String response = get.getResponseBodyAsString();
|
|
||||||
Log.e(TAG, "Failed response while getting user information ");
|
|
||||||
if (response != null) {
|
|
||||||
Log.e(TAG, "*** status code: " + status + " ; response message: " + response);
|
|
||||||
} else {
|
|
||||||
Log.e(TAG, "*** status code: " + status);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status == 401) {
|
|
||||||
bRet = LoginReturnCode.INVALID_LOGIN;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bRet = LoginReturnCode.UNKNOWN_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Exception while getting OC user information", e);
|
|
||||||
bRet = LoginReturnCode.UNKNOWN_ERROR;
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
get.releaseConnection();
|
|
||||||
}
|
|
||||||
return bRet;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isSuccess(int status) {
|
|
||||||
return (status == HttpStatus.SC_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setClient(OwnCloudClient oc) {
|
|
||||||
_client = oc;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Context _context;
|
|
||||||
private OwnCloudClient _client;
|
|
||||||
|
|
||||||
private static final String TAG = OwnCloudAuthenticator.class.getSimpleName();
|
private static final String TAG = OwnCloudAuthenticator.class.getSimpleName();
|
||||||
|
|
||||||
private static final String NODE_OCS = "ocs";
|
|
||||||
private static final String NODE_DATA = "data";
|
|
||||||
private static final String NODE_ID = "id";
|
|
||||||
private static final String NODE_DISPLAY_NAME= "display-name";
|
|
||||||
private static final String NODE_EMAIL= "email";
|
|
||||||
}
|
}
|
@ -0,0 +1,98 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.broadcast_receivers;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.accounts.Account;
|
||||||
|
import android.accounts.AccountManager;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
|
import fr.unix_experience.owncloud_sms.engine.ASyncSMSSync;
|
||||||
|
import fr.unix_experience.owncloud_sms.engine.AndroidSmsFetcher;
|
||||||
|
import fr.unix_experience.owncloud_sms.engine.ConnectivityMonitor;
|
||||||
|
import fr.unix_experience.owncloud_sms.enums.PermissionID;
|
||||||
|
import fr.unix_experience.owncloud_sms.prefs.OCSMSSharedPrefs;
|
||||||
|
import fr.unix_experience.owncloud_sms.prefs.PermissionChecker;
|
||||||
|
import ncsmsgo.SmsBuffer;
|
||||||
|
|
||||||
|
public class ConnectivityChanged extends BroadcastReceiver implements ASyncSMSSync {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
// No account: abort
|
||||||
|
Account[] myAccountList = AccountManager.get(context).
|
||||||
|
getAccountsByType(context.getString(R.string.account_type));
|
||||||
|
if (myAccountList.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectivityMonitor cMon = new ConnectivityMonitor(context);
|
||||||
|
|
||||||
|
OCSMSSharedPrefs prefs = new OCSMSSharedPrefs(context);
|
||||||
|
|
||||||
|
if (!prefs.pushOnReceive()) {
|
||||||
|
Log.i(ConnectivityChanged.TAG,"ConnectivityChanges.onReceive: pushOnReceive is disabled");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If data is available and previous dataConnectionState was false, then we need to sync
|
||||||
|
if (cMon.isValid() && !ConnectivityChanged.dataConnectionAvailable) {
|
||||||
|
ConnectivityChanged.dataConnectionAvailable = true;
|
||||||
|
Log.i(ConnectivityChanged.TAG,"ConnectivityChanged.onReceive, data conn available");
|
||||||
|
|
||||||
|
if (!PermissionChecker.checkPermission(context, Manifest.permission.READ_SMS,
|
||||||
|
PermissionID.REQUEST_SMS)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkMessagesAndSend(context);
|
||||||
|
}
|
||||||
|
// No data available and previous dataConnectionState was true
|
||||||
|
else if (ConnectivityChanged.dataConnectionAvailable && !cMon.isValid()) {
|
||||||
|
ConnectivityChanged.dataConnectionAvailable = false;
|
||||||
|
Log.i(ConnectivityChanged.TAG,"ConnectivityChanges.onReceive: data conn is off");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkMessagesAndSend(Context context) {
|
||||||
|
// Get last message synced from preferences
|
||||||
|
Long lastMessageSynced = (new OCSMSSharedPrefs(context)).getLastMessageDate();
|
||||||
|
Log.i(ConnectivityChanged.TAG,"Synced Last:" + lastMessageSynced);
|
||||||
|
|
||||||
|
// Now fetch messages since last stored date
|
||||||
|
SmsBuffer smsBuffer = new SmsBuffer();
|
||||||
|
new AndroidSmsFetcher(context).bufferMessagesSinceDate(smsBuffer, lastMessageSynced);
|
||||||
|
|
||||||
|
AtomicReference<ConnectivityMonitor> cMon = new AtomicReference<>(new ConnectivityMonitor(context));
|
||||||
|
|
||||||
|
// Synchronize if network is valid and there are SMS
|
||||||
|
if (cMon.get().isValid() && !smsBuffer.empty()) {
|
||||||
|
new SyncTask(context, smsBuffer).execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean dataConnectionAvailable = false;
|
||||||
|
|
||||||
|
private static final String TAG = ConnectivityChanged.class.getSimpleName();
|
||||||
|
}
|
@ -17,7 +17,6 @@ package fr.unix_experience.owncloud_sms.broadcast_receivers;
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import fr.unix_experience.owncloud_sms.observers.SmsObserver;
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@ -25,15 +24,17 @@ import android.net.Uri;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import fr.unix_experience.owncloud_sms.observers.SmsObserver;
|
||||||
|
|
||||||
public class IncomingSms extends BroadcastReceiver {
|
public class IncomingSms extends BroadcastReceiver {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if (_mboxObserver == null) {
|
if (IncomingSms._mboxObserver == null) {
|
||||||
Log.d(TAG,"_mboxObserver == null");
|
Log.i(IncomingSms.TAG,"_mboxObserver == null");
|
||||||
_mboxObserver = new SmsObserver(new Handler(), context);
|
IncomingSms._mboxObserver = new SmsObserver(new Handler(), context);
|
||||||
context.getContentResolver().
|
context.getContentResolver().
|
||||||
registerContentObserver(Uri.parse("content://sms"), true, _mboxObserver);
|
registerContentObserver(Uri.parse("content://sms"), true, IncomingSms._mboxObserver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.defines;
|
||||||
|
|
||||||
|
public class DefaultPrefs {
|
||||||
|
public final static Integer syncInterval = 15;
|
||||||
|
public final static Integer minimumCharsForSync = 0;
|
||||||
|
public final static Boolean pushOnReceive = true;
|
||||||
|
public final static Boolean showSyncNotifications = true;
|
||||||
|
|
||||||
|
public final static Boolean syncWifi = true;
|
||||||
|
public final static Boolean sync2G = true;
|
||||||
|
public final static Boolean syncGPRS = true;
|
||||||
|
public final static Boolean sync3G = true;
|
||||||
|
public final static Boolean sync4G = true;
|
||||||
|
public final static Boolean syncOthers = true;
|
||||||
|
}
|
@ -0,0 +1,153 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.engine;
|
||||||
|
|
||||||
|
import android.accounts.Account;
|
||||||
|
import android.accounts.AccountManager;
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.provider.ContactsContract;
|
||||||
|
import android.support.v4.widget.SwipeRefreshLayout;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
|
import fr.unix_experience.owncloud_sms.adapters.ContactListAdapter;
|
||||||
|
import fr.unix_experience.owncloud_sms.exceptions.OCSyncException;
|
||||||
|
import ncsmsgo.SmsPhoneListResponse;
|
||||||
|
|
||||||
|
public interface ASyncContactLoad {
|
||||||
|
class ContactLoadTask extends AsyncTask<Void, Void, Boolean> {
|
||||||
|
private static AccountManager _accountMgr = null;
|
||||||
|
private static Account _account;
|
||||||
|
private final Context _context;
|
||||||
|
private final ContactListAdapter _adapter;
|
||||||
|
private final ArrayList<String> _objects;
|
||||||
|
private final SwipeRefreshLayout _layout;
|
||||||
|
private final ProgressBar _pg;
|
||||||
|
private final LinearLayout _contactLayout;
|
||||||
|
|
||||||
|
public ContactLoadTask(Account account, Context context,
|
||||||
|
ContactListAdapter adapter, ArrayList<String> objects, SwipeRefreshLayout layout,
|
||||||
|
ProgressBar pg, LinearLayout sp) {
|
||||||
|
if (ContactLoadTask._accountMgr == null) {
|
||||||
|
ContactLoadTask._accountMgr = AccountManager.get(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
ContactLoadTask._account = account;
|
||||||
|
_context = context;
|
||||||
|
_adapter = adapter;
|
||||||
|
_objects = objects;
|
||||||
|
_layout = layout;
|
||||||
|
_pg = pg;
|
||||||
|
_contactLayout = sp;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected Boolean doInBackground(Void... params) {
|
||||||
|
OCSMSOwnCloudClient _client = null;
|
||||||
|
try {
|
||||||
|
_client = new OCSMSOwnCloudClient(_context, ContactLoadTask._account);
|
||||||
|
}
|
||||||
|
catch (IllegalStateException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove all objects, due to refreshing handling
|
||||||
|
_objects.clear();
|
||||||
|
try {
|
||||||
|
if (_client.getServerAPIVersion() < 2) {
|
||||||
|
_objects.add(_context.getString(R.string.err_proto_v2));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<String> serverPhoneList = new ArrayList<>();
|
||||||
|
|
||||||
|
SmsPhoneListResponse splr = _client.getServerPhoneNumbers();
|
||||||
|
if (splr == null) {
|
||||||
|
_objects.add(_context.getString(R.string.err_fetch_phonelist));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String phoneNumber;
|
||||||
|
while (!(phoneNumber = splr.getNextEntry()).equals("")) {
|
||||||
|
serverPhoneList.add(phoneNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read all contacts
|
||||||
|
readContacts(serverPhoneList);
|
||||||
|
|
||||||
|
_objects.addAll(serverPhoneList);
|
||||||
|
|
||||||
|
// Sort phone numbers
|
||||||
|
Collections.sort(_objects);
|
||||||
|
} catch (OCSyncException e) {
|
||||||
|
_objects.add(_context.getString(e.getErrorId()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readContacts(ArrayList<String> serverPhoneList) {
|
||||||
|
ContentResolver cr = _context.getContentResolver();
|
||||||
|
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
|
||||||
|
null, null, null, null);
|
||||||
|
if (cur == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur.getCount() == 0) {
|
||||||
|
cur.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String id, name;
|
||||||
|
while (cur.moveToNext()) {
|
||||||
|
id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
|
||||||
|
name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
|
||||||
|
if (Integer.parseInt(cur.getString(
|
||||||
|
cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
|
||||||
|
|
||||||
|
// Fetch all phone numbers
|
||||||
|
Cursor pCur = cr.query(
|
||||||
|
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
|
||||||
|
null,
|
||||||
|
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
|
||||||
|
new String[]{id}, null);
|
||||||
|
while ((pCur != null) && pCur.moveToNext()) {
|
||||||
|
String phoneNo = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))
|
||||||
|
.replaceAll(" ", "");
|
||||||
|
if (serverPhoneList.contains(phoneNo)) {
|
||||||
|
if (!_objects.contains(name)) {
|
||||||
|
_objects.add(name);
|
||||||
|
}
|
||||||
|
serverPhoneList.remove(phoneNo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pCur != null) {
|
||||||
|
pCur.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cur.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onPostExecute(Boolean success) {
|
||||||
|
_adapter.notifyDataSetChanged();
|
||||||
|
_layout.setRefreshing(false);
|
||||||
|
if (_pg != null) {
|
||||||
|
_pg.setVisibility(View.INVISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_contactLayout != null) {
|
||||||
|
_contactLayout.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String TAG = ASyncContactLoad.class.getSimpleName();
|
||||||
|
}
|
@ -0,0 +1,145 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.engine;
|
||||||
|
|
||||||
|
import android.accounts.Account;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.provider.Telephony;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import fr.unix_experience.owncloud_sms.activities.remote_account.RestoreMessagesActivity;
|
||||||
|
import fr.unix_experience.owncloud_sms.enums.MailboxID;
|
||||||
|
import fr.unix_experience.owncloud_sms.providers.SmsDataProvider;
|
||||||
|
import ncsmsgo.SmsMessage;
|
||||||
|
import ncsmsgo.SmsMessagesResponse;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2016, Loic Blot <loic.blot@unix-experience.fr>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface ASyncSMSRecovery {
|
||||||
|
class SMSRecoveryTask extends AsyncTask<Void, Integer, Void> {
|
||||||
|
private final RestoreMessagesActivity _context;
|
||||||
|
private final Account _account;
|
||||||
|
|
||||||
|
public SMSRecoveryTask(RestoreMessagesActivity context, Account account) {
|
||||||
|
_context = context;
|
||||||
|
_account = account;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params) {
|
||||||
|
// This feature is only available for Android 4.4 and greater
|
||||||
|
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!new ConnectivityMonitor(_context).isValid()) {
|
||||||
|
Log.e(ASyncSMSRecovery.TAG, "Restore connectivity problems, aborting");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.i(ASyncSMSRecovery.TAG, "Starting background recovery");
|
||||||
|
Long start = (long) 0;
|
||||||
|
|
||||||
|
OCSMSOwnCloudClient client = new OCSMSOwnCloudClient(_context, _account);
|
||||||
|
SmsDataProvider smsDataProvider = new SmsDataProvider(_context);
|
||||||
|
SmsMessagesResponse obj = client.retrieveSomeMessages(start, 500);
|
||||||
|
if (obj == null) {
|
||||||
|
Log.i(ASyncSMSRecovery.TAG, "Retrieved returns failure");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer nb = 0;
|
||||||
|
while ((obj != null) && (obj.getLastID() != start)) {
|
||||||
|
Log.i(TAG, "Retrieving messages from " + Long.toString(start)
|
||||||
|
+ " to " + Long.toString(obj.getLastID()));
|
||||||
|
SmsMessage message;
|
||||||
|
while ((message = obj.getNextMessage()) != null) {
|
||||||
|
int mbid = (int) message.getMailbox();
|
||||||
|
// Ignore invalid mailbox
|
||||||
|
if (mbid > MailboxID.ALL.getId()) {
|
||||||
|
Log.e(ASyncSMSRecovery.TAG, "Invalid mailbox found: " + mbid);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String address = message.getAddress();
|
||||||
|
String body = message.getMessage();
|
||||||
|
int type = (int) message.getType();
|
||||||
|
if (address.isEmpty() || body.isEmpty()) {
|
||||||
|
Log.e(ASyncSMSRecovery.TAG, "Invalid SMS message found: " + message.toString());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
MailboxID mailbox_id = MailboxID.fromInt(mbid);
|
||||||
|
|
||||||
|
String date = Long.toString(message.getDate());
|
||||||
|
// Ignore already existing messages
|
||||||
|
if (smsDataProvider.messageExists(address, body, date, mailbox_id)) {
|
||||||
|
publishProgress(nb);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
values.put(Telephony.Sms.ADDRESS, address);
|
||||||
|
values.put(Telephony.Sms.BODY, body);
|
||||||
|
values.put(Telephony.Sms.DATE, date);
|
||||||
|
values.put(Telephony.Sms.TYPE, type);
|
||||||
|
values.put(Telephony.Sms.SEEN, 1);
|
||||||
|
values.put(Telephony.Sms.READ, 1);
|
||||||
|
|
||||||
|
_context.getContentResolver().insert(Uri.parse(mailbox_id.getURI()), values);
|
||||||
|
|
||||||
|
nb++;
|
||||||
|
if ((nb % 10) == 0) {
|
||||||
|
publishProgress(nb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
start = obj.getLastID();
|
||||||
|
|
||||||
|
if (!new ConnectivityMonitor(_context).isValid()) {
|
||||||
|
Log.e(ASyncSMSRecovery.TAG, "Restore connectivity problems, aborting");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
obj = client.retrieveSomeMessages(start, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force this refresh to fix dates
|
||||||
|
_context.getContentResolver().delete(Uri.parse("content://sms/conversations/-1"),
|
||||||
|
null, null);
|
||||||
|
|
||||||
|
publishProgress(nb);
|
||||||
|
|
||||||
|
Log.i(ASyncSMSRecovery.TAG, "Finishing background recovery");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onProgressUpdate(Integer... values) {
|
||||||
|
super.onProgressUpdate(values);
|
||||||
|
_context.onProgressUpdate(values[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void aVoid) {
|
||||||
|
super.onPostExecute(aVoid);
|
||||||
|
_context.onRestoreDone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String TAG = ASyncSMSRecovery.class.getSimpleName();
|
||||||
|
}
|
@ -0,0 +1,140 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.engine;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2016, Loic Blot <loic.blot@unix-experience.fr>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.accounts.Account;
|
||||||
|
import android.accounts.AccountManager;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
|
import fr.unix_experience.owncloud_sms.enums.OCSMSNotificationType;
|
||||||
|
import fr.unix_experience.owncloud_sms.exceptions.OCSyncException;
|
||||||
|
import fr.unix_experience.owncloud_sms.notifications.OCSMSNotificationUI;
|
||||||
|
import fr.unix_experience.owncloud_sms.prefs.OCSMSSharedPrefs;
|
||||||
|
import ncsmsgo.SmsBuffer;
|
||||||
|
|
||||||
|
public interface ASyncSMSSync {
|
||||||
|
class SyncTask extends AsyncTask<Void, Void, Void> {
|
||||||
|
public SyncTask(Activity context) {
|
||||||
|
_activity = context;
|
||||||
|
_context = context;
|
||||||
|
_smsBuffer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SyncTask(Context context, SmsBuffer buffer) {
|
||||||
|
_activity = null;
|
||||||
|
_context = context;
|
||||||
|
_smsBuffer = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params) {
|
||||||
|
Log.i(ASyncSMSSync.TAG, "Starting background sync");
|
||||||
|
|
||||||
|
// If no smsBuffer given it's a full sync
|
||||||
|
if (_smsBuffer == null) {
|
||||||
|
doFullSync();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
performSync(_smsBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.i(ASyncSMSSync.TAG, "Stopping background sync");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doFullSync() {
|
||||||
|
OCSMSSharedPrefs prefs = new OCSMSSharedPrefs(_context);
|
||||||
|
long syncStartupDate = prefs.getLastMessageDate();
|
||||||
|
|
||||||
|
Log.i(ASyncSMSSync.TAG, "Current message date is " + syncStartupDate);
|
||||||
|
boolean shouldSync = true;
|
||||||
|
boolean hasSyncSomething = false;
|
||||||
|
AndroidSmsFetcher fetcher = new AndroidSmsFetcher(_context);
|
||||||
|
while (shouldSync) {
|
||||||
|
SmsBuffer smsBuffer = new SmsBuffer();
|
||||||
|
fetcher.bufferMessagesSinceDate(smsBuffer, syncStartupDate);
|
||||||
|
if (smsBuffer.empty()) {
|
||||||
|
if (_activity != null) {
|
||||||
|
final boolean syncComplete = hasSyncSomething;
|
||||||
|
_activity.runOnUiThread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
Toast.makeText(_context,
|
||||||
|
_context.getString(syncComplete ? R.string.sync_complete : R.string.nothing_to_sync),
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.i(ASyncSMSSync.TAG, "Finish syncAllMessages(): no more sms");
|
||||||
|
smsBuffer.clear();
|
||||||
|
shouldSync = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefs.showSyncNotifications()) {
|
||||||
|
OCSMSNotificationUI.notify(_context, _context.getString(R.string.sync_title),
|
||||||
|
_context.getString(R.string.sync_inprogress), OCSMSNotificationType.SYNC);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
syncStartupDate = smsBuffer.getLastMessageDate();
|
||||||
|
performSync(smsBuffer);
|
||||||
|
hasSyncSomething = true;
|
||||||
|
} finally {
|
||||||
|
OCSMSNotificationUI.cancel(_context, OCSMSNotificationType.SYNC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void performSync(SmsBuffer smsBuffer) {
|
||||||
|
// Get ownCloud SMS account list
|
||||||
|
AccountManager _accountMgr = AccountManager.get(_context);
|
||||||
|
Account[] myAccountList = _accountMgr.getAccountsByType(_context.getString(R.string.account_type));
|
||||||
|
|
||||||
|
// Notify that we are syncing SMS
|
||||||
|
for (Account element : myAccountList) {
|
||||||
|
try {
|
||||||
|
OCSMSOwnCloudClient _client = new OCSMSOwnCloudClient(_context, element);
|
||||||
|
// Fetch API version first to do some early verifications
|
||||||
|
Log.i(ASyncSMSSync.TAG, "Server API version: " + _client.getServerAPIVersion());
|
||||||
|
_client.doPushRequest(smsBuffer);
|
||||||
|
OCSMSNotificationUI.cancel(_context, OCSMSNotificationType.SYNC_FAILED);
|
||||||
|
} catch (IllegalStateException e) { // Fail to read account data
|
||||||
|
OCSMSNotificationUI.notify(_context, _context.getString(R.string.fatal_error),
|
||||||
|
e.getMessage(), OCSMSNotificationType.SYNC_FAILED);
|
||||||
|
} catch (OCSyncException e) {
|
||||||
|
Log.e(ASyncSMSSync.TAG, _context.getString(e.getErrorId()));
|
||||||
|
OCSMSNotificationUI.notify(_context, _context.getString(R.string.fatal_error),
|
||||||
|
e.getMessage(), OCSMSNotificationType.SYNC_FAILED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
smsBuffer.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final SmsBuffer _smsBuffer;
|
||||||
|
private final Context _context;
|
||||||
|
private final Activity _activity;
|
||||||
|
}
|
||||||
|
|
||||||
|
String TAG = ASyncSMSSync.class.getSimpleName();
|
||||||
|
}
|
@ -0,0 +1,254 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.engine;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
|
||||||
|
import fr.unix_experience.owncloud_sms.enums.MailboxID;
|
||||||
|
import fr.unix_experience.owncloud_sms.providers.SmsDataProvider;
|
||||||
|
import ncsmsgo.SmsBuffer;
|
||||||
|
|
||||||
|
public class AndroidSmsFetcher {
|
||||||
|
public AndroidSmsFetcher(Context ct) {
|
||||||
|
_context = ct;
|
||||||
|
|
||||||
|
_existingInboxMessages = null;
|
||||||
|
_existingSentMessages = null;
|
||||||
|
_existingDraftsMessages = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fetchAllMessages(SmsBuffer result) {
|
||||||
|
bufferMailboxMessages(result, MailboxID.INBOX);
|
||||||
|
bufferMailboxMessages(result, MailboxID.SENT);
|
||||||
|
bufferMailboxMessages(result, MailboxID.DRAFTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readMailBox(Cursor c, SmsBuffer smsBuffer, MailboxID mbID) {
|
||||||
|
do {
|
||||||
|
SmsEntry entry = new SmsEntry();
|
||||||
|
|
||||||
|
for (int idx = 0; idx < c.getColumnCount(); idx++) {
|
||||||
|
handleProviderColumn(c, idx, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mailbox ID is required by server
|
||||||
|
entry.mailboxId = mbID.ordinal();
|
||||||
|
smsBuffer.push(entry.id,
|
||||||
|
mbID.ordinal(),
|
||||||
|
entry.type,
|
||||||
|
entry.date,
|
||||||
|
entry.address,
|
||||||
|
entry.body,
|
||||||
|
entry.read ? "true" : "false",
|
||||||
|
entry.seen ? "true" : "false");
|
||||||
|
}
|
||||||
|
while (c.moveToNext());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bufferMailboxMessages(SmsBuffer smsBuffer, MailboxID mbID) {
|
||||||
|
if ((_context == null)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mbID != MailboxID.INBOX) && (mbID != MailboxID.SENT) &&
|
||||||
|
(mbID != MailboxID.DRAFTS)) {
|
||||||
|
Log.e(AndroidSmsFetcher.TAG, "Unhandled MailboxID " + mbID.ordinal());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We generate a ID list for this message box
|
||||||
|
String existingIDs = buildExistingMessagesString(mbID);
|
||||||
|
Cursor c = new SmsDataProvider(_context).queryNonExistingMessages(mbID.getURI(), existingIDs);
|
||||||
|
|
||||||
|
if (c == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reading mailbox
|
||||||
|
readMailBox(c, smsBuffer, mbID);
|
||||||
|
|
||||||
|
Log.i(AndroidSmsFetcher.TAG, c.getCount() + " messages read from " + mbID.getURI());
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used by Content Observer
|
||||||
|
public SmsBuffer getLastMessage(MailboxID mbID) {
|
||||||
|
if ((_context == null)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch Sent SMS Message from Built-in Content Provider
|
||||||
|
Cursor c = (new SmsDataProvider(_context)).query(mbID.getURI());
|
||||||
|
if (c == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We create a list of strings to store results
|
||||||
|
SmsEntry entry = new SmsEntry();
|
||||||
|
SmsBuffer results = new SmsBuffer();
|
||||||
|
|
||||||
|
Integer mboxId = -1;
|
||||||
|
for (int idx = 0; idx < c.getColumnCount(); idx++) {
|
||||||
|
Integer rid = handleProviderColumn(c, idx, entry);
|
||||||
|
if (rid != -1) {
|
||||||
|
mboxId = rid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mailbox ID is required by server
|
||||||
|
* mboxId is greater than server mboxId by 1 because types
|
||||||
|
* aren't indexed in the same mean
|
||||||
|
*/
|
||||||
|
entry.mailboxId = mboxId - 1;
|
||||||
|
results.push(entry.id,
|
||||||
|
mbID.ordinal(),
|
||||||
|
entry.type,
|
||||||
|
entry.date,
|
||||||
|
entry.address,
|
||||||
|
entry.body,
|
||||||
|
entry.read ? "true" : "false",
|
||||||
|
entry.seen ? "true" : "false");
|
||||||
|
|
||||||
|
c.close();
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used by ConnectivityChanged Event
|
||||||
|
public void bufferMessagesSinceDate(SmsBuffer smsBuffer, Long sinceDate) {
|
||||||
|
bufferMessagesSinceDate(smsBuffer, MailboxID.INBOX, sinceDate);
|
||||||
|
bufferMessagesSinceDate(smsBuffer, MailboxID.SENT, sinceDate);
|
||||||
|
bufferMessagesSinceDate(smsBuffer, MailboxID.DRAFTS, sinceDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used by ConnectivityChanged Event
|
||||||
|
private void bufferMessagesSinceDate(SmsBuffer smsBuffer, MailboxID mbID, Long sinceDate) {
|
||||||
|
Log.i(AndroidSmsFetcher.TAG, "bufferMessagesSinceDate for " + mbID.toString() + " sinceDate " + sinceDate.toString());
|
||||||
|
if ((_context == null)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor c = new SmsDataProvider(_context).queryMessagesSinceDate(mbID.getURI(), sinceDate);
|
||||||
|
if (c != null) {
|
||||||
|
Log.i(AndroidSmsFetcher.TAG, "Retrieved " + c.getCount() + " messages.");
|
||||||
|
} else {
|
||||||
|
Log.i(AndroidSmsFetcher.TAG, "No message retrieved.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read Mailbox
|
||||||
|
readMailBox(c, smsBuffer, mbID);
|
||||||
|
|
||||||
|
Log.i(AndroidSmsFetcher.TAG, c.getCount() + " messages read from " + mbID.getURI());
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer handleProviderColumn(Cursor c, int idx, SmsEntry entry) {
|
||||||
|
String colName = c.getColumnName(idx);
|
||||||
|
|
||||||
|
// Id column is must be an integer
|
||||||
|
switch (colName) {
|
||||||
|
case "_id":
|
||||||
|
entry.id = c.getInt(idx);
|
||||||
|
break;
|
||||||
|
case "type":
|
||||||
|
entry.type = c.getInt(idx);
|
||||||
|
return c.getInt(idx);
|
||||||
|
/* For debug purpose
|
||||||
|
case "length(address)":
|
||||||
|
Log.i(AndroidSmsFetcher.TAG, "Column name " + colName + " " + c.getString(idx));
|
||||||
|
break;*/
|
||||||
|
// Seen and read must be pseudo boolean
|
||||||
|
case "read":
|
||||||
|
entry.read = (c.getInt(idx) > 0);
|
||||||
|
break;
|
||||||
|
case "seen":
|
||||||
|
entry.seen = (c.getInt(idx) > 0);
|
||||||
|
break;
|
||||||
|
case "date":
|
||||||
|
entry.date = c.getLong(idx);
|
||||||
|
break;
|
||||||
|
case "address":
|
||||||
|
entry.address = c.getString(idx);
|
||||||
|
break;
|
||||||
|
case "body":
|
||||||
|
entry.body = c.getString(idx);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Unhandled column
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildExistingMessagesString(MailboxID _mbID) {
|
||||||
|
JSONArray existingMessages = null;
|
||||||
|
if (_mbID == MailboxID.INBOX) {
|
||||||
|
existingMessages = _existingInboxMessages;
|
||||||
|
} else if (_mbID == MailboxID.DRAFTS) {
|
||||||
|
existingMessages = _existingDraftsMessages;
|
||||||
|
} else if (_mbID == MailboxID.SENT) {
|
||||||
|
existingMessages = _existingSentMessages;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existingMessages == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: The default case isn't possible, we check the mailbox before
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
int len = existingMessages.length();
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
try {
|
||||||
|
if (sb.length() > 0) {
|
||||||
|
sb.append(",");
|
||||||
|
}
|
||||||
|
sb.append(existingMessages.getInt(i));
|
||||||
|
} catch (JSONException ignored) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setExistingInboxMessages(JSONArray inboxMessages) {
|
||||||
|
_existingInboxMessages = inboxMessages;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setExistingSentMessages(JSONArray sentMessages) {
|
||||||
|
_existingSentMessages = sentMessages;
|
||||||
|
}
|
||||||
|
void setExistingDraftsMessages(JSONArray draftMessages) {
|
||||||
|
_existingDraftsMessages = draftMessages;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Context _context;
|
||||||
|
private JSONArray _existingInboxMessages;
|
||||||
|
private JSONArray _existingSentMessages;
|
||||||
|
private JSONArray _existingDraftsMessages;
|
||||||
|
|
||||||
|
private static final String TAG = AndroidSmsFetcher.class.getSimpleName();
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.engine;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
|
import android.net.NetworkInfo;
|
||||||
|
import android.telephony.TelephonyManager;
|
||||||
|
|
||||||
|
import fr.unix_experience.owncloud_sms.prefs.OCSMSSharedPrefs;
|
||||||
|
|
||||||
|
public class ConnectivityMonitor {
|
||||||
|
public ConnectivityMonitor(Context context) {
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid connection = WiFi or Mobile data
|
||||||
|
public boolean isValid() {
|
||||||
|
if (_cMgr == null) {
|
||||||
|
_cMgr = (ConnectivityManager) _context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
android.net.NetworkInfo niWiFi = _cMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
|
||||||
|
android.net.NetworkInfo niMobile = _cMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
|
||||||
|
|
||||||
|
if (niWiFi.isAvailable() || niMobile.isAvailable()) {
|
||||||
|
// Load the connectivity manager to determine on which network we are connected
|
||||||
|
NetworkInfo netInfo = _cMgr.getActiveNetworkInfo();
|
||||||
|
if (netInfo == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
OCSMSSharedPrefs prefs = new OCSMSSharedPrefs(_context);
|
||||||
|
|
||||||
|
// Check
|
||||||
|
switch (netInfo.getType()) {
|
||||||
|
case ConnectivityManager.TYPE_WIFI:
|
||||||
|
return prefs.syncInWifi();
|
||||||
|
case ConnectivityManager.TYPE_MOBILE:
|
||||||
|
switch (netInfo.getSubtype()) {
|
||||||
|
case TelephonyManager.NETWORK_TYPE_EDGE:
|
||||||
|
case TelephonyManager.NETWORK_TYPE_CDMA:
|
||||||
|
case TelephonyManager.NETWORK_TYPE_1xRTT:
|
||||||
|
case TelephonyManager.NETWORK_TYPE_IDEN:
|
||||||
|
return prefs.syncIn2G();
|
||||||
|
case TelephonyManager.NETWORK_TYPE_GPRS:
|
||||||
|
return prefs.syncInGPRS();
|
||||||
|
case TelephonyManager.NETWORK_TYPE_HSDPA:
|
||||||
|
case TelephonyManager.NETWORK_TYPE_HSPA:
|
||||||
|
case TelephonyManager.NETWORK_TYPE_HSUPA:
|
||||||
|
case TelephonyManager.NETWORK_TYPE_UMTS:
|
||||||
|
case TelephonyManager.NETWORK_TYPE_EHRPD:
|
||||||
|
case TelephonyManager.NETWORK_TYPE_EVDO_B:
|
||||||
|
case TelephonyManager.NETWORK_TYPE_HSPAP:
|
||||||
|
return prefs.syncIn3G();
|
||||||
|
case TelephonyManager.NETWORK_TYPE_LTE:
|
||||||
|
return prefs.syncIn4G();
|
||||||
|
default:
|
||||||
|
return prefs.syncInOtherModes();
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return prefs.syncInOtherModes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConnectivityManager _cMgr;
|
||||||
|
private final Context _context;
|
||||||
|
}
|
@ -0,0 +1,114 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.engine;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2016, Loic Blot <loic.blot@unix-experience.fr>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Pair;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
|
import fr.unix_experience.owncloud_sms.enums.OCSyncErrorType;
|
||||||
|
import fr.unix_experience.owncloud_sms.exceptions.OCSyncException;
|
||||||
|
import fr.unix_experience.owncloud_sms.providers.AndroidVersionProvider;
|
||||||
|
import ncsmsgo.SmsBuffer;
|
||||||
|
import ncsmsgo.SmsHTTPClient;
|
||||||
|
import ncsmsgo.SmsIDListResponse;
|
||||||
|
import ncsmsgo.SmsMessagesResponse;
|
||||||
|
import ncsmsgo.SmsPhoneListResponse;
|
||||||
|
import ncsmsgo.SmsPushResponse;
|
||||||
|
|
||||||
|
public class OCHttpClient {
|
||||||
|
private SmsHTTPClient _smsHttpClient;
|
||||||
|
|
||||||
|
public OCHttpClient(Context context, URL serverURL, String accountName, String accountPassword) {
|
||||||
|
_smsHttpClient = new SmsHTTPClient();
|
||||||
|
// @TODO: at a point add a flag to permit insecure connections somewhere instead of trusting them
|
||||||
|
_smsHttpClient.init(serverURL.toString(), new AndroidVersionProvider(context).getVersionCode(),
|
||||||
|
accountName, accountPassword, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleEarlyHTTPStatus(int httpStatus) throws OCSyncException {
|
||||||
|
switch (httpStatus) {
|
||||||
|
case 403: {
|
||||||
|
// Authentication failed
|
||||||
|
throw new OCSyncException(R.string.err_sync_auth_failed, OCSyncErrorType.AUTH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastError() {
|
||||||
|
return _smsHttpClient.getLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
Pair<Integer, SmsIDListResponse> getAllSmsIds() throws OCSyncException {
|
||||||
|
SmsIDListResponse silr = _smsHttpClient.doGetSmsIDList();
|
||||||
|
int httpStatus = (int) _smsHttpClient.getLastHTTPStatus();
|
||||||
|
handleEarlyHTTPStatus(httpStatus);
|
||||||
|
return new Pair<>(httpStatus, silr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform the GoLang doVersionCall and handle return
|
||||||
|
public Pair<Integer, Integer> getVersion() throws OCSyncException {
|
||||||
|
Integer serverAPIVersion = (int) _smsHttpClient.doVersionCall();
|
||||||
|
int httpStatus = (int) _smsHttpClient.getLastHTTPStatus();
|
||||||
|
|
||||||
|
handleEarlyHTTPStatus(httpStatus);
|
||||||
|
|
||||||
|
// If last status is not 200, send the wrong status now
|
||||||
|
if (httpStatus != 200) {
|
||||||
|
return new Pair<>(httpStatus, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serverAPIVersion > 0) {
|
||||||
|
return new Pair<>(200, serverAPIVersion);
|
||||||
|
}
|
||||||
|
else if (serverAPIVersion == 0) {
|
||||||
|
// Return default version
|
||||||
|
return new Pair<>(200, 1);
|
||||||
|
}
|
||||||
|
else if (serverAPIVersion == -1) {
|
||||||
|
// This return code from API means I/O error
|
||||||
|
throw new OCSyncException(R.string.err_sync_http_request_ioexception, OCSyncErrorType.IO);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new OCSyncException(R.string.err_sync_http_request_returncode_unhandled, OCSyncErrorType.SERVER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Pair<Integer, SmsPushResponse> pushSms(SmsBuffer smsBuf) throws OCSyncException {
|
||||||
|
SmsPushResponse spr = _smsHttpClient.doPushCall(smsBuf);
|
||||||
|
int httpStatus = (int) _smsHttpClient.getLastHTTPStatus();
|
||||||
|
handleEarlyHTTPStatus(httpStatus);
|
||||||
|
return new Pair<>(httpStatus, spr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Pair<Integer, SmsPhoneListResponse> getPhoneList() throws OCSyncException {
|
||||||
|
SmsPhoneListResponse splr = _smsHttpClient.doGetPhoneList();
|
||||||
|
int httpStatus = (int) _smsHttpClient.getLastHTTPStatus();
|
||||||
|
handleEarlyHTTPStatus(httpStatus);
|
||||||
|
return new Pair<>(httpStatus, splr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Pair<Integer, SmsMessagesResponse> getMessages(Long start, Integer limit) throws OCSyncException {
|
||||||
|
SmsMessagesResponse smr = _smsHttpClient.doGetMessagesCall(start, limit);
|
||||||
|
int httpStatus = (int) _smsHttpClient.getLastHTTPStatus();
|
||||||
|
handleEarlyHTTPStatus(httpStatus);
|
||||||
|
return new Pair<>(httpStatus, smr);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,156 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.engine;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2016, Loic Blot <loic.blot@unix-experience.fr>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.accounts.Account;
|
||||||
|
import android.accounts.AccountManager;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.Pair;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
|
import fr.unix_experience.owncloud_sms.enums.OCSyncErrorType;
|
||||||
|
import fr.unix_experience.owncloud_sms.exceptions.OCSyncException;
|
||||||
|
import fr.unix_experience.owncloud_sms.prefs.OCSMSSharedPrefs;
|
||||||
|
import ncsmsgo.SmsBuffer;
|
||||||
|
import ncsmsgo.SmsIDListResponse;
|
||||||
|
import ncsmsgo.SmsMessagesResponse;
|
||||||
|
import ncsmsgo.SmsPhoneListResponse;
|
||||||
|
import ncsmsgo.SmsPushResponse;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public class OCSMSOwnCloudClient {
|
||||||
|
|
||||||
|
private static final Integer SERVER_RECOVERY_MSG_LIMIT = 500;
|
||||||
|
|
||||||
|
public OCSMSOwnCloudClient(Context context, Account account) {
|
||||||
|
_context = context;
|
||||||
|
_serverAPIVersion = 1;
|
||||||
|
|
||||||
|
AccountManager accountManager = AccountManager.get(context);
|
||||||
|
String ocURI = accountManager.getUserData(account, "ocURI");
|
||||||
|
if (ocURI == null) {
|
||||||
|
throw new IllegalStateException(context.getString(R.string.err_sync_account_unparsable));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
URL serverURL = new URL(ocURI);
|
||||||
|
_http = new OCHttpClient(context,
|
||||||
|
serverURL, accountManager.getUserData(account, "ocLogin"),
|
||||||
|
accountManager.getPassword(account));
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
throw new IllegalStateException(context.getString(R.string.err_sync_account_unparsable));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getServerAPIVersion() throws OCSyncException {
|
||||||
|
Pair<Integer, Integer> vPair = _http.getVersion();
|
||||||
|
_serverAPIVersion = vPair.second;
|
||||||
|
if (vPair.first == 200 && _serverAPIVersion > 0) {
|
||||||
|
return _serverAPIVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmsPhoneListResponse getServerPhoneNumbers() throws OCSyncException {
|
||||||
|
Pair<Integer, SmsPhoneListResponse> response = _http.getPhoneList();
|
||||||
|
if (response.second == null || response.first != 200) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doPushRequest(SmsBuffer smsBuffer) throws OCSyncException {
|
||||||
|
/*
|
||||||
|
* If we need other API push, set it here
|
||||||
|
*/
|
||||||
|
switch (_serverAPIVersion) {
|
||||||
|
case 1:
|
||||||
|
default: doPushRequestV1(smsBuffer); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doPushRequestV1(SmsBuffer smsBuffer) throws OCSyncException {
|
||||||
|
if (smsBuffer == null) {
|
||||||
|
Pair<Integer, SmsIDListResponse> response = _http.getAllSmsIds();
|
||||||
|
if (response.second == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new SmsBuffer to get results
|
||||||
|
smsBuffer = new SmsBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (smsBuffer.empty()) {
|
||||||
|
Log.i(OCSMSOwnCloudClient.TAG, "No new SMS to sync, sync done");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pair<Integer, SmsPushResponse> response = _http.pushSms(smsBuffer);
|
||||||
|
|
||||||
|
if (response.second == null) {
|
||||||
|
Log.e(OCSMSOwnCloudClient.TAG,"Push request failed. GoLang response is empty.");
|
||||||
|
throw new OCSyncException(R.string.err_sync_push_request, OCSyncErrorType.IO);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push was OK, we can save the lastMessageDate which was saved to server
|
||||||
|
(new OCSMSSharedPrefs(_context)).setLastMessageDate(smsBuffer.getLastMessageDate());
|
||||||
|
|
||||||
|
Log.i(OCSMSOwnCloudClient.TAG, "SMS Push request said: status " +
|
||||||
|
response.second.getStatus() + " - " + response.second.getMessage());
|
||||||
|
Log.i(OCSMSOwnCloudClient.TAG, "LastMessageDate set to: " + smsBuffer.getLastMessageDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
SmsMessagesResponse retrieveSomeMessages(Long start, Integer limit) {
|
||||||
|
// This is not allowed by server
|
||||||
|
if (limit > OCSMSOwnCloudClient.SERVER_RECOVERY_MSG_LIMIT) {
|
||||||
|
Log.e(OCSMSOwnCloudClient.TAG, "Message recovery limit exceeded");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pair<Integer, SmsMessagesResponse> response;
|
||||||
|
try {
|
||||||
|
response = _http.getMessages(start, limit);
|
||||||
|
} catch (OCSyncException e) {
|
||||||
|
Log.e(OCSMSOwnCloudClient.TAG, "Request failed.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.second == null) {
|
||||||
|
Log.e(OCSMSOwnCloudClient.TAG,
|
||||||
|
"Invalid response received from server, either messages or last_id field is missing.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final OCHttpClient _http;
|
||||||
|
private final Context _context;
|
||||||
|
|
||||||
|
private Integer _serverAPIVersion;
|
||||||
|
|
||||||
|
private static final String TAG = OCSMSOwnCloudClient.class.getSimpleName();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
package fr.unix_experience.owncloud_sms.enums;
|
package fr.unix_experience.owncloud_sms.engine;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
* Copyright (c) 2014-2016, Loic Blot <loic.blot@unix-experience.fr>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Affero General Public License as
|
* it under the terms of the GNU Affero General Public License as
|
||||||
@ -12,13 +12,18 @@ package fr.unix_experience.owncloud_sms.enums;
|
|||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Affero General Public License for more details.
|
* GNU Affero General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public enum OCSMSNotificationType {
|
public class SmsEntry {
|
||||||
SYNC,
|
public int id;
|
||||||
SYNC_FAILED,
|
public int mailboxId;
|
||||||
DEBUG,
|
public int type;
|
||||||
|
public boolean read;
|
||||||
|
public boolean seen;
|
||||||
|
public long date;
|
||||||
|
public String address;
|
||||||
|
public String body;
|
||||||
}
|
}
|
@ -30,6 +30,8 @@ public enum LoginReturnCode {
|
|||||||
INVALID_ADDR,
|
INVALID_ADDR,
|
||||||
HTTP_CONN_FAILED,
|
HTTP_CONN_FAILED,
|
||||||
CONN_FAILED,
|
CONN_FAILED,
|
||||||
|
CONN_FAILED_NOT_FOUND,
|
||||||
INVALID_LOGIN,
|
INVALID_LOGIN,
|
||||||
UNKNOWN_ERROR,
|
UNKNOWN_ERROR,
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.enums;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
||||||
|
* All rights reserved.
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public enum MailboxID {
|
||||||
|
INBOX(0),
|
||||||
|
SENT(1),
|
||||||
|
DRAFTS(2),
|
||||||
|
ALL(3);
|
||||||
|
|
||||||
|
MailboxID(int id) {
|
||||||
|
switch (id) {
|
||||||
|
case 0: uri = "content://sms/inbox"; break;
|
||||||
|
case 1: uri = "content://sms/sent"; break;
|
||||||
|
case 2: uri = "content://sms/drafts"; break;
|
||||||
|
case 3: uri = "content://sms"; break;
|
||||||
|
default: throw new AssertionError();
|
||||||
|
}
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MailboxID fromInt(int id) {
|
||||||
|
switch (id) {
|
||||||
|
case 0: return MailboxID.INBOX;
|
||||||
|
case 1: return MailboxID.SENT;
|
||||||
|
case 2: return MailboxID.DRAFTS;
|
||||||
|
case 3: return MailboxID.ALL;
|
||||||
|
default: throw new AssertionError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private final String uri;
|
||||||
|
private final int id;
|
||||||
|
public int getId() { return id; }
|
||||||
|
public String getURI() { return uri; }
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.enums;
|
||||||
|
|
||||||
|
import android.app.NotificationManager;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.support.annotation.StringRes;
|
||||||
|
|
||||||
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
|
|
||||||
|
public enum OCSMSNotificationChannel {
|
||||||
|
DEFAULT("OCSMS_DEFAULT", R.string.notification_channel_name_default, null),
|
||||||
|
SYNC("OCSMS_SYNC", R.string.notification_channel_name_sync, null);
|
||||||
|
|
||||||
|
static {
|
||||||
|
// well, that's a bit of a hack :/
|
||||||
|
// can be inlined in the future
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
DEFAULT.importance = NotificationManager.IMPORTANCE_DEFAULT;
|
||||||
|
SYNC.importance = NotificationManager.IMPORTANCE_LOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String channelId;
|
||||||
|
private final int nameResId;
|
||||||
|
private final Integer descResId;
|
||||||
|
private int importance;
|
||||||
|
|
||||||
|
OCSMSNotificationChannel(String channelId, @StringRes int nameResId, @StringRes Integer descResId) {
|
||||||
|
this.channelId = channelId;
|
||||||
|
this.nameResId = nameResId;
|
||||||
|
this.descResId = descResId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getChannelId() {
|
||||||
|
return channelId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNameResId() {
|
||||||
|
return nameResId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getDescResId() {
|
||||||
|
return descResId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getImportance() {
|
||||||
|
return importance;
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package fr.unix_experience.owncloud_sms.prefs;
|
package fr.unix_experience.owncloud_sms.enums;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
||||||
@ -12,33 +12,29 @@ package fr.unix_experience.owncloud_sms.prefs;
|
|||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Affero General Public License for more details.
|
* GNU Affero General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import fr.unix_experience.owncloud_sms.R;
|
public enum OCSMSNotificationType {
|
||||||
import android.content.Context;
|
SYNC(OCSMSNotificationChannel.SYNC, 0),
|
||||||
import android.content.SharedPreferences;
|
SYNC_FAILED(OCSMSNotificationChannel.DEFAULT, 1),
|
||||||
|
PERMISSION(OCSMSNotificationChannel.DEFAULT, 2);
|
||||||
|
|
||||||
public class OCSMSSharedPrefs {
|
private final OCSMSNotificationChannel channel;
|
||||||
|
private final int notificationId;
|
||||||
|
|
||||||
public OCSMSSharedPrefs(Context context) {
|
OCSMSNotificationType(OCSMSNotificationChannel channel, int notificationId) {
|
||||||
_context = context;
|
this.channel = channel;
|
||||||
|
this.notificationId = notificationId;
|
||||||
_sPrefs = _context.getSharedPreferences(_context.getString(R.string.shared_preference_file), Context.MODE_PRIVATE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLastMessageDate(Long msgDate) {
|
public OCSMSNotificationChannel getChannel() {
|
||||||
SharedPreferences.Editor editor = _sPrefs.edit();
|
return channel;
|
||||||
editor.putLong(_context.getString(R.string.pref_lastmsgdate), msgDate);
|
|
||||||
editor.commit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getLastMessageDate() {
|
public int getNotificationId() {
|
||||||
return _sPrefs.getLong(_context.getString(R.string.pref_lastmsgdate), 0);
|
return notificationId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SharedPreferences _sPrefs;
|
|
||||||
private Context _context;
|
|
||||||
}
|
}
|
@ -11,7 +11,7 @@ package fr.unix_experience.owncloud_sms.enums;
|
|||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
@ -25,9 +25,9 @@ package fr.unix_experience.owncloud_sms.enums;
|
|||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public enum MailboxID {
|
public enum PermissionID {
|
||||||
INBOX,
|
REQUEST_SMS,
|
||||||
SENT,
|
REQUEST_CONTACTS,
|
||||||
DRAFTS,
|
REQUEST_ACCOUNTS,
|
||||||
ALL,
|
REQUEST_MAX,
|
||||||
}
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.misc;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
|
||||||
|
public class ComposeSmsActivity extends Activity {
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.misc;
|
||||||
|
|
||||||
|
import android.app.Service;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
public class HeadlessSmsSendService extends Service {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.misc;
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
public class MmsReceiver extends BroadcastReceiver {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,133 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.notifications;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2017, Loic Blot <loic.blot@unix-experience.fr>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.app.Notification;
|
||||||
|
import android.app.NotificationChannel;
|
||||||
|
import android.app.NotificationManager;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.support.v4.app.NotificationCompat;
|
||||||
|
|
||||||
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
|
import fr.unix_experience.owncloud_sms.enums.OCSMSNotificationChannel;
|
||||||
|
import fr.unix_experience.owncloud_sms.enums.OCSMSNotificationType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class for showing and canceling ui
|
||||||
|
* notifications.
|
||||||
|
* <p/>
|
||||||
|
* This class makes heavy use of the {@link NotificationCompat.Builder} helper
|
||||||
|
* class to create notifications in a backward-compatible way.
|
||||||
|
*/
|
||||||
|
public class OCSMSNotificationUI {
|
||||||
|
/**
|
||||||
|
* The unique identifier for this type of notification.
|
||||||
|
*/
|
||||||
|
private static final String NOTIFICATION_TAG = "OCSMS_NOTIFICATION";
|
||||||
|
|
||||||
|
public static void notify(Context context, String titleString,
|
||||||
|
String contentString, OCSMSNotificationType type) {
|
||||||
|
notify(context, titleString, contentString,
|
||||||
|
type.getChannel().getChannelId(), type.getNotificationId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the notification, or updates a previously shown notification of
|
||||||
|
* this type, with the given parameters.
|
||||||
|
*
|
||||||
|
* @see #cancel(Context, OCSMSNotificationType)
|
||||||
|
*/
|
||||||
|
public static void notify(Context context, String titleString, String contentString,
|
||||||
|
String channelId, int notificationId) {
|
||||||
|
Resources res = context.getResources();
|
||||||
|
|
||||||
|
// This image is used as the notification's large icon (thumbnail).
|
||||||
|
// TODO: Remove this if your notification has no relevant thumbnail.
|
||||||
|
// Bitmap picture = BitmapFactory.decodeResource(res, R.mipmap.ic_launcher);
|
||||||
|
|
||||||
|
// String ticker = (titleString.length() > 20) ? titleString.substring(0, 20) : titleString;
|
||||||
|
String title = res.getString(R.string.ui_notification_title_template, titleString);
|
||||||
|
|
||||||
|
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId)
|
||||||
|
|
||||||
|
// Set appropriate defaults for the notification light, sound,
|
||||||
|
// and vibration.
|
||||||
|
.setSmallIcon(R.drawable.notification_icon)
|
||||||
|
.setContentTitle(title)
|
||||||
|
.setContentText(contentString)
|
||||||
|
|
||||||
|
// All fields below this line are optional.
|
||||||
|
|
||||||
|
// Use a default priority (recognized on devices running Android
|
||||||
|
// 4.1 or later)
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
||||||
|
|
||||||
|
// Set ticker text (preview) information for this notification.
|
||||||
|
//.setTicker(ticker)
|
||||||
|
|
||||||
|
.setStyle(new NotificationCompat.BigTextStyle()
|
||||||
|
.bigText(contentString)
|
||||||
|
.setBigContentTitle(title)
|
||||||
|
.setSummaryText(titleString))
|
||||||
|
.setAutoCancel(true)
|
||||||
|
.setColor(context.getResources().getColor(R.color.oc_primary));
|
||||||
|
|
||||||
|
notify(context, builder.build(), notificationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void notify(Context context, Notification notification, int notificationId) {
|
||||||
|
NotificationManager nm = (NotificationManager) context
|
||||||
|
.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
createNotificationChannels(context, nm);
|
||||||
|
nm.notify(OCSMSNotificationUI.NOTIFICATION_TAG, notificationId, notification);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels any notifications of this type previously shown using
|
||||||
|
* {@link #notify(Context, String, String, OCSMSNotificationType)}.
|
||||||
|
*/
|
||||||
|
public static void cancel(Context context, OCSMSNotificationType type) {
|
||||||
|
cancel(context, type.getNotificationId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void cancel(Context context, int notificationId) {
|
||||||
|
NotificationManager nm = (NotificationManager) context
|
||||||
|
.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
nm.cancel(OCSMSNotificationUI.NOTIFICATION_TAG, notificationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void createNotificationChannels(Context context, NotificationManager nm) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
for (OCSMSNotificationChannel ocsmsChannel : OCSMSNotificationChannel.values()) {
|
||||||
|
NotificationChannel channel = new NotificationChannel(
|
||||||
|
ocsmsChannel.getChannelId(),
|
||||||
|
context.getString(ocsmsChannel.getNameResId()),
|
||||||
|
ocsmsChannel.getImportance());
|
||||||
|
|
||||||
|
if (ocsmsChannel.getDescResId() != null) {
|
||||||
|
channel.setDescription(context.getString(ocsmsChannel.getDescResId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
nm.createNotificationChannel(channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -17,37 +17,55 @@ package fr.unix_experience.owncloud_sms.observers;
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import android.Manifest;
|
||||||
|
import android.accounts.Account;
|
||||||
import fr.unix_experience.owncloud_sms.engine.ASyncTask;
|
import android.accounts.AccountManager;
|
||||||
import fr.unix_experience.owncloud_sms.engine.OCSMSOwnCloudClient;
|
|
||||||
import fr.unix_experience.owncloud_sms.engine.SmsFetcher;
|
|
||||||
import fr.unix_experience.owncloud_sms.enums.MailboxID;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.ContentObserver;
|
import android.database.ContentObserver;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class SmsObserver extends ContentObserver implements ASyncTask {
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
|
import fr.unix_experience.owncloud_sms.engine.ASyncSMSSync;
|
||||||
|
import fr.unix_experience.owncloud_sms.engine.AndroidSmsFetcher;
|
||||||
|
import fr.unix_experience.owncloud_sms.engine.ConnectivityMonitor;
|
||||||
|
import fr.unix_experience.owncloud_sms.engine.OCSMSOwnCloudClient;
|
||||||
|
import fr.unix_experience.owncloud_sms.enums.MailboxID;
|
||||||
|
import fr.unix_experience.owncloud_sms.enums.PermissionID;
|
||||||
|
import fr.unix_experience.owncloud_sms.prefs.PermissionChecker;
|
||||||
|
import ncsmsgo.SmsBuffer;
|
||||||
|
|
||||||
public SmsObserver(Handler handler) {
|
public class SmsObserver extends ContentObserver implements ASyncSMSSync {
|
||||||
super(handler);
|
|
||||||
}
|
public SmsObserver(Handler handler, Context ct) {
|
||||||
|
|
||||||
public SmsObserver(Handler handler, Context ct) {
|
|
||||||
super(handler);
|
super(handler);
|
||||||
_context = ct;
|
_context = ct;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onChange(boolean selfChange) {
|
public void onChange(boolean selfChange) {
|
||||||
|
if (!PermissionChecker.checkPermission(_context, Manifest.permission.READ_SMS,
|
||||||
|
PermissionID.REQUEST_SMS)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
super.onChange(selfChange);
|
super.onChange(selfChange);
|
||||||
Log.d(TAG, "onChange SmsObserver");
|
Log.i(SmsObserver.TAG, "onChange SmsObserver");
|
||||||
|
|
||||||
|
// No account, abort
|
||||||
|
Account[] myAccountList = AccountManager.get(_context).
|
||||||
|
getAccountsByType(_context.getString(R.string.account_type));
|
||||||
|
if (myAccountList.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
SmsFetcher fetcher = new SmsFetcher(_context);
|
AndroidSmsFetcher fetcher = new AndroidSmsFetcher(_context);
|
||||||
JSONArray smsList = fetcher.getLastMessage(MailboxID.ALL);
|
SmsBuffer smsBuffer = fetcher.getLastMessage(MailboxID.ALL);
|
||||||
|
|
||||||
if (smsList != null) {
|
ConnectivityMonitor cMon = new ConnectivityMonitor(_context);
|
||||||
new SyncTask(_context, smsList).execute();
|
|
||||||
|
// Synchronize if network is valid and there are SMS
|
||||||
|
if (cMon.isValid() && (smsBuffer != null)) {
|
||||||
|
new SyncTask(_context, smsBuffer).execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,79 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.prefs;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
|
||||||
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
|
import fr.unix_experience.owncloud_sms.defines.DefaultPrefs;
|
||||||
|
|
||||||
|
public class OCSMSSharedPrefs extends SharedPrefs {
|
||||||
|
|
||||||
|
public OCSMSSharedPrefs(Context context) {
|
||||||
|
super(context, R.string.shared_preference_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastMessageDate(Long msgDate) {
|
||||||
|
SharedPreferences.Editor editor = _sPrefs.edit();
|
||||||
|
editor.putLong(_context.getString(R.string.pref_lastmsgdate), msgDate);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getLastMessageDate() {
|
||||||
|
return _sPrefs.getLong(_context.getString(R.string.pref_lastmsgdate), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean pushOnReceive() {
|
||||||
|
return _sPrefs.getBoolean("push_on_receive", DefaultPrefs.pushOnReceive);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean showSyncNotifications() {
|
||||||
|
return _sPrefs.getBoolean("show_sync_notifications", DefaultPrefs.showSyncNotifications);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean syncInWifi() {
|
||||||
|
return _sPrefs.getBoolean("sync_wifi", DefaultPrefs.syncWifi);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean syncIn2G() {
|
||||||
|
return _sPrefs.getBoolean("sync_2g", DefaultPrefs.sync2G);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean syncInGPRS() {
|
||||||
|
return _sPrefs.getBoolean("sync_gprs", DefaultPrefs.syncGPRS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean syncIn3G() {
|
||||||
|
return _sPrefs.getBoolean("sync_3g", DefaultPrefs.sync3G);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean syncIn4G() {
|
||||||
|
return _sPrefs.getBoolean("sync_4g", DefaultPrefs.sync4G);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean syncInOtherModes() {
|
||||||
|
return _sPrefs.getBoolean("sync_others", DefaultPrefs.syncOthers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getSyncBulkLimit() {
|
||||||
|
return _sPrefs.getInt("sync_bulk_messages", -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getMinPhoneNumberCharsToSync() { return _sPrefs.getInt("minimum_sync_chars", DefaultPrefs.minimumCharsForSync); }
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.prefs;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
||||||
|
* All rights reserved.
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.support.v4.app.ActivityCompat;
|
||||||
|
import android.support.v4.content.ContextCompat;
|
||||||
|
|
||||||
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
|
import fr.unix_experience.owncloud_sms.enums.OCSMSNotificationType;
|
||||||
|
import fr.unix_experience.owncloud_sms.enums.PermissionID;
|
||||||
|
import fr.unix_experience.owncloud_sms.notifications.OCSMSNotificationUI;
|
||||||
|
|
||||||
|
public class PermissionChecker {
|
||||||
|
public static boolean checkPermission(Context context, final String permissionName,
|
||||||
|
final PermissionID permissionId) {
|
||||||
|
int hasWriteContactsPermission = ContextCompat.checkSelfPermission(context, permissionName);
|
||||||
|
if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
// Check if we only have a context or a full activity
|
||||||
|
final Activity activity = (context instanceof Activity) ? ((Activity) context) : null;
|
||||||
|
if (activity != null) {
|
||||||
|
// For activity notify directly the user
|
||||||
|
if (!ActivityCompat.shouldShowRequestPermissionRationale(activity, permissionName)) {
|
||||||
|
PermissionChecker.showMessageOKCancel(activity, "You need to fix application permissions.",
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
ActivityCompat.requestPermissions(activity,
|
||||||
|
new String[]{ permissionName }, permissionId.ordinal());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ActivityCompat.requestPermissions(activity, new String[]{permissionName},
|
||||||
|
permissionId.ordinal());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For context only show a notification
|
||||||
|
OCSMSNotificationUI.notify(context, context.getString(R.string.notif_permission_required),
|
||||||
|
context.getString(R.string.notif_permission_required_content),
|
||||||
|
OCSMSNotificationType.PERMISSION);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void showMessageOKCancel(Activity activity, String message,
|
||||||
|
DialogInterface.OnClickListener okListener) {
|
||||||
|
new AlertDialog.Builder(activity)
|
||||||
|
.setMessage(message)
|
||||||
|
.setPositiveButton(R.string.understood, okListener)
|
||||||
|
.setNegativeButton(R.string.cancel, null)
|
||||||
|
.create()
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.prefs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2013-2015, Loic Blot <loic.blot@unix-experience.fr>
|
||||||
|
* All rights reserved.
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are those
|
||||||
|
* of the authors and should not be interpreted as representing official policies,
|
||||||
|
* either expressed or implied, of the FreeBSD Project.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.SharedPreferences.Editor;
|
||||||
|
|
||||||
|
public class SharedPrefs {
|
||||||
|
|
||||||
|
protected final SharedPreferences _sPrefs;
|
||||||
|
protected final Context _context;
|
||||||
|
|
||||||
|
public SharedPrefs(Context context, int prefFile) {
|
||||||
|
_context = context;
|
||||||
|
|
||||||
|
_sPrefs = _context.getSharedPreferences(_context.getString(prefFile), Context.MODE_PRIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putBoolean(String prefKey, Boolean boolValue) {
|
||||||
|
Editor edit = _sPrefs.edit();
|
||||||
|
edit.putBoolean(prefKey, boolValue);
|
||||||
|
edit.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putInteger(String prefKey, Integer intValue) {
|
||||||
|
Editor edit = _sPrefs.edit();
|
||||||
|
edit.putInt(prefKey, intValue);
|
||||||
|
edit.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putLong(String prefKey, long longValue) {
|
||||||
|
Editor edit = _sPrefs.edit();
|
||||||
|
edit.putLong(prefKey, longValue);
|
||||||
|
edit.apply();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.providers;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2017, Loic Blot <loic.blot@unix-experience.fr>
|
||||||
|
* All rights reserved.
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class AndroidVersionProvider {
|
||||||
|
private Context _context;
|
||||||
|
|
||||||
|
public AndroidVersionProvider(Context context) {
|
||||||
|
assert (context != null);
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVersionCode() {
|
||||||
|
try {
|
||||||
|
return _context.getPackageManager().
|
||||||
|
getPackageInfo(_context.getPackageName(), 0).versionName;
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
return "unknown version";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,165 @@
|
|||||||
|
package fr.unix_experience.owncloud_sms.providers;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014-2015, Loic Blot <loic.blot@unix-experience.fr>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.content.ContentProvider;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import fr.unix_experience.owncloud_sms.enums.MailboxID;
|
||||||
|
import fr.unix_experience.owncloud_sms.prefs.OCSMSSharedPrefs;
|
||||||
|
|
||||||
|
public class SmsDataProvider extends ContentProvider {
|
||||||
|
static String[] messageFields = {
|
||||||
|
"read",
|
||||||
|
"date",
|
||||||
|
"address",
|
||||||
|
"seen",
|
||||||
|
"body",
|
||||||
|
"_id",
|
||||||
|
"type",
|
||||||
|
//"length(address)" // For debug purposes
|
||||||
|
};
|
||||||
|
|
||||||
|
// WARNING: mandatory
|
||||||
|
public SmsDataProvider() {}
|
||||||
|
public SmsDataProvider (Context ct) {
|
||||||
|
super();
|
||||||
|
_context = ct;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreate() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cursor query(String mailBox) {
|
||||||
|
return query(Uri.parse(mailBox),
|
||||||
|
SmsDataProvider.messageFields,
|
||||||
|
null, null, null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: in APIv2 this call should be modified to use date instead of _id which is likely unique
|
||||||
|
public Cursor queryNonExistingMessages(String mailBox, String existingIds) {
|
||||||
|
Log.i(SmsDataProvider.TAG, "queryNonExistingMessages !");
|
||||||
|
if (!existingIds.isEmpty()) {
|
||||||
|
return query(Uri.parse(mailBox), SmsDataProvider.messageFields,
|
||||||
|
"_id NOT IN (" + existingIds + ")", null, null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return query(mailBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cursor queryMessagesSinceDate(String mailBox, Long sinceDate) {
|
||||||
|
return query(Uri.parse(mailBox), SmsDataProvider.messageFields,
|
||||||
|
"date > ?", new String[] { sinceDate.toString() }, "date ASC"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean messageExists(String address, String body, String date, MailboxID mb) {
|
||||||
|
Cursor c = query(Uri.parse(mb.getURI()), new String[] { "_id" },
|
||||||
|
"address = ? AND body = ? AND date = ?",
|
||||||
|
new String[] { address, body, date }, null);
|
||||||
|
if (c == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean exists = c.getCount() > 0;
|
||||||
|
c.close();
|
||||||
|
return exists;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cursor query(@NonNull Uri uri, String[] projection, String selection,
|
||||||
|
String[] selectionArgs, String sortOrder) {
|
||||||
|
if ((_context == null) || (_context.getContentResolver() == null)) {
|
||||||
|
Log.e(SmsDataProvider.TAG, "query: context is null or content resolver is null, abort.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
OCSMSSharedPrefs prefs = new OCSMSSharedPrefs(_context);
|
||||||
|
Integer bulkLimit = prefs.getSyncBulkLimit();
|
||||||
|
Integer senderMinSize = prefs.getMinPhoneNumberCharsToSync();
|
||||||
|
if (senderMinSize < 0) {
|
||||||
|
senderMinSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If minSize > 0 we should filter
|
||||||
|
if (senderMinSize > 0) {
|
||||||
|
selection = ((selection == null) || (selection.isEmpty())) ?
|
||||||
|
("length(address) >= " + senderMinSize.toString()) :
|
||||||
|
("length(address) >= " + senderMinSize.toString() + " AND " + selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bulkLimit > 0) {
|
||||||
|
if (sortOrder == null)
|
||||||
|
sortOrder = "date DESC";
|
||||||
|
sortOrder += " LIMIT " + bulkLimit.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor cursor = _context.getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
|
||||||
|
if (cursor == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursor.getCount() == 0) {
|
||||||
|
cursor.close();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cursor.moveToFirst()) {
|
||||||
|
cursor.close();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType(@NonNull Uri uri) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Uri insert(@NonNull Uri uri, ContentValues values) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int update(@NonNull Uri uri, ContentValues values, String selection,
|
||||||
|
String[] selectionArgs) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Context _context;
|
||||||
|
private static final String TAG = SmsDataProvider.class.getSimpleName();
|
||||||
|
}
|
@ -12,63 +12,57 @@ package fr.unix_experience.owncloud_sms.sync_adapters;
|
|||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Affero General Public License for more details.
|
* GNU Affero General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import fr.unix_experience.owncloud_sms.R;
|
|
||||||
import fr.unix_experience.owncloud_sms.engine.OCSMSOwnCloudClient;
|
|
||||||
import fr.unix_experience.owncloud_sms.enums.OCSyncErrorType;
|
|
||||||
import fr.unix_experience.owncloud_sms.exceptions.OCSyncException;
|
|
||||||
import fr.unix_experience.owncloud_sms.notifications.OCSMSNotificationManager;
|
|
||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
import android.accounts.AccountManager;
|
|
||||||
import android.content.AbstractThreadedSyncAdapter;
|
import android.content.AbstractThreadedSyncAdapter;
|
||||||
import android.content.ContentProviderClient;
|
import android.content.ContentProviderClient;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SyncResult;
|
import android.content.SyncResult;
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class SmsSyncAdapter extends AbstractThreadedSyncAdapter {
|
import fr.unix_experience.owncloud_sms.R;
|
||||||
|
import fr.unix_experience.owncloud_sms.engine.OCSMSOwnCloudClient;
|
||||||
|
import fr.unix_experience.owncloud_sms.enums.OCSMSNotificationType;
|
||||||
|
import fr.unix_experience.owncloud_sms.enums.OCSyncErrorType;
|
||||||
|
import fr.unix_experience.owncloud_sms.exceptions.OCSyncException;
|
||||||
|
import fr.unix_experience.owncloud_sms.notifications.OCSMSNotificationUI;
|
||||||
|
import fr.unix_experience.owncloud_sms.prefs.OCSMSSharedPrefs;
|
||||||
|
|
||||||
public SmsSyncAdapter(Context context, boolean autoInitialize) {
|
class SmsSyncAdapter extends AbstractThreadedSyncAdapter {
|
||||||
|
|
||||||
|
SmsSyncAdapter(Context context, boolean autoInitialize) {
|
||||||
super(context, autoInitialize);
|
super(context, autoInitialize);
|
||||||
_accountMgr = AccountManager.get(context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPerformSync(Account account, Bundle extras, String authority,
|
public void onPerformSync(Account account, Bundle extras, String authority,
|
||||||
ContentProviderClient provider, SyncResult syncResult) {
|
ContentProviderClient provider, SyncResult syncResult) {
|
||||||
|
|
||||||
OCSMSNotificationManager nMgr = new OCSMSNotificationManager(getContext());
|
if (new OCSMSSharedPrefs(getContext()).showSyncNotifications()) {
|
||||||
|
OCSMSNotificationUI.notify(getContext(), getContext().getString(R.string.sync_title),
|
||||||
// Create client
|
getContext().getString(R.string.sync_inprogress), OCSMSNotificationType.SYNC);
|
||||||
String ocURI = _accountMgr.getUserData(account, "ocURI");
|
|
||||||
if (ocURI == null) {
|
|
||||||
nMgr.setSyncErrorMsg(getContext().getString(R.string.err_sync_account_unparsable));
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Uri serverURI = Uri.parse(ocURI);
|
|
||||||
nMgr.setSyncProcessMsg();
|
|
||||||
|
|
||||||
OCSMSOwnCloudClient _client = new OCSMSOwnCloudClient(getContext(),
|
|
||||||
serverURI, _accountMgr.getUserData(account, "ocLogin"),
|
|
||||||
_accountMgr.getPassword(account));
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
OCSMSOwnCloudClient _client = new OCSMSOwnCloudClient(getContext(), account);
|
||||||
|
|
||||||
// getServerAPI version
|
// getServerAPI version
|
||||||
Log.d(TAG,"Server API version: " + _client.getServerAPIVersion());
|
Log.i(SmsSyncAdapter.TAG, "Server API version: " + _client.getServerAPIVersion());
|
||||||
|
|
||||||
// and push datas
|
// and push datas
|
||||||
_client.doPushRequest(null);
|
_client.doPushRequest(null);
|
||||||
|
OCSMSNotificationUI.cancel(getContext(), OCSMSNotificationType.SYNC_FAILED);
|
||||||
nMgr.dropSyncErrorMsg();
|
} catch (IllegalStateException e) {
|
||||||
|
OCSMSNotificationUI.notify(getContext(), getContext().getString(R.string.fatal_error),
|
||||||
|
e.getMessage(), OCSMSNotificationType.SYNC_FAILED);
|
||||||
} catch (OCSyncException e) {
|
} catch (OCSyncException e) {
|
||||||
nMgr.setSyncErrorMsg(getContext().getString(e.getErrorId()));
|
OCSMSNotificationUI.notify(getContext(), getContext().getString(R.string.fatal_error),
|
||||||
|
getContext().getString(e.getErrorId()), OCSMSNotificationType.SYNC_FAILED);
|
||||||
if (e.getErrorType() == OCSyncErrorType.IO) {
|
if (e.getErrorType() == OCSyncErrorType.IO) {
|
||||||
syncResult.stats.numIoExceptions++;
|
syncResult.stats.numIoExceptions++;
|
||||||
}
|
}
|
||||||
@ -79,15 +73,12 @@ public class SmsSyncAdapter extends AbstractThreadedSyncAdapter {
|
|||||||
syncResult.stats.numAuthExceptions++;
|
syncResult.stats.numAuthExceptions++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// UNHANDLED
|
Log.w(SmsSyncAdapter.TAG, "onPerformSync: unhandled response");
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
OCSMSNotificationUI.cancel(getContext(), OCSMSNotificationType.SYNC);
|
||||||
}
|
}
|
||||||
|
|
||||||
nMgr.dropSyncProcessMsg();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private AccountManager _accountMgr;
|
|
||||||
|
|
||||||
private static final String TAG = SmsSyncAdapter.class.getSimpleName();
|
private static final String TAG = SmsSyncAdapter.class.getSimpleName();
|
||||||
}
|
}
|