Compare commits
No commits in common. "master" and "0.23.0" have entirely different histories.
3
.gitignore
vendored
@ -4,6 +4,3 @@ ownCloudSMS.iml
|
||||
ownCloudSMS-release.apk
|
||||
lint.xml
|
||||
.gradle/
|
||||
.idea/
|
||||
local.properties
|
||||
ownCloud-SMS-App.iml
|
231
.idea/codeStyleSettings.xml
generated
@ -1,231 +0,0 @@
|
||||
<?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
@ -1,28 +0,0 @@
|
||||
---
|
||||
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
@ -1,17 +0,0 @@
|
||||
[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,20 +0,0 @@
|
||||
# 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.
|
68
README.md
@ -1,45 +1,59 @@
|
||||
# Nextcloud SMS (Android)
|
||||
# ownCloud SMS Android Application Offical Repository
|
||||
|
||||
[](https://codebeat.co/projects/github-com-nerzhul-owncloud-sms-app-master)
|
||||
## Introduction
|
||||
|
||||
Nextcloud SMS app pushes your Android devices conversation into your Nextcloud instance, using [ocsms app](https://github.com/nerzhul/ocsms).
|
||||
ownCloud SMS app push your Android devices conversation into your ownCloud instance, using ocsms app.
|
||||
|
||||
## :arrow_forward: Access
|
||||
<a href="https://play.google.com/store/apps/details?id=fr.unix_experience.owncloud_sms">
|
||||
<img src="http://www.android.com/images/brand/android_app_on_play_large.png" alt="Download from Google Play" />
|
||||
</a>
|
||||
<a href="https://f-droid.org/repository/browse/?fdid=fr.unix_experience.owncloud_sms">
|
||||
<img src="https://camo.githubusercontent.com/7df0eafa4433fa4919a56f87c3d99cf81b68d01c/68747470733a2f2f662d64726f69642e6f72672f77696b692f696d616765732f632f63342f462d44726f69642d627574746f6e5f617661696c61626c652d6f6e2e706e67" alt="ownCloud Notes App on fdroid.org" />
|
||||
</a>
|
||||
|
||||
[](https://f-droid.org/repository/browse/?fdid=fr.unix_experience.owncloud_sms)
|
||||
ocsms app sources are available here: https://github.com/nerzhul/ocsms/
|
||||
|
||||
ocsms app sources are available here: https://github.com/nextcloud/ocsms
|
||||
## Application documentation
|
||||
|
||||
## :notebook: Application documentation
|
||||
You can found application documentation here: https://github.com/nerzhul/ownCloud-SMS-App/wiki
|
||||
|
||||
You can find the application documentation here: https://github.com/nerzhul/ncsms-android/wiki
|
||||
## Licence
|
||||
|
||||
## :link: Requirements
|
||||
- [Nextcloud](https://nextcloud.com/) instance running
|
||||
- [ocsms](https://github.com/nextcloud/ocsms) app enabled
|
||||
ownCloud SMS Android Application licence is in reflexion, then sources are partial.
|
||||
|
||||
## :exclamation: Reporting issues
|
||||
- App locales and layouts are under BSD 2 clause licence
|
||||
- App DataProviders are under AGPLv3
|
||||
|
||||
- **Client:** https://github.com/nerzhul/ncsms-android/issues
|
||||
- **Server:** https://github.com/nextcloud/ocsms/issues
|
||||
## Contributions
|
||||
|
||||
## :rocket: Contributions
|
||||
We are searching for translations in others langs
|
||||
|
||||
- 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
|
||||
To contribute please download `res/values/strings.xml` and `res/values/google_playstore_strings.xml` and give us a translated version!
|
||||
|
||||
### Build requirements
|
||||
- gradle
|
||||
You can also contribute by adding patches in Java code or cleanups.
|
||||
|
||||
## Requirements
|
||||
- An ownCloud instance with ocsms app
|
||||
|
||||
## Build requirements
|
||||
- nrz-androidlib (last version)
|
||||
- ownCloud-Android-Library v1.0
|
||||
|
||||
## Reporting issues
|
||||
|
||||
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
|
||||
|
||||
## Developers
|
||||
|
||||
You can find our continuous integration here: http://jenkins.unix-experience.fr/job/ownCloud%20SMS%20%28Android%29/
|
||||
|
||||
### 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
|
||||
|
43
build.gradle
@ -1,26 +1,18 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.2.1'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
google()
|
||||
classpath 'com.android.tools.build:gradle:2.2.2'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
buildToolsVersion "28.0.3"
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion "25.0.0"
|
||||
useLibrary 'org.apache.http.legacy'
|
||||
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
@ -28,17 +20,9 @@ android {
|
||||
|
||||
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'
|
||||
}
|
||||
targetSdkVersion 25
|
||||
maxSdkVersion 25
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
@ -57,15 +41,14 @@ repositories {
|
||||
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')
|
||||
compile project(':owncloudAndroidLibrary')
|
||||
compile 'com.android.support:support-v13:25.0.1'
|
||||
compile 'com.android.support:appcompat-v7:25.0.1'
|
||||
compile 'com.android.support:design:25.0.1'
|
||||
compile 'in.srain.cube:ultra-ptr:1.0.11'
|
||||
compile 'com.github.dmytrodanylyk.android-process-button:library:1.0.4'
|
||||
compile 'com.android.support:support-v4:25.0.1'
|
||||
}
|
||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
6
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +0,0 @@
|
||||
#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
@ -1,164 +0,0 @@
|
||||
#!/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
@ -1,90 +0,0 @@
|
||||
@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
|
@ -48,9 +48,9 @@
|
||||
y="32"
|
||||
x="32"
|
||||
id="rect4"
|
||||
style="fill:#0082C9" /><path
|
||||
style="fill:#1d2d44" /><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>
|
||||
sodipodi:nodetypes="sssscccssssssssssssssssssssssssssssssss" /></svg>
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
@ -17,11 +17,11 @@ Tell us what happens instead
|
||||
|
||||
### Server configuration
|
||||
|
||||
**Nextcloud version:**
|
||||
**ownCloud version:**
|
||||
|
||||
**PHP version:**
|
||||
|
||||
**Webserver:**
|
||||
**HTTPd server:**
|
||||
|
||||
**HTTPS:**
|
||||
|
||||
@ -31,15 +31,10 @@ Tell us what happens instead
|
||||
|
||||
**Phone:**
|
||||
|
||||
**Nextcloud SMS app version:**
|
||||
**ownCloud SMS app version:**
|
||||
|
||||
### Logs
|
||||
|
||||
```
|
||||
Insert your log here
|
||||
```
|
||||
|
||||
## Screenshots
|
||||
<!--
|
||||
Upload your screenshots here if any
|
||||
-->
|
||||
|
@ -1,2 +0,0 @@
|
||||
configurations.maybeCreate("default")
|
||||
artifacts.add("default", file('ncsmsgo.aar'))
|
@ -1,25 +0,0 @@
|
||||
<?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>
|
@ -1,51 +0,0 @@
|
||||
<?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>
|
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 45 KiB |
@ -1 +0,0 @@
|
||||
include ':ncsmsgo'
|
@ -1,43 +1,43 @@
|
||||
<?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" />
|
||||
<manifest package="fr.unix_experience.owncloud_sms"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:versionCode="42"
|
||||
android:versionName="0.23.0"> <!-- From Android 4.1 to 7.0 -->
|
||||
<uses-sdk android:maxSdkVersion="25"/>
|
||||
|
||||
<uses-permission android:name="android.permission.READ_SMS" />
|
||||
<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" />
|
||||
<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" />
|
||||
<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" />
|
||||
<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" />
|
||||
<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" />
|
||||
<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:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:theme="@style/OcSmsTheme">
|
||||
|
||||
<!-- Related to periodic sync -->
|
||||
@ -46,59 +46,55 @@
|
||||
android:exported="true"
|
||||
android:process=":sync">
|
||||
<intent-filter>
|
||||
<action android:name="android.content.SyncAdapter" />
|
||||
<action android:name="android.content.SyncAdapter"/>
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.content.SyncAdapter"
|
||||
android:resource="@xml/sync_adapter" />
|
||||
android:resource="@xml/sync_adapter"/>
|
||||
</service>
|
||||
|
||||
<provider
|
||||
android:name=".providers.SmsDataProvider"
|
||||
android:authorities="@string/account_authority"
|
||||
android:label="@string/pref_title_sync"></provider>
|
||||
android:label="@string/pref_title_sync">
|
||||
</provider>
|
||||
|
||||
<!-- Related to Login -->
|
||||
<service android:name=".authenticators.OwnCloudAuthenticatorService">
|
||||
<intent-filter>
|
||||
<action android:name="android.accounts.AccountAuthenticator" />
|
||||
<action android:name="android.accounts.AccountAuthenticator"/>
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.accounts.AccountAuthenticator"
|
||||
android:resource="@xml/owncloud_account_authenticator" />
|
||||
android:resource="@xml/owncloud_account_authenticator"/>
|
||||
</service>
|
||||
|
||||
<receiver
|
||||
android:name=".broadcast_receivers.IncomingSms"
|
||||
android:permission="android.permission.BROADCAST_SMS">
|
||||
<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_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">
|
||||
<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">
|
||||
<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" />
|
||||
@ -107,15 +103,12 @@
|
||||
</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">
|
||||
<service android:name=".misc.HeadlessSmsSendService"
|
||||
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"
|
||||
android:exported="true" >
|
||||
<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" />
|
||||
@ -125,43 +118,43 @@
|
||||
|
||||
<receiver android:name=".broadcast_receivers.ConnectivityChanged">
|
||||
<intent-filter>
|
||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
|
||||
<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>
|
||||
android:label="@string/title_activity_login">
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activities.remote_account.AccountListActivity"
|
||||
android:label="@string/title_activity_select_account"></activity>
|
||||
android:label="@string/title_activity_select_account">
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activities.OCSMSSettingsActivity"
|
||||
android:label="@string/title_activity_general_settings"></activity>
|
||||
android:label="@string/title_activity_general_settings">
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activities.MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/OcSmsTheme.Drawer">
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<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>
|
||||
android:label="@string/title_activity_select_contact">
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activities.remote_account.AccountActionsActivity"
|
||||
android:label="@string/account_actions"></activity>
|
||||
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>
|
||||
android:label="@string/restore_all_messages">
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
Before Width: | Height: | Size: 37 KiB |
@ -208,7 +208,7 @@ public class AppCompatListActivity extends AppCompatActivity {
|
||||
super.onContentChanged();
|
||||
|
||||
View emptyView = findViewById(R.id.empty);
|
||||
mList = findViewById(R.id.list);
|
||||
mList = (ListView)findViewById(R.id.list);
|
||||
if (mList == null) {
|
||||
throw new RuntimeException(
|
||||
"Your content must have a ListView whose id attribute is " +
|
||||
|
@ -24,17 +24,15 @@ import android.animation.AnimatorListenerAdapter;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
@ -43,23 +41,20 @@ import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.dd.processbutton.iml.ActionProcessButton;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
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.authenticators.OwnCloudAuthenticator;
|
||||
import fr.unix_experience.owncloud_sms.defines.DefaultPrefs;
|
||||
import fr.unix_experience.owncloud_sms.engine.OCHttpClient;
|
||||
import fr.unix_experience.owncloud_sms.exceptions.OCSyncException;
|
||||
import fr.unix_experience.owncloud_sms.enums.LoginReturnCode;
|
||||
|
||||
/**
|
||||
* A login screen that offers login via email/password.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
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.
|
||||
*/
|
||||
@ -70,7 +65,7 @@ public class LoginActivity extends AppCompatActivity {
|
||||
private EditText _loginView;
|
||||
private EditText _passwordView;
|
||||
private EditText _serverView;
|
||||
private ActionProcessButton _signInButton;
|
||||
private ActionProcessButton _signInButton;
|
||||
private View mProgressView;
|
||||
private View mLoginFormView;
|
||||
|
||||
@ -79,20 +74,17 @@ public class LoginActivity extends AppCompatActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_login);
|
||||
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
// Set up the login form.
|
||||
_protocolView = findViewById(R.id.oc_protocol);
|
||||
_serverView = findViewById(R.id.oc_server);
|
||||
_loginView = findViewById(R.id.oc_login);
|
||||
_protocolView = (Spinner) findViewById(R.id.oc_protocol);
|
||||
_serverView = (EditText) findViewById(R.id.oc_server);
|
||||
_loginView = (EditText) findViewById(R.id.oc_login);
|
||||
|
||||
_passwordView = findViewById(R.id.oc_password);
|
||||
_passwordView = (EditText) findViewById(R.id.oc_password);
|
||||
_passwordView
|
||||
.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||
@Override
|
||||
public boolean onEditorAction(TextView textView, int id,
|
||||
KeyEvent keyEvent) {
|
||||
KeyEvent keyEvent) {
|
||||
if ((id == R.id.oc_login) || (id == EditorInfo.IME_NULL)) {
|
||||
attemptLogin();
|
||||
return true;
|
||||
@ -101,7 +93,7 @@ public class LoginActivity extends AppCompatActivity {
|
||||
}
|
||||
});
|
||||
|
||||
_signInButton = findViewById(R.id.oc_signin_button);
|
||||
_signInButton = (ActionProcessButton) findViewById(R.id.oc_signin_button);
|
||||
_signInButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
@ -113,19 +105,6 @@ public class LoginActivity extends AppCompatActivity {
|
||||
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.
|
||||
* If there are form errors (invalid email, missing fields, etc.), the
|
||||
@ -148,12 +127,12 @@ public class LoginActivity extends AppCompatActivity {
|
||||
|
||||
boolean cancel = false;
|
||||
View focusView = null;
|
||||
|
||||
|
||||
// Check for a valid server address.
|
||||
if (TextUtils.isEmpty(protocol)) {
|
||||
cancel = true;
|
||||
}
|
||||
|
||||
|
||||
// Check for a valid server address.
|
||||
if (TextUtils.isEmpty(serverAddr)) {
|
||||
_serverView.setError(getString(R.string.error_field_required));
|
||||
@ -167,14 +146,14 @@ public class LoginActivity extends AppCompatActivity {
|
||||
focusView = _loginView;
|
||||
cancel = true;
|
||||
}
|
||||
|
||||
|
||||
// Check for a valid password
|
||||
if (TextUtils.isEmpty(password)) {
|
||||
_passwordView.setError(getString(R.string.error_field_required));
|
||||
focusView = _passwordView;
|
||||
cancel = true;
|
||||
}
|
||||
|
||||
|
||||
if (!isPasswordValid(password)) {
|
||||
_passwordView.setError(getString(R.string.error_invalid_password));
|
||||
focusView = _passwordView;
|
||||
@ -184,23 +163,19 @@ public class LoginActivity extends AppCompatActivity {
|
||||
if (cancel) {
|
||||
// There was an error; don't attempt login and focus the first
|
||||
// form field with an error.
|
||||
// reset the button progress
|
||||
_signInButton.setProgress(0);
|
||||
if (focusView != null) {
|
||||
focusView.requestFocus();
|
||||
}
|
||||
} else {
|
||||
// reset the button progress
|
||||
_signInButton.setProgress(0);
|
||||
if (focusView != null) {
|
||||
focusView.requestFocus();
|
||||
}
|
||||
} else {
|
||||
// Show a progress spinner, and kick off a background task to
|
||||
// perform the user login attempt.
|
||||
_signInButton.setProgress(25);
|
||||
_signInButton.setProgress(25);
|
||||
showProgress(true);
|
||||
String serverURL = protocol + serverAddr;
|
||||
try {
|
||||
mAuthTask = new UserLoginTask(serverURL, login, password);
|
||||
mAuthTask.execute((Void) null);
|
||||
} catch (MalformedURLException e) {
|
||||
Log.e(TAG, "Invalid server URL " + serverURL);
|
||||
}
|
||||
mAuthTask = new UserLoginTask(serverURL, login, password);
|
||||
mAuthTask.execute((Void) null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -254,118 +229,114 @@ public class LoginActivity extends AppCompatActivity {
|
||||
* Represents an asynchronous login/registration task used to authenticate
|
||||
* the user.
|
||||
*/
|
||||
public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {
|
||||
public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {
|
||||
|
||||
UserLoginTask(String serverURL, String login, String password) throws MalformedURLException {
|
||||
_serverURL = new URL(serverURL);
|
||||
Log.i(TAG, "_serverURL = " + serverURL);
|
||||
UserLoginTask(String serverURI, String login, String password) {
|
||||
Log.i(TAG, "_serverURI = " + serverURI);
|
||||
_serverURI = Uri.parse(serverURI);
|
||||
_login = login;
|
||||
_password = password;
|
||||
_last_http_error = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... params) {
|
||||
_returnCode = 0;
|
||||
OCHttpClient http = new OCHttpClient(getBaseContext(), _serverURL, _login, _password);
|
||||
try {
|
||||
Pair<Integer, Integer> vPair = http.getVersion();
|
||||
_returnCode = vPair.first;
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.w(TAG, "Failed to getVersion, IllegalArgumentException occured: " + e.getMessage());
|
||||
_returnCode = 597;
|
||||
} catch (OCSyncException e) {
|
||||
Log.w(TAG, "Failed to login, OCSyncException occured: " + e.getMessage());
|
||||
_returnCode = 599;
|
||||
}
|
||||
|
||||
_last_http_error = http.getLastError();
|
||||
return (_returnCode == 200);
|
||||
// Create client object to perform remote operations
|
||||
OwnCloudClient ocClient = OwnCloudClientFactory.createOwnCloudClient(
|
||||
_serverURI, getBaseContext(),
|
||||
// Activity or Service context
|
||||
true
|
||||
);
|
||||
|
||||
// Set basic credentials
|
||||
ocClient.setCredentials(
|
||||
OwnCloudCredentialsFactory.newBasicCredentials(_login, _password)
|
||||
);
|
||||
|
||||
// Send an authentication test to ownCloud
|
||||
OwnCloudAuthenticator at = new OwnCloudAuthenticator(getBaseContext());
|
||||
at.setClient(ocClient);
|
||||
|
||||
_returnCode = at.testCredentials();
|
||||
|
||||
return (_returnCode == LoginReturnCode.OK);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean success) {
|
||||
mAuthTask = null;
|
||||
showProgress(false);
|
||||
_signInButton.setProgress(90);
|
||||
_signInButton.setProgress(90);
|
||||
|
||||
if (success) {
|
||||
_signInButton.setProgress(100);
|
||||
_signInButton.setProgress(100);
|
||||
String accountType = getIntent().getStringExtra(UserLoginTask.PARAM_AUTHTOKEN_TYPE);
|
||||
if (accountType == null) {
|
||||
accountType = getString(R.string.account_type);
|
||||
}
|
||||
|
||||
if (accountType == null) {
|
||||
accountType = getString(R.string.account_type);
|
||||
}
|
||||
|
||||
// Generate a label
|
||||
String accountLabel = _login + "@" + _serverURL.getHost();
|
||||
|
||||
String accountLabel = _login + "@" + _serverURI.getHost();
|
||||
|
||||
// We create the account
|
||||
Account account = new Account(accountLabel, accountType);
|
||||
Bundle accountBundle = new Bundle();
|
||||
accountBundle.putString("ocLogin", _login);
|
||||
accountBundle.putString("ocURI", _serverURL.toString());
|
||||
|
||||
accountBundle.putString("ocURI", _serverURI.toString());
|
||||
|
||||
// And we push it to Android
|
||||
AccountManager accMgr = AccountManager.get(getApplicationContext());
|
||||
accMgr.addAccountExplicitly(account, _password, accountBundle);
|
||||
|
||||
accMgr.addAccountExplicitly(account, _password, accountBundle);
|
||||
|
||||
// Set sync options
|
||||
ContentResolver.setSyncAutomatically(account, getString(R.string.account_authority), true);
|
||||
|
||||
|
||||
Bundle b = new Bundle();
|
||||
b.putInt("synctype", 1);
|
||||
|
||||
|
||||
ContentResolver.addPeriodicSync(account, getString(R.string.account_authority), b, DefaultPrefs.syncInterval * 60);
|
||||
// Then it's finished
|
||||
finish();
|
||||
|
||||
|
||||
// Start sync settings, we have finished to configure account
|
||||
Intent settingsIntent = new Intent(Settings.ACTION_SYNC_SETTINGS);
|
||||
settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
getApplicationContext().startActivity(settingsIntent);
|
||||
} else {
|
||||
boolean serverViewRequestFocus = true;
|
||||
boolean serverViewRequestFocus = true;
|
||||
switch (_returnCode) {
|
||||
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:
|
||||
case INVALID_ADDR:
|
||||
_serverView.setError(getString(R.string.error_invalid_server_address));
|
||||
break;
|
||||
case 400:
|
||||
case 598:
|
||||
_serverView.setError(getString(R.string.error_connection_failed));
|
||||
break;
|
||||
case 599:
|
||||
case HTTP_CONN_FAILED:
|
||||
_serverView.setError(getString(R.string.error_http_connection_failed));
|
||||
break;
|
||||
case 401:
|
||||
case 403:
|
||||
_passwordView.setError(getString(R.string.error_invalid_login));
|
||||
_passwordView.requestFocus();
|
||||
// Warning, there is no break here to disable serverViewRequestFocus too
|
||||
case 200:
|
||||
default:
|
||||
serverViewRequestFocus = false;
|
||||
case CONN_FAILED:
|
||||
_serverView.setError(getString(R.string.error_connection_failed));
|
||||
break;
|
||||
case CONN_FAILED_NOT_FOUND:
|
||||
_serverView.setError(getString(R.string.error_connection_failed_not_found));
|
||||
break;
|
||||
case UNKNOWN_ERROR:
|
||||
_serverView.setError("UNK");
|
||||
break;
|
||||
case INVALID_LOGIN:
|
||||
_passwordView.setError(getString(R.string.error_invalid_login));
|
||||
_passwordView.requestFocus();
|
||||
// Warning, there is no break here to disable serverViewRequestFocus too
|
||||
case OK:
|
||||
default:
|
||||
serverViewRequestFocus = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (serverViewRequestFocus) {
|
||||
_serverView.requestFocus();
|
||||
}
|
||||
if (serverViewRequestFocus) {
|
||||
_serverView.requestFocus();
|
||||
}
|
||||
|
||||
// If not ok, reset the progress
|
||||
if (_returnCode != 200) {
|
||||
_signInButton.setProgress(0);
|
||||
}
|
||||
// If not ok, reset the progress
|
||||
if (_returnCode != LoginReturnCode.OK) {
|
||||
_signInButton.setProgress(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -374,14 +345,13 @@ public class LoginActivity extends AppCompatActivity {
|
||||
mAuthTask = null;
|
||||
showProgress(false);
|
||||
}
|
||||
|
||||
private final URL _serverURL;
|
||||
|
||||
private final Uri _serverURI;
|
||||
private final String _login;
|
||||
private final String _password;
|
||||
private String _last_http_error;
|
||||
private int _returnCode;
|
||||
|
||||
static final String PARAM_AUTHTOKEN_TYPE = "auth.token";
|
||||
private final String TAG = UserLoginTask.class.getCanonicalName();
|
||||
}
|
||||
private LoginReturnCode _returnCode;
|
||||
|
||||
public static final String PARAM_AUTHTOKEN_TYPE = "auth.token";
|
||||
private final String TAG = UserLoginTask.class.getCanonicalName();
|
||||
}
|
||||
}
|
||||
|
@ -38,242 +38,175 @@ 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 org.json.JSONArray;
|
||||
|
||||
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.AndroidSmsFetcher;
|
||||
import fr.unix_experience.owncloud_sms.engine.ConnectivityMonitor;
|
||||
import fr.unix_experience.owncloud_sms.enums.OCSMSNotificationType;
|
||||
import fr.unix_experience.owncloud_sms.enums.PermissionID;
|
||||
import fr.unix_experience.owncloud_sms.notifications.OCSMSNotificationUI;
|
||||
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;
|
||||
implements NavigationView.OnNavigationItemSelectedListener{
|
||||
|
||||
private ConnectivityMonitor _ConnectivityMonitor = null;
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
if (_ConnectivityMonitor == null) {
|
||||
_ConnectivityMonitor = new ConnectivityMonitor(getApplicationContext());
|
||||
}
|
||||
if (_ConnectivityMonitor == null) {
|
||||
_ConnectivityMonitor = new ConnectivityMonitor(getApplicationContext());
|
||||
}
|
||||
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
|
||||
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();
|
||||
|
||||
setupToolbar();
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setHomeButtonEnabled(true);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
|
||||
assert navigationView != null;
|
||||
navigationView.setNavigationItemSelectedListener(this);
|
||||
|
||||
drawer = findViewById(R.id.drawer_layout);
|
||||
setupDrawer();
|
||||
drawer.openDrawer(GravityCompat.START);
|
||||
drawer.openDrawer(GravityCompat.START);
|
||||
}
|
||||
|
||||
protected void setupToolbar() {
|
||||
setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
|
||||
}
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
|
||||
assert drawer != null;
|
||||
if (drawer.isDrawerOpen(GravityCompat.START)) {
|
||||
drawer.closeDrawer(GravityCompat.START);
|
||||
} else {
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
@Override
|
||||
public boolean onNavigationItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
boolean res = true;
|
||||
|
||||
NavigationView navigationView = findViewById(R.id.nav_view);
|
||||
assert navigationView != null;
|
||||
navigationView.setNavigationItemSelectedListener(this);
|
||||
}
|
||||
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;
|
||||
}
|
||||
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
|
||||
assert drawer != null;
|
||||
drawer.closeDrawer(GravityCompat.START);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
private boolean openAppSettings () {
|
||||
startActivity(new Intent(this, OCSMSSettingsActivity.class));
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean openAddAccount() {
|
||||
private boolean openAddAccount () {
|
||||
startActivity(new Intent(Settings.ACTION_ADD_ACCOUNT));
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void syncAllMessages() {
|
||||
Log.v(MainActivity.TAG, "Launch syncAllMessages()");
|
||||
if (!PermissionChecker.checkPermission(this, Manifest.permission.READ_SMS,
|
||||
REQUEST_SMS)) {
|
||||
return;
|
||||
}
|
||||
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;
|
||||
if (_ConnectivityMonitor.isValid()) {
|
||||
// Now fetch messages since last stored date
|
||||
JSONArray smsList = new JSONArray();
|
||||
new AndroidSmsFetcher(ctx).bufferMessagesSinceDate(smsList, (long) 0);
|
||||
|
||||
if (smsList.length() > 0) {
|
||||
OCSMSNotificationUI.notify(ctx, ctx.getString(R.string.sync_title),
|
||||
ctx.getString(R.string.sync_inprogress), OCSMSNotificationType.SYNC.ordinal());
|
||||
new SyncTask(getApplicationContext(), smsList).execute();
|
||||
}
|
||||
else {
|
||||
Toast.makeText(ctx, ctx.getString(R.string.nothing_to_sync), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
new SyncTask(this).execute();
|
||||
Log.v(MainActivity.TAG, "Finish syncAllMessages()");
|
||||
else {
|
||||
Toast.makeText(ctx, ctx.getString(R.string.err_sync_no_connection_available), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
Log.v(MainActivity.TAG, "Finish syncAllMessages()");
|
||||
}
|
||||
|
||||
private boolean openMyAccounts() {
|
||||
private boolean openMyAccounts () {
|
||||
startActivity(new Intent(this, AccountListActivity.class));
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean openGooglePlayStore() {
|
||||
private boolean openGooglePlayStore () {
|
||||
Intent intent;
|
||||
try {
|
||||
intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + getPackageName()));
|
||||
} catch (android.content.ActivityNotFoundException e) {
|
||||
} catch (android.content.ActivityNotFoundException anfe) {
|
||||
intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + getPackageName()));
|
||||
}
|
||||
|
||||
startActivity(intent);
|
||||
return true;
|
||||
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 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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];
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
private static final String TAG = MainActivity.class.getSimpleName();
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package fr.unix_experience.owncloud_sms.activities;
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014-2017, Loic Blot <loic.blot@unix-experience.fr>
|
||||
* 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
|
||||
@ -24,14 +24,9 @@ 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;
|
||||
@ -42,115 +37,82 @@ 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 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 static AccountManager _accountMgr;
|
||||
private static String _accountAuthority;
|
||||
private static String _accountType;
|
||||
|
||||
private AppCompatDelegate mDelegate;
|
||||
@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;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
// Bind our boolean preferences
|
||||
VirtualSettingsActivity._boolPrefs.add(new BindObjectPref("push_on_receive", DefaultPrefs.pushOnReceive));
|
||||
VirtualSettingsActivity._boolPrefs.add(new BindObjectPref("sync_wifi", DefaultPrefs.syncWifi));
|
||||
VirtualSettingsActivity._boolPrefs.add(new BindObjectPref("sync_4g", DefaultPrefs.sync4G));
|
||||
VirtualSettingsActivity._boolPrefs.add(new BindObjectPref("sync_3g", DefaultPrefs.sync3G));
|
||||
VirtualSettingsActivity._boolPrefs.add(new BindObjectPref("sync_gprs", DefaultPrefs.syncGPRS));
|
||||
VirtualSettingsActivity._boolPrefs.add(new BindObjectPref("sync_2g", DefaultPrefs.sync2G));
|
||||
VirtualSettingsActivity._boolPrefs.add(new BindObjectPref("sync_others", DefaultPrefs.syncOthers));
|
||||
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
// Bind our string preferences
|
||||
VirtualSettingsActivity._stringPrefs.add(new BindObjectPref("sync_frequency", "15"));
|
||||
VirtualSettingsActivity._stringPrefs.add(new BindObjectPref("sync_bulk_messages", "-1"));
|
||||
VirtualSettingsActivity._stringPrefs.add(new BindObjectPref("minimum_sync_chars", "1"));
|
||||
|
||||
private AppCompatDelegate getDelegate() {
|
||||
if (mDelegate == null) {
|
||||
mDelegate = AppCompatDelegate.create(this, null);
|
||||
}
|
||||
return mDelegate;
|
||||
}
|
||||
// Must be at the end, after preference bind
|
||||
super.onPostCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
public ActionBar getSupportActionBar() {
|
||||
return getDelegate().getSupportActionBar();
|
||||
}
|
||||
protected void handleCheckboxPreference(String key, Boolean value) {
|
||||
// Network types allowed for sync
|
||||
if ("push_on_receive".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);
|
||||
}
|
||||
}
|
||||
|
||||
@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;
|
||||
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);
|
||||
|
||||
// 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));
|
||||
// Set the summary to reflect the new value.
|
||||
preference
|
||||
.setSummary((index >= 0) ? preference.getEntries()[index]
|
||||
: null);
|
||||
|
||||
// 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"));
|
||||
Log.i(OCSMSSettingsActivity.TAG, "Modifying listPreference " + key);
|
||||
|
||||
// Must be at the end, after preference bind
|
||||
super.onPostCreate(savedInstanceState);
|
||||
}
|
||||
OCSMSSharedPrefs prefs = new OCSMSSharedPrefs(VirtualSettingsActivity._context);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
// Handle sync frequency change
|
||||
if ("sync_frequency".equals(key)) {
|
||||
if (!PermissionChecker.checkPermission(this, Manifest.permission.GET_ACCOUNTS,
|
||||
REQUEST_ACCOUNTS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
Account[] myAccountList = OCSMSSettingsActivity._accountMgr.getAccountsByType(OCSMSSettingsActivity._accountType);
|
||||
long syncFreq = Long.parseLong(value);
|
||||
|
||||
// Get ownCloud SMS account list
|
||||
for (Account acct : myAccountList) {
|
||||
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) {
|
||||
for (PeriodicSync ps: syncList) {
|
||||
if ((ps.period == syncFreq) && (ps.extras.getInt("synctype") == 1)) {
|
||||
foundSameSyncCycle = true;
|
||||
}
|
||||
@ -161,29 +123,16 @@ public class OCSMSSettingsActivity extends VirtualSettingsActivity {
|
||||
b.putInt("synctype", 1);
|
||||
|
||||
ContentResolver.removePeriodicSync(acct, OCSMSSettingsActivity._accountAuthority, b);
|
||||
if (syncFreq > 0) {
|
||||
ContentResolver.addPeriodicSync(acct, OCSMSSettingsActivity._accountAuthority, b, syncFreq * 60);
|
||||
}
|
||||
if (syncFreq > 0) {
|
||||
ContentResolver.addPeriodicSync(acct, OCSMSSettingsActivity._accountAuthority, b, syncFreq * 60);
|
||||
}
|
||||
}
|
||||
|
||||
prefs.putLong(key, syncFreq);
|
||||
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;
|
||||
else if ("sync_bulk_messages".equals(key) || "minimum_sync_chars".equals(key)) {
|
||||
prefs.putInteger(key, Integer.parseInt(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,13 +1,8 @@
|
||||
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;
|
||||
@ -16,7 +11,6 @@ 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
|
||||
@ -25,9 +19,6 @@ public class AccountActionsActivity extends AppCompatListActivity {
|
||||
|
||||
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);
|
||||
@ -35,7 +26,6 @@ public class AccountActionsActivity extends AppCompatListActivity {
|
||||
|
||||
// Create item list
|
||||
itemList.add(getBaseContext().getString(R.string.restore_all_messages));
|
||||
itemList.add(getBaseContext().getString(R.string.reinit_sync_cursor));
|
||||
|
||||
adp.notifyDataSetChanged();
|
||||
|
||||
@ -43,19 +33,6 @@ public class AccountActionsActivity extends AppCompatListActivity {
|
||||
_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) {
|
||||
@ -69,23 +46,6 @@ public class AccountActionsActivity extends AppCompatListActivity {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -3,14 +3,13 @@ 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.owncloud_sms.adapters.AndroidAccountAdapter;
|
||||
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 {
|
||||
|
||||
@ -22,35 +21,21 @@ public class AccountListActivity extends AppCompatListActivity {
|
||||
|
||||
setContentView(R.layout.restore_activity_accountlist);
|
||||
|
||||
getSupportActionBar().setHomeButtonEnabled(true);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
ArrayList<Account> itemList = new ArrayList<>();
|
||||
|
||||
ArrayList<Account> itemList = new ArrayList<>();
|
||||
|
||||
AndroidAccountAdapter adapter = new AndroidAccountAdapter(this,
|
||||
AndroidAccountAdapter adapter = new AndroidAccountAdapter(this,
|
||||
android.R.layout.simple_list_item_1,
|
||||
itemList,
|
||||
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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,78 +49,41 @@ public class ContactListActivity extends AppCompatActivity implements ASyncConta
|
||||
|
||||
assert getIntent().getExtras() != null;
|
||||
|
||||
String accountName = getIntent().getExtras().getString("account");
|
||||
|
||||
// accountName cannot be null, devel error
|
||||
assert accountName != null;
|
||||
|
||||
ContactListActivity.mAccountMgr = AccountManager.get(getBaseContext());
|
||||
Account[] myAccountList =
|
||||
ContactListActivity.mAccountMgr.getAccountsByType(getString(R.string.account_type));
|
||||
|
||||
// Init view
|
||||
mObjects = new ArrayList<>();
|
||||
setContentView(R.layout.restore_activity_contactlist);
|
||||
|
||||
mLayout = findViewById(R.id.contactlist_swipe_container);
|
||||
mLayout = (SwipeRefreshLayout) findViewById(R.id.contactlist_swipe_container);
|
||||
|
||||
mAdapter = new ContactListAdapter(getBaseContext(), mObjects);
|
||||
|
||||
mContactInfos = findViewById(R.id.contactinfos_layout);
|
||||
ListView contactPhoneListView = findViewById(R.id.contact_phonelistView);
|
||||
final Spinner sp = (Spinner) findViewById(R.id.contact_spinner);
|
||||
mContactInfos = (LinearLayout) findViewById(R.id.contactinfos_layout);
|
||||
final ProgressBar contactProgressBar = (ProgressBar) findViewById(R.id.contactlist_pgbar);
|
||||
ListView contactPhoneListView = (ListView) 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() {
|
||||
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();
|
||||
mContactPhoneListAdapter.clear();
|
||||
|
||||
mFetchedContact = sp.getSelectedItem().toString();
|
||||
mFetchedContact = sp.getSelectedItem().toString();
|
||||
fetchContact(mFetchedContact);
|
||||
}
|
||||
|
||||
@ -132,9 +95,37 @@ public class ContactListActivity extends AppCompatActivity implements ASyncConta
|
||||
|
||||
});
|
||||
sp.setAdapter(mAdapter);
|
||||
|
||||
for (final Account element : myAccountList) {
|
||||
if (element.name.equals(accountName)) {
|
||||
// Load "contacts"
|
||||
assert contactProgressBar != null;
|
||||
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 fetchContact(String name) {
|
||||
private void fetchContact(String name) {
|
||||
if (!PermissionChecker.checkPermission(this, Manifest.permission.READ_CONTACTS,
|
||||
REQUEST_CONTACTS)) {
|
||||
return;
|
||||
|
@ -26,10 +26,8 @@ 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;
|
||||
@ -51,9 +49,6 @@ public class RestoreMessagesActivity extends AppCompatActivity {
|
||||
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");
|
||||
@ -73,9 +68,9 @@ public class RestoreMessagesActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
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);
|
||||
Button fix_button = (Button) findViewById(R.id.button_fix_permissions);
|
||||
final Button launch_restore = (Button) findViewById(R.id.button_launch_restore);
|
||||
final ProgressBar pb = (ProgressBar) findViewById(R.id.progressbar_restore);
|
||||
|
||||
final RestoreMessagesActivity me = this;
|
||||
fix_button.setOnClickListener(new View.OnClickListener() {
|
||||
@ -116,27 +111,14 @@ public class RestoreMessagesActivity extends AppCompatActivity {
|
||||
});
|
||||
}
|
||||
|
||||
@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);
|
||||
TextView tv_error = (TextView) 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);
|
||||
Button fix_button = (Button) findViewById(R.id.button_fix_permissions);
|
||||
Button launch_restore = (Button) findViewById(R.id.button_launch_restore);
|
||||
ProgressBar pb = (ProgressBar) findViewById(R.id.progressbar_restore);
|
||||
pb.setVisibility(View.INVISIBLE);
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT) {
|
||||
@ -150,7 +132,8 @@ public class RestoreMessagesActivity extends AppCompatActivity {
|
||||
tv_error.setVisibility(View.VISIBLE);
|
||||
fix_button.setVisibility(View.VISIBLE);
|
||||
launch_restore.setVisibility(View.INVISIBLE);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
tv_error.setVisibility(View.INVISIBLE);
|
||||
fix_button.setVisibility(View.INVISIBLE);
|
||||
launch_restore.setVisibility(View.VISIBLE);
|
||||
@ -158,10 +141,10 @@ public class RestoreMessagesActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
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);
|
||||
TextView tv = (TextView) findViewById(R.id.tv_error_default_smsapp);
|
||||
Button fix_button = (Button) findViewById(R.id.button_fix_permissions);
|
||||
Button launch_restore = (Button) findViewById(R.id.button_launch_restore);
|
||||
ProgressBar pb = (ProgressBar) findViewById(R.id.progressbar_restore);
|
||||
tv.setText(err);
|
||||
tv.setVisibility(View.VISIBLE);
|
||||
fix_button.setVisibility(View.INVISIBLE);
|
||||
@ -182,9 +165,9 @@ public class RestoreMessagesActivity extends AppCompatActivity {
|
||||
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);
|
||||
TextView tv = (TextView) findViewById(R.id.tv_error_default_smsapp);
|
||||
Button fix_button = (Button) findViewById(R.id.button_fix_permissions);
|
||||
Button launch_restore = (Button) findViewById(R.id.button_launch_restore);
|
||||
tv.setVisibility(View.INVISIBLE);
|
||||
fix_button.setVisibility(View.INVISIBLE);
|
||||
launch_restore.setVisibility(View.VISIBLE);
|
||||
@ -225,7 +208,7 @@ public class RestoreMessagesActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
public void onProgressUpdate(Integer value) {
|
||||
TextView tv_progress = findViewById(R.id.tv_progress_value);
|
||||
TextView tv_progress = (TextView) findViewById(R.id.tv_progress_value);
|
||||
if (tv_progress.getVisibility() == View.INVISIBLE) {
|
||||
tv_progress.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
@ -177,9 +177,9 @@ public class VirtualSettingsActivity extends PreferenceActivity {
|
||||
// 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);
|
||||
public Object value;
|
||||
public BindObjectPref(String prefName, Object prefVal) {
|
||||
name = prefName;
|
||||
value = prefVal;
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ public class AndroidAccountAdapter extends ArrayAdapter<Account> {
|
||||
final Account account = _accounts.get(position);
|
||||
|
||||
if (account != null) {
|
||||
TextView label = v.findViewById(AndroidAccountAdapter._accountFieldId);
|
||||
TextView label = (TextView) v.findViewById(AndroidAccountAdapter._accountFieldId);
|
||||
if (label != null) {
|
||||
label.setText(account.name + " >");
|
||||
v.setOnClickListener(new OnClickListener() {
|
||||
|
@ -39,7 +39,7 @@ public class ContactListAdapter extends ArrayAdapter<String> {
|
||||
String element = _objects.get(position);
|
||||
|
||||
if (element != null) {
|
||||
TextView label = v.findViewById(ContactListAdapter._fieldId);
|
||||
TextView label = (TextView) v.findViewById(ContactListAdapter._fieldId);
|
||||
if (label != null) {
|
||||
label.setText(element);
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public class RecoveryPhoneNumberListViewAdapter extends ArrayAdapter<String> {
|
||||
v = inflater.inflate(RecoveryPhoneNumberListViewAdapter._itemLayout, null);
|
||||
}
|
||||
|
||||
TextView label = v.findViewById(RecoveryPhoneNumberListViewAdapter._fieldId);
|
||||
TextView label = (TextView) v.findViewById(RecoveryPhoneNumberListViewAdapter._fieldId);
|
||||
if (label != null) {
|
||||
final String l = getItem(position).toString();
|
||||
label.setText(getItem(position).toString());
|
||||
|
@ -25,8 +25,19 @@ import android.accounts.NetworkErrorException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
|
||||
import org.apache.commons.httpclient.HttpException;
|
||||
import org.apache.commons.httpclient.methods.GetMethod;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import fr.unix_experience.owncloud_sms.activities.LoginActivity;
|
||||
import fr.unix_experience.owncloud_sms.enums.LoginReturnCode;
|
||||
|
||||
public class OwnCloudAuthenticator extends AbstractAccountAuthenticator {
|
||||
// Simple constructor
|
||||
@ -92,8 +103,95 @@ public class OwnCloudAuthenticator extends AbstractAccountAuthenticator {
|
||||
// TODO Auto-generated method stub
|
||||
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;
|
||||
int status;
|
||||
|
||||
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(OwnCloudAuthenticator.isSuccess(status)) {
|
||||
String response = get.getResponseBodyAsString();
|
||||
Log.i(OwnCloudAuthenticator.TAG, "Successful response: " + response);
|
||||
|
||||
// Parse the response
|
||||
JSONObject respJSON = new JSONObject(response);
|
||||
JSONObject respOCS = respJSON.getJSONObject(OwnCloudAuthenticator.NODE_OCS);
|
||||
JSONObject respData = respOCS.getJSONObject(OwnCloudAuthenticator.NODE_DATA);
|
||||
String id = respData.getString(OwnCloudAuthenticator.NODE_ID);
|
||||
String displayName = respData.getString(OwnCloudAuthenticator.NODE_DISPLAY_NAME);
|
||||
String email = respData.getString(OwnCloudAuthenticator.NODE_EMAIL);
|
||||
|
||||
Log.i(OwnCloudAuthenticator.TAG, "*** Parsed user information: " + id + " - " + displayName + " - " + email);
|
||||
|
||||
} else {
|
||||
String response = get.getResponseBodyAsString();
|
||||
Log.e(OwnCloudAuthenticator.TAG, "Failed response while getting user information ");
|
||||
if (response != null) {
|
||||
Log.e(OwnCloudAuthenticator.TAG, "*** status code: " + status + " ; response message: " + response);
|
||||
} else {
|
||||
Log.e(OwnCloudAuthenticator.TAG, "*** status code: " + status);
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
case 401: bRet = LoginReturnCode.INVALID_LOGIN; break;
|
||||
case 404: bRet = LoginReturnCode.CONN_FAILED_NOT_FOUND; break;
|
||||
default: bRet = LoginReturnCode.UNKNOWN_ERROR; break;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(OwnCloudAuthenticator.TAG, "Exception while getting OC user information", e);
|
||||
bRet = LoginReturnCode.UNKNOWN_ERROR;
|
||||
|
||||
} finally {
|
||||
get.releaseConnection();
|
||||
}
|
||||
return bRet;
|
||||
}
|
||||
|
||||
private static boolean isSuccess(int status) {
|
||||
return (status == HttpStatus.SC_OK);
|
||||
}
|
||||
|
||||
public void setClient(OwnCloudClient oc) {
|
||||
_client = oc;
|
||||
}
|
||||
|
||||
private final Context _context;
|
||||
|
||||
private OwnCloudClient _client;
|
||||
|
||||
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";
|
||||
}
|
@ -25,6 +25,8 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONArray;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import fr.unix_experience.owncloud_sms.R;
|
||||
@ -34,7 +36,6 @@ 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 {
|
||||
|
||||
@ -81,14 +82,14 @@ public class ConnectivityChanged extends BroadcastReceiver implements ASyncSMSSy
|
||||
Log.i(ConnectivityChanged.TAG,"Synced Last:" + lastMessageSynced);
|
||||
|
||||
// Now fetch messages since last stored date
|
||||
SmsBuffer smsBuffer = new SmsBuffer();
|
||||
new AndroidSmsFetcher(context).bufferMessagesSinceDate(smsBuffer, lastMessageSynced);
|
||||
JSONArray smsList = new JSONArray();
|
||||
new AndroidSmsFetcher(context).bufferMessagesSinceDate(smsList, 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();
|
||||
if (cMon.get().isValid() && (smsList.length() > 0)) {
|
||||
new SyncTask(context, smsList).execute();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@ 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;
|
||||
|
@ -12,13 +12,15 @@ import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
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> {
|
||||
@ -66,24 +68,59 @@ public interface ASyncContactLoad {
|
||||
|
||||
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);
|
||||
JSONArray phoneNumbers = _client.getServerPhoneNumbers();
|
||||
for (int i = 0; i < phoneNumbers.length(); i++) {
|
||||
String phone = phoneNumbers.getString(i);
|
||||
serverPhoneList.add(phone);
|
||||
}
|
||||
|
||||
// Read all contacts
|
||||
readContacts(serverPhoneList);
|
||||
ContentResolver cr = _context.getContentResolver();
|
||||
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
|
||||
null, null, null, null);
|
||||
if (((cur != null) ? cur.getCount() : 0) > 0) {
|
||||
String id, name;
|
||||
while ((cur != null) && 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) {
|
||||
|
||||
_objects.addAll(serverPhoneList);
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cur != null) {
|
||||
cur.close();
|
||||
}
|
||||
|
||||
for (String phone : serverPhoneList) {
|
||||
_objects.add(phone);
|
||||
}
|
||||
|
||||
// Sort phone numbers
|
||||
Collections.sort(_objects);
|
||||
} catch (JSONException e) {
|
||||
_objects.add(_context.getString(R.string.err_fetch_phonelist));
|
||||
return false;
|
||||
} catch (OCSyncException e) {
|
||||
_objects.add(_context.getString(e.getErrorId()));
|
||||
return false;
|
||||
@ -91,51 +128,6 @@ public interface ASyncContactLoad {
|
||||
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);
|
||||
|
@ -7,11 +7,14 @@ import android.os.AsyncTask;
|
||||
import android.provider.Telephony;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
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>
|
||||
@ -57,70 +60,81 @@ public interface ASyncSMSRecovery {
|
||||
|
||||
OCSMSOwnCloudClient client = new OCSMSOwnCloudClient(_context, _account);
|
||||
SmsDataProvider smsDataProvider = new SmsDataProvider(_context);
|
||||
SmsMessagesResponse obj = client.retrieveSomeMessages(start, 500);
|
||||
JSONObject 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;
|
||||
try {
|
||||
while (obj.getLong("last_id") != start) {
|
||||
JSONObject messages = obj.getJSONObject("messages");
|
||||
Iterator<?> keys = messages.keys();
|
||||
while (keys.hasNext()) {
|
||||
String key = (String)keys.next();
|
||||
if (messages.get(key) instanceof JSONObject) {
|
||||
JSONObject msg = messages.getJSONObject(key);
|
||||
|
||||
int mbid = msg.getInt("mailbox");
|
||||
// Ignore invalid mailbox
|
||||
if (mbid > MailboxID.ALL.getId()) {
|
||||
Log.e(ASyncSMSRecovery.TAG, "Invalid mailbox found: " + msg.getString("mailbox"));
|
||||
continue;
|
||||
}
|
||||
|
||||
String address;
|
||||
String body;
|
||||
int type;
|
||||
try {
|
||||
address = msg.getString("address");
|
||||
body = msg.getString("msg");
|
||||
type = msg.getInt("type");
|
||||
}
|
||||
catch (JSONException e) {
|
||||
Log.e(ASyncSMSRecovery.TAG, "Invalid SMS data found: " + e.getMessage());
|
||||
continue;
|
||||
}
|
||||
MailboxID mailbox_id = MailboxID.fromInt(mbid);
|
||||
|
||||
// Ignore already existing messages
|
||||
if (smsDataProvider.messageExists(address, body, key, 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, key);
|
||||
values.put(Telephony.Sms.TYPE, type);
|
||||
values.put(Telephony.Sms.SEEN, 1);
|
||||
values.put(Telephony.Sms.READ, 1);
|
||||
|
||||
// @TODO verify message exists before inserting it
|
||||
_context.getContentResolver().insert(Uri.parse(mailbox_id.getURI()), values);
|
||||
|
||||
nb++;
|
||||
if ((nb % 5) == 0) {
|
||||
publishProgress(nb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.getLong("last_id");
|
||||
|
||||
if (!new ConnectivityMonitor(_context).isValid()) {
|
||||
Log.e(ASyncSMSRecovery.TAG, "Restore connectivity problems, aborting");
|
||||
return null;
|
||||
}
|
||||
obj = client.retrieveSomeMessages(start, 500);
|
||||
}
|
||||
|
||||
start = obj.getLastID();
|
||||
|
||||
if (!new ConnectivityMonitor(_context).isValid()) {
|
||||
Log.e(ASyncSMSRecovery.TAG, "Restore connectivity problems, aborting");
|
||||
return null;
|
||||
}
|
||||
obj = client.retrieveSomeMessages(start, 500);
|
||||
} catch (JSONException e) {
|
||||
Log.e(ASyncSMSRecovery.TAG, "Missing last_id field!");
|
||||
}
|
||||
|
||||
// Force this refresh to fix dates
|
||||
_context.getContentResolver().delete(Uri.parse("content://sms/conversations/-1"),
|
||||
null, null);
|
||||
_context.getContentResolver().delete(Uri.parse("content://sms/conversations/-1"), null, null);
|
||||
|
||||
publishProgress(nb);
|
||||
|
||||
|
@ -19,94 +19,28 @@ package fr.unix_experience.owncloud_sms.engine;
|
||||
|
||||
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 org.json.JSONArray;
|
||||
|
||||
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;
|
||||
public SyncTask(Context context, JSONArray smsList) {
|
||||
_context = context;
|
||||
_smsBuffer = null;
|
||||
}
|
||||
|
||||
public SyncTask(Context context, SmsBuffer buffer) {
|
||||
_activity = null;
|
||||
_context = context;
|
||||
_smsBuffer = buffer;
|
||||
_smsList = smsList;
|
||||
}
|
||||
|
||||
@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));
|
||||
@ -115,25 +49,24 @@ public interface ASyncSMSSync {
|
||||
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);
|
||||
_client.doPushRequest(_smsList);
|
||||
OCSMSNotificationUI.cancel(_context);
|
||||
} catch (IllegalStateException e) { // Fail to read account data
|
||||
OCSMSNotificationUI.notify(_context, _context.getString(R.string.fatal_error),
|
||||
e.getMessage(), OCSMSNotificationType.SYNC_FAILED);
|
||||
e.getMessage(), OCSMSNotificationType.SYNC_FAILED.ordinal());
|
||||
} 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);
|
||||
OCSMSNotificationUI.notify(_context, _context.getString(R.string.fatal_error),
|
||||
e.getMessage(), OCSMSNotificationType.SYNC_FAILED.ordinal());
|
||||
}
|
||||
}
|
||||
smsBuffer.clear();
|
||||
OCSMSNotificationUI.cancel(_context);
|
||||
Log.i(ASyncSMSSync.TAG, "Stopping background sync");
|
||||
return null;
|
||||
}
|
||||
|
||||
private final SmsBuffer _smsBuffer;
|
||||
private final Context _context;
|
||||
private final Activity _activity;
|
||||
private final JSONArray _smsList;
|
||||
}
|
||||
|
||||
String TAG = ASyncSMSSync.class.getSimpleName();
|
||||
|
@ -23,13 +23,14 @@ import android.util.Log;
|
||||
|
||||
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 ncsmsgo.SmsBuffer;
|
||||
|
||||
public class AndroidSmsFetcher {
|
||||
public AndroidSmsFetcher(Context ct) {
|
||||
_lastMsgDate = (long) 0;
|
||||
_context = ct;
|
||||
|
||||
_existingInboxMessages = null;
|
||||
@ -37,35 +38,13 @@ public class AndroidSmsFetcher {
|
||||
_existingDraftsMessages = null;
|
||||
}
|
||||
|
||||
void fetchAllMessages(SmsBuffer result) {
|
||||
void fetchAllMessages(JSONArray 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) {
|
||||
private void bufferMailboxMessages(JSONArray result, MailboxID mbID) {
|
||||
if ((_context == null)) {
|
||||
return;
|
||||
}
|
||||
@ -85,14 +64,30 @@ public class AndroidSmsFetcher {
|
||||
}
|
||||
|
||||
// Reading mailbox
|
||||
readMailBox(c, smsBuffer, mbID);
|
||||
do {
|
||||
JSONObject entry = new JSONObject();
|
||||
|
||||
try {
|
||||
for (int idx = 0; idx < c.getColumnCount(); idx++) {
|
||||
handleProviderColumn(c, idx, entry);
|
||||
}
|
||||
|
||||
// Mailbox ID is required by server
|
||||
entry.put("mbox", mbID.ordinal());
|
||||
result.put(entry);
|
||||
|
||||
} catch (JSONException e) {
|
||||
Log.e(AndroidSmsFetcher.TAG, "JSON Exception when reading SMS Mailbox", e);
|
||||
}
|
||||
}
|
||||
while (c.moveToNext());
|
||||
|
||||
Log.i(AndroidSmsFetcher.TAG, c.getCount() + " messages read from " + mbID.getURI());
|
||||
c.close();
|
||||
}
|
||||
|
||||
// Used by Content Observer
|
||||
public SmsBuffer getLastMessage(MailboxID mbID) {
|
||||
public JSONArray getLastMessage(MailboxID mbID) {
|
||||
if ((_context == null)) {
|
||||
return null;
|
||||
}
|
||||
@ -104,31 +99,29 @@ public class AndroidSmsFetcher {
|
||||
}
|
||||
|
||||
// We create a list of strings to store results
|
||||
SmsEntry entry = new SmsEntry();
|
||||
SmsBuffer results = new SmsBuffer();
|
||||
JSONArray results = new JSONArray();
|
||||
JSONObject entry = new JSONObject();
|
||||
|
||||
Integer mboxId = -1;
|
||||
for (int idx = 0; idx < c.getColumnCount(); idx++) {
|
||||
Integer rid = handleProviderColumn(c, idx, entry);
|
||||
if (rid != -1) {
|
||||
mboxId = rid;
|
||||
try {
|
||||
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");
|
||||
/*
|
||||
* Mailbox ID is required by server
|
||||
* mboxId is greater than server mboxId by 1 because types
|
||||
* aren't indexed in the same mean
|
||||
*/
|
||||
entry.put("mbox", (mboxId - 1));
|
||||
|
||||
results.put(entry);
|
||||
} catch (JSONException e) {
|
||||
Log.e(AndroidSmsFetcher.TAG, "JSON Exception when reading SMS Mailbox", e);
|
||||
}
|
||||
|
||||
c.close();
|
||||
|
||||
@ -136,14 +129,14 @@ public class AndroidSmsFetcher {
|
||||
}
|
||||
|
||||
// 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);
|
||||
public void bufferMessagesSinceDate(JSONArray result, Long sinceDate) {
|
||||
bufferMessagesSinceDate(result, MailboxID.INBOX, sinceDate);
|
||||
bufferMessagesSinceDate(result, MailboxID.SENT, sinceDate);
|
||||
bufferMessagesSinceDate(result, MailboxID.DRAFTS, sinceDate);
|
||||
}
|
||||
|
||||
// Used by ConnectivityChanged Event
|
||||
private void bufferMessagesSinceDate(SmsBuffer smsBuffer, MailboxID mbID, Long sinceDate) {
|
||||
private void bufferMessagesSinceDate(JSONArray result, MailboxID mbID, Long sinceDate) {
|
||||
Log.i(AndroidSmsFetcher.TAG, "bufferMessagesSinceDate for " + mbID.toString() + " sinceDate " + sinceDate.toString());
|
||||
if ((_context == null)) {
|
||||
return;
|
||||
@ -157,23 +150,37 @@ public class AndroidSmsFetcher {
|
||||
return;
|
||||
}
|
||||
|
||||
// Read Mailbox
|
||||
readMailBox(c, smsBuffer, mbID);
|
||||
do {
|
||||
JSONObject entry = new JSONObject();
|
||||
|
||||
try {
|
||||
for (int idx = 0; idx < c.getColumnCount(); idx++) {
|
||||
handleProviderColumn(c, idx, entry);
|
||||
}
|
||||
|
||||
// Mailbox ID is required by server
|
||||
entry.put("mbox", mbID.ordinal());
|
||||
result.put(entry);
|
||||
} catch (JSONException e) {
|
||||
Log.e(AndroidSmsFetcher.TAG, "JSON Exception when reading SMS Mailbox", e);
|
||||
}
|
||||
}
|
||||
while (c.moveToNext());
|
||||
|
||||
Log.i(AndroidSmsFetcher.TAG, c.getCount() + " messages read from " + mbID.getURI());
|
||||
c.close();
|
||||
}
|
||||
|
||||
private Integer handleProviderColumn(Cursor c, int idx, SmsEntry entry) {
|
||||
private Integer handleProviderColumn(Cursor c, int idx, JSONObject entry) throws JSONException {
|
||||
String colName = c.getColumnName(idx);
|
||||
|
||||
// Id column is must be an integer
|
||||
switch (colName) {
|
||||
case "_id":
|
||||
entry.id = c.getInt(idx);
|
||||
entry.put(colName, c.getInt(idx));
|
||||
break;
|
||||
case "type":
|
||||
entry.type = c.getInt(idx);
|
||||
entry.put(colName, c.getInt(idx));
|
||||
return c.getInt(idx);
|
||||
/* For debug purpose
|
||||
case "length(address)":
|
||||
@ -181,22 +188,19 @@ public class AndroidSmsFetcher {
|
||||
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);
|
||||
entry.put(colName, (c.getInt(idx) > 0) ? "true" : "false");
|
||||
break;
|
||||
case "date":
|
||||
entry.date = c.getLong(idx);
|
||||
break;
|
||||
case "address":
|
||||
entry.address = c.getString(idx);
|
||||
break;
|
||||
case "body":
|
||||
entry.body = c.getString(idx);
|
||||
// Special case for date, we need to record last without searching
|
||||
Long tmpDate = c.getLong(idx);
|
||||
if (tmpDate > _lastMsgDate) {
|
||||
_lastMsgDate = tmpDate;
|
||||
}
|
||||
entry.put(colName, c.getString(idx));
|
||||
break;
|
||||
default:
|
||||
// Unhandled column
|
||||
entry.put(colName, c.getString(idx));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -245,10 +249,16 @@ public class AndroidSmsFetcher {
|
||||
_existingDraftsMessages = draftMessages;
|
||||
}
|
||||
|
||||
Long getLastMessageDate() {
|
||||
return _lastMsgDate;
|
||||
}
|
||||
|
||||
private final Context _context;
|
||||
private JSONArray _existingInboxMessages;
|
||||
private JSONArray _existingSentMessages;
|
||||
private JSONArray _existingDraftsMessages;
|
||||
|
||||
private Long _lastMsgDate;
|
||||
|
||||
private static final String TAG = AndroidSmsFetcher.class.getSimpleName();
|
||||
}
|
||||
|
@ -0,0 +1,93 @@
|
||||
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.net.Uri;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
import com.owncloud.android.lib.common.OwnCloudClientFactory;
|
||||
import com.owncloud.android.lib.common.OwnCloudCredentialsFactory;
|
||||
|
||||
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 java.io.IOException;
|
||||
|
||||
class HTTPRequestBuilder {
|
||||
|
||||
private final OwnCloudClient _ocClient;
|
||||
|
||||
// API v1 calls
|
||||
private static final String OC_GET_VERSION = "/index.php/apps/ocsms/get/apiversion?format=json";
|
||||
private static final String OC_GET_ALL_SMS_IDS = "/index.php/apps/ocsms/get/smsidlist?format=json";
|
||||
private static final String OC_GET_LAST_MSG_TIMESTAMP = "/index.php/apps/ocsms/get/lastmsgtime?format=json";
|
||||
private static final String OC_PUSH_ROUTE = "/index.php/apps/ocsms/push?format=json";
|
||||
|
||||
// API v2 calls
|
||||
private static final String OC_V2_GET_PHONELIST = "/index.php/apps/ocsms/api/v2/phones/list?format=json";
|
||||
private static final String OC_V2_GET_MESSAGES ="/index.php/apps/ocsms/api/v2/messages/[START]/[LIMIT]?format=json";
|
||||
private static final String OC_V2_GET_MESSAGES_PHONE ="/index.php/apps/ocsms/api/v2/messages/[PHONENUMBER]/[START]/[LIMIT]?format=json";
|
||||
private static final String OC_V2_GET_MESSAGES_SENDQUEUE = "/index.php/apps/ocsms/api/v2/messages/sendqueue?format=json";
|
||||
|
||||
HTTPRequestBuilder(Context context, Uri serverURI, String accountName, String accountPassword) {
|
||||
_ocClient = OwnCloudClientFactory.createOwnCloudClient(
|
||||
serverURI, context, true);
|
||||
|
||||
// Set basic credentials
|
||||
_ocClient.setCredentials(
|
||||
OwnCloudCredentialsFactory.newBasicCredentials(accountName, accountPassword)
|
||||
);
|
||||
}
|
||||
|
||||
private GetMethod get(String oc_call) {
|
||||
GetMethod get = new GetMethod(_ocClient.getBaseUri() + oc_call);
|
||||
get.addRequestHeader("OCS-APIREQUEST", "true");
|
||||
return get;
|
||||
}
|
||||
|
||||
GetMethod getAllSmsIds() {
|
||||
return get(HTTPRequestBuilder.OC_GET_ALL_SMS_IDS);
|
||||
}
|
||||
|
||||
public GetMethod getVersion() {
|
||||
return get(HTTPRequestBuilder.OC_GET_VERSION);
|
||||
}
|
||||
|
||||
PostMethod pushSms(StringRequestEntity ent) {
|
||||
PostMethod post = new PostMethod(_ocClient.getBaseUri() + HTTPRequestBuilder.OC_PUSH_ROUTE);
|
||||
post.addRequestHeader("OCS-APIREQUEST", "true");
|
||||
post.setRequestEntity(ent);
|
||||
return post;
|
||||
}
|
||||
|
||||
GetMethod getPhoneList() {
|
||||
return get(HTTPRequestBuilder.OC_V2_GET_PHONELIST);
|
||||
}
|
||||
|
||||
GetMethod getMessages(Long start, Integer limit) {
|
||||
return get(HTTPRequestBuilder.OC_V2_GET_MESSAGES.
|
||||
replace("[START]", start.toString()).replace("[LIMIT]", limit.toString()));
|
||||
}
|
||||
|
||||
int execute(HttpMethod req) throws IOException {
|
||||
return _ocClient.executeMethod(req);
|
||||
}
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
@ -20,21 +20,26 @@ package fr.unix_experience.owncloud_sms.engine;
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import org.apache.commons.httpclient.HttpException;
|
||||
import org.apache.commons.httpclient.HttpMethod;
|
||||
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 java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.ConnectException;
|
||||
|
||||
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 {
|
||||
@ -51,104 +56,327 @@ public class OCSMSOwnCloudClient {
|
||||
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));
|
||||
}
|
||||
Uri serverURI = Uri.parse(ocURI);
|
||||
_http = new HTTPRequestBuilder(context, serverURI,
|
||||
accountManager.getUserData(account, "ocLogin"),
|
||||
accountManager.getPassword(account));
|
||||
_connectivityMonitor = new ConnectivityMonitor(_context);
|
||||
}
|
||||
|
||||
public Integer getServerAPIVersion() throws OCSyncException {
|
||||
Pair<Integer, Integer> vPair = _http.getVersion();
|
||||
_serverAPIVersion = vPair.second;
|
||||
if (vPair.first == 200 && _serverAPIVersion > 0) {
|
||||
return _serverAPIVersion;
|
||||
doHttpRequest(_http.getVersion(), true);
|
||||
if (_jsonQueryBuffer == null) {
|
||||
// Return default version
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
try {
|
||||
_serverAPIVersion = _jsonQueryBuffer.getInt("version");
|
||||
}
|
||||
catch (JSONException e) {
|
||||
Log.e(OCSMSOwnCloudClient.TAG, "No version received from server, assuming version 1", e);
|
||||
_serverAPIVersion = 1;
|
||||
}
|
||||
|
||||
return _serverAPIVersion;
|
||||
}
|
||||
|
||||
SmsPhoneListResponse getServerPhoneNumbers() throws OCSyncException {
|
||||
Pair<Integer, SmsPhoneListResponse> response = _http.getPhoneList();
|
||||
if (response.second == null || response.first != 200) {
|
||||
JSONArray getServerPhoneNumbers() throws OCSyncException {
|
||||
doHttpRequest(_http.getPhoneList(), true);
|
||||
if (_jsonQueryBuffer == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return response.second;
|
||||
try {
|
||||
return _jsonQueryBuffer.getJSONArray("phoneList");
|
||||
} catch (JSONException e) {
|
||||
Log.e(OCSMSOwnCloudClient.TAG, "No phonelist received from server, empty it", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void doPushRequest(SmsBuffer smsBuffer) throws OCSyncException {
|
||||
/*
|
||||
public void doPushRequest(JSONArray smsList) throws OCSyncException {
|
||||
/**
|
||||
* If we need other API push, set it here
|
||||
*/
|
||||
switch (_serverAPIVersion) {
|
||||
case 1:
|
||||
default: doPushRequestV1(smsBuffer); break;
|
||||
default: doPushRequestV1(smsList); break;
|
||||
}
|
||||
}
|
||||
|
||||
private void doPushRequestV1(SmsBuffer smsBuffer) throws OCSyncException {
|
||||
if (smsBuffer == null) {
|
||||
Pair<Integer, SmsIDListResponse> response = _http.getAllSmsIds();
|
||||
if (response.second == null) {
|
||||
private 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) {
|
||||
doHttpRequest(_http.getAllSmsIds());
|
||||
if (_jsonQueryBuffer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create new SmsBuffer to get results
|
||||
smsBuffer = new SmsBuffer();
|
||||
JSONObject smsBoxes = new JSONObject();
|
||||
JSONArray inboxSmsList = null, sentSmsList = null, draftsSmsList = null;
|
||||
try {
|
||||
smsBoxes = _jsonQueryBuffer.getJSONObject("smslist");
|
||||
} catch (JSONException e) {
|
||||
try {
|
||||
_jsonQueryBuffer.getJSONArray("smslist");
|
||||
} catch (JSONException e2) {
|
||||
Log.e(OCSMSOwnCloudClient.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.i(OCSMSOwnCloudClient.TAG, "No inbox Sms received from server (doPushRequest, get SMS list)");
|
||||
}
|
||||
|
||||
try {
|
||||
sentSmsList = smsBoxes.getJSONArray("sent");
|
||||
} catch (JSONException e) {
|
||||
Log.i(OCSMSOwnCloudClient.TAG, "No sent Sms received from server (doPushRequest, get SMS list)");
|
||||
}
|
||||
|
||||
try {
|
||||
draftsSmsList = smsBoxes.getJSONArray("drafts");
|
||||
} catch (JSONException e) {
|
||||
Log.i(OCSMSOwnCloudClient.TAG, "No drafts Sms received from server (doPushRequest, get SMS list)");
|
||||
}
|
||||
|
||||
AndroidSmsFetcher fetcher = new AndroidSmsFetcher(_context);
|
||||
fetcher.setExistingInboxMessages(inboxSmsList);
|
||||
fetcher.setExistingSentMessages(sentSmsList);
|
||||
fetcher.setExistingDraftsMessages(draftsSmsList);
|
||||
|
||||
smsList = new JSONArray();
|
||||
fetcher.fetchAllMessages(smsList);
|
||||
|
||||
// Get maximum message date present in smsList to keep a step when connectivity changes
|
||||
lastMsgDate = fetcher.getLastMessageDate();
|
||||
}
|
||||
|
||||
if (smsBuffer.empty()) {
|
||||
if (smsList.length() == 0) {
|
||||
Log.i(OCSMSOwnCloudClient.TAG, "No new SMS to sync, sync done");
|
||||
return;
|
||||
}
|
||||
|
||||
Pair<Integer, SmsPushResponse> response = _http.pushSms(smsBuffer);
|
||||
PostMethod post = createPushRequest(smsList);
|
||||
if (post == null) {
|
||||
Log.e(OCSMSOwnCloudClient.TAG,"Push request for POST is null");
|
||||
throw new OCSyncException(R.string.err_sync_craft_http_request, OCSyncErrorType.IO);
|
||||
}
|
||||
|
||||
if (response.second == null) {
|
||||
Log.e(OCSMSOwnCloudClient.TAG,"Push request failed. GoLang response is empty.");
|
||||
doHttpRequest(post);
|
||||
if (_jsonQueryBuffer == null) {
|
||||
Log.e(OCSMSOwnCloudClient.TAG,"Request failed. It doesn't return a valid JSON Object");
|
||||
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());
|
||||
Boolean pushStatus;
|
||||
String pushMessage;
|
||||
try {
|
||||
pushStatus = _jsonQueryBuffer.getBoolean("status");
|
||||
pushMessage = _jsonQueryBuffer.getString("msg");
|
||||
}
|
||||
catch (JSONException e) {
|
||||
Log.e(OCSMSOwnCloudClient.TAG, "Invalid datas received from server", e);
|
||||
throw new OCSyncException(R.string.err_sync_push_request_resp, OCSyncErrorType.PARSE);
|
||||
}
|
||||
|
||||
Log.i(OCSMSOwnCloudClient.TAG, "SMS Push request said: status " +
|
||||
response.second.getStatus() + " - " + response.second.getMessage());
|
||||
Log.i(OCSMSOwnCloudClient.TAG, "LastMessageDate set to: " + smsBuffer.getLastMessageDate());
|
||||
// Push was OK, we can save the lastMessageDate which was saved to server
|
||||
(new OCSMSSharedPrefs(_context)).setLastMessageDate(lastMsgDate);
|
||||
|
||||
Log.i(OCSMSOwnCloudClient.TAG, "SMS Push request said: status " + pushStatus + " - " + pushMessage);
|
||||
}
|
||||
|
||||
SmsMessagesResponse retrieveSomeMessages(Long start, Integer limit) {
|
||||
private PostMethod createPushRequest(JSONArray smsList) throws OCSyncException {
|
||||
JSONObject obj = createPushJSONObject(smsList);
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
StringRequestEntity ent = createJSONRequestEntity(obj);
|
||||
if (ent == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return _http.pushSms(ent);
|
||||
}
|
||||
|
||||
private JSONObject createPushJSONObject(JSONArray smsList) throws OCSyncException {
|
||||
if (smsList == null) {
|
||||
Log.e(OCSMSOwnCloudClient.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.length());
|
||||
} catch (JSONException e) {
|
||||
Log.e(OCSMSOwnCloudClient.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(OCSMSOwnCloudClient.TAG,"Unsupported encoding when generating request");
|
||||
throw new OCSyncException(R.string.err_sync_create_json_request_encoding, OCSyncErrorType.PARSE);
|
||||
}
|
||||
|
||||
return requestEntity;
|
||||
}
|
||||
|
||||
JSONObject 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);
|
||||
doHttpRequest(_http.getMessages(start, limit));
|
||||
} catch (OCSyncException e) {
|
||||
_jsonQueryBuffer = null;
|
||||
Log.e(OCSMSOwnCloudClient.TAG, "Request failed.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (response.second == null) {
|
||||
if (!_jsonQueryBuffer.has("messages") || !_jsonQueryBuffer.has("last_id")) {
|
||||
Log.e(OCSMSOwnCloudClient.TAG,
|
||||
"Invalid response received from server, either messages or last_id field is missing.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return response.second;
|
||||
return _jsonQueryBuffer;
|
||||
}
|
||||
|
||||
private final OCHttpClient _http;
|
||||
private void doHttpRequest(HttpMethod req) throws OCSyncException {
|
||||
doHttpRequest(req, false);
|
||||
}
|
||||
|
||||
// skipError permit to skip invalid JSON datas
|
||||
private void doHttpRequest(HttpMethod req, Boolean skipError) throws OCSyncException {
|
||||
// Reinit the queryBuffer
|
||||
_jsonQueryBuffer = null;
|
||||
int status = 0;
|
||||
// We try maximumHttpReqTries because sometimes network is slow or unstable
|
||||
int tryNb = 0;
|
||||
|
||||
while (tryNb < OCSMSOwnCloudClient.maximumHttpReqTries) {
|
||||
tryNb++;
|
||||
|
||||
if (!_connectivityMonitor.isValid()) {
|
||||
if (tryNb == OCSMSOwnCloudClient.maximumHttpReqTries) {
|
||||
req.releaseConnection();
|
||||
throw new OCSyncException(R.string.err_sync_no_connection_available, OCSyncErrorType.IO);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
status = _http.execute(req);
|
||||
Log.i(OCSMSOwnCloudClient.TAG, "HTTP Request done at try " + tryNb);
|
||||
|
||||
// Force loop exit
|
||||
tryNb = OCSMSOwnCloudClient.maximumHttpReqTries;
|
||||
} catch (ConnectException e) {
|
||||
Log.e(OCSMSOwnCloudClient.TAG, "Unable to perform a connection to ownCloud instance", e);
|
||||
|
||||
// If it's the last try
|
||||
if (tryNb == OCSMSOwnCloudClient.maximumHttpReqTries) {
|
||||
req.releaseConnection();
|
||||
throw new OCSyncException(R.string.err_sync_http_request_connect, OCSyncErrorType.IO);
|
||||
}
|
||||
} catch (HttpException e) {
|
||||
Log.e(OCSMSOwnCloudClient.TAG, "Unable to perform a connection to ownCloud instance", e);
|
||||
|
||||
// If it's the last try
|
||||
if (tryNb == OCSMSOwnCloudClient.maximumHttpReqTries) {
|
||||
req.releaseConnection();
|
||||
throw new OCSyncException(R.string.err_sync_http_request_httpexception, OCSyncErrorType.IO);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(OCSMSOwnCloudClient.TAG, "Unable to perform a connection to ownCloud instance", e);
|
||||
|
||||
// If it's the last try
|
||||
if (tryNb == OCSMSOwnCloudClient.maximumHttpReqTries) {
|
||||
req.releaseConnection();
|
||||
throw new OCSyncException(R.string.err_sync_http_request_ioexception, OCSyncErrorType.IO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (status == HttpStatus.SC_OK) {
|
||||
String response;
|
||||
try {
|
||||
response = req.getResponseBodyAsString();
|
||||
} catch (IOException e) {
|
||||
Log.e(OCSMSOwnCloudClient.TAG, "Unable to parse server response", e);
|
||||
throw new OCSyncException(R.string.err_sync_http_request_resp, OCSyncErrorType.IO);
|
||||
}
|
||||
|
||||
// Parse the response
|
||||
try {
|
||||
_jsonQueryBuffer = new JSONObject(response);
|
||||
} catch (JSONException e) {
|
||||
if (!skipError) {
|
||||
if (response.contains("ownCloud") && response.contains("DOCTYPE")) {
|
||||
Log.e(OCSMSOwnCloudClient.TAG, "OcSMS app not enabled or ownCloud upgrade is required");
|
||||
throw new OCSyncException(R.string.err_sync_ocsms_not_installed_or_oc_upgrade_required,
|
||||
OCSyncErrorType.SERVER_ERROR);
|
||||
}
|
||||
else {
|
||||
Log.e(OCSMSOwnCloudClient.TAG, "Unable to parse server response", e);
|
||||
throw new OCSyncException(R.string.err_sync_http_request_parse_resp, OCSyncErrorType.PARSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (status == HttpStatus.SC_FORBIDDEN) {
|
||||
// Authentication failed
|
||||
throw new OCSyncException(R.string.err_sync_auth_failed, OCSyncErrorType.AUTH);
|
||||
} else {
|
||||
// Unk error
|
||||
String response;
|
||||
try {
|
||||
response = req.getResponseBodyAsString();
|
||||
} catch (IOException e) {
|
||||
Log.e(OCSMSOwnCloudClient.TAG, "Unable to parse server response", e);
|
||||
throw new OCSyncException(R.string.err_sync_http_request_resp, OCSyncErrorType.PARSE);
|
||||
}
|
||||
|
||||
Log.e(OCSMSOwnCloudClient.TAG, "Server set unhandled HTTP return code " + status);
|
||||
if (response != null) {
|
||||
Log.e(OCSMSOwnCloudClient.TAG, "Status code: " + status + ". Response message: " + response);
|
||||
} else {
|
||||
Log.e(OCSMSOwnCloudClient.TAG, "Status code: " + status);
|
||||
}
|
||||
throw new OCSyncException(R.string.err_sync_http_request_returncode_unhandled, OCSyncErrorType.SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
private static final int maximumHttpReqTries = 3;
|
||||
|
||||
private final HTTPRequestBuilder _http;
|
||||
private final Context _context;
|
||||
private final ConnectivityMonitor _connectivityMonitor;
|
||||
|
||||
private Integer _serverAPIVersion;
|
||||
private JSONObject _jsonQueryBuffer;
|
||||
|
||||
private static final String TAG = OCSMSOwnCloudClient.class.getSimpleName();
|
||||
|
||||
|
@ -1,29 +0,0 @@
|
||||
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/>.
|
||||
*/
|
||||
|
||||
public class SmsEntry {
|
||||
public int id;
|
||||
public int mailboxId;
|
||||
public int type;
|
||||
public boolean read;
|
||||
public boolean seen;
|
||||
public long date;
|
||||
public String address;
|
||||
public String body;
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
@ -18,23 +18,8 @@ package fr.unix_experience.owncloud_sms.enums;
|
||||
*/
|
||||
|
||||
public enum OCSMSNotificationType {
|
||||
SYNC(OCSMSNotificationChannel.SYNC, 0),
|
||||
SYNC_FAILED(OCSMSNotificationChannel.DEFAULT, 1),
|
||||
PERMISSION(OCSMSNotificationChannel.DEFAULT, 2);
|
||||
|
||||
private final OCSMSNotificationChannel channel;
|
||||
private final int notificationId;
|
||||
|
||||
OCSMSNotificationType(OCSMSNotificationChannel channel, int notificationId) {
|
||||
this.channel = channel;
|
||||
this.notificationId = notificationId;
|
||||
}
|
||||
|
||||
public OCSMSNotificationChannel getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
public int getNotificationId() {
|
||||
return notificationId;
|
||||
}
|
||||
SYNC,
|
||||
SYNC_FAILED,
|
||||
DEBUG,
|
||||
PERMISSION,
|
||||
}
|
||||
|
@ -1,33 +1,19 @@
|
||||
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.annotation.TargetApi;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
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
|
||||
@ -42,92 +28,80 @@ public class OCSMSNotificationUI {
|
||||
*/
|
||||
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)
|
||||
* @see #cancel(Context)
|
||||
*/
|
||||
public static void notify(Context context, String titleString, String contentString,
|
||||
String channelId, int notificationId) {
|
||||
public static void notify(Context context, String titleString,
|
||||
String contentString, int number) {
|
||||
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);
|
||||
Bitmap picture = BitmapFactory.decodeResource(res, R.drawable.ic_launcher);
|
||||
|
||||
// String ticker = (titleString.length() > 20) ? titleString.substring(0, 20) : titleString;
|
||||
|
||||
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)
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
|
||||
|
||||
// Set appropriate defaults for the notification light, sound,
|
||||
// and vibration.
|
||||
.setSmallIcon(R.drawable.notification_icon)
|
||||
.setSmallIcon(R.drawable.ic_launcher)
|
||||
.setContentTitle(title)
|
||||
.setContentText(contentString)
|
||||
|
||||
// All fields below this line are optional.
|
||||
// All fields below this line are optional.
|
||||
|
||||
// Use a default priority (recognized on devices running Android
|
||||
// 4.1 or later)
|
||||
// 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.
|
||||
// Provide a large icon, shown with the notification in the
|
||||
// notification drawer on devices running Android 3.0 or later.
|
||||
.setLargeIcon(picture)
|
||||
|
||||
// Set ticker text (preview) information for this notification.
|
||||
//.setTicker(ticker)
|
||||
|
||||
// Show a number. This is useful when stacking notifications of
|
||||
// a single type.
|
||||
.setNumber(number)
|
||||
.setStyle(new NotificationCompat.BigTextStyle()
|
||||
.bigText(contentString)
|
||||
.setBigContentTitle(title)
|
||||
.setSummaryText(titleString))
|
||||
.setAutoCancel(true)
|
||||
.setColor(context.getResources().getColor(R.color.oc_primary));
|
||||
.setAutoCancel(true);
|
||||
|
||||
notify(context, builder.build(), notificationId);
|
||||
OCSMSNotificationUI.notify(context, builder.build());
|
||||
}
|
||||
|
||||
private static void notify(Context context, Notification notification, int notificationId) {
|
||||
@TargetApi(Build.VERSION_CODES.ECLAIR)
|
||||
private static void notify(Context context, Notification notification) {
|
||||
NotificationManager nm = (NotificationManager) context
|
||||
.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
createNotificationChannels(context, nm);
|
||||
nm.notify(OCSMSNotificationUI.NOTIFICATION_TAG, notificationId, notification);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR) {
|
||||
nm.notify(OCSMSNotificationUI.NOTIFICATION_TAG, 0, notification);
|
||||
} else {
|
||||
nm.notify(OCSMSNotificationUI.NOTIFICATION_TAG.hashCode(), notification);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels any notifications of this type previously shown using
|
||||
* {@link #notify(Context, String, String, OCSMSNotificationType)}.
|
||||
* {@link #notify(Context, String, int)}.
|
||||
*/
|
||||
public static void cancel(Context context, OCSMSNotificationType type) {
|
||||
cancel(context, type.getNotificationId());
|
||||
}
|
||||
|
||||
public static void cancel(Context context, int notificationId) {
|
||||
@TargetApi(Build.VERSION_CODES.ECLAIR)
|
||||
public static void cancel(Context context) {
|
||||
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);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR) {
|
||||
nm.cancel(OCSMSNotificationUI.NOTIFICATION_TAG, 0);
|
||||
} else {
|
||||
nm.cancel(OCSMSNotificationUI.NOTIFICATION_TAG.hashCode());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ import android.database.ContentObserver;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONArray;
|
||||
|
||||
import fr.unix_experience.owncloud_sms.R;
|
||||
import fr.unix_experience.owncloud_sms.engine.ASyncSMSSync;
|
||||
import fr.unix_experience.owncloud_sms.engine.AndroidSmsFetcher;
|
||||
@ -33,7 +35,6 @@ 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 class SmsObserver extends ContentObserver implements ASyncSMSSync {
|
||||
|
||||
@ -59,13 +60,13 @@ public class SmsObserver extends ContentObserver implements ASyncSMSSync {
|
||||
}
|
||||
|
||||
AndroidSmsFetcher fetcher = new AndroidSmsFetcher(_context);
|
||||
SmsBuffer smsBuffer = fetcher.getLastMessage(MailboxID.ALL);
|
||||
JSONArray smsList = fetcher.getLastMessage(MailboxID.ALL);
|
||||
|
||||
ConnectivityMonitor cMon = new ConnectivityMonitor(_context);
|
||||
|
||||
// Synchronize if network is valid and there are SMS
|
||||
if (cMon.isValid() && (smsBuffer != null)) {
|
||||
new SyncTask(_context, smsBuffer).execute();
|
||||
if (cMon.isValid() && (smsList != null)) {
|
||||
new SyncTask(_context, smsList).execute();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,10 +43,6 @@ public class OCSMSSharedPrefs extends SharedPrefs {
|
||||
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);
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ public class PermissionChecker {
|
||||
// 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);
|
||||
OCSMSNotificationType.PERMISSION.ordinal());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -1,47 +0,0 @@
|
||||
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";
|
||||
}
|
||||
}
|
||||
}
|
@ -29,17 +29,6 @@ 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) {
|
||||
@ -54,7 +43,7 @@ public class SmsDataProvider extends ContentProvider {
|
||||
|
||||
public Cursor query(String mailBox) {
|
||||
return query(Uri.parse(mailBox),
|
||||
SmsDataProvider.messageFields,
|
||||
new String[] { "read", "date", "address", "seen", "body", "_id", "type", },
|
||||
null, null, null
|
||||
);
|
||||
}
|
||||
@ -63,7 +52,16 @@ public class SmsDataProvider extends ContentProvider {
|
||||
public Cursor queryNonExistingMessages(String mailBox, String existingIds) {
|
||||
Log.i(SmsDataProvider.TAG, "queryNonExistingMessages !");
|
||||
if (!existingIds.isEmpty()) {
|
||||
return query(Uri.parse(mailBox), SmsDataProvider.messageFields,
|
||||
return query(Uri.parse(mailBox),
|
||||
new String[] {
|
||||
"read",
|
||||
"date",
|
||||
"address",
|
||||
"seen",
|
||||
"body",
|
||||
"_id",
|
||||
"type",
|
||||
},
|
||||
"_id NOT IN (" + existingIds + ")", null, null
|
||||
);
|
||||
}
|
||||
@ -72,8 +70,18 @@ public class SmsDataProvider extends ContentProvider {
|
||||
}
|
||||
|
||||
public Cursor queryMessagesSinceDate(String mailBox, Long sinceDate) {
|
||||
return query(Uri.parse(mailBox), SmsDataProvider.messageFields,
|
||||
"date > ?", new String[] { sinceDate.toString() }, "date ASC"
|
||||
return query(Uri.parse(mailBox),
|
||||
new String[] {
|
||||
"read",
|
||||
"date",
|
||||
"address",
|
||||
"seen",
|
||||
"body",
|
||||
"_id",
|
||||
"type",
|
||||
//"length(address)" // For debug purposes
|
||||
},
|
||||
"date > ?", new String[] { sinceDate.toString() }, null
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,6 @@ 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;
|
||||
|
||||
class SmsSyncAdapter extends AbstractThreadedSyncAdapter {
|
||||
|
||||
@ -42,11 +41,8 @@ class SmsSyncAdapter extends AbstractThreadedSyncAdapter {
|
||||
@Override
|
||||
public void onPerformSync(Account account, Bundle extras, String authority,
|
||||
ContentProviderClient provider, SyncResult syncResult) {
|
||||
|
||||
if (new OCSMSSharedPrefs(getContext()).showSyncNotifications()) {
|
||||
OCSMSNotificationUI.notify(getContext(), getContext().getString(R.string.sync_title),
|
||||
getContext().getString(R.string.sync_inprogress), OCSMSNotificationType.SYNC);
|
||||
}
|
||||
OCSMSNotificationUI.notify(getContext(), getContext().getString(R.string.sync_title),
|
||||
getContext().getString(R.string.sync_inprogress), OCSMSNotificationType.SYNC.ordinal());
|
||||
|
||||
try {
|
||||
OCSMSOwnCloudClient _client = new OCSMSOwnCloudClient(getContext(), account);
|
||||
@ -56,13 +52,14 @@ class SmsSyncAdapter extends AbstractThreadedSyncAdapter {
|
||||
|
||||
// and push datas
|
||||
_client.doPushRequest(null);
|
||||
OCSMSNotificationUI.cancel(getContext(), OCSMSNotificationType.SYNC_FAILED);
|
||||
OCSMSNotificationUI.cancel(getContext());
|
||||
} catch (IllegalStateException e) {
|
||||
OCSMSNotificationUI.notify(getContext(), getContext().getString(R.string.fatal_error),
|
||||
e.getMessage(), OCSMSNotificationType.SYNC_FAILED);
|
||||
e.getMessage(), OCSMSNotificationType.SYNC_FAILED.ordinal());
|
||||
} catch (OCSyncException e) {
|
||||
OCSMSNotificationUI.cancel(getContext());
|
||||
OCSMSNotificationUI.notify(getContext(), getContext().getString(R.string.fatal_error),
|
||||
getContext().getString(e.getErrorId()), OCSMSNotificationType.SYNC_FAILED);
|
||||
getContext().getString(e.getErrorId()), OCSMSNotificationType.SYNC_FAILED.ordinal());
|
||||
if (e.getErrorType() == OCSyncErrorType.IO) {
|
||||
syncResult.stats.numIoExceptions++;
|
||||
}
|
||||
@ -75,8 +72,6 @@ class SmsSyncAdapter extends AbstractThreadedSyncAdapter {
|
||||
else {
|
||||
Log.w(SmsSyncAdapter.TAG, "onPerformSync: unhandled response");
|
||||
}
|
||||
} finally {
|
||||
OCSMSNotificationUI.cancel(getContext(), OCSMSNotificationType.SYNC);
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 657 B |
Before Width: | Height: | Size: 558 B |
Before Width: | Height: | Size: 748 B |
BIN
src/main/res/drawable-hdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1004 B |
Before Width: | Height: | Size: 840 B |
Before Width: | Height: | Size: 873 B |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 586 B |
Before Width: | Height: | Size: 398 B |
Before Width: | Height: | Size: 384 B |
Before Width: | Height: | Size: 459 B |
BIN
src/main/res/drawable-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 646 B |
Before Width: | Height: | Size: 576 B |
Before Width: | Height: | Size: 639 B |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 446 B |
Before Width: | Height: | Size: 677 B |
Before Width: | Height: | Size: 686 B |
Before Width: | Height: | Size: 900 B |
BIN
src/main/res/drawable-xhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 604 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 701 B |
Before Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 910 B |
Before Width: | Height: | Size: 1.2 KiB |
BIN
src/main/res/drawable-xxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 994 B |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 1.3 KiB |
BIN
src/main/res/drawable/ic_launcher.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
@ -1,28 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:autoMirrored="true"
|
||||
android:viewportWidth="1344"
|
||||
android:viewportHeight="1344">
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M0,0h1344v1344h-1344z"
|
||||
android:strokeLineJoin="round">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="1344"
|
||||
android:endY="1.2959057E-4"
|
||||
android:startX="163.34073"
|
||||
android:startY="1344"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#FF0082C9"
|
||||
android:offset="0" />
|
||||
<item
|
||||
android:color="#FF1CAFFF"
|
||||
android:offset="1" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
</vector>
|
@ -1,22 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="816.5869"
|
||||
android:viewportHeight="816.5869">
|
||||
<group android:translateX="20.414673"
|
||||
android:translateY="20.414673">
|
||||
<group android:translateX="131.87878"
|
||||
android:translateY="131.87878">
|
||||
<path
|
||||
android:pathData="m122.444,89.125c-18.459,0 -33.319,14.115 -33.319,31.648l0,143.74c0,17.533 14.86,31.648 33.319,31.648l38.249,0 152.528,126.434 -49.393,-126.434 125.728,0c18.459,0 33.319,-14.115 33.319,-31.648l0,-143.74c0,-17.533 -14.86,-31.648 -33.319,-31.648zM131.499,116.333 L380.501,116.333c9.089,0 16.405,5.854 16.405,13.126l0,8.539c0,7.271 -7.317,13.124 -16.405,13.124l-249.003,0c-9.089,0 -16.406,-5.852 -16.406,-13.124l0,-8.539c0,-7.271 7.317,-13.126 16.406,-13.126zM131.499,176.841 L380.501,176.841c9.089,0 16.405,5.854 16.405,13.126l0,8.537c0,7.271 -7.317,13.126 -16.405,13.126l-249.003,0c-9.089,0 -16.406,-5.854 -16.406,-13.126l0,-8.537c0,-7.271 7.317,-13.126 16.406,-13.126zM131.499,236.851 L221.453,236.851c9.089,0 16.405,7.988 16.405,15.259l0,6.404c0,7.271 -7.317,13.126 -16.405,13.126l-89.954,0c-9.089,0 -16.406,-5.854 -16.406,-13.126l0,-6.404c0,-7.271 7.317,-15.259 16.406,-15.259z"
|
||||
android:strokeAlpha="0"
|
||||
android:strokeLineJoin="miter"
|
||||
android:strokeWidth="0.25007507"
|
||||
android:fillColor="#ffffff"
|
||||
android:strokeColor="#000000"
|
||||
android:fillType="evenOdd"
|
||||
android:fillAlpha="1"
|
||||
android:strokeLineCap="butt"/>
|
||||
</group>
|
||||
</group>
|
||||
</vector>
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.7 KiB |
@ -61,9 +61,7 @@
|
||||
android:id="@+id/ocsms_logo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="24dp"
|
||||
android:paddingBottom="36dp"
|
||||
android:src="@drawable/logo"
|
||||
android:src="@drawable/login_logo"
|
||||
android:contentDescription="@string/login_logo" />
|
||||
|
||||
<LinearLayout
|
||||
@ -75,9 +73,8 @@
|
||||
android:id="@+id/oc_protocol"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:popupBackground="@color/oc_primary"
|
||||
android:entries="@array/protocol_array" />
|
||||
android:entries="@array/protocol_array">
|
||||
</Spinner>
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
@ -87,7 +84,6 @@
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/prompt_serverURI"
|
||||
android:textColor="@color/oc_white"
|
||||
android:inputType="textUri" >
|
||||
<requestFocus />
|
||||
</EditText>
|
||||
@ -103,9 +99,9 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/prompt_login"
|
||||
android:textColor="@color/oc_white"
|
||||
android:inputType="textEmailAddress"
|
||||
android:maxLines="1" />
|
||||
android:maxLines="1"
|
||||
android:singleLine="true" />
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
@ -121,7 +117,7 @@
|
||||
android:imeOptions="actionUnspecified"
|
||||
android:inputType="textPassword"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/oc_white" />
|
||||
android:singleLine="true" />
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<com.dd.processbutton.iml.ActionProcessButton
|
||||
|
@ -34,14 +34,9 @@
|
||||
android:fitsSystemWindows="true"
|
||||
tools:openDrawer="start"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<LinearLayout
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include
|
||||
layout="@layout/toolbar" />
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/main_title_welcome"
|
||||
@ -49,6 +44,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/ma_title_welcome"
|
||||
android:gravity="top"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||
|
||||
<TextView
|
||||
@ -57,16 +53,33 @@
|
||||
android:paddingRight="16dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="top"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_below="@+id/main_title_welcome"
|
||||
android:text="@string/ma_content_welcome"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/main_tv_swipe"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="top"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_below="@+id/main_tv_welcome"
|
||||
android:text="@string/ma_content_swipeaction"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||
</RelativeLayout>
|
||||
|
||||
<android.support.design.widget.NavigationView
|
||||
android:id="@+id/nav_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="start"
|
||||
android:fitsSystemWindows="true"
|
||||
app:headerLayout="@layout/nav_header_main"
|
||||
app:menu="@menu/activity_main_drawer"
|
||||
android:fitsSystemWindows="true"/>
|
||||
app:menu="@menu/activity_main_drawer"/>
|
||||
</android.support.v4.widget.DrawerLayout>
|