file_filter = res/values-<lang>/strings.xml
source_file = res/values/strings.xml
source_lang = en
-lang_map = af_ZA: af-rZA, am_ET: am-rET, ar_AE: ar-rAE, ar_BH: ar-rBH, ar_DZ: ar-rDZ, ar_EG: ar-rEG, ar_IQ: ar-rIQ, ar_JO: ar-rJO, ar_KW: ar-rKW, ar_LB: ar-rLB, ar_LY: ar-rLY, ar_MA: ar-rMA, ar_OM: ar-rOM, ar_QA: ar-rQA, ar_SA: ar-rSA, ar_SY: ar-rSY, ar_TN: ar-rTN, ar_YE: ar-rYE, arn_CL: arn-rCL, as_IN: as-rIN, az_AZ: az-rAZ, ba_RU: ba-rRU, be_BY: be-rBY, bg_BG: bg-rBG, bn_BD: bn-rBD, bn_IN: bn-rIN, bo_CN: bo-rCN, br_FR: br-rFR, bs_BA: bs-rBA, ca_ES: ca-rES, co_FR: co-rFR, cs_CZ: cs-rCZ, cy_GB: cy-rGB, da_DK: da-rDK, de_AT: de-rAT, de_CH: de-rCH, de_DE: de-rDE, de_LI: de-rLI, de_LU: de-rLU, dsb_DE: dsb-rDE, dv_MV: dv-rMV, el_GR: el-rGR, en_AU: en-rAU, en_BZ: en-rBZ, en_CA: en-rCA, en_GB: en-rGB, en_IE: en-rIE, en_IN: en-rIN, en_JM: en-rJM, en_MY: en-rMY, en_NZ: en-rNZ, en_PH: en-rPH, en_SG: en-rSG, en_TT: en-rTT, en_US: en-rUS, en_ZA: en-rZA, en_ZW: en-rZW, es_AR: es-rAR, es_BO: es-rBO, es_CL: es-rCL, es_CO: es-rCO, es_CR: es-rCR, es_DO: es-rDO, es_EC: es-rEC, es_ES: es-rES, es_GT: es-rGT, es_HN: es-rHN, es_MX: es-rMX, es_NI: es-rNI, es_PA: es-rPA, es_PE: es-rPE, es_PR: es-rPR, es_PY: es-rPY, es_SV: es-rSV, es_US: es-rUS, es_UY: es-rUY, es_VE: es-rVE, et_EE: et-rEE, eu_ES: eu-rES, fa_IR: fa-rIR, fi_FI: fi-rFI, fil_PH: fil-rPH, fo_FO: fo-rFO, fr_BE: fr-rBE, fr_CA: fr-rCA, fr_CH: fr-rCH, fr_FR: fr-rFR, fr_LU: fr-rLU, fr_MC: fr-rMC, fy_NL: fy-rNL, ga_IE: ga-rIE, gd_GB: gd-rGB, gl_ES: gl-rES, gsw_FR: gsw-rFR, gu_IN: gu-rIN, ha_NG: ha-rNG, he_IL: he-rIL, hi_IN: hi-rIN, hr_BA: hr-rBA, hr_HR: hr-rHR, hsb_DE: hsb-rDE, hu_HU: hu-rHU, hy_AM: hy-rAM, id_ID: id-rID, ig_NG: ig-rNG, ii_CN: ii-rCN, is_IS: is-rIS, it_CH: it-rCH, it_IT: it-rIT, iu_CA: iu-rCA, ja_JP: ja-rJP, ka_GE: ka-rGE, kk_KZ: kk-rKZ, kl_GL: kl-rGL, km_KH: km-rKH, kn_IN: kn-rIN, ko_KR: ko-rKR, kok_IN: kok-rIN, ku_IQ: ku-rIQ, ky_KG: ky-rKG, lb_LU: lb-rLU, lo_LA: lo-rLA, lt_LT: lt-rLT, lv_LV: lv-rLV, mi_NZ: mi-rNZ, mk_MK: mk-rMK, ml_IN: ml-rIN, mn_CN: mn-rCN, mn_MN: mn-rMN, moh_CA: moh-rCA, mr_IN: mr-rIN, ms_BN: ms-rBN, ms_MY: ms-rMY, mt_MT: mt-rMT, nb_NO: nb-rNO, ne_NP: ne-rNP, nl_BE: nl-rBE, nl_NL: nl-rNL, nn_NO: nn-rNO, nso_ZA: nso-rZA, oc_FR: oc-rFR, or_IN: or-rIN, pa_IN: pa-rIN, pl_PL: pl-rPL, prs_AF: prs-rAF, ps_AF: ps-rAF, pt_BR: pt-rBR, pt_PT: pt-rPT, qut_GT: qut-rGT, quz_BO: quz-rBO, quz_EC: quz-rEC, quz_PE: quz-rPE, rm_CH: rm-rCH, ro_RO: ro-rRO, ru_RU: ru-rRU, rw_RW: rw-rRW, sa_IN: sa-rIN, sah_RU: sah-rRU, se_FI: se-rFI, se_NO: se-rNO, se_SE: se-rSE, si_LK: si-rLK, sk_SK: sk-rSK, sl_SI: sl-rSI, sma_NO: sma-rNO, sma_SE: sma-rSE, smj_NO: smj-rNO, smj_SE: smj-rSE, smn_FI: smn-rFI, sms_FI: sms-rFI, sq_AL: sq-rAL, sr_BA: sr-rBA, sr_CS: sr-rCS, sr_ME: sr-rME, sr_RS: sr-rRS, sr@latin: sr-rSP, sv_FI: sv-rFI, sv_SE: sv-rSE, sw_KE: sw-rKE, syr_SY: syr-rSY, ta_IN: ta-rIN, ta_LK: ta-rLK, te_IN: te-rIN, tg_TJ: tg-rTJ, th_TH: th-rTH, tk_TM: tk-rTM, tn_ZA: tn-rZA, tr_TR: tr-rTR, tt_RU: tt-rRU, tzm_DZ: tzm-rDZ, ug_CN: ug-rCN, uk_UA: uk-rUA, ur_PK: ur-rPK, uz_UZ: uz-rUZ, vi_VN: vi-rVN, wo_SN: wo-rSN, xh_ZA: xh-rZA, yo_NG: yo-rNG, zh_CN: zh-rCN, zh_CN.GB2312:zh-rBG, zh_HK: zh-rHK, zh_MO: zh-rMO, zh_SG: zh-rSG, zh_TW: zh-rTW, zu_ZA: zu-rZA
+lang_map = af_ZA: af-rZA, am_ET: am-rET, ar_AE: ar-rAE, ar_BH: ar-rBH, ar_DZ: ar-rDZ, ar_EG: ar-rEG, ar_IQ: ar-rIQ, ar_JO: ar-rJO, ar_KW: ar-rKW, ar_LB: ar-rLB, ar_LY: ar-rLY, ar_MA: ar-rMA, ar_OM: ar-rOM, ar_QA: ar-rQA, ar_SA: ar-rSA, ar_SY: ar-rSY, ar_TN: ar-rTN, ar_YE: ar-rYE, arn_CL: arn-rCL, as_IN: as-rIN, az_AZ: az-rAZ, ba_RU: ba-rRU, be_BY: be-rBY, bg_BG: bg-rBG, bn_BD: bn-rBD, bn_IN: bn-rIN, bo_CN: bo-rCN, br_FR: br-rFR, bs_BA: bs-rBA, ca_ES: ca-rES, co_FR: co-rFR, cs_CZ: cs-rCZ, cy_GB: cy-rGB, da_DK: da-rDK, de_AT: de-rAT, de_CH: de-rCH, de_DE: de-rDE, de_LI: de-rLI, de_LU: de-rLU, dsb_DE: dsb-rDE, dv_MV: dv-rMV, el_GR: el-rGR, en_AU: en-rAU, en_BZ: en-rBZ, en_CA: en-rCA, en_GB: en-rGB, en_IE: en-rIE, en_IN: en-rIN, en_JM: en-rJM, en_MY: en-rMY, en_NZ: en-rNZ, en_PH: en-rPH, en_SG: en-rSG, en_TT: en-rTT, en_US: en-rUS, en_ZA: en-rZA, en_ZW: en-rZW, es_AR: es-rAR, es_BO: es-rBO, es_CL: es-rCL, es_CO: es-rCO, es_CR: es-rCR, es_DO: es-rDO, es_EC: es-rEC, es_ES: es-rES, es_GT: es-rGT, es_HN: es-rHN, es_MX: es-rMX, es_NI: es-rNI, es_PA: es-rPA, es_PE: es-rPE, es_PR: es-rPR, es_PY: es-rPY, es_SV: es-rSV, es_US: es-rUS, es_UY: es-rUY, es_VE: es-rVE, et_EE: et-rEE, eu_ES: eu-rES, fa_IR: fa-rIR, fi_FI: fi-rFI, fil_PH: fil-rPH, fo_FO: fo-rFO, fr_BE: fr-rBE, fr_CA: fr-rCA, fr_CH: fr-rCH, fr_FR: fr-rFR, fr_LU: fr-rLU, fr_MC: fr-rMC, fy_NL: fy-rNL, ga_IE: ga-rIE, gd_GB: gd-rGB, gl_ES: gl-rES, gsw_FR: gsw-rFR, gu_IN: gu-rIN, ha_NG: ha-rNG, he_IL: he-rIL, hi_IN: hi-rIN, hr_BA: hr-rBA, hr_HR: hr-rHR, hsb_DE: hsb-rDE, hu_HU: hu-rHU, hy_AM: hy-rAM, id_ID: id-rID, ig_NG: ig-rNG, ii_CN: ii-rCN, is_IS: is-rIS, it_CH: it-rCH, it_IT: it-rIT, iu_CA: iu-rCA, ja_JP: ja-rJP, ka_GE: ka-rGE, kk_KZ: kk-rKZ, kl_GL: kl-rGL, km_KH: km-rKH, kn_IN: kn-rIN, ko_KR: ko-rKR, kok_IN: kok-rIN, ku_IQ: ku-rIQ, ky_KG: ky-rKG, lb_LU: lb-rLU, lo_LA: lo-rLA, lt_LT: lt-rLT, lv_LV: lv-rLV, mi_NZ: mi-rNZ, mk_MK: mk-rMK, ml_IN: ml-rIN, mn_CN: mn-rCN, mn_MN: mn-rMN, moh_CA: moh-rCA, mr_IN: mr-rIN, ms_BN: ms-rBN, ms_MY: ms-rMY, my_MM: my, mt_MT: mt-rMT, nb_NO: nb-rNO, ne_NP: ne-rNP, nl_BE: nl-rBE, nl_NL: nl-rNL, nn_NO: nn-rNO, nso_ZA: nso-rZA, oc_FR: oc-rFR, or_IN: or-rIN, pa_IN: pa-rIN, pl_PL: pl-rPL, prs_AF: prs-rAF, ps_AF: ps-rAF, pt_BR: pt-rBR, pt_PT: pt-rPT, qut_GT: qut-rGT, quz_BO: quz-rBO, quz_EC: quz-rEC, quz_PE: quz-rPE, rm_CH: rm-rCH, ro_RO: ro-rRO, ru_RU: ru-rRU, rw_RW: rw-rRW, sa_IN: sa-rIN, sah_RU: sah-rRU, se_FI: se-rFI, se_NO: se-rNO, se_SE: se-rSE, si_LK: si-rLK, sk_SK: sk-rSK, sl_SI: sl-rSI, sma_NO: sma-rNO, sma_SE: sma-rSE, smj_NO: smj-rNO, smj_SE: smj-rSE, smn_FI: smn-rFI, sms_FI: sms-rFI, sq_AL: sq-rAL, sr_BA: sr-rBA, sr_CS: sr-rCS, sr_ME: sr-rME, sr_RS: sr-rRS, sr@latin: sr-rSP, sv_FI: sv-rFI, sv_SE: sv-rSE, sw_KE: sw-rKE, syr_SY: syr-rSY, ta_IN: ta-rIN, ta_LK: ta-rLK, te_IN: te-rIN, tg_TJ: tg-rTJ, th_TH: th-rTH, tk_TM: tk-rTM, tn_ZA: tn-rZA, tr_TR: tr-rTR, tt_RU: tt-rRU, tzm_DZ: tzm-rDZ, ug_CN: ug-rCN, uk_UA: uk-rUA, ur_PK: ur-rPK, uz_UZ: uz-rUZ, vi_VN: vi-rVN, wo_SN: wo-rSN, xh_ZA: xh-rZA, yo_NG: yo-rNG, zh_CN: zh-rCN, zh_CN.GB2312:zh-rBG, zh_HK: zh-rHK, zh_MO: zh-rMO, zh_SG: zh-rSG, zh_TW: zh-rTW, zu_ZA: zu-rZA
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<manifest package="com.owncloud.android"
- android:versionCode="103020"
- android:versionName="1.3.20" xmlns:android="http://schemas.android.com/apk/res/android">
+ android:versionCode="104000"
+ android:versionName="1.4.0" xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
-
+ <uses-permission android:name="android.permission.WAKE_LOCK"/>
+
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="13" />
</activity>
<activity android:name=".ui.activity.InstantUploadActivity">
</activity>
+ <activity android:name=".ui.activity.FailedUploadActivity" android:theme="@android:style/Theme.Dialog" android:excludeFromRecents="true"/>
<activity android:name=".Uploader" >
<intent-filter>
<action android:name="android.intent.action.SEND" >
</activity>
<activity android:name=".ui.activity.PreferencesNewSessionewSession" >
</activity>
+
+ <activity android:name="com.owncloud.android.ui.preview.PreviewImageActivity" />
+
+ <activity android:name="com.owncloud.android.ui.preview.PreviewVideoActivity"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
+ </activity>
<service
android:name=".authenticator.AccountAuthenticatorService"
</intent-filter>
</activity>
- <service android:name=".files.services.FileDownloader" >
- </service>
-
+ <service android:name=".files.services.FileDownloader" />
+ <service android:name=".files.services.FileUploader" />
+ <service android:name=".media.MediaService" />
+
<activity android:name=".ui.activity.FileDetailActivity" />
<activity android:name=".ui.activity.PinCodeActivity" />
<activity android:name=".extensions.ExtensionsAvailableActivity"></activity>
<activity android:name=".ui.activity.ConflictsResolveActivity"/>
<activity android:name=".ui.activity.GenericExplanationActivity"/>
<activity android:name=".ui.activity.ErrorsWhileCopyingHandlerActivity"/>
+
<activity android:name=".ui.activity.LogHistoryActivity"/>
- <service android:name=".files.services.FileUploader" >
- </service>
<service android:name=".files.services.InstantUploadService" />
<receiver android:name=".files.InstantUploadBroadcastReceiver">
<intent-filter>
</receiver>
<service android:name=".files.services.FileObserverService"/>
</application>
-
+
</manifest>
--- /dev/null
+## Submitting issues
+
+If you have questions about how to use ownCloud, please direct these to the [mailing list][mailinglist] or our [forum][forum]. We are also available on [IRC][irc].
+
+### Guidelines
+* [Report the issue](https://github.com/owncloud/android/issues/new) using our [template][template], it includes all the informations we need to track down the issue.
+* This repository is *only* for issues within the ownCloud Android app code. Issues in other compontents should be reported in their own repositores:
+ - [ownCloud code](https://github.com/owncloud/core/issues)
+ - [iOS client](https://github.com/owncloud/ios-issues/issues)
+ - [Desktop client](https://github.com/owncloud/mirall/issues)
+ - [ownCloud apps](https://github.com/owncloud/apps/issues) (e.g. Calendar, Contacts...)
+* Search the existing issues first, it's likely that your issue was already reported.
+
+If your issue appears to be a bug, and hasn't been reported, open a new issue.
+
+Help us to maximize the effort we can spend fixing issues and adding new features, by not reporting duplicate issues.
+
+[template]: https://raw.github.com/owncloud/android/master/issue_template.md
+[mailinglist]: https://mail.kde.org/mailman/listinfo/owncloud
+[forum]: http://forum.owncloud.org/
+[irc]: http://webchat.freenode.net/?channels=owncloud&uio=d4
+
+## Contributing to Source Code
+
+Thanks for wanting to contribute source code to ownCloud. That's great!
+
+Before we're able to merge your code into the ownCloud app for Android, you need to sign our [Contributor Agreement][agreement].
+
+### Guidelines
+* Contribute your code in the branch 'develop'. It will give us a better chance to test your code before merging it with stable code.
+* For your first contribution, start a pull request on develop and send us the signed [Contributor Agreement][agreement].
+* Keep on using pull requests for your next contributions although you own write permissions.
+
+[agreement]: http://owncloud.org/about/contributor-agreement/
+
+## Translations
+Please submit translations via [Transifex][transifex].
+
+[transifex]: https://www.transifex.com/projects/p/owncloud/
--- /dev/null
+This is the android client for [owncloud][0].
+
+Make sure you read [SETUP.md][1] when you start working on this project.
+
+[0]: https://github.com/owncloud/core
+[1]: https://raw.github.com/owncloud/android/master/SETUP.md
\ No newline at end of file
+++ /dev/null
-If you want to start development of ownCloud android client you have two way to do so
-(a) building with console
-(b) building with eclipse
-
-1. Use setup_env.sh
-2a. ant clean;ant debug
-2b. Open Eclipse and import actionbarsherlock/library project to your workspace
-
-after those space you should be good to go.
-
-HAVE FUN!
-
-NOTE: You must have 'tools' and 'platforms-tools' in your path in order to run setup_env.sh
--- /dev/null
+
+ If you want to start development of ownCloud android client you have two way to do so:
+
+ 1. Building with console:
+
+ - Use setup_env.sh or setup_env.bat
+ - NOTE: You must have git, ant/bin, android/tools in your enviroment path
+
+ 2. Building with eclipse:
+
+ - Run ant clean debug
+ - Open Eclipse and import *actionbarsherlock/library* project to your workspace
+ - NOTE: You must have 'tools' and 'platforms-tools' in your path in order to run setup_env.sh
+
+ After those actions you should be good to go.
+
+ HAVE FUN!
+
+
+
+
+
+
--- /dev/null
+###################################################################
+ ownCloud Android client
+
+ Copyright (C) 2012-2013 ownCloud Inc.
+ Copyright (C) 2012 Bartek Przybylski
+###################################################################
+
+
+###########
+# LICENSE #
+###########
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+The source distribution of this program should include a full copy
+of the GNU GPL version 2 license in the LICENSE.txt file located
+in its root directory. If not, see <http://www.gnu.org/licenses/>.
+
+
+########################
+# THIRD PARTY LICENSES #
+########################
+
+Both the source and binary distributions of this software contain
+some third party software. All the third party software included
+or linked is redistributed under the terms and conditions of their
+original licenses. These licenses are compatible the GPL license
+that govern this software, for the purposes they are being used.
+
+The third party software included and used by this project is:
+
+ * Apache JackRabbit, version 2.2.5.
+ Copyright (C) 2004-2010 The Apache Software Foundation.
+ Licensed under Apache License, Version 2.0.
+ Placed at libs/jackrabbit-webdav-2.2.5-jar-with-dependencies.jar
+ The jar file must be included in the ownCloud client APK.
+ Original license document included at libs/LICENSE.txt
+ See http://jackrabbit.apache.org/
+
+ * Transifex client.JavaMail API, version 1.4.3
+ Copyright (C) Transifex.
+ Licensed under GNU General Public License.
+ Placed at third_party/transifex-client.
+ Used as a helper tool, not included in the ownCloud client APK.
+ Original license document included at third_party/transifex-client/LICENSE.
+ See http://help.transifex.com/features/client/
+
+ * ActionBarSherlock, master branch.
+ Copyright (C) 2012 Jake Wharton.
+ Licensed under Apache License, Version 2.0.
+ The official repository is linked as a submodule in the
+ ownCloud/android repository.
+ A binary JAR file must be generated from this linked project
+ and included in the ownCloud client APK.
+ See http://http://actionbarsherlock.com/
+
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<profiles version="12">
+<profile kind="CodeFormatterProfile" name="Owncloud" version="12">
+<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="32"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
+<setting id="org.eclipse.jdt.core.compiler.source" value="1.7"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
+<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
+<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="2"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.7"/>
+<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="120"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="2"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.7"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="49"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="2"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
+</profile>
+</profiles>
--- /dev/null
+### Expected behaviour
+Tell us what should happen
+
+### Actual behaviour
+Tell us what happens instead
+
+### Steps to reproduce
+1.
+2.
+3.
+
+### Environment data
+Android version:
+
+Device model:
+
+Stock or customized system:
+
+ownCloud app version:
+
+ownCloud server version:
+
+### Logs
+#### Web server error log
+```
+Insert your webserver log here
+```
+
+#### ownCloud log (data/owncloud.log)
+```
+Insert your ownCloud log here
+```
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>com.owncloud.android</groupId>
+ <artifactId>owncloud</artifactId>
+ <version>1.3.21-SNAPSHOT</version>
+ <packaging>apk</packaging>
+ <name>Owncloud Android</name>
+
+ <properties>
+ <java-version>1.6</java-version>
+ <google.android-version>4.1.1.4</google.android-version>
+ <google.android.support-version>r7</google.android.support-version>
+ <actionbarsherlock-version>4.2.0</actionbarsherlock-version>
+ </properties>
+
+ <url>https://github.com/owncloud/android</url>
+ <description>Owncloud for Android</description>
+ <scm>
+ <connection>scm:git:git@github.com:owncloud/android.git</connection>
+ <developerConnection>scm:git:git@github.com:owncloud/android.git</developerConnection>
+ <url>https://github.com/owncloud/android</url>
+ </scm>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>com.google.android</groupId>
+ <artifactId>android</artifactId>
+ <version>${google.android-version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.android</groupId>
+ <artifactId>support-v4</artifactId>
+ <version>${google.android.support-version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.actionbarsherlock</groupId>
+ <artifactId>actionbarsherlock</artifactId>
+ <version>${actionbarsherlock-version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.actionbarsherlock</groupId>
+ <artifactId>actionbarsherlock</artifactId>
+ <version>${actionbarsherlock-version}</version>
+ <type>apklib</type>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>jackrabbit-webdav</artifactId>
+ <version>2.5.2</version>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+
+ <sourceDirectory>src</sourceDirectory>
+
+ <plugins>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.0</version>
+ <configuration>
+ <source>${java-version}</source>
+ <target>${java-version}</target>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>com.jayway.maven.plugins.android.generation2</groupId>
+ <artifactId>android-maven-plugin</artifactId>
+ <version>3.5.0</version>
+ <configuration>
+ <sdk>
+ <!-- platform or api level (api level 4 = platform 1.6)-->
+ <path>${env.ANDROID_HOME}</path>
+ <platform>17</platform>
+ </sdk>
+ </configuration>
+ <extensions>true</extensions>
+ </plugin>
+
+ </plugins>
+
+ </build>
+
+</project>
+
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/main_audio_view"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:orientation="vertical">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:text="Now playing:"
+ android:textSize="25sp"
+ android:textStyle="bold"
+ />
+ <TextView
+ android:id="@+id/now_playing_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="20dip"
+ android:layout_marginLeft="10dip"
+ android:layout_marginRight="10dip"
+ android:layout_gravity="center"
+ android:text="Now playing.."
+ android:textSize="16sp"
+ android:textStyle="italic"
+ />
+</LinearLayout>
\ No newline at end of file
--- /dev/null
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"\r
+ android:id="@+id/failed_upload_message_view"\r
+ android:layout_width="fill_parent"\r
+ android:layout_height="fill_parent"\r
+ android:background="@color/owncloud_white"\r
+ android:orientation="vertical" >\r
+\r
+ <TextView android:id="@+id/faild_upload_message" \r
+ android:layout_width="match_parent"\r
+ android:layout_height="wrap_content"\r
+ android:minWidth="100dp"/>\r
+ \r
+ <Button\r
+ android:id="@+id/failed_uploadactivity_close_button"\r
+ android:layout_width="fill_parent"\r
+ android:layout_height="wrap_content"\r
+ android:text="Dismiss" />\r
+\r
+</LinearLayout>
\ No newline at end of file
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:background="@color/owncloud_white" >
-
- <ScrollView
- android:id="@+id/fdScrollView"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" >
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content" >
-
- <RelativeLayout
- android:id="@+id/fdFileHeaderContainer"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="16dp"
- android:layout_marginTop="4dp" >
-
- <ImageView
- android:id="@+id/fdIcon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/file" />
-
- <TextView
- android:id="@+id/fdFilename"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_toRightOf="@+id/fdIcon"
- android:text="file.name"
- android:textAppearance="?android:attr/textAppearanceLarge" />
- </RelativeLayout>
-
- <RelativeLayout
- android:id="@+id/fdDetailsContainer"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@+id/fdFileHeaderContainer" >
-
- <RelativeLayout
- android:id="@+id/fdLabelContainer"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
- android:layout_marginLeft="16dp" >
-
- <TextView
- android:id="@+id/fdTypeLabel"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="24dp"
- android:text="@string/filedetails_type"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <TextView
- android:id="@+id/fdSizeLabel"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/fdTypeLabel"
- android:layout_marginTop="12dp"
- android:text="@string/filedetails_size"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <TextView
- android:id="@+id/fdCreatedLabel"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/fdSizeLabel"
- android:layout_marginTop="12dp"
- android:text="@string/filedetails_created"
- android:visibility="gone"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <TextView
- android:id="@+id/fdModifiedLabel"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/fdCreatedLabel"
- android:layout_marginTop="12dp"
- android:text="@string/filedetails_modified"
- android:textAppearance="?android:attr/textAppearanceMedium" />
- </RelativeLayout>
-
- <RelativeLayout
- android:id="@+id/fdValueContainer"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_marginLeft="12dp"
- android:layout_toRightOf="@+id/fdLabelContainer" >
-
- <TextView
- android:id="@+id/fdType"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="24dp"
- android:text="JPG Image"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <TextView
- android:id="@+id/fdSize"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/fdType"
- android:layout_marginTop="12dp"
- android:text="389 KB"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <TextView
- android:id="@+id/fdCreated"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/fdSize"
- android:layout_marginTop="12dp"
- android:visibility="gone"
- android:text="2012/05/18 12:23 PM"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <TextView
- android:id="@+id/fdModified"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/fdCreated"
- android:layout_marginTop="12dp"
- android:text="2012/05/19 02:56 PM"
- android:textAppearance="?android:attr/textAppearanceMedium" />
- </RelativeLayout>
-
- </RelativeLayout>
-
- <RelativeLayout
- android:id="@+id/fdPreviewAndDL"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@+id/fdDetailsContainer"
- android:gravity="center_horizontal" >
-
- <CheckBox
- android:id="@+id/fdKeepInSync"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerHorizontal="true"
- android:text="@string/fd_keep_in_sync" />
-
- <ImageView
- android:id="@+id/fdPreview"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_below="@id/fdKeepInSync"
- android:layout_centerHorizontal="true"
- android:layout_marginTop="16dp"
- android:src="@drawable/owncloud_logo" />
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/fdPreview"
- android:orientation="vertical" >
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal" >
-
- <Button
- android:id="@+id/fdRemoveBtn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dp"
- android:text="@string/common_remove" />
-
- <Button
- android:id="@+id/fdOpenBtn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dp"
- android:text="@string/filedetails_open" />
-
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal">
-
- <Button
- android:id="@+id/fdDownloadBtn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dp"
- android:text="@string/filedetails_download" />
-
- <Button
- android:id="@+id/fdRenameBtn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dp"
- android:text="@string/common_rename" />
-
- </LinearLayout>
-<!--
- <Button
- android:id="@+id/fdShareBtn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dp"
- android:text="@string/common_share" />
- -->
-
- </LinearLayout>
- </RelativeLayout>
-
- </RelativeLayout>
- </ScrollView>
-
-</RelativeLayout>
\ No newline at end of file
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/fdScrollView"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" >
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <RelativeLayout
+ android:id="@+id/fdFileHeaderContainer"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="16dp"
+ android:layout_marginTop="4dp" >
+
+ <ImageView
+ android:id="@+id/fdIcon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/file" />
+
+ <TextView
+ android:id="@+id/fdFilename"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_toRightOf="@+id/fdIcon"
+ android:text="@string/placeholder_filename"
+ android:textAppearance="?android:attr/textAppearanceLarge" />
+
+ </RelativeLayout>
+
+ <RelativeLayout
+ android:id="@+id/fdDetailsContainer"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/fdFileHeaderContainer" >
+
+ <RelativeLayout
+ android:id="@+id/fdLabelContainer"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:layout_marginLeft="16dp" >
+
+ <TextView
+ android:id="@+id/fdTypeLabel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="24dp"
+ android:text="@string/filedetails_type"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/fdSizeLabel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/fdTypeLabel"
+ android:layout_marginTop="12dp"
+ android:text="@string/filedetails_size"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/fdCreatedLabel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/fdSizeLabel"
+ android:layout_marginTop="12dp"
+ android:text="@string/filedetails_created"
+ android:visibility="gone"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/fdModifiedLabel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/fdCreatedLabel"
+ android:layout_marginTop="12dp"
+ android:text="@string/filedetails_modified"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+ </RelativeLayout>
+
+ <RelativeLayout
+ android:id="@+id/fdValueContainer"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_marginLeft="12dp"
+ android:layout_toRightOf="@+id/fdLabelContainer" >
+
+ <TextView
+ android:id="@+id/fdType"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="24dp"
+ android:text="@string/placeholder_filetype"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/fdSize"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/fdType"
+ android:layout_marginTop="12dp"
+ android:text="@string/placeholder_filesize"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/fdCreated"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/fdSize"
+ android:layout_marginTop="12dp"
+ android:visibility="gone"
+ android:text="@string/placeholder_timestamp"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/fdModified"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/fdCreated"
+ android:layout_marginTop="12dp"
+ android:text="@string/placeholder_timestamp"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ </RelativeLayout>
+
+ </RelativeLayout>
+
+ <RelativeLayout
+ android:id="@+id/fdProgressAndControl"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/fdDetailsContainer"
+ android:gravity="center_horizontal"
+ android:layout_margin="16dp"
+ >
+
+ <CheckBox
+ android:id="@+id/fdKeepInSync"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:text="@string/fd_keep_in_sync" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/fdKeepInSync"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/fdProgressText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/downloader_download_in_progress_ticker"
+ />
+
+ <ProgressBar android:id="@+id/fdProgressBar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:progressDrawable="@android:drawable/progress_horizontal"
+ android:indeterminate="false"
+ android:indeterminateOnly="false"
+ />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:layout_marginTop="12dp"
+ >
+
+ <Button
+ android:id="@+id/fdDownloadBtn"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/filedetails_download" />
+
+ <Button
+ android:id="@+id/fdOpenBtn"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/filedetails_open" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:layout_marginTop="12dp"
+ >
+
+ <Button
+ android:id="@+id/fdRenameBtn"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/common_rename" />
+
+ <Button
+ android:id="@+id/fdRemoveBtn"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/common_remove" />
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ </RelativeLayout>
+
+ </RelativeLayout>
+
+</ScrollView>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ownCloud Android client application
+
+ Copyright (C) 2012-2013 ownCloud Inc.
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:layout_gravity="center"
+ android:gravity="center_vertical"
+ android:padding="20dp"
+ >
+
+ <TextView
+ android:id="@+id/progressText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/downloader_not_downloaded_yet"
+ android:layout_marginBottom="15dp"
+ />
+
+ <ProgressBar android:id="@+id/progressBar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:progressDrawable="@android:drawable/progress_horizontal"
+ android:indeterminate="false"
+ android:indeterminateOnly="false"
+ android:layout_marginBottom="15dp"
+ />
+
+ <Button
+ android:id="@+id/cancelBtn"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/common_cancel"
+ android:layout_marginBottom="15dp"
+ />
+
+ <ImageView
+ android:id="@+id/error_image"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="0dp"
+ android:layout_gravity="center_horizontal"
+ android:contentDescription="@string/downloader_download_failed_ticker"
+ android:src="@drawable/image_fail" />
+
+ <TextView
+ android:id="@+id/errorText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_margin="40dp"
+ android:text="@string/downloader_download_failed_ticker"
+ />
+
+</LinearLayout>
+
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ownCloud Android client application
+
+ Copyright (C) 2012-2013 ownCloud Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/top"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/owncloud_white"
+ android:gravity="center"
+ tools:context=".ui.fragment.FilePreviewFragment" >
+
+ <FrameLayout
+ android:id="@+id/visual_area"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_alignParentTop="true"
+ android:layout_above="@+id/media_controller"
+ >
+
+ <ImageView
+ android:id="@+id/image_preview"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_margin="16dp"
+ android:layout_gravity="center"
+ android:contentDescription="@string/preview_image_description"
+ android:src="@drawable/owncloud_logo" />
+
+ <VideoView
+ android:id="@+id/video_preview"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:visibility="gone"
+ />
+
+ </FrameLayout>
+
+ <com.owncloud.android.media.MediaControlView
+ android:id="@id/media_controller"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ />
+
+</RelativeLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ownCloud Android client application
+
+ Copyright (C) 2012-2013 ownCloud Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:paddingTop="4dip"
+ android:orientation="horizontal"
+ >
+
+ <ImageButton
+ android:id="@+id/rewindBtn"
+ style="@android:style/MediaButton.Rew"
+ android:contentDescription="@string/media_rewind_description"
+ />
+ <ImageButton
+ android:id="@+id/playBtn"
+ style="@android:style/MediaButton.Play"
+ android:contentDescription="@string/media_play_pause_description"
+ />
+ <ImageButton
+ android:id="@+id/forwardBtn"
+ style="@android:style/MediaButton.Ffwd"
+ android:contentDescription="@string/media_forward_description"
+ />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <TextView
+ android:id="@+id/currentTimeText"
+ android:textSize="14sp"
+ android:textStyle="bold"
+ android:paddingTop="4dip"
+ android:paddingStart="4dip"
+ android:layout_gravity="center_horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingEnd="4dip"
+ android:text="@string/placeholder_media_time"
+ />
+
+ <SeekBar
+ android:id="@+id/progressBar"
+ style="?android:attr/progressBarStyleHorizontal"
+ android:layout_width="0dip"
+ android:layout_weight="1"
+ android:layout_height="32dip"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentEnd="true" />
+
+ <TextView android:id="@+id/totalTimeText"
+ android:textSize="14sp"
+ android:textStyle="bold"
+ android:paddingTop="4dip"
+ android:paddingEnd="4dip"
+ android:layout_gravity="center_horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingStart="4dip"
+ android:text="@string/placeholder_media_time"
+ />
+
+ </LinearLayout>
+
+</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ownCloud Android client application
+
+ Copyright (C) 2012-2013 ownCloud Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <android.support.v4.view.ViewPager
+ android:id="@+id/fragmentPager"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ />
+
+ <!-- LinearLayout
+ android:id="@+id/fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+ <!- - Preview: layout=@layout/preview_image_fragment - ->
+ </LinearLayout -->
+
+</LinearLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ownCloud Android client application
+
+ Copyright (C) 2012-2013 ownCloud Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+-->
+
+<!--
+ ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/fdScrollView"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@color/owncloud_white"
+ android:gravity="center_horizontal"
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/top"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@color/owncloud_white"
+ tools:context=".ui.fragment.PreviewImageFragment" >
+
+ <ProgressBar
+ android:id="@+id/progressWheel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:indeterminate="true"
+ android:indeterminateOnly="true"
+ android:layout_centerInParent="true"
+ />
+
+ <ImageView
+ android:id="@+id/image"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="0dp"
+ android:layout_centerInParent="true"
+ android:contentDescription="@string/preview_image_description"
+ android:src="@drawable/image_fail" />
+
+ <TextView
+ android:id="@+id/message"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_below="@id/image"
+ android:layout_margin="40dp"
+ android:text="@string/placeholder_sentence"
+ />
+
+</RelativeLayout>
\ No newline at end of file
android:layout_height="wrap_content" android:orientation="vertical"
android:layout_width="wrap_content" android:background="#fefefe"
android:gravity="center">
- <TextView android:layout_width="fill_parent" android:text="Choose upload directory"
+ <TextView android:layout_width="fill_parent" android:text="@string/uploader_top_message"
android:layout_height="wrap_content" android:id="@+id/textView1" android:textColor="@android:color/black"
android:gravity="center_horizontal"></TextView>
<FrameLayout android:layout_height="fill_parent"
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" >
+
+ <VideoView android:id="@+id/videoPlayer"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center" />
+
+</FrameLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ownCloud Android client application
+
+ Copyright (C) 2012 Bartek Przybylski
+ Copyright (C) 2012-2013 ownCloud Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:id="@+id/action_open_file_with" android:title="@string/filedetails_open" android:icon="@android:drawable/ic_menu_edit" android:orderInCategory="1" />
+ <item android:id="@+id/action_download_file" android:title="@string/filedetails_download" android:orderInCategory="1" />
+ <item android:id="@+id/action_cancel_download" android:title="@string/common_cancel_download" android:icon="@android:drawable/ic_menu_close_clear_cancel" android:orderInCategory="1" />
+ <item android:id="@+id/action_cancel_upload" android:title="@string/common_cancel_upload" android:icon="@android:drawable/ic_menu_close_clear_cancel" android:orderInCategory="1" />
+ <item android:id="@+id/action_rename_file" android:title="@string/common_rename" android:icon="@android:drawable/ic_menu_set_as" android:orderInCategory="1" />
+ <item android:id="@+id/action_remove_file" android:title="@string/common_remove" android:icon="@android:drawable/ic_menu_delete" android:orderInCategory="1" />
+ <item android:id="@+id/action_see_details" android:title="@string/actionbar_see_details" android:icon="@android:drawable/ic_menu_view" android:orderInCategory="1" />
+
+</menu>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ownCloud Android client application
-
- Copyright (C) 2012 Bartek Przybylski
- Copyright (C) 2012-2013 ownCloud Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
--->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-
- <item android:id="@+id/open_file_item"
- android:title="@string/filedetails_open"
- android:icon="@android:drawable/ic_menu_edit"
- />
-
- <item android:id="@+id/download_file_item"
- android:title="@string/filedetails_download"
- />
-
- <item android:id="@+id/cancel_download_item"
- android:title="@string/common_cancel_download"
- android:icon="@android:drawable/ic_menu_close_clear_cancel"
- />
-
- <item android:id="@+id/cancel_upload_item"
- android:title="@string/common_cancel_upload"
- android:icon="@android:drawable/ic_menu_close_clear_cancel"
- />
-
- <item android:id="@+id/rename_file_item"
- android:title="@string/common_rename"
- android:icon="@android:drawable/ic_menu_set_as"
- />
-
- <item android:id="@+id/remove_file_item"
- android:title="@string/common_remove"
- android:icon="@android:drawable/ic_menu_delete"
- />
-
-</menu>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ownCloud Android client application
+
+ Copyright (C) 2012 Bartek Przybylski
+ Copyright (C) 2012-2013 ownCloud Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+-->
+<menu
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/action_sync_account" android:title="@string/actionbar_sync" android:icon="@drawable/ic_action_refresh" android:orderInCategory="2" />
+ <item android:id="@+id/action_create_dir" android:title="@string/actionbar_mkdir" android:icon="@drawable/ic_action_create_dir" android:orderInCategory="2" />
+ <item android:id="@+id/action_upload" android:title="@string/actionbar_upload" android:icon="@drawable/ic_action_upload" android:orderInCategory="2" />
+ <item android:id="@+id/action_settings" android:title="@string/actionbar_settings" android:icon="@android:drawable/ic_menu_preferences" android:orderInCategory="2" />
+ <item android:id="@+id/action_about_app" android:title="@string/about_title" android:icon="@android:drawable/ic_menu_info_details" android:orderInCategory="2" />
+
+ <!-- <item android:id="@+id/search" android:title="@string/actionbar_search" android:icon="@drawable/ic_action_search"></item>-->
+</menu>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ownCloud Android client application
-
- Copyright (C) 2012 Bartek Przybylski
- Copyright (C) 2012-2013 ownCloud Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
--->
-<menu
- xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:id="@+id/startSync" android:title="@string/actionbar_sync" android:icon="@drawable/ic_action_refresh"></item>
- <item android:id="@+id/createDirectoryItem" android:title="@string/actionbar_mkdir" android:icon="@drawable/ic_action_create_dir"></item>
-
- <!-- <item android:id="@+id/search" android:title="@string/actionbar_search" android:icon="@drawable/ic_action_search"></item>-->
- <item android:id="@+id/action_upload" android:title="@string/actionbar_upload" android:icon="@drawable/ic_action_upload"></item>
- <item android:id="@+id/action_settings" android:title="@string/actionbar_settings" android:icon="@android:drawable/ic_menu_preferences"></item>
-</menu>
--- /dev/null
+<?xml version='1.0' encoding='UTF-8'?>
+<resources>
+ <string name="main_settings">Instellings</string>
+ <string name="actionbar_settings">Instellings</string>
+ <string name="auth_username">Gebruikersnaam</string>
+ <string name="auth_password">Wagwoord</string>
+ <string name="setup_hint_username">Gebruikersnaam</string>
+ <string name="setup_hint_password">Wagwoord</string>
+</resources>
--- /dev/null
+<?xml version='1.0' encoding='UTF-8'?>
+<resources/>
<string name="actionbar_upload">Качване</string>
<string name="actionbar_upload_files">Файлове</string>
<string name="actionbar_settings">Настройки</string>
+ <string name="prefs_category_general">Общи</string>
<string name="auth_host_url">Уеб адрес</string>
<string name="auth_password">Парола</string>
<string name="sync_string_files">Файлове</string>
<string name="uploader_btn_upload_text">Качване</string>
<string name="uploader_wrn_no_account_quit_btn_text">Изход</string>
<string name="filedetails_download">Изтегляне</string>
+ <string name="common_cancel_upload">Спри качването</string>
<string name="common_error">Грешка</string>
<string name="sync_string_contacts">Контакти</string>
<string name="common_share">Споделяне</string>
<string name="setup_title">Mit Ihrer %1$s verbinden</string>
<string name="setup_btn_connect">Verbinden</string>
<string name="uploader_btn_upload_text">Hochladen</string>
+ <string name="uploader_top_message">Wähle Zielverzeichnis:</string>
<string name="uploader_wrn_no_account_title">Kein Konto gefunden</string>
<string name="uploader_wrn_no_account_text">Es sind keine %1$s-Konten auf Ihrem Gerät eingerichtet. Bitte richten Sie zuerst ein Konto ein.</string>
<string name="uploader_wrn_no_account_setup_btn_text">Einrichten</string>
<string name="common_save_exit">Speichern & Schließen</string>
<string name="common_exit">%1$s verlassen</string>
<string name="common_error">Fehler</string>
+ <string name="common_loading">Wird geladen …</string>
+ <string name="common_error_unknown">Unbekannter Fehler</string>
<string name="about_title">Über</string>
<string name="delete_account">Account löschen</string>
<string name="create_account">Account erstellen</string>
<string name="downloader_download_succeeded_content">%1$s wurde erfolgreich heruntergeladen</string>
<string name="downloader_download_failed_ticker">Herunterladen fehlgeschlagen</string>
<string name="downloader_download_failed_content">Herunterladen von %1$s konnte nicht abgeschlossen werden</string>
+ <string name="downloader_not_downloaded_yet">Noch nicht heruntergeladen</string>
<string name="common_choose_account">Konto auswählen</string>
<string name="sync_string_contacts">Kontakte</string>
<string name="sync_fail_ticker">Synchronisation fehlgeschlagen</string>
<string name="pincode_wrong">Falsche App-PIN</string>
<string name="pincode_removed">Die App-PIN wurde entfernt</string>
<string name="pincode_stored">Die App-PIN wurde gespeichert</string>
+ <string name="media_notif_ticker">"%1$s Musik Player"</string>
+ <string name="media_state_playing">"%1$s (wird abgespielt)"</string>
+ <string name="media_state_loading">"%1$s (wird geladen)"</string>
+ <string name="media_event_done">"%1$s Wiedergabe beendet"</string>
+ <string name="media_err_nothing_to_play">Keine Media-Datei gefunden</string>
+ <string name="media_err_no_account">Ungültiger Account</string>
+ <string name="media_err_not_in_owncloud">Datei ist nicht in einem gültigen Account</string>
+ <string name="media_err_unsupported">Nicht unterstützter Medien-Codec</string>
+ <string name="media_err_io">Media-Datei konnte nicht gelesen werden</string>
+ <string name="media_err_malformed">Die Media-Datei ist noch nicht kodiert</string>
+ <string name="media_err_timeout">Zeitüberschreitung ist beim Abspielen aufgetreten</string>
+ <string name="media_err_invalid_progressive_playback">Media-Datei konnte nicht gestreamt werden</string>
+ <string name="media_err_unknown">Media-Datei kann nicht vom Standard Player wiedergegeben werden</string>
+ <string name="media_err_security_ex">Sicherheits-Fehler ist beim Abspielen aufgetreten %1$s</string>
+ <string name="media_err_io_ex">Eingabe-Fehler ist beim Abspielen aufgetreten %1$s</string>
+ <string name="media_err_unexpected">Unerwarteter Fehler bei der Wiedergabe %1$s</string>
+ <string name="media_rewind_description">Zurückspulen</string>
+ <string name="media_play_pause_description">Wiedergabe oder Pause</string>
+ <string name="media_forward_description">Vorspulen</string>
+
<string-array name="prefs_trackmydevice_intervall_keys">
<item>15 Minuten</item>
<item>30 Minuten</item>
<string name="extensions_avail_title">Erweiterung verfügbar!</string>
<string name="extensions_avail_message">Scheinbar unterstützt Ihr Server weitere Erweiterungen. Möchten Sie die verfügbaren Erweiterungen für Android sehen?</string>
<string name="fd_keep_in_sync">Datei aktuell halten</string>
- <string name="common_share">Freigeben</string>
+ <string name="common_share">Teilen</string>
<string name="common_rename">Umbenennen</string>
<string name="common_remove">Löschen</string>
<string name="confirmation_remove_alert">Möchten Sie %1$s wirklich löschen?</string>
<string name="conflict_keep_both">Beide behalten</string>
<string name="conflict_overwrite">Überschreiben</string>
<string name="conflict_dont_upload">Nicht hochladen</string>
+ <string name="preview_image_description">Bildvorschau</string>
+ <string name="preview_image_error_unknown_format">Das Bild kann nicht angezeigt werden</string>
+ <string name="preview_image_error_out_of_memory">"Nicht genug Speicherplatz um das Bild anzuzeigen</string>
<string name="actionbar_failed_instant_upload">Fehlgeschlagene Sofortuploads</string>
<string name="failed_upload_headline_text">Fehlgeschlagene Sofortuploads</string>
<string name="setup_title">Mit Deiner %1$s verbinden</string>
<string name="setup_btn_connect">Verbinden</string>
<string name="uploader_btn_upload_text">Hochladen</string>
+ <string name="uploader_top_message">Wähle Zielverzeichnis:</string>
<string name="uploader_wrn_no_account_title">Kein Account gefunden</string>
<string name="uploader_wrn_no_account_text">Es sind keine %1$s-Accounts auf Deinem Gerät eingerichtet. Bitte richte zuerst ein Konto ein.</string>
<string name="uploader_wrn_no_account_setup_btn_text">Einrichten</string>
<string name="sync_fail_ticker">Synchronisation fehlgeschlagen</string>
<string name="sync_fail_content">Bei der Synchronisation konnte %1$s nicht übertragen werden</string>
<string name="sync_conflicts_in_favourites_ticker">Konflikte gefunden</string>
- <string name="sync_conflicts_in_favourites_content">%1$d synchrongehaltene Dateien konnte nicht synchronisiert werden.</string>
- <string name="sync_fail_in_favourites_ticker">Synchronhalten schlug fehl.</string>
+ <string name="sync_conflicts_in_favourites_content">%1$d synchron zu haltende Dateien konnte nicht synchronisiert werden.</string>
+ <string name="sync_fail_in_favourites_ticker">Synchron halten schlug fehl.</string>
<string name="sync_fail_in_favourites_content">Inhalte von %1$d konnte nicht synchronisiert werden (%2$d Konflikte)</string>
<string name="use_ssl">Sichere Verbindung benutzen</string>
<string name="location_no_provider">%1$s kann Dein Gerät nicht verfolgen. Bitte überprüfe Deine Standorteinstellungen</string>
<string name="sync_file_fail_msg">Die entfernte Datei konnte nicht überprüft werden</string>
<string name="sync_file_nothing_to_do_msg">Dateiinhalte bereits synchronisiert</string>
<string name="create_dir_fail_msg">Das Verzeichnis konnte nicht erstellt werden.</string>
- <string name="wait_a_moment">Bitte warten Sie einen Moment.</string>
+ <string name="wait_a_moment">Bitte warte einen Moment.</string>
<string name="filedisplay_unexpected_bad_get_content">Ein unerwartetes Problem ist aufgetreten. Bitte versuche, die Datei in einer anderen App zu öffnen</string>
<string name="filedisplay_no_file_selected">Es wurde keine Datei ausgewählt.</string>
<string name="ssl_validator_title">Warnung</string>
<string name="failed_upload_headline_delete_all_btn">Ausgewählte löschen </string>
<string name="failed_upload_retry_text">Versuche ausgewählte erneut hochzuladen</string>
<string name="failed_upload_load_more_images">Weitere Bilder laden</string>
-<string name="failed_upload_retry_do_nothing_text">Upload nicht gestarted, Sie sind nicht online für ein Softupload</string>
+ <string name="failed_upload_retry_do_nothing_text">Upload nicht gestarted, Sie sind nicht online für ein Softupload</string>
+ <string name="failed_upload_failure_text">Fehlermeldung: </string>
+ <string name="failed_upload_quota_exceeded_text">Bitte überprüfen sie ihre Serverkonfiguration, möglicherweise ist ihre Upload Limit überschritten</string>
</resources>
<string name="uploader_wrn_no_account_quit_btn_text">Irten</string>
<string name="uploader_wrn_no_content_title">Ez dago igotzeko edukirik</string>
<string name="uploader_wrn_no_content_text">Ez da edukirik jaso. Ez dago ezer igotzeko.</string>
- <string name="uploader_error_forbidden_content">ownCloudek ez du baimenik partekatutako edukian sartzeko</string>
+ <string name="uploader_error_forbidden_content">%1$s-(e)k ez du baimenik elkarbanatutako edukian sartzeko</string>
<string name="uploader_info_uploading">Igotzen</string>
<string name="uploader_btn_create_dir_text">Sortu igotzeko karpeta bat</string>
<string name="file_list_empty">Ez dago fitxategirik karpeta honetan.\nFitxategi berriak \"Igo\" menu aukerarekin gehi daitezke.</string>
<string name="ssl_validator_label_ST">Estatua:</string>
<string name="ssl_validator_label_L">Kokapena:</string>
<string name="ssl_validator_label_validity">Baliozkotasuna:</string>
+ <string name="ssl_validator_label_validity_from">Noiztik:</string>
+ <string name="ssl_validator_label_validity_to">Noiz arte:</string>
<string name="ssl_validator_label_signature">Sinadura:</string>
<string name="ssl_validator_label_signature_algorithm">Algoritmoa:</string>
<string name="text_placeholder">Hau leku-marka da</string>
<string name="main_settings">تنظیمات</string>
<string name="main_tit_accsetup">نصب حساب کاربری</string>
<string name="main_wrn_accsetup">حساب کاربری ownCloud در دستگاه شما وجود ندارد. برای استفاده از این برنامه میبایست یکی ایجاد کنید.</string>
+ <string name="actionbar_sync">بازنمایی</string>
<string name="actionbar_upload">بارگزاری</string>
<string name="actionbar_upload_files">پروندهها</string>
<string name="actionbar_mkdir">ایجاد پوشه</string>
<string name="actionbar_search">جستوجو</string>
<string name="actionbar_settings">تنظیمات</string>
<string name="prefs_category_general">عمومی</string>
+ <string name="prefs_category_trackmydevice">ردیابی دستگاه</string>
+ <string name="prefs_add_session">ایجاد جلسه جدید</string>
+ <string name="prefs_create_img_thumbnails">ایجاد پیش نمایش تصاویر</string>
<string name="prefs_select_oc_account">انتخاب یک حساب</string>
+ <string name="prefs_trackmydevice">ردیابی دستگاه</string>
+ <string name="prefs_trackmydevice_summary_off">برنامه را فعال کنید تا محل دستگاه شما پیگیری شود</string>
+ <string name="prefs_trackmydevice_interval">به روز رسانی بازه</string>
<string name="prefs_accounts">حسابها</string>
<string name="auth_host_url">آدرس ownCloud </string>
<string name="auth_username">نام کاربری</string>
<string name="uploader_wrn_no_content_title">هیچ مطلبی بارگزاری نشده است</string>
<string name="uploader_wrn_no_content_text">هیچ مطلبی دریافت نشده است. هیچچیزی بارگزاری نشده.</string>
<string name="uploader_info_uploading">در حال بارگزاری</string>
+ <string name="uploader_btn_create_dir_text">ایجاد دایرکتوری برای بارگذاری</string>
+ <string name="filedetails_size">اندازه</string>
+ <string name="filedetails_type">نوع:</string>
+ <string name="filedetails_created">ایجاد شده توسط:</string>
+ <string name="filedetails_modified">تغییر یافته توسط:</string>
<string name="filedetails_download">بارگیری</string>
+ <string name="filedetails_sync_file">بازنمایی</string>
<string name="filedetails_redownload">بارگزاری دوباره</string>
<string name="common_yes">بله</string>
+ <string name="common_no">نه</string>
<string name="common_ok">باشه</string>
<string name="common_cancel_upload">متوقف کردن بار گذاری</string>
<string name="common_cancel">منصرف شدن</string>
<string name="downloader_download_succeeded_ticker">بارگیری موفقیتآمیز بود</string>
<string name="downloader_download_failed_ticker">بارگیری ناموفق بود</string>
<string name="sync_string_contacts">ارتباطها</string>
+ <string name="auth_nossl_plain_ok_title">اتصال امن در دسترس نیست</string>
+ <string name="auth_connection_established">اتصال برقرار شد</string>
<string name="auth_testing_connection">آزمایش اتصال...</string>
+ <string name="auth_unknown_error_title">خطای ناشناخته رخ داده است!</string>
<string name="auth_login_details">جزئیات ورود</string>
<string name="crashlog_send_report">ارسال گزارش</string>
<string name="crashlog_dont_send_report">گزارش را ارسال نکن</string>
<string name="common_share">اشتراکگزاری</string>
<string name="common_rename">تغییرنام</string>
<string name="common_remove">حذف</string>
+ <string name="confirmation_remove_remote">پاک کردن از سرور</string>
<string name="wait_a_moment">لحظهای صبر کنید</string>
<string name="filedisplay_no_file_selected">هیچ پروندهای انتخاب نشده است</string>
<string name="ssl_validator_title">اخطار</string>
+ <string name="ssl_validator_btn_details_see">جزییات</string>
+ <string name="ssl_validator_btn_details_hide">پنهان کردن</string>
+ <string name="ssl_validator_label_C">کشور:</string>
+ <string name="instant_upload_on_wifi">تصاویر را فقط از طریق wifi بارگذاری کن</string>
</resources>
<string name="filedetails_sync_file">Päivitä</string>
<string name="filedetails_redownload">Lataa uudelleen</string>
<string name="filedetails_open">Avaa</string>
+ <string name="filedetails_renamed_in_upload_msg">Tiedoston nimeksi muutettiin %1$s siirron yhteydessä</string>
<string name="common_yes">Kyllä</string>
<string name="common_no">Ei</string>
<string name="common_ok">OK</string>
<string name="sync_fail_ticker">Synkronointi epäonnistui</string>
<string name="sync_fail_content">Kohteen %1$s synkronointia ei voitu suorittaa loppuun</string>
<string name="sync_conflicts_in_favourites_ticker">Ristiriitoja löytynyt</string>
+ <string name="sync_conflicts_in_favourites_content">%1$d \"pidä synkronoituna\" tiedostoja ei voitu synkronoida</string>
+ <string name="sync_fail_in_favourites_ticker">\"Pidä synkronoituna\" epäonnistui</string>
+ <string name="sync_fail_in_favourites_content">Hakemiston %1$d tiedostoja ei voitu synkronoida (%2$d konfliktia)</string>
<string name="use_ssl">Käytä salattua yhteyttä</string>
<string name="location_no_provider">ownCloud ei voi jäljittää laitettasi. Tarkista laitteesi sijaintiasetukset</string>
<string name="pincode_enter_pin_code">Aseta sovelluksesi PIN</string>
<string name="common_rename">Nimeä uudelleen</string>
<string name="common_remove">Poista</string>
<string name="confirmation_remove_alert">Haluatko poistaa kohteen %1$s?</string>
+ <string name="confirmation_remove_folder_alert">Haluatko poistaa kohteen %1$s ja sen sisällön?</string>
<string name="confirmation_remove_local">Vain paikallinen</string>
+ <string name="confirmation_remove_folder_local">Vain paikallinen sisältö</string>
<string name="confirmation_remove_remote">Poista palvelimelta</string>
<string name="confirmation_remove_remote_and_local">Sekä etä- että paikallinen</string>
<string name="remove_success_msg">Poistettu onnistuneesti</string>
<string name="rename_dialog_title">Anna uusi nimi</string>
<string name="rename_local_fail_msg">Paikallista kopiota ei voitu uudelleennimetä; yritä eri nimellä</string>
<string name="rename_server_fail_msg">Nimen muutos epäonnistui</string>
+ <string name="sync_file_fail_msg">Etäpään tiedostoa ei voitu tarkistaa</string>
+ <string name="sync_file_nothing_to_do_msg">Tiedoston sisältö on jo synkronoitu</string>
<string name="create_dir_fail_msg">Kansion luonti epäonnistui</string>
<string name="wait_a_moment">Odota hetki</string>
<string name="filedisplay_unexpected_bad_get_content">Odottamaton ongelma; kokeile valita tiedosto toisella sovelluksella</string>
<string name="ssl_validator_header">Sivuston identiteetin vahvistaminen ei onnistunut</string>
<string name="ssl_validator_reason_cert_not_trusted">- Palvelimen varmenteeseen ei luoteta</string>
<string name="ssl_validator_reason_cert_expired">- Palvelimen varmenne on vanhentunut</string>
+ <string name="ssl_validator_reason_cert_not_yet_valid">- Palvelimen varmenteen kelvolliset päivät ovat tulevaisuudessa</string>
+ <string name="ssl_validator_reason_hostname_not_verified">- Osoite ei vastaa sertifikaatissa mainittua isäntänimeä</string>
<string name="ssl_validator_certificate_not_available">Palvelimen varmenteen noutaminen epäonnistui</string>
<string name="ssl_validator_question">Haluatko silti luottaa tähän varmenteeseen?</string>
<string name="ssl_validator_not_saved">Varmenteen tallennus epäonnistui</string>
<string name="ssl_validator_label_validity_to">Päättyen:</string>
<string name="ssl_validator_label_signature">Allekirjoitus:</string>
<string name="ssl_validator_label_signature_algorithm">Algoritmi:</string>
+ <string name="text_placeholder">Tämä on paikkavaraus</string>
<string name="instant_upload_on_wifi">Lähetä kuvat vain WiFi-verkossa</string>
+ <string name="instant_upload_path">/InstantUpload</string>
<string name="conflict_title">Päivitysristiriita</string>
<string name="conflict_message">Etätiedostoa %s ei ole synkronoitu paikallisen tiedoston kanssa. Jatkaminen korvaa palvelimella olevan tiedoston sisällön.</string>
<string name="conflict_keep_both">Säilytä molemmat</string>
<string name="main_password">Contrasinal:</string>
<string name="main_login">Nome de usuario:</string>
<string name="main_button_login">Acceso</string>
- <string name="main_welcome">Benvido/a a ownCloud</string>
+ <string name="main_welcome">Benvido/a</string>
<string name="main_files">Ficheiros</string>
<string name="main_music">Música</string>
<string name="main_contacts">Contactos</string>
<string name="main_bookmarks">Marcadores</string>
<string name="main_settings">Preferencias</string>
<string name="main_tit_accsetup">Activar a conta</string>
- <string name="main_wrn_accsetup">Non hai contas de ownCloud no teu dispositivo. Para empregar o aplicativos necesitas crear unha.</string>
- <string name="about_message">O cliente de ownCloud para Android\n\nversion: %1$s</string>
+ <string name="main_wrn_accsetup">Non hai ningunha conta configurada no seu dispositivo. Para empregar o aplicativo necesita crear unha.</string>
+ <string name="about_message">O aplicativo %1$s para Android\n\nversión: %2$s</string>
<string name="actionbar_sync">Actualizar</string>
- <string name="actionbar_upload">Subir</string>
+ <string name="actionbar_upload">Enviar</string>
<string name="actionbar_upload_from_apps">Contido doutros aplicativos</string>
<string name="actionbar_upload_files">Ficheiros</string>
<string name="actionbar_mkdir">Crear un directorio</string>
<string name="prefs_add_session">Engadir unha nova sesión</string>
<string name="prefs_create_img_thumbnails">Crear miniaturas das imaxes</string>
<string name="prefs_select_oc_account">Escoller unha conta</string>
- <string name="prefs_summary_select_oc_account">Escolle cal das túas contas ten que usar o aplicativo.</string>
+ <string name="prefs_summary_select_oc_account">Escolla cal das súas contas ten que usar o aplicativo.</string>
<string name="prefs_trackmydevice">Rastrexamento do dispositivo</string>
- <string name="prefs_trackmydevice_summary_off">Permitir que ownCloud rexistre as posicións do teu dispositivo</string>
- <string name="prefs_trackmydevice_summary_on">O teu ownCloud mantén o rexistro de posicións do teu dispositivo</string>
+ <string name="prefs_trackmydevice_summary_off">Permitir que este aplicativo rexistre as posicións do seu dispositivo</string>
+ <string name="prefs_trackmydevice_summary_on">Este aplicativo mantén o rexistro de posicións do seu dispositivo</string>
<string name="prefs_trackmydevice_interval">Intervalo de actualizacións</string>
<string name="prefs_trackmydevice_interval_summary">Actualizar cada %1$s minutos</string>
<string name="prefs_accounts">Contas</string>
<string name="prefs_manage_accounts">Xestionar as contas</string>
- <string name="prefs_pincode">PIN do aplicativo ownCloud</string>
- <string name="prefs_pincode_summary">Protexe o teu cliente de ownCloud</string>
- <string name="prefs_instant_upload">Activar a subida instantánea</string>
- <string name="prefs_instant_upload_summary">Subir instantaneamente as fotos sacadas coa cámara</string>
- <string name="auth_host_url">URL de ownCloud</string>
+ <string name="prefs_pincode">PIN do aplicativo</string>
+ <string name="prefs_pincode_summary">Protexe o seu cliente</string>
+ <string name="prefs_instant_upload">Activar o envío instantáneo</string>
+ <string name="prefs_instant_upload_summary">Enviar instantaneamente as fotos tiradas coa cámara</string>
+ <string name="auth_host_url">URL</string>
<string name="auth_username">Nome de usuario</string>
<string name="auth_password">Contrasinal</string>
- <string name="auth_register">Son novo en ownCloud</string>
- <string name="new_session_uri_error">Deuse unha URL errada</string>
- <string name="new_session_session_name_error">Usuario de sesión errado</string>
+ <string name="auth_register">Son novo en %1$s</string>
+ <string name="new_session_uri_error">Deuse un enderezo incorrecto</string>
+ <string name="new_session_session_name_error">Nome de sesión incorrecto</string>
<string name="sync_string_files">Ficheiros</string>
- <string name="uploader_no_file_selected">Non se escolleron ficheiros para subir</string>
+ <string name="uploader_no_file_selected">Non se escolleron ficheiros para enviar</string>
<string name="setup_hint_username">Nome de usuario</string>
<string name="setup_hint_password">Contrasinal</string>
- <string name="setup_hint_address">Dirección web</string>
- <string name="setup_hint_show_password">Mostrar o contrasinal?</string>
- <string name="setup_title">Conectar co teu ownCloud</string>
+ <string name="setup_hint_address">Enderezo web</string>
+ <string name="setup_hint_show_password">Amosar o contrasinal?</string>
+ <string name="setup_title">Conectar co seu %1$s</string>
<string name="setup_btn_connect">Conectar</string>
- <string name="uploader_btn_upload_text">Subir</string>
+ <string name="uploader_btn_upload_text">Enviar</string>
<string name="uploader_wrn_no_account_title">Non se atoparon contas</string>
- <string name="uploader_wrn_no_account_text">Non hai contas de ownCloud no teu dispositivo. Crea unha nova conta primeiro.</string>
+ <string name="uploader_wrn_no_account_text">Non hai contas de %1$s no seu dispositivo. Cree unha nova conta primeiro.</string>
<string name="uploader_wrn_no_account_setup_btn_text">Instalación</string>
<string name="uploader_wrn_no_account_quit_btn_text">Saír</string>
- <string name="uploader_wrn_no_content_title">Non hai contido para subir</string>
+ <string name="uploader_wrn_no_content_title">Non hai contido para enviar</string>
<string name="uploader_wrn_no_content_text">Non se recibiu contido. Non hai nada para enviar.</string>
- <string name="uploader_error_forbidden_content">Non se lle permite a ownCloud a que acceda ao contido compartido</string>
+ <string name="uploader_error_forbidden_content">%1$s non ten permiso para acceder ao contido compartido</string>
<string name="uploader_info_uploading">Enviando</string>
<string name="uploader_btn_create_dir_text">Crear un directorio para os envíos</string>
- <string name="file_list_empty">Non hai ficheiros neste cartafol.\nOs novos ficheiros pódense engadir ca opción do menú «Subir»</string>
- <string name="filedetails_select_file">Déalle a un ficheiro para que mostre a información adicional</string>
+ <string name="file_list_empty">Non hai ficheiros neste cartafol.\nOs novos ficheiros pódense engadir ca opción do menú «Enviar».</string>
+ <string name="filedetails_select_file">Prema nun ficheiro para que amose a información adicional.</string>
<string name="filedetails_size">Tamaño:</string>
<string name="filedetails_type">Tipo:</string>
<string name="filedetails_created">Creado:</string>
<string name="filedetails_modified">Modificado:</string>
- <string name="filedetails_download">Baixar</string>
+ <string name="filedetails_download">Descargar</string>
<string name="filedetails_sync_file">Actualizar</string>
- <string name="filedetails_redownload">Actualizar</string>
+ <string name="filedetails_redownload">Descargar de novo</string>
<string name="filedetails_open">Abrir</string>
- <string name="filedetails_renamed_in_upload_msg">O ficheiroi renomeouse a %1$s durante a subida</string>
+ <string name="filedetails_renamed_in_upload_msg">O ficheiro foi renomeado a %1$s durante o envío</string>
<string name="common_yes">Si</string>
<string name="common_no">Non</string>
<string name="common_ok">Aceptar</string>
<string name="common_cancel_download">Cancelar a descarga</string>
- <string name="common_cancel_upload">Cancelar a subida</string>
+ <string name="common_cancel_upload">Cancelar o envío</string>
<string name="common_cancel">Cancelar</string>
- <string name="common_save_exit">Gardar & Saír</string>
- <string name="common_exit">Saír de ownCloud</string>
+ <string name="common_save_exit">Gardar e saír</string>
+ <string name="common_exit">Abandonar %1$s</string>
<string name="common_error">Erro</string>
- <string name="about_title">Acerca de</string>
+ <string name="about_title">Sobre</string>
<string name="delete_account">Eliminar a conta</string>
- <string name="create_account">Crear a conta</string>
- <string name="upload_chooser_title">Subir desde...</string>
+ <string name="create_account">Crear unha conta</string>
+ <string name="upload_chooser_title">Enviar desde…</string>
<string name="uploader_info_dirname">Nome do directorio</string>
- <string name="uploader_upload_in_progress_ticker">Subindo...</string>
- <string name="uploader_upload_in_progress_content">%1$d%% Subindo %2$s</string>
- <string name="uploader_upload_succeeded_ticker">Subiuse correctamente</string>
- <string name="uploader_upload_succeeded_content_single">%1$s subiuse correctamente</string>
- <string name="uploader_upload_succeeded_content_multiple">Os ficheiros %1$d subíronse correctamente</string>
- <string name="uploader_upload_failed_ticker">Fallou o envío</string>
- <string name="uploader_upload_failed_content_single">O envío de %1$s non se puido completar</string>
- <string name="uploader_upload_failed_content_multiple">Fallou o envío: subíronse %1$d/%2$d ficheiros</string>
- <string name="downloader_download_in_progress_ticker">Descargando...</string>
- <string name="downloader_download_in_progress_content">%1$d%% Descargando %2$s</string>
+ <string name="uploader_upload_in_progress_ticker">Enviando…</string>
+ <string name="uploader_upload_in_progress_content">%1$d%% enviando %2$s</string>
+ <string name="uploader_upload_succeeded_ticker">Enviado correctamente</string>
+ <string name="uploader_upload_succeeded_content_single">%1$s foi enviado correctamente</string>
+ <string name="uploader_upload_succeeded_content_multiple">%1$d ficheiros foron enviados correctamente</string>
+ <string name="uploader_upload_failed_ticker">Produciuse un fallou no envío</string>
+ <string name="uploader_upload_failed_content_single">Non foi posíbel completar o envío de %1$s</string>
+ <string name="uploader_upload_failed_content_multiple">Produciuse un fallou no envío: enviáronse %1$d/%2$d ficheiros</string>
+ <string name="downloader_download_in_progress_ticker">Descargando…</string>
+ <string name="downloader_download_in_progress_content">%1$d%% descargando %2$s</string>
<string name="downloader_download_succeeded_ticker">Completouse a descarga</string>
<string name="downloader_download_succeeded_content">%1$s descargouse correctamente</string>
- <string name="downloader_download_failed_ticker">Fallou a descarga</string>
- <string name="downloader_download_failed_content">Non se puido completar a descarga de %1$s</string>
+ <string name="downloader_download_failed_ticker">Produciuse un fallo na descarga</string>
+ <string name="downloader_download_failed_content">Non foi posíbel completar a descarga de %1$s</string>
<string name="common_choose_account">Escoller unha conta</string>
<string name="sync_string_contacts">Contactos</string>
- <string name="sync_fail_ticker">Fallou a sincronización</string>
- <string name="sync_fail_content">Non se puido rematar a sincronización de %1$s</string>
+ <string name="sync_fail_ticker">Produciuse un fallo na sincronización</string>
+ <string name="sync_fail_content">Non foi posíbel completar a sincronización de %1$s</string>
<string name="sync_conflicts_in_favourites_ticker">Atopáronse conflictos</string>
- <string name="sync_conflicts_in_favourites_content">%1$d ficheiros de kept-in-sync non se puideron sincronizar</string>
- <string name="sync_fail_in_favourites_ticker">Fallou a sincronización de ficheiros Kept-in-sync</string>
- <string name="sync_fail_in_favourites_content">Os contidos dos ficheiros %1$d non se puideron sincronizar (%1$d conflictos)</string>
+ <string name="sync_conflicts_in_favourites_content">Non foi posíbel sincronizar %1$d ficheiros «kept-in-sync»</string>
+ <string name="sync_fail_in_favourites_ticker">Produciuse un fallou ao sincronizar ficheiros «kept-in-sync»</string>
+ <string name="sync_fail_in_favourites_content">Non foi posíbel sincronizar o contido de %1$d ficheiros (%2$d conflitos)</string>
<string name="use_ssl">Empregar a conexión segura</string>
- <string name="location_no_provider">ownCloud non pode seguir o teu dispositivo. Comproba as configuracións de de localización.</string>
- <string name="pincode_enter_pin_code">Introduce o teu PIN de aplicación</string>
- <string name="pincode_enter_new_pin_code">Introduce o teu PIN da app</string>
- <string name="pincode_configure_your_pin">Introduce o PIN da app ownCloud</string>
- <string name="pincode_configure_your_pin_explanation">Pedirase o PIN cada vez que se inicie o aplicativo</string>
- <string name="pincode_reenter_your_pincode">Volve a introducir o PIN da app ownCloud</string>
- <string name="pincode_remove_your_pincode">Elimina o PIN da app ownCloud</string>
- <string name="pincode_mismatch">Os dous PIN da app ownCloud non son iguais</string>
- <string name="pincode_wrong">PIN incorrecto da app ownCloud</string>
- <string name="pincode_removed">Eliminouse o PIN da app ownCloud</string>
- <string name="pincode_stored">Almacenouse o PIN da app ownCloud</string>
+ <string name="location_no_provider">%1$s non pode rastrexar o seu dispositivo. Comprobe as configuracións de localización.</string>
+ <string name="pincode_enter_pin_code">Insira o seu PIN do aplicativo</string>
+ <string name="pincode_enter_new_pin_code">Insira o seu novo PIN do aplicativo</string>
+ <string name="pincode_configure_your_pin">Introduza o seu PIN do aplicativo</string>
+ <string name="pincode_configure_your_pin_explanation">Pediráselle o PIN cada vez que se inicie o aplicativo</string>
+ <string name="pincode_reenter_your_pincode">Volva a introducir o seu PIN do aplicativo</string>
+ <string name="pincode_remove_your_pincode">Retirar o seu PIN do aplicativo</string>
+ <string name="pincode_mismatch">Os PIN do aplicativo non son iguais</string>
+ <string name="pincode_wrong">PIN do aplicativo incorrecto</string>
+ <string name="pincode_removed">O PIN do aplicativo foi retirado</string>
+ <string name="pincode_stored">Almacenouse o PIN do aplicativo</string>
<string-array name="prefs_trackmydevice_intervall_keys">
<item>15 minutos</item>
<item>30 minutos</item>
<item>30</item>
<item>60</item>
</string-array>
- <string name="auth_trying_to_login">Intentando acceder...</string>
+ <string name="auth_trying_to_login">Tentando acceder…</string>
<string name="auth_no_net_conn_title">Sen conexión de rede</string>
- <string name="auth_no_net_conn_message">Non se detectaron conexións a rede. Comproba a conexión a internet e proba de novo.</string>
+ <string name="auth_no_net_conn_message">Non se detectaron conexións de rede. Comprobe a conexión a Internet e tenteo de novo.</string>
<string name="auth_connect_anyway">Conectar igualmente</string>
<string name="auth_nossl_plain_ok_title">Non hai conexión seguras dispoñíbeis.</string>
- <string name="auth_nossl_plain_ok_message">O aplicativo non puido facer unha conexión segura co servidor. Inda que non é segura, hai unha conexión posíbel. Podes continuar ou cancelala.</string>
+ <string name="auth_nossl_plain_ok_message">O aplicativo non puido facer unha conexión segura co servidor. Inda que non é segura, hai unha conexión posíbel. Pode continuar ou cancelala.</string>
<string name="auth_connection_established">Estabeleceuse a conexión</string>
- <string name="auth_testing_connection">Comprobando a conexión...</string>
- <string name="auth_not_configured_title">Configuración errada de ownCloud</string>
- <string name="auth_not_configured_message">Semella que a túa instancia de ownCloud non está configurada correctamente. Contacta co teu administrador para máis detalles.</string>
- <string name="auth_unknown_error_title">Ocorreu un erro descoñecido!</string>
- <string name="auth_unknown_error_message">Ocorreu un erro descoñecido. Contacta cos autores e infórmaos do fallo cos rexistros de erro do teu dispositivo.</string>
- <string name="auth_unknown_host_title">Non atopou o servidor</string>
- <string name="auth_unknown_host_message">Non se puido atopar o servidor que se indicou. Comproba o nome do host e proba de novo.</string>
- <string name="auth_incorrect_path_title">Non se atopa unha instancia de ownCloud</string>
- <string name="auth_incorrect_path_message">O aplicativo non atopou instancias de ownCloud na rua que se indicou. Comproba a ruta e proba de novo.</string>
- <string name="auth_timeout_title">O servidor tardou en responder</string>
- <string name="auth_incorrect_address_title">URL mal formada</string>
- <string name="auth_ssl_general_error_title">Fallou a inicialización de SSL</string>
- <string name="auth_ssl_unverified_server_title">Non se verificou a identidade do servidor SSL</string>
- <string name="auth_bad_oc_version_title">Versión do servidor de ownCloud non recoñecida</string>
- <string name="auth_wrong_connection_title">Non se pode establecer a conexión</string>
- <string name="auth_secure_connection">Fíxose unha conexión segura</string>
+ <string name="auth_testing_connection">Comprobando a conexión…</string>
+ <string name="auth_not_configured_title">Configuración errada do servidor</string>
+ <string name="auth_not_configured_message">Semella que a súa instancia do servidor non está configurada correctamente. Contacte co seu administrador para máis detalles.</string>
+ <string name="auth_unknown_error_title">Produciuse un erro descoñecido!</string>
+ <string name="auth_unknown_error_message">Produciuse un erro descoñecido. Contacte cos autores e infórmeos do fallo cos rexistros de erro do seu dispositivo.</string>
+ <string name="auth_unknown_host_title">Non foi posíbel atopar a máquina</string>
+ <string name="auth_unknown_host_message">Non foi posíbel atopar a máquina indicada. Comprobe o nome da máquina e tenteo de novo.</string>
+ <string name="auth_incorrect_path_title">Non se atopou unha instancia do servidor</string>
+ <string name="auth_incorrect_path_message">O aplicativo non atopou instancias do servidor na ruta indicada. Comprobe a ruta e tenteo de novo.</string>
+ <string name="auth_timeout_title">O servidor tardou demasiado en responder</string>
+ <string name="auth_incorrect_address_title">URL incorrecto</string>
+ <string name="auth_ssl_general_error_title">Produciuse un fallo ao iniciar o SSL</string>
+ <string name="auth_ssl_unverified_server_title">A identidade SSL do servidor non foi verficada</string>
+ <string name="auth_bad_oc_version_title">Versión do servidor non recoñecida</string>
+ <string name="auth_wrong_connection_title">Non é posíbel estabelecer a conexión</string>
+ <string name="auth_secure_connection">Estabeleceuse unha conexión segura</string>
<string name="auth_login_details">Detalles do acceso</string>
<string name="auth_unauthorized">Usuario ou contrasinal incorrectos</string>
- <string name="auth_not_found">Deuse unha ruta errada</string>
- <string name="auth_internal">Erro interno do servidor, código %1$d</string>
- <string name="crashlog_message">O aplicativo deixou de funcionar de xeito inesperado. Queres enviar un informe desta quebra?</string>
- <string name="crashlog_send_report">Envíar un informe</string>
- <string name="crashlog_dont_send_report">Non envíar un informe</string>
- <string name="extensions_avail_title">Engadido dispoñíbel!</string>
- <string name="extensions_avail_message">Semella que a túa instancia de ownCloud non soporta engadidos avanzados. Queres ver se hai engadidos dispoñíbeis para Android?</string>
- <string name="fd_keep_in_sync">Manter o ficheiro ao día</string>
+ <string name="auth_not_found">Deuse unha ruta incorrecta</string>
+ <string name="auth_internal">Produciuse un erro interno do servidor, código %1$d</string>
+ <string name="crashlog_message">O aplicativo deixou de funcionar de xeito inesperado. Quere enviar un informe desta quebra?</string>
+ <string name="crashlog_send_report">Enviar un informe</string>
+ <string name="crashlog_dont_send_report">Non enviar un informe</string>
+ <string name="extensions_avail_title">Extensión dispoñíbel!</string>
+ <string name="extensions_avail_message">Semella que a súa instancia do servidor admite extensións avanzadas. Quere ver se hai extensións dispoñíbeis para Android ?</string>
+ <string name="fd_keep_in_sync">Manter actualizado o ficheiro</string>
<string name="common_share">Compartir</string>
<string name="common_rename">Renomear</string>
- <string name="common_remove">Eliminar</string>
- <string name="confirmation_remove_alert">Queres eliminar %1$s ?</string>
- <string name="confirmation_remove_folder_alert">Seguro que queres eliminar %1$s e o seu contido?</string>
+ <string name="common_remove">Retirar</string>
+ <string name="confirmation_remove_alert">Confirma que quere retirar %1$s ?</string>
+ <string name="confirmation_remove_folder_alert">Confirma que quere retirar %1$s e o seu contido ?</string>
<string name="confirmation_remove_local">Só local</string>
<string name="confirmation_remove_folder_local">Só contidos locais</string>
- <string name="confirmation_remove_remote">Eliminar do servidor</string>
+ <string name="confirmation_remove_remote">Retirar do servidor</string>
<string name="confirmation_remove_remote_and_local">Remoto e local</string>
- <string name="remove_success_msg">Eliminouse correctamente</string>
- <string name="remove_fail_msg">Non se puido eliminar completamente</string>
- <string name="rename_dialog_title">Inrtoducir un novo nome</string>
- <string name="rename_local_fail_msg">Non se lle puido cambiar o nome a copia local. Proba con outro nome diferente.</string>
- <string name="rename_server_fail_msg">Non se rematou o cambio de nome</string>
- <string name="sync_file_fail_msg">Non se puido comprobar o ficheiro remoto</string>
+ <string name="remove_success_msg">Retirado correctamente</string>
+ <string name="remove_fail_msg">Non foi posíbel retiralo</string>
+ <string name="rename_dialog_title">Introducir un novo nome</string>
+ <string name="rename_local_fail_msg">Non foi posíbel cambiarlle o nome á copia local. Proba con outro nome diferente.</string>
+ <string name="rename_server_fail_msg">Non foi posíbel completar a operación de cambio de nome</string>
+ <string name="sync_file_fail_msg">Non foi posíbel comprobar o ficheiro remoto</string>
<string name="sync_file_nothing_to_do_msg">Os contidos do ficheiro xa están sincronizados</string>
- <string name="create_dir_fail_msg">Non se puido crear o directorio</string>
- <string name="wait_a_moment">Agarda un momento</string>
- <string name="filedisplay_unexpected_bad_get_content">Erro inesperado. Escolle outro aplicativo para seleccionar o ficheiro.</string>
+ <string name="create_dir_fail_msg">Non foi posíbel crear o directorio</string>
+ <string name="wait_a_moment">Agarde un chisco</string>
+ <string name="filedisplay_unexpected_bad_get_content">Produciuse un erro non agardado. Seleccione o ficheiro con outro aplicativo diferente</string>
<string name="filedisplay_no_file_selected">Non se escolleu ningún ficheiro</string>
- <string name="ssl_validator_title">Advertencia</string>
- <string name="ssl_validator_header">A identidade do sitio non se puido verificar</string>
- <string name="ssl_validator_reason_cert_not_trusted">Non se confía no certificado do servidor</string>
- <string name="ssl_validator_reason_cert_expired">O certificado do servidor caducou</string>
- <string name="ssl_validator_reason_cert_not_yet_valid">O certificado do servidor é moi novo</string>
- <string name="ssl_validator_reason_hostname_not_verified">A URL non coincide co nome de host do certificado</string>
- <string name="ssl_validator_certificate_not_available">Non se puido obter o certificado do servidor</string>
- <string name="ssl_validator_question">Queres confiar neste certificado igualmente?</string>
- <string name="ssl_validator_not_saved">Non se puido gardar o certificado</string>
+ <string name="ssl_validator_title">Aviso</string>
+ <string name="ssl_validator_header">Non foi posíbel verificar a identidade do sitio</string>
+ <string name="ssl_validator_reason_cert_not_trusted">- O certificado do servidor non é de confianza</string>
+ <string name="ssl_validator_reason_cert_expired">- O certificado do servidor caducou</string>
+ <string name="ssl_validator_reason_cert_not_yet_valid">- As datas de validez do certificado están son do futuro</string>
+ <string name="ssl_validator_reason_hostname_not_verified">- O URL non coincide co nome de máquina no certificado</string>
+ <string name="ssl_validator_certificate_not_available">Non foi posíbel obter o certificado do servidor</string>
+ <string name="ssl_validator_question">Aínda así, quere fiar neste certificado igualmente?</string>
+ <string name="ssl_validator_not_saved">Non foi posíbel gardar o certificado</string>
<string name="ssl_validator_btn_details_see">Detalles</string>
<string name="ssl_validator_btn_details_hide">Agochar</string>
<string name="ssl_validator_label_subject">Emitido para:</string>
<string name="ssl_validator_label_signature">Sinatura:</string>
<string name="ssl_validator_label_signature_algorithm">Algoritmo:</string>
<string name="text_placeholder">Isto é unha marca de posición</string>
- <string name="instant_upload_on_wifi">Subir imaxes só con WiFi</string>
- <string name="instant_upload_path">/SubidaInstantánea</string>
- <string name="conflict_title">Actualizar o conflito</string>
+ <string name="instant_upload_on_wifi">Enviar imaxes só medinte WiFi</string>
+ <string name="instant_upload_path">/EnvíoInstantáneo</string>
+ <string name="conflict_title">Conflito de actualización</string>
<string name="conflict_message">O ficheiro remoto %s non está sincronizado co ficheiro local. Continuando substituirase o contido do ficheiro no servidor.</string>
<string name="conflict_keep_both">Manter ambos</string>
<string name="conflict_overwrite">Sobrescribir</string>
- <string name="conflict_dont_upload">Non subir</string>
+ <string name="conflict_dont_upload">Non enviar</string>
</resources>
<?xml version='1.0' encoding='UTF-8'?>
<resources>
+ <string name="main_settings">सेटिंग्स</string>
+ <string name="actionbar_settings">सेटिंग्स</string>
<string name="auth_username">प्रयोक्ता का नाम</string>
<string name="auth_password">पासवर्ड</string>
<string name="setup_hint_username">प्रयोक्ता का नाम</string>
<string name="main_password">Jelszó:</string>
<string name="main_login">Felhasználói név:</string>
<string name="main_button_login">Belépés</string>
- <string name="main_welcome">Üdvözlünk a ownCloud-ban</string>
+ <string name="main_welcome">Üdv</string>
<string name="main_files">Fájlok</string>
<string name="main_music">Zene</string>
- <string name="main_contacts">Kapcsolat</string>
+ <string name="main_contacts">Címjegyzék</string>
<string name="main_calendar">Naptár</string>
<string name="main_bookmarks">Könyvjelzők</string>
<string name="main_settings">Beállítások</string>
<string name="main_tit_accsetup">Fiók beállítása</string>
- <string name="main_wrn_accsetup">Nincs beállított fiók a készülékén. Ahhoz hogy használja ezt az App-ot használja, létre kell hozzon egyet.</string>
- <string name="about_message">%1$s Android alkalmazás⏎ ⏎ verzió: %2$s</string>
+ <string name="main_wrn_accsetup">Nincs beállított fiók a készülékén. Ahhoz, hogy használja ezt a programot, létre kell hozzon egyet.</string>
+ <string name="about_message">%1$s Android alkalmazás\nverzió: %2$s</string>
<string name="actionbar_sync">Frissítés</string>
<string name="actionbar_upload">Feltöltés</string>
+ <string name="actionbar_upload_from_apps">Más alkalmazásokból származó tartalom</string>
<string name="actionbar_upload_files">Fájlok</string>
- <string name="actionbar_mkdir">Könyvtár létrahozása</string>
+ <string name="actionbar_mkdir">Mappa létrehozása</string>
<string name="actionbar_search">Keresés</string>
- <string name="actionbar_settings">beállítások</string>
+ <string name="actionbar_settings">Beállítások</string>
<string name="prefs_category_general">Általános</string>
<string name="prefs_category_trackmydevice">Eszközkövetés</string>
<string name="prefs_add_session">Új munkafolyamat létrehozása</string>
<string name="prefs_create_img_thumbnails">Bélyegkép készítése</string>
- <string name="prefs_select_oc_account">Válassz egy felhasználó nevet</string>
- <string name="prefs_summary_select_oc_account">Válassza ki, hogy az App milyen fiókot használjon.</string>
+ <string name="prefs_select_oc_account">Válasszon egy felhasználónevet</string>
+ <string name="prefs_summary_select_oc_account">Válassza ki, hogy a program milyen fiókot használjon.</string>
<string name="prefs_trackmydevice">Eszközkövetés</string>
- <string name="prefs_trackmydevice_summary_off">Engedélyezze ennek az App-nak a helykövetést</string>
- <string name="prefs_trackmydevice_summary_on">Ez az App eltárolja ennek a készüléknek az útvonalát</string>
- <string name="prefs_trackmydevice_interval">Frissítés gyakorisága</string>
+ <string name="prefs_trackmydevice_summary_off">Engedélyezze ennek a programnak a helykövetést</string>
+ <string name="prefs_trackmydevice_summary_on">Ez a program eltárolja ennek a készüléknek az útvonalát</string>
+ <string name="prefs_trackmydevice_interval">A frissítés gyakorisága</string>
<string name="prefs_trackmydevice_interval_summary">Minden %1$s percben</string>
<string name="prefs_accounts">Fiókok</string>
<string name="prefs_manage_accounts">Fiókok kezelése</string>
- <string name="prefs_pincode">ownCloud App PIN</string>
- <string name="prefs_pincode_summary">Védje meg az ügyfeleit</string>
- <string name="prefs_instant_upload">Az instant feltöltés engedélyezése</string>
- <string name="auth_host_url">ownCloud URL</string>
+ <string name="prefs_pincode">Alkalmazás PIN</string>
+ <string name="prefs_pincode_summary">Védje meg az alkalmazást</string>
+ <string name="prefs_instant_upload">Az azonnali feltöltés engedélyezése</string>
+ <string name="prefs_instant_upload_summary">Az eszköz által készített fényképek azonnali feltöltése</string>
+ <string name="auth_host_url">URL</string>
<string name="auth_username">Felhasználói név</string>
<string name="auth_password">Jelszó</string>
- <string name="auth_register">Új vagyok ehhez: %1$s</string>
+ <string name="auth_register">Új kapcsolat: %1$s</string>
<string name="new_session_uri_error">A megadott cím helytelen</string>
<string name="new_session_session_name_error">A megadott munkafolyamatnév érvénytelen</string>
<string name="sync_string_files">Fájlok</string>
<string name="setup_hint_password">Jelszó</string>
<string name="setup_hint_address">Web cím</string>
<string name="setup_hint_show_password">A jelszó megjelenjen?</string>
- <string name="setup_title">Kapcsolódás az ownCloud-hoz</string>
+ <string name="setup_title">Kapcsolódás ehhez: %1$s</string>
<string name="setup_btn_connect">Kapcsolódás</string>
<string name="uploader_btn_upload_text">Feltöltés</string>
<string name="uploader_wrn_no_account_title">Nincs ilyen felhasználói fiók</string>
<string name="uploader_wrn_no_account_setup_btn_text">Beállítás</string>
<string name="uploader_wrn_no_account_quit_btn_text">Kilépés</string>
<string name="uploader_wrn_no_content_title">Nincs feltölthető tartalom</string>
- <string name="uploader_wrn_no_content_text">Nem lett tartalom fogadva. Nincs mit feltölteni.</string>
+ <string name="uploader_wrn_no_content_text">Nem jött tartalom. Nincs mit feltölteni.</string>
+ <string name="uploader_error_forbidden_content">%1$s nem jogosult a megosztott tartalom elérésére</string>
<string name="uploader_info_uploading">Feltöltés</string>
<string name="uploader_btn_create_dir_text">Könyvtár létrehozása a feltöltésekhez</string>
+ <string name="file_list_empty">Ebben a mappában nincsenek állományok. A \"Feltöltés\" menüpont segítségével tölthet föl fájlokat.</string>
<string name="filedetails_select_file">Érintsen meg egy fájlt a további információkért.</string>
<string name="filedetails_size">Méret:</string>
<string name="filedetails_type">Tipus:</string>
<string name="filedetails_modified">Módosítva:</string>
<string name="filedetails_download">Letöltés</string>
<string name="filedetails_sync_file">Frissítés</string>
- <string name="filedetails_redownload">Frissítés</string>
+ <string name="filedetails_redownload">Ismételt letöltés</string>
<string name="filedetails_open">Megnyitás</string>
+ <string name="filedetails_renamed_in_upload_msg">A feltöltés során az állmányt erre neveztük át: %1$s</string>
<string name="common_yes">Igen</string>
<string name="common_no">Nem</string>
<string name="common_ok">OK</string>
- <string name="common_cancel_download">Letöltés megszakítása</string>
- <string name="common_cancel_upload">Feltöltés megszakítása</string>
+ <string name="common_cancel_download">A letöltés megszakítása</string>
+ <string name="common_cancel_upload">A feltöltés megszakítása</string>
<string name="common_cancel">Mégsem</string>
<string name="common_save_exit">Mentés & Kilépés</string>
+ <string name="common_exit">%1$s elhagyása</string>
<string name="common_error">Hiba</string>
<string name="about_title">Rólunk</string>
<string name="delete_account">Fiók törlése</string>
<string name="create_account">Fiók létrehozása</string>
<string name="upload_chooser_title">Feltöltés innen ...</string>
- <string name="uploader_info_dirname">Mappa név</string>
- <string name="uploader_upload_in_progress_ticker">Feltöltve ...</string>
+ <string name="uploader_info_dirname">Mappanév</string>
+ <string name="uploader_upload_in_progress_ticker">Feltöltés ...</string>
<string name="uploader_upload_in_progress_content">%1$d%% Feltöltés %2$s</string>
- <string name="uploader_upload_succeeded_ticker">Feltöltés sikerült</string>
+ <string name="uploader_upload_succeeded_ticker">A feltöltés sikerült</string>
<string name="uploader_upload_succeeded_content_single">%1$s sikeresen fel lett töltve</string>
<string name="uploader_upload_succeeded_content_multiple">%1$d fájl sikeresen fel lett töltve</string>
<string name="uploader_upload_failed_ticker">A feltöltés nem sikerült</string>
<string name="uploader_upload_failed_content_single"> %1$s fájl feltöltése sikertelen</string>
<string name="uploader_upload_failed_content_multiple">Hibás feltöltés: %1$d/%2$d fájl feltöltve</string>
- <string name="downloader_download_in_progress_ticker">Letöltése ...</string>
+ <string name="downloader_download_in_progress_ticker">Letöltés ...</string>
<string name="downloader_download_in_progress_content">%1$d%% Letöltés %2$s</string>
<string name="downloader_download_succeeded_ticker">A letöltés sikeres</string>
<string name="downloader_download_succeeded_content">%1$s sikeresen letöltve</string>
<string name="downloader_download_failed_ticker">A letöltés sikertelen</string>
<string name="downloader_download_failed_content">A letöltésből %1$s nem lett befejezve</string>
- <string name="common_choose_account">Válasz azonosítót</string>
- <string name="sync_string_contacts">Kapcsolat</string>
+ <string name="common_choose_account">Válasszon azonosítót</string>
+ <string name="sync_string_contacts">Címtár</string>
<string name="sync_fail_ticker">A szinkronizálás sikertelen</string>
+ <string name="sync_fail_content">%1$s szinkronizációját nem sikerült befejezni</string>
+ <string name="sync_conflicts_in_favourites_ticker">Ütközések vannak</string>
+ <string name="sync_conflicts_in_favourites_content">%1$d szinkronizálandó állományokat nem sikerült szinkronizálni</string>
+ <string name="sync_fail_in_favourites_ticker">A szinkronizálandó fájlokat nem sikerült szinkronizálni</string>
+ <string name="sync_fail_in_favourites_content">%1$d fájl szinkronizálása nem sikerült (%2$d ütközés)</string>
<string name="use_ssl">Biztonságos kapcsolat használata</string>
<string name="location_no_provider">%1$s nem tudja követni az eszközét. Kérem ellenőrizze a helybeállításait</string>
- <string name="pincode_enter_pin_code">Kérlek add meg az App PIN kódját</string>
- <string name="pincode_enter_new_pin_code">Kérlek add meg az új APP PIN kódját</string>
- <string name="pincode_configure_your_pin">ownCloud App PIN kója</string>
- <string name="pincode_reenter_your_pincode">Kérlek, hogy add meg újra az alkalmazás PIN-edet</string>
- <string name="pincode_remove_your_pincode">Alkalmazás PIN eltávolítása</string>
- <string name="pincode_mismatch">Az alkalmazás PIN-ek nem egyeznek meg</string>
- <string name="pincode_wrong">Helytelen alkalmazás PIN</string>
- <string name="pincode_removed">Alkalmazás PIN eltávolítva</string>
- <string name="pincode_stored">Alkalmazás PIN eltárolva</string>
+ <string name="pincode_enter_pin_code">Kérem adja meg az alkalmazás PIN-kódját</string>
+ <string name="pincode_enter_new_pin_code">Kérem adja meg az alkalmazás új PIN-kódját</string>
+ <string name="pincode_configure_your_pin">Az alkalmazás PIN-kódja</string>
+ <string name="pincode_configure_your_pin_explanation">A PIN-t kötelező lesz megadni az alkalmazás minden indításakor</string>
+ <string name="pincode_reenter_your_pincode">Kérem, adja meg újra az alkalmazás PIN-kódját</string>
+ <string name="pincode_remove_your_pincode">Az alkalmazás PIN-kódjának eltávolítása</string>
+ <string name="pincode_mismatch">A megadott PIN-ek nem egyeznek meg</string>
+ <string name="pincode_wrong">Rossz a megadott PIN</string>
+ <string name="pincode_removed">Az alkalmazás PIN-ját eltávolítottuk</string>
+ <string name="pincode_stored">Az alkalmazás PIN-jét eltároltuk</string>
<string-array name="prefs_trackmydevice_intervall_keys">
<item>15 perc</item>
<item>30 perc</item>
<string name="auth_no_net_conn_message">Nem található hálózati kapcsolat, ellenőrizze az internetkapcsolatát, és próbálja újra.</string>
<string name="auth_connect_anyway">Csatlakozás mindenképpen</string>
<string name="auth_nossl_plain_ok_title">Nem érhető el biztonságos kapcsolat.</string>
- <string name="auth_nossl_plain_ok_message">Az Alkalmazás nem tudott titkos kapcsolatot kialakítani a kiszolgálóval. A titkosítatlan kapcsolat elérhető. Folytathatja vagy kiléphet.</string>
+ <string name="auth_nossl_plain_ok_message">Az alkalmazás nem tudott titkosított kapcsolatot kialakítani a kiszolgálóval. A nem titkosított kapcsolat elérhető. Folytathatja vagy kiléphet.</string>
<string name="auth_connection_established">A kapcsolat létrejött</string>
<string name="auth_testing_connection">Kapcsolat tesztelése...</string>
- <string name="auth_not_configured_title">Hibás kiszolgáló beállítása</string>
+ <string name="auth_not_configured_title">Hibás a kiszolgáló beállítása</string>
<string name="auth_not_configured_message">Úgy tűnik a kiszolgáló nincs megfelelően beállítva. Lépjen kapcsolatba a rendszergazdával további információkért.</string>
<string name="auth_unknown_error_title">Ismeretlen hiba történt!</string>
<string name="auth_unknown_error_message">Ismeretlen hiba történt. Értesítse a terméktámogatást csatolva a az eszközének a naplóbejegyzéseit.</string>
+ <string name="auth_unknown_host_title">A kiszolgáló nem található</string>
+ <string name="auth_unknown_host_message">Nem található a keresett kiszolgáló. Ellenőrizze a nevét és a szerver elérhetőségét majd próbálja újra.</string>
<string name="auth_incorrect_path_title">Kiszolgáló nem található</string>
<string name="auth_incorrect_path_message">A program nem találta a kiszolgálót a megadott útvonalon. Kérem ellenőrizze az útvonalat, majd próbálja újra.</string>
+ <string name="auth_timeout_title">A kiszolgáló túl sokára válaszolt</string>
+ <string name="auth_incorrect_address_title">Hibás URL</string>
+ <string name="auth_ssl_general_error_title">Nem sikerült az SSL kapcsolat felépítése</string>
+ <string name="auth_ssl_unverified_server_title">Nem ellenőrizhető az kiszolgáló biztonsági tanúsítványa</string>
+ <string name="auth_bad_oc_version_title">Ismeretlen változat a kiszolgálón</string>
+ <string name="auth_wrong_connection_title">A kapcsolat nem hozható létre</string>
<string name="auth_secure_connection">Létrejött a titkosított kapcsolat</string>
<string name="auth_login_details">Belépési adatok</string>
<string name="auth_unauthorized">Érvénytelen felhasználónév / jelszó</string>
+ <string name="auth_not_found">Rossz a megadott útvonal</string>
+ <string name="auth_internal">Belső hiba történt a kiszolgálón, hibakód: %1$d</string>
<string name="crashlog_message">A program összeomlott. El akar küldeni egy összeomlási jelentést?</string>
<string name="crashlog_send_report">Jelentés küldése</string>
<string name="crashlog_dont_send_report">Ne küldjön jelentést</string>
- <string name="extensions_avail_title">Kiegészítők elérhetők!</string>
+ <string name="extensions_avail_title">Kiegészítők állnak rendelkezésre!</string>
<string name="extensions_avail_message">Úgy tűnik a programja támogatja a haladó kiterjesztéseket. Látni akarja az androidon elérhető kiterjesztéseket?</string>
- <string name="fd_keep_in_sync">Frissítse a fájlokat</string>
+ <string name="fd_keep_in_sync">Automatikusan frissítse a fájlokat</string>
<string name="common_share">Megosztás</string>
<string name="common_rename">Átnevezés</string>
<string name="common_remove">Eltávolítás</string>
- <string name="confirmation_remove_alert">Tényleg szeretnéd törölni %1$s ?</string>
- <string name="confirmation_remove_local">Csak helyből</string>
+ <string name="confirmation_remove_alert">Tényleg szeretné törölni ezt: %1$s ?</string>
+ <string name="confirmation_remove_folder_alert">Tényleg törölni akarja ezt a tartalmával együtt: %1$s?</string>
+ <string name="confirmation_remove_local">Csak a helyi példány</string>
+ <string name="confirmation_remove_folder_local">Csak a helyi tartalmat</string>
<string name="confirmation_remove_remote">Törlés a szerverről</string>
- <string name="confirmation_remove_remote_and_local">Törlés a szerverről és helyből</string>
- <string name="remove_success_msg">Az eltávolítás sikertelen</string>
- <string name="remove_fail_msg">Az eltávolítás meghiúsult</string>
+ <string name="confirmation_remove_remote_and_local">A szerveren levő és a helyi példány törlése</string>
+ <string name="remove_success_msg">Az eltávolítás sikerült</string>
+ <string name="remove_fail_msg">Az eltávolítás nem sikerült</string>
<string name="rename_dialog_title">Adj meg egy új nevet</string>
+ <string name="rename_local_fail_msg">A helyi példány nem nevezhető át, adjon másik nevet</string>
+ <string name="rename_server_fail_msg">Az átnevezés nem sikerült</string>
+ <string name="sync_file_fail_msg">A távoli fájl nem volt ellenőrizhető</string>
+ <string name="sync_file_nothing_to_do_msg">Az állományok már szinkonizálva vannak</string>
+ <string name="create_dir_fail_msg">A mappa nem hozható létre</string>
+ <string name="wait_a_moment">Egy pillanat...</string>
<string name="filedisplay_unexpected_bad_get_content">Váratlan hiba; válassza ki a fájlt más programból</string>
+ <string name="filedisplay_no_file_selected">Egy fájl sincs kiválasztva</string>
<string name="ssl_validator_title">Figyelmeztetés</string>
+ <string name="ssl_validator_header">A kiszolgálót nem sikerült azonosítani</string>
+ <string name="ssl_validator_reason_cert_not_trusted">- A kiszolgáló tanúsítványa nem megbízható</string>
+ <string name="ssl_validator_reason_cert_expired">- A kiszolgáló tanúsítványának lejárt az érvényessége</string>
+ <string name="ssl_validator_reason_cert_not_yet_valid">- A kiszolgáló tanúsítványa most még nem érvényes</string>
+ <string name="ssl_validator_reason_hostname_not_verified">- Az URL nem egyezik a tanúsítványban szereplő kiszolgálónévvel</string>
+ <string name="ssl_validator_certificate_not_available">A kiszolgáló tanúsítványa nem érhető el</string>
+ <string name="ssl_validator_question">Mégis megbízik ebben a tanúsítványban?</string>
+ <string name="ssl_validator_not_saved">A tanúsítvány nem menthető el</string>
<string name="ssl_validator_btn_details_see">Részletek</string>
<string name="ssl_validator_btn_details_hide">Elrejtés</string>
+ <string name="ssl_validator_label_subject">A tanúsítvány birtokosa:</string>
+ <string name="ssl_validator_label_issuer">Kiadta:</string>
+ <string name="ssl_validator_label_CN">Név:</string>
<string name="ssl_validator_label_O">Szervezet:</string>
<string name="ssl_validator_label_OU">Szervezeti egység:</string>
<string name="ssl_validator_label_C">Ország:</string>
<string name="ssl_validator_label_ST">Állam:</string>
<string name="ssl_validator_label_L">Hely:</string>
+ <string name="ssl_validator_label_validity">Érvényesség:</string>
+ <string name="ssl_validator_label_validity_from">Ettől a dátumtól:</string>
+ <string name="ssl_validator_label_validity_to">Eddig a dátumig:</string>
<string name="ssl_validator_label_signature">Aláírás:</string>
<string name="ssl_validator_label_signature_algorithm">Algoritmus:</string>
- <string name="conflict_title">Frissítési konfliktus</string>
+ <string name="text_placeholder">Ez egy helykitöltő</string>
+ <string name="instant_upload_on_wifi">Képeket csak WiFi kapcsolaton keresztül töltsünk föl</string>
+ <string name="instant_upload_path">/InstantUpload</string>
+ <string name="conflict_title">Frissítési ütközés</string>
+ <string name="conflict_message">%s távoli állományt nem szinkronizáltuk a helyi példánnyal. Ha folytatja, akkor a távoli állományt felülírjuk.</string>
<string name="conflict_keep_both">Mindkettő megtartása</string>
<string name="conflict_overwrite">Felülírás</string>
- <string name="conflict_dont_upload">Ne töltse fel</string>
+ <string name="conflict_dont_upload">Ne töltsük föl</string>
</resources>
--- /dev/null
+<?xml version='1.0' encoding='UTF-8'?>
+<resources>
+ <string name="main_files">ფაილები</string>
+ <string name="actionbar_upload_files">ფაილები</string>
+ <string name="auth_password">პაროლი</string>
+ <string name="sync_string_files">ფაილები</string>
+ <string name="setup_hint_password">პაროლი</string>
+ <string name="filedetails_download">გადმოწერა</string>
+</resources>
<?xml version='1.0' encoding='UTF-8'?>
<resources>
- <string name="main_files">Faili</string>
+ <string name="app_name">ownCloud</string>
+ <string name="main_password">Parole:</string>
+ <string name="main_login">Lietotājvārds:</string>
+ <string name="main_button_login">Ierakstīties</string>
+ <string name="main_welcome">Laipni lūgti</string>
+ <string name="main_files">Datnes</string>
<string name="main_music">Mūzika</string>
+ <string name="main_contacts">Kontakti</string>
<string name="main_calendar">Kalendārs</string>
+ <string name="main_bookmarks">Grāmatzīmes</string>
<string name="main_settings">Iestatījumi</string>
- <string name="actionbar_upload">Augšuplādet</string>
- <string name="actionbar_upload_files">Faili</string>
+ <string name="main_tit_accsetup">Iestatīt kontu</string>
+ <string name="main_wrn_accsetup">Uz šīs ierīces nav iestatīta konta. Lai lietotu šo lietotni, tāds ir jāizveido.</string>
+ <string name="about_message">%1$s Android lietotne\n\nversija: %2$s</string>
+ <string name="actionbar_sync">Atsvaidzināt</string>
+ <string name="actionbar_upload">Augšupielādēt</string>
+ <string name="actionbar_upload_from_apps">Saturs no citām lietotnēm</string>
+ <string name="actionbar_upload_files">Datnes</string>
+ <string name="actionbar_mkdir">Izveidot direktoriju</string>
+ <string name="actionbar_search">Meklēt</string>
<string name="actionbar_settings">Iestatījumi</string>
+ <string name="prefs_category_general">Vispārīgi</string>
+ <string name="prefs_category_trackmydevice">Ierīces izsekošana</string>
+ <string name="prefs_add_session">Pievienot jaunu sesiju</string>
+ <string name="prefs_create_img_thumbnails">Izveidot attēlu sīktēlus</string>
+ <string name="prefs_select_oc_account">Izvēlieties kontu</string>
+ <string name="prefs_summary_select_oc_account">Izvēlieties, kuru no kontiem jūsu lietotnei vajadzētu izmantot</string>
+ <string name="prefs_trackmydevice">Ierīču izsekošana</string>
+ <string name="prefs_trackmydevice_summary_off">Aktivējiet šo lietotni, lai izsekotu savas ierīces atrašanās vietu</string>
+ <string name="prefs_trackmydevice_summary_on">Šī lietotne izseko šo ierīci</string>
+ <string name="prefs_trackmydevice_interval">Atjaunināšanas intervāls</string>
+ <string name="prefs_trackmydevice_interval_summary">Atjaunināt katras %1$s minūtes</string>
+ <string name="prefs_accounts">Konti</string>
+ <string name="prefs_manage_accounts">Pārvaldīt kontus</string>
+ <string name="prefs_pincode">Lietotnes PIN</string>
+ <string name="prefs_pincode_summary">Aizsargā savu klientu</string>
+ <string name="prefs_instant_upload">Aktivēt tūlītējo augšupielādēšanu</string>
+ <string name="prefs_instant_upload_summary">Nekavējoties augšupielādēt kameras uzņemtos attēlus</string>
+ <string name="auth_host_url">URL</string>
<string name="auth_username">Lietotājvārds</string>
<string name="auth_password">Parole</string>
- <string name="sync_string_files">Faili</string>
+ <string name="auth_register">Esmu %1$s iesācējs</string>
+ <string name="new_session_uri_error">Ir dota nepareiza adrese</string>
+ <string name="new_session_session_name_error">Nepareizs sesijas nosaukums</string>
+ <string name="sync_string_files">Datnes</string>
+ <string name="uploader_no_file_selected">Neviena datne nav izvēlēta augšupielādei</string>
<string name="setup_hint_username">Lietotājvārds</string>
<string name="setup_hint_password">Parole</string>
- <string name="uploader_btn_upload_text">Augšuplādet</string>
- <string name="filedetails_download">Lejuplādēt</string>
- <string name="common_cancel_upload">Atcelt augšuplādi</string>
+ <string name="setup_hint_address">Tīmekļa adrese</string>
+ <string name="setup_hint_show_password">Rādīt paroli?</string>
+ <string name="setup_title">Savienoties ar savu %1$s</string>
+ <string name="setup_btn_connect">Savienoties</string>
+ <string name="uploader_btn_upload_text">Augšupielādēt</string>
+ <string name="uploader_wrn_no_account_title">Nav atrastu kontu</string>
+ <string name="uploader_wrn_no_account_text">Uz šīs ierīces nav %1$s kontu. Lūdzu, vispirms iestatiet kontu.</string>
+ <string name="uploader_wrn_no_account_setup_btn_text">Iestatīt</string>
+ <string name="uploader_wrn_no_account_quit_btn_text">Iziet</string>
+ <string name="uploader_wrn_no_content_title">Nav satura, ko augšupielādēt</string>
+ <string name="uploader_wrn_no_content_text">Nav saņemts nekāds saturs. Nav ko augšupielādēt.</string>
+ <string name="uploader_error_forbidden_content">%1$s nedrīkst piekļūt koplietotajam saturam</string>
+ <string name="uploader_info_uploading">Augšupielādē</string>
+ <string name="uploader_btn_create_dir_text">Izveidot direktoriju augšupielādēšanai</string>
+ <string name="file_list_empty">Šajā mapē nav datņu.\nJaunas datnes var pievienot ar izvēlnes opciju “Augšupielādēt”</string>
+ <string name="filedetails_select_file">Uzsitiet uz datnes, lai redzētu papildinformāciju.</string>
+ <string name="filedetails_size">Izmērs:</string>
+ <string name="filedetails_type">Tips:</string>
+ <string name="filedetails_created">Izveidota:</string>
+ <string name="filedetails_modified">Modificēta:</string>
+ <string name="filedetails_download">Lejupielādēt</string>
+ <string name="filedetails_sync_file">Atsvaidzināt</string>
+ <string name="filedetails_redownload">Atkārtoti lejupielādēt</string>
+ <string name="filedetails_open">Atvērt</string>
+ <string name="filedetails_renamed_in_upload_msg">Datne tika pārsaukta uz %1$s augšupielādes laikā</string>
+ <string name="common_yes">Jā</string>
+ <string name="common_no">Nē</string>
+ <string name="common_ok">Labi</string>
+ <string name="common_cancel_download">Atcelt lejupielādi</string>
+ <string name="common_cancel_upload">Atcelt augšupielādi</string>
<string name="common_cancel">Atcelt</string>
- <string name="common_error">Kļūme</string>
- <string name="common_share">Līdzdalīt</string>
- <string name="common_rename">Pārdēvēt</string>
+ <string name="common_save_exit">Saglabāt un iziet</string>
+ <string name="common_exit">Pamest %1$s</string>
+ <string name="common_error">Kļūda</string>
+ <string name="about_title">Par</string>
+ <string name="delete_account">Dzēst kontu</string>
+ <string name="create_account">Izveidot kontu</string>
+ <string name="upload_chooser_title">Augšupielādēt no...</string>
+ <string name="uploader_info_dirname">Direktorijas nosaukums</string>
+ <string name="uploader_upload_in_progress_ticker">Augšupielādē ...</string>
+ <string name="uploader_upload_in_progress_content">%1$d%% augšupielādē %2$s</string>
+ <string name="uploader_upload_succeeded_ticker">Augšupielāde ir veiksmīga</string>
+ <string name="uploader_upload_succeeded_content_single">%1$s tika veiksmīgi augšupielādēts</string>
+ <string name="uploader_upload_succeeded_content_multiple">%1$d datnes tika veiksmīgi augšupielādētas</string>
+ <string name="uploader_upload_failed_ticker">Neizdevās augšupielādēt</string>
+ <string name="uploader_upload_failed_content_single">Nevarēja pabeigt %1$s augšupielādēšanu</string>
+ <string name="uploader_upload_failed_content_multiple">Neizdevās augšupielādēt: tika augšupielādētas %1$d/%2$d datnes</string>
+ <string name="downloader_download_in_progress_ticker">Lejupielādē ...</string>
+ <string name="downloader_download_in_progress_content">%1$d%% lejupielādē %2$s</string>
+ <string name="downloader_download_succeeded_ticker">Lejupielāde beidzās veiksmīgi</string>
+ <string name="downloader_download_succeeded_content">%1$s tika veiksmīgi lejupielādēts</string>
+ <string name="downloader_download_failed_ticker">Neizdevās lejupielādēt</string>
+ <string name="downloader_download_failed_content">Nevarēja pabeigt %1$s lejupielādēšanu</string>
+ <string name="common_choose_account">Izvēlieties kontu</string>
+ <string name="sync_string_contacts">Kontakti</string>
+ <string name="sync_fail_ticker">Neizdevās sinhronizēties</string>
+ <string name="sync_fail_content">Nevarēja pabeigt %1$s sinhronizēšanu</string>
+ <string name="sync_conflicts_in_favourites_ticker">Ir atrasti konflikti</string>
+ <string name="sync_conflicts_in_favourites_content">Nevarēja sinhronizēt %1$d kept-in-sync datnes</string>
+ <string name="sync_fail_in_favourites_ticker">Kept-in-sync datnes cieta neveiksmi</string>
+ <string name="sync_fail_in_favourites_content">Nevarēja sinhronizēt %1$d datņu saturu (%2$d konflikti)</string>
+ <string name="use_ssl">Lietot drošo savienojumu</string>
+ <string name="location_no_provider">%1$s nevar izsekot šo ierīci. Lūdzu, pārbaudiet savus vietas iestatījumus</string>
+ <string name="pincode_enter_pin_code">Lūdzu, ierakstiet savu lietotnes PIN</string>
+ <string name="pincode_enter_new_pin_code">Lūdzu, ierakstiet savu jauno lietotnes PIN</string>
+ <string name="pincode_configure_your_pin">Ievadiet savu lietotnes PIN</string>
+ <string name="pincode_configure_your_pin_explanation">PIN tiks pieprasīts katrā lietotnes palaišanas reizē</string>
+ <string name="pincode_reenter_your_pincode">Lūdzu, vēlreiz ievadiet savu lietotnes PIN</string>
+ <string name="pincode_remove_your_pincode">Izņemt savu lietotnes PIN</string>
+ <string name="pincode_mismatch">Lietotņu PIN nav vienādi</string>
+ <string name="pincode_wrong">Nepareizs lietotnes PIN</string>
+ <string name="pincode_removed">Lietotnes PIN ir izņemts</string>
+ <string name="pincode_stored">Lietotnes PIN ir noglabāts</string>
+ <string-array name="prefs_trackmydevice_intervall_keys">
+ <item>15 minūtes</item>
+ <item>30 minūtes</item>
+ <item>60 minūtes</item>
+ </string-array>
+ <string-array name="prefs_trackmydevice_intervall_values">
+ <item>15</item>
+ <item>30</item>
+ <item>60</item>
+ </string-array>
+ <string name="auth_trying_to_login">Mēģina ierakstīties...</string>
+ <string name="auth_no_net_conn_title">Nav tīkla savienojumu</string>
+ <string name="auth_no_net_conn_message">Nav atklātu tīkla savienojumu. Pārbaudiet interneta savienojumus un mēģiniet vēlreiz.</string>
+ <string name="auth_connect_anyway">Tomēr savienoties</string>
+ <string name="auth_nossl_plain_ok_title">Nav pieejams drošs savienojums.</string>
+ <string name="auth_nossl_plain_ok_message">Lietotne nevar izveidot drošu savienojumu ar serveri. Ir pieejams nedrošs savienojums. Jūs varat turpināt vai atcelt.</string>
+ <string name="auth_connection_established">Savienojums ir izveidots</string>
+ <string name="auth_testing_connection">Testē savienojumu...</string>
+ <string name="auth_not_configured_title">Slikti formatēta servera konfigurācija</string>
+ <string name="auth_not_configured_message">Izskatās, ka jūsu servera instance nav pareizi konfigurēta. Sazinieties ar servera administratoru, lai uzzinātu vairāk.</string>
+ <string name="auth_unknown_error_title">Gadījās nezināma kļūda!</string>
+ <string name="auth_unknown_error_message">Gadījās nezināma kļūda. Lūdzu, sazinieties ar atbalstu un pievienojiet žurnālus no savas ierīces.</string>
+ <string name="auth_unknown_host_title">Nevarēja atrast datoru</string>
+ <string name="auth_unknown_host_message">Nevarēja atrast ievadīto datoru. Lūdzu, pārliecinieties ka datora nosaukums ir ievadīts pareizi un ka serveris ir pieejams.</string>
+ <string name="auth_incorrect_path_title">Servera instance nav atrasta</string>
+ <string name="auth_incorrect_path_message">Lietotne uz dotā ceļa nevarēja atrast servera instanci. Lūdzu, pārbaudiet ceļu un mēģiniet vēlreiz.</string>
+ <string name="auth_timeout_title">Serveris pārāk ilgi neatbildēja</string>
+ <string name="auth_incorrect_address_title">Slikti formatēts URL</string>
+ <string name="auth_ssl_general_error_title">Neizdevās inicializēt SSL</string>
+ <string name="auth_ssl_unverified_server_title">Nepārbaudīta SSL servera identitāte</string>
+ <string name="auth_bad_oc_version_title">Neatpazīta servera versija</string>
+ <string name="auth_wrong_connection_title">Nevarēja izveidot savienojumu</string>
+ <string name="auth_secure_connection">Ir izveidots drošs savienojums</string>
+ <string name="auth_login_details">Sīkāka informācija par ierakstīšanos</string>
+ <string name="auth_unauthorized">Nederīgs lietotājvārds/parole</string>
+ <string name="auth_not_found">Dots nepareizs ceļš</string>
+ <string name="auth_internal">Iekšējā servera kļūda, kods %1$d</string>
+ <string name="crashlog_message">Lietotne negaidīti beidza darbu. Vai vēlaties iesniegt kļūdas ziņojumu?</string>
+ <string name="crashlog_send_report">Sūtīt ziņojumu</string>
+ <string name="crashlog_dont_send_report">Nesūtīt ziņojumu</string>
+ <string name="extensions_avail_title">Ir pieejams paplašinājums!</string>
+ <string name="extensions_avail_message">Izskatās, ka jūsu servera instance atbalsta papildu paplašinājumus. Vai vēlaties redzēt paplašinājumus, kas ir pieejami uz android?</string>
+ <string name="fd_keep_in_sync">Uzturēt datni aktuālu</string>
+ <string name="common_share">Dalīties</string>
+ <string name="common_rename">Pārsaukt</string>
+ <string name="common_remove">Izņemt</string>
+ <string name="confirmation_remove_alert">Vai tiešām vēlaties izņemt %1$s?</string>
+ <string name="confirmation_remove_folder_alert">Vai vēlaties izņemt %1$s un tā saturu?</string>
+ <string name="confirmation_remove_local">Tikai lokālos</string>
+ <string name="confirmation_remove_folder_local">Tikai lokālo saturu</string>
+ <string name="confirmation_remove_remote">Izņemt no servera</string>
+ <string name="confirmation_remove_remote_and_local">Attālinātās un lokālās</string>
+ <string name="remove_success_msg">Veiksmīgi izņemts</string>
+ <string name="remove_fail_msg">Neizdevās izņemt</string>
+ <string name="rename_dialog_title">Ievadīt jaunu nosaukumu</string>
+ <string name="rename_local_fail_msg">Nevarēja pārsaukt lokālo kopiju; pamēģiniet citu nosaukumu</string>
+ <string name="rename_server_fail_msg">Nevarēja pabeigt pārsaukšanu</string>
+ <string name="sync_file_fail_msg">Nevarēja atzīmēt attālinātas datnes</string>
+ <string name="sync_file_nothing_to_do_msg">Datnes saturs jau ir sinhronizēts</string>
+ <string name="create_dir_fail_msg">Nevarēja izveidot direktoriju</string>
+ <string name="wait_a_moment">Uzgaidīt brīdi</string>
+ <string name="filedisplay_unexpected_bad_get_content">Negaidīta problēma; lūdzu, izvēlieties datni no citas lietotnes</string>
+ <string name="filedisplay_no_file_selected">Netika izvēlēta neviena datne</string>
+ <string name="ssl_validator_title">Brīdinājums</string>
+ <string name="ssl_validator_header">Šīs vietnes identitāti nevarēja pārbaudīt</string>
+ <string name="ssl_validator_reason_cert_not_trusted">- Nav uzticības servera sertifikātam</string>
+ <string name="ssl_validator_reason_cert_expired">- Servera sertifikātam ir beidzies termiņš</string>
+ <string name="ssl_validator_reason_cert_not_yet_valid">- Servera sertifikāta datumi ir nākotnē</string>
+ <string name="ssl_validator_reason_hostname_not_verified">- URL sertifikātā neatbilst datora nosaukumam</string>
+ <string name="ssl_validator_certificate_not_available">Nevarēja saņemt sertifikātu</string>
+ <string name="ssl_validator_question">Vai tomēr uzticēties sertifikātam?</string>
+ <string name="ssl_validator_not_saved">Nevarēja saglabāt sertifikātu</string>
+ <string name="ssl_validator_btn_details_see">Sīkāka informācija</string>
+ <string name="ssl_validator_btn_details_hide">Slēpt</string>
+ <string name="ssl_validator_label_subject">Izsniegts:</string>
+ <string name="ssl_validator_label_issuer">Izsniedza:</string>
+ <string name="ssl_validator_label_CN">Kopīgais nosaukums:</string>
+ <string name="ssl_validator_label_O">Organizācija:</string>
+ <string name="ssl_validator_label_OU">Organizācijas vienība:</string>
+ <string name="ssl_validator_label_C">Valsts:</string>
+ <string name="ssl_validator_label_ST">Štats:</string>
+ <string name="ssl_validator_label_L">Vieta:</string>
+ <string name="ssl_validator_label_validity">Derīgums:</string>
+ <string name="ssl_validator_label_validity_from">No:</string>
+ <string name="ssl_validator_label_validity_to">Kam:</string>
+ <string name="ssl_validator_label_signature">Paraksts:</string>
+ <string name="ssl_validator_label_signature_algorithm">Algoritms:</string>
+ <string name="text_placeholder">Šis ir vietturis</string>
+ <string name="instant_upload_on_wifi">Attēlus augšupielādēt tikai caur WiFi</string>
+ <string name="instant_upload_path">/TūlītējaAugšupielāde</string>
+ <string name="conflict_title">Atjaunināšanas konflikts</string>
+ <string name="conflict_message">Attālinātā datne %s nav sinhronizēta ar lokālo datni. Turpināšana aizstās datņu servera saturu.</string>
+ <string name="conflict_keep_both">Paturēt abas</string>
+ <string name="conflict_overwrite">Pārrakstīt</string>
+ <string name="conflict_dont_upload">Neaugšupielādēt</string>
</resources>
--- /dev/null
+<?xml version='1.0' encoding='UTF-8'?>
+<resources>
+ <string name="main_files">ဖိုင်များ</string>
+ <string name="main_calendar">ပြက္ခဒိန်</string>
+ <string name="actionbar_upload_files">ဖိုင်များ</string>
+ <string name="auth_username">သုံးစွဲသူအမည်</string>
+ <string name="auth_password">စကားဝှက်</string>
+ <string name="sync_string_files">ဖိုင်များ</string>
+ <string name="setup_hint_username">သုံးစွဲသူအမည်</string>
+ <string name="setup_hint_password">စကားဝှက်</string>
+ <string name="filedetails_download">ဒေါင်းလုတ်</string>
+ <string name="common_yes">ဟုတ်</string>
+ <string name="common_no">မဟုတ်ဘူး</string>
+ <string name="common_cancel">ပယ်ဖျက်မည်</string>
+</resources>
<string name="main_contacts">Kontakter</string>
<string name="main_calendar">Kalender</string>
<string name="main_bookmarks">Bokmerker</string>
- <string name="main_settings">Innstilinger</string>
+ <string name="main_settings">Innstillinger</string>
<string name="main_tit_accsetup">Sett opp konto</string>
<string name="main_wrn_accsetup">Det finnes ingen ownClound kontoer for din enhent. For å bruker denne appen må du opprette en,</string>
<string name="actionbar_sync">Oppdater</string>
- <string name="actionbar_upload">Opplasting</string>
+ <string name="actionbar_upload">Last opp</string>
+ <string name="actionbar_upload_from_apps">Innhold fra andre applikasjoner</string>
<string name="actionbar_upload_files">Filer</string>
<string name="actionbar_mkdir">Opprett katalog</string>
<string name="actionbar_search">Søk</string>
<string name="actionbar_settings">Innstillinger</string>
- <string name="prefs_category_general">Generellt</string>
- <string name="prefs_category_trackmydevice">Enherssporing</string>
- <string name="prefs_create_img_thumbnails">Lag minityrbilder</string>
+ <string name="prefs_category_general">Generelt</string>
+ <string name="prefs_category_trackmydevice">Enhetssporing</string>
+ <string name="prefs_add_session">Legg til ny sesjon</string>
+ <string name="prefs_create_img_thumbnails">Opprett miniatyrbilder</string>
<string name="prefs_select_oc_account">Velg konto</string>
<string name="prefs_trackmydevice">Enhetssporing</string>
<string name="prefs_trackmydevice_interval">Oppdateringsfrekvens</string>
+ <string name="prefs_trackmydevice_interval_summary">Oppdater hvert %1$s minutt</string>
<string name="prefs_accounts">Kontoer</string>
+ <string name="prefs_instant_upload_summary">Last opp bilder tatt med kamera øyeblikkelig</string>
<string name="auth_host_url">URL</string>
<string name="auth_username">Brukernavn</string>
<string name="auth_password">Passord</string>
<string name="sync_string_files">Filer</string>
+ <string name="uploader_no_file_selected">Ingen fil valgt for opplasting</string>
<string name="setup_hint_username">Brukernavn</string>
<string name="setup_hint_password">Passord</string>
<string name="setup_hint_address">Internettadresse</string>
<string name="setup_hint_show_password">Vise passord?</string>
- <string name="setup_btn_connect">Kople til</string>
- <string name="uploader_btn_upload_text">Last op</string>
+ <string name="setup_btn_connect">Koble til</string>
+ <string name="uploader_btn_upload_text">Last opp</string>
<string name="uploader_wrn_no_account_title">Ingen konto funnet</string>
<string name="uploader_wrn_no_account_setup_btn_text">Oppsett</string>
<string name="uploader_wrn_no_account_quit_btn_text">Avslutt</string>
+ <string name="uploader_wrn_no_content_title">Intet innhold å laste opp</string>
+ <string name="uploader_wrn_no_content_text">Intet innhold ble mottatt. Intet å laste opp.</string>
<string name="uploader_info_uploading">Laster opp</string>
<string name="uploader_btn_create_dir_text">Opprett mappe for opplasting</string>
+ <string name="filedetails_select_file">Trykk på en fil for å vise ekstra informasjon.</string>
<string name="filedetails_size">Størrelse:</string>
<string name="filedetails_type">Type:</string>
- <string name="filedetails_created">Opprette:</string>
+ <string name="filedetails_created">Opprettet:</string>
<string name="filedetails_modified">Endret:</string>
<string name="filedetails_download">Last ned</string>
<string name="filedetails_sync_file">Oppdater</string>
<string name="common_cancel_download">Avbryt nedlasting</string>
<string name="common_cancel_upload">Avbryt opplasting</string>
<string name="common_cancel">Avbryt</string>
- <string name="common_save_exit">Lager og avslutt</string>
+ <string name="common_save_exit">Lagre og avslutt</string>
<string name="common_error">Feil</string>
<string name="about_title">Om</string>
<string name="delete_account">Slett konto</string>
- <string name="create_account">Opprett Konto</string>
+ <string name="create_account">Opprett konto</string>
<string name="upload_chooser_title">Last opp fra...</string>
<string name="uploader_info_dirname">Katalognavn</string>
<string name="uploader_upload_in_progress_ticker">Laster opp...</string>
+ <string name="uploader_upload_in_progress_content">%1$d%% Laster opp %2$s</string>
<string name="uploader_upload_succeeded_ticker">Opplasting fullført</string>
<string name="uploader_upload_failed_ticker">Opplasting feilet</string>
+ <string name="uploader_upload_failed_content_single">Opplasting av %1$s kunne ikke fullføres</string>
+ <string name="uploader_upload_failed_content_multiple">Opplasting feilet: %1$d/%2$d filer ble lastet opp</string>
<string name="downloader_download_in_progress_ticker">Laster ned...</string>
+ <string name="downloader_download_in_progress_content">%1$d%% Laster ned %2$s</string>
<string name="downloader_download_succeeded_ticker">Nedlasting fullført</string>
<string name="downloader_download_failed_ticker">Nedlasting feilet</string>
+ <string name="downloader_download_failed_content">Nedlasting av %1$s kunne ikke fullføres</string>
<string name="common_choose_account">Velg konto</string>
<string name="sync_string_contacts">Kontakter</string>
+ <string name="sync_fail_ticker">Synkronisering feilet</string>
+ <string name="sync_fail_content">Synkronisering av %1$s kunne ikke fullføres</string>
<string name="sync_conflicts_in_favourites_ticker">Konflikter funnet</string>
<string name="use_ssl">Bruk sikker tilkobling</string>
+ <string name="pincode_enter_pin_code">Vennligst tast inn din App-PIN</string>
+ <string name="pincode_enter_new_pin_code">Vennligst tast inn ny App-PIN</string>
+ <string-array name="prefs_trackmydevice_intervall_keys">
+ <item>15 minutter</item>
+ <item>30 minutter</item>
+ <item>60 minutter</item>
+ </string-array>
+ <string-array name="prefs_trackmydevice_intervall_values">
+ <item>15</item>
+ <item>30</item>
+ <item>60</item>
+ </string-array>
<string name="auth_trying_to_login">Prøver å logge inn...</string>
- <string name="auth_no_net_conn_title">Ingen nettverkstilgang</string>
+ <string name="auth_no_net_conn_title">Ingen nettverkstilkobling</string>
<string name="auth_connect_anyway">Koble til likevel</string>
- <string name="auth_testing_connection">Tester tilgang...</string>
+ <string name="auth_nossl_plain_ok_title">Sikker tilkobling ikke tilgjengelig.</string>
+ <string name="auth_connection_established">Tilkobling opprettet</string>
+ <string name="auth_testing_connection">Tester tilkobling...</string>
+ <string name="auth_unknown_error_title">Ukjent feil oppstod!</string>
+ <string name="auth_unknown_host_title">Fant ikke tjener</string>
+ <string name="auth_unknown_host_message">Fant ikke spesifisert tjener. Vennligst sjekk tjenernavnet og server-tilgjengeligheten, og prøv på nytt.</string>
+ <string name="auth_timeout_title">Serveren brukte for lang tid på å svare</string>
+ <string name="auth_incorrect_address_title">Feil formatert URL</string>
+ <string name="auth_ssl_general_error_title">Oppstart av SSL feilet</string>
+ <string name="auth_ssl_unverified_server_title">Uverifisert SSL-servers identitet</string>
+ <string name="auth_wrong_connection_title">Klarte ikke å opprette tilkobling</string>
+ <string name="auth_secure_connection">Sikker tilkobling opprettet</string>
+ <string name="auth_login_details">Innloggingsdetaljer</string>
<string name="auth_unauthorized">Ugyldig brukernavn / passord</string>
<string name="crashlog_send_report">Send rapport</string>
<string name="crashlog_dont_send_report">Ikke send rapport</string>
+ <string name="extensions_avail_title">Utvidelser tilgjengelig!</string>
+ <string name="fd_keep_in_sync">Hold filen oppdatert</string>
<string name="common_share">Del</string>
<string name="common_rename">Endre navn</string>
<string name="common_remove">Fjern</string>
+ <string name="confirmation_remove_alert">Er du sikker på at du vil fjerne %1$s ?</string>
<string name="confirmation_remove_local">Kun lokalt</string>
+ <string name="confirmation_remove_remote">Fjern fra server</string>
+ <string name="rename_server_fail_msg">Klarte ikke å endre navn</string>
+ <string name="create_dir_fail_msg">Mappe kunne ikke opprettes</string>
+ <string name="wait_a_moment">Vent et øyeblikk</string>
+ <string name="filedisplay_no_file_selected">Ingen fil ble valgt</string>
<string name="ssl_validator_title">Advarsel</string>
+ <string name="ssl_validator_header">Identiteten til siden kunne ikke verifiseres</string>
+ <string name="ssl_validator_reason_cert_not_trusted">- Serverens sertifikat er ikke til å stole på</string>
+ <string name="ssl_validator_reason_cert_expired">- Serverens sertifikat er utløpt</string>
<string name="ssl_validator_btn_details_see">Detaljer</string>
<string name="ssl_validator_btn_details_hide">Skjul</string>
<string name="ssl_validator_label_C">Land:</string>
<string name="ssl_validator_label_validity_from">Fra:</string>
<string name="ssl_validator_label_validity_to">Til:</string>
<string name="ssl_validator_label_signature">Signatur:</string>
+ <string name="text_placeholder">Dette er en plassholder</string>
<string name="conflict_keep_both">Behold begge</string>
</resources>
<string name="app_name">ownCloud</string>
<string name="main_password">Hasło:</string>
<string name="main_login">Nazwa użytkownika:</string>
- <string name="main_button_login">Login</string>
- <string name="main_welcome">Witaj w ownCloud</string>
+ <string name="main_button_login">Zaloguj</string>
+ <string name="main_welcome">Witaj</string>
<string name="main_files">Pliki</string>
<string name="main_music">Muzyka</string>
<string name="main_contacts">Kontakty</string>
<string name="main_bookmarks">Zakładki</string>
<string name="main_settings">Ustawienia</string>
<string name="main_tit_accsetup">Załóż konto</string>
- <string name="main_wrn_accsetup">Nie wykryto kont ownCloud, załóż konto w celu używania aplikacji.</string>
- <string name="about_message">ownCloud Android klient⏎ ⏎ wersja: %2$s</string>
+ <string name="main_wrn_accsetup">Nie wykryto kont ownCloud. Aby korzystać z tej aplikacji, musisz utworzyć konto.</string>
+ <string name="about_message">%1$s Android App⏎ ⏎ wersja: %2$s</string>
<string name="actionbar_sync">Odśwież</string>
<string name="actionbar_upload">Wyślij plik</string>
- <string name="actionbar_upload_from_apps">Zasoby innej aplikacji</string>
- <string name="actionbar_upload_files">Pliki z telefonu</string>
+ <string name="actionbar_upload_from_apps">Zasoby innych aplikacji</string>
+ <string name="actionbar_upload_files">Pliki</string>
<string name="actionbar_mkdir">Nowy katalog</string>
<string name="actionbar_search">Szukaj</string>
<string name="actionbar_settings">Ustawienia</string>
<string name="prefs_category_general">Ogólne</string>
- <string name="prefs_category_trackmydevice">Śledzenie urządzeń</string>
- <string name="prefs_add_session">Dodaj sesje</string>
- <string name="prefs_create_img_thumbnails">Nie można utworzyć podglądu</string>
+ <string name="prefs_category_trackmydevice">Śledzenie urządzenia</string>
+ <string name="prefs_add_session">Dodaj nową sesję</string>
+ <string name="prefs_create_img_thumbnails">Utwórz miniaturki obrazów</string>
<string name="prefs_select_oc_account">Wybierz konto</string>
- <string name="prefs_summary_select_oc_account">Wybierz aplikację, której chcesz użyć.</string>
+ <string name="prefs_summary_select_oc_account">Wybierz konto, z którego ma korzystać aplikacja.</string>
<string name="prefs_trackmydevice">Śledzenie urządzeń</string>
- <string name="prefs_trackmydevice_summary_off">Włącz śledzenie lokalizacji urządzenia w ownCloud</string>
- <string name="prefs_trackmydevice_summary_on">Twój ownCloud trzyma informacje o tym urządzeniu</string>
+ <string name="prefs_trackmydevice_summary_off">Włącz śledzenie lokalizacji urządzenia przez tę aplikację</string>
+ <string name="prefs_trackmydevice_summary_on">Ta aplikacja śledzi to urządzenie</string>
<string name="prefs_trackmydevice_interval">Odstęp aktualizacji</string>
<string name="prefs_trackmydevice_interval_summary">Aktualizuj co %1$ minut</string>
<string name="prefs_accounts">Konta</string>
<string name="prefs_manage_accounts">Zarządzaj kontami</string>
- <string name="prefs_pincode">Pin aplikacji ownCloud</string>
- <string name="prefs_pincode_summary">Chroni klienta ownCloud</string>
- <string name="prefs_instant_upload">Włącz automatyczne wysyłanie</string>
+ <string name="prefs_pincode">PIN aplikacji</string>
+ <string name="prefs_pincode_summary">Chroń klienta</string>
+ <string name="prefs_instant_upload">Włącz natychmiastowe wysyłanie</string>
<string name="prefs_instant_upload_summary">Natychmiast wysyłaj zdjęcia zrobione aparatem</string>
- <string name="auth_host_url">URL ownCloud</string>
+ <string name="auth_host_url">URL</string>
<string name="auth_username">Nazwa użytkownika</string>
<string name="auth_password">Hasło</string>
- <string name="auth_register">Jestem nowy na ownCloud</string>
- <string name="new_session_uri_error">Podano niepoprawny URL</string>
- <string name="new_session_session_name_error">Zła nazwa sesji</string>
+ <string name="auth_register">Jestem nowym użytkownikiem %1$s</string>
+ <string name="new_session_uri_error">Podano niepoprawny adres</string>
+ <string name="new_session_session_name_error">Niepoprawna nazwa sesji</string>
<string name="sync_string_files">Pliki</string>
<string name="uploader_no_file_selected">Nie wybrano plików do wysłania</string>
<string name="setup_hint_username">Nazwa użytkownika</string>
<string name="setup_hint_password">Hasło</string>
- <string name="setup_hint_address">Adres sieciowy</string>
- <string name="setup_hint_show_password">Pokaż hasło</string>
- <string name="setup_title">Połącz do ownCloud</string>
+ <string name="setup_hint_address">Adres internetowy</string>
+ <string name="setup_hint_show_password">Wyświetlić hasło?</string>
+ <string name="setup_title">Połącz z %1$s</string>
<string name="setup_btn_connect">Połącz</string>
- <string name="uploader_btn_upload_text">Wyslij</string>
- <string name="uploader_wrn_no_account_title">Nie znaleziono kont</string>
- <string name="uploader_wrn_no_account_text">Nie wykryto kont ownCloud, załóż konto w celu używania aplikacji.</string>
+ <string name="uploader_btn_upload_text">Wyślij</string>
+ <string name="uploader_wrn_no_account_title">Nie znaleziono konta</string>
+ <string name="uploader_wrn_no_account_text">Nie wykryto kont %1$s na twoim urządzeniu. Załóż konto.</string>
<string name="uploader_wrn_no_account_setup_btn_text">Ustawienia</string>
<string name="uploader_wrn_no_account_quit_btn_text">Wyjdź</string>
<string name="uploader_wrn_no_content_title">Brak danych do wysłania</string>
<string name="uploader_wrn_no_content_text">Nie otrzymano danych. Nie ma nic do wysłania.</string>
- <string name="uploader_error_forbidden_content">ownCloud niema dostępu do udostępnionych zawartości</string>
+ <string name="uploader_error_forbidden_content">%1$s nie ma dostępu do udostępnionych treści</string>
<string name="uploader_info_uploading">Wysyłanie</string>
<string name="uploader_btn_create_dir_text">Stwórz katalog do wysyłania</string>
<string name="file_list_empty">Nie ma plików w tym katalogu.⏎ Nowe pliki można dodać wybierając w menu Wyślij.</string>
- <string name="filedetails_select_file">Dotknij po dodatkowe informacje</string>
+ <string name="filedetails_select_file">Dotknij plik aby wyświetlić dodatkowe informacje</string>
<string name="filedetails_size">Rozmiar:</string>
<string name="filedetails_type">Typ:</string>
<string name="filedetails_created">Utworzono:</string>
<string name="common_cancel_upload">Anuluj wysyłanie</string>
<string name="common_cancel">Anuluj</string>
<string name="common_save_exit">Zapisz i wyjdź</string>
- <string name="common_exit">Opuść ownCloud</string>
+ <string name="common_exit">Opuść %1$s</string>
<string name="common_error">Błąd</string>
<string name="about_title">O aplikacji</string>
<string name="delete_account">Usuń konto</string>
<string name="uploader_info_dirname">Nazwa katalogu</string>
<string name="uploader_upload_in_progress_ticker">Wysyłam…</string>
<string name="uploader_upload_in_progress_content">%1$d%% Wysyłanie %2$s</string>
- <string name="uploader_upload_succeeded_ticker">Wysyłanie zakończone</string>
+ <string name="uploader_upload_succeeded_ticker">Wysyłanie zakończone powodzeniem</string>
<string name="uploader_upload_succeeded_content_single">Wysyłanie %1$s zakończone sukcesem</string>
<string name="uploader_upload_succeeded_content_multiple">Wysłano %1$d plików</string>
- <string name="uploader_upload_failed_ticker">Wysyłanie nieudane</string>
- <string name="uploader_upload_failed_content_single">Wysyłanie %1$s plików nie powiodło się</string>
+ <string name="uploader_upload_failed_ticker">Wysyłanie nie powiodło się</string>
+ <string name="uploader_upload_failed_content_single">Wysyłanie %1$s nie powiodło się</string>
<string name="uploader_upload_failed_content_multiple">Wysyłanie nieudane: wysłano %1$d/%2$d plików</string>
- <string name="downloader_download_in_progress_ticker">Pobieram …</string>
+ <string name="downloader_download_in_progress_ticker">Pobieranie …</string>
<string name="downloader_download_in_progress_content">%1$d%% Pobieranie %2$s</string>
<string name="downloader_download_succeeded_ticker">Pobieranie zakończone</string>
<string name="downloader_download_succeeded_content">Pobrano %1$s plików</string>
<string name="downloader_download_failed_ticker">Pobieranie nieudane</string>
- <string name="downloader_download_failed_content">Pobieranie %1$s plików nie powiodło się</string>
+ <string name="downloader_download_failed_content">Pobieranie %1$s nie powiodło się</string>
<string name="common_choose_account">Wybierz konto</string>
<string name="sync_string_contacts">Kontakty</string>
<string name="sync_fail_ticker">Błąd synchronizacji</string>
<string name="sync_fail_content">Nie można było ukończyć synchronizacji %1$s </string>
<string name="sync_conflicts_in_favourites_ticker">Znaleziono konflikty</string>
- <string name="sync_conflicts_in_favourites_content">%1$d nie może zostać zsynchronizowany</string>
+ <string name="sync_conflicts_in_favourites_content">%1$d synchronizowanych plików nie może zostać zsynchronizowanych</string>
<string name="sync_fail_in_favourites_ticker">Synchronizacja plików nie powiodła się</string>
<string name="sync_fail_in_favourites_content">Zawartość %1$d plików nie może zostać synchronizowana (%2$d konfliktów)</string>
<string name="use_ssl">Użyj bezpiecznego połączenia</string>
- <string name="location_no_provider">ownCloud nie może śledzić urządzenia. Sprawdź ustawienia lokalizacji</string>
- <string name="pincode_enter_pin_code">Podaj PIN</string>
- <string name="pincode_enter_new_pin_code">Podaj nowy PIN</string>
- <string name="pincode_configure_your_pin">Wpisz PIN</string>
- <string name="pincode_configure_your_pin_explanation">Kod PIN bedzie wymagany za każdym razem, gdy aplikacja będzie uruchamiana.</string>
- <string name="pincode_reenter_your_pincode">Podaj PIN ponownie</string>
- <string name="pincode_remove_your_pincode">Usuń PIN</string>
+ <string name="location_no_provider">%1$s nie może śledzić urządzenia. Sprawdź ustawienia lokalizacji</string>
+ <string name="pincode_enter_pin_code">Podaj PIN aplikacji</string>
+ <string name="pincode_enter_new_pin_code">Podaj nowy PIN aplikacji</string>
+ <string name="pincode_configure_your_pin">Wpisz PIN aplikacji</string>
+ <string name="pincode_configure_your_pin_explanation">Kod PIN będzie wymagany za każdym razem, gdy aplikacja będzie uruchamiana.</string>
+ <string name="pincode_reenter_your_pincode">Ponownie wpisz PIN aplikacji</string>
+ <string name="pincode_remove_your_pincode">Usuń PIN aplikacji</string>
<string name="pincode_mismatch">Podane numery PIN są różne</string>
- <string name="pincode_wrong">Niepoprawny PIN</string>
- <string name="pincode_removed">Usunięto PIN</string>
- <string name="pincode_stored">Zapisano PIN</string>
+ <string name="pincode_wrong">Niepoprawny PIN aplikacji</string>
+ <string name="pincode_removed">Usunięto PIN aplikacji</string>
+ <string name="pincode_stored">Zapisano PIN aplikacji</string>
<string-array name="prefs_trackmydevice_intervall_keys">
- <item>15 Minut</item>
- <item>30 Minut</item>
- <item>60 Minut</item>
+ <item>15 minut</item>
+ <item>30 minut</item>
+ <item>60 minut</item>
</string-array>
<string-array name="prefs_trackmydevice_intervall_values">
<item>15</item>
</string-array>
<string name="auth_trying_to_login">Próbuję się zalogować...</string>
<string name="auth_no_net_conn_title">Brak połączenia sieciowego</string>
- <string name="auth_no_net_conn_message">Wykryto brak połączenia z siecią, sprawdź połączenie internetowe i spróbuj ponownie.</string>
+ <string name="auth_no_net_conn_message">Nie znaleziono połączenia sieciowego. Sprawdź połączenie internetowe i spróbuj ponownie.</string>
<string name="auth_connect_anyway">Połącz mimo wszystko</string>
<string name="auth_nossl_plain_ok_title">Nie można nawiązać bezpiecznego połączenia.</string>
- <string name="auth_nossl_plain_ok_message">Aplikacji nie można ustanowić bezpiecznego połączenia z serwerem. Niezabezpieczone połączenie jest dostępne. Możesz kontynuować lub anuluować.</string>
+ <string name="auth_nossl_plain_ok_message">Aplikacja nie można ustanowić bezpiecznego połączenia z serwerem. Niezabezpieczone połączenie jest dostępne. Możesz kontynuować lub anulować.</string>
<string name="auth_connection_established">Połączenie nawiązane</string>
<string name="auth_testing_connection">Testowanie połączenia…</string>
- <string name="auth_not_configured_title">Uszkodzona configuracja ownCloud</string>
- <string name="auth_not_configured_message">Wydaje się, że Twoja instalacja ownCloud nie jest poprawnie skonfigurowana. Aby uzyskać więcej informacji, skontaktuj się z administratorem.</string>
- <string name="auth_unknown_error_title">Napotkano nieznany błąd</string>
- <string name="auth_unknown_error_message">Wystąpił nieznany błąd. Proszę skontaktować się z autorem i dodać dzienniki z urządzenia.</string>
+ <string name="auth_not_configured_title">Uszkodzona konfiguracja serwera</string>
+ <string name="auth_not_configured_message">Wygląda na to, że twoja instancja ownCloud nie jest poprawnie skonfigurowana. Aby uzyskać więcej informacji, skontaktuj się z administratorem.</string>
+ <string name="auth_unknown_error_title">Wystąpił nieznany błąd!</string>
+ <string name="auth_unknown_error_message">Wystąpił nieznany błąd. Proszę skontaktować się z autorami i dodać dzienniki z urządzenia.</string>
<string name="auth_unknown_host_title">Nie mogę znaleźć hosta</string>
<string name="auth_unknown_host_message">Nie można znaleźć podanego hosta. Sprawdź nazwę hosta oraz dostępność serwera i spróbuj ponownie.</string>
- <string name="auth_incorrect_path_title">Nie znaleziono instalacji ownCloud</string>
- <string name="auth_incorrect_path_message">Aplikacja nie odnalazła instalacji ownCloud. Sprawdź URL i spróbuj ponownie.</string>
+ <string name="auth_incorrect_path_title">Nie znaleziono instancji ownCloud</string>
+ <string name="auth_incorrect_path_message">Aplikacja nie odnalazła instancji serwera pod podaną ścieżką. Sprawdź ścieżkę i spróbuj ponownie.</string>
<string name="auth_timeout_title">Serwer zbyt długo nie odpowiadał</string>
<string name="auth_incorrect_address_title">Zły format adresu URL</string>
<string name="auth_ssl_general_error_title">Inicjowanie SSL nie powiodło się</string>
<string name="auth_ssl_unverified_server_title">Tożsamość SSL serwera niezweryfikowana</string>
- <string name="auth_bad_oc_version_title">Nie rozpoznano wersji serwera ownCloud</string>
+ <string name="auth_bad_oc_version_title">Nie rozpoznano wersji serwera</string>
<string name="auth_wrong_connection_title">Nie można ustanowić połączenia</string>
<string name="auth_secure_connection">Nawiązano bezpieczne połączenie</string>
<string name="auth_login_details">Szczegóły logowania</string>
<string name="crashlog_send_report">Wyślij raport</string>
<string name="crashlog_dont_send_report">Nie wysyłaj raportu</string>
<string name="extensions_avail_title">Rozszerzenie dostępne!</string>
- <string name="extensions_avail_message">Twoja instalacja ownCloud wspiera zaawansowane rozszerzenia. Czy chcesz zobaczyć rozszerzenia dostępne dla Androida?</string>
+ <string name="extensions_avail_message">Twoja instancja serwera wspiera zaawansowane rozszerzenia. Czy chcesz zobaczyć rozszerzenia dostępne dla systemu Android?</string>
<string name="fd_keep_in_sync">Automatyczne aktualizuj plik</string>
<string name="common_share">Udostępnij</string>
<string name="common_rename">Zmień nazwę</string>
<string name="common_remove">Usuń</string>
- <string name="confirmation_remove_alert">Czy chcesz usunąć %1$s ?</string>
+ <string name="confirmation_remove_alert">Czy na pewno chcesz usunąć %1$s ?</string>
<string name="confirmation_remove_folder_alert">Czy usunąć %1$s oraz jego zawartość?</string>
<string name="confirmation_remove_local">Tylko lokalnie</string>
- <string name="confirmation_remove_folder_local">Tylko zasoby lokalna</string>
+ <string name="confirmation_remove_folder_local">Tylko zasoby lokalne</string>
<string name="confirmation_remove_remote">Usuń z serwera</string>
<string name="confirmation_remove_remote_and_local">Z serwera i telefonu</string>
<string name="remove_success_msg">Usunięto</string>
- <string name="remove_fail_msg">Nie można usunąć pliku</string>
+ <string name="remove_fail_msg">Nie można usunąć</string>
<string name="rename_dialog_title">Wprowadź nową nazwę</string>
- <string name="rename_local_fail_msg">Nie można zmienić nazwy lokalnej kopii; Spróbuj wybrać inną nazwę </string>
- <string name="rename_server_fail_msg">Nie można zmienić nazwy</string>
+ <string name="rename_local_fail_msg">Nie można zmienić nazwy kopii lokalnej; spróbuj wybrać inną nazwę </string>
+ <string name="rename_server_fail_msg">Zmiana nazwy nie powiodła się</string>
<string name="sync_file_fail_msg">Nie można sprawdzić zdalnego pliku</string>
<string name="sync_file_nothing_to_do_msg">Zawartość pliku została już synchronizowana</string>
<string name="create_dir_fail_msg">Nie można utworzyć katalogu</string>
<string name="wait_a_moment">Poczekaj chwilę</string>
- <string name="filedisplay_unexpected_bad_get_content">Nieoczekiwany problem; Spróbuj wybrać plik z innej aplikacji</string>
- <string name="filedisplay_no_file_selected">Nie wybrano żadnego pliku</string>
+ <string name="filedisplay_unexpected_bad_get_content">Nieoczekiwany problem; spróbuj wybrać plik z innej aplikacji</string>
+ <string name="filedisplay_no_file_selected">Nie wybrano żadnych plików</string>
<string name="ssl_validator_title">Uwaga</string>
<string name="ssl_validator_header">Nie można zweryfikować tożsamości strony</string>
<string name="ssl_validator_reason_cert_not_trusted">- Certyfikat serwera jest niezaufany</string>
<string name="ssl_validator_question">Zaakceptować certyfikat mimo wszystko?</string>
<string name="ssl_validator_not_saved">Nie można zapisać certyfikatu</string>
<string name="ssl_validator_btn_details_see">Szczegóły</string>
- <string name="ssl_validator_btn_details_hide">Schowaj</string>
- <string name="ssl_validator_label_subject">Wydane dla:</string>
- <string name="ssl_validator_label_issuer">Wydane przez:</string>
+ <string name="ssl_validator_btn_details_hide">Ukryj</string>
+ <string name="ssl_validator_label_subject">Wydany dla:</string>
+ <string name="ssl_validator_label_issuer">Wydany przez:</string>
<string name="ssl_validator_label_CN">Nazwa:</string>
<string name="ssl_validator_label_O">Organizacja:</string>
<string name="ssl_validator_label_OU">Jednostka organizacyjna:</string>
- <string name="ssl_validator_label_C">Państwo:</string>
- <string name="ssl_validator_label_ST">Województwo:</string>
+ <string name="ssl_validator_label_C">Kraj:</string>
+ <string name="ssl_validator_label_ST">Stan:</string>
<string name="ssl_validator_label_L">Lokalizacja:</string>
<string name="ssl_validator_label_validity">Ważność:</string>
- <string name="ssl_validator_label_validity_from">Z:</string>
+ <string name="ssl_validator_label_validity_from">Od:</string>
<string name="ssl_validator_label_validity_to">Do:</string>
<string name="ssl_validator_label_signature">Sygnatura:</string>
<string name="ssl_validator_label_signature_algorithm">Algorytm:</string>
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="app_name">ownCloud</string>
- <string name="main_password">Senha</string>
- <string name="main_login">Nome de usuário</string>
+ <string name="main_password">Senha:</string>
+ <string name="main_login">Nome de usuário:</string>
<string name="main_button_login">Login</string>
- <string name="main_welcome">Bem-vindo ao seu ownCloud</string>
+ <string name="main_welcome">Bem-vindo</string>
<string name="main_files">Arquivos</string>
<string name="main_music">Música</string>
- <string name="main_contacts">Contato</string>
+ <string name="main_contacts">Contatos</string>
<string name="main_calendar">Calendário</string>
<string name="main_bookmarks">Favoritos</string>
<string name="main_settings">Ajustes</string>
<string name="about_title">Sobre</string>
<string name="delete_account">Remover conta</string>
<string name="create_account">Criar conta</string>
- <string name="upload_chooser_title">Enviando de ...</string>
+ <string name="upload_chooser_title">Enviar de …</string>
<string name="uploader_info_dirname">Nome do diretório</string>
- <string name="uploader_upload_in_progress_ticker">Enviando ...</string>
+ <string name="uploader_upload_in_progress_ticker">Enviando …</string>
<string name="uploader_upload_in_progress_content">%1$d%% Enviando %2$s</string>
<string name="uploader_upload_succeeded_ticker">Envio bem sucedido</string>
<string name="uploader_upload_succeeded_content_single">%1$s foi enviado com sucesso</string>
<string name="uploader_upload_succeeded_content_multiple">%1$d arquivos foram enviados com sucesso</string>
- <string name="uploader_upload_failed_ticker">Envio falhou</string>
+ <string name="uploader_upload_failed_ticker">Falha no envio</string>
<string name="uploader_upload_failed_content_single">Envio de %1$s não pôde ser completado</string>
<string name="uploader_upload_failed_content_multiple">Envio falhou: %1$d/%2$d arquivos foram enviados</string>
- <string name="downloader_download_in_progress_ticker">Baixando ...</string>
+ <string name="downloader_download_in_progress_ticker">Baixando …</string>
<string name="downloader_download_in_progress_content">%1$d%% Baixando %2$s</string>
<string name="downloader_download_succeeded_ticker">Download bem sucedido</string>
<string name="downloader_download_succeeded_content">%1$s foi baixado com sucesso</string>
<string name="sync_fail_ticker">Sincronização falhou</string>
<string name="sync_fail_content">Sincronização de %1$s não pôde ser completada</string>
<string name="sync_conflicts_in_favourites_ticker">Conflitos encontrados</string>
+ <string name="sync_conflicts_in_favourites_content">%1$d arquivos \"manter sincronizados\" não puderam ser sincronizados</string>
+ <string name="sync_fail_in_favourites_ticker">Falha ao manter arquivos sincronizados</string>
+ <string name="sync_fail_in_favourites_content">O conteúdo de %1$d arquivos não puderam ser sincronizados (%2$d conflitos)</string>
<string name="use_ssl">Usar Conexão Segura</string>
- <string name="location_no_provider">ownCloud não pode rastrear seu dispositivo. Por favor verifique suas configurações de localização</string>
- <string name="pincode_enter_pin_code">Por favor insira o PIN da sua aplicação</string>
- <string name="pincode_enter_new_pin_code">Por favor, insira seu novo App PIN</string>
- <string name="pincode_configure_your_pin">Digite ownCloud App PIN</string>
+ <string name="location_no_provider">%1$s não pode rastrear seu dispositivo. Por favor verifique suas configurações de localização</string>
+ <string name="pincode_enter_pin_code">Por favor, insira o seu PIN de Aplicativo</string>
+ <string name="pincode_enter_new_pin_code">Por favor, insira seu novo PIN de Aplicativo</string>
+ <string name="pincode_configure_your_pin">Insira seu PIN de Aplicativo</string>
<string name="pincode_configure_your_pin_explanation">O PIN (senha) será solicitado toda vez que o aplicativo for iniciado</string>
- <string name="pincode_reenter_your_pincode">Redigite ownCloud App PIN, por favor</string>
- <string name="pincode_remove_your_pincode">Remova seu ownCloud App PIN</string>
- <string name="pincode_mismatch">Ambos ownCloud App PIN não são o mesmo</string>
- <string name="pincode_wrong">ownCloud App PIN incorreto</string>
- <string name="pincode_removed">ownCloud App PIN removido</string>
- <string name="pincode_stored">ownCloud App PIN armazenado</string>
+ <string name="pincode_reenter_your_pincode">Por favor, reinsira seu PIN de Aplicativo</string>
+ <string name="pincode_remove_your_pincode">Remova seu PIN de Aplicativo</string>
+ <string name="pincode_mismatch">Os PINs de Aplicativo não são iguais</string>
+ <string name="pincode_wrong">PIN de Aplicativo incorreto</string>
+ <string name="pincode_removed">PIN de Aplicativo removido</string>
+ <string name="pincode_stored">PIN de Aplicativo armazenado</string>
<string-array name="prefs_trackmydevice_intervall_keys">
- <item>15 Minutos</item>
- <item>30 Minutos</item>
- <item>60 Minutos</item>
+ <item>15 minutos</item>
+ <item>30 minutos</item>
+ <item>60 minutos</item>
</string-array>
<string-array name="prefs_trackmydevice_intervall_values">
<item>15</item>
<string name="auth_no_net_conn_message">Nenhuma conexão foi detectada, verifique sua conexão com a Internet e tente novamente.</string>
<string name="auth_connect_anyway">Conectar mesmo assim</string>
<string name="auth_nossl_plain_ok_title">Conexão segura indisponível.</string>
- <string name="auth_nossl_plain_ok_message">Aplicação não pôde estabelecer uma conexão segura. Entretanto conexão não-segura está disponível. Você pode continuar ou cancelar.</string>
+ <string name="auth_nossl_plain_ok_message">O aplicativo não pôde estabelecer uma conexão segura. Uma conexão não-segura está disponível. Você pode continuar ou cancelar.</string>
<string name="auth_connection_established">Conexão estabelecida</string>
<string name="auth_testing_connection">Testando conexão...</string>
- <string name="auth_not_configured_title">Configuração ownCloud mal formada</string>
- <string name="auth_not_configured_message">Parece que sua instância ownCloud não está corretamente configurada. Contate seu administrador para mais detalhes.</string>
- <string name="auth_unknown_error_title">Erro desconhecido ocorreu!</string>
- <string name="auth_unknown_error_message">Erro desconhecido ocorreu. Por favor contate os desenvolvedores e inclua dos logs do seu dispositivo.</string>
+ <string name="auth_not_configured_title">Configuração do servidor mal formada</string>
+ <string name="auth_not_configured_message">Parece que a instância do seu servidor não está corretamente configurada. Contate seu administrador para mais detalhes.</string>
+ <string name="auth_unknown_error_title">Ocorreu um erro desconhecido!</string>
+ <string name="auth_unknown_error_message">Ocorreu um erro desconhecido. Por favor contate o suporte e inclua registros do seu dispositivo.</string>
<string name="auth_unknown_host_title">Não pôde encontrar host</string>
<string name="auth_unknown_host_message">Couldn\'t find the entered host. Por favor verifique o nome de host, disponibilidade do servidor e tente novamente.</string>
- <string name="auth_incorrect_path_title">Instância ownCloud não encontrada</string>
- <string name="auth_incorrect_path_message">Aplicação não pôde encontrar uma instância ownCloud no caminho dado. Por favor, verifique e tente novamente.</string>
+ <string name="auth_incorrect_path_title">Instância de servidor não encontrada</string>
+ <string name="auth_incorrect_path_message">O aplicativo não pôde encontrar uma instância de servidor no caminho indicado. Por favor, verifique-o e tente novamente.</string>
<string name="auth_timeout_title">O servidor demorou demais a responder</string>
<string name="auth_incorrect_address_title">URL mal formada</string>
<string name="auth_ssl_general_error_title">Inicialização SSL falhou</string>
<string name="auth_unauthorized">Login / senha inválida</string>
<string name="auth_not_found">Caminho dado está errado</string>
<string name="auth_internal">Erro interno do servidor, código %1$d</string>
- <string name="crashlog_message">Aplicação terminou inesperadamente. Gostaria de submeter um relatório de erros?</string>
+ <string name="crashlog_message">O aplicativo terminou inesperadamente. Gostaria de enviar um relatório de erros?</string>
<string name="crashlog_send_report">Enviar relatório</string>
<string name="crashlog_dont_send_report">Não enviar relatório</string>
<string name="extensions_avail_title">Extensões disponíveis!</string>
<string name="sync_file_nothing_to_do_msg">Conteúdo do arquivo já foi sincronizado</string>
<string name="create_dir_fail_msg">Diretório não pôde ser criado</string>
<string name="wait_a_moment">Aguarde um momento</string>
- <string name="filedisplay_unexpected_bad_get_content">Problema inesperado ; por favor, tente usar outro app para selecionar o arquivo</string>
+ <string name="filedisplay_unexpected_bad_get_content">Problema inesperado; por favor, tente selecionar o arquivo com outro app</string>
<string name="filedisplay_no_file_selected">Nenhum arquivo foi selecionado</string>
<string name="ssl_validator_title">Aviso</string>
<string name="ssl_validator_header">A identidade do site não pode ser verificada</string>
<?xml version='1.0' encoding='UTF-8'?>
<resources>
- <string name="app_name">%1$s</string>
+ <string name="app_name">ownCloud</string>
<string name="main_password">Palavra-passe:</string>
<string name="main_login">Nome de Utilizador:</string>
<string name="main_button_login">Login</string>
<string name="main_bookmarks">Marcadores</string>
<string name="main_settings">Definições</string>
<string name="main_tit_accsetup">Configurar conta</string>
- <string name="main_wrn_accsetup">Não há contas ownCloud no seu aparelho. Para usar esta Aplicação, precisa de criar uma.</string>
+ <string name="main_wrn_accsetup">Não há contas no seu aparelho. Para usar esta Aplicação, precisa de criar uma.</string>
<string name="about_message">cliente Android %1$s\n\nversão: %1$s</string>
<string name="actionbar_sync">Actualizar</string>
<string name="actionbar_upload">Enviar</string>
<string name="app_name">ownCloud</string>
<string name="main_password">Heslo:</string>
<string name="main_login">Meno:</string>
- <string name="main_button_login">Login</string>
+ <string name="main_button_login">Prihlásenie</string>
<string name="main_welcome">Vitajte vo svojom ownCloud</string>
<string name="main_files">Súbory</string>
<string name="main_music">Hudba</string>
<string name="main_bookmarks">Záložky</string>
<string name="main_settings">Nastavenia</string>
<string name="main_tit_accsetup">Nastavenie účtu</string>
- <string name="main_wrn_accsetup">Vo vašom zariadení nie sú žiadne účty ownCloud. Vytvorte si účet ak chcete používať túto aplikáciu.</string>
+ <string name="main_wrn_accsetup">Vo vašom zariadení nie sú žiadne účty. Vytvorte si účet ak chcete používať túto aplikáciu.</string>
<string name="about_message">%1$s Android App\n\nverzia: %2$s</string>
<string name="actionbar_sync">Obnoviť</string>
<string name="actionbar_upload">Nahraj súbor</string>
<string name="prefs_category_trackmydevice">Sledovanie zariadenia</string>
<string name="prefs_add_session">Vytvoriť nové sedenie</string>
<string name="prefs_create_img_thumbnails">Vytvor náhľad obrázku</string>
- <string name="prefs_select_oc_account">Výbor účet</string>
+ <string name="prefs_select_oc_account">Vyber účet</string>
<string name="prefs_summary_select_oc_account">Vyberte účet pre túto aplikáciu.</string>
<string name="prefs_trackmydevice">Sledovanie zariadenia</string>
<string name="prefs_trackmydevice_summary_off">Povoliť sledovanie polohy zariadenia</string>
<string name="prefs_instant_upload">Zapnúť okamžité odosielanie</string>
<string name="prefs_instant_upload_summary">Okamžite odosielať fotky z fotoaparátu</string>
<string name="auth_host_url">ownCloud URL</string>
- <string name="auth_username">PoužÃvateľská meno</string>
+ <string name="auth_username">PoužÃvateľské meno</string>
<string name="auth_password">Heslo</string>
- <string name="auth_register">Som nový v ownCloud</string>
- <string name="new_session_uri_error">Zadané nesprávne URL</string>
+ <string name="auth_register">Som nový v %1$s</string>
+ <string name="new_session_uri_error">Zadaná nesprávna URL</string>
<string name="new_session_session_name_error">Nesprávny názov sedenia</string>
<string name="sync_string_files">Súbory</string>
<string name="uploader_no_file_selected">Nebol označený žiadny súbor pre odoslanie</string>
- <string name="setup_hint_username">Meno užívateľa</string>
+ <string name="setup_hint_username">Meno používateľa</string>
<string name="setup_hint_password">Heslo</string>
<string name="setup_hint_address">Web adresa</string>
<string name="setup_hint_show_password">Zobraziť heslo?</string>
<string name="setup_title">Pripojiť k ownCloud</string>
<string name="setup_btn_connect">Pripoj</string>
<string name="uploader_btn_upload_text">Nahrať</string>
- <string name="uploader_wrn_no_account_title">Účet sa nenašie</string>
+ <string name="uploader_wrn_no_account_title">Účet sa nenašiel</string>
<string name="uploader_wrn_no_account_text">Na tomto zariadení nie je zadaný žiadny ownCloud účet. Zadajte ho prosím.</string>
<string name="uploader_wrn_no_account_setup_btn_text">Nastavenie</string>
<string name="uploader_wrn_no_account_quit_btn_text">Koniec</string>
<string name="uploader_wrn_no_content_text">Nedodaný žiaden obsah. Nič na odoslanie.</string>
<string name="uploader_error_forbidden_content">%1$s nemá práva pre prístup k zdieľanému obsahu</string>
<string name="uploader_info_uploading">Nahrávanie</string>
- <string name="uploader_btn_create_dir_text">Vytvoriť adresár pre nahrávanie</string>
+ <string name="uploader_btn_create_dir_text">Vytvoriť priečinok pre nahrávanie</string>
<string name="file_list_empty">Priečinok neobsahuje súbory.\nNové súbory môžete pridať cez \"Upload\".</string>
<string name="filedetails_select_file">Viac informácií získate kliknutím na súbor.</string>
<string name="filedetails_size">Veľkosť:</string>
<string name="delete_account">Zmazať účet</string>
<string name="create_account">Vytvoriť účet</string>
<string name="upload_chooser_title">Odoslať z ...</string>
- <string name="uploader_info_dirname">Názov adresára</string>
+ <string name="uploader_info_dirname">Názov priečinka</string>
<string name="uploader_upload_in_progress_ticker">Odosielam ...</string>
<string name="uploader_upload_in_progress_content">%1$d%% Odosielam %2$s</string>
<string name="uploader_upload_succeeded_ticker">Odoslanie bolo úspešné</string>
<string name="use_ssl">Použiť zabezpečené pripojenie</string>
<string name="location_no_provider">ownCloud nemôže sledovať polohu vášho zariadenia. Skontrolujte nastavenia umiestnenia.</string>
<string name="pincode_enter_pin_code">Zadajte PIN aplikácie</string>
- <string name="pincode_enter_new_pin_code">Zadajte nové PIN aplikácie</string>
- <string name="pincode_configure_your_pin">Zadajte PIN ownCloud aplikácie</string>
+ <string name="pincode_enter_new_pin_code">Zadajte nový PIN aplikácie</string>
+ <string name="pincode_configure_your_pin">Zadajte PIN aplikácie</string>
<string name="pincode_configure_your_pin_explanation">Pri každom spustení aplikácie bude vyžadovaný PIN</string>
- <string name="pincode_reenter_your_pincode">Zadajte znovu PIN ownCloud aplikácie</string>
- <string name="pincode_remove_your_pincode">Zrušiť PIN pre ownCloud aplikáciu</string>
+ <string name="pincode_reenter_your_pincode">Zadajte znovu PIN aplikácie</string>
+ <string name="pincode_remove_your_pincode">Zrušiť PIN pre aplikáciu</string>
<string name="pincode_mismatch">PIN sa neshodujú</string>
<string name="pincode_wrong">Nesprávny PIN aplikácie</string>
<string name="pincode_removed">PIN aplikácie bol odstránený</string>
<item>60</item>
</string-array>
<string name="auth_trying_to_login">Pokus o pripojenie...</string>
- <string name="auth_no_net_conn_title">Bez siete</string>
+ <string name="auth_no_net_conn_title">Bez sieťového pripojenia</string>
<string name="auth_no_net_conn_message">Skontrolujte pripojenie k sieti a opakujte pripojenie znovu.</string>
<string name="auth_connect_anyway">Aj tak pripojiť</string>
<string name="auth_nossl_plain_ok_title">Nie je k dispozícii bezpečné pripojenie</string>
<string name="auth_connection_established">Pripojenie vytvorené</string>
<string name="auth_testing_connection">Testovane pripojenia...</string>
<string name="auth_not_configured_title">Nesprávna konfigurácia ownCloud</string>
- <string name="auth_not_configured_message">Nastavenie ownCloud nie je správne. Kontaktujte správcu pre získanie viac informácií.</string>
+ <string name="auth_not_configured_message">Nastavenie ownCloud nie je správne. Kontaktujte administrátora pre získanie viac informácií.</string>
<string name="auth_unknown_error_title">Nastala neznáma chyba!</string>
<string name="auth_unknown_error_message">Nastala neznáma chyba. Kontaktujte podporu a pripojte záznam z Vášho zariadenia.</string>
<string name="auth_unknown_host_title">Nemožno nájsť hosta</string>
<string name="auth_unknown_host_message">Nemôžm sa pripojiť k serveru. Skontrolujte nastavenia servera, či beží a skúste to znovu.</string>
- <string name="auth_incorrect_path_title">ownCloud instance not found</string>
+ <string name="auth_incorrect_path_title">ownCloud inštancia nebola nájdená</string>
<string name="auth_incorrect_path_message">Aplikácia na zadanej adrese nenašla inštanciu ownCloud. Skontrolujte cestu a skúste to znovu.</string>
<string name="auth_timeout_title">Serveru trvá odpoveď príliš dlho</string>
<string name="auth_incorrect_address_title">Poškodená URL</string>
--- /dev/null
+<?xml version='1.0' encoding='UTF-8'?>
+<resources/>
<?xml version='1.0' encoding='UTF-8'?>
<resources>
+ <string name="app_name">ownCloud</string>
+ <string name="main_password">Лозинка:</string>
<string name="main_login">Корисничко име:</string>
- <string name="main_button_login">Ð\9fÑ\80иÑ\98ава</string>
- <string name="main_files">ФаÑ\98лови</string>
+ <string name="main_button_login">Ð\9fÑ\80иÑ\98ави ме</string>
+ <string name="main_files">Ð\94аÑ\82оÑ\82еке</string>
<string name="main_music">Музика</string>
<string name="main_contacts">Контакти</string>
- <string name="main_settings">Подешавања</string>
- <string name="actionbar_upload">Пошаљи</string>
- <string name="actionbar_upload_files">Фајлови</string>
- <string name="actionbar_settings">Подешавања</string>
+ <string name="main_calendar">Календар</string>
+ <string name="main_bookmarks">Обележивачи</string>
+ <string name="main_settings">Поставке</string>
+ <string name="main_tit_accsetup">Подешавање налога</string>
+ <string name="actionbar_sync">Освежи</string>
+ <string name="actionbar_upload">Отпреми</string>
+ <string name="actionbar_upload_from_apps">Садржај са других апликација</string>
+ <string name="actionbar_upload_files">Датотеке</string>
+ <string name="actionbar_mkdir">Направи фасциклу</string>
+ <string name="actionbar_search">Претражи</string>
+ <string name="actionbar_settings">Поставке</string>
<string name="prefs_category_general">Опште</string>
+ <string name="prefs_category_trackmydevice">Праћење уређаја</string>
+ <string name="prefs_add_session">Додај нову сесију</string>
+ <string name="prefs_create_img_thumbnails">Направи умањене приказе слика</string>
+ <string name="prefs_select_oc_account">Изаберите налог</string>
+ <string name="prefs_trackmydevice_interval_summary">Ажурирај на %1$s мин.</string>
+ <string name="prefs_accounts">Налози</string>
+ <string name="prefs_instant_upload_summary">Тренутно отпремај фотографије сликане камером</string>
<string name="auth_username">Корисничко име</string>
<string name="auth_password">Лозинка</string>
<string name="sync_string_files">Фајлови</string>
+ <string name="uploader_no_file_selected">Нисте изабрали датотеку за отпремање</string>
<string name="setup_hint_username">Корисничко име</string>
<string name="setup_hint_password">Лозинка</string>
- <string name="uploader_btn_upload_text">Пошаљи</string>
- <string name="filedetails_download">Преузимање</string>
+ <string name="setup_hint_address">Веб адреса</string>
+ <string name="setup_hint_show_password">Приказати лозинку?</string>
+ <string name="setup_btn_connect">Повежи ме</string>
+ <string name="uploader_btn_upload_text">Отпреми</string>
+ <string name="uploader_wrn_no_account_title">Нема налога</string>
+ <string name="uploader_wrn_no_account_setup_btn_text">Подеси</string>
+ <string name="uploader_wrn_no_account_quit_btn_text">Изађи</string>
+ <string name="uploader_wrn_no_content_title">Нема садржаја за отпремање</string>
+ <string name="uploader_wrn_no_content_text">Садржај није примљен. Нема ништа да се отпреми.</string>
+ <string name="uploader_info_uploading">Отпремање</string>
+ <string name="uploader_btn_create_dir_text">Направи фасциклу за отпремање</string>
+ <string name="file_list_empty">Нема датотека у овој фасцикли.\nНове датотеке можете да додате путем опције „Отпреми“.</string>
+ <string name="filedetails_select_file">Додирните датотеку ради приказа додатних информација.</string>
+ <string name="filedetails_size">Величина:</string>
+ <string name="filedetails_type">Врста:</string>
+ <string name="filedetails_created">Направљено:</string>
+ <string name="filedetails_modified">Измењено:</string>
+ <string name="filedetails_download">Преузми</string>
+ <string name="filedetails_sync_file">Освежи</string>
+ <string name="filedetails_open">Отвори</string>
<string name="common_yes">Да</string>
+ <string name="common_no">Не</string>
+ <string name="common_ok">У реду</string>
<string name="common_cancel_upload">Прекини слање</string>
<string name="common_cancel">Откажи</string>
+ <string name="common_save_exit">Сачувај и изађи</string>
<string name="common_error">Грешка</string>
+ <string name="about_title">О програму</string>
+ <string name="delete_account">Обриши налог</string>
+ <string name="create_account">Отвори налог</string>
+ <string name="upload_chooser_title">Отпреми из…</string>
+ <string name="uploader_info_dirname">Име фасцикле</string>
+ <string name="uploader_upload_in_progress_ticker">Отпремам…</string>
+ <string name="uploader_upload_in_progress_content">%1$d%% Отпремам %2$s</string>
+ <string name="uploader_upload_succeeded_ticker">Отпремање је успело</string>
+ <string name="uploader_upload_failed_ticker">Отпремање није успело</string>
+ <string name="uploader_upload_failed_content_single">Не могу да довршим отпремање датотеке %1$s</string>
+ <string name="uploader_upload_failed_content_multiple">Отпремање није успело. Отпремљено датотека: %1$d/%2$d</string>
+ <string name="downloader_download_in_progress_ticker">Преузимам…</string>
+ <string name="downloader_download_in_progress_content">%1$d%% Преузимам %2$s</string>
+ <string name="downloader_download_failed_ticker">Преузимање није успело</string>
+ <string name="downloader_download_failed_content">Не могу да довршим преузимање датотеке %1$s</string>
+ <string name="common_choose_account">Изабери налог</string>
<string name="sync_string_contacts">Контакти</string>
- <string name="common_share">Дељење</string>
+ <string name="sync_fail_ticker">Синхронизовање није успело</string>
+ <string name="sync_fail_content">Не могу да довршим синхронизацију датотеке %1$s</string>
+ <string name="use_ssl">Безбедна веза</string>
+ <string name="pincode_enter_pin_code">Унесите PIN апликације</string>
+ <string name="pincode_enter_new_pin_code">Унесите нови PIN апликације</string>
+ <string name="pincode_configure_your_pin_explanation">Са сваким покретањем апликације мораћете да унесете PIN</string>
+ <string-array name="prefs_trackmydevice_intervall_keys">
+ <item>15 минута</item>
+ <item>30 минута</item>
+ <item>60 минута</item>
+ </string-array>
+ <string-array name="prefs_trackmydevice_intervall_values">
+ <item>15</item>
+ <item>30</item>
+ <item>60</item>
+ </string-array>
+ <string name="auth_trying_to_login">Покушавам да вас пријавим…</string>
+ <string name="auth_no_net_conn_title">Нема мрежне везе</string>
+ <string name="auth_connect_anyway">Ипак ме повежи</string>
+ <string name="auth_nossl_plain_ok_title">Безбедна веза није доступна.</string>
+ <string name="auth_connection_established">Веза је успостављена</string>
+ <string name="auth_testing_connection">Тестирам везу…</string>
+ <string name="auth_unknown_error_title">Дошло је до непознате грешке.</string>
+ <string name="auth_unknown_host_title">Не могу да пронађем домаћина</string>
+ <string name="auth_unknown_host_message">Не могу да пронађем наведеног домаћина. Проверите име домаћина и доступност сервера па покушајте поново.</string>
+ <string name="auth_incorrect_path_title">Не могу да пронађем примерак сервера</string>
+ <string name="auth_timeout_title">Серверу је требало предуго да се одазове</string>
+ <string name="auth_incorrect_address_title">Погрешно уобличена адреса</string>
+ <string name="auth_ssl_general_error_title">Покретање SSL-а није успело</string>
+ <string name="auth_ssl_unverified_server_title">Непроверен идентитет SSL сервера</string>
+ <string name="auth_wrong_connection_title">Не могу да успоставим везу</string>
+ <string name="auth_secure_connection">Безбедна веза је успостављена</string>
+ <string name="auth_login_details">Подаци за пријаву</string>
+ <string name="crashlog_send_report">Пошаљи извештај</string>
+ <string name="crashlog_dont_send_report">Не шаљи извештај</string>
+ <string name="extensions_avail_title">Доступна су проширења.</string>
+ <string name="fd_keep_in_sync">Редовно ажурирај датотеку</string>
+ <string name="common_share">Дели</string>
<string name="common_rename">Преименуј</string>
+ <string name="common_remove">Уклони</string>
+ <string name="confirmation_remove_alert">Желите ли да уклоните %1$s?</string>
+ <string name="confirmation_remove_local">Само локално</string>
+ <string name="confirmation_remove_remote">Уклони са сервера</string>
+ <string name="confirmation_remove_remote_and_local">Удаљено и локално</string>
+ <string name="rename_server_fail_msg">Не могу да довршим преименовање</string>
+ <string name="create_dir_fail_msg">Не могу да направим фасциклу</string>
+ <string name="wait_a_moment">Сачекајте тренутак</string>
+ <string name="filedisplay_no_file_selected">Нисте изабрали датотеку</string>
+ <string name="ssl_validator_title">Упозорење</string>
+ <string name="ssl_validator_header">Не могу да проверим идентитет сајта</string>
+ <string name="ssl_validator_reason_cert_not_trusted">– Сертификат сервера није поверљив</string>
+ <string name="ssl_validator_reason_cert_expired">– Сертификат сервера је истекао</string>
+ <string name="ssl_validator_reason_hostname_not_verified">– Адреса се не поклапа са именом домаћина у сертификату</string>
+ <string name="ssl_validator_certificate_not_available">Не могу да прибавим сертификат сервера</string>
+ <string name="ssl_validator_question">Желите ли ипак да означите сертификат као поверљив?</string>
+ <string name="ssl_validator_not_saved">Не могу да сачувам сертификат</string>
+ <string name="ssl_validator_btn_details_see">Подаци</string>
+ <string name="ssl_validator_btn_details_hide">Сакриј</string>
+ <string name="ssl_validator_label_subject">Издато за:</string>
+ <string name="ssl_validator_label_issuer">Издао/ла:</string>
+ <string name="ssl_validator_label_CN">Уобичајено име:</string>
+ <string name="ssl_validator_label_O">Организација:</string>
+ <string name="ssl_validator_label_OU">Организациона јединица:</string>
+ <string name="ssl_validator_label_C">Земља:</string>
+ <string name="ssl_validator_label_ST">Држава:</string>
+ <string name="ssl_validator_label_L">Локација:</string>
+ <string name="ssl_validator_label_validity">Ваљаност:</string>
+ <string name="ssl_validator_label_validity_from">Од:</string>
+ <string name="ssl_validator_label_validity_to">За:</string>
+ <string name="ssl_validator_label_signature">Потпис:</string>
+ <string name="ssl_validator_label_signature_algorithm">Алгоритам:</string>
+ <string name="text_placeholder">Ово је чувар места</string>
+ <string name="instant_upload_on_wifi">Отпремај слике само путем бежичне мреже</string>
+ <string name="conflict_title">Ажурирај сукоб</string>
</resources>
--- /dev/null
+<?xml version='1.0' encoding='UTF-8'?>
+<resources/>
<string name="main_wrn_accsetup">Cihazınızda ownCloud hesabı bulunmamaktadır. Bu uygulamayı kullanabilmeniz için ownCloud hesabı oluşturmalısınız.</string>
<string name="actionbar_sync">Eşitleme hesabi</string>
<string name="actionbar_upload">Dosya yükle</string>
+ <string name="actionbar_upload_from_apps">Diğer uygulamalardan içerik</string>
<string name="actionbar_upload_files">Dosyalar</string>
<string name="actionbar_mkdir">Klasör yarat</string>
<string name="actionbar_search">Arama</string>
<string name="uploader_wrn_no_account_setup_btn_text">Kurulum</string>
<string name="uploader_wrn_no_account_quit_btn_text">Çıkış</string>
<string name="uploader_wrn_no_content_title">Yüklenecek içerik yok</string>
+ <string name="uploader_wrn_no_content_text">Yüklenecek içerik yok. Yüklenecek dosya yok.</string>
<string name="uploader_error_forbidden_content">ownCloud, paylaşılan içeriğe erişim izni vermiyor</string>
<string name="uploader_info_uploading">Yükleniyor</string>
<string name="uploader_btn_create_dir_text">Yükleme için dizin oluştur</string>
+ <string name="file_list_empty">Klasörde dosya yok. Yeni dosyalar yükle\'ye tıklayarak eklenebilir.</string>
<string name="filedetails_select_file">Ek bilgileri görmek için dosyaya tıklayınız.</string>
<string name="filedetails_size">Boyut:</string>
<string name="filedetails_type">Tür:</string>
<string name="common_choose_account">Hesap seçiniz</string>
<string name="sync_string_contacts">Kontaklar</string>
<string name="sync_fail_ticker">Eşitleme başarısız</string>
+ <string name="sync_fail_content">%1$s Senkronizasyonu tamamlanamadı</string>
<string name="sync_conflicts_in_favourites_ticker">Çakışma bulundu</string>
<string name="use_ssl">Güvenli bağlanti kullan</string>
<string name="location_no_provider">ownCloud cihazınızı takip edemiyor. Lütfen konum ayarlarınızı kontrol ediniz</string>
<string name="pincode_enter_pin_code">Lütfen uygulama PIN\'ınızı giriniz</string>
<string name="pincode_enter_new_pin_code">Lütfen yeni uygulama PIN\'ınızı giriniz</string>
<string name="pincode_configure_your_pin">ownCloud App PIN giriniz</string>
+ <string name="pincode_configure_your_pin_explanation">PIN uygulama yeniden başladığında tekrar sorulacak</string>
<string name="pincode_reenter_your_pincode">Lütfen, ownCloud App PIN ni tekrar giriniz</string>
<string name="pincode_remove_your_pincode">ownCloud App PIN\'nizi kaldırınız.</string>
<string name="pincode_mismatch">Her iki ownCloud App PIN aynı değil.</string>
<string name="filedisplay_unexpected_bad_get_content">Beklenmeyen problem ; lütfen, dosya seçmek için diğer uygulamayı deneyin</string>
<string name="filedisplay_no_file_selected">Hiçbir dosya seçilmedi</string>
<string name="ssl_validator_title">Uyarı</string>
+ <string name="ssl_validator_header">Bu sitenin sertifikası doğrulanamadı</string>
+ <string name="ssl_validator_reason_cert_not_trusted">- Sunucu sertifikası güvenilmez</string>
<string name="ssl_validator_reason_cert_expired">- Sunucu sertifikasının süresi geçmiş</string>
+ <string name="ssl_validator_reason_hostname_not_verified">- URL adresi sunucu isminin sertifikası ile uyuşmuyor</string>
<string name="ssl_validator_certificate_not_available">Sunucu sertifikası elde edilemedi</string>
<string name="ssl_validator_question">Sertifikaya yine de güvenmek istiyor musunuz?</string>
<string name="ssl_validator_not_saved">Sertifika kaydedilemedi</string>
<string name="ssl_validator_label_signature_algorithm">Algoritma:</string>
<string name="text_placeholder">Bu bir yer tutucudur</string>
<string name="instant_upload_on_wifi">Resimleri sadece WiFi bağlantısında yükle</string>
+ <string name="instant_upload_path">/AnındaYükle</string>
<string name="conflict_title">Çakışmayı güncelle</string>
<string name="conflict_keep_both">İkisini de koru</string>
<string name="conflict_overwrite">Üzerine yaz</string>
<string name="main_settings">Налаштування</string>
<string name="main_tit_accsetup">Налаштування облікового запису</string>
<string name="main_wrn_accsetup">На Вашому пристрої відсутні облікові запси ownCloud. Для того, щоб користуватися цим ПО, Вам потрібно створити обліковий запис.</string>
- <string name="about_message">ownCloud Android клієнт\n\nверсія: %1$s</string>
+ <string name="about_message">%1$s Android клієнт\n\nверсія: %2$s</string>
<string name="actionbar_sync">Оновити</string>
<string name="actionbar_upload">Відвантажити</string>
<string name="actionbar_upload_from_apps">Вміст із інших програм</string>
<string name="prefs_trackmydevice_summary_off">Дозволити ownCloud стежити за місцезнаходженням Вашого пристрою</string>
<string name="prefs_trackmydevice_summary_on">Ваш ownCloud стежить за цим пристроєм</string>
<string name="prefs_trackmydevice_interval">Інтервал оновлення</string>
- <string name="prefs_trackmydevice_interval_summary">Оновлювати кожні %1$ хвилин</string>
+ <string name="prefs_trackmydevice_interval_summary">Оновлювати кожні %1$s хвилин</string>
<string name="prefs_accounts">Облікові записи</string>
<string name="prefs_manage_accounts">Управління обліковими записами</string>
<string name="prefs_pincode">ownCloud програмний PIN</string>
<string name="downloader_download_in_progress_ticker">Зкачування …</string>
<string name="downloader_download_in_progress_content">%1$d%% Зкачування %2$s</string>
<string name="downloader_download_succeeded_ticker">Успішно зкачано</string>
- <string name="downloader_download_succeeded_content">%1$ успішно завантажено</string>
+ <string name="downloader_download_succeeded_content">%1$s успішно завантажено</string>
<string name="downloader_download_failed_ticker">Завантаження не вдалося</string>
- <string name="downloader_download_failed_content">Завантаження %1$ не вдається завершити</string>
+ <string name="downloader_download_failed_content">Завантаження %1$s не вдається завершити</string>
<string name="common_choose_account">Оберіть обліковий запис</string>
<string name="sync_string_contacts">Контакти</string>
<string name="sync_fail_ticker">Помилка синхронізації</string>
- <string name="sync_fail_content">Синхронізація %1$не вдалась</string>
+ <string name="sync_fail_content">Синхронізація %1$s не вдалась</string>
<string name="sync_conflicts_in_favourites_ticker">Конфліктів знайдено</string>
<string name="sync_conflicts_in_favourites_content">%1$d файли, які мають бути синхронізованими не можуть синхронізуватися</string>
<string name="sync_fail_in_favourites_ticker">Синхронізувати файли не вдалося</string>
--- /dev/null
+<?xml version='1.0' encoding='UTF-8'?>
+<resources>
+ <string name="main_settings">سیٹینگز</string>
+ <string name="actionbar_settings">سیٹینگز</string>
+ <string name="auth_username">یوزر نیم</string>
+ <string name="auth_password">پاسورڈ</string>
+ <string name="setup_hint_username">یوزر نیم</string>
+ <string name="setup_hint_password">پاسورڈ</string>
+</resources>
<string name="sync_fail_ticker">Đồng bộ thất bại</string>
<string name="sync_fail_content">Đồng bộ %1$s không thể hoàn thành</string>
<string name="sync_conflicts_in_favourites_ticker">Tìm thấy xung đột</string>
+ <string name="sync_conflicts_in_favourites_content">%1$d file trong hàng đợi đồng bộ không thể được đồng bộ</string>
+ <string name="sync_fail_in_favourites_ticker">Các file trong hàng đợi đồng bộ không thành công</string>
<string name="sync_fail_in_favourites_content">Nội dung tập tin %1$d không thể đồng bộ (%2$d xung đột)</string>
<string name="use_ssl">Sử dụng kết nối an toàn</string>
<string name="location_no_provider">ownCloud không thể theo dõi điện thoại của bạn. Vui lòng kiểm tra cài đặt vị trí của bạn</string>
<string name="auth_wrong_connection_title">Không thể thiết lập kết nối</string>
<string name="auth_secure_connection">Kết nối an toàn đã được thiết lập</string>
<string name="auth_login_details">Chi tiết đăng nhập</string>
+ <string name="auth_unauthorized">Sai tên đăng nhập/ mật khẩu</string>
<string name="auth_not_found">Đường dẫn đã cho không đúng</string>
<string name="auth_internal">Lỗi máy chủ nội bộ, mã lỗi %1$d</string>
<string name="crashlog_message">Ứng dụng chấm dứt đột ngột. Bạn có muốn gửi báo cáo sự cố?</string>
<string name="confirmation_remove_alert">Bạn có thực sự muốn xóa %1$s ?</string>
<string name="confirmation_remove_folder_alert">Bạn có thật sự muốn xóa %1$s và nội dung của nó ?</string>
<string name="confirmation_remove_local">Chỉ cục bộ</string>
+ <string name="confirmation_remove_folder_local">Chỉ nội dung trên máy</string>
<string name="confirmation_remove_remote">Xóa từ máy chủ</string>
<string name="confirmation_remove_remote_and_local">Remote và local</string>
<string name="remove_success_msg">Xóa thành công</string>
<string name="ssl_validator_label_signature_algorithm">Thuật toán :</string>
<string name="text_placeholder">Vị trí này đã được đặt chỗ trước</string>
<string name="instant_upload_on_wifi">Tải hình ảnh lên thông qua WiFi</string>
+ <string name="instant_upload_path">/Upload tức thì</string>
<string name="conflict_title">Cập nhật xung đột</string>
<string name="conflict_message">%s là tập tin từ xa nó không đồng bộ với tập tin máy bạn . Nếu bạn tiếp tục sẽ thay đổi nội dung của tập tin trên máy chủ.</string>
<string name="conflict_keep_both">Giữ cho cả hai</string>
<string name="filedetails_sync_file">刷新</string>
<string name="filedetails_redownload">重新下载</string>
<string name="filedetails_open">打开</string>
+ <string name="filedetails_renamed_in_upload_msg">文件在上传过程中被重命名为 %1$s </string>
<string name="common_yes">是</string>
<string name="common_no">否</string>
<string name="common_ok">好</string>
+ <string name="common_cancel_download">取消下载</string>
<string name="common_cancel_upload">取消上传</string>
<string name="common_cancel">取消</string>
<string name="common_save_exit">保存 & 退出</string>
<string name="sync_string_contacts">联系人</string>
<string name="sync_fail_ticker">同步失败</string>
<string name="sync_fail_content">不能完成 %1$s 的同步</string>
+ <string name="sync_conflicts_in_favourites_ticker">存在冲突</string>
+ <string name="sync_conflicts_in_favourites_content">%1$d 计划同步文件无法同步</string>
<string name="use_ssl">使用安全连接</string>
<string name="location_no_provider">ownCloud 不能跟踪您的设备。请检查您的位置设置</string>
<string name="pincode_enter_pin_code">请插入您的应用 PIN</string>
<string name="sync_fail_ticker">同步失败</string>
<string name="sync_fail_content"> %1$s同步未完成。</string>
<string name="sync_conflicts_in_favourites_ticker">发现冲突</string>
+ <string name="sync_conflicts_in_favourites_content">%1$d 文件无法同步</string>
+ <string name="sync_fail_in_favourites_ticker">文件同步失败</string>
<string name="sync_fail_in_favourites_content">无法同步 %1$d 文件内容(与 %2$d 冲突)</string>
<string name="use_ssl">使用安全链接</string>
<string name="location_no_provider">ownCloud不能跟踪你的设备。请检查你的位置设置。</string>
<string name="ssl_validator_label_signature_algorithm">算法:</string>
<string name="text_placeholder">占位符一枚</string>
<string name="instant_upload_on_wifi">仅通过WIFI上传图片。</string>
+ <string name="instant_upload_path">/InstantUpload</string>
<string name="conflict_title">上传冲突</string>
<string name="conflict_message">远程文件 %s 未与本地文件同步。继续将替换服务器上的文件内容。</string>
<string name="conflict_keep_both">保留两者</string>
<string name="main_password">密碼:</string>
<string name="main_login">使用者名稱:</string>
<string name="main_button_login">登入</string>
- <string name="main_welcome">歡迎來到您的ownCloud</string>
+ <string name="main_welcome">歡迎</string>
<string name="main_files">檔案</string>
<string name="main_music">音樂</string>
<string name="main_contacts">通訊錄</string>
<string name="main_bookmarks">書籤</string>
<string name="main_settings">設定</string>
<string name="main_tit_accsetup">設定帳號</string>
- <string name="main_wrn_accsetup">您尚未在裝置上設定您的ownCloud帳號. 您必需建立一組帳號才能繼續使用.</string>
- <string name="actionbar_sync">更新</string>
+ <string name="main_wrn_accsetup">您尚未在裝置上設定您的 ownCloud 帳號,您必需建立一組帳號才能繼續使用。</string>
+ <string name="actionbar_sync">重新整理</string>
<string name="actionbar_upload">上傳檔案</string>
<string name="actionbar_upload_files">檔案</string>
<string name="actionbar_mkdir">建立目錄</string>
<string name="actionbar_search">搜尋</string>
<string name="actionbar_settings">設定</string>
<string name="prefs_category_general">一般</string>
+ <string name="prefs_category_trackmydevice">裝置追蹤</string>
+ <string name="prefs_add_session">增加新連線</string>
<string name="prefs_create_img_thumbnails">建立圖片縮圖</string>
<string name="prefs_select_oc_account">選擇一個帳號</string>
+ <string name="prefs_summary_select_oc_account">您要使用哪幾個帳號?</string>
+ <string name="prefs_trackmydevice">裝置追蹤</string>
+ <string name="prefs_trackmydevice_summary_off">啓用此應用程式以追蹤所在位置</string>
+ <string name="prefs_trackmydevice_summary_on">此應用程式會追蹤這個裝置</string>
<string name="prefs_trackmydevice_interval">更新間隔</string>
<string name="prefs_trackmydevice_interval_summary">每 %1$s 分鐘更新</string>
<string name="prefs_accounts">帳號</string>
<string name="prefs_manage_accounts">管理帳號</string>
<string name="prefs_pincode_summary">保護您的ownCloud用戶端</string>
<string name="prefs_instant_upload">啟用即時上傳</string>
- <string name="auth_host_url">網址URL</string>
+ <string name="auth_host_url">URL</string>
<string name="auth_username">使用者名稱</string>
<string name="auth_password">密碼</string>
- <string name="new_session_uri_error">錯誤的URL</string>
+ <string name="new_session_uri_error">錯誤的位址</string>
+ <string name="new_session_session_name_error">錯誤的連線名稱</string>
<string name="sync_string_files">檔案</string>
+ <string name="uploader_no_file_selected">未選擇任何要上傳的檔案</string>
<string name="setup_hint_username">使用者名稱</string>
<string name="setup_hint_password">密碼</string>
- <string name="setup_title">連線至您的ownCloud</string>
+ <string name="setup_hint_address">網頁位址</string>
+ <string name="setup_hint_show_password">顯示密碼?</string>
+ <string name="setup_title">連線至您的 %1$s</string>
<string name="setup_btn_connect">連線</string>
<string name="uploader_btn_upload_text">上傳</string>
<string name="uploader_wrn_no_account_title">找不到帳號</string>
<string name="uploader_wrn_no_account_quit_btn_text">離開</string>
<string name="uploader_info_uploading">上傳中</string>
<string name="uploader_btn_create_dir_text">建立上傳目錄</string>
+ <string name="filedetails_select_file">在檔案上輕觸來顯示更多資訊。</string>
<string name="filedetails_size">容量:</string>
<string name="filedetails_type">類型:</string>
<string name="filedetails_created">建立:</string>
<string name="filedetails_open">開啟</string>
<string name="common_yes">是</string>
<string name="common_no">否</string>
+ <string name="common_ok">好</string>
<string name="common_cancel_upload">取消上傳</string>
<string name="common_cancel">取消</string>
+ <string name="common_save_exit">儲存並離開</string>
<string name="common_exit">離開ownCloud</string>
<string name="common_error">錯誤</string>
<string name="about_title">關於</string>
<string name="downloader_download_failed_ticker">下載失敗</string>
<string name="common_choose_account">選擇帳號</string>
<string name="sync_string_contacts">通訊錄</string>
+ <string name="use_ssl">使用安全連線</string>
+ <string name="location_no_provider">%1$s 無法追蹤您的裝置,請檢查定位服務設定</string>
+ <string name="pincode_enter_pin_code">請輸入您的 App PIN</string>
+ <string name="pincode_enter_new_pin_code">請輸入您的新 App PIN</string>
+ <string name="pincode_configure_your_pin">輸入您的 App PIN</string>
+ <string name="pincode_reenter_your_pincode">請重新輸入您的 App PIN</string>
+ <string name="pincode_remove_your_pincode">移除您的 App PIN</string>
+ <string name="pincode_mismatch">App PIN 不相符</string>
+ <string name="pincode_wrong">App PIN 不正確</string>
+ <string name="pincode_removed">App PIN 已移除</string>
+ <string name="pincode_stored">App PIN 已儲存</string>
+ <string-array name="prefs_trackmydevice_intervall_keys">
+ <item>15 分鐘</item>
+ <item>30 分鐘</item>
+ <item>60 分鐘</item>
+ </string-array>
<string-array name="prefs_trackmydevice_intervall_values">
<item>15</item>
<item>30</item>
<item>60</item>
</string-array>
+ <string name="auth_trying_to_login">嘗試登入...</string>
+ <string name="auth_no_net_conn_title">沒有網際網路連線</string>
+ <string name="auth_no_net_conn_message">沒有偵測到網際網路連線,請檢查您的連線然後再試一次。</string>
+ <string name="auth_connect_anyway">繼續連線</string>
+ <string name="auth_nossl_plain_ok_title">安全連線不可用。</string>
+ <string name="auth_nossl_plain_ok_message">無法與伺服器建立安全連線,可以使用不安全連線(未加密)以繼續,您可以繼續或取消。</string>
+ <string name="auth_connection_established">連線已建立</string>
+ <string name="auth_testing_connection">測試連線...</string>
+ <string name="auth_not_configured_title">伺服器設定有問題</string>
+ <string name="auth_not_configured_message">看起來您的伺服器並未被正確設定,請聯絡服務管理者以取得協助。</string>
+ <string name="auth_unknown_error_title">發生未知的錯誤!</string>
+ <string name="auth_unknown_error_message">發生未知的錯誤,請聯絡支援服務並附上您的記錄檔。</string>
+ <string name="auth_incorrect_path_title">找不到伺服器</string>
+ <string name="auth_incorrect_path_message">在指定的路徑找不到伺服器,請檢查您的路徑然後再試一次。</string>
<string name="auth_incorrect_address_title">URL 不正確</string>
<string name="auth_ssl_general_error_title">SSL 初始化失敗</string>
<string name="auth_ssl_unverified_server_title">未經驗證的 SSL 伺服器身份</string>
<string name="auth_bad_oc_version_title">無法辨識的ownCloud伺服器版本</string>
<string name="auth_wrong_connection_title">無法建立連線</string>
+ <string name="auth_secure_connection">安全連線已建立</string>
+ <string name="auth_login_details">登入細節</string>
<string name="fd_keep_in_sync">讓檔案保持最新的</string>
<string name="common_share">分享</string>
<string name="common_rename">重新命名</string>
<resources>
<string name="app_name">ownCloud</string>
- <string name="whats_new">What\'s new</string>
<string name="main_password">Password:</string>
<string name="main_login">Username:</string>
<string name="main_button_login">Login</string>
<string name="actionbar_mkdir">Create directory</string>
<string name="actionbar_search">Search</string>
<string name="actionbar_settings">Settings</string>
+ <string name="actionbar_see_details">Details</string>
+
<string name="prefs_category_general">General</string>
- <string name="prefs_category_trackmydevice">Device tracking</string>
<string name="prefs_add_session">Add new session</string>
<string name="prefs_create_img_thumbnails">Create image thumbnails</string>
<string name="prefs_select_oc_account">Select an account</string>
<string name="setup_title">Connect to your %1$s</string>
<string name="setup_btn_connect">Connect</string>
<string name="uploader_btn_upload_text">Upload</string>
+ <string name="uploader_top_message">Choose upload directory:</string>
<string name="uploader_wrn_no_account_title">No account found</string>
<string name="uploader_wrn_no_account_text">There are no %1$s accounts on your device. Please setup an account first.</string>
<string name="uploader_wrn_no_account_setup_btn_text">Setup</string>
<string name="common_save_exit">Save & Exit</string>
<string name="common_exit">Leave %1$s</string>
<string name="common_error">Error</string>
+ <string name="common_loading">Loading …</string>
+ <string name="common_error_unknown">Unknown error</string>
<string name="about_title">About</string>
<string name="delete_account">Delete account</string>
<string name="create_account">Create account</string>
<string name="downloader_download_succeeded_content">%1$s was successfully downloaded</string>
<string name="downloader_download_failed_ticker">Download failed</string>
<string name="downloader_download_failed_content">Download of %1$s could not be completed</string>
+ <string name="downloader_not_downloaded_yet">Not downloaded yet</string>
<string name="common_choose_account">Choose account</string>
<string name="sync_string_contacts">Contacts</string>
<string name="sync_fail_ticker">Synchronization failed</string>
<string name="pincode_wrong">Incorrect App PIN</string>
<string name="pincode_removed">App PIN removed</string>
<string name="pincode_stored">App PIN stored</string>
-
+
+ <string name="media_notif_ticker">"%1$s music player"</string>
+ <string name="media_state_playing">"%1$s (playing)"</string>
+ <string name="media_state_loading">"%1$s (loading)"</string>
+ <string name="media_event_done">"%1$s playback finished"</string>
+ <string name="media_err_nothing_to_play">No media file found</string>
+ <string name="media_err_no_account">No account provided</string>
+ <string name="media_err_not_in_owncloud">File not in a valid account</string>
+ <string name="media_err_unsupported">Unsupported media codec</string>
+ <string name="media_err_io">Media file could not be read</string>
+ <string name="media_err_malformed">Media file not correctly encoded</string>
+ <string name="media_err_timeout">Too much time trying to play</string>
+ <string name="media_err_invalid_progressive_playback">Media file cannot be streamed</string>
+ <string name="media_err_unknown">Media file cannot be played with the stock media player</string>
+ <string name="media_err_security_ex">Security error trying to play %1$s</string>
+ <string name="media_err_io_ex">Input error trying to play %1$s</string>
+ <string name="media_err_unexpected">Unexpected error trying to play %1$s</string>
+ <string name="media_previous_description">Previous track button</string>
+ <string name="media_rewind_description">Rewind button</string>
+ <string name="media_play_pause_description">Play or pause button</string>
+ <string name="media_forward_description">Fast forward button</string>
+ <string name="media_next_description">Next track button</string>
<string-array name="prefs_trackmydevice_intervall_keys">
<item>15 Minutes</item>
<item>30 Minutes</item>
<string name="ssl_validator_label_L">Location:</string>
<string name="ssl_validator_label_validity">Validity:</string>
<string name="ssl_validator_label_validity_from">From:</string>
- <string name="ssl_validator_label_validity_to">To:</string>
- <string name="ssl_validator_label_signature">Signature:</string>
- <string name="ssl_validator_label_signature_algorithm">Algorithm:</string>
- <string name="text_placeholder">This is a placeholder</string>
+ <string name="ssl_validator_label_validity_to">To:</string>
+ <string name="ssl_validator_label_signature">Signature:</string>
+ <string name="ssl_validator_label_signature_algorithm">Algorithm:</string>
+
+ <string name="placeholder_sentence">This is a placeholder</string>
+ <string name="placeholder_filename">placeholder.txt</string>
+ <string name="placeholder_filetype">PNG Image</string>
+ <string name="placeholder_filesize">389 KB</string>
+ <string name="placeholder_timestamp">2012/05/18 12:23 PM</string>
+ <string name="placeholder_media_time">12:23:45</string>
+
<string name="instant_upload_on_wifi">Upload pictures via WiFi only</string>
<string name="instant_upload_path">/InstantUpload</string>
<string name="conflict_title">Update conflict</string>
<string name="conflict_keep_both">Keep both</string>
<string name="conflict_overwrite">Overwrite</string>
<string name="conflict_dont_upload">Don\'t upload</string>
-
+
+ <string name="preview_image_description">Image preview</string>
+ <string name="preview_image_error_unknown_format">This image can not be shown</string>
+ <string name="preview_image_error_out_of_memory">"Not enough memory to show this image</string>
+
<!-- we need to improve the communication of errors to the user -->
<string name="error__upload__local_file_not_copied">%1$s could not be copied to %2$s local directory</string>
<string name="actionbar_failed_instant_upload">Failed InstantUpload"</string>
<string name="failed_upload_retry_text">retry to upload the image: </string>
<string name="failed_upload_load_more_images">Load more Picrures</string>
<string name="failed_upload_retry_do_nothing_text">do nothing you are not online for instant upload</string>
-
-</resources>
\ No newline at end of file
+ <string name="failed_upload_failure_text">Failure Message: </string>
+ <string name="failed_upload_quota_exceeded_text">Please check your server configuration,maybe your quota is exceeded.</string>
+</resources>
--- /dev/null
+git submodule init
+git submodule update
+android.bat update project -p actionbarsherlock\library --target 1
+android.bat update project -p . --target 1
+cp third_party\android-support-library\android-support-v4.jar actionbarsherlock\library\libs\android-support-v4.jar
+cd tests
+android.bat update test-project -m .. -p .
\ No newline at end of file
break;\r
}\r
}\r
- } else if (ocAccounts.length != 0) {\r
+ }\r
+ \r
+ if (defaultAccount == null && ocAccounts.length != 0) {\r
// we at least need to take first account as fallback\r
defaultAccount = ocAccounts[0];\r
}\r
}\r
\r
\r
- public static void setCurrentOwnCloudAccount(Context context, String name) {\r
- SharedPreferences.Editor appPrefs = PreferenceManager\r
- .getDefaultSharedPreferences(context).edit();\r
- appPrefs.putString("select_oc_account", name);\r
- appPrefs.commit();\r
+ public static boolean setCurrentOwnCloudAccount(Context context, String accountName) {\r
+ boolean result = false;\r
+ if (accountName != null) {\r
+ Account[] ocAccounts = AccountManager.get(context).getAccountsByType(\r
+ AccountAuthenticator.ACCOUNT_TYPE);\r
+ boolean found = false;\r
+ for (Account account : ocAccounts) {\r
+ found = (account.name.equals(accountName));\r
+ if (found) {\r
+ SharedPreferences.Editor appPrefs = PreferenceManager\r
+ .getDefaultSharedPreferences(context).edit();\r
+ appPrefs.putString("select_oc_account", accountName);\r
+ \r
+ appPrefs.commit();\r
+ result = true;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ return result;\r
}\r
\r
/**\r
} else {\r
String [] parts = mimetype.split("/");\r
String type = parts[0];\r
- String subtype = parts[1];\r
+ String subtype = (parts.length > 1) ? parts[1] : "";\r
\r
if(TYPE_TXT.equals(type)) {\r
return R.drawable.file_doc;\r
public void removeDirectory(OCFile dir, boolean removeDBData, boolean removeLocalContent);
public void moveDirectory(OCFile dir, String newPath);
+
+ public Vector<OCFile> getDirectoryImages(OCFile mParentFolder);
}
}
}
+ @Override
+ public Vector<OCFile> getDirectoryImages(OCFile directory) {
+ Vector<OCFile> ret = new Vector<OCFile>();
+ if (directory != null) {
+ // TODO better implementation, filtering in the access to database (if possible) instead of here
+ Vector<OCFile> tmp = getDirectoryContent(directory);
+ OCFile current = null;
+ for (int i=0; i<tmp.size(); i++) {
+ current = tmp.get(i);
+ if (current.isImage()) {
+ ret.add(current);
+ }
+ }
+ }
+ return ret;
+ }
+
}
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.Log;
+import android.webkit.MimeTypeMap;
public class OCFile implements Parcelable, Comparable<OCFile> {
return 0;
}
+ /** @return 'True' if the file contains audio */
+ public boolean isAudio() {
+ return (mMimeType != null && mMimeType.startsWith("audio/"));
+ }
+
+ /** @return 'True' if the file contains video */
+ public boolean isVideo() {
+ return (mMimeType != null && mMimeType.startsWith("video/"));
+ }
+
+ /** @return 'True' if the file contains an image */
+ public boolean isImage() {
+ return ((mMimeType != null && mMimeType.startsWith("image/")) ||
+ getMimeTypeFromName().startsWith("image/"));
+ }
+
+ public String getMimeTypeFromName() {
+ String extension = "";
+ int pos = mRemotePath.lastIndexOf('.');
+ if (pos >= 0) {
+ extension = mRemotePath.substring(pos + 1);
+ }
+ String result = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase());
+ return (result != null) ? result : "";
+ }
+
}
mDB.close();
}
- public boolean putFileForLater(String filepath, String account) {
+ public boolean putFileForLater(String filepath, String account, String message) {
ContentValues cv = new ContentValues();
cv.put("path", filepath);
cv.put("account", account);
cv.put("attempt", UPLOAD_STATUS_UPLOAD_LATER);
+ cv.put("message", message);
long result = mDB.insert(TABLE_INSTANT_UPLOAD, null, cv);
Log_OC.d(TABLE_INSTANT_UPLOAD, "putFileForLater returns with: " + result + " for file: " + filepath);
return result != -1;
}
- public int updateFileState(String filepath, Integer status) {
+ public int updateFileState(String filepath, Integer status, String message) {
ContentValues cv = new ContentValues();
cv.put("attempt", status);
+ cv.put("message", message);
int result = mDB.update(TABLE_INSTANT_UPLOAD, cv, "path=?", new String[] { filepath });
Log_OC.d(TABLE_INSTANT_UPLOAD, "updateFileState returns with: " + result + " for file: " + filepath);
return result;
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_INSTANT_UPLOAD + " (" + " _id INTEGER PRIMARY KEY, " + " path TEXT,"
- + " account TEXT,attempt INTEGER);");
+ + " account TEXT,attempt INTEGER,message TEXT);");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- db.execSQL("ALTER TABLE " + TABLE_INSTANT_UPLOAD + " ADD COLUMN attempt;");
+ if (oldVersion < 2) {
+ db.execSQL("ALTER TABLE " + TABLE_INSTANT_UPLOAD + " ADD COLUMN attempt INTEGER;");
+ }
+ db.execSQL("ALTER TABLE " + TABLE_INSTANT_UPLOAD + " ADD COLUMN message TEXT;");
}
}
import com.owncloud.android.authenticator.AccountAuthenticator;
import com.owncloud.android.db.DbHandler;
import com.owncloud.android.files.services.FileUploader;
+import com.owncloud.android.utils.FileStorageUtils;
public class InstantUploadBroadcastReceiver extends BroadcastReceiver {
- public static String INSTANT_UPLOAD_DIR = "/InstantUpload/";
private static String TAG = "PhotoTakenBroadcastReceiver";
private static final String[] CONTENT_PROJECTION = { Media.DATA, Media.DISPLAY_NAME, Media.MIME_TYPE, Media.SIZE };
private static String NEW_PHOTO_ACTION = "com.android.camera.NEW_PICTURE";
// same always temporally the picture to upload
DbHandler db = new DbHandler(context);
- db.putFileForLater(file_path, account.name);
+ db.putFileForLater(file_path, account.name, null);
db.close();
if (!isOnline(context) || (instantUploadViaWiFiOnly(context) && !isConnectedViaWiFi(context))) {
Intent i = new Intent(context, FileUploader.class);
i.putExtra(FileUploader.KEY_ACCOUNT, account);
i.putExtra(FileUploader.KEY_LOCAL_FILE, file_path);
- i.putExtra(FileUploader.KEY_REMOTE_FILE, INSTANT_UPLOAD_DIR + file_name);
+ i.putExtra(FileUploader.KEY_REMOTE_FILE, FileStorageUtils.getInstantUploadFilePath(file_name));
i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE);
i.putExtra(FileUploader.KEY_MIME_TYPE, mime_type);
i.putExtra(FileUploader.KEY_INSTANT_UPLOAD, true);
Intent i = new Intent(context, FileUploader.class);
i.putExtra(FileUploader.KEY_ACCOUNT, account);
i.putExtra(FileUploader.KEY_LOCAL_FILE, file_path);
- i.putExtra(FileUploader.KEY_REMOTE_FILE, INSTANT_UPLOAD_DIR + f.getName());
+ i.putExtra(FileUploader.KEY_REMOTE_FILE, FileStorageUtils.getInstantUploadFilePath(f.getName()));
i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE);
i.putExtra(FileUploader.KEY_INSTANT_UPLOAD, true);
context.startService(i);
import java.io.File;
import java.util.AbstractList;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.Map;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.owncloud.android.operations.RemoteOperationResult;
import com.owncloud.android.ui.activity.FileDetailActivity;
import com.owncloud.android.ui.fragment.FileDetailFragment;
+import com.owncloud.android.ui.preview.PreviewImageActivity;
+import com.owncloud.android.ui.preview.PreviewImageFragment;
import android.accounts.Account;
import android.app.Notification;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
-import android.util.Log;
import android.widget.RemoteViews;
import com.owncloud.android.Log_OC;
DownloadFileOperation newDownload = new DownloadFileOperation(account, file);
mPendingDownloads.putIfAbsent(downloadKey, newDownload);
newDownload.addDatatransferProgressListener(this);
+ newDownload.addDatatransferProgressListener((FileDownloaderBinder)mBinder);
requestedDownloads.add(downloadKey);
sendBroadcastNewDownload(newDownload);
return mBinder;
}
+
+ /**
+ * Called when ALL the bound clients were onbound.
+ */
+ @Override
+ public boolean onUnbind(Intent intent) {
+ ((FileDownloaderBinder)mBinder).clearListeners();
+ return false; // not accepting rebinding (default behaviour)
+ }
+
/**
* Binder to let client components to perform operations on the queue of downloads.
*
* It provides by itself the available operations.
*/
- public class FileDownloaderBinder extends Binder {
+ public class FileDownloaderBinder extends Binder implements OnDatatransferProgressListener {
+
+ /**
+ * Map of listeners that will be reported about progress of downloads from a {@link FileDownloaderBinder} instance
+ */
+ private Map<String, OnDatatransferProgressListener> mBoundListeners = new HashMap<String, OnDatatransferProgressListener>();
+
/**
* Cancels a pending or current download of a remote file.
}
+ public void clearListeners() {
+ mBoundListeners.clear();
+ }
+
+
/**
* Returns True when the file described by 'file' in the ownCloud account 'account' is downloading or waiting to download.
*
}
}
}
+
+
+ /**
+ * Adds a listener interested in the progress of the download for a concrete file.
+ *
+ * @param listener Object to notify about progress of transfer.
+ * @param account ownCloud account holding the file of interest.
+ * @param file {@link OCfile} of interest for listener.
+ */
+ public void addDatatransferProgressListener (OnDatatransferProgressListener listener, Account account, OCFile file) {
+ if (account == null || file == null || listener == null) return;
+ String targetKey = buildRemoteName(account, file);
+ mBoundListeners.put(targetKey, listener);
+ }
+
+
+
+ /**
+ * Removes a listener interested in the progress of the download for a concrete file.
+ *
+ * @param listener Object to notify about progress of transfer.
+ * @param account ownCloud account holding the file of interest.
+ * @param file {@link OCfile} of interest for listener.
+ */
+ public void removeDatatransferProgressListener (OnDatatransferProgressListener listener, Account account, OCFile file) {
+ if (account == null || file == null || listener == null) return;
+ String targetKey = buildRemoteName(account, file);
+ if (mBoundListeners.get(targetKey) == listener) {
+ mBoundListeners.remove(targetKey);
+ }
+ }
+
+
+ @Override
+ public void onTransferProgress(long progressRate) {
+ // old way, should not be in use any more
+ }
+
+
+ @Override
+ public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer,
+ String fileName) {
+ String key = buildRemoteName(mCurrentDownload.getAccount(), mCurrentDownload.getFile());
+ OnDatatransferProgressListener boundListener = mBoundListeners.get(key);
+ if (boundListener != null) {
+ boundListener.onTransferProgress(progressRate, totalTransferredSoFar, totalToTransfer, fileName);
+ }
+ }
+
}
mNotification.contentView.setImageViewResource(R.id.status_icon, R.drawable.icon);
/// includes a pending intent in the notification showing the details view of the file
- Intent showDetailsIntent = new Intent(this, FileDetailActivity.class);
+ Intent showDetailsIntent = null;
+ if (PreviewImageFragment.canBePreviewed(download.getFile())) {
+ showDetailsIntent = new Intent(this, PreviewImageActivity.class);
+ } else {
+ showDetailsIntent = new Intent(this, FileDetailActivity.class);
+ }
showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, download.getFile());
showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, download.getAccount());
showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
int contentId = (downloadResult.isSuccess()) ? R.string.downloader_download_succeeded_content : R.string.downloader_download_failed_content;
Notification finalNotification = new Notification(R.drawable.icon, getString(tickerId), System.currentTimeMillis());
finalNotification.flags |= Notification.FLAG_AUTO_CANCEL;
- // TODO put something smart in the contentIntent below
- finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);
+ Intent showDetailsIntent = null;
+ if (downloadResult.isSuccess()) {
+ if (PreviewImageFragment.canBePreviewed(download.getFile())) {
+ showDetailsIntent = new Intent(this, PreviewImageActivity.class);
+ } else {
+ showDetailsIntent = new Intent(this, FileDetailActivity.class);
+ }
+ showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, download.getFile());
+ showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, download.getAccount());
+ showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+
+ } else {
+ // TODO put something smart in showDetailsIntent
+ showDetailsIntent = new Intent();
+ }
+ finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), (int)System.currentTimeMillis(), showDetailsIntent, 0);
finalNotification.setLatestEventInfo(getApplicationContext(), getString(tickerId), String.format(getString(contentId), new File(download.getSavePath()).getName()), finalNotification.contentIntent);
mNotificationManager.notify(tickerId, finalNotification);
}
*/
private void sendBroadcastNewDownload(DownloadFileOperation download) {
Intent added = new Intent(DOWNLOAD_ADDED_MESSAGE);
- /*added.putExtra(ACCOUNT_NAME, download.getAccount().name);
- added.putExtra(EXTRA_REMOTE_PATH, download.getRemotePath());*/
+ added.putExtra(ACCOUNT_NAME, download.getAccount().name);
+ added.putExtra(EXTRA_REMOTE_PATH, download.getRemotePath());
added.putExtra(EXTRA_FILE_PATH, download.getSavePath());
sendStickyBroadcast(added);
}
import java.io.File;
import java.util.AbstractList;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.Map;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.db.DbHandler;
-import com.owncloud.android.files.InstantUploadBroadcastReceiver;
import com.owncloud.android.network.OwnCloudClientUtils;
import com.owncloud.android.operations.ChunkedUploadFileOperation;
import com.owncloud.android.operations.RemoteOperationResult;
import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.operations.UploadFileOperation;
+import com.owncloud.android.ui.activity.FailedUploadActivity;
import com.owncloud.android.ui.activity.FileDetailActivity;
import com.owncloud.android.ui.activity.InstantUploadActivity;
import com.owncloud.android.ui.fragment.FileDetailFragment;
+import com.owncloud.android.ui.preview.PreviewImageActivity;
+import com.owncloud.android.ui.preview.PreviewImageFragment;
import com.owncloud.android.utils.OwnCloudVersion;
import eu.alefzero.webdav.OnDatatransferProgressListener;
/**
* Builds a key for mPendingUploads from the account and file to upload
*
- * @param account Account where the file to download is stored
- * @param file File to download
+ * @param account Account where the file to upload is stored
+ * @param file File to upload
*/
private String buildRemoteName(Account account, OCFile file) {
return account.name + file.getRemotePath();
}
mPendingUploads.putIfAbsent(uploadKey, newUpload);
newUpload.addDatatransferProgressListener(this);
+ newUpload.addDatatransferProgressListener((FileUploaderBinder)mBinder);
requestedUploads.add(uploadKey);
}
public IBinder onBind(Intent arg0) {
return mBinder;
}
+
+ /**
+ * Called when ALL the bound clients were onbound.
+ */
+ @Override
+ public boolean onUnbind(Intent intent) {
+ ((FileUploaderBinder)mBinder).clearListeners();
+ return false; // not accepting rebinding (default behaviour)
+ }
+
/**
* Binder to let client components to perform operations on the queue of
*
* It provides by itself the available operations.
*/
- public class FileUploaderBinder extends Binder {
-
+ public class FileUploaderBinder extends Binder implements OnDatatransferProgressListener {
+
+ /**
+ * Map of listeners that will be reported about progress of uploads from a {@link FileUploaderBinder} instance
+ */
+ private Map<String, OnDatatransferProgressListener> mBoundListeners = new HashMap<String, OnDatatransferProgressListener>();
+
/**
* Cancels a pending or current upload of a remote file.
*
upload.cancel();
}
}
+
+
+
+ public void clearListeners() {
+ mBoundListeners.clear();
+ }
+
+
+
/**
* Returns True when the file described by 'file' is being uploaded to
* the ownCloud account 'account' or waiting for it
*
- * If 'file' is a directory, returns 'true' if some of its descendant
- * files is downloading or waiting to download.
+ * If 'file' is a directory, returns 'true' if some of its descendant files is uploading or waiting to upload.
*
* @param account Owncloud account where the remote file will be stored.
* @param file A file that could be in the queue of pending uploads
String targetKey = buildRemoteName(account, file);
synchronized (mPendingUploads) {
if (file.isDirectory()) {
- // this can be slow if there are many downloads :(
+ // this can be slow if there are many uploads :(
Iterator<String> it = mPendingUploads.keySet().iterator();
boolean found = false;
while (it.hasNext() && !found) {
}
}
}
+
+
+ /**
+ * Adds a listener interested in the progress of the upload for a concrete file.
+ *
+ * @param listener Object to notify about progress of transfer.
+ * @param account ownCloud account holding the file of interest.
+ * @param file {@link OCfile} of interest for listener.
+ */
+ public void addDatatransferProgressListener (OnDatatransferProgressListener listener, Account account, OCFile file) {
+ if (account == null || file == null || listener == null) return;
+ String targetKey = buildRemoteName(account, file);
+ mBoundListeners.put(targetKey, listener);
+ }
+
+
+
+ /**
+ * Removes a listener interested in the progress of the upload for a concrete file.
+ *
+ * @param listener Object to notify about progress of transfer.
+ * @param account ownCloud account holding the file of interest.
+ * @param file {@link OCfile} of interest for listener.
+ */
+ public void removeDatatransferProgressListener (OnDatatransferProgressListener listener, Account account, OCFile file) {
+ if (account == null || file == null || listener == null) return;
+ String targetKey = buildRemoteName(account, file);
+ if (mBoundListeners.get(targetKey) == listener) {
+ mBoundListeners.remove(targetKey);
+ }
+ }
+
+
+ @Override
+ public void onTransferProgress(long progressRate) {
+ // old way, should not be in use any more
+ }
+
+
+ @Override
+ public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer,
+ String fileName) {
+ String key = buildRemoteName(mCurrentUpload.getAccount(), mCurrentUpload.getFile());
+ OnDatatransferProgressListener boundListener = mBoundListeners.get(key);
+ if (boundListener != null) {
+ boundListener.onTransferProgress(progressRate, totalTransferredSoFar, totalToTransfer, fileName);
+ }
+ }
+
}
/**
// / create remote folder for instant uploads
if (mCurrentUpload.isRemoteFolderToBeCreated()) {
- mUploadClient.createDirectory(InstantUploadBroadcastReceiver.INSTANT_UPLOAD_DIR); // ignoring
- // result;
- // fail
- // could
- // just
- // mean
- // that
- // it
- // already
- // exists,
- // but
- // local
- // database
- // is
- // not
- // synchronized;
- // the
- // upload
- // will
- // be
- // tried
- // anyway
+ mUploadClient.createDirectory(InstantUploadService.INSTANT_UPLOAD_DIR);
+ // ignoring result fail could just mean that it already exists,
+ // but local database is not synchronized the upload will be
+ // tried anyway
}
// / perform the upload
file.setMimetype(we.contentType());
file.setModificationTimestamp(we.modifiedTimestamp());
file.setModificationTimestampAtLastSyncForData(we.modifiedTimestamp());
- // file.setEtag(mCurrentDownload.getEtag()); // TODO Etag, where
- // available
+ // file.setEtag(mCurrentUpload.getEtag()); // TODO Etag, where available
}
private boolean checkAndFixInstantUploadDirectory(FileDataStorageManager storageManager) {
- OCFile instantUploadDir = storageManager.getFileByPath(InstantUploadBroadcastReceiver.INSTANT_UPLOAD_DIR);
+ OCFile instantUploadDir = storageManager.getFileByPath(InstantUploadService.INSTANT_UPLOAD_DIR);
if (instantUploadDir == null) {
// first instant upload in the account, or never account not
// synchronized after the remote InstantUpload folder was created
- OCFile newDir = new OCFile(InstantUploadBroadcastReceiver.INSTANT_UPLOAD_DIR);
+ OCFile newDir = new OCFile(InstantUploadService.INSTANT_UPLOAD_DIR);
newDir.setMimetype("DIR");
OCFile path = storageManager.getFileByPath(OCFile.PATH_SEPARATOR);
*
* @param upload Upload operation starting.
*/
+ @SuppressWarnings("deprecation")
private void notifyUploadStart(UploadFileOperation upload) {
// / create status notification with a progress bar
mLastPercent = 0;
mNotification.contentView.setTextViewText(R.id.status_text,
String.format(getString(R.string.uploader_upload_in_progress_content), 0, upload.getFileName()));
mNotification.contentView.setImageViewResource(R.id.status_icon, R.drawable.icon);
-
- // / includes a pending intent in the notification showing the details
- // view of the file
- Intent showDetailsIntent = new Intent(this, FileDetailActivity.class);
+
+ /// includes a pending intent in the notification showing the details view of the file
+ Intent showDetailsIntent = null;
+ if (PreviewImageFragment.canBePreviewed(upload.getFile())) {
+ showDetailsIntent = new Intent(this, PreviewImageActivity.class);
+ } else {
+ showDetailsIntent = new Intent(this, FileDetailActivity.class);
+ showDetailsIntent.putExtra(FileDetailActivity.EXTRA_MODE, FileDetailActivity.MODE_DETAILS);
+ }
showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, upload.getFile());
showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, upload.getAccount());
showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// flag
mNotification.flags |= Notification.FLAG_AUTO_CANCEL;
mNotification.contentView = mDefaultNotificationContentView;
-
- // / includes a pending intent in the notification showing the
- // details view of the file
- Intent showDetailsIntent = new Intent(this, FileDetailActivity.class);
+
+ /// includes a pending intent in the notification showing the details view of the file
+ Intent showDetailsIntent = null;
+ if (PreviewImageFragment.canBePreviewed(upload.getFile())) {
+ showDetailsIntent = new Intent(this, PreviewImageActivity.class);
+ } else {
+ showDetailsIntent = new Intent(this, FileDetailActivity.class);
+ showDetailsIntent.putExtra(FileDetailActivity.EXTRA_MODE, FileDetailActivity.MODE_DETAILS);
+ }
showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, upload.getFile());
showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, upload.getAccount());
showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
getString(R.string.uploader_upload_failed_ticker), System.currentTimeMillis());
finalNotification.flags |= Notification.FLAG_AUTO_CANCEL;
- Intent detailUploudIntent = new Intent(this, InstantUploadActivity.class);
- detailUploudIntent.putExtra(FileUploader.KEY_ACCOUNT, upload.getAccount());
- finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(),
- (int) System.currentTimeMillis(), detailUploudIntent, PendingIntent.FLAG_UPDATE_CURRENT
- | PendingIntent.FLAG_ONE_SHOT);
-
String content = null;
if (uploadResult.getCode() == ResultCode.LOCAL_STORAGE_FULL
|| uploadResult.getCode() == ResultCode.LOCAL_STORAGE_NOT_COPIED) {
// from a RemoteOperationResult and a RemoteOperation
content = String.format(getString(R.string.error__upload__local_file_not_copied), upload.getFileName(),
getString(R.string.app_name));
+ } else if (uploadResult.getCode() == ResultCode.QUOTA_EXCEEDED) {
+ content = getString(R.string.failed_upload_quota_exceeded_text);
} else {
content = String
.format(getString(R.string.uploader_upload_failed_content_single), upload.getFileName());
}
- finalNotification.setLatestEventInfo(getApplicationContext(),
- getString(R.string.uploader_upload_failed_ticker), content, finalNotification.contentIntent);
- mNotificationManager.notify(R.string.uploader_upload_failed_ticker, finalNotification);
+ // we add only for instant-uploads the InstantUploadActivity and the
+ // db entry
+ Intent detailUploadIntent = null;
+ if (upload.isInstant() && InstantUploadActivity.IS_ENABLED) {
+ detailUploadIntent = new Intent(this, InstantUploadActivity.class);
+ detailUploadIntent.putExtra(FileUploader.KEY_ACCOUNT, upload.getAccount());
+ } else {
+ detailUploadIntent = new Intent(this, FailedUploadActivity.class);
+ detailUploadIntent.putExtra(FailedUploadActivity.MESSAGE, content);
+ }
+ finalNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(),
+ (int) System.currentTimeMillis(), detailUploadIntent, PendingIntent.FLAG_UPDATE_CURRENT
+ | PendingIntent.FLAG_ONE_SHOT);
- DbHandler db = new DbHandler(this.getBaseContext());
- if (db.updateFileState(upload.getOriginalStoragePath(), DbHandler.UPLOAD_STATUS_UPLOAD_FAILED) == 0) {
- db.putFileForLater(upload.getOriginalStoragePath(), upload.getAccount().name);
+ if (upload.isInstant()) {
+ DbHandler db = null;
+ try {
+ db = new DbHandler(this.getBaseContext());
+ String message = uploadResult.getLogMessage() + " errorCode: " + uploadResult.getCode();
+ Log.e(TAG, message + " Http-Code: " + uploadResult.getHttpCode());
+ if (uploadResult.getCode() == ResultCode.QUOTA_EXCEEDED) {
+ message = getString(R.string.failed_upload_quota_exceeded_text);
+ }
+ if (db.updateFileState(upload.getOriginalStoragePath(), DbHandler.UPLOAD_STATUS_UPLOAD_FAILED,
+ message) == 0) {
+ db.putFileForLater(upload.getOriginalStoragePath(), upload.getAccount().name, message);
+ }
+ } finally {
+ if (db != null) {
+ db.close();
+ }
+ }
}
- db.close();
+ finalNotification.setLatestEventInfo(getApplicationContext(),
+ getString(R.string.uploader_upload_failed_ticker), content, finalNotification.contentIntent);
+ mNotificationManager.notify(R.string.uploader_upload_failed_ticker, finalNotification);
}
}
import java.util.List;
import com.owncloud.android.Log_OC;
+import com.owncloud.android.utils.FileStorageUtils;
import com.owncloud.android.network.OwnCloudClientUtils;
import eu.alefzero.webdav.WebdavClient;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
-import android.util.Log;
public class InstantUploadService extends Service {
private static String TAG = "InstantUploadService";
// TODO make it configurable over the settings dialog
- public static String INSTANT_UPLOAD_DIR = "/InstantUpload";
+ public static final String INSTANT_UPLOAD_DIR = "/InstantUpload";
private UploaderRunnable mUploaderRunnable;
@Override
Log_OC.w(TAG, "Not all required information was provided, abording");
return Service.START_NOT_STICKY;
}
-
+
if (mUploaderRunnable == null) {
mUploaderRunnable = new UploaderRunnable();
}
-
+
String filename = intent.getStringExtra(KEY_DISPLAY_NAME);
String filepath = intent.getStringExtra(KEY_FILE_PATH);
String mimetype = intent.getStringExtra(KEY_MIME_TYPE);
Account account = intent.getParcelableExtra(KEY_ACCOUNT);
long filesize = intent.getLongExtra(KEY_FILE_SIZE, -1);
-
+
mUploaderRunnable.addElementToQueue(filename, filepath, mimetype, filesize, account);
-
+
// starting new thread for new download doesnt seems like a good idea
// maybe some thread pool or single background thread would be better
Log_OC.d(TAG, "Starting instant upload thread");
new Thread(mUploaderRunnable).start();
-
+
return Service.START_STICKY;
}
-
+
private class UploaderRunnable implements Runnable {
-
+
Object mLock;
List<HashMap<String, Object>> mHashMapList;
-
+
public UploaderRunnable() {
mHashMapList = new LinkedList<HashMap<String, Object>>();
mLock = new Object();
}
-
- public void addElementToQueue(String filename,
- String filepath,
- String mimetype,
- long length,
- Account account) {
+
+ public void addElementToQueue(String filename, String filepath, String mimetype, long length, Account account) {
HashMap<String, Object> new_map = new HashMap<String, Object>();
new_map.put(KEY_ACCOUNT, account);
new_map.put(KEY_DISPLAY_NAME, filename);
new_map.put(KEY_FILE_PATH, filepath);
new_map.put(KEY_MIME_TYPE, mimetype);
new_map.put(KEY_FILE_SIZE, length);
-
+
synchronized (mLock) {
mHashMapList.add(new_map);
}
}
-
+
private HashMap<String, Object> getFirstObject() {
synchronized (mLock) {
if (mHashMapList.size() == 0)
return ret;
}
}
-
+
public void run() {
HashMap<String, Object> working_map;
-
+
while ((working_map = getFirstObject()) != null) {
Account account = (Account) working_map.get(KEY_ACCOUNT);
String filename = (String) working_map.get(KEY_DISPLAY_NAME);
String mimetype = (String) working_map.get(KEY_MIME_TYPE);
WebdavClient wdc = OwnCloudClientUtils.createOwnCloudClient(account, getApplicationContext());
-
- wdc.createDirectory(INSTANT_UPLOAD_DIR); // fail could just mean that it already exists; put will be tried anyway
+
+ wdc.createDirectory(INSTANT_UPLOAD_DIR); // fail could just mean that it already exists put will be tried anyway
try {
- wdc.putFile(filepath, INSTANT_UPLOAD_DIR + "/" + filename, mimetype);
+ wdc.putFile(filepath, FileStorageUtils.getInstantUploadFilePath(filename), mimetype);
} catch (Exception e) {
// nothing to do; this service is deprecated, indeed
}
}
}
}
-
+
}
--- /dev/null
+/* ownCloud Android client application
+ *
+ * Copyright (C) 2012-2013 ownCloud Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package com.owncloud.android.media;
+
+import android.content.Context;
+import android.media.MediaPlayer;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.FrameLayout;
+import android.widget.ImageButton;
+import android.widget.MediaController.MediaPlayerControl;
+import android.widget.ProgressBar;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+import android.widget.TextView;
+
+import java.util.Formatter;
+import java.util.Locale;
+
+import com.owncloud.android.R;
+
+/**
+ * View containing controls for a {@link MediaPlayer}.
+ *
+ * Holds buttons "play / pause", "rewind", "fast forward"
+ * and a progress slider.
+ *
+ * It synchronizes itself with the state of the
+ * {@link MediaPlayer}.
+ *
+ * @author David A. Velasco
+ */
+
+public class MediaControlView extends FrameLayout /* implements OnLayoutChangeListener, OnTouchListener */ implements OnClickListener, OnSeekBarChangeListener {
+
+ private MediaPlayerControl mPlayer;
+ private Context mContext;
+ private View mRoot;
+ private ProgressBar mProgress;
+ private TextView mEndTime, mCurrentTime;
+ private boolean mDragging;
+ private static final int SHOW_PROGRESS = 1;
+ StringBuilder mFormatBuilder;
+ Formatter mFormatter;
+ private ImageButton mPauseButton;
+ private ImageButton mFfwdButton;
+ private ImageButton mRewButton;
+
+ public MediaControlView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mContext = context;
+
+ FrameLayout.LayoutParams frameParams = new FrameLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT
+ );
+ LayoutInflater inflate = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ mRoot = inflate.inflate(R.layout.media_control, null);
+ initControllerView(mRoot);
+ addView(mRoot, frameParams);
+
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+ setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
+ requestFocus();
+ }
+
+ @Override
+ public void onFinishInflate() {
+ /*
+ if (mRoot != null)
+ initControllerView(mRoot);
+ */
+ }
+
+ /* TODO REMOVE
+ public MediaControlView(Context context, boolean useFastForward) {
+ super(context);
+ mContext = context;
+ mUseFastForward = useFastForward;
+ initFloatingWindowLayout();
+ //initFloatingWindow();
+ }
+ */
+
+ /* TODO REMOVE
+ public MediaControlView(Context context) {
+ this(context, true);
+ }
+ */
+
+ /* T
+ private void initFloatingWindow() {
+ mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
+ mWindow = PolicyManager.makeNewWindow(mContext);
+ mWindow.setWindowManager(mWindowManager, null, null);
+ mWindow.requestFeature(Window.FEATURE_NO_TITLE);
+ mDecor = mWindow.getDecorView();
+ mDecor.setOnTouchListener(mTouchListener);
+ mWindow.setContentView(this);
+ mWindow.setBackgroundDrawableResource(android.R.color.transparent);
+
+ // While the media controller is up, the volume control keys should
+ // affect the media stream type
+ mWindow.setVolumeControlStream(AudioManager.STREAM_MUSIC);
+
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+ setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
+ requestFocus();
+ }
+ */
+
+ /*
+ // Allocate and initialize the static parts of mDecorLayoutParams. Must
+ // also call updateFloatingWindowLayout() to fill in the dynamic parts
+ // (y and width) before mDecorLayoutParams can be used.
+ private void initFloatingWindowLayout() {
+ mDecorLayoutParams = new WindowManager.LayoutParams();
+ WindowManager.LayoutParams p = mDecorLayoutParams;
+ p.gravity = Gravity.TOP;
+ p.height = LayoutParams.WRAP_CONTENT;
+ p.x = 0;
+ p.format = PixelFormat.TRANSLUCENT;
+ p.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
+ p.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
+ p.token = null;
+ p.windowAnimations = 0; // android.R.style.DropDownAnimationDown;
+ }
+ */
+
+ // Update the dynamic parts of mDecorLayoutParams
+ // Must be called with mAnchor != NULL.
+ /*
+ private void updateFloatingWindowLayout() {
+ int [] anchorPos = new int[2];
+ mAnchor.getLocationOnScreen(anchorPos);
+
+ WindowManager.LayoutParams p = mDecorLayoutParams;
+ p.width = mAnchor.getWidth();
+ p.y = anchorPos[1] + mAnchor.getHeight();
+ }
+ */
+
+ /*
+ // This is called whenever mAnchor's layout bound changes
+ public void onLayoutChange(View v, int left, int top, int right,
+ int bottom, int oldLeft, int oldTop, int oldRight,
+ int oldBottom) {
+ //updateFloatingWindowLayout();
+ if (mShowing) {
+ mWindowManager.updateViewLayout(mDecor, mDecorLayoutParams);
+ }
+ }
+ */
+
+ /*
+ public boolean onTouch(View v, MotionEvent event) {
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ if (mShowing) {
+ hide();
+ }
+ }
+ return false;
+ }
+ */
+
+
+ public void setMediaPlayer(MediaPlayerControl player) {
+ mPlayer = player;
+ mHandler.sendEmptyMessage(SHOW_PROGRESS);
+ updatePausePlay();
+ }
+
+
+ private void initControllerView(View v) {
+ mPauseButton = (ImageButton) v.findViewById(R.id.playBtn);
+ if (mPauseButton != null) {
+ mPauseButton.requestFocus();
+ mPauseButton.setOnClickListener(this);
+ }
+
+ mFfwdButton = (ImageButton) v.findViewById(R.id.forwardBtn);
+ if (mFfwdButton != null) {
+ mFfwdButton.setOnClickListener(this);
+ }
+
+ mRewButton = (ImageButton) v.findViewById(R.id.rewindBtn);
+ if (mRewButton != null) {
+ mRewButton.setOnClickListener(this);
+ }
+
+ mProgress = (ProgressBar) v.findViewById(R.id.progressBar);
+ if (mProgress != null) {
+ if (mProgress instanceof SeekBar) {
+ SeekBar seeker = (SeekBar) mProgress;
+ seeker.setOnSeekBarChangeListener(this);
+ }
+ mProgress.setMax(1000);
+ }
+
+ mEndTime = (TextView) v.findViewById(R.id.totalTimeText);
+ mCurrentTime = (TextView) v.findViewById(R.id.currentTimeText);
+ mFormatBuilder = new StringBuilder();
+ mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
+
+ }
+
+
+ /**
+ * Disable pause or seek buttons if the stream cannot be paused or seeked.
+ * This requires the control interface to be a MediaPlayerControlExt
+ */
+ private void disableUnsupportedButtons() {
+ try {
+ if (mPauseButton != null && !mPlayer.canPause()) {
+ mPauseButton.setEnabled(false);
+ }
+ if (mRewButton != null && !mPlayer.canSeekBackward()) {
+ mRewButton.setEnabled(false);
+ }
+ if (mFfwdButton != null && !mPlayer.canSeekForward()) {
+ mFfwdButton.setEnabled(false);
+ }
+ } catch (IncompatibleClassChangeError ex) {
+ // We were given an old version of the interface, that doesn't have
+ // the canPause/canSeekXYZ methods. This is OK, it just means we
+ // assume the media can be paused and seeked, and so we don't disable
+ // the buttons.
+ }
+ }
+
+
+ private Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ int pos;
+ switch (msg.what) {
+ case SHOW_PROGRESS:
+ pos = setProgress();
+ if (!mDragging) {
+ msg = obtainMessage(SHOW_PROGRESS);
+ sendMessageDelayed(msg, 1000 - (pos % 1000));
+ }
+ break;
+ }
+ }
+ };
+
+ private String stringForTime(int timeMs) {
+ int totalSeconds = timeMs / 1000;
+
+ int seconds = totalSeconds % 60;
+ int minutes = (totalSeconds / 60) % 60;
+ int hours = totalSeconds / 3600;
+
+ mFormatBuilder.setLength(0);
+ if (hours > 0) {
+ return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
+ } else {
+ return mFormatter.format("%02d:%02d", minutes, seconds).toString();
+ }
+ }
+
+ private int setProgress() {
+ if (mPlayer == null || mDragging) {
+ return 0;
+ }
+ int position = mPlayer.getCurrentPosition();
+ int duration = mPlayer.getDuration();
+ if (mProgress != null) {
+ if (duration > 0) {
+ // use long to avoid overflow
+ long pos = 1000L * position / duration;
+ mProgress.setProgress( (int) pos);
+ }
+ int percent = mPlayer.getBufferPercentage();
+ mProgress.setSecondaryProgress(percent * 10);
+ }
+
+ if (mEndTime != null)
+ mEndTime.setText(stringForTime(duration));
+ if (mCurrentTime != null)
+ mCurrentTime.setText(stringForTime(position));
+
+ return position;
+ }
+
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ int keyCode = event.getKeyCode();
+ final boolean uniqueDown = event.getRepeatCount() == 0
+ && event.getAction() == KeyEvent.ACTION_DOWN;
+ if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK
+ || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE
+ || keyCode == KeyEvent.KEYCODE_SPACE) {
+ if (uniqueDown) {
+ doPauseResume();
+ //show(sDefaultTimeout);
+ if (mPauseButton != null) {
+ mPauseButton.requestFocus();
+ }
+ }
+ return true;
+ } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) {
+ if (uniqueDown && !mPlayer.isPlaying()) {
+ mPlayer.start();
+ updatePausePlay();
+ //show(sDefaultTimeout);
+ }
+ return true;
+ } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP
+ || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) {
+ if (uniqueDown && mPlayer.isPlaying()) {
+ mPlayer.pause();
+ updatePausePlay();
+ //show(sDefaultTimeout);
+ }
+ return true;
+ }
+
+ //show(sDefaultTimeout);
+ return super.dispatchKeyEvent(event);
+ }
+
+ public void updatePausePlay() {
+ if (mRoot == null || mPauseButton == null)
+ return;
+
+ if (mPlayer.isPlaying()) {
+ mPauseButton.setImageResource(android.R.drawable.ic_media_pause);
+ } else {
+ mPauseButton.setImageResource(android.R.drawable.ic_media_play);
+ }
+ }
+
+ private void doPauseResume() {
+ if (mPlayer.isPlaying()) {
+ mPlayer.pause();
+ } else {
+ mPlayer.start();
+ }
+ updatePausePlay();
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ if (mPauseButton != null) {
+ mPauseButton.setEnabled(enabled);
+ }
+ if (mFfwdButton != null) {
+ mFfwdButton.setEnabled(enabled);
+ }
+ if (mRewButton != null) {
+ mRewButton.setEnabled(enabled);
+ }
+ if (mProgress != null) {
+ mProgress.setEnabled(enabled);
+ }
+ disableUnsupportedButtons();
+ super.setEnabled(enabled);
+ }
+
+ @Override
+ public void onClick(View v) {
+ int pos;
+ boolean playing = mPlayer.isPlaying();
+ switch (v.getId()) {
+
+ case R.id.playBtn:
+ doPauseResume();
+ break;
+
+ case R.id.rewindBtn:
+ pos = mPlayer.getCurrentPosition();
+ pos -= 5000;
+ mPlayer.seekTo(pos);
+ if (!playing) mPlayer.pause(); // necessary in some 2.3.x devices
+ setProgress();
+ break;
+
+ case R.id.forwardBtn:
+ pos = mPlayer.getCurrentPosition();
+ pos += 15000;
+ mPlayer.seekTo(pos);
+ if (!playing) mPlayer.pause(); // necessary in some 2.3.x devices
+ setProgress();
+ break;
+
+ }
+ }
+
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if (!fromUser) {
+ // We're not interested in programmatically generated changes to
+ // the progress bar's position.
+ return;
+ }
+
+ long duration = mPlayer.getDuration();
+ long newposition = (duration * progress) / 1000L;
+ mPlayer.seekTo( (int) newposition);
+ if (mCurrentTime != null)
+ mCurrentTime.setText(stringForTime( (int) newposition));
+ }
+
+ /**
+ * Called in devices with touchpad when the user starts to adjust the
+ * position of the seekbar's thumb.
+ *
+ * Will be followed by several onProgressChanged notifications.
+ */
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ mDragging = true; // monitors the duration of dragging
+ mHandler.removeMessages(SHOW_PROGRESS); // grants no more updates with media player progress while dragging
+ }
+
+
+ /**
+ * Called in devices with touchpad when the user finishes the
+ * adjusting of the seekbar.
+ */
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ mDragging = false;
+ setProgress();
+ updatePausePlay();
+ mHandler.sendEmptyMessage(SHOW_PROGRESS); // grants future updates with media player progress
+ }
+
+ @Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(event);
+ event.setClassName(MediaControlView.class.getName());
+ }
+
+ @Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(info);
+ info.setClassName(MediaControlView.class.getName());
+ }
+
+}
--- /dev/null
+/* ownCloud Android client application
+ * Copyright 2013 ownCloud Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.media;
+
+import android.accounts.Account;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnCompletionListener;
+import android.media.MediaPlayer.OnErrorListener;
+import android.media.MediaPlayer.OnPreparedListener;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiManager.WifiLock;
+import android.os.IBinder;
+import android.os.PowerManager;
+import android.util.Log;
+import android.widget.Toast;
+
+import java.io.IOException;
+
+import com.owncloud.android.R;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.ui.activity.FileDetailActivity;
+import com.owncloud.android.ui.fragment.FileDetailFragment;
+
+/**
+ * Service that handles media playback, both audio and video.
+ *
+ * Waits for Intents which signal the service to perform specific operations: Play, Pause,
+ * Rewind, etc.
+ *
+ * @author David A. Velasco
+ */
+public class MediaService extends Service implements OnCompletionListener, OnPreparedListener,
+ OnErrorListener, AudioManager.OnAudioFocusChangeListener {
+
+ private static final String TAG = MediaService.class.getSimpleName();
+
+ private static final String MY_PACKAGE = MediaService.class.getPackage() != null ? MediaService.class.getPackage().getName() : "com.owncloud.android.media";
+
+ /// Intent actions that we are prepared to handle
+ public static final String ACTION_PLAY_FILE = MY_PACKAGE + ".action.PLAY_FILE";
+ public static final String ACTION_STOP_ALL = MY_PACKAGE + ".action.STOP_ALL";
+
+ /// Keys to add extras to the action
+ public static final String EXTRA_FILE = MY_PACKAGE + ".extra.FILE";
+ public static final String EXTRA_ACCOUNT = MY_PACKAGE + ".extra.ACCOUNT";
+ public static String EXTRA_START_POSITION = MY_PACKAGE + ".extra.START_POSITION";
+ public static final String EXTRA_PLAY_ON_LOAD = MY_PACKAGE + ".extra.PLAY_ON_LOAD";
+
+
+ /** Error code for specific messages - see regular error codes at {@link MediaPlayer} */
+ public static final int OC_MEDIA_ERROR = 0;
+
+ /** Time To keep the control panel visible when the user does not use it */
+ public static final int MEDIA_CONTROL_SHORT_LIFE = 4000;
+
+ /** Time To keep the control panel visible when the user does not use it */
+ public static final int MEDIA_CONTROL_PERMANENT = 0;
+
+ /** Volume to set when audio focus is lost and ducking is allowed */
+ private static final float DUCK_VOLUME = 0.1f;
+
+ /** Media player instance */
+ private MediaPlayer mPlayer = null;
+
+ /** Reference to the system AudioManager */
+ private AudioManager mAudioManager = null;
+
+
+ /** Values to indicate the state of the service */
+ enum State {
+ STOPPED,
+ PREPARING,
+ PLAYING,
+ PAUSED
+ };
+
+
+ /** Current state */
+ private State mState = State.STOPPED;
+
+ /** Possible focus values */
+ enum AudioFocus {
+ NO_FOCUS,
+ NO_FOCUS_CAN_DUCK,
+ FOCUS
+ }
+
+ /** Current focus state */
+ private AudioFocus mAudioFocus = AudioFocus.NO_FOCUS;
+
+
+ /** 'True' when the current song is streaming from the network */
+ private boolean mIsStreaming = false;
+
+ /** Wifi lock kept to prevents the device from shutting off the radio when streaming a file. */
+ private WifiLock mWifiLock;
+
+ private static final String MEDIA_WIFI_LOCK_TAG = MY_PACKAGE + ".WIFI_LOCK";
+
+ /** Notification to keep in the notification bar while a song is playing */
+ private NotificationManager mNotificationManager;
+ private Notification mNotification = null;
+
+ /** File being played */
+ private OCFile mFile;
+
+ /** Account holding the file being played */
+ private Account mAccount;
+
+ /** Flag signaling if the audio should be played immediately when the file is prepared */
+ protected boolean mPlayOnPrepared;
+
+ /** Position, in miliseconds, where the audio should be started */
+ private int mStartPosition;
+
+ /** Interface to access the service through binding */
+ private IBinder mBinder;
+
+ /** Control panel shown to the user to control the playback, to register through binding */
+ private MediaControlView mMediaController;
+
+
+
+ /**
+ * Helper method to get an error message suitable to show to users for errors occurred in media playback,
+ *
+ * @param context A context to access string resources.
+ * @param what See {@link MediaPlayer.OnErrorListener#onError(MediaPlayer, int, int)
+ * @param extra See {@link MediaPlayer.OnErrorListener#onError(MediaPlayer, int, int)
+ * @return Message suitable to users.
+ */
+ public static String getMessageForMediaError(Context context, int what, int extra) {
+ int messageId;
+
+ if (what == OC_MEDIA_ERROR) {
+ messageId = extra;
+
+ } else if (extra == MediaPlayer.MEDIA_ERROR_UNSUPPORTED) {
+ /* Added in API level 17
+ Bitstream is conforming to the related coding standard or file spec, but the media framework does not support the feature.
+ Constant Value: -1010 (0xfffffc0e)
+ */
+ messageId = R.string.media_err_unsupported;
+
+ } else if (extra == MediaPlayer.MEDIA_ERROR_IO) {
+ /* Added in API level 17
+ File or network related operation errors.
+ Constant Value: -1004 (0xfffffc14)
+ */
+ messageId = R.string.media_err_io;
+
+ } else if (extra == MediaPlayer.MEDIA_ERROR_MALFORMED) {
+ /* Added in API level 17
+ Bitstream is not conforming to the related coding standard or file spec.
+ Constant Value: -1007 (0xfffffc11)
+ */
+ messageId = R.string.media_err_malformed;
+
+ } else if (extra == MediaPlayer.MEDIA_ERROR_TIMED_OUT) {
+ /* Added in API level 17
+ Some operation takes too long to complete, usually more than 3-5 seconds.
+ Constant Value: -110 (0xffffff92)
+ */
+ messageId = R.string.media_err_timeout;
+
+ } else if (what == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) {
+ /* Added in API level 3
+ The video is streamed and its container is not valid for progressive playback i.e the video's index (e.g moov atom) is not at the start of the file.
+ Constant Value: 200 (0x000000c8)
+ */
+ messageId = R.string.media_err_invalid_progressive_playback;
+
+ } else {
+ /* MediaPlayer.MEDIA_ERROR_UNKNOWN
+ Added in API level 1
+ Unspecified media player error.
+ Constant Value: 1 (0x00000001)
+ */
+ /* MediaPlayer.MEDIA_ERROR_SERVER_DIED)
+ Added in API level 1
+ Media server died. In this case, the application must release the MediaPlayer object and instantiate a new one.
+ Constant Value: 100 (0x00000064)
+ */
+ messageId = R.string.media_err_unknown;
+ }
+ return context.getString(messageId);
+ }
+
+
+
+ /**
+ * Initialize a service instance
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public void onCreate() {
+ Log.d(TAG, "Creating ownCloud media service");
+
+ mWifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE)).
+ createWifiLock(WifiManager.WIFI_MODE_FULL, MEDIA_WIFI_LOCK_TAG);
+
+ mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+ mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
+ mBinder = new MediaServiceBinder(this);
+ }
+
+
+ /**
+ * Entry point for Intents requesting actions, sent here via startService.
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ String action = intent.getAction();
+ if (action.equals(ACTION_PLAY_FILE)) {
+ processPlayFileRequest(intent);
+
+ } else if (action.equals(ACTION_STOP_ALL)) {
+ processStopRequest(true);
+ }
+
+ return START_NOT_STICKY; // don't want it to restart in case it's killed.
+ }
+
+
+ /**
+ * Processes a request to play a media file received as a parameter
+ *
+ * TODO If a new request is received when a file is being prepared, it is ignored. Is this what we want?
+ *
+ * @param intent Intent received in the request with the data to identify the file to play.
+ */
+ private void processPlayFileRequest(Intent intent) {
+ if (mState != State.PREPARING) {
+ mFile = intent.getExtras().getParcelable(EXTRA_FILE);
+ mAccount = intent.getExtras().getParcelable(EXTRA_ACCOUNT);
+ mPlayOnPrepared = intent.getExtras().getBoolean(EXTRA_PLAY_ON_LOAD, false);
+ mStartPosition = intent.getExtras().getInt(EXTRA_START_POSITION, 0);
+ tryToGetAudioFocus();
+ playMedia();
+ }
+ }
+
+
+ /**
+ * Processes a request to play a media file.
+ */
+ protected void processPlayRequest() {
+ // request audio focus
+ tryToGetAudioFocus();
+
+ // actually play the song
+ if (mState == State.STOPPED) {
+ // (re)start playback
+ playMedia();
+
+ } else if (mState == State.PAUSED) {
+ // continue playback
+ mState = State.PLAYING;
+ setUpAsForeground(String.format(getString(R.string.media_state_playing), mFile.getFileName()));
+ configAndStartMediaPlayer();
+
+ }
+ }
+
+
+ /**
+ * Makes sure the media player exists and has been reset. This will create the media player
+ * if needed, or reset the existing media player if one already exists.
+ */
+ protected void createMediaPlayerIfNeeded() {
+ if (mPlayer == null) {
+ mPlayer = new MediaPlayer();
+
+ // make sure the CPU won't go to sleep while media is playing
+ mPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
+
+ // the media player will notify the service when it's ready preparing, and when it's done playing
+ mPlayer.setOnPreparedListener(this);
+ mPlayer.setOnCompletionListener(this);
+ mPlayer.setOnErrorListener(this);
+
+ } else {
+ mPlayer.reset();
+ }
+ }
+
+ /**
+ * Processes a request to pause the current playback
+ */
+ protected void processPauseRequest() {
+ if (mState == State.PLAYING) {
+ mState = State.PAUSED;
+ mPlayer.pause();
+ releaseResources(false); // retain media player in pause
+ // TODO polite audio focus, instead of keep it owned; or not?
+ }
+ }
+
+
+ /**
+ * Processes a request to stop the playback.
+ *
+ * @param force When 'true', the playback is stopped no matter the value of mState
+ */
+ protected void processStopRequest(boolean force) {
+ if (mState != State.PREPARING || force) {
+ mState = State.STOPPED;
+ mFile = null;
+ mAccount = null;
+ releaseResources(true);
+ giveUpAudioFocus();
+ stopSelf(); // service is no longer necessary
+ }
+ }
+
+
+ /**
+ * Releases resources used by the service for playback. This includes the "foreground service"
+ * status and notification, the wake locks and possibly the MediaPlayer.
+ *
+ * @param releaseMediaPlayer Indicates whether the Media Player should also be released or not
+ */
+ protected void releaseResources(boolean releaseMediaPlayer) {
+ // stop being a foreground service
+ stopForeground(true);
+
+ // stop and release the Media Player, if it's available
+ if (releaseMediaPlayer && mPlayer != null) {
+ mPlayer.reset();
+ mPlayer.release();
+ mPlayer = null;
+ }
+
+ // release the Wifi lock, if holding it
+ if (mWifiLock.isHeld()) {
+ mWifiLock.release();
+ }
+ }
+
+
+ /**
+ * Fully releases the audio focus.
+ */
+ private void giveUpAudioFocus() {
+ if (mAudioFocus == AudioFocus.FOCUS
+ && mAudioManager != null
+ && AudioManager.AUDIOFOCUS_REQUEST_GRANTED == mAudioManager.abandonAudioFocus(this)) {
+
+ mAudioFocus = AudioFocus.NO_FOCUS;
+ }
+ }
+
+
+ /**
+ * Reconfigures MediaPlayer according to audio focus settings and starts/restarts it.
+ */
+ protected void configAndStartMediaPlayer() {
+ if (mPlayer == null) {
+ throw new IllegalStateException("mPlayer is NULL");
+ }
+
+ if (mAudioFocus == AudioFocus.NO_FOCUS) {
+ if (mPlayer.isPlaying()) {
+ mPlayer.pause(); // have to be polite; but mState is not changed, to resume when focus is received again
+ }
+
+ } else {
+ if (mAudioFocus == AudioFocus.NO_FOCUS_CAN_DUCK) {
+ mPlayer.setVolume(DUCK_VOLUME, DUCK_VOLUME);
+
+ } else {
+ mPlayer.setVolume(1.0f, 1.0f); // full volume
+ }
+
+ if (!mPlayer.isPlaying()) {
+ mPlayer.start();
+ }
+ }
+ }
+
+
+ /**
+ * Requests the audio focus to the Audio Manager
+ */
+ private void tryToGetAudioFocus() {
+ if (mAudioFocus != AudioFocus.FOCUS
+ && mAudioManager != null
+ && (AudioManager.AUDIOFOCUS_REQUEST_GRANTED == mAudioManager.requestAudioFocus( this,
+ AudioManager.STREAM_MUSIC,
+ AudioManager.AUDIOFOCUS_GAIN))
+ ) {
+ mAudioFocus = AudioFocus.FOCUS;
+ }
+ }
+
+
+ /**
+ * Starts playing the current media file.
+ */
+ protected void playMedia() {
+ mState = State.STOPPED;
+ releaseResources(false); // release everything except MediaPlayer
+
+ try {
+ if (mFile == null) {
+ Toast.makeText(this, R.string.media_err_nothing_to_play, Toast.LENGTH_LONG).show();
+ processStopRequest(true);
+ return;
+
+ } else if (mAccount == null) {
+ Toast.makeText(this, R.string.media_err_not_in_owncloud, Toast.LENGTH_LONG).show();
+ processStopRequest(true);
+ return;
+ }
+
+ createMediaPlayerIfNeeded();
+ mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+ String url = mFile.getStoragePath();
+ /* Streaming is not possible right now
+ if (url == null || url.length() <= 0) {
+ url = AccountUtils.constructFullURLForAccount(this, mAccount) + mFile.getRemotePath();
+ }
+ mIsStreaming = url.startsWith("http:") || url.startsWith("https:");
+ */
+ mIsStreaming = false;
+
+ mPlayer.setDataSource(url);
+
+ mState = State.PREPARING;
+ setUpAsForeground(String.format(getString(R.string.media_state_loading), mFile.getFileName()));
+
+ // starts preparing the media player in background
+ mPlayer.prepareAsync();
+
+ // prevent the Wifi from going to sleep when streaming
+ if (mIsStreaming) {
+ mWifiLock.acquire();
+ } else if (mWifiLock.isHeld()) {
+ mWifiLock.release();
+ }
+
+ } catch (SecurityException e) {
+ Log.e(TAG, "SecurityException playing " + mAccount.name + mFile.getRemotePath(), e);
+ Toast.makeText(this, String.format(getString(R.string.media_err_security_ex), mFile.getFileName()), Toast.LENGTH_LONG).show();
+ processStopRequest(true);
+
+ } catch (IOException e) {
+ Log.e(TAG, "IOException playing " + mAccount.name + mFile.getRemotePath(), e);
+ Toast.makeText(this, String.format(getString(R.string.media_err_io_ex), mFile.getFileName()), Toast.LENGTH_LONG).show();
+ processStopRequest(true);
+
+ } catch (IllegalStateException e) {
+ Log.e(TAG, "IllegalStateException " + mAccount.name + mFile.getRemotePath(), e);
+ Toast.makeText(this, String.format(getString(R.string.media_err_unexpected), mFile.getFileName()), Toast.LENGTH_LONG).show();
+ processStopRequest(true);
+
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "IllegalArgumentException " + mAccount.name + mFile.getRemotePath(), e);
+ Toast.makeText(this, String.format(getString(R.string.media_err_unexpected), mFile.getFileName()), Toast.LENGTH_LONG).show();
+ processStopRequest(true);
+ }
+ }
+
+
+ /** Called when media player is done playing current song. */
+ public void onCompletion(MediaPlayer player) {
+ Toast.makeText(this, String.format(getString(R.string.media_event_done, mFile.getFileName())), Toast.LENGTH_LONG).show();
+ if (mMediaController != null) {
+ // somebody is still bound to the service
+ player.seekTo(0);
+ processPauseRequest();
+ mMediaController.updatePausePlay();
+ } else {
+ // nobody is bound
+ processStopRequest(true);
+ }
+ return;
+ }
+
+
+ /**
+ * Called when media player is done preparing.
+ *
+ * Time to start.
+ */
+ public void onPrepared(MediaPlayer player) {
+ mState = State.PLAYING;
+ updateNotification(String.format(getString(R.string.media_state_playing), mFile.getFileName()));
+ if (mMediaController != null) {
+ mMediaController.setEnabled(true);
+ }
+ player.seekTo(mStartPosition);
+ configAndStartMediaPlayer();
+ if (!mPlayOnPrepared) {
+ processPauseRequest();
+ }
+
+ if (mMediaController != null) {
+ mMediaController.updatePausePlay();
+ }
+ }
+
+
+ /**
+ * Updates the status notification
+ */
+ @SuppressWarnings("deprecation")
+ private void updateNotification(String content) {
+ // TODO check if updating the Intent is really necessary
+ Intent showDetailsIntent = new Intent(this, FileDetailActivity.class);
+ showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, mFile);
+ showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, mAccount);
+ showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ mNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(),
+ (int)System.currentTimeMillis(),
+ showDetailsIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+ mNotification.when = System.currentTimeMillis();
+ //mNotification.contentView.setTextViewText(R.id.status_text, content);
+ String ticker = String.format(getString(R.string.media_notif_ticker), getString(R.string.app_name));
+ mNotification.setLatestEventInfo(getApplicationContext(), ticker, content, mNotification.contentIntent);
+ mNotificationManager.notify(R.string.media_notif_ticker, mNotification);
+ }
+
+
+ /**
+ * Configures the service as a foreground service.
+ *
+ * The system will avoid finishing the service as much as possible when resources as low.
+ *
+ * A notification must be created to keep the user aware of the existance of the service.
+ */
+ @SuppressWarnings("deprecation")
+ private void setUpAsForeground(String content) {
+ /// creates status notification
+ // TODO put a progress bar to follow the playback progress
+ mNotification = new Notification();
+ mNotification.icon = android.R.drawable.ic_media_play;
+ //mNotification.tickerText = text;
+ mNotification.when = System.currentTimeMillis();
+ mNotification.flags |= Notification.FLAG_ONGOING_EVENT;
+ //mNotification.contentView.setTextViewText(R.id.status_text, "ownCloud Music Player"); // NULL POINTER
+ //mNotification.contentView.setTextViewText(R.id.status_text, getString(R.string.downloader_download_in_progress_content));
+
+
+ /// includes a pending intent in the notification showing the details view of the file
+ Intent showDetailsIntent = new Intent(this, FileDetailActivity.class);
+ showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, mFile);
+ showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, mAccount);
+ showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ mNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(),
+ (int)System.currentTimeMillis(),
+ showDetailsIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+
+
+ //mNotificationManager.notify(R.string.downloader_download_in_progress_ticker, mNotification);
+ String ticker = String.format(getString(R.string.media_notif_ticker), getString(R.string.app_name));
+ mNotification.setLatestEventInfo(getApplicationContext(), ticker, content, mNotification.contentIntent);
+ startForeground(R.string.media_notif_ticker, mNotification);
+
+ }
+
+ /**
+ * Called when there's an error playing media.
+ *
+ * Warns the user about the error and resets the media player.
+ */
+ public boolean onError(MediaPlayer mp, int what, int extra) {
+ Log.e(TAG, "Error in audio playback, what = " + what + ", extra = " + extra);
+
+ String message = getMessageForMediaError(this, what, extra);
+ Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
+
+ processStopRequest(true);
+ return true;
+ }
+
+ /**
+ * Called by the system when another app tries to play some sound.
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public void onAudioFocusChange(int focusChange) {
+ if (focusChange > 0) {
+ // focus gain; check AudioManager.AUDIOFOCUS_* values
+ mAudioFocus = AudioFocus.FOCUS;
+ // restart media player with new focus settings
+ if (mState == State.PLAYING)
+ configAndStartMediaPlayer();
+
+ } else if (focusChange < 0) {
+ // focus loss; check AudioManager.AUDIOFOCUS_* values
+ boolean canDuck = AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK == focusChange;
+ mAudioFocus = canDuck ? AudioFocus.NO_FOCUS_CAN_DUCK : AudioFocus.NO_FOCUS;
+ // start/restart/pause media player with new focus settings
+ if (mPlayer != null && mPlayer.isPlaying())
+ configAndStartMediaPlayer();
+ }
+
+ }
+
+ /**
+ * Called when the service is finished for final clean-up.
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public void onDestroy() {
+ mState = State.STOPPED;
+ releaseResources(true);
+ giveUpAudioFocus();
+ }
+
+
+ /**
+ * Provides a binder object that clients can use to perform operations on the MediaPlayer managed by the MediaService.
+ */
+ @Override
+ public IBinder onBind(Intent arg) {
+ return mBinder;
+ }
+
+
+ /**
+ * Called when ALL the bound clients were onbound.
+ *
+ * The service is destroyed if playback stopped or paused
+ */
+ @Override
+ public boolean onUnbind(Intent intent) {
+ if (mState == State.PAUSED || mState == State.STOPPED) {
+ processStopRequest(false);
+ }
+ return false; // not accepting rebinding (default behaviour)
+ }
+
+
+ /**
+ * Accesses the current MediaPlayer instance in the service.
+ *
+ * To be handled carefully. Visibility is protected to be accessed only
+ *
+ * @return Current MediaPlayer instance handled by MediaService.
+ */
+ protected MediaPlayer getPlayer() {
+ return mPlayer;
+ }
+
+
+ /**
+ * Accesses the current OCFile loaded in the service.
+ *
+ * @return The current OCFile loaded in the service.
+ */
+ protected OCFile getCurrentFile() {
+ return mFile;
+ }
+
+
+ /**
+ * Accesses the current {@link State} of the MediaService.
+ *
+ * @return The current {@link State} of the MediaService.
+ */
+ protected State getState() {
+ return mState;
+ }
+
+
+ protected void setMediaContoller(MediaControlView mediaController) {
+ mMediaController = mediaController;
+ }
+
+ protected MediaControlView getMediaController() {
+ return mMediaController;
+ }
+
+}
--- /dev/null
+/* ownCloud Android client application
+ * Copyright (C) 2013 ownCloud Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.media;
+
+
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.media.MediaService.State;
+
+import android.accounts.Account;
+import android.content.Intent;
+import android.media.MediaPlayer;
+import android.os.Binder;
+import android.util.Log;
+import android.widget.MediaController;
+
+
+/**
+ * Binder allowing client components to perform operations on on the MediaPlayer managed by a MediaService instance.
+ *
+ * Provides the operations of {@link MediaController.MediaPlayerControl}, and an extra method to check if
+ * an {@link OCFile} instance is handled by the MediaService.
+ *
+ * @author David A. Velasco
+ */
+public class MediaServiceBinder extends Binder implements MediaController.MediaPlayerControl {
+
+ private static final String TAG = MediaServiceBinder.class.getSimpleName();
+ /**
+ * {@link MediaService} instance to access with the binder
+ */
+ private MediaService mService = null;
+
+ /**
+ * Public constructor
+ *
+ * @param service A {@link MediaService} instance to access with the binder
+ */
+ public MediaServiceBinder(MediaService service) {
+ if (service == null) {
+ throw new IllegalArgumentException("Argument 'service' can not be null");
+ }
+ mService = service;
+ }
+
+
+ public boolean isPlaying(OCFile mFile) {
+ return (mFile != null && mFile.equals(mService.getCurrentFile()));
+ }
+
+
+ @Override
+ public boolean canPause() {
+ return true;
+ }
+
+ @Override
+ public boolean canSeekBackward() {
+ return true;
+ }
+
+ @Override
+ public boolean canSeekForward() {
+ return true;
+ }
+
+ @Override
+ public int getBufferPercentage() {
+ MediaPlayer currentPlayer = mService.getPlayer();
+ if (currentPlayer != null) {
+ return 100;
+ // TODO update for streamed playback; add OnBufferUpdateListener in MediaService
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public int getCurrentPosition() {
+ MediaPlayer currentPlayer = mService.getPlayer();
+ if (currentPlayer != null) {
+ int pos = currentPlayer.getCurrentPosition();
+ return pos;
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public int getDuration() {
+ MediaPlayer currentPlayer = mService.getPlayer();
+ if (currentPlayer != null) {
+ int dur = currentPlayer.getDuration();
+ return dur;
+ } else {
+ return 0;
+ }
+ }
+
+
+ /**
+ * Reports if the MediaService is playing a file or not.
+ *
+ * Considers that the file is being played when it is in preparation because the expected
+ * client of this method is a {@link MediaController} , and we do not want that the 'play'
+ * button is shown when the file is being prepared by the MediaService.
+ */
+ @Override
+ public boolean isPlaying() {
+ MediaService.State currentState = mService.getState();
+ return (currentState == State.PLAYING || (currentState == State.PREPARING && mService.mPlayOnPrepared));
+ }
+
+
+ @Override
+ public void pause() {
+ Log.d(TAG, "Pausing through binder...");
+ mService.processPauseRequest();
+ }
+
+ @Override
+ public void seekTo(int pos) {
+ Log.d(TAG, "Seeking " + pos + " through binder...");
+ MediaPlayer currentPlayer = mService.getPlayer();
+ MediaService.State currentState = mService.getState();
+ if (currentPlayer != null && currentState != State.PREPARING && currentState != State.STOPPED) {
+ currentPlayer.seekTo(pos);
+ }
+ }
+
+ @Override
+ public void start() {
+ Log.d(TAG, "Starting through binder...");
+ mService.processPlayRequest(); // this will finish the service if there is no file preloaded to play
+ }
+
+ public void start(Account account, OCFile file, boolean playImmediately, int position) {
+ Log.d(TAG, "Loading and starting through binder...");
+ Intent i = new Intent(mService, MediaService.class);
+ i.putExtra(MediaService.EXTRA_ACCOUNT, account);
+ i.putExtra(MediaService.EXTRA_FILE, file);
+ i.putExtra(MediaService.EXTRA_PLAY_ON_LOAD, playImmediately);
+ i.putExtra(MediaService.EXTRA_START_POSITION, position);
+ i.setAction(MediaService.ACTION_PLAY_FILE);
+ mService.startService(i);
+ }
+
+
+ public void registerMediaController(MediaControlView mediaController) {
+ mService.setMediaContoller(mediaController);
+ }
+
+ public void unregisterMediaController(MediaControlView mediaController) {
+ if (mediaController != null && mediaController == mService.getMediaController()) {
+ mService.setMediaContoller(null);
+ }
+
+ }
+
+ public boolean isInPlaybackState() {
+ MediaService.State currentState = mService.getState();
+ return (currentState == MediaService.State.PLAYING || currentState == MediaService.State.PAUSED);
+ }
+
+}
+
+
--- /dev/null
+/* ownCloud Android client application
+ * Copyright (C) 2012-2013 ownCloud Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.network;
+
+import java.util.Collection;
+
+import eu.alefzero.webdav.OnDatatransferProgressListener;
+
+public interface ProgressiveDataTransferer {
+
+ public void addDatatransferProgressListener (OnDatatransferProgressListener listener);
+
+ public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners);
+
+ public void removeDatatransferProgressListener(OnDatatransferProgressListener listener);
+
+}
import com.owncloud.android.Log_OC;
import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.network.ProgressiveDataTransferer;
import android.accounts.Account;
import android.util.Log;
File file = new File(getStoragePath());
raf = new RandomAccessFile(file, "r");
channel = raf.getChannel();
- ChunkFromFileChannelRequestEntity entity = new ChunkFromFileChannelRequestEntity(channel, getMimeType(), CHUNK_SIZE, file);
- entity.addOnDatatransferProgressListeners(getDataTransferListeners());
+ mEntity = new ChunkFromFileChannelRequestEntity(channel, getMimeType(), CHUNK_SIZE, file);
+ ((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(getDataTransferListeners());
long offset = 0;
String uriPrefix = client.getBaseUri() + WebdavUtils.encodePath(getRemotePath()) + "-chunking-" + Math.abs((new Random()).nextInt(9000)+1000) + "-" ;
long chunkCount = (long) Math.ceil((double)file.length() / CHUNK_SIZE);
for (int chunkIndex = 0; chunkIndex < chunkCount ; chunkIndex++, offset += CHUNK_SIZE) {
mPutMethod = new PutMethod(uriPrefix + chunkCount + "-" + chunkIndex);
mPutMethod.addRequestHeader(OC_CHUNKED_HEADER, OC_CHUNKED_HEADER);
- entity.setOffset(offset);
- mPutMethod.setRequestEntity(entity);
+ ((ChunkFromFileChannelRequestEntity)mEntity).setOffset(offset);
+ mPutMethod.setRequestEntity(mEntity);
status = client.executeMethod(mPutMethod);
client.exhaustResponse(mPutMethod.getResponseBodyAsStream());
Log_OC.d(TAG, "Upload of " + getStoragePath() + " to " + getRemotePath() + ", chunk index " + chunkIndex + ", count " + chunkCount + ", HTTP result status " + status);
public void addDatatransferProgressListener (OnDatatransferProgressListener listener) {
- mDataTransferListeners.add(listener);
+ synchronized (mDataTransferListeners) {
+ mDataTransferListeners.add(listener);
+ }
}
+ public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
+ synchronized (mDataTransferListeners) {
+ mDataTransferListeners.remove(listener);
+ }
+ }
+
@Override
protected RemoteOperationResult run(WebdavClient client) {
RemoteOperationResult result = null;
}
fos.write(bytes, 0, readResult);
transferred += readResult;
- it = mDataTransferListeners.iterator();
- while (it.hasNext()) {
- it.next().onTransferProgress(readResult, transferred, mFile.getFileLength(), targetFile.getName());
+ synchronized (mDataTransferListeners) {
+ it = mDataTransferListeners.iterator();
+ while (it.hasNext()) {
+ it.next().onTransferProgress(readResult, transferred, mFile.getFileLength(), targetFile.getName());
+ }
}
}
savedFile = true;
mCancellationRequested.set(true); // atomic set; there is no need of synchronizing it
}
+
}
import org.apache.commons.httpclient.HttpStatus;
import org.apache.jackrabbit.webdav.DavException;
-import com.owncloud.android.network.CertificateCombinedException;
+import android.util.Log;
+import com.owncloud.android.network.CertificateCombinedException;
/**
* The result of a remote operation required to an ownCloud server.
*
- * Provides a common classification of remote operation results for all the application.
+ * Provides a common classification of remote operation results for all the
+ * application.
*
* @author David A. Velasco
*/
public class RemoteOperationResult implements Serializable {
-
+
/** Generated - should be refreshed every time the class changes!! */
private static final long serialVersionUID = -7805531062432602444L;
+ private static final String TAG = "RemoteOperationResult";
-
- public enum ResultCode {
- OK,
- OK_SSL,
- OK_NO_SSL,
- UNHANDLED_HTTP_CODE,
- UNAUTHORIZED,
- FILE_NOT_FOUND,
- INSTANCE_NOT_CONFIGURED,
- UNKNOWN_ERROR,
- WRONG_CONNECTION,
- TIMEOUT,
- INCORRECT_ADDRESS,
- HOST_NOT_AVAILABLE,
- NO_NETWORK_CONNECTION,
- SSL_ERROR,
- SSL_RECOVERABLE_PEER_UNVERIFIED,
- BAD_OC_VERSION,
- CANCELLED,
- INVALID_LOCAL_FILE_NAME,
- INVALID_OVERWRITE,
- CONFLICT,
- SYNC_CONFLICT,
- LOCAL_STORAGE_FULL,
- LOCAL_STORAGE_NOT_MOVED,
- LOCAL_STORAGE_NOT_COPIED
+ public enum ResultCode {
+ OK, OK_SSL, OK_NO_SSL, UNHANDLED_HTTP_CODE, UNAUTHORIZED, FILE_NOT_FOUND, INSTANCE_NOT_CONFIGURED, UNKNOWN_ERROR, WRONG_CONNECTION, TIMEOUT, INCORRECT_ADDRESS, HOST_NOT_AVAILABLE, NO_NETWORK_CONNECTION, SSL_ERROR, SSL_RECOVERABLE_PEER_UNVERIFIED, BAD_OC_VERSION, CANCELLED, INVALID_LOCAL_FILE_NAME, INVALID_OVERWRITE, CONFLICT, SYNC_CONFLICT, LOCAL_STORAGE_FULL, LOCAL_STORAGE_NOT_MOVED, LOCAL_STORAGE_NOT_COPIED, QUOTA_EXCEEDED
}
private boolean mSuccess = false;
private int mHttpCode = -1;
private Exception mException = null;
private ResultCode mCode = ResultCode.UNKNOWN_ERROR;
-
+
public RemoteOperationResult(ResultCode code) {
mCode = code;
mSuccess = (code == ResultCode.OK || code == ResultCode.OK_SSL || code == ResultCode.OK_NO_SSL);
}
-
+
public RemoteOperationResult(boolean success, int httpCode) {
- mSuccess = success;
+ mSuccess = success;
mHttpCode = httpCode;
if (success) {
mCode = ResultCode.OK;
-
+
} else if (httpCode > 0) {
switch (httpCode) {
- case HttpStatus.SC_UNAUTHORIZED:
- mCode = ResultCode.UNAUTHORIZED;
- break;
- case HttpStatus.SC_NOT_FOUND:
- mCode = ResultCode.FILE_NOT_FOUND;
- break;
- case HttpStatus.SC_INTERNAL_SERVER_ERROR:
- mCode = ResultCode.INSTANCE_NOT_CONFIGURED;
- break;
- case HttpStatus.SC_CONFLICT:
- mCode = ResultCode.CONFLICT;
- break;
- default:
- mCode = ResultCode.UNHANDLED_HTTP_CODE;
+ case HttpStatus.SC_UNAUTHORIZED:
+ mCode = ResultCode.UNAUTHORIZED;
+ break;
+ case HttpStatus.SC_NOT_FOUND:
+ mCode = ResultCode.FILE_NOT_FOUND;
+ break;
+ case HttpStatus.SC_INTERNAL_SERVER_ERROR:
+ mCode = ResultCode.INSTANCE_NOT_CONFIGURED;
+ break;
+ case HttpStatus.SC_CONFLICT:
+ mCode = ResultCode.CONFLICT;
+ break;
+ case HttpStatus.SC_INSUFFICIENT_STORAGE:
+ mCode = ResultCode.QUOTA_EXCEEDED;
+ break;
+ default:
+ mCode = ResultCode.UNHANDLED_HTTP_CODE;
+ Log.d(TAG, "RemoteOperationResult has prcessed UNHANDLED_HTTP_CODE: " + httpCode);
}
}
}
-
+
public RemoteOperationResult(Exception e) {
- mException = e;
-
+ mException = e;
+
if (e instanceof OperationCancelledException) {
mCode = ResultCode.CANCELLED;
-
- } else if (e instanceof SocketException) {
+
+ } else if (e instanceof SocketException) {
mCode = ResultCode.WRONG_CONNECTION;
-
+
} else if (e instanceof SocketTimeoutException) {
mCode = ResultCode.TIMEOUT;
-
+
} else if (e instanceof ConnectTimeoutException) {
mCode = ResultCode.TIMEOUT;
-
+
} else if (e instanceof MalformedURLException) {
mCode = ResultCode.INCORRECT_ADDRESS;
-
+
} else if (e instanceof UnknownHostException) {
mCode = ResultCode.HOST_NOT_AVAILABLE;
-
+
} else if (e instanceof SSLException || e instanceof RuntimeException) {
CertificateCombinedException se = getCertificateCombinedException(e);
if (se != null) {
mException = se;
- if (se.isRecoverable()) {
+ if (se.isRecoverable()) {
mCode = ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED;
}
-
- } else {
+ } else if (e instanceof RuntimeException) {
+ mCode = ResultCode.HOST_NOT_AVAILABLE;
+
+ } else {
mCode = ResultCode.SSL_ERROR;
}
-
+
} else {
mCode = ResultCode.UNKNOWN_ERROR;
}
-
+
}
-
-
+
public boolean isSuccess() {
return mSuccess;
}
-
+
public boolean isCancelled() {
return mCode == ResultCode.CANCELLED;
}
-
+
public int getHttpCode() {
return mHttpCode;
}
-
+
public ResultCode getCode() {
return mCode;
}
-
+
public Exception getException() {
return mException;
}
public boolean isSslRecoverableException() {
return mCode == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED;
}
-
+
private CertificateCombinedException getCertificateCombinedException(Exception e) {
CertificateCombinedException result = null;
if (e instanceof CertificateCombinedException) {
- return (CertificateCombinedException)e;
+ return (CertificateCombinedException) e;
}
Throwable cause = mException.getCause();
Throwable previousCause = null;
cause = cause.getCause();
}
if (cause != null && cause instanceof CertificateCombinedException) {
- result = (CertificateCombinedException)cause;
+ result = (CertificateCombinedException) cause;
}
return result;
}
-
-
+
public String getLogMessage() {
-
+
if (mException != null) {
if (mException instanceof OperationCancelledException) {
return "Operation cancelled by the caller";
-
- } else if (mException instanceof SocketException) {
+
+ } else if (mException instanceof SocketException) {
return "Socket exception";
-
+
} else if (mException instanceof SocketTimeoutException) {
return "Socket timeout exception";
-
+
} else if (mException instanceof ConnectTimeoutException) {
return "Connect timeout exception";
-
+
} else if (mException instanceof MalformedURLException) {
return "Malformed URL exception";
-
+
} else if (mException instanceof UnknownHostException) {
return "Unknown host exception";
-
+
} else if (mException instanceof CertificateCombinedException) {
if (((CertificateCombinedException) mException).isRecoverable())
return "SSL recoverable exception";
else
return "SSL exception";
-
+
} else if (mException instanceof SSLException) {
return "SSL exception";
return "Unexpected exception";
}
}
-
+
if (mCode == ResultCode.INSTANCE_NOT_CONFIGURED) {
return "The ownCloud server is not configured!";
-
+
} else if (mCode == ResultCode.NO_NETWORK_CONNECTION) {
return "No network connection";
-
+
} else if (mCode == ResultCode.BAD_OC_VERSION) {
return "No valid ownCloud version was found at the server";
-
+
} else if (mCode == ResultCode.LOCAL_STORAGE_FULL) {
return "Local storage full";
-
+
} else if (mCode == ResultCode.LOCAL_STORAGE_NOT_MOVED) {
return "Error while moving file to final directory";
}
-
- return "Operation finished with HTTP status code " + mHttpCode + " (" + (isSuccess()?"success":"fail") + ")";
-
+
+ return "Operation finished with HTTP status code " + mHttpCode + " (" + (isSuccess() ? "success" : "fail") + ")";
+
}
}
} catch (Exception e) {
result = new RemoteOperationResult(e);
- Log_OC.e(TAG, "Synchronizing " + mAccount.name + ", file " + mLocalFile.getRemotePath() + ": " + result.getLogMessage(), result.getException());
+ Log_OC.e(TAG, "Synchronizing " + mAccount.name + ", file " + (mLocalFile != null ? mLocalFile.getRemotePath() : "NULL") + ": " + result.getLogMessage(), result.getException());
} finally {
if (propfind != null)
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PutMethod;
+import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.http.HttpStatus;
import com.owncloud.android.Log_OC;
+import android.accounts.Account;
+
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.services.FileUploader;
+import com.owncloud.android.network.ProgressiveDataTransferer;
import com.owncloud.android.operations.RemoteOperation;
import com.owncloud.android.operations.RemoteOperationResult;
import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
import eu.alefzero.webdav.OnDatatransferProgressListener;
import eu.alefzero.webdav.WebdavClient;
import eu.alefzero.webdav.WebdavUtils;
-import android.accounts.Account;
-import android.util.Log;
/**
* Remote operation performing the upload of a file to an ownCloud server
* @author David A. Velasco
*/
public class UploadFileOperation extends RemoteOperation {
-
+
private static final String TAG = UploadFileOperation.class.getSimpleName();
private Account mAccount;
private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
+ protected RequestEntity mEntity = null;
+
public UploadFileOperation( Account account,
OCFile file,
throw new IllegalArgumentException("Illegal NULL account in UploadFileOperation creation");
if (file == null)
throw new IllegalArgumentException("Illegal NULL file in UploadFileOperation creation");
- if (file.getStoragePath() == null || file.getStoragePath().length() <= 0 || !(new File(file.getStoragePath()).exists())) {
- throw new IllegalArgumentException("Illegal file in UploadFileOperation; storage path invalid or file not found: " + file.getStoragePath());
+ if (file.getStoragePath() == null || file.getStoragePath().length() <= 0
+ || !(new File(file.getStoragePath()).exists())) {
+ throw new IllegalArgumentException(
+ "Illegal file in UploadFileOperation; storage path invalid or file not found: "
+ + file.getStoragePath());
}
-
+
mAccount = account;
mFile = file;
mRemotePath = file.getRemotePath();
mOriginalFileName = mFile.getFileName();
}
-
public Account getAccount() {
return mAccount;
}
-
+
public String getFileName() {
return mOriginalFileName;
}
-
+
public OCFile getFile() {
return mFile;
}
-
+
public OCFile getOldFile() {
- return mOldFile;
+ return mOldFile;
}
-
+
public String getOriginalStoragePath() {
return mOriginalStoragePath;
}
-
+
public String getStoragePath() {
return mFile.getStoragePath();
}
public String getRemotePath() {
- return mFile.getRemotePath();
+ return mFile.getRemotePath();
}
public String getMimeType() {
return mFile.getMimetype();
}
-
+
public boolean isInstant() {
return mIsInstant;
}
public boolean isRemoteFolderToBeCreated() {
return mRemoteFolderToBeCreated;
}
-
+
public void setRemoteFolderToBeCreated() {
mRemoteFolderToBeCreated = true;
}
public boolean getForceOverwrite() {
return mForceOverwrite;
}
-
+
public boolean wasRenamed() {
return mWasRenamed;
}
-
+
public Set<OnDatatransferProgressListener> getDataTransferListeners() {
return mDataTransferListeners;
}
public void addDatatransferProgressListener (OnDatatransferProgressListener listener) {
- mDataTransferListeners.add(listener);
+ synchronized (mDataTransferListeners) {
+ mDataTransferListeners.add(listener);
+ }
+ if (mEntity != null) {
+ ((ProgressiveDataTransferer)mEntity).addDatatransferProgressListener(listener);
+ }
}
+ public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
+ synchronized (mDataTransferListeners) {
+ mDataTransferListeners.remove(listener);
+ }
+ if (mEntity != null) {
+ ((ProgressiveDataTransferer)mEntity).removeDatatransferProgressListener(listener);
+ }
+ }
+
@Override
protected RemoteOperationResult run(WebdavClient client) {
RemoteOperationResult result = null;
boolean localCopyPassed = false, nameCheckPassed = false;
File temporalFile = null, originalFile = new File(mOriginalStoragePath), expectedFile = null;
try {
- /// rename the file to upload, if necessary
+ // / rename the file to upload, if necessary
if (!mForceOverwrite) {
String remotePath = getAvailableRemotePath(client, mRemotePath);
mWasRenamed = !remotePath.equals(mRemotePath);
if (mWasRenamed) {
- createNewOCFile(remotePath);
+ createNewOCFile(remotePath);
}
}
nameCheckPassed = true;
-
- String expectedPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, mFile); /// not before getAvailableRemotePath() !!!
+
+ String expectedPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, mFile); // /
+ // not
+ // before
+ // getAvailableRemotePath()
+ // !!!
expectedFile = new File(expectedPath);
-
- /// check location of local file; if not the expected, copy to a temporal file before upload (if COPY is the expected behaviour)
+
+ // / check location of local file; if not the expected, copy to a
+ // temporal file before upload (if COPY is the expected behaviour)
if (!mOriginalStoragePath.equals(expectedPath) && mLocalBehaviour == FileUploader.LOCAL_BEHAVIOUR_COPY) {
if (FileStorageUtils.getUsableSpace(mAccount.name) < originalFile.length()) {
result = new RemoteOperationResult(ResultCode.LOCAL_STORAGE_FULL);
- return result; // error condition when the file should be copied
-
+ return result; // error condition when the file should be
+ // copied
+
} else {
String temporalPath = FileStorageUtils.getTemporalPath(mAccount.name) + mFile.getRemotePath();
mFile.setStoragePath(temporalPath);
temporalFile = new File(temporalPath);
- if (!mOriginalStoragePath.equals(temporalPath)) { // preventing weird but possible situation
+ if (!mOriginalStoragePath.equals(temporalPath)) { // preventing
+ // weird
+ // but
+ // possible
+ // situation
InputStream in = null;
OutputStream out = null;
try {
temporalFile.createNewFile();
if (!temporalFile.isFile()) {
throw new IOException("Unexpected error: target file could not be created");
- }
+ }
in = new FileInputStream(originalFile);
out = new FileOutputStream(temporalFile);
byte[] buf = new byte[1024];
int len;
- while ((len = in.read(buf)) > 0){
+ while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
-
+
} catch (Exception e) {
result = new RemoteOperationResult(ResultCode.LOCAL_STORAGE_NOT_COPIED);
return result;
-
+
} finally {
try {
- if (in != null) in.close();
+ if (in != null)
+ in.close();
} catch (Exception e) {
Log_OC.d(TAG, "Weird exception while closing input stream for " + mOriginalStoragePath + " (ignoring)", e);
}
try {
- if (out != null) out.close();
+ if (out != null)
+ out.close();
} catch (Exception e) {
Log_OC.d(TAG, "Weird exception while closing output stream for " + expectedPath + " (ignoring)", e);
}
}
}
localCopyPassed = true;
-
- /// perform the upload
- synchronized(mCancellationRequested) {
+
+ // / perform the upload
+ synchronized (mCancellationRequested) {
if (mCancellationRequested.get()) {
throw new OperationCancelledException();
} else {
}
}
int status = uploadFile(client);
-
-
- /// move local temporal file or original file to its corresponding location in the ownCloud local folder
+
+ // / move local temporal file or original file to its corresponding
+ // location in the ownCloud local folder
if (isSuccess(status)) {
if (mLocalBehaviour == FileUploader.LOCAL_BEHAVIOUR_FORGET) {
mFile.setStoragePath(null);
-
+
} else {
mFile.setStoragePath(expectedPath);
File fileToMove = null;
- if (temporalFile != null) { // FileUploader.LOCAL_BEHAVIOUR_COPY ; see where temporalFile was set
+ if (temporalFile != null) { // FileUploader.LOCAL_BEHAVIOUR_COPY
+ // ; see where temporalFile was
+ // set
fileToMove = temporalFile;
- } else { // FileUploader.LOCAL_BEHAVIOUR_MOVE
+ } else { // FileUploader.LOCAL_BEHAVIOUR_MOVE
fileToMove = originalFile;
}
if (!expectedFile.equals(fileToMove)) {
expectedFolder.mkdirs();
if (!expectedFolder.isDirectory() || !fileToMove.renameTo(expectedFile)) {
mFile.setStoragePath(null); // forget the local file
- // by now, treat this as a success; the file was uploaded; the user won't like that the local file is not linked, but this should be a veeery rare fail;
- // the best option could be show a warning message (but not a fail)
- //result = new RemoteOperationResult(ResultCode.LOCAL_STORAGE_NOT_MOVED);
- //return result;
+ // by now, treat this as a success; the file was
+ // uploaded; the user won't like that the local file
+ // is not linked, but this should be a very rare
+ // fail;
+ // the best option could be show a warning message
+ // (but not a fail)
+ // result = new
+ // RemoteOperationResult(ResultCode.LOCAL_STORAGE_NOT_MOVED);
+ // return result;
}
}
- }
+ }
}
-
+
result = new RemoteOperationResult(isSuccess(status), status);
-
-
+
} catch (Exception e) {
// TODO something cleaner with cancellations
if (mCancellationRequested.get()) {
} else {
result = new RemoteOperationResult(e);
}
-
-
+
} finally {
if (temporalFile != null && !originalFile.equals(temporalFile)) {
temporalFile.delete();
}
if (result.isSuccess()) {
Log_OC.i(TAG, "Upload of " + mOriginalStoragePath + " to " + mRemotePath + ": " + result.getLogMessage());
-
} else {
if (result.getException() != null) {
String complement = "";
if (!nameCheckPassed) {
complement = " (while checking file existence in server)";
} else if (!localCopyPassed) {
- complement = " (while copying local file to " + FileStorageUtils.getSavePath(mAccount.name) + ")";
+ complement = " (while copying local file to " + FileStorageUtils.getSavePath(mAccount.name)
+ + ")";
}
Log_OC.e(TAG, "Upload of " + mOriginalStoragePath + " to " + mRemotePath + ": " + result.getLogMessage() + complement, result.getException());
} else {
}
}
}
-
+
return result;
}
-
private void createNewOCFile(String newRemotePath) {
// a new OCFile instance must be created for a new remote path
OCFile newFile = new OCFile(newRemotePath);
mFile = newFile;
}
-
public boolean isSuccess(int status) {
return ((status == HttpStatus.SC_OK || status == HttpStatus.SC_CREATED || status == HttpStatus.SC_NO_CONTENT));
}
-
-
+
protected int uploadFile(WebdavClient client) throws HttpException, IOException, OperationCancelledException {
int status = -1;
try {
File f = new File(mFile.getStoragePath());
- FileRequestEntity entity = new FileRequestEntity(f, getMimeType());
- entity.addOnDatatransferProgressListeners(mDataTransferListeners);
- mPutMethod.setRequestEntity(entity);
+ mEntity = new FileRequestEntity(f, getMimeType());
+ synchronized (mDataTransferListeners) {
+ ((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(mDataTransferListeners);
+ }
+ mPutMethod.setRequestEntity(mEntity);
status = client.executeMethod(mPutMethod);
client.exhaustResponse(mPutMethod.getResponseBodyAsStream());
-
+
} finally {
- mPutMethod.releaseConnection(); // let the connection available for other methods
+ mPutMethod.releaseConnection(); // let the connection available for
+ // other methods
}
return status;
}
-
+
/**
- * Checks if remotePath does not exist in the server and returns it, or adds a suffix to it in order to avoid the server
- * file is overwritten.
+ * Checks if remotePath does not exist in the server and returns it, or adds
+ * a suffix to it in order to avoid the server file is overwritten.
*
* @param string
* @return
if (!check) {
return remotePath;
}
-
+
int pos = remotePath.lastIndexOf(".");
String suffix = "";
String extension = "";
if (pos >= 0) {
- extension = remotePath.substring(pos+1);
+ extension = remotePath.substring(pos + 1);
remotePath = remotePath.substring(0, pos);
}
int count = 2;
count++;
} while (check);
- if (pos >=0) {
+ if (pos >= 0) {
return remotePath + suffix + "." + extension;
} else {
return remotePath + suffix;
}
}
-
public void cancel() {
- synchronized(mCancellationRequested) {
+ synchronized (mCancellationRequested) {
mCancellationRequested.set(true);
if (mPutMethod != null)
mPutMethod.abort();
}
}
-
}
--- /dev/null
+package com.owncloud.android.ui.activity;\r
+\r
+import android.app.Activity;\r
+import android.os.Bundle;\r
+import android.view.View;\r
+import android.view.View.OnClickListener;\r
+import android.widget.Button;\r
+import android.widget.TextView;\r
+\r
+import com.owncloud.android.R;\r
+\r
+/**\r
+ * This Activity is used to display a detail message for failed uploads\r
+ * \r
+ * The entry-point for this activity is the 'Failed upload Notification"\r
+ * \r
+ * \r
+ * @author andomaex / Matthias Baumann\r
+ * \r
+ * This program is free software: you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation, either version 3 of the License, or (at\r
+ * your option) any later version.\r
+ * \r
+ * This program is distributed in the hope that it will be useful, but\r
+ * WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+ * General Public License for more de/\r
+ */\r
+public class FailedUploadActivity extends Activity {\r
+\r
+ public static final String MESSAGE = "message";\r
+\r
+ @Override\r
+ public void onCreate(Bundle savedInstanceState) {\r
+ super.onCreate(savedInstanceState);\r
+ setContentView(R.layout.failed_upload_message_view);\r
+ String message = getIntent().getStringExtra(MESSAGE);\r
+ TextView textView = (TextView) findViewById(R.id.faild_upload_message);\r
+ textView.setText(message);\r
+ Button close_button = (Button) findViewById(R.id.failed_uploadactivity_close_button);\r
+ close_button.setOnClickListener(new OnClickListener() {\r
+ @Override\r
+ public void onClick(View v) {\r
+ finish();\r
+ }\r
+ });\r
+ }\r
+}\r
import android.accounts.Account;
import android.app.Dialog;
import android.app.ProgressDialog;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.IBinder;
+import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.MenuItem;
+import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.services.FileDownloader;
import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
import com.owncloud.android.files.services.FileUploader;
import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
import com.owncloud.android.ui.fragment.FileDetailFragment;
-
+import com.owncloud.android.ui.fragment.FileFragment;
+import com.owncloud.android.ui.preview.PreviewMediaFragment;
+import com.owncloud.android.AccountUtils;
import com.owncloud.android.Log_OC;
+
import com.owncloud.android.R;
/**
* on.
*
* @author Bartek Przybylski
- *
+ * @author David A. Velasco
*/
-public class FileDetailActivity extends SherlockFragmentActivity implements FileDetailFragment.ContainerActivity {
+public class FileDetailActivity extends SherlockFragmentActivity implements FileFragment.ContainerActivity {
public static final int DIALOG_SHORT_WAIT = 0;
public static final String TAG = FileDetailActivity.class.getSimpleName();
+ public static final String EXTRA_MODE = "MODE";
+ public static final int MODE_DETAILS = 0;
+ public static final int MODE_PREVIEW = 1;
+
+ public static final String KEY_WAITING_TO_PREVIEW = "WAITING_TO_PREVIEW";
+
private boolean mConfigurationChangedToLandscape = false;
private FileDownloaderBinder mDownloaderBinder = null;
private ServiceConnection mDownloadConnection, mUploadConnection = null;
private FileUploaderBinder mUploaderBinder = null;
+ private boolean mWaitingToPreview;
+
+ private OCFile mFile;
+ private Account mAccount;
+ private FileDataStorageManager mStorageManager;
+ private DownloadFinishReceiver mDownloadFinishReceiver;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ mFile = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_FILE);
+ mAccount = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_ACCOUNT);
+ mStorageManager = new FileDataStorageManager(mAccount, getContentResolver());
+
// check if configuration changed to large-land ; for a tablet being changed from portrait to landscape when in FileDetailActivity
Configuration conf = getResources().getConfiguration();
mConfigurationChangedToLandscape = (conf.orientation == Configuration.ORIENTATION_LANDSCAPE &&
);
if (!mConfigurationChangedToLandscape) {
- mDownloadConnection = new DetailsServiceConnection();
- bindService(new Intent(this, FileDownloader.class), mDownloadConnection, Context.BIND_AUTO_CREATE);
- mUploadConnection = new DetailsServiceConnection();
- bindService(new Intent(this, FileUploader.class), mUploadConnection, Context.BIND_AUTO_CREATE);
-
setContentView(R.layout.file_activity_details);
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
- OCFile file = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_FILE);
- Account account = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_ACCOUNT);
- FileDetailFragment mFileDetail = new FileDetailFragment(file, account);
-
- FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
- ft.replace(R.id.fragment, mFileDetail, FileDetailFragment.FTAG);
- ft.commit();
+ if (savedInstanceState == null) {
+ mWaitingToPreview = false;
+ createChildFragment();
+ } else {
+ mWaitingToPreview = savedInstanceState.getBoolean(KEY_WAITING_TO_PREVIEW);
+ }
+
+ mDownloadConnection = new DetailsServiceConnection();
+ bindService(new Intent(this, FileDownloader.class), mDownloadConnection, Context.BIND_AUTO_CREATE);
+ mUploadConnection = new DetailsServiceConnection();
+ bindService(new Intent(this, FileUploader.class), mUploadConnection, Context.BIND_AUTO_CREATE);
+
} else {
- backToDisplayActivity(); // the 'back' won't be effective until this.onStart() and this.onResume() are completed;
+ backToDisplayActivity(false); // the 'back' won't be effective until this.onStart() and this.onResume() are completed;
}
+ }
+
+ /**
+ * Creates the proper fragment depending upon the state of the handled {@link OCFile} and
+ * the requested {@link Intent}.
+ */
+ private void createChildFragment() {
+ int mode = getIntent().getIntExtra(EXTRA_MODE, MODE_PREVIEW);
+ Fragment newFragment = null;
+ if (PreviewMediaFragment.canBePreviewed(mFile) && mode == MODE_PREVIEW) {
+ if (mFile.isDown()) {
+ newFragment = new PreviewMediaFragment(mFile, mAccount);
+
+ } else {
+ newFragment = new FileDetailFragment(mFile, mAccount);
+ mWaitingToPreview = true;
+ }
+
+ } else {
+ newFragment = new FileDetailFragment(mFile, mAccount);
+ }
+ FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
+ ft.replace(R.id.fragment, newFragment, FileDetailFragment.FTAG);
+ ft.commit();
+ }
+
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putBoolean(KEY_WAITING_TO_PREVIEW, mWaitingToPreview);
+ }
+
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ if (mDownloadFinishReceiver != null) {
+ unregisterReceiver(mDownloadFinishReceiver);
+ mDownloadFinishReceiver = null;
+ }
+ }
+
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (!mConfigurationChangedToLandscape) {
+ // TODO this is probably unnecessary
+ Fragment fragment = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
+ if (fragment != null && fragment instanceof FileDetailFragment) {
+ ((FileDetailFragment) fragment).updateFileDetails(false, false);
+ }
+ }
+ // Listen for download messages
+ IntentFilter downloadIntentFilter = new IntentFilter(FileDownloader.DOWNLOAD_ADDED_MESSAGE);
+ downloadIntentFilter.addAction(FileDownloader.DOWNLOAD_FINISH_MESSAGE);
+ mDownloadFinishReceiver = new DownloadFinishReceiver();
+ registerReceiver(mDownloadFinishReceiver, downloadIntentFilter);
}
@Override
public void onServiceConnected(ComponentName component, IBinder service) {
+
if (component.equals(new ComponentName(FileDetailActivity.this, FileDownloader.class))) {
Log_OC.d(TAG, "Download service connected");
mDownloaderBinder = (FileDownloaderBinder) service;
+ if (mWaitingToPreview) {
+ requestForDownload();
+ }
+
} else if (component.equals(new ComponentName(FileDetailActivity.this, FileUploader.class))) {
Log_OC.d(TAG, "Upload service connected");
mUploaderBinder = (FileUploaderBinder) service;
} else {
return;
}
- FileDetailFragment fragment = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
- if (fragment != null)
- fragment.updateFileDetails(false); // let the fragment gets the mDownloadBinder through getDownloadBinder() (see FileDetailFragment#updateFileDetais())
+
+ Fragment fragment = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
+ FileDetailFragment detailsFragment = (fragment instanceof FileDetailFragment) ? (FileDetailFragment) fragment : null;
+ if (detailsFragment != null) {
+ detailsFragment.listenForTransferProgress();
+ detailsFragment.updateFileDetails(mWaitingToPreview, false); // let the fragment gets the mDownloadBinder through getDownloadBinder() (see FileDetailFragment#updateFileDetais())
+ }
}
@Override
}
};
-
+
@Override
public void onDestroy() {
super.onDestroy();
switch(item.getItemId()){
case android.R.id.home:
- backToDisplayActivity();
+ backToDisplayActivity(true);
returnValue = true;
break;
default:
- returnValue = super.onOptionsItemSelected(item);
+ returnValue = super.onOptionsItemSelected(item);
}
return returnValue;
}
-
-
- @Override
- protected void onResume() {
-
- super.onResume();
- if (!mConfigurationChangedToLandscape) {
- FileDetailFragment fragment = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
- fragment.updateFileDetails(false);
- }
- }
-
-
- private void backToDisplayActivity() {
+ private void backToDisplayActivity(boolean moveToParent) {
Intent intent = new Intent(this, FileDisplayActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- intent.putExtra(FileDetailFragment.EXTRA_FILE, getIntent().getParcelableExtra(FileDetailFragment.EXTRA_FILE));
- intent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, getIntent().getParcelableExtra(FileDetailFragment.EXTRA_ACCOUNT));
+ OCFile targetFile = null;
+ if (mFile != null) {
+ targetFile = moveToParent ? mStorageManager.getFileById(mFile.getParentId()) : mFile;
+ }
+ intent.putExtra(FileDetailFragment.EXTRA_FILE, targetFile);
+ intent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, mAccount);
startActivity(intent);
finish();
}
return dialog;
}
-
+
/**
* {@inheritDoc}
*/
public FileUploaderBinder getFileUploaderBinder() {
return mUploaderBinder;
}
+
+
+ @Override
+ public void showFragmentWithDetails(OCFile file) {
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ transaction.replace(R.id.fragment, new FileDetailFragment(file, mAccount), FileDetailFragment.FTAG);
+ transaction.commit();
+ }
+
+
+ private void requestForDownload() {
+ if (!mDownloaderBinder.isDownloading(mAccount, mFile)) {
+ Intent i = new Intent(this, FileDownloader.class);
+ i.putExtra(FileDownloader.EXTRA_ACCOUNT, mAccount);
+ i.putExtra(FileDownloader.EXTRA_FILE, mFile);
+ startService(i);
+ }
+ }
+
+ /**
+ * Class waiting for broadcast events from the {@link FielDownloader} service.
+ *
+ * Updates the UI when a download is started or finished, provided that it is relevant for the
+ * current file.
+ */
+ private class DownloadFinishReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ boolean sameAccount = isSameAccount(context, intent);
+ String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
+ boolean samePath = (mFile != null && mFile.getRemotePath().equals(downloadedRemotePath));
+
+ if (sameAccount && samePath) {
+ updateChildFragment(intent.getAction(), downloadedRemotePath, intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false));
+ }
+
+ removeStickyBroadcast(intent);
+ }
+
+ private boolean isSameAccount(Context context, Intent intent) {
+ String accountName = intent.getStringExtra(FileDownloader.ACCOUNT_NAME);
+ return (accountName != null && accountName.equals(AccountUtils.getCurrentOwnCloudAccount(context).name));
+ }
+ }
+
+
+ public void updateChildFragment(String downloadEvent, String downloadedRemotePath, boolean success) {
+ Fragment fragment = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
+ if (fragment != null && fragment instanceof FileDetailFragment) {
+ FileDetailFragment detailsFragment = (FileDetailFragment) fragment;
+ OCFile fileInFragment = detailsFragment.getFile();
+ if (fileInFragment != null && !downloadedRemotePath.equals(fileInFragment.getRemotePath())) {
+ // this never should happen; fileInFragment should be always equals to mFile, that was compared to downloadedRemotePath in DownloadReceiver
+ mWaitingToPreview = false;
+
+ } else if (downloadEvent.equals(FileDownloader.DOWNLOAD_ADDED_MESSAGE)) {
+ // grants that the progress bar is updated
+ detailsFragment.listenForTransferProgress();
+ detailsFragment.updateFileDetails(true, false);
+
+ } else if (downloadEvent.equals(FileDownloader.DOWNLOAD_FINISH_MESSAGE)) {
+ // refresh the details fragment
+ if (success && mWaitingToPreview) {
+ mFile = mStorageManager.getFileById(mFile.getFileId()); // update the file from database, for the local storage path
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ transaction.replace(R.id.fragment, new PreviewMediaFragment(mFile, mAccount), FileDetailFragment.FTAG);
+ transaction.commit();
+ mWaitingToPreview = false;
+
+ } else {
+ detailsFragment.updateFileDetails(false, (success));
+ // TODO error message if !success ¿?
+ }
+ }
+ } // TODO else if (fragment != null && fragment )
+
+ }
+
}
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
+ * 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,
import android.accounts.Account;
import android.app.AlertDialog;
+import android.app.ProgressDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
-import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.provider.MediaStore;
+import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.View;
import com.owncloud.android.operations.OnRemoteOperationListener;
import com.owncloud.android.operations.RemoteOperation;
import com.owncloud.android.operations.RemoteOperationResult;
-import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.operations.RemoveFileOperation;
import com.owncloud.android.operations.RenameFileOperation;
import com.owncloud.android.operations.SynchronizeFileOperation;
+import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.syncadapter.FileSyncService;
import com.owncloud.android.ui.dialog.ChangelogDialog;
+import com.owncloud.android.ui.dialog.EditNameDialog;
import com.owncloud.android.ui.dialog.SslValidatorDialog;
+import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;
import com.owncloud.android.ui.dialog.SslValidatorDialog.OnSslValidatorListener;
import com.owncloud.android.ui.fragment.FileDetailFragment;
+import com.owncloud.android.ui.fragment.FileFragment;
import com.owncloud.android.ui.fragment.OCFileListFragment;
+import com.owncloud.android.ui.preview.PreviewImageActivity;
+import com.owncloud.android.ui.preview.PreviewImageFragment;
+import com.owncloud.android.ui.preview.PreviewMediaFragment;
+import com.owncloud.android.R;
import eu.alefzero.webdav.WebdavClient;
/**
* Displays, what files the user has available in his ownCloud.
*
* @author Bartek Przybylski
- *
+ * @author David A. Velasco
*/
-public class FileDisplayActivity extends SherlockFragmentActivity implements OCFileListFragment.ContainerActivity,
- FileDetailFragment.ContainerActivity, OnNavigationListener, OnSslValidatorListener, OnRemoteOperationListener {
-
+public class FileDisplayActivity extends SherlockFragmentActivity implements
+ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNavigationListener, OnSslValidatorListener, OnRemoteOperationListener, EditNameDialogListener {
+
private ArrayAdapter<String> mDirectories;
private OCFile mCurrentDir = null;
private OCFile mCurrentFile = null;
private OCFileListFragment mFileList;
private boolean mDualPane;
+ private boolean mBackFromCreatingFirstAccount;
private static final int DIALOG_SETUP_ACCOUNT = 0;
private static final int DIALOG_CREATE_DIR = 1;
private static final int ACTION_SELECT_CONTENT_FROM_APPS = 1;
private static final int ACTION_SELECT_MULTIPLE_FILES = 2;
- private static final int ACTION_SELECT_FAILED_INSTANT_UPLOAD = 2;
-
+
private static final String TAG = "FileDisplayActivity";
+ private static int[] mMenuIdentifiersToPatch = {R.id.action_about_app};
+ private OCFile mWaitingToPreview;
+ private Handler mHandler;
+
@Override
public void onCreate(Bundle savedInstanceState) {
Log_OC.d(getClass().toString(), "onCreate() start");
super.onCreate(savedInstanceState);
/// Load of parameters from received intent
- mCurrentDir = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_FILE); // no check necessary, mCurrenDir == null if the parameter is not in the intent
Account account = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_ACCOUNT);
- if (account != null)
- AccountUtils.setCurrentOwnCloudAccount(this, account.name);
+ if (account != null && AccountUtils.setCurrentOwnCloudAccount(this, account.name)) {
+ mCurrentDir = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_FILE);
+ }
/// Load of saved instance state: keep this always before initDataFromCurrentAccount()
if(savedInstanceState != null) {
// TODO - test if savedInstanceState should take precedence over file in the intent ALWAYS (now), NEVER, or SOME TIMES
mCurrentDir = savedInstanceState.getParcelable(FileDetailFragment.EXTRA_FILE);
+ mWaitingToPreview = (OCFile) savedInstanceState.getParcelable(FileDetailActivity.KEY_WAITING_TO_PREVIEW);
+
+ } else {
+ mWaitingToPreview = null;
}
if (!AccountUtils.accountsAreSetup(this)) {
/// no account available: FORCE ACCOUNT CREATION
mStorageManager = null;
createFirstAccount();
-
- } else { // / at least an account is available
-
- initDataFromCurrentAccount(); // it checks mCurrentDir and
- // mCurrentFile with the current
- // account
-
+
+ } else { /// at least an account is available
+
+ initDataFromCurrentAccount(); // it checks mCurrentDir and mCurrentFile with the current account
+
}
mUploadConnection = new ListServiceConnection();
// Drop-down navigation
mDirectories = new CustomArrayAdapter<String>(this, R.layout.sherlock_spinner_dropdown_item);
OCFile currFile = mCurrentDir;
- while (currFile != null && currFile.getFileName() != OCFile.PATH_SEPARATOR) {
+ while(mStorageManager != null && currFile != null && currFile.getFileName() != OCFile.PATH_SEPARATOR) {
mDirectories.add(currFile.getFileName());
currFile = mStorageManager.getFileById(currFile.getParentId());
}
mFileList = (OCFileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList);
mDualPane = (findViewById(R.id.file_details_container) != null);
if (mDualPane) {
- initFileDetailsInDualPane();
+ if (savedInstanceState == null) initFileDetailsInDualPane();
+ } else {
+ // quick patchES to fix problem in turn from landscape to portrait, when a file is selected in the right pane
+ // TODO serious refactorization in activities and fragments providing file browsing and handling
+ if (mCurrentFile != null) {
+ onFileClick(mCurrentFile);
+ mCurrentFile = null;
+ }
+ Fragment rightPanel = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
+ if (rightPanel != null) {
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ transaction.remove(rightPanel);
+ transaction.commit();
+ }
}
// Action bar setup
// show changelog, if needed
- showChangeLog();
+ //showChangeLog();
+ mBackFromCreatingFirstAccount = false;
Log_OC.d(getClass().toString(), "onCreate() end");
}
startActivity(intent); // the new activity won't be created until this.onStart() and this.onResume() are finished;
}
-
+
/**
* Load of state dependent of the existence of an ownCloud account
*/
if (mDualPane && getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG) == null) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (mCurrentFile != null) {
- transaction.replace(R.id.file_details_container,
- new FileDetailFragment(mCurrentFile, AccountUtils.getCurrentOwnCloudAccount(this)),
- FileDetailFragment.FTAG); // empty FileDetailFragment
+ if (PreviewMediaFragment.canBePreviewed(mCurrentFile)) {
+ if (mCurrentFile.isDown()) {
+ transaction.replace(R.id.file_details_container, new PreviewMediaFragment(mCurrentFile, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);
+ } else {
+ transaction.replace(R.id.file_details_container, new FileDetailFragment(mCurrentFile, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);
+ mWaitingToPreview = mCurrentFile;
+ }
+ } else {
+ transaction.replace(R.id.file_details_container, new FileDetailFragment(mCurrentFile, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);
+ }
mCurrentFile = null;
+
} else {
- transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null),
- FileDetailFragment.FTAG); // empty FileDetailFragment
+ transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null), FileDetailFragment.FTAG); // empty FileDetailFragment
}
transaction.commit();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getSherlock().getMenuInflater();
- inflater.inflate(R.menu.menu, menu);
+ inflater.inflate(R.menu.main_menu, menu);
+
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
boolean retval = true;
switch (item.getItemId()) {
- case R.id.createDirectoryItem: {
- showDialog(DIALOG_CREATE_DIR);
- break;
- }
- case R.id.startSync: {
- startSynchronization();
- break;
- }
- case R.id.action_upload: {
- showDialog(DIALOG_CHOOSE_UPLOAD_SOURCE);
- break;
- }
- case R.id.action_settings: {
- Intent settingsIntent = new Intent(this, Preferences.class);
- startActivity(settingsIntent);
- break;
- }
- case android.R.id.home: {
- if (mCurrentDir != null && mCurrentDir.getParentId() != 0) {
- onBackPressed();
+ case R.id.action_create_dir: {
+ EditNameDialog dialog = EditNameDialog.newInstance(getString(R.string.uploader_info_dirname), "", this);
+ dialog.show(getSupportFragmentManager(), "createdirdialog");
+ break;
}
- break;
- }
- default:
- retval = super.onOptionsItemSelected(item);
+ case R.id.action_sync_account: {
+ startSynchronization();
+ break;
+ }
+ case R.id.action_upload: {
+ showDialog(DIALOG_CHOOSE_UPLOAD_SOURCE);
+ break;
+ }
+ case R.id.action_settings: {
+ Intent settingsIntent = new Intent(this, Preferences.class);
+ startActivity(settingsIntent);
+ break;
+ }
+ case android.R.id.home: {
+ if(mCurrentDir != null && mCurrentDir.getParentId() != 0){
+ onBackPressed();
+ }
+ break;
+ }
+ default:
+ retval = super.onOptionsItemSelected(item);
}
return retval;
}
* Called, when the user selected something for uploading
*/
public void onActivityResult(int requestCode, int resultCode, Intent data) {
-
- if (requestCode == ACTION_SELECT_CONTENT_FROM_APPS
- && (resultCode == RESULT_OK || resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE)) {
+
+ if (requestCode == ACTION_SELECT_CONTENT_FROM_APPS && (resultCode == RESULT_OK || resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE)) {
requestSimpleUpload(data, resultCode);
-
- } else if (requestCode == ACTION_SELECT_MULTIPLE_FILES
- && (resultCode == RESULT_OK || resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE)) {
+
+ } else if (requestCode == ACTION_SELECT_MULTIPLE_FILES && (resultCode == RESULT_OK || resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE)) {
requestMultipleUpload(data, resultCode);
}
}
if (!remotePathBase.endsWith(OCFile.PATH_SEPARATOR))
remotePathBase += OCFile.PATH_SEPARATOR;
- for (int j = 0; j < remotePaths.length; j++) {
+ for (int j = 0; j< remotePaths.length; j++) {
remotePaths[j] = remotePathBase + (new File(filePaths[j])).getName();
}
}
Intent i = new Intent(this, FileUploader.class);
- i.putExtra(FileUploader.KEY_ACCOUNT, AccountUtils.getCurrentOwnCloudAccount(this));
+ i.putExtra(FileUploader.KEY_ACCOUNT,
+ AccountUtils.getCurrentOwnCloudAccount(this));
String remotepath = new String();
for (int j = mDirectories.getCount() - 2; j >= 0; --j) {
remotepath += OCFile.PATH_SEPARATOR + mDirectories.getItem(j);
mCurrentDir = mFileList.getCurrentFile();
if (mDualPane) {
- // Resets the FileDetailsFragment on Tablets so that it always
- // displays
- FileDetailFragment fileDetails = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(
- FileDetailFragment.FTAG);
- if (fileDetails != null && !fileDetails.isEmpty()) {
+ // Resets the FileDetailsFragment on Tablets so that it always displays
+ Fragment fileFragment = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
+ if (fileFragment != null && (fileFragment instanceof PreviewMediaFragment || !((FileDetailFragment) fileFragment).isEmpty())) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
- transaction.remove(fileDetails);
- transaction.add(R.id.file_details_container, new FileDetailFragment(null, null),
- FileDetailFragment.FTAG);
+ transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null), FileDetailFragment.FTAG); // empty FileDetailFragment
transaction.commit();
}
}
-
- if (mCurrentDir.getParentId() == 0) {
- ActionBar actionBar = getSupportActionBar();
+
+ if(mCurrentDir.getParentId() == 0){
+ ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(false);
- }
+ }
}
@Override
super.onSaveInstanceState(outState);
outState.putParcelable(FileDetailFragment.EXTRA_FILE, mCurrentDir);
if (mDualPane) {
- FileDetailFragment fragment = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
+ FileFragment fragment = (FileFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
if (fragment != null) {
- OCFile file = fragment.getDisplayedFile();
+ OCFile file = fragment.getFile();
if (file != null) {
outState.putParcelable(FileDetailFragment.EXTRA_FILE, file);
}
}
}
+ outState.putParcelable(FileDetailActivity.KEY_WAITING_TO_PREVIEW, mWaitingToPreview);
Log_OC.d(getClass().toString(), "onSaveInstanceState() end");
}
+
@Override
protected void onResume() {
Log_OC.d(getClass().toString(), "onResume() start");
if (mDualPane) {
initFileDetailsInDualPane();
}
+ mBackFromCreatingFirstAccount = true;
}
// Listen for sync messages
registerReceiver(mUploadFinishReceiver, uploadIntentFilter);
// Listen for download messages
- IntentFilter downloadIntentFilter = new IntentFilter(FileDownloader.DOWNLOAD_FINISH_MESSAGE);
+ IntentFilter downloadIntentFilter = new IntentFilter(FileDownloader.DOWNLOAD_ADDED_MESSAGE);
+ downloadIntentFilter.addAction(FileDownloader.DOWNLOAD_FINISH_MESSAGE);
mDownloadFinishReceiver = new DownloadFinishReceiver();
registerReceiver(mDownloadFinishReceiver, downloadIntentFilter);
builder.setTitle(R.string.uploader_info_dirname);
int typed_color = getResources().getColor(R.color.setup_text_typed);
dirNameInput.setTextColor(typed_color);
- builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- String directoryName = dirNameInput.getText().toString();
- if (directoryName.trim().length() == 0) {
- dialog.cancel();
- return;
- }
-
- // Figure out the path where the dir needs to be created
- String path;
- if (mCurrentDir == null) {
- // this is just a patch; we should ensure that
- // mCurrentDir never is null
- if (!mStorageManager.fileExists(OCFile.PATH_SEPARATOR)) {
- OCFile file = new OCFile(OCFile.PATH_SEPARATOR);
- mStorageManager.saveFile(file);
+ builder.setPositiveButton(android.R.string.ok,
+ new OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ String directoryName = dirNameInput.getText().toString();
+ if (directoryName.trim().length() == 0) {
+ dialog.cancel();
+ return;
+ }
+
+ // Figure out the path where the dir needs to be created
+ String path;
+ if (mCurrentDir == null) {
+ // this is just a patch; we should ensure that mCurrentDir never is null
+ if (!mStorageManager.fileExists(OCFile.PATH_SEPARATOR)) {
+ OCFile file = new OCFile(OCFile.PATH_SEPARATOR);
+ mStorageManager.saveFile(file);
+ }
+ mCurrentDir = mStorageManager.getFileByPath(OCFile.PATH_SEPARATOR);
+ }
+ path = FileDisplayActivity.this.mCurrentDir.getRemotePath();
+
+ // Create directory
+ path += directoryName + OCFile.PATH_SEPARATOR;
+ Thread thread = new Thread(new DirectoryCreator(path, AccountUtils.getCurrentOwnCloudAccount(FileDisplayActivity.this), new Handler()));
+ thread.start();
+
+ dialog.dismiss();
+
+ showDialog(DIALOG_SHORT_WAIT);
}
- mCurrentDir = mStorageManager.getFileByPath(OCFile.PATH_SEPARATOR);
- }
- path = FileDisplayActivity.this.mCurrentDir.getRemotePath();
-
- // Create directory
- path += directoryName + OCFile.PATH_SEPARATOR;
- Thread thread = new Thread(new DirectoryCreator(path, AccountUtils
- .getCurrentOwnCloudAccount(FileDisplayActivity.this), new Handler()));
- thread.start();
-
- dialog.dismiss();
-
- showDialog(DIALOG_SHORT_WAIT);
- }
- });
- builder.setNegativeButton(R.string.common_cancel, new OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- dialog.cancel();
- }
- });
+ });
+ builder.setNegativeButton(R.string.common_cancel,
+ new OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.cancel();
+ }
+ });
dialog = builder.create();
break;
}
case DIALOG_SHORT_WAIT: {
ProgressDialog working_dialog = new ProgressDialog(this);
- working_dialog.setMessage(getResources().getString(R.string.wait_a_moment));
+ working_dialog.setMessage(getResources().getString(
+ R.string.wait_a_moment));
working_dialog.setIndeterminate(true);
working_dialog.setCancelable(false);
dialog = working_dialog;
break;
}
case DIALOG_CHOOSE_UPLOAD_SOURCE: {
- final String[] items = { getString(R.string.actionbar_upload_files),
- getString(R.string.actionbar_upload_from_apps), getString(R.string.actionbar_failed_instant_upload) };
+
+ String[] items = null;
+
+ String[] allTheItems = { getString(R.string.actionbar_upload_files),
+ getString(R.string.actionbar_upload_from_apps),
+ getString(R.string.actionbar_failed_instant_upload) };
+
+ String[] commonItems = { getString(R.string.actionbar_upload_files),
+ getString(R.string.actionbar_upload_from_apps) };
+
+ if (InstantUploadActivity.IS_ENABLED)
+ items = allTheItems;
+ else
+ items = commonItems;
+
builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.actionbar_upload);
builder.setItems(items, new DialogInterface.OnClickListener() {
action = action.setType("*/*").addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(Intent.createChooser(action, getString(R.string.upload_chooser_title)),
ACTION_SELECT_CONTENT_FROM_APPS);
- } else if (item == 2) {
+ } else if (item == 2 && InstantUploadActivity.IS_ENABLED) {
Account account = AccountUtils.getCurrentOwnCloudAccount(FileDisplayActivity.this);
Intent action = new Intent(FileDisplayActivity.this, InstantUploadActivity.class);
action.putExtra(FileUploader.KEY_ACCOUNT, account);
builder.setMessage(getResources().getString(R.string.ssl_validator_not_saved));
builder.setCancelable(false);
builder.setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- };
- });
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ };
+ });
dialog = builder.create();
break;
}
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
if (cursor != null) {
- int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
+ int column_index = cursor
+ .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
- }
+ }
return null;
}
public void run() {
dismissDialog(DIALOG_SHORT_WAIT);
try {
- Toast msg = Toast.makeText(FileDisplayActivity.this, R.string.create_dir_fail_msg,
- Toast.LENGTH_LONG);
+ Toast msg = Toast.makeText(FileDisplayActivity.this, R.string.create_dir_fail_msg, Toast.LENGTH_LONG);
msg.show();
} catch (NotFoundException e) {
public View getView(int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);
-
- ((TextView) v).setTextColor(getResources().getColorStateList(android.R.color.white));
+
+ ((TextView) v).setTextColor(getResources().getColorStateList(
+ android.R.color.white));
return v;
}
-
- public View getDropDownView(int position, View convertView, ViewGroup parent) {
+
+ public View getDropDownView(int position, View convertView,
+ ViewGroup parent) {
View v = super.getDropDownView(position, convertView, parent);
-
- ((TextView) v).setTextColor(getResources().getColorStateList(android.R.color.white));
-
+
+ ((TextView) v).setTextColor(getResources().getColorStateList(
+ android.R.color.white));
+
return v;
}
Log_OC.d("FileDisplay", "sync of account " + accountName + " is in_progress: " + inProgress);
- if (accountName.equals(AccountUtils.getCurrentOwnCloudAccount(context).name)) {
-
- String synchFolderRemotePath = intent.getStringExtra(FileSyncService.SYNC_FOLDER_REMOTE_PATH);
-
+ if (accountName.equals(AccountUtils.getCurrentOwnCloudAccount(context).name)) {
+
+ String synchFolderRemotePath = intent.getStringExtra(FileSyncService.SYNC_FOLDER_REMOTE_PATH);
+
boolean fillBlankRoot = false;
if (mCurrentDir == null) {
mCurrentDir = mStorageManager.getFileByPath("/");
fillBlankRoot = (mCurrentDir != null);
}
- if ((synchFolderRemotePath != null && mCurrentDir != null && (mCurrentDir.getRemotePath()
- .equals(synchFolderRemotePath))) || fillBlankRoot) {
- if (!fillBlankRoot)
+ if ((synchFolderRemotePath != null && mCurrentDir != null && (mCurrentDir.getRemotePath().equals(synchFolderRemotePath)))
+ || fillBlankRoot ) {
+ if (!fillBlankRoot)
mCurrentDir = getStorageManager().getFileByPath(synchFolderRemotePath);
OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager()
.findFragmentById(R.id.fileList);
}
setSupportProgressBarIndeterminateVisibility(inProgress);
+ if (mBackFromCreatingFirstAccount) {
+ // awful patch to fix problem with visibility of progress circle with the first refresh of the first account
+ // TODO - kill this Activity when the first account has to be created instead of stack the account creation on it
+ getSupportActionBar().hide();
+ getSupportActionBar().show();
+ mBackFromCreatingFirstAccount = false;
+ }
removeStickyBroadcast(intent);
}
-
- RemoteOperationResult synchResult = (RemoteOperationResult) intent
- .getSerializableExtra(FileSyncService.SYNC_RESULT);
+
+ RemoteOperationResult synchResult = (RemoteOperationResult)intent.getSerializableExtra(FileSyncService.SYNC_RESULT);
if (synchResult != null) {
if (synchResult.getCode().equals(RemoteOperationResult.ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED)) {
mLastSslUntrustedServerResult = synchResult;
- showDialog(DIALOG_SSL_VALIDATOR);
+ showDialog(DIALOG_SSL_VALIDATOR);
}
}
}
String uploadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
String accountName = intent.getStringExtra(FileUploader.ACCOUNT_NAME);
boolean sameAccount = accountName.equals(AccountUtils.getCurrentOwnCloudAccount(context).name);
- boolean isDescendant = (mCurrentDir != null) && (uploadedRemotePath != null)
- && (uploadedRemotePath.startsWith(mCurrentDir.getRemotePath()));
+ boolean isDescendant = (mCurrentDir != null) && (uploadedRemotePath != null) && (uploadedRemotePath.startsWith(mCurrentDir.getRemotePath()));
if (sameAccount && isDescendant) {
- OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager()
- .findFragmentById(R.id.fileList);
- if (fileListFragment != null) {
+ OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList);
+ if (fileListFragment != null) {
fileListFragment.listDirectory();
}
}
/**
- * Once the file download has finished -> update view
+ * Class waiting for broadcast events from the {@link FielDownloader} service.
+ *
+ * Updates the UI when a download is started or finished, provided that it is relevant for the
+ * current folder.
*/
private class DownloadFinishReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
+ boolean sameAccount = isSameAccount(context, intent);
String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
- String accountName = intent.getStringExtra(FileDownloader.ACCOUNT_NAME);
- boolean sameAccount = accountName.equals(AccountUtils.getCurrentOwnCloudAccount(context).name);
- boolean isDescendant = (mCurrentDir != null) && (downloadedRemotePath != null)
- && (downloadedRemotePath.startsWith(mCurrentDir.getRemotePath()));
+ boolean isDescendant = isDescendant(downloadedRemotePath);
+
if (sameAccount && isDescendant) {
- OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager()
- .findFragmentById(R.id.fileList);
- if (fileListFragment != null) {
- fileListFragment.listDirectory();
+ updateLeftPanel();
+ if (mDualPane) {
+ updateRightPanel(intent.getAction(), downloadedRemotePath, intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false));
}
}
+
+ removeStickyBroadcast(intent);
+ }
+
+ private boolean isDescendant(String downloadedRemotePath) {
+ return (mCurrentDir != null && downloadedRemotePath != null && downloadedRemotePath.startsWith(mCurrentDir.getRemotePath()));
+ }
+
+ private boolean isSameAccount(Context context, Intent intent) {
+ String accountName = intent.getStringExtra(FileDownloader.ACCOUNT_NAME);
+ return (accountName != null && accountName.equals(AccountUtils.getCurrentOwnCloudAccount(context).name));
}
}
-
-
+ protected void updateLeftPanel() {
+ OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList);
+ if (fileListFragment != null) {
+ fileListFragment.listDirectory();
+ }
+ }
+
+ protected void updateRightPanel(String downloadEvent, String downloadedRemotePath, boolean success) {
+ Fragment fragment = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
+ boolean waitedPreview = (mWaitingToPreview != null && mWaitingToPreview.getRemotePath().equals(downloadedRemotePath));
+ if (fragment != null && fragment instanceof FileDetailFragment) {
+ FileDetailFragment detailsFragment = (FileDetailFragment) fragment;
+ OCFile fileInFragment = detailsFragment.getFile();
+ if (fileInFragment != null && !downloadedRemotePath.equals(fileInFragment.getRemotePath())) {
+ // the user browsed to other file ; forget the automatic preview
+ mWaitingToPreview = null;
+
+ } else if (downloadEvent.equals(FileDownloader.DOWNLOAD_ADDED_MESSAGE)) {
+ // grant that the right panel updates the progress bar
+ detailsFragment.listenForTransferProgress();
+ detailsFragment.updateFileDetails(true, false);
+
+ } else if (downloadEvent.equals(FileDownloader.DOWNLOAD_FINISH_MESSAGE)) {
+ // update the right panel
+ if (success && waitedPreview) {
+ mWaitingToPreview = mStorageManager.getFileById(mWaitingToPreview.getFileId()); // update the file from database, for the local storage path
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ transaction.replace(R.id.file_details_container, new PreviewMediaFragment(mWaitingToPreview, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);
+ transaction.commit();
+ mWaitingToPreview = null;
+
+ } else {
+ detailsFragment.updateFileDetails(false, (success));
+ }
+ }
+ }
+ }
+
+
/**
* {@inheritDoc}
*/
return mStorageManager;
}
-
+
/**
* {@inheritDoc}
*/
if (mDualPane) {
// Resets the FileDetailsFragment on Tablets so that it always displays
- FileDetailFragment fileDetails = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
- if (fileDetails != null && !fileDetails.isEmpty()) {
+ Fragment fileFragment = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
+ if (fileFragment != null && (fileFragment instanceof PreviewMediaFragment || !((FileDetailFragment) fileFragment).isEmpty())) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
- transaction.remove(fileDetails);
- transaction.add(R.id.file_details_container, new FileDetailFragment(null, null),
- FileDetailFragment.FTAG);
+ transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null), FileDetailFragment.FTAG); // empty FileDetailFragment
transaction.commit();
}
}
*/
@Override
public void onFileClick(OCFile file) {
-
- // If we are on a large device -> update fragment
+ if (file != null && PreviewImageFragment.canBePreviewed(file)) {
+ // preview image - it handles the download, if needed
+ startPreviewImage(file);
+
+ } else if (file != null && PreviewMediaFragment.canBePreviewed(file)) {
+ if (file.isDown()) {
+ // general preview
+ startMediaPreview(file);
+
+ } else {
+ // automatic download, preview on finish
+ startDownloadForPreview(file);
+
+ }
+ } else {
+ // details view
+ startDetails(file);
+ }
+ }
+
+ private void startPreviewImage(OCFile file) {
+ Intent showDetailsIntent = new Intent(this, PreviewImageActivity.class);
+ showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, file);
+ showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, AccountUtils.getCurrentOwnCloudAccount(this));
+ startActivity(showDetailsIntent);
+ }
+
+ private void startMediaPreview(OCFile file) {
if (mDualPane) {
- // buttons in the details view are problematic when trying to reuse an existing fragment; create always a new one solves some of them, BUT no all; downloads are 'dangerous'
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
- transaction
- .replace(R.id.file_details_container,
- new FileDetailFragment(file, AccountUtils.getCurrentOwnCloudAccount(this)),
- FileDetailFragment.FTAG);
- transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
+ transaction.replace(R.id.file_details_container, new PreviewMediaFragment(file, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);
transaction.commit();
-
- } else { // small or medium screen device -> new Activity
+
+ } else {
Intent showDetailsIntent = new Intent(this, FileDetailActivity.class);
showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, file);
showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, AccountUtils.getCurrentOwnCloudAccount(this));
}
}
+ private void startDownloadForPreview(OCFile file) {
+ if (mDualPane) {
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ transaction.replace(R.id.file_details_container, new FileDetailFragment(file, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);
+ transaction.commit();
+ mWaitingToPreview = file;
+ requestForDownload();
+
+ } else {
+ Intent showDetailsIntent = new Intent(this, FileDetailActivity.class);
+ showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, file);
+ showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, AccountUtils.getCurrentOwnCloudAccount(this));
+ startActivity(showDetailsIntent);
+ }
+ }
+
+ private void startDetails(OCFile file) {
+ if (mDualPane && !file.isImage()) {
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ transaction.replace(R.id.file_details_container, new FileDetailFragment(file, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);
+ transaction.commit();
+ } else {
+ Intent showDetailsIntent = new Intent(this, FileDetailActivity.class);
+ showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, file);
+ showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, AccountUtils.getCurrentOwnCloudAccount(this));
+ startActivity(showDetailsIntent);
+ }
+ }
+
+
/**
* {@inheritDoc}
*/
*/
@Override
public void onFileStateChanged() {
- OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager().findFragmentById(
- R.id.fileList);
- if (fileListFragment != null) {
+ OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList);
+ if (fileListFragment != null) {
fileListFragment.listDirectory();
}
}
if (component.equals(new ComponentName(FileDisplayActivity.this, FileDownloader.class))) {
Log_OC.d(TAG, "Download service connected");
mDownloaderBinder = (FileDownloaderBinder) service;
+ if (mWaitingToPreview != null) {
+ requestForDownload();
+ }
+
} else if (component.equals(new ComponentName(FileDisplayActivity.this, FileUploader.class))) {
Log_OC.d(TAG, "Upload service connected");
mUploaderBinder = (FileUploaderBinder) service;
if (mFileList != null)
mFileList.listDirectory();
if (mDualPane) {
- FileDetailFragment fragment = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(
- FileDetailFragment.FTAG);
- if (fragment != null)
- fragment.updateFileDetails(false);
+ Fragment fragment = getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
+ if (fragment != null && fragment instanceof FileDetailFragment) {
+ FileDetailFragment detailFragment = (FileDetailFragment)fragment;
+ detailFragment.listenForTransferProgress();
+ detailFragment.updateFileDetails(false, false);
+ }
}
}
startSynchronization();
}
+
@Override
public void onFailedSavingCertificate() {
showDialog(DIALOG_CERT_NOT_SAVED);
@Override
public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
if (operation instanceof RemoveFileOperation) {
- onRemoveFileOperationFinish((RemoveFileOperation) operation, result);
-
+ onRemoveFileOperationFinish((RemoveFileOperation)operation, result);
+
} else if (operation instanceof RenameFileOperation) {
- onRenameFileOperationFinish((RenameFileOperation) operation, result);
-
+ onRenameFileOperationFinish((RenameFileOperation)operation, result);
+
} else if (operation instanceof SynchronizeFileOperation) {
- onSynchronizeFileOperationFinish((SynchronizeFileOperation) operation, result);
+ onSynchronizeFileOperationFinish((SynchronizeFileOperation)operation, result);
}
}
msg.show();
OCFile removedFile = operation.getFile();
if (mDualPane) {
- FileDetailFragment details = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(
- FileDetailFragment.FTAG);
- if (details != null && removedFile.equals(details.getDisplayedFile())) {
+ FileFragment details = (FileFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
+ if (details != null && removedFile.equals(details.getFile())) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
- transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null)); // empty
- // FileDetailFragment
+ transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null)); // empty FileDetailFragment
transaction.commit();
}
}
}
} else {
- Toast msg = Toast.makeText(this, R.string.remove_fail_msg, Toast.LENGTH_LONG);
+ Toast msg = Toast.makeText(this, R.string.remove_fail_msg, Toast.LENGTH_LONG);
msg.show();
if (result.isSslRecoverableException()) {
mLastSslUntrustedServerResult = result;
- showDialog(DIALOG_SSL_VALIDATOR);
+ showDialog(DIALOG_SSL_VALIDATOR);
}
}
}
OCFile renamedFile = operation.getFile();
if (result.isSuccess()) {
if (mDualPane) {
- FileDetailFragment details = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(
- FileDetailFragment.FTAG);
- if (details != null && renamedFile.equals(details.getDisplayedFile())) {
- details.updateFileDetails(renamedFile, AccountUtils.getCurrentOwnCloudAccount(this));
+ FileFragment details = (FileFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
+ if (details != null && details instanceof FileDetailFragment && renamedFile.equals(details.getFile()) ) {
+ ((FileDetailFragment) details).updateFileDetails(renamedFile, AccountUtils.getCurrentOwnCloudAccount(this));
}
}
if (mStorageManager.getFileById(renamedFile.getParentId()).equals(mCurrentDir)) {
} else {
if (result.getCode().equals(ResultCode.INVALID_LOCAL_FILE_NAME)) {
- Toast msg = Toast.makeText(this, R.string.rename_local_fail_msg, Toast.LENGTH_LONG);
+ Toast msg = Toast.makeText(this, R.string.rename_local_fail_msg, Toast.LENGTH_LONG);
msg.show();
// TODO throw again the new rename dialog
} else {
- Toast msg = Toast.makeText(this, R.string.rename_server_fail_msg, Toast.LENGTH_LONG);
+ Toast msg = Toast.makeText(this, R.string.rename_server_fail_msg, Toast.LENGTH_LONG);
msg.show();
if (result.isSslRecoverableException()) {
mLastSslUntrustedServerResult = result;
- showDialog(DIALOG_SSL_VALIDATOR);
+ showDialog(DIALOG_SSL_VALIDATOR);
}
}
}
}
+
private void onSynchronizeFileOperationFinish(SynchronizeFileOperation operation, RemoteOperationResult result) {
dismissDialog(DIALOG_SHORT_WAIT);
OCFile syncedFile = operation.getLocalFile();
startActivity(i);
} else {
- Toast msg = Toast.makeText(this, R.string.sync_file_fail_msg, Toast.LENGTH_LONG);
+ Toast msg = Toast.makeText(this, R.string.sync_file_fail_msg, Toast.LENGTH_LONG);
msg.show();
}
onTransferStateChanged(syncedFile, true, true);
} else {
- Toast msg = Toast.makeText(this, R.string.sync_file_nothing_to_do_msg, Toast.LENGTH_LONG);
+ Toast msg = Toast.makeText(this, R.string.sync_file_nothing_to_do_msg, Toast.LENGTH_LONG);
msg.show();
}
}
fileListFragment.listDirectory();
}*/
if (mDualPane) {
- FileDetailFragment details = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(
- FileDetailFragment.FTAG);
- if (details != null && file.equals(details.getDisplayedFile())) {
+ FileFragment details = (FileFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG);
+ if (details != null && details instanceof FileDetailFragment && file.equals(details.getFile()) ) {
if (downloading || uploading) {
- details.updateFileDetails(file, AccountUtils.getCurrentOwnCloudAccount(this));
+ ((FileDetailFragment)details).updateFileDetails(file, AccountUtils.getCurrentOwnCloudAccount(this));
} else {
- details.updateFileDetails(downloading || uploading);
+ ((FileDetailFragment)details).updateFileDetails(false, true);
}
}
}
}
-
+ @Override
+ public void showFragmentWithDetails(OCFile file) {
+ if (mDualPane) {
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ transaction.replace(R.id.file_details_container, new FileDetailFragment(file, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG);
+ transaction.commit();
+
+ } else {
+ Intent showDetailsIntent = new Intent(this, FileDetailActivity.class);
+ showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, file);
+ showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, AccountUtils.getCurrentOwnCloudAccount(this));
+ showDetailsIntent.putExtra(FileDetailActivity.EXTRA_MODE, FileDetailActivity.MODE_DETAILS);
+ startActivity(showDetailsIntent);
+ }
+ }
+ public void onDismiss(EditNameDialog dialog) {
+ //dialog.dismiss();
+ if (dialog.getResult()) {
+ String newDirectoryName = dialog.getNewFilename().trim();
+ Log.d(TAG, "'create directory' dialog dismissed with new name " + newDirectoryName);
+ if (newDirectoryName.length() > 0) {
+ String path;
+ if (mCurrentDir == null) {
+ // this is just a patch; we should ensure that mCurrentDir never is null
+ if (!mStorageManager.fileExists(OCFile.PATH_SEPARATOR)) {
+ OCFile file = new OCFile(OCFile.PATH_SEPARATOR);
+ mStorageManager.saveFile(file);
+ }
+ mCurrentDir = mStorageManager.getFileByPath(OCFile.PATH_SEPARATOR);
+ }
+ path = FileDisplayActivity.this.mCurrentDir.getRemotePath();
+
+ // Create directory
+ path += newDirectoryName + OCFile.PATH_SEPARATOR;
+ Thread thread = new Thread(new DirectoryCreator(path, AccountUtils.getCurrentOwnCloudAccount(FileDisplayActivity.this), new Handler()));
+ thread.start();
+
+ showDialog(DIALOG_SHORT_WAIT);
+ }
+ }
+ }
+
+ private void requestForDownload() {
+ Account account = AccountUtils.getCurrentOwnCloudAccount(this);
+ if (!mDownloaderBinder.isDownloading(account, mWaitingToPreview)) {
+ Intent i = new Intent(this, FileDownloader.class);
+ i.putExtra(FileDownloader.EXTRA_ACCOUNT, account);
+ i.putExtra(FileDownloader.EXTRA_FILE, mWaitingToPreview);
+ startService(i);
+ }
+ }
+
}
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
+import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageButton;
import android.widget.LinearLayout;
+import android.widget.TextView;
import android.widget.Toast;
import com.owncloud.android.AccountUtils;
import com.owncloud.android.db.DbHandler;
import com.owncloud.android.files.InstantUploadBroadcastReceiver;
import com.owncloud.android.files.services.FileUploader;
-import com.owncloud.android.files.services.InstantUploadService;
+import com.owncloud.android.utils.FileStorageUtils;
/**
* This Activity is used to display a list with images they could not be
* uploaded instantly. The images can be selected for delete or for a try again
* upload
*
- * The entrypoint for this activity is the 'Failed upload Notification" and a
- * submenue underneath the 'Upload' menuentry
+ * The entry-point for this activity is the 'Failed upload Notification" and a
+ * sub-menu underneath the 'Upload' menu-item
*
* @author andomaex / Matthias Baumann
*
private static final String LOG_TAG = InstantUploadActivity.class.getSimpleName();
private LinearLayout listView;
private static final String retry_chexbox_tag = "retry_chexbox_tag";
+ public static final boolean IS_ENABLED = false;
private static int MAX_LOAD_IMAGES = 5;
private int lastLoadImageIdx = 0;
private SparseArray<String> fileList = null;
+ CheckBox failed_upload_all_cb;
@Override
protected void onCreate(Bundle savedInstanceState) {
delete_all_btn.setOnClickListener(getDeleteListner());
Button retry_all_btn = (Button) findViewById(R.id.failed_upload_retry_all_btn);
retry_all_btn.setOnClickListener(getRetryListner());
- CheckBox failed_upload_all_cb = (CheckBox) findViewById(R.id.failed_upload_headline_cb);
+ this.failed_upload_all_cb = (CheckBox) findViewById(R.id.failed_upload_headline_cb);
failed_upload_all_cb.setOnCheckedChangeListener(getCheckAllListener());
listView = (LinearLayout) findViewById(R.id.failed_upload_scrollviewlayout);
lastLoadImageIdx++;
String imp_path = c.getString(1);
+ String message = c.getString(4);
fileList.put(lastLoadImageIdx, imp_path);
- LinearLayout rowLayout = getLinearLayout(lastLoadImageIdx);
+ LinearLayout rowLayout = getHorizontalLinearLayout(lastLoadImageIdx);
rowLayout.addView(getFileCheckbox(lastLoadImageIdx));
rowLayout.addView(getImageButton(imp_path, lastLoadImageIdx));
- rowLayout.addView(getFileButton(imp_path, lastLoadImageIdx));
+ rowLayout.addView(getFileButton(imp_path, message, lastLoadImageIdx));
listView.addView(rowLayout);
Log_OC.d(LOG_TAG, imp_path + " on idx: " + lastLoadImageIdx);
if (lastLoadImageIdx % MAX_LOAD_IMAGES == 0) {
public void onClick(View v) {
try {
+
List<CheckBox> list = getCheckboxList();
for (CheckBox checkbox : list) {
boolean to_retry = checkbox.isChecked();
// refresh the List
listView.removeAllViews();
loadListView(true);
+ if (failed_upload_all_cb != null) {
+ failed_upload_all_cb.setChecked(false);
+ }
}
}
@Override
public void onClick(View v) {
+
final DbHandler dbh = new DbHandler(getApplicationContext());
try {
List<CheckBox> list = getCheckboxList();
// refresh the List
listView.removeAllViews();
loadListView(true);
+ if (failed_upload_all_cb != null) {
+ failed_upload_all_cb.setChecked(false);
+ }
}
}
};
}
- private LinearLayout getLinearLayout(int id) {
+ private LinearLayout getHorizontalLinearLayout(int id) {
LinearLayout linearLayout = new LinearLayout(getApplicationContext());
linearLayout.setId(id);
linearLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
return linearLayout;
}
- private Button getFileButton(final String img_path, int id) {
- Button retryButton = new Button(this);
+ private LinearLayout getVerticalLinearLayout() {
+ LinearLayout linearLayout = new LinearLayout(getApplicationContext());
+ linearLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
+ LinearLayout.LayoutParams.MATCH_PARENT));
+ linearLayout.setGravity(Gravity.TOP);
+ linearLayout.setOrientation(LinearLayout.VERTICAL);
+ return linearLayout;
+ }
+
+ private View getFileButton(final String img_path, String message, int id) {
+
+ TextView failureTextView = new TextView(this);
+ failureTextView.setText(getString(R.string.failed_upload_failure_text) + message);
+ failureTextView.setBackgroundResource(R.color.owncloud_white);
+ failureTextView.setTextSize(8);
+ failureTextView.setOnLongClickListener(getOnLongClickListener(message));
+ failureTextView.setPadding(5, 5, 5, 10);
+ TextView retryButton = new TextView(this);
retryButton.setId(id);
retryButton.setText(img_path);
retryButton.setBackgroundResource(R.color.owncloud_white);
retryButton.setTextSize(8);
retryButton.setOnClickListener(getImageButtonOnClickListener(img_path));
- return retryButton;
+ retryButton.setOnLongClickListener(getOnLongClickListener(message));
+ retryButton.setPadding(5, 5, 5, 10);
+ LinearLayout verticalLayout = getVerticalLinearLayout();
+ verticalLayout.addView(retryButton);
+ verticalLayout.addView(failureTextView);
+
+ return verticalLayout;
+ }
+
+ private OnLongClickListener getOnLongClickListener(final String message) {
+ return new OnLongClickListener() {
+
+ @Override
+ public boolean onLongClick(View v) {
+ Log.d(LOG_TAG, message);
+ Toast toast = Toast.makeText(InstantUploadActivity.this, getString(R.string.failed_upload_retry_text)
+ + message, Toast.LENGTH_LONG);
+ toast.show();
+ return true;
+ }
+
+ };
}
private CheckBox getFileCheckbox(int id) {
*/
private void startUpload(String img_path) {
// extract filename
- String filename = img_path.substring(img_path.lastIndexOf('/'), img_path.length());
+ String filename = FileStorageUtils.getInstantUploadFilePath(img_path);
if (canInstantUpload()) {
Account account = AccountUtils.getCurrentOwnCloudAccount(InstantUploadActivity.this);
// add file again to upload queue
DbHandler db = new DbHandler(InstantUploadActivity.this);
try {
- db.updateFileState(img_path, DbHandler.UPLOAD_STATUS_UPLOAD_LATER);
+ db.updateFileState(img_path, DbHandler.UPLOAD_STATUS_UPLOAD_LATER, null);
} finally {
db.close();
}
Intent i = new Intent(InstantUploadActivity.this, FileUploader.class);
i.putExtra(FileUploader.KEY_ACCOUNT, account);
i.putExtra(FileUploader.KEY_LOCAL_FILE, img_path);
- i.putExtra(FileUploader.KEY_REMOTE_FILE, InstantUploadService.INSTANT_UPLOAD_DIR + "/" + filename);
+ i.putExtra(FileUploader.KEY_REMOTE_FILE, filename);
i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE);
i.putExtra(com.owncloud.android.files.services.FileUploader.KEY_INSTANT_UPLOAD, true);
String[] args = {getString(R.string.app_name)};
ConfirmationDialogFragment dialog = ConfirmationDialogFragment.newInstance(R.string.upload_query_move_foreign_files, args, R.string.common_yes, -1, R.string.common_no);
dialog.setOnConfirmationListener(UploadFilesActivity.this);
- mCurrentDialog = dialog;
- mCurrentDialog.show(getSupportFragmentManager(), QUERY_TO_MOVE_DIALOG_TAG);
+ dialog.show(getSupportFragmentManager(), QUERY_TO_MOVE_DIALOG_TAG);
}
}
}
setResult(RESULT_OK_AND_MOVE, data);
finish();
}
- mCurrentDialog.dismiss();
- mCurrentDialog = null;
}
@Override
public void onNeutral(String callerTag) {
Log_OC.d(TAG, "Phantom neutral button in dialog was clicked; dialog tag is " + callerTag);
- mCurrentDialog.dismiss();
- mCurrentDialog = null;
}
public void onCancel(String callerTag) {
/// nothing to do; don't finish, let the user change the selection
Log_OC.d(TAG, "Negative button in dialog was clicked; dialog tag is " + callerTag);
- mCurrentDialog.dismiss();
- mCurrentDialog = null;
}
/// build the dialog
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+
Dialog dialog = builder.setView(webview)
.setIcon(R.drawable.icon)
- .setTitle(R.string.whats_new)
+ //.setTitle(R.string.whats_new)
.setPositiveButton(R.string.common_ok,
new DialogInterface.OnClickListener() {
@Override
dialog.setIndeterminate(true);
/// set message
- int messageId = getArguments().getInt(ARG_MESSAGE_ID, R.string.text_placeholder);
+ int messageId = getArguments().getInt(ARG_MESSAGE_ID, R.string.placeholder_sentence);
dialog.setMessage(getString(messageId));
/// set cancellation behavior
public final static String ARG_NEUTRAL_BTN_RES = "neutral_btn_res";
public final static String ARG_NEGATIVE_BTN_RES = "negative_btn_res";
+ public static final String FTAG_CONFIRMATION = "CONFIRMATION_FRAGMENT";
+
private ConfirmationDialogFragmentListener mListener;
/**
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
mListener.onConfirmation(getTag());
+ dialog.dismiss();
}
});
if (neuBtn != -1)
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
mListener.onNeutral(getTag());
+ dialog.dismiss();
}
});
if (negBtn != -1)
@Override
public void onClick(DialogInterface dialog, int which) {
mListener.onCancel(getTag());
+ dialog.dismiss();
}
});
return builder.create();
package com.owncloud.android.ui.fragment;
import java.io.File;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import android.accounts.Account;
import android.accounts.AccountManager;
-import android.annotation.SuppressLint;
+//import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.v4.app.FragmentTransaction;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.webkit.MimeTypeMap;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import android.widget.Toast;
+
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.widget.TextView;
import android.widget.Toast;
+
import com.actionbarsherlock.app.SherlockFragment;
import com.owncloud.android.AccountUtils;
import com.owncloud.android.DisplayUtils;
import com.owncloud.android.authenticator.AccountAuthenticator;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.files.services.FileDownloader;
import com.owncloud.android.files.services.FileObserverService;
import com.owncloud.android.files.services.FileUploader;
import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
import com.owncloud.android.ui.activity.ConflictsResolveActivity;
import com.owncloud.android.ui.activity.FileDetailActivity;
import com.owncloud.android.ui.activity.FileDisplayActivity;
-import com.owncloud.android.ui.activity.TransferServiceGetter;
import com.owncloud.android.ui.dialog.EditNameDialog;
import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;
import com.owncloud.android.utils.OwnCloudVersion;
import com.owncloud.android.R;
+
+import eu.alefzero.webdav.OnDatatransferProgressListener;
import eu.alefzero.webdav.WebdavClient;
import eu.alefzero.webdav.WebdavUtils;
+
/**
* This Fragment is used to display the details about a file.
*
* @author Bartek Przybylski
- *
+ * @author David A. Velasco
*/
public class FileDetailFragment extends SherlockFragment implements
- OnClickListener, ConfirmationDialogFragment.ConfirmationDialogFragmentListener, OnRemoteOperationListener, EditNameDialogListener {
+ OnClickListener,
+ ConfirmationDialogFragment.ConfirmationDialogFragmentListener, OnRemoteOperationListener, EditNameDialogListener,
+ FileFragment {
public static final String EXTRA_FILE = "FILE";
public static final String EXTRA_ACCOUNT = "ACCOUNT";
- private FileDetailFragment.ContainerActivity mContainerActivity;
+ private FileFragment.ContainerActivity mContainerActivity;
private int mLayout;
private View mView;
private OCFile mFile;
private Account mAccount;
private FileDataStorageManager mStorageManager;
- private ImageView mPreview;
- private DownloadFinishReceiver mDownloadFinishReceiver;
private UploadFinishReceiver mUploadFinishReceiver;
+ public ProgressListener mProgressListener;
private Handler mHandler;
private RemoteOperation mLastRemoteOperation;
- private DialogFragment mCurrentDialog;
-
+
private static final String TAG = FileDetailFragment.class.getSimpleName();
public static final String FTAG = "FileDetails";
public static final String FTAG_CONFIRMATION = "REMOVE_CONFIRMATION_FRAGMENT";
-
+
/**
* Creates an empty details fragment.
*
mAccount = null;
mStorageManager = null;
mLayout = R.layout.file_details_empty;
+ mProgressListener = null;
}
mAccount = ocAccount;
mStorageManager = null; // we need a context to init this; the container activity is not available yet at this moment
mLayout = R.layout.file_details_empty;
+ mProgressListener = null;
}
mView.findViewById(R.id.fdOpenBtn).setOnClickListener(this);
mView.findViewById(R.id.fdRemoveBtn).setOnClickListener(this);
//mView.findViewById(R.id.fdShareBtn).setOnClickListener(this);
- mPreview = (ImageView)mView.findViewById(R.id.fdPreview);
+ ProgressBar progressBar = (ProgressBar)mView.findViewById(R.id.fdProgressBar);
+ mProgressListener = new ProgressListener(progressBar);
}
- updateFileDetails(false);
+ updateFileDetails(false, false);
return view;
}
super.onAttach(activity);
try {
mContainerActivity = (ContainerActivity) activity;
+
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement " + FileDetailFragment.ContainerActivity.class.getSimpleName());
}
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (mAccount != null) {
- mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());;
+ mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
- Log_OC.i(getClass().toString(), "onSaveInstanceState() start");
super.onSaveInstanceState(outState);
outState.putParcelable(FileDetailFragment.EXTRA_FILE, mFile);
outState.putParcelable(FileDetailFragment.EXTRA_ACCOUNT, mAccount);
- Log_OC.i(getClass().toString(), "onSaveInstanceState() end");
}
+ @Override
+ public void onStart() {
+ super.onStart();
+ listenForTransferProgress();
+ }
@Override
public void onResume() {
super.onResume();
-
- mDownloadFinishReceiver = new DownloadFinishReceiver();
- IntentFilter filter = new IntentFilter(
- FileDownloader.DOWNLOAD_FINISH_MESSAGE);
- getActivity().registerReceiver(mDownloadFinishReceiver, filter);
-
mUploadFinishReceiver = new UploadFinishReceiver();
- filter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);
+ IntentFilter filter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);
getActivity().registerReceiver(mUploadFinishReceiver, filter);
-
- mPreview = (ImageView)mView.findViewById(R.id.fdPreview);
+
}
+
@Override
public void onPause() {
super.onPause();
-
- getActivity().unregisterReceiver(mDownloadFinishReceiver);
- mDownloadFinishReceiver = null;
-
- getActivity().unregisterReceiver(mUploadFinishReceiver);
- mUploadFinishReceiver = null;
-
- if (mPreview != null) {
- mPreview = null;
+ if (mUploadFinishReceiver != null) {
+ getActivity().unregisterReceiver(mUploadFinishReceiver);
+ mUploadFinishReceiver = null;
}
}
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ leaveTransferProgress();
+ }
+
+
@Override
public View getView() {
return super.getView() == null ? mView : super.getView();
}
-
-
@Override
public void onClick(View v) {
switch (v.getId()) {
// update ui
boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
- setButtonsForTransferring(); // disable button immediately, although the synchronization does not result in a file transference
}
break;
FileObserverService.CMD_DEL_OBSERVED_FILE));
intent.putExtra(FileObserverService.KEY_CMD_ARG_FILE, mFile);
intent.putExtra(FileObserverService.KEY_CMD_ARG_ACCOUNT, mAccount);
- Log_OC.e(TAG, "starting observer service");
getActivity().startService(intent);
if (mFile.keepInSync()) {
mFile.isDown() ? R.string.confirmation_remove_local : -1,
R.string.common_cancel);
confDialog.setOnConfirmationListener(this);
- mCurrentDialog = confDialog;
- mCurrentDialog.show(getFragmentManager(), FTAG_CONFIRMATION);
+ confDialog.show(getFragmentManager(), FTAG_CONFIRMATION);
break;
}
case R.id.fdOpenBtn: {
- String storagePath = mFile.getStoragePath();
- String encodedStoragePath = WebdavUtils.encodePath(storagePath);
- try {
- Intent i = new Intent(Intent.ACTION_VIEW);
- i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mFile.getMimetype());
- i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
- startActivity(i);
-
- } catch (Throwable t) {
- Log_OC.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());
- boolean toastIt = true;
- String mimeType = "";
- try {
- Intent i = new Intent(Intent.ACTION_VIEW);
- mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(storagePath.substring(storagePath.lastIndexOf('.') + 1));
- if (mimeType == null || !mimeType.equals(mFile.getMimetype())) {
- if (mimeType != null) {
- i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mimeType);
- } else {
- // desperate try
- i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), "*/*");
- }
- i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
- startActivity(i);
- toastIt = false;
- }
-
- } catch (IndexOutOfBoundsException e) {
- Log_OC.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
-
- } catch (ActivityNotFoundException e) {
- Log_OC.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
-
- } catch (Throwable th) {
- Log_OC.e(TAG, "Unexpected problem when opening: " + storagePath, th);
-
- } finally {
- if (toastIt) {
- Toast.makeText(getActivity(), "There is no application to handle file " + mFile.getFileName(), Toast.LENGTH_SHORT).show();
- }
- }
-
- }
+ openFile();
break;
}
default:
}
+ /**
+ * Opens mFile.
+ */
+ private void openFile() {
+
+ String storagePath = mFile.getStoragePath();
+ String encodedStoragePath = WebdavUtils.encodePath(storagePath);
+ try {
+ Intent i = new Intent(Intent.ACTION_VIEW);
+ i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mFile.getMimetype());
+ i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ startActivity(i);
+
+ } catch (Throwable t) {
+ Log.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());
+ boolean toastIt = true;
+ String mimeType = "";
+ try {
+ Intent i = new Intent(Intent.ACTION_VIEW);
+ mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(storagePath.substring(storagePath.lastIndexOf('.') + 1));
+ if (mimeType == null || !mimeType.equals(mFile.getMimetype())) {
+ if (mimeType != null) {
+ i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mimeType);
+ } else {
+ // desperate try
+ i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), "*/*");
+ }
+ i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ startActivity(i);
+ toastIt = false;
+ }
+
+ } catch (IndexOutOfBoundsException e) {
+ Log.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
+
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
+
+ } catch (Throwable th) {
+ Log.e(TAG, "Unexpected problem when opening: " + storagePath, th);
+
+ } finally {
+ if (toastIt) {
+ Toast.makeText(getActivity(), "There is no application to handle file " + mFile.getFileName(), Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ }
+ }
+
+
@Override
public void onConfirmation(String callerTag) {
if (callerTag.equals(FTAG_CONFIRMATION)) {
getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
}
}
- mCurrentDialog.dismiss();
- mCurrentDialog = null;
}
@Override
mStorageManager.saveFile(mFile);
updateFileDetails(mFile, mAccount);
}
- mCurrentDialog.dismiss();
- mCurrentDialog = null;
}
@Override
public void onCancel(String callerTag) {
- Log_OC.d(TAG, "REMOVAL CANCELED");
- mCurrentDialog.dismiss();
- mCurrentDialog = null;
+ Log.d(TAG, "REMOVAL CANCELED");
}
/**
- * Can be used to get the file that is currently being displayed.
- * @return The file on the screen.
+ * {@inheritDoc}
*/
- public OCFile getDisplayedFile(){
+ public OCFile getFile(){
return mFile;
}
mStorageManager = new FileDataStorageManager(ocAccount, getActivity().getApplicationContext().getContentResolver());
}
mAccount = ocAccount;
- updateFileDetails(false);
+ updateFileDetails(false, false);
}
-
/**
* Updates the view with all relevant details about that file.
*
* TODO Remove parameter when the transferring state of files is kept in database.
*
+ * TODO REFACTORING! this method called 5 times before every time the fragment is shown!
+ *
* @param transferring Flag signaling if the file should be considered as downloading or uploading,
* although {@link FileDownloaderBinder#isDownloading(Account, OCFile)} and
* {@link FileUploaderBinder#isUploading(Account, OCFile)} return false.
- *
+ *
+ * @param refresh If 'true', try to refresh the hold file from the database
*/
- public void updateFileDetails(boolean transferring) {
+ public void updateFileDetails(boolean transferring, boolean refresh) {
- if (mFile != null && mAccount != null && mLayout == R.layout.file_details_fragment) {
+ if (readyToShow()) {
+
+ if (refresh && mStorageManager != null) {
+ mFile = mStorageManager.getFileByPath(mFile.getRemotePath());
+ }
// set file details
setFilename(mFile.getFileName());
setButtonsForTransferring();
} else if (mFile.isDown()) {
- // Update preview
- if (mFile.getMimetype().startsWith("image/")) {
- BitmapLoader bl = new BitmapLoader();
- bl.execute(new String[]{mFile.getStoragePath()});
- }
setButtonsForDown();
/**
+ * Checks if the fragment is ready to show details of a OCFile
+ *
+ * @return 'True' when the fragment is ready to show details of a file
+ */
+ private boolean readyToShow() {
+ return (mFile != null && mAccount != null && mLayout == R.layout.file_details_fragment);
+ }
+
+
+ /**
* Updates the filename in view
* @param filename to set
*/
((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(false);
((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(false);
getView().findViewById(R.id.fdKeepInSync).setEnabled(false);
+
+ // show the progress bar for the transfer
+ ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.fdProgressBar);
+ progressBar.setVisibility(View.VISIBLE);
+ TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText);
+ progressText.setVisibility(View.VISIBLE);
+ FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
+ FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();
+ if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) {
+ progressText.setText(R.string.downloader_download_in_progress_ticker);
+ } else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile)) {
+ progressText.setText(R.string.uploader_upload_in_progress_ticker);
+ }
}
}
-
+
/**
* Enables or disables buttons for a file locally available
*/
((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(true);
((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(true);
getView().findViewById(R.id.fdKeepInSync).setEnabled(true);
+
+ // hides the progress bar
+ ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.fdProgressBar);
+ progressBar.setVisibility(View.GONE);
+ TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText);
+ progressText.setVisibility(View.GONE);
}
}
((Button) getView().findViewById(R.id.fdRenameBtn)).setEnabled(true);
((Button) getView().findViewById(R.id.fdRemoveBtn)).setEnabled(true);
getView().findViewById(R.id.fdKeepInSync).setEnabled(true);
+
+ // hides the progress bar
+ ProgressBar progressBar = (ProgressBar)getView().findViewById(R.id.fdProgressBar);
+ progressBar.setVisibility(View.GONE);
+ TextView progressText = (TextView)getView().findViewById(R.id.fdProgressText);
+ progressText.setVisibility(View.GONE);
}
}
return false;
}
-
- /**
- * Interface to implement by any Activity that includes some instance of FileDetailFragment
- *
- * @author David A. Velasco
- */
- public interface ContainerActivity extends TransferServiceGetter {
-
- /**
- * Callback method invoked when the detail fragment wants to notice its container
- * activity about a relevant state the file shown by the fragment.
- *
- * Added to notify to FileDisplayActivity about the need of refresh the files list.
- *
- * Currently called when:
- * - a download is started;
- * - a rename is completed;
- * - a deletion is completed;
- * - the 'inSync' flag is changed;
- */
- public void onFileStateChanged();
-
- }
-
-
- /**
- * Once the file download has finished -> update view
- * @author Bartek Przybylski
- */
- private class DownloadFinishReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- String accountName = intent.getStringExtra(FileDownloader.ACCOUNT_NAME);
- if (!isEmpty() && accountName.equals(mAccount.name)) {
- boolean downloadWasFine = intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false);
- String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
- if (mFile.getRemotePath().equals(downloadedRemotePath)) {
- if (downloadWasFine) {
- mFile = mStorageManager.getFileByPath(downloadedRemotePath);
- }
- updateFileDetails(false); // it updates the buttons; must be called although !downloadWasFine
- }
- }
- }
- }
-
-
/**
* Once the file upload has finished -> update view
*
msg.show();
}
getSherlockActivity().removeStickyBroadcast(intent); // not the best place to do this; a small refactorization of BroadcastReceivers should be done
- updateFileDetails(false); // it updates the buttons; must be called although !uploadWasFine; interrupted uploads still leave an incomplete file in the server
+ updateFileDetails(false, false); // it updates the buttons; must be called although !uploadWasFine; interrupted uploads still leave an incomplete file in the server
}
}
}
OwnCloudVersion ocv = new OwnCloudVersion(am.getUserData(account, AccountAuthenticator.KEY_OC_VERSION));
String url = am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + AccountUtils.getWebdavPath(ocv);
- Log_OC.d("share", "sharing for version " + ocv.toString());
+ Log.d("share", "sharing for version " + ocv.toString());
if (ocv.compareTo(new OwnCloudVersion(0x040000)) >= 0) {
String APPS_PATH = "/apps/files_sharing/";
post.addRequestHeader("Content-type","application/x-www-form-urlencoded; charset=UTF-8" );
post.addRequestHeader("Referer", am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL));
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
- Log_OC.d("share", mPath+"");
+ Log.d("share", mPath+"");
formparams.add(new BasicNameValuePair("sources",mPath));
formparams.add(new BasicNameValuePair("uid_shared_with", "public"));
formparams.add(new BasicNameValuePair("permissions", "0"));
try {
PropFindMethod find = new PropFindMethod(url+"/");
find.addRequestHeader("Referer", am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL));
- Log_OC.d("sharer", ""+ url+"/");
+ Log.d("sharer", ""+ url+"/");
for (org.apache.commons.httpclient.Header a : find.getRequestHeaders()) {
- Log_OC.d("sharer-h", a.getName() + ":"+a.getValue());
+ Log.d("sharer-h", a.getName() + ":"+a.getValue());
}
int status2 = wc.executeMethod(find);
- Log_OC.d("sharer", "propstatus "+status2);
+ Log.d("sharer", "propstatus "+status2);
GetMethod get = new GetMethod(am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + "/");
get.addRequestHeader("Referer", am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL));
status2 = wc.executeMethod(get);
- Log_OC.d("sharer", "getstatus "+status2);
- Log_OC.d("sharer", "" + get.getResponseBodyAsString());
+ Log.d("sharer", "getstatus "+status2);
+ Log.d("sharer", "" + get.getResponseBodyAsString());
for (org.apache.commons.httpclient.Header a : get.getResponseHeaders()) {
- Log_OC.d("sharer", a.getName() + ":"+a.getValue());
+ Log.d("sharer", a.getName() + ":"+a.getValue());
}
status = wc.executeMethod(post);
for (org.apache.commons.httpclient.Header a : post.getRequestHeaders()) {
- Log_OC.d("sharer-h", a.getName() + ":"+a.getValue());
+ Log.d("sharer-h", a.getName() + ":"+a.getValue());
}
for (org.apache.commons.httpclient.Header a : post.getResponseHeaders()) {
- Log_OC.d("sharer", a.getName() + ":"+a.getValue());
+ Log.d("sharer", a.getName() + ":"+a.getValue());
}
String resp = post.getResponseBodyAsString();
- Log_OC.d("share", ""+post.getURI().toString());
- Log_OC.d("share", "returned status " + status);
- Log_OC.d("share", " " +resp);
+ Log.d("share", ""+post.getURI().toString());
+ Log.d("share", "returned status " + status);
+ Log.d("share", " " +resp);
if(status != HttpStatus.SC_OK ||resp == null || resp.equals("") || resp.startsWith("false")) {
return;
String token = jsonObject.getString("data");
String uri = am.getUserData(account, AccountAuthenticator.KEY_OC_BASE_URL) + SHARED_PATH + token;
- Log_OC.d("Actions:shareFile ok", "url: " + uri);
+ Log.d("Actions:shareFile ok", "url: " + uri);
} catch (Exception e) {
e.printStackTrace();
public void onDismiss(EditNameDialog dialog) {
if (dialog.getResult()) {
String newFilename = dialog.getNewFilename();
- Log_OC.d(TAG, "name edit dialog dismissed with new name " + newFilename);
+ Log.d(TAG, "name edit dialog dismissed with new name " + newFilename);
mLastRemoteOperation = new RenameFileOperation( mFile,
mAccount,
newFilename,
}
- class BitmapLoader extends AsyncTask<String, Void, Bitmap> {
- @SuppressLint({ "NewApi", "NewApi", "NewApi" }) // to avoid Lint errors since Android SDK r20
- @Override
- protected Bitmap doInBackground(String... params) {
- Bitmap result = null;
- if (params.length != 1) return result;
- String storagePath = params[0];
- try {
-
- BitmapFactory.Options options = new Options();
- options.inScaled = true;
- options.inPurgeable = true;
- options.inJustDecodeBounds = true;
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- options.inPreferQualityOverSpeed = false;
- }
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
- options.inMutable = false;
- }
-
- result = BitmapFactory.decodeFile(storagePath, options);
- options.inJustDecodeBounds = false;
-
- int width = options.outWidth;
- int height = options.outHeight;
- int scale = 1;
- if (width >= 2048 || height >= 2048) {
- scale = (int) Math.ceil((Math.ceil(Math.max(height, width) / 2048.)));
- options.inSampleSize = scale;
- }
- Display display = getActivity().getWindowManager().getDefaultDisplay();
- Point size = new Point();
- int screenwidth;
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB_MR2) {
- display.getSize(size);
- screenwidth = size.x;
- } else {
- screenwidth = display.getWidth();
- }
-
- Log_OC.e("ASD", "W " + width + " SW " + screenwidth);
-
- if (width > screenwidth) {
- scale = (int) Math.ceil((float)width / screenwidth);
- options.inSampleSize = scale;
- }
-
- result = BitmapFactory.decodeFile(storagePath, options);
-
- Log_OC.e("ASD", "W " + options.outWidth + " SW " + options.outHeight);
-
- } catch (OutOfMemoryError e) {
- result = null;
- Log_OC.e(TAG, "Out of memory occured for file with size " + storagePath);
-
- } catch (NoSuchFieldError e) {
- result = null;
- Log_OC.e(TAG, "Error from access to unexisting field despite protection " + storagePath);
-
- } catch (Throwable t) {
- result = null;
- Log_OC.e(TAG, "Unexpected error while creating image preview " + storagePath, t);
- }
- return result;
- }
- @Override
- protected void onPostExecute(Bitmap result) {
- if (result != null && mPreview != null) {
- mPreview.setImageBitmap(result);
- }
- }
-
- }
-
/**
* {@inheritDoc}
*/
} else {
if (operation.transferWasRequested()) {
+ setButtonsForTransferring();
mContainerActivity.onFileStateChanged(); // this is not working; FileDownloader won't do NOTHING at all until this method finishes, so
// checking the service to see if the file is downloading results in FALSE
} else {
}
}
}
+
+
+ public void listenForTransferProgress() {
+ if (mProgressListener != null) {
+ if (mContainerActivity.getFileDownloaderBinder() != null) {
+ mContainerActivity.getFileDownloaderBinder().addDatatransferProgressListener(mProgressListener, mAccount, mFile);
+ }
+ if (mContainerActivity.getFileUploaderBinder() != null) {
+ mContainerActivity.getFileUploaderBinder().addDatatransferProgressListener(mProgressListener, mAccount, mFile);
+ }
+ }
+ }
+
+
+ public void leaveTransferProgress() {
+ if (mProgressListener != null) {
+ if (mContainerActivity.getFileDownloaderBinder() != null) {
+ mContainerActivity.getFileDownloaderBinder().removeDatatransferProgressListener(mProgressListener, mAccount, mFile);
+ }
+ if (mContainerActivity.getFileUploaderBinder() != null) {
+ mContainerActivity.getFileUploaderBinder().removeDatatransferProgressListener(mProgressListener, mAccount, mFile);
+ }
+ }
+ }
+
+
+
+ /**
+ * Helper class responsible for updating the progress bar shown for file uploading or downloading
+ *
+ * @author David A. Velasco
+ */
+ private class ProgressListener implements OnDatatransferProgressListener {
+ int mLastPercent = 0;
+ WeakReference<ProgressBar> mProgressBar = null;
+
+ ProgressListener(ProgressBar progressBar) {
+ mProgressBar = new WeakReference<ProgressBar>(progressBar);
+ }
+
+ @Override
+ public void onTransferProgress(long progressRate) {
+ // old method, nothing here
+ };
+
+ @Override
+ public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String filename) {
+ int percent = (int)(100.0*((double)totalTransferredSoFar)/((double)totalToTransfer));
+ if (percent != mLastPercent) {
+ ProgressBar pb = mProgressBar.get();
+ if (pb != null) {
+ pb.setProgress(percent);
+ pb.postInvalidate();
+ }
+ }
+ mLastPercent = percent;
+ }
+
+ };
-}
+}
\ No newline at end of file
--- /dev/null
+/* ownCloud Android client application
+ * Copyright (C) 2012-2013 ownCloud Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.ui.fragment;
+
+import android.content.Intent;
+import android.support.v4.app.Fragment;
+
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.ui.activity.TransferServiceGetter;
+
+/**
+ * Common methods for {@link Fragment}s containing {@link OCFile}s
+ *
+ * @author David A. Velasco
+ *
+ */
+public interface FileFragment {
+
+ /**
+ * Getter for the hold {@link OCFile}
+ *
+ * @return The {@link OCFile} hold
+ */
+ public OCFile getFile();
+
+
+ /**
+ * Interface to implement by any Activity that includes some instance of FileFragment
+ *
+ * @author David A. Velasco
+ */
+ public interface ContainerActivity extends TransferServiceGetter {
+
+ /**
+ * Callback method invoked when the detail fragment wants to notice its container
+ * activity about a relevant state the file shown by the fragment.
+ *
+ * Added to notify to FileDisplayActivity about the need of refresh the files list.
+ *
+ * Currently called when:
+ * - a download is started;
+ * - a rename is completed;
+ * - a deletion is completed;
+ * - the 'inSync' flag is changed;
+ */
+ public void onFileStateChanged();
+
+ /**
+ * Request the parent activity to show the details of an {@link OCFile}.
+ *
+ * @param file File to show details
+ */
+ public void showFragmentWithDetails(OCFile file);
+
+
+ }
+
+}
private Handler mHandler;
private OCFile mTargetFile;
- private DialogFragment mCurrentDialog;
-
/**
* {@inheritDoc}
*/
public void onCreateContextMenu (ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getActivity().getMenuInflater();
- inflater.inflate(R.menu.file_context_menu, menu);
+ inflater.inflate(R.menu.file_actions_menu, menu);
AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
OCFile targetFile = (OCFile) mAdapter.getItem(info.position);
List<Integer> toHide = new ArrayList<Integer>();
MenuItem item = null;
if (targetFile.isDirectory()) {
// contextual menu for folders
- toHide.add(R.id.open_file_item);
- toHide.add(R.id.download_file_item);
- toHide.add(R.id.cancel_download_item);
- toHide.add(R.id.cancel_upload_item);
+ toHide.add(R.id.action_open_file_with);
+ toHide.add(R.id.action_download_file);
+ toHide.add(R.id.action_cancel_download);
+ toHide.add(R.id.action_cancel_upload);
+ toHide.add(R.id.action_see_details);
if ( mContainerActivity.getFileDownloaderBinder().isDownloading(AccountUtils.getCurrentOwnCloudAccount(getActivity()), targetFile) ||
mContainerActivity.getFileUploaderBinder().isUploading(AccountUtils.getCurrentOwnCloudAccount(getActivity()), targetFile) ) {
- toDisable.add(R.id.rename_file_item);
- toDisable.add(R.id.remove_file_item);
+ toDisable.add(R.id.action_rename_file);
+ toDisable.add(R.id.action_remove_file);
}
} else {
// contextual menu for regular files
if (targetFile.isDown()) {
- toHide.add(R.id.cancel_download_item);
- toHide.add(R.id.cancel_upload_item);
- item = menu.findItem(R.id.download_file_item);
+ toHide.add(R.id.action_cancel_download);
+ toHide.add(R.id.action_cancel_upload);
+ item = menu.findItem(R.id.action_download_file);
if (item != null) {
item.setTitle(R.string.filedetails_sync_file);
}
} else {
- toHide.add(R.id.open_file_item);
+ toHide.add(R.id.action_open_file_with);
}
if ( mContainerActivity.getFileDownloaderBinder().isDownloading(AccountUtils.getCurrentOwnCloudAccount(getActivity()), targetFile)) {
- toHide.add(R.id.download_file_item);
- toHide.add(R.id.cancel_upload_item);
- toDisable.add(R.id.open_file_item);
- toDisable.add(R.id.rename_file_item);
- toDisable.add(R.id.remove_file_item);
+ toHide.add(R.id.action_download_file);
+ toHide.add(R.id.action_cancel_upload);
+ toDisable.add(R.id.action_open_file_with);
+ toDisable.add(R.id.action_rename_file);
+ toDisable.add(R.id.action_remove_file);
} else if ( mContainerActivity.getFileUploaderBinder().isUploading(AccountUtils.getCurrentOwnCloudAccount(getActivity()), targetFile)) {
- toHide.add(R.id.download_file_item);
- toHide.add(R.id.cancel_download_item);
- toDisable.add(R.id.open_file_item);
- toDisable.add(R.id.rename_file_item);
- toDisable.add(R.id.remove_file_item);
+ toHide.add(R.id.action_download_file);
+ toHide.add(R.id.action_cancel_download);
+ toDisable.add(R.id.action_open_file_with);
+ toDisable.add(R.id.action_rename_file);
+ toDisable.add(R.id.action_remove_file);
} else {
- toHide.add(R.id.cancel_download_item);
- toHide.add(R.id.cancel_upload_item);
+ toHide.add(R.id.action_cancel_download);
+ toHide.add(R.id.action_cancel_upload);
}
}
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
mTargetFile = (OCFile) mAdapter.getItem(info.position);
switch (item.getItemId()) {
- case R.id.rename_file_item: {
+ case R.id.action_rename_file: {
EditNameDialog dialog = EditNameDialog.newInstance(getString(R.string.rename_dialog_title), mTargetFile.getFileName(), this);
dialog.show(getFragmentManager(), EditNameDialog.TAG);
return true;
}
- case R.id.remove_file_item: {
+ case R.id.action_remove_file: {
int messageStringId = R.string.confirmation_remove_alert;
int posBtnStringId = R.string.confirmation_remove_remote;
int neuBtnStringId = -1;
neuBtnStringId,
R.string.common_cancel);
confDialog.setOnConfirmationListener(this);
- mCurrentDialog = confDialog;
- mCurrentDialog.show(getFragmentManager(), FileDetailFragment.FTAG_CONFIRMATION);
+ confDialog.show(getFragmentManager(), FileDetailFragment.FTAG_CONFIRMATION);
return true;
}
- case R.id.open_file_item: {
+ case R.id.action_open_file_with: {
String storagePath = mTargetFile.getStoragePath();
String encodedStoragePath = WebdavUtils.encodePath(storagePath);
try {
}
return true;
}
- case R.id.download_file_item: {
+ case R.id.action_download_file: {
Account account = AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity());
RemoteOperation operation = new SynchronizeFileOperation(mTargetFile, null, mContainerActivity.getStorageManager(), account, true, false, getSherlockActivity());
WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(account, getSherlockActivity().getApplicationContext());
getSherlockActivity().showDialog(FileDisplayActivity.DIALOG_SHORT_WAIT);
return true;
}
- case R.id.cancel_download_item: {
+ case R.id.action_cancel_download: {
FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
Account account = AccountUtils.getCurrentOwnCloudAccount(getActivity());
if (downloaderBinder != null && downloaderBinder.isDownloading(account, mTargetFile)) {
}
return true;
}
- case R.id.cancel_upload_item: {
+ case R.id.action_cancel_upload: {
FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();
Account account = AccountUtils.getCurrentOwnCloudAccount(getActivity());
if (uploaderBinder != null && uploaderBinder.isUploading(account, mTargetFile)) {
}
return true;
}
+ case R.id.action_see_details: {
+ ((FileFragment.ContainerActivity)getActivity()).showFragmentWithDetails(mTargetFile);
+ return true;
+ }
default:
return super.onContextItemSelected(item);
}
getActivity().showDialog(FileDisplayActivity.DIALOG_SHORT_WAIT);
}
- if (mCurrentDialog != null) {
- mCurrentDialog.dismiss();
- mCurrentDialog = null;
- }
}
}
mTargetFile.setStoragePath(null);
mContainerActivity.getStorageManager().saveFile(mTargetFile);
}
- if (mCurrentDialog != null) {
- mCurrentDialog.dismiss();
- mCurrentDialog = null;
- }
listDirectory();
mContainerActivity.onTransferStateChanged(mTargetFile, false, false);
}
@Override
public void onCancel(String callerTag) {
Log_OC.d(TAG, "REMOVAL CANCELED");
- if (mCurrentDialog != null) {
- mCurrentDialog.dismiss();
- mCurrentDialog = null;
- }
}
--- /dev/null
+/* ownCloud Android client application
+ *
+ * Copyright (C) 2012-2013 ownCloud Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package com.owncloud.android.ui.preview;
+
+import java.lang.ref.WeakReference;
+
+import android.accounts.Account;
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.v4.app.FragmentStatePagerAdapter;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import com.actionbarsherlock.app.SherlockFragment;
+import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
+import com.owncloud.android.ui.fragment.FileFragment;
+
+import com.owncloud.android.R;
+
+import eu.alefzero.webdav.OnDatatransferProgressListener;
+
+/**
+ * This Fragment is used to monitor the progress of a file downloading.
+ *
+ * @author David A. Velasco
+ */
+public class FileDownloadFragment extends SherlockFragment implements OnClickListener, FileFragment {
+
+ public static final String EXTRA_FILE = "FILE";
+ public static final String EXTRA_ACCOUNT = "ACCOUNT";
+ private static final String EXTRA_ERROR = "ERROR";
+
+ private FileFragment.ContainerActivity mContainerActivity;
+
+ private View mView;
+ private OCFile mFile;
+ private Account mAccount;
+ private FileDataStorageManager mStorageManager;
+
+ public ProgressListener mProgressListener;
+ private boolean mListening;
+
+ private static final String TAG = FileDownloadFragment.class.getSimpleName();
+
+ private boolean mIgnoreFirstSavedState;
+ private boolean mError;
+
+
+ /**
+ * Creates an empty details fragment.
+ *
+ * It's necessary to keep a public constructor without parameters; the system uses it when tries to reinstantiate a fragment automatically.
+ */
+ public FileDownloadFragment() {
+ mFile = null;
+ mAccount = null;
+ mStorageManager = null;
+ mProgressListener = null;
+ mListening = false;
+ mIgnoreFirstSavedState = false;
+ mError = false;
+ }
+
+
+ /**
+ * Creates a details fragment.
+ *
+ * When 'fileToDetail' or 'ocAccount' are null, creates a dummy layout (to use when a file wasn't tapped before).
+ *
+ * @param fileToDetail An {@link OCFile} to show in the fragment
+ * @param ocAccount An ownCloud account; needed to start downloads
+ * @param ignoreFirstSavedState Flag to work around an unexpected behaviour of {@link FragmentStatePagerAdapter}; TODO better solution
+ */
+ public FileDownloadFragment(OCFile fileToDetail, Account ocAccount, boolean ignoreFirstSavedState) {
+ mFile = fileToDetail;
+ mAccount = ocAccount;
+ mStorageManager = null; // we need a context to init this; the container activity is not available yet at this moment
+ mProgressListener = null;
+ mListening = false;
+ mIgnoreFirstSavedState = ignoreFirstSavedState;
+ mError = false;
+ }
+
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ super.onCreateView(inflater, container, savedInstanceState);
+
+ if (savedInstanceState != null) {
+ if (!mIgnoreFirstSavedState) {
+ mFile = savedInstanceState.getParcelable(FileDownloadFragment.EXTRA_FILE);
+ mAccount = savedInstanceState.getParcelable(FileDownloadFragment.EXTRA_ACCOUNT);
+ mError = savedInstanceState.getBoolean(FileDownloadFragment.EXTRA_ERROR);
+ } else {
+ mIgnoreFirstSavedState = false;
+ }
+ }
+
+ View view = null;
+ view = inflater.inflate(R.layout.file_download_fragment, container, false);
+ mView = view;
+
+ ProgressBar progressBar = (ProgressBar)mView.findViewById(R.id.progressBar);
+ mProgressListener = new ProgressListener(progressBar);
+
+ ((Button)mView.findViewById(R.id.cancelBtn)).setOnClickListener(this);
+
+ if (mError) {
+ setButtonsForRemote();
+ } else {
+ setButtonsForTransferring();
+ }
+
+ return view;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ try {
+ mContainerActivity = (ContainerActivity) activity;
+
+ } catch (ClassCastException e) {
+ throw new ClassCastException(activity.toString() + " must implement " + FileFragment.ContainerActivity.class.getSimpleName());
+ }
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ if (mAccount != null) {
+ mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());;
+ }
+ }
+
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putParcelable(FileDownloadFragment.EXTRA_FILE, mFile);
+ outState.putParcelable(FileDownloadFragment.EXTRA_ACCOUNT, mAccount);
+ outState.putBoolean(FileDownloadFragment.EXTRA_ERROR, mError);
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ listenForTransferProgress();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ }
+
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ }
+
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ leaveTransferProgress();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ }
+
+
+ @Override
+ public View getView() {
+ if (!mListening) {
+ listenForTransferProgress();
+ }
+ return super.getView() == null ? mView : super.getView();
+ }
+
+
+ @Override
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.cancelBtn: {
+ FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
+ if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) {
+ downloaderBinder.cancel(mAccount, mFile);
+ getActivity().finish(); // :)
+ /*
+ leaveTransferProgress();
+ if (mFile.isDown()) {
+ setButtonsForDown();
+ } else {
+ setButtonsForRemote();
+ }
+ */
+ }
+ break;
+ }
+ default:
+ Log.e(TAG, "Incorrect view clicked!");
+ }
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public OCFile getFile(){
+ return mFile;
+ }
+
+
+ /**
+ * Updates the view depending upon the state of the downloading file.
+ *
+ * @param transferring When true, the view must be updated assuming that the holded file is
+ * downloading, no matter what the downloaderBinder says.
+ */
+ public void updateView(boolean transferring) {
+ // configure UI for depending upon local state of the file
+ FileDownloaderBinder downloaderBinder = (mContainerActivity == null) ? null : mContainerActivity.getFileDownloaderBinder();
+ if (transferring || (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile))) {
+ setButtonsForTransferring();
+
+ } else if (mFile.isDown()) {
+
+ setButtonsForDown();
+
+ } else {
+ setButtonsForRemote();
+ }
+ getView().invalidate();
+
+ }
+
+
+ /**
+ * Enables or disables buttons for a file being downloaded
+ */
+ private void setButtonsForTransferring() {
+ getView().findViewById(R.id.cancelBtn).setVisibility(View.VISIBLE);
+
+ // show the progress bar for the transfer
+ getView().findViewById(R.id.progressBar).setVisibility(View.VISIBLE);
+ TextView progressText = (TextView)getView().findViewById(R.id.progressText);
+ progressText.setText(R.string.downloader_download_in_progress_ticker);
+ progressText.setVisibility(View.VISIBLE);
+
+ // hides the error icon
+ getView().findViewById(R.id.errorText).setVisibility(View.GONE);
+ getView().findViewById(R.id.error_image).setVisibility(View.GONE);
+ }
+
+
+ /**
+ * Enables or disables buttons for a file locally available
+ */
+ private void setButtonsForDown() {
+ getView().findViewById(R.id.cancelBtn).setVisibility(View.GONE);
+
+ // hides the progress bar
+ getView().findViewById(R.id.progressBar).setVisibility(View.GONE);
+
+ // updates the text message
+ TextView progressText = (TextView)getView().findViewById(R.id.progressText);
+ progressText.setText(R.string.common_loading);
+ progressText.setVisibility(View.VISIBLE);
+
+ // hides the error icon
+ getView().findViewById(R.id.errorText).setVisibility(View.GONE);
+ getView().findViewById(R.id.error_image).setVisibility(View.GONE);
+ }
+
+
+ /**
+ * Enables or disables buttons for a file not locally available
+ *
+ * Currently, this is only used when a download was failed
+ */
+ private void setButtonsForRemote() {
+ getView().findViewById(R.id.cancelBtn).setVisibility(View.GONE);
+
+ // hides the progress bar and message
+ getView().findViewById(R.id.progressBar).setVisibility(View.GONE);
+ getView().findViewById(R.id.progressText).setVisibility(View.GONE);
+
+ // shows the error icon and message
+ getView().findViewById(R.id.errorText).setVisibility(View.VISIBLE);
+ getView().findViewById(R.id.error_image).setVisibility(View.VISIBLE);
+ }
+
+
+ public void listenForTransferProgress() {
+ if (mProgressListener != null && !mListening) {
+ if (mContainerActivity.getFileDownloaderBinder() != null) {
+ mContainerActivity.getFileDownloaderBinder().addDatatransferProgressListener(mProgressListener, mAccount, mFile);
+ mListening = true;
+ setButtonsForTransferring();
+ }
+ }
+ }
+
+
+ public void leaveTransferProgress() {
+ if (mProgressListener != null) {
+ if (mContainerActivity.getFileDownloaderBinder() != null) {
+ mContainerActivity.getFileDownloaderBinder().removeDatatransferProgressListener(mProgressListener, mAccount, mFile);
+ mListening = false;
+ }
+ }
+ }
+
+
+ /**
+ * Helper class responsible for updating the progress bar shown for file uploading or downloading
+ *
+ * @author David A. Velasco
+ */
+ private class ProgressListener implements OnDatatransferProgressListener {
+ int mLastPercent = 0;
+ WeakReference<ProgressBar> mProgressBar = null;
+
+ ProgressListener(ProgressBar progressBar) {
+ mProgressBar = new WeakReference<ProgressBar>(progressBar);
+ }
+
+ @Override
+ public void onTransferProgress(long progressRate) {
+ // old method, nothing here
+ };
+
+ @Override
+ public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String filename) {
+ int percent = (int)(100.0*((double)totalTransferredSoFar)/((double)totalToTransfer));
+ if (percent != mLastPercent) {
+ ProgressBar pb = mProgressBar.get();
+ if (pb != null) {
+ pb.setProgress(percent);
+ pb.postInvalidate();
+ }
+ }
+ mLastPercent = percent;
+ }
+
+ }
+
+
+ public void setError(boolean error) {
+ mError = error;
+ };
+
+
+
+}
--- /dev/null
+/* ownCloud Android client application
+ * Copyright (C) 2012-2013 ownCloud Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package com.owncloud.android.ui.preview;
+
+import org.apache.commons.httpclient.methods.PostMethod;
+
+import android.accounts.Account;
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.support.v4.app.Fragment;
+import android.support.v4.view.ViewPager;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnTouchListener;
+
+import com.actionbarsherlock.app.ActionBar;
+import com.actionbarsherlock.app.SherlockFragmentActivity;
+import com.actionbarsherlock.view.MenuItem;
+import com.actionbarsherlock.view.Window;
+import com.owncloud.android.datamodel.DataStorageManager;
+import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.files.services.FileDownloader;
+import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
+import com.owncloud.android.files.services.FileUploader;
+import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
+import com.owncloud.android.ui.activity.FileDetailActivity;
+import com.owncloud.android.ui.fragment.FileDetailFragment;
+import com.owncloud.android.ui.fragment.FileFragment;
+
+import com.owncloud.android.AccountUtils;
+import com.owncloud.android.R;
+
+/**
+ * Used as an utility to preview image files contained in an ownCloud account.
+ *
+ * @author David A. Velasco
+ */
+public class PreviewImageActivity extends SherlockFragmentActivity implements FileFragment.ContainerActivity, ViewPager.OnPageChangeListener, OnTouchListener {
+
+ public static final int DIALOG_SHORT_WAIT = 0;
+
+ public static final String TAG = PreviewImageActivity.class.getSimpleName();
+
+ public static final String KEY_WAITING_TO_PREVIEW = "WAITING_TO_PREVIEW";
+ private static final String KEY_WAITING_FOR_BINDER = "WAITING_FOR_BINDER";
+
+ private OCFile mFile;
+ private OCFile mParentFolder;
+ private Account mAccount;
+ private DataStorageManager mStorageManager;
+
+ private ViewPager mViewPager;
+ private PreviewImagePagerAdapter mPreviewImagePagerAdapter;
+
+ private FileDownloaderBinder mDownloaderBinder = null;
+ private ServiceConnection mDownloadConnection, mUploadConnection = null;
+ private FileUploaderBinder mUploaderBinder = null;
+
+ private boolean mRequestWaitingForBinder;
+
+ private DownloadFinishReceiver mDownloadFinishReceiver;
+
+ private boolean mFullScreen;
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mFile = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_FILE);
+ mAccount = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_ACCOUNT);
+ if (mFile == null) {
+ throw new IllegalStateException("Instanced with a NULL OCFile");
+ }
+ if (mAccount == null) {
+ throw new IllegalStateException("Instanced with a NULL ownCloud Account");
+ }
+ if (!mFile.isImage()) {
+ throw new IllegalArgumentException("Non-image file passed as argument");
+ }
+ requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
+ setContentView(R.layout.preview_image_activity);
+
+ ActionBar actionBar = getSupportActionBar();
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setTitle(mFile.getFileName());
+ actionBar.hide();
+
+ mFullScreen = true;
+
+ mStorageManager = new FileDataStorageManager(mAccount, getContentResolver());
+ mParentFolder = mStorageManager.getFileById(mFile.getParentId());
+ if (mParentFolder == null) {
+ // should not be necessary
+ mParentFolder = mStorageManager.getFileByPath(OCFile.PATH_SEPARATOR);
+ }
+
+ if (savedInstanceState != null) {
+ mRequestWaitingForBinder = savedInstanceState.getBoolean(KEY_WAITING_FOR_BINDER);
+ } else {
+ mRequestWaitingForBinder = false;
+ }
+
+ createViewPager();
+
+ }
+
+ private void createViewPager() {
+ mPreviewImagePagerAdapter = new PreviewImagePagerAdapter(getSupportFragmentManager(), mParentFolder, mAccount, mStorageManager);
+ mViewPager = (ViewPager) findViewById(R.id.fragmentPager);
+ int position = mPreviewImagePagerAdapter.getFilePosition(mFile);
+ position = (position >= 0) ? position : 0;
+ mViewPager.setAdapter(mPreviewImagePagerAdapter);
+ mViewPager.setOnPageChangeListener(this);
+ mViewPager.setCurrentItem(position);
+ if (position == 0 && !mFile.isDown()) {
+ // this is necessary because mViewPager.setCurrentItem(0) just after setting the adapter does not result in a call to #onPageSelected(0)
+ mRequestWaitingForBinder = true;
+ }
+ }
+
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ mDownloadConnection = new PreviewImageServiceConnection();
+ bindService(new Intent(this, FileDownloader.class), mDownloadConnection, Context.BIND_AUTO_CREATE);
+ mUploadConnection = new PreviewImageServiceConnection();
+ bindService(new Intent(this, FileUploader.class), mUploadConnection, Context.BIND_AUTO_CREATE);
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putBoolean(KEY_WAITING_FOR_BINDER, mRequestWaitingForBinder);
+ }
+
+
+ /** Defines callbacks for service binding, passed to bindService() */
+ private class PreviewImageServiceConnection implements ServiceConnection {
+
+ @Override
+ public void onServiceConnected(ComponentName component, IBinder service) {
+
+ if (component.equals(new ComponentName(PreviewImageActivity.this, FileDownloader.class))) {
+ mDownloaderBinder = (FileDownloaderBinder) service;
+ if (mRequestWaitingForBinder) {
+ mRequestWaitingForBinder = false;
+ Log.d(TAG, "Simulating reselection of current page after connection of download binder");
+ onPageSelected(mViewPager.getCurrentItem());
+ }
+
+ } else if (component.equals(new ComponentName(PreviewImageActivity.this, FileUploader.class))) {
+ Log.d(TAG, "Upload service connected");
+ mUploaderBinder = (FileUploaderBinder) service;
+ } else {
+ return;
+ }
+
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName component) {
+ if (component.equals(new ComponentName(PreviewImageActivity.this, FileDownloader.class))) {
+ Log.d(TAG, "Download service suddenly disconnected");
+ mDownloaderBinder = null;
+ } else if (component.equals(new ComponentName(PreviewImageActivity.this, FileUploader.class))) {
+ Log.d(TAG, "Upload service suddenly disconnected");
+ mUploaderBinder = null;
+ }
+ }
+ };
+
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ if (mDownloadConnection != null) {
+ unbindService(mDownloadConnection);
+ mDownloadConnection = null;
+ }
+ if (mUploadConnection != null) {
+ unbindService(mUploadConnection);
+ mUploadConnection = null;
+ }
+ }
+
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ }
+
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ boolean returnValue = false;
+
+ switch(item.getItemId()){
+ case android.R.id.home:
+ backToDisplayActivity();
+ returnValue = true;
+ break;
+ default:
+ returnValue = super.onOptionsItemSelected(item);
+ }
+
+ return returnValue;
+ }
+
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ //Log.e(TAG, "ACTIVITY, ONRESUME");
+ mDownloadFinishReceiver = new DownloadFinishReceiver();
+ IntentFilter filter = new IntentFilter(FileDownloader.DOWNLOAD_FINISH_MESSAGE);
+ filter.addAction(FileDownloader.DOWNLOAD_ADDED_MESSAGE);
+ registerReceiver(mDownloadFinishReceiver, filter);
+ }
+
+ @Override
+ protected void onPostResume() {
+ //Log.e(TAG, "ACTIVITY, ONPOSTRESUME");
+ super.onPostResume();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ unregisterReceiver(mDownloadFinishReceiver);
+ mDownloadFinishReceiver = null;
+ }
+
+
+ private void backToDisplayActivity() {
+ /*
+ Intent intent = new Intent(this, FileDisplayActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ intent.putExtra(FileDetailFragment.EXTRA_FILE, mFile);
+ intent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, mAccount);
+ startActivity(intent);
+ */
+ finish();
+ }
+
+
+ @Override
+ protected Dialog onCreateDialog(int id) {
+ Dialog dialog = null;
+ switch (id) {
+ case DIALOG_SHORT_WAIT: {
+ ProgressDialog working_dialog = new ProgressDialog(this);
+ working_dialog.setMessage(getResources().getString(
+ R.string.wait_a_moment));
+ working_dialog.setIndeterminate(true);
+ working_dialog.setCancelable(false);
+ dialog = working_dialog;
+ break;
+ }
+ default:
+ dialog = null;
+ }
+ return dialog;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onFileStateChanged() {
+ // nothing to do here!
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public FileDownloaderBinder getFileDownloaderBinder() {
+ return mDownloaderBinder;
+ }
+
+
+ @Override
+ public FileUploaderBinder getFileUploaderBinder() {
+ return mUploaderBinder;
+ }
+
+
+ @Override
+ public void showFragmentWithDetails(OCFile file) {
+ Intent showDetailsIntent = new Intent(this, FileDetailActivity.class);
+ showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, file);
+ showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, AccountUtils.getCurrentOwnCloudAccount(this));
+ showDetailsIntent.putExtra(FileDetailActivity.EXTRA_MODE, FileDetailActivity.MODE_DETAILS);
+ startActivity(showDetailsIntent);
+ int pos = mPreviewImagePagerAdapter.getFilePosition(file);
+ file = mPreviewImagePagerAdapter.getFileAt(pos);
+
+ }
+
+
+ private void requestForDownload(OCFile file) {
+ if (mDownloaderBinder == null) {
+ Log.d(TAG, "requestForDownload called without binder to download service");
+
+ } else if (!mDownloaderBinder.isDownloading(mAccount, file)) {
+ Intent i = new Intent(this, FileDownloader.class);
+ i.putExtra(FileDownloader.EXTRA_ACCOUNT, mAccount);
+ i.putExtra(FileDownloader.EXTRA_FILE, file);
+ startService(i);
+ }
+ }
+
+ /**
+ * This method will be invoked when a new page becomes selected. Animation is not necessarily complete.
+ *
+ * @param Position Position index of the new selected page
+ */
+ @Override
+ public void onPageSelected(int position) {
+ if (mDownloaderBinder == null) {
+ mRequestWaitingForBinder = true;
+
+ } else {
+ OCFile currentFile = mPreviewImagePagerAdapter.getFileAt(position);
+ getSupportActionBar().setTitle(currentFile.getFileName());
+ if (!currentFile.isDown()) {
+ if (!mPreviewImagePagerAdapter.pendingErrorAt(position)) {
+ requestForDownload(currentFile);
+ }
+ }
+ }
+ }
+
+ /**
+ * Called when the scroll state changes. Useful for discovering when the user begins dragging,
+ * when the pager is automatically settling to the current page, or when it is fully stopped/idle.
+ *
+ * @param State The new scroll state (SCROLL_STATE_IDLE, _DRAGGING, _SETTLING
+ */
+ @Override
+ public void onPageScrollStateChanged(int state) {
+ }
+
+ /**
+ * This method will be invoked when the current page is scrolled, either as part of a programmatically
+ * initiated smooth scroll or a user initiated touch scroll.
+ *
+ * @param position Position index of the first page currently being displayed.
+ * Page position+1 will be visible if positionOffset is nonzero.
+ *
+ * @param positionOffset Value from [0, 1) indicating the offset from the page at position.
+ * @param positionOffsetPixels Value in pixels indicating the offset from position.
+ */
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+ }
+
+
+ /**
+ * Class waiting for broadcast events from the {@link FielDownloader} service.
+ *
+ * Updates the UI when a download is started or finished, provided that it is relevant for the
+ * folder displayed in the gallery.
+ */
+ private class DownloadFinishReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String accountName = intent.getStringExtra(FileDownloader.ACCOUNT_NAME);
+ String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
+ if (mAccount.name.equals(accountName) &&
+ downloadedRemotePath != null) {
+
+ OCFile file = mStorageManager.getFileByPath(downloadedRemotePath);
+ int position = mPreviewImagePagerAdapter.getFilePosition(file);
+ boolean downloadWasFine = intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false);
+ //boolean isOffscreen = Math.abs((mViewPager.getCurrentItem() - position)) <= mViewPager.getOffscreenPageLimit();
+
+ if (position >= 0 && intent.getAction().equals(FileDownloader.DOWNLOAD_FINISH_MESSAGE)) {
+ if (downloadWasFine) {
+ mPreviewImagePagerAdapter.updateFile(position, file);
+
+ } else {
+ mPreviewImagePagerAdapter.updateWithDownloadError(position);
+ }
+ mPreviewImagePagerAdapter.notifyDataSetChanged(); // will trigger the creation of new fragments
+
+ } else {
+ Log.d(TAG, "Download finished, but the fragment is offscreen");
+ }
+
+ }
+ removeStickyBroadcast(intent);
+ }
+
+ }
+
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ if (event.getAction() == MotionEvent.ACTION_UP) {
+ toggleFullScreen();
+ }
+ return true;
+ }
+
+
+ private void toggleFullScreen() {
+ ActionBar actionBar = getSupportActionBar();
+ if (mFullScreen) {
+ actionBar.show();
+
+ } else {
+ actionBar.hide();
+
+ }
+ mFullScreen = !mFullScreen;
+ }
+
+
+}
--- /dev/null
+/* ownCloud Android client application
+ * Copyright (C) 2012-2013 ownCloud Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package com.owncloud.android.ui.preview;
+
+import java.io.File;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
+
+
+import android.accounts.Account;
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.BitmapFactory.Options;
+import android.graphics.Point;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.v4.app.FragmentStatePagerAdapter;
+import android.util.Log;
+import android.view.Display;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnTouchListener;
+import android.view.ViewGroup;
+import android.webkit.MimeTypeMap;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.actionbarsherlock.app.SherlockFragment;
+import com.actionbarsherlock.view.Menu;
+import com.actionbarsherlock.view.MenuInflater;
+import com.actionbarsherlock.view.MenuItem;
+import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.network.OwnCloudClientUtils;
+import com.owncloud.android.operations.OnRemoteOperationListener;
+import com.owncloud.android.operations.RemoteOperation;
+import com.owncloud.android.operations.RemoteOperationResult;
+import com.owncloud.android.operations.RemoveFileOperation;
+import com.owncloud.android.ui.fragment.ConfirmationDialogFragment;
+import com.owncloud.android.ui.fragment.FileFragment;
+
+import com.owncloud.android.R;
+import eu.alefzero.webdav.WebdavClient;
+import eu.alefzero.webdav.WebdavUtils;
+
+
+/**
+ * This fragment shows a preview of a downloaded image.
+ *
+ * Trying to get an instance with NULL {@link OCFile} or ownCloud {@link Account} values will produce an {@link IllegalStateException}.
+ *
+ * If the {@link OCFile} passed is not downloaded, an {@link IllegalStateException} is generated on instantiation too.
+ *
+ * @author David A. Velasco
+ */
+public class PreviewImageFragment extends SherlockFragment implements FileFragment,
+ OnRemoteOperationListener,
+ ConfirmationDialogFragment.ConfirmationDialogFragmentListener {
+ public static final String EXTRA_FILE = "FILE";
+ public static final String EXTRA_ACCOUNT = "ACCOUNT";
+
+ private View mView;
+ private OCFile mFile;
+ private Account mAccount;
+ private FileDataStorageManager mStorageManager;
+ private ImageView mImageView;
+ private TextView mMessageView;
+ private ProgressBar mProgressWheel;
+
+ public Bitmap mBitmap = null;
+
+ private Handler mHandler;
+ private RemoteOperation mLastRemoteOperation;
+
+ private static final String TAG = PreviewImageFragment.class.getSimpleName();
+
+ private boolean mIgnoreFirstSavedState;
+
+
+ /**
+ * Creates a fragment to preview an image.
+ *
+ * When 'imageFile' or 'ocAccount' are null
+ *
+ * @param imageFile An {@link OCFile} to preview as an image in the fragment
+ * @param ocAccount An ownCloud account; needed to start downloads
+ * @param ignoreFirstSavedState Flag to work around an unexpected behaviour of {@link FragmentStatePagerAdapter}; TODO better solution
+ */
+ public PreviewImageFragment(OCFile fileToDetail, Account ocAccount, boolean ignoreFirstSavedState) {
+ mFile = fileToDetail;
+ mAccount = ocAccount;
+ mStorageManager = null; // we need a context to init this; the container activity is not available yet at this moment
+ mIgnoreFirstSavedState = ignoreFirstSavedState;
+ }
+
+
+ /**
+ * Creates an empty fragment for image previews.
+ *
+ * MUST BE KEPT: the system uses it when tries to reinstantiate a fragment automatically (for instance, when the device is turned a aside).
+ *
+ * DO NOT CALL IT: an {@link OCFile} and {@link Account} must be provided for a successful construction
+ */
+ public PreviewImageFragment() {
+ mFile = null;
+ mAccount = null;
+ mStorageManager = null;
+ mIgnoreFirstSavedState = false;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mHandler = new Handler();
+ setHasOptionsMenu(true);
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ super.onCreateView(inflater, container, savedInstanceState);
+ mView = inflater.inflate(R.layout.preview_image_fragment, container, false);
+ mImageView = (ImageView)mView.findViewById(R.id.image);
+ mImageView.setVisibility(View.GONE);
+ mView.setOnTouchListener((OnTouchListener)getActivity()); // WATCH OUT THAT CAST
+ mMessageView = (TextView)mView.findViewById(R.id.message);
+ mMessageView.setVisibility(View.GONE);
+ mProgressWheel = (ProgressBar)mView.findViewById(R.id.progressWheel);
+ mProgressWheel.setVisibility(View.VISIBLE);
+ return mView;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ if (!(activity instanceof FileFragment.ContainerActivity))
+ throw new ClassCastException(activity.toString() + " must implement " + FileFragment.ContainerActivity.class.getSimpleName());
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());
+ if (savedInstanceState != null) {
+ if (!mIgnoreFirstSavedState) {
+ mFile = savedInstanceState.getParcelable(PreviewImageFragment.EXTRA_FILE);
+ mAccount = savedInstanceState.getParcelable(PreviewImageFragment.EXTRA_ACCOUNT);
+ } else {
+ mIgnoreFirstSavedState = false;
+ }
+ }
+ if (mFile == null) {
+ throw new IllegalStateException("Instanced with a NULL OCFile");
+ }
+ if (mAccount == null) {
+ throw new IllegalStateException("Instanced with a NULL ownCloud Account");
+ }
+ if (!mFile.isDown()) {
+ throw new IllegalStateException("There is no local file to preview");
+ }
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putParcelable(PreviewImageFragment.EXTRA_FILE, mFile);
+ outState.putParcelable(PreviewImageFragment.EXTRA_ACCOUNT, mAccount);
+ }
+
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ if (mFile != null) {
+ BitmapLoader bl = new BitmapLoader(mImageView, mMessageView, mProgressWheel);
+ bl.execute(new String[]{mFile.getStoragePath()});
+ }
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ super.onCreateOptionsMenu(menu, inflater);
+
+ inflater.inflate(R.menu.file_actions_menu, menu);
+ List<Integer> toHide = new ArrayList<Integer>();
+
+ MenuItem item = null;
+ toHide.add(R.id.action_cancel_download);
+ toHide.add(R.id.action_cancel_upload);
+ toHide.add(R.id.action_download_file);
+ toHide.add(R.id.action_rename_file); // by now
+
+ for (int i : toHide) {
+ item = menu.findItem(i);
+ if (item != null) {
+ item.setVisible(false);
+ item.setEnabled(false);
+ }
+ }
+
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.action_open_file_with: {
+ openFile();
+ return true;
+ }
+ case R.id.action_remove_file: {
+ removeFile();
+ return true;
+ }
+ case R.id.action_see_details: {
+ seeDetails();
+ return true;
+ }
+
+ default:
+ return false;
+ }
+ }
+
+
+ private void seeDetails() {
+ ((FileFragment.ContainerActivity)getActivity()).showFragmentWithDetails(mFile);
+ }
+
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ //Log.e(TAG, "FRAGMENT, ONRESUME");
+ /*
+ mDownloadFinishReceiver = new DownloadFinishReceiver();
+ IntentFilter filter = new IntentFilter(
+ FileDownloader.DOWNLOAD_FINISH_MESSAGE);
+ getActivity().registerReceiver(mDownloadFinishReceiver, filter);
+
+ mUploadFinishReceiver = new UploadFinishReceiver();
+ filter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);
+ getActivity().registerReceiver(mUploadFinishReceiver, filter);
+ */
+
+ }
+
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ /*
+ if (mVideoPreview.getVisibility() == View.VISIBLE) {
+ mSavedPlaybackPosition = mVideoPreview.getCurrentPosition();
+ }*/
+ /*
+ getActivity().unregisterReceiver(mDownloadFinishReceiver);
+ mDownloadFinishReceiver = null;
+
+ getActivity().unregisterReceiver(mUploadFinishReceiver);
+ mUploadFinishReceiver = null;
+ */
+ }
+
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mBitmap != null) {
+ mBitmap.recycle();
+ }
+ }
+
+
+ /**
+ * Opens the previewed image with an external application.
+ *
+ * TODO - improve this; instead of prioritize the actions available for the MIME type in the server,
+ * we should get a list of available apps for MIME tpye in the server and join it with the list of
+ * available apps for the MIME type known from the file extension, to let the user choose
+ */
+ private void openFile() {
+ String storagePath = mFile.getStoragePath();
+ String encodedStoragePath = WebdavUtils.encodePath(storagePath);
+ try {
+ Intent i = new Intent(Intent.ACTION_VIEW);
+ i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mFile.getMimetype());
+ i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ startActivity(i);
+
+ } catch (Throwable t) {
+ Log.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());
+ boolean toastIt = true;
+ String mimeType = "";
+ try {
+ Intent i = new Intent(Intent.ACTION_VIEW);
+ mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(storagePath.substring(storagePath.lastIndexOf('.') + 1));
+ if (mimeType == null || !mimeType.equals(mFile.getMimetype())) {
+ if (mimeType != null) {
+ i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mimeType);
+ } else {
+ // desperate try
+ i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), "*-/*");
+ }
+ i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ startActivity(i);
+ toastIt = false;
+ }
+
+ } catch (IndexOutOfBoundsException e) {
+ Log.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
+
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
+
+ } catch (Throwable th) {
+ Log.e(TAG, "Unexpected problem when opening: " + storagePath, th);
+
+ } finally {
+ if (toastIt) {
+ Toast.makeText(getActivity(), "There is no application to handle file " + mFile.getFileName(), Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ }
+ finish();
+ }
+
+
+ /**
+ * Starts a the removal of the previewed file.
+ *
+ * Shows a confirmation dialog. The action continues in {@link #onConfirmation(String)} , {@link #onNeutral(String)} or {@link #onCancel(String)},
+ * depending upon the user selection in the dialog.
+ */
+ private void removeFile() {
+ ConfirmationDialogFragment confDialog = ConfirmationDialogFragment.newInstance(
+ R.string.confirmation_remove_alert,
+ new String[]{mFile.getFileName()},
+ R.string.confirmation_remove_remote_and_local,
+ R.string.confirmation_remove_local,
+ R.string.common_cancel);
+ confDialog.setOnConfirmationListener(this);
+ confDialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
+ }
+
+
+ /**
+ * Performs the removal of the previewed file, both locally and in the server.
+ */
+ @Override
+ public void onConfirmation(String callerTag) {
+ if (mStorageManager.getFileById(mFile.getFileId()) != null) { // check that the file is still there;
+ mLastRemoteOperation = new RemoveFileOperation( mFile, // TODO we need to review the interface with RemoteOperations, and use OCFile IDs instead of OCFile objects as parameters
+ true,
+ mStorageManager);
+ WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());
+ mLastRemoteOperation.execute(wc, this, mHandler);
+
+ getActivity().showDialog(PreviewImageActivity.DIALOG_SHORT_WAIT);
+ }
+ }
+
+
+ /**
+ * Removes the file from local storage
+ */
+ @Override
+ public void onNeutral(String callerTag) {
+ // TODO this code should be made in a secondary thread,
+ if (mFile.isDown()) { // checks it is still there
+ File f = new File(mFile.getStoragePath());
+ f.delete();
+ mFile.setStoragePath(null);
+ mStorageManager.saveFile(mFile);
+ finish();
+ }
+ }
+
+ /**
+ * User cancelled the removal action.
+ */
+ @Override
+ public void onCancel(String callerTag) {
+ // nothing to do here
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public OCFile getFile(){
+ return mFile;
+ }
+
+ /*
+ /**
+ * Use this method to signal this Activity that it shall update its view.
+ *
+ * @param file : An {@link OCFile}
+ *-/
+ public void updateFileDetails(OCFile file, Account ocAccount) {
+ mFile = file;
+ if (ocAccount != null && (
+ mStorageManager == null ||
+ (mAccount != null && !mAccount.equals(ocAccount))
+ )) {
+ mStorageManager = new FileDataStorageManager(ocAccount, getActivity().getApplicationContext().getContentResolver());
+ }
+ mAccount = ocAccount;
+ updateFileDetails(false);
+ }
+ */
+
+
+ private class BitmapLoader extends AsyncTask<String, Void, Bitmap> {
+
+ /**
+ * Weak reference to the target {@link ImageView} where the bitmap will be loaded into.
+ *
+ * Using a weak reference will avoid memory leaks if the target ImageView is retired from memory before the load finishes.
+ */
+ private final WeakReference<ImageView> mImageViewRef;
+
+ /**
+ * Weak reference to the target {@link TextView} where error messages will be written.
+ *
+ * Using a weak reference will avoid memory leaks if the target ImageView is retired from memory before the load finishes.
+ */
+ private final WeakReference<TextView> mMessageViewRef;
+
+
+ /**
+ * Weak reference to the target {@link Progressbar} shown while the load is in progress.
+ *
+ * Using a weak reference will avoid memory leaks if the target ImageView is retired from memory before the load finishes.
+ */
+ private final WeakReference<ProgressBar> mProgressWheelRef;
+
+
+ /**
+ * Error message to show when a load fails
+ */
+ private int mErrorMessageId;
+
+
+ /**
+ * Constructor.
+ *
+ * @param imageView Target {@link ImageView} where the bitmap will be loaded into.
+ */
+ public BitmapLoader(ImageView imageView, TextView messageView, ProgressBar progressWheel) {
+ mImageViewRef = new WeakReference<ImageView>(imageView);
+ mMessageViewRef = new WeakReference<TextView>(messageView);
+ mProgressWheelRef = new WeakReference<ProgressBar>(progressWheel);
+ }
+
+
+ @SuppressWarnings("deprecation")
+ @SuppressLint({ "NewApi", "NewApi", "NewApi" }) // to avoid Lint errors since Android SDK r20
+ @Override
+ protected Bitmap doInBackground(String... params) {
+ Bitmap result = null;
+ if (params.length != 1) return result;
+ String storagePath = params[0];
+ try {
+ // set desired options that will affect the size of the bitmap
+ BitmapFactory.Options options = new Options();
+ options.inScaled = true;
+ options.inPurgeable = true;
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
+ options.inPreferQualityOverSpeed = false;
+ }
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
+ options.inMutable = false;
+ }
+ // make a false load of the bitmap - just to be able to read outWidth, outHeight and outMimeType
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeFile(storagePath, options);
+
+ int width = options.outWidth;
+ int height = options.outHeight;
+ int scale = 1;
+
+ Display display = getActivity().getWindowManager().getDefaultDisplay();
+ Point size = new Point();
+ int screenWidth;
+ int screenHeight;
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB_MR2) {
+ display.getSize(size);
+ screenWidth = size.x;
+ screenHeight = size.y;
+ } else {
+ screenWidth = display.getWidth();
+ screenHeight = display.getHeight();
+ }
+
+ if (width > screenWidth) {
+ // second try to scale down the image , this time depending upon the screen size
+ scale = (int) Math.floor((float)width / screenWidth);
+ }
+ if (height > screenHeight) {
+ scale = Math.max(scale, (int) Math.floor((float)height / screenHeight));
+ }
+ options.inSampleSize = scale;
+
+ // really load the bitmap
+ options.inJustDecodeBounds = false; // the next decodeFile call will be real
+ result = BitmapFactory.decodeFile(storagePath, options);
+ //Log.d(TAG, "Image loaded - width: " + options.outWidth + ", loaded height: " + options.outHeight);
+
+ if (result == null) {
+ mErrorMessageId = R.string.preview_image_error_unknown_format;
+ Log.e(TAG, "File could not be loaded as a bitmap: " + storagePath);
+ }
+
+ } catch (OutOfMemoryError e) {
+ mErrorMessageId = R.string.preview_image_error_unknown_format;
+ Log.e(TAG, "Out of memory occured for file " + storagePath, e);
+
+ } catch (NoSuchFieldError e) {
+ mErrorMessageId = R.string.common_error_unknown;
+ Log.e(TAG, "Error from access to unexisting field despite protection; file " + storagePath, e);
+
+ } catch (Throwable t) {
+ mErrorMessageId = R.string.common_error_unknown;
+ Log.e(TAG, "Unexpected error loading " + mFile.getStoragePath(), t);
+
+ }
+ return result;
+ }
+
+ @Override
+ protected void onPostExecute(Bitmap result) {
+ hideProgressWheel();
+ if (result != null) {
+ showLoadedImage(result);
+ } else {
+ showErrorMessage();
+ }
+ }
+
+ private void showLoadedImage(Bitmap result) {
+ if (mImageViewRef != null) {
+ final ImageView imageView = mImageViewRef.get();
+ if (imageView != null) {
+ imageView.setImageBitmap(result);
+ imageView.setVisibility(View.VISIBLE);
+ mBitmap = result;
+ } // else , silently finish, the fragment was destroyed
+ }
+ if (mMessageViewRef != null) {
+ final TextView messageView = mMessageViewRef.get();
+ if (messageView != null) {
+ messageView.setVisibility(View.GONE);
+ } // else , silently finish, the fragment was destroyed
+ }
+ }
+
+ private void showErrorMessage() {
+ if (mImageViewRef != null) {
+ final ImageView imageView = mImageViewRef.get();
+ if (imageView != null) {
+ // shows the default error icon
+ imageView.setVisibility(View.VISIBLE);
+ } // else , silently finish, the fragment was destroyed
+ }
+ if (mMessageViewRef != null) {
+ final TextView messageView = mMessageViewRef.get();
+ if (messageView != null) {
+ messageView.setText(mErrorMessageId);
+ messageView.setVisibility(View.VISIBLE);
+ } // else , silently finish, the fragment was destroyed
+ }
+ }
+
+ private void hideProgressWheel() {
+ if (mProgressWheelRef != null) {
+ final ProgressBar progressWheel = mProgressWheelRef.get();
+ if (progressWheel != null) {
+ progressWheel.setVisibility(View.GONE);
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Helper method to test if an {@link OCFile} can be passed to a {@link PreviewImageFragment} to be previewed.
+ *
+ * @param file File to test if can be previewed.
+ * @return 'True' if the file can be handled by the fragment.
+ */
+ public static boolean canBePreviewed(OCFile file) {
+ return (file != null && file.isImage());
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
+ if (operation.equals(mLastRemoteOperation) && operation instanceof RemoveFileOperation) {
+ onRemoveFileOperationFinish((RemoveFileOperation)operation, result);
+ }
+ }
+
+ private void onRemoveFileOperationFinish(RemoveFileOperation operation, RemoteOperationResult result) {
+ getActivity().dismissDialog(PreviewImageActivity.DIALOG_SHORT_WAIT);
+
+ if (result.isSuccess()) {
+ Toast msg = Toast.makeText(getActivity().getApplicationContext(), R.string.remove_success_msg, Toast.LENGTH_LONG);
+ msg.show();
+ finish();
+
+ } else {
+ Toast msg = Toast.makeText(getActivity(), R.string.remove_fail_msg, Toast.LENGTH_LONG);
+ msg.show();
+ if (result.isSslRecoverableException()) {
+ // TODO show the SSL warning dialog
+ }
+ }
+ }
+
+ /**
+ * Finishes the preview
+ */
+ private void finish() {
+ Activity container = getActivity();
+ container.finish();
+ }
+
+
+}
--- /dev/null
+/* ownCloud Android client application
+ * Copyright (C) 2012-2013 ownCloud Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package com.owncloud.android.ui.preview;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.Vector;
+
+import android.accounts.Account;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentStatePagerAdapter;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v4.view.PagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.owncloud.android.datamodel.DataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.ui.fragment.FileFragment;
+
+/**
+ * Adapter class that provides Fragment instances
+ *
+ * @author David A. Velasco
+ */
+//public class PreviewImagePagerAdapter extends PagerAdapter {
+public class PreviewImagePagerAdapter extends FragmentStatePagerAdapter {
+
+ private static final String TAG = PreviewImagePagerAdapter.class.getSimpleName();
+
+ private Vector<OCFile> mImageFiles;
+ private Account mAccount;
+ private Set<Object> mObsoleteFragments;
+ private Set<Integer> mObsoletePositions;
+ private Set<Integer> mDownloadErrors;
+ private DataStorageManager mStorageManager;
+
+ private Map<Integer, FileFragment> mCachedFragments;
+
+ /*
+ private final FragmentManager mFragmentManager;
+ private FragmentTransaction mCurTransaction = null;
+ private ArrayList<Fragment.SavedState> mSavedState = new ArrayList<Fragment.SavedState>();
+ private ArrayList<Fragment> mFragments = new ArrayList<Fragment>();
+ private Fragment mCurrentPrimaryItem = null;
+ */
+
+ /**
+ * Constructor.
+ *
+ * @param fragmentManager {@link FragmentManager} instance that will handle the {@link Fragment}s provided by the adapter.
+ * @param parentFolder Folder where images will be searched for.
+ * @param storageManager Bridge to database.
+ */
+ public PreviewImagePagerAdapter(FragmentManager fragmentManager, OCFile parentFolder, Account account, DataStorageManager storageManager) {
+ super(fragmentManager);
+
+ if (fragmentManager == null) {
+ throw new IllegalArgumentException("NULL FragmentManager instance");
+ }
+ if (parentFolder == null) {
+ throw new IllegalArgumentException("NULL parent folder");
+ }
+ if (storageManager == null) {
+ throw new IllegalArgumentException("NULL storage manager");
+ }
+
+ mAccount = account;
+ mStorageManager = storageManager;
+ mImageFiles = mStorageManager.getDirectoryImages(parentFolder);
+ mObsoleteFragments = new HashSet<Object>();
+ mObsoletePositions = new HashSet<Integer>();
+ mDownloadErrors = new HashSet<Integer>();
+ //mFragmentManager = fragmentManager;
+ mCachedFragments = new HashMap<Integer, FileFragment>();
+ }
+
+
+ /**
+ * Returns the image files handled by the adapter.
+ *
+ * @return A vector with the image files handled by the adapter.
+ */
+ protected OCFile getFileAt(int position) {
+ return mImageFiles.get(position);
+ }
+
+
+ public Fragment getItem(int i) {
+ OCFile file = mImageFiles.get(i);
+ Fragment fragment = null;
+ if (file.isDown()) {
+ fragment = new PreviewImageFragment(file, mAccount, mObsoletePositions.contains(Integer.valueOf(i)));
+
+ } else if (mDownloadErrors.contains(Integer.valueOf(i))) {
+ fragment = new FileDownloadFragment(file, mAccount, true);
+ ((FileDownloadFragment)fragment).setError(true);
+ mDownloadErrors.remove(Integer.valueOf(i));
+
+ } else {
+ fragment = new FileDownloadFragment(file, mAccount, mObsoletePositions.contains(Integer.valueOf(i)));
+ }
+ mObsoletePositions.remove(Integer.valueOf(i));
+ return fragment;
+ }
+
+ public int getFilePosition(OCFile file) {
+ return mImageFiles.indexOf(file);
+ }
+
+ @Override
+ public int getCount() {
+ return mImageFiles.size();
+ }
+
+ @Override
+ public CharSequence getPageTitle(int position) {
+ return mImageFiles.get(position).getFileName();
+ }
+
+
+ public void updateFile(int position, OCFile file) {
+ FileFragment fragmentToUpdate = mCachedFragments.get(Integer.valueOf(position));
+ if (fragmentToUpdate != null) {
+ mObsoleteFragments.add(fragmentToUpdate);
+ }
+ mObsoletePositions.add(Integer.valueOf(position));
+ mImageFiles.set(position, file);
+ }
+
+
+ public void updateWithDownloadError(int position) {
+ FileFragment fragmentToUpdate = mCachedFragments.get(Integer.valueOf(position));
+ if (fragmentToUpdate != null) {
+ mObsoleteFragments.add(fragmentToUpdate);
+ }
+ mDownloadErrors.add(Integer.valueOf(position));
+ }
+
+ public void clearErrorAt(int position) {
+ FileFragment fragmentToUpdate = mCachedFragments.get(Integer.valueOf(position));
+ if (fragmentToUpdate != null) {
+ mObsoleteFragments.add(fragmentToUpdate);
+ }
+ mDownloadErrors.remove(Integer.valueOf(position));
+ }
+
+
+ @Override
+ public int getItemPosition(Object object) {
+ if (mObsoleteFragments.contains(object)) {
+ mObsoleteFragments.remove(object);
+ return POSITION_NONE;
+ }
+ return super.getItemPosition(object);
+ }
+
+
+ @Override
+ public Object instantiateItem(ViewGroup container, int position) {
+ Object fragment = super.instantiateItem(container, position);
+ mCachedFragments.put(Integer.valueOf(position), (FileFragment)fragment);
+ return fragment;
+ }
+
+ @Override
+ public void destroyItem(ViewGroup container, int position, Object object) {
+ mCachedFragments.remove(Integer.valueOf(position));
+ super.destroyItem(container, position, object);
+ }
+
+
+ public boolean pendingErrorAt(int position) {
+ return mDownloadErrors.contains(Integer.valueOf(position));
+ }
+
+
+
+ /* -*
+ * Called when a change in the shown pages is going to start being made.
+ *
+ * @param container The containing View which is displaying this adapter's page views.
+ *- /
+ @Override
+ public void startUpdate(ViewGroup container) {
+ Log.e(TAG, "** startUpdate");
+ }
+
+ @Override
+ public Object instantiateItem(ViewGroup container, int position) {
+ Log.e(TAG, "** instantiateItem " + position);
+
+ if (mFragments.size() > position) {
+ Fragment fragment = mFragments.get(position);
+ if (fragment != null) {
+ Log.e(TAG, "** \t returning cached item");
+ return fragment;
+ }
+ }
+
+ if (mCurTransaction == null) {
+ mCurTransaction = mFragmentManager.beginTransaction();
+ }
+
+ Fragment fragment = getItem(position);
+ if (mSavedState.size() > position) {
+ Fragment.SavedState savedState = mSavedState.get(position);
+ if (savedState != null) {
+ // TODO WATCH OUT:
+ // * The Fragment must currently be attached to the FragmentManager.
+ // * A new Fragment created using this saved state must be the same class type as the Fragment it was created from.
+ // * The saved state can not contain dependencies on other fragments -- that is it can't use putFragment(Bundle, String, Fragment)
+ // to store a fragment reference
+ fragment.setInitialSavedState(savedState);
+ }
+ }
+ while (mFragments.size() <= position) {
+ mFragments.add(null);
+ }
+ fragment.setMenuVisibility(false);
+ mFragments.set(position, fragment);
+ //Log.e(TAG, "** \t adding fragment at position " + position + ", containerId " + container.getId());
+ mCurTransaction.add(container.getId(), fragment);
+
+ return fragment;
+ }
+
+ @Override
+ public void destroyItem(ViewGroup container, int position, Object object) {
+ Log.e(TAG, "** destroyItem " + position);
+ Fragment fragment = (Fragment)object;
+
+ if (mCurTransaction == null) {
+ mCurTransaction = mFragmentManager.beginTransaction();
+ }
+ Log.e(TAG, "** \t removing fragment at position " + position);
+ while (mSavedState.size() <= position) {
+ mSavedState.add(null);
+ }
+ mSavedState.set(position, mFragmentManager.saveFragmentInstanceState(fragment));
+ mFragments.set(position, null);
+
+ mCurTransaction.remove(fragment);
+ }
+
+ @Override
+ public void setPrimaryItem(ViewGroup container, int position, Object object) {
+ Fragment fragment = (Fragment)object;
+ if (fragment != mCurrentPrimaryItem) {
+ if (mCurrentPrimaryItem != null) {
+ mCurrentPrimaryItem.setMenuVisibility(false);
+ }
+ if (fragment != null) {
+ fragment.setMenuVisibility(true);
+ }
+ mCurrentPrimaryItem = fragment;
+ }
+ }
+
+ @Override
+ public void finishUpdate(ViewGroup container) {
+ Log.e(TAG, "** finishUpdate (start)");
+ if (mCurTransaction != null) {
+ mCurTransaction.commitAllowingStateLoss();
+ mCurTransaction = null;
+ mFragmentManager.executePendingTransactions();
+ }
+ Log.e(TAG, "** finishUpdate (end)");
+ }
+
+ @Override
+ public boolean isViewFromObject(View view, Object object) {
+ return ((Fragment)object).getView() == view;
+ }
+
+ @Override
+ public Parcelable saveState() {
+ Bundle state = null;
+ if (mSavedState.size() > 0) {
+ state = new Bundle();
+ Fragment.SavedState[] savedStates = new Fragment.SavedState[mSavedState.size()];
+ mSavedState.toArray(savedStates);
+ state.putParcelableArray("states", savedStates);
+ }
+ for (int i=0; i<mFragments.size(); i++) {
+ Fragment fragment = mFragments.get(i);
+ if (fragment != null) {
+ if (state == null) {
+ state = new Bundle();
+ }
+ String key = "f" + i;
+ mFragmentManager.putFragment(state, key, fragment);
+ }
+ }
+ return state;
+ }
+
+ @Override
+ public void restoreState(Parcelable state, ClassLoader loader) {
+ if (state != null) {
+ Bundle bundle = (Bundle)state;
+ bundle.setClassLoader(loader);
+ Parcelable[] states = bundle.getParcelableArray("states");
+ mSavedState.clear();
+ mFragments.clear();
+ if (states != null) {
+ for (int i=0; i<states.length; i++) {
+ mSavedState.add((Fragment.SavedState)states[i]);
+ }
+ }
+ Iterable<String> keys = bundle.keySet();
+ for (String key: keys) {
+ if (key.startsWith("f")) {
+ int index = Integer.parseInt(key.substring(1));
+ Fragment f = mFragmentManager.getFragment(bundle, key);
+ if (f != null) {
+ while (mFragments.size() <= index) {
+ mFragments.add(null);
+ }
+ f.setMenuVisibility(false);
+ mFragments.set(index, f);
+ } else {
+ Log.w(TAG, "Bad fragment at key " + key);
+ }
+ }
+ }
+ }
+ }
+ */
+}
--- /dev/null
+/* ownCloud Android client application
+ * Copyright (C) 2012-2013 ownCloud Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package com.owncloud.android.ui.preview;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import android.accounts.Account;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnCompletionListener;
+import android.media.MediaPlayer.OnErrorListener;
+import android.media.MediaPlayer.OnPreparedListener;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.support.v4.app.FragmentTransaction;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnTouchListener;
+import android.view.ViewGroup;
+import android.webkit.MimeTypeMap;
+import android.widget.ImageView;
+import android.widget.Toast;
+import android.widget.VideoView;
+
+import com.actionbarsherlock.app.SherlockFragment;
+import com.actionbarsherlock.view.Menu;
+import com.actionbarsherlock.view.MenuInflater;
+import com.actionbarsherlock.view.MenuItem;
+import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.media.MediaControlView;
+import com.owncloud.android.media.MediaService;
+import com.owncloud.android.media.MediaServiceBinder;
+import com.owncloud.android.network.OwnCloudClientUtils;
+import com.owncloud.android.operations.OnRemoteOperationListener;
+import com.owncloud.android.operations.RemoteOperation;
+import com.owncloud.android.operations.RemoteOperationResult;
+import com.owncloud.android.operations.RemoveFileOperation;
+import com.owncloud.android.ui.activity.FileDetailActivity;
+import com.owncloud.android.ui.activity.FileDisplayActivity;
+import com.owncloud.android.ui.fragment.ConfirmationDialogFragment;
+import com.owncloud.android.ui.fragment.FileDetailFragment;
+import com.owncloud.android.ui.fragment.FileFragment;
+
+import com.owncloud.android.R;
+import eu.alefzero.webdav.WebdavClient;
+import eu.alefzero.webdav.WebdavUtils;
+
+/**
+ * This fragment shows a preview of a downloaded media file (audio or video).
+ *
+ * Trying to get an instance with NULL {@link OCFile} or ownCloud {@link Account} values will produce an {@link IllegalStateException}.
+ *
+ * By now, if the {@link OCFile} passed is not downloaded, an {@link IllegalStateException} is generated on instantiation too.
+ *
+ * @author David A. Velasco
+ */
+public class PreviewMediaFragment extends SherlockFragment implements
+ OnTouchListener , FileFragment,
+ ConfirmationDialogFragment.ConfirmationDialogFragmentListener, OnRemoteOperationListener {
+
+ public static final String EXTRA_FILE = "FILE";
+ public static final String EXTRA_ACCOUNT = "ACCOUNT";
+ private static final String EXTRA_PLAY_POSITION = "PLAY_POSITION";
+ private static final String EXTRA_PLAYING = "PLAYING";
+
+ private View mView;
+ private OCFile mFile;
+ private Account mAccount;
+ private FileDataStorageManager mStorageManager;
+ private ImageView mImagePreview;
+ private VideoView mVideoPreview;
+ private int mSavedPlaybackPosition;
+
+ private Handler mHandler;
+ private RemoteOperation mLastRemoteOperation;
+
+ private MediaServiceBinder mMediaServiceBinder = null;
+ private MediaControlView mMediaController = null;
+ private MediaServiceConnection mMediaServiceConnection = null;
+ private VideoHelper mVideoHelper;
+ private boolean mAutoplay;
+
+ private static final String TAG = PreviewMediaFragment.class.getSimpleName();
+
+
+ /**
+ * Creates a fragment to preview a file.
+ *
+ * When 'fileToDetail' or 'ocAccount' are null
+ *
+ * @param fileToDetail An {@link OCFile} to preview in the fragment
+ * @param ocAccount An ownCloud account; needed to start downloads
+ */
+ public PreviewMediaFragment(OCFile fileToDetail, Account ocAccount) {
+ mFile = fileToDetail;
+ mAccount = ocAccount;
+ mSavedPlaybackPosition = 0;
+ mStorageManager = null; // we need a context to init this; the container activity is not available yet at this moment
+ mAutoplay = true;
+ }
+
+
+ /**
+ * Creates an empty fragment for previews.
+ *
+ * MUST BE KEPT: the system uses it when tries to reinstantiate a fragment automatically (for instance, when the device is turned a aside).
+ *
+ * DO NOT CALL IT: an {@link OCFile} and {@link Account} must be provided for a successful construction
+ */
+ public PreviewMediaFragment() {
+ mFile = null;
+ mAccount = null;
+ mSavedPlaybackPosition = 0;
+ mStorageManager = null;
+ mAutoplay = true;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mHandler = new Handler();
+ setHasOptionsMenu(true);
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ super.onCreateView(inflater, container, savedInstanceState);
+
+ mView = inflater.inflate(R.layout.file_preview, container, false);
+
+ mImagePreview = (ImageView)mView.findViewById(R.id.image_preview);
+ mVideoPreview = (VideoView)mView.findViewById(R.id.video_preview);
+ mVideoPreview.setOnTouchListener(this);
+
+ mMediaController = (MediaControlView)mView.findViewById(R.id.media_controller);
+
+ return mView;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ if (!(activity instanceof FileFragment.ContainerActivity))
+ throw new ClassCastException(activity.toString() + " must implement " + FileFragment.ContainerActivity.class.getSimpleName());
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ mStorageManager = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());
+ if (savedInstanceState != null) {
+ mFile = savedInstanceState.getParcelable(PreviewMediaFragment.EXTRA_FILE);
+ mAccount = savedInstanceState.getParcelable(PreviewMediaFragment.EXTRA_ACCOUNT);
+ mSavedPlaybackPosition = savedInstanceState.getInt(PreviewMediaFragment.EXTRA_PLAY_POSITION);
+ mAutoplay = savedInstanceState.getBoolean(PreviewMediaFragment.EXTRA_PLAYING);
+
+ }
+ if (mFile == null) {
+ throw new IllegalStateException("Instanced with a NULL OCFile");
+ }
+ if (mAccount == null) {
+ throw new IllegalStateException("Instanced with a NULL ownCloud Account");
+ }
+ if (!mFile.isDown()) {
+ throw new IllegalStateException("There is no local file to preview");
+ }
+ if (mFile.isVideo()) {
+ mVideoPreview.setVisibility(View.VISIBLE);
+ mImagePreview.setVisibility(View.GONE);
+ prepareVideo();
+
+ } else {
+ mVideoPreview.setVisibility(View.GONE);
+ mImagePreview.setVisibility(View.VISIBLE);
+ }
+
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putParcelable(PreviewMediaFragment.EXTRA_FILE, mFile);
+ outState.putParcelable(PreviewMediaFragment.EXTRA_ACCOUNT, mAccount);
+
+ if (mFile.isVideo()) {
+ mSavedPlaybackPosition = mVideoPreview.getCurrentPosition();
+ mAutoplay = mVideoPreview.isPlaying();
+ outState.putInt(PreviewMediaFragment.EXTRA_PLAY_POSITION , mSavedPlaybackPosition);
+ outState.putBoolean(PreviewMediaFragment.EXTRA_PLAYING , mAutoplay);
+ } else {
+ outState.putInt(PreviewMediaFragment.EXTRA_PLAY_POSITION , mMediaServiceBinder.getCurrentPosition());
+ outState.putBoolean(PreviewMediaFragment.EXTRA_PLAYING , mMediaServiceBinder.isPlaying());
+ }
+ }
+
+
+ @Override
+ public void onStart() {
+ super.onStart();
+
+ if (mFile != null) {
+ if (mFile.isAudio()) {
+ bindMediaService();
+
+ } else if (mFile.isVideo()) {
+ stopAudio();
+ playVideo();
+ }
+ }
+ }
+
+
+ private void stopAudio() {
+ Intent i = new Intent(getSherlockActivity(), MediaService.class);
+ i.setAction(MediaService.ACTION_STOP_ALL);
+ getSherlockActivity().startService(i);
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ super.onCreateOptionsMenu(menu, inflater);
+
+ inflater.inflate(R.menu.file_actions_menu, menu);
+ List<Integer> toHide = new ArrayList<Integer>();
+
+ MenuItem item = null;
+ toHide.add(R.id.action_cancel_download);
+ toHide.add(R.id.action_cancel_upload);
+ toHide.add(R.id.action_download_file);
+ toHide.add(R.id.action_rename_file); // by now
+
+ for (int i : toHide) {
+ item = menu.findItem(i);
+ if (item != null) {
+ item.setVisible(false);
+ item.setEnabled(false);
+ }
+ }
+
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.action_open_file_with: {
+ openFile();
+ return true;
+ }
+ case R.id.action_remove_file: {
+ removeFile();
+ return true;
+ }
+ case R.id.action_see_details: {
+ seeDetails();
+ return true;
+ }
+
+ default:
+ return false;
+ }
+ }
+
+
+ private void seeDetails() {
+ stopPreview(false);
+ ((FileFragment.ContainerActivity)getActivity()).showFragmentWithDetails(mFile);
+ }
+
+
+ private void prepareVideo() {
+ // create helper to get more control on the playback
+ mVideoHelper = new VideoHelper();
+ mVideoPreview.setOnPreparedListener(mVideoHelper);
+ mVideoPreview.setOnCompletionListener(mVideoHelper);
+ mVideoPreview.setOnErrorListener(mVideoHelper);
+ }
+
+ private void playVideo() {
+ // create and prepare control panel for the user
+ mMediaController.setMediaPlayer(mVideoPreview);
+
+ // load the video file in the video player ; when done, VideoHelper#onPrepared() will be called
+ mVideoPreview.setVideoPath(mFile.getStoragePath());
+ }
+
+
+ private class VideoHelper implements OnCompletionListener, OnPreparedListener, OnErrorListener {
+
+ /**
+ * Called when the file is ready to be played.
+ *
+ * Just starts the playback.
+ *
+ * @param mp {@link MediaPlayer} instance performing the playback.
+ */
+ @Override
+ public void onPrepared(MediaPlayer vp) {
+ Log.e(TAG, "onPrepared");
+ mVideoPreview.seekTo(mSavedPlaybackPosition);
+ if (mAutoplay) {
+ mVideoPreview.start();
+ }
+ mMediaController.setEnabled(true);
+ mMediaController.updatePausePlay();
+ }
+
+
+ /**
+ * Called when the file is finished playing.
+ *
+ * Finishes the activity.
+ *
+ * @param mp {@link MediaPlayer} instance performing the playback.
+ */
+ @Override
+ public void onCompletion(MediaPlayer mp) {
+ Log.e(TAG, "completed");
+ if (mp != null) {
+ mVideoPreview.seekTo(0);
+ // next lines are necessary to work around undesired video loops
+ if (Build.VERSION.SDK_INT == Build.VERSION_CODES.GINGERBREAD) {
+ mVideoPreview.pause();
+
+ } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.GINGERBREAD_MR1) {
+ // mVideePreview.pause() is not enough
+
+ mMediaController.setEnabled(false);
+ mVideoPreview.stopPlayback();
+ mAutoplay = false;
+ mSavedPlaybackPosition = 0;
+ mVideoPreview.setVideoPath(mFile.getStoragePath());
+ }
+ } // else : called from onError()
+ mMediaController.updatePausePlay();
+ }
+
+
+ /**
+ * Called when an error in playback occurs.
+ *
+ * @param mp {@link MediaPlayer} instance performing the playback.
+ * @param what Type of error
+ * @param extra Extra code specific to the error
+ */
+ @Override
+ public boolean onError(MediaPlayer mp, int what, int extra) {
+ if (mVideoPreview.getWindowToken() != null) {
+ String message = MediaService.getMessageForMediaError(getActivity(), what, extra);
+ new AlertDialog.Builder(getActivity())
+ .setMessage(message)
+ .setPositiveButton(android.R.string.VideoView_error_button,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+ dialog.dismiss();
+ VideoHelper.this.onCompletion(null);
+ }
+ })
+ .setCancelable(false)
+ .show();
+ }
+ return true;
+ }
+
+ }
+
+
+ @Override
+ public void onStop() {
+ super.onStop();
+
+ if (mMediaServiceConnection != null) {
+ Log.d(TAG, "Unbinding from MediaService ...");
+ if (mMediaServiceBinder != null && mMediaController != null) {
+ mMediaServiceBinder.unregisterMediaController(mMediaController);
+ }
+ getActivity().unbindService(mMediaServiceConnection);
+ mMediaServiceConnection = null;
+ mMediaServiceBinder = null;
+ }
+ }
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ if (event.getAction() == MotionEvent.ACTION_DOWN && v == mVideoPreview) {
+ startFullScreenVideo();
+ return true;
+ }
+ return false;
+ }
+
+
+ private void startFullScreenVideo() {
+ Intent i = new Intent(getActivity(), PreviewVideoActivity.class);
+ i.putExtra(PreviewVideoActivity.EXTRA_ACCOUNT, mAccount);
+ i.putExtra(PreviewVideoActivity.EXTRA_FILE, mFile);
+ i.putExtra(PreviewVideoActivity.EXTRA_AUTOPLAY, mVideoPreview.isPlaying());
+ mVideoPreview.pause();
+ i.putExtra(PreviewVideoActivity.EXTRA_START_POSITION, mVideoPreview.getCurrentPosition());
+ startActivityForResult(i, 0);
+ }
+
+
+ @Override
+ public void onActivityResult (int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (resultCode == Activity.RESULT_OK) {
+ mSavedPlaybackPosition = data.getExtras().getInt(PreviewVideoActivity.EXTRA_START_POSITION);
+ mAutoplay = data.getExtras().getBoolean(PreviewVideoActivity.EXTRA_AUTOPLAY);
+ }
+ }
+
+
+ private void playAudio() {
+ if (!mMediaServiceBinder.isPlaying(mFile)) {
+ Log.d(TAG, "starting playback of " + mFile.getStoragePath());
+ mMediaServiceBinder.start(mAccount, mFile, mAutoplay, mSavedPlaybackPosition);
+
+ } else {
+ if (!mMediaServiceBinder.isPlaying() && mAutoplay) {
+ mMediaServiceBinder.start();
+ mMediaController.updatePausePlay();
+ }
+ }
+ }
+
+
+ private void bindMediaService() {
+ Log.d(TAG, "Binding to MediaService...");
+ if (mMediaServiceConnection == null) {
+ mMediaServiceConnection = new MediaServiceConnection();
+ }
+ getActivity().bindService( new Intent(getActivity(),
+ MediaService.class),
+ mMediaServiceConnection,
+ Context.BIND_AUTO_CREATE);
+ // follow the flow in MediaServiceConnection#onServiceConnected(...)
+ }
+
+ /** Defines callbacks for service binding, passed to bindService() */
+ private class MediaServiceConnection implements ServiceConnection {
+
+ @Override
+ public void onServiceConnected(ComponentName component, IBinder service) {
+ if (component.equals(new ComponentName(getActivity(), MediaService.class))) {
+ Log.d(TAG, "Media service connected");
+ mMediaServiceBinder = (MediaServiceBinder) service;
+ if (mMediaServiceBinder != null) {
+ prepareMediaController();
+ playAudio(); // do not wait for the touch of nobody to play audio
+
+ Log.d(TAG, "Successfully bound to MediaService, MediaController ready");
+
+ } else {
+ Log.e(TAG, "Unexpected response from MediaService while binding");
+ }
+ }
+ }
+
+ private void prepareMediaController() {
+ mMediaServiceBinder.registerMediaController(mMediaController);
+ if (mMediaController != null) {
+ mMediaController.setMediaPlayer(mMediaServiceBinder);
+ mMediaController.setEnabled(true);
+ mMediaController.updatePausePlay();
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName component) {
+ if (component.equals(new ComponentName(getActivity(), MediaService.class))) {
+ Log.e(TAG, "Media service suddenly disconnected");
+ if (mMediaController != null) {
+ mMediaController.setMediaPlayer(null);
+ } else {
+ Toast.makeText(getActivity(), "No media controller to release when disconnected from media service", Toast.LENGTH_SHORT).show();
+ }
+ mMediaServiceBinder = null;
+ mMediaServiceConnection = null;
+ }
+ }
+ }
+
+
+
+ /**
+ * Opens the previewed file with an external application.
+ *
+ * TODO - improve this; instead of prioritize the actions available for the MIME type in the server,
+ * we should get a list of available apps for MIME tpye in the server and join it with the list of
+ * available apps for the MIME type known from the file extension, to let the user choose
+ */
+ private void openFile() {
+ stopPreview(true);
+ String storagePath = mFile.getStoragePath();
+ String encodedStoragePath = WebdavUtils.encodePath(storagePath);
+ try {
+ Intent i = new Intent(Intent.ACTION_VIEW);
+ i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mFile.getMimetype());
+ i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ startActivity(i);
+
+ } catch (Throwable t) {
+ Log.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mFile.getMimetype());
+ boolean toastIt = true;
+ String mimeType = "";
+ try {
+ Intent i = new Intent(Intent.ACTION_VIEW);
+ mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(storagePath.substring(storagePath.lastIndexOf('.') + 1));
+ if (mimeType == null || !mimeType.equals(mFile.getMimetype())) {
+ if (mimeType != null) {
+ i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mimeType);
+ } else {
+ // desperate try
+ i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), "*-/*");
+ }
+ i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ startActivity(i);
+ toastIt = false;
+ }
+
+ } catch (IndexOutOfBoundsException e) {
+ Log.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
+
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
+
+ } catch (Throwable th) {
+ Log.e(TAG, "Unexpected problem when opening: " + storagePath, th);
+
+ } finally {
+ if (toastIt) {
+ Toast.makeText(getActivity(), "There is no application to handle file " + mFile.getFileName(), Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ }
+ finish();
+ }
+
+ /**
+ * Starts a the removal of the previewed file.
+ *
+ * Shows a confirmation dialog. The action continues in {@link #onConfirmation(String)} , {@link #onNeutral(String)} or {@link #onCancel(String)},
+ * depending upon the user selection in the dialog.
+ */
+ private void removeFile() {
+ ConfirmationDialogFragment confDialog = ConfirmationDialogFragment.newInstance(
+ R.string.confirmation_remove_alert,
+ new String[]{mFile.getFileName()},
+ R.string.confirmation_remove_remote_and_local,
+ R.string.confirmation_remove_local,
+ R.string.common_cancel);
+ confDialog.setOnConfirmationListener(this);
+ confDialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
+ }
+
+
+ /**
+ * Performs the removal of the previewed file, both locally and in the server.
+ */
+ @Override
+ public void onConfirmation(String callerTag) {
+ if (mStorageManager.getFileById(mFile.getFileId()) != null) { // check that the file is still there;
+ stopPreview(true);
+ mLastRemoteOperation = new RemoveFileOperation( mFile, // TODO we need to review the interface with RemoteOperations, and use OCFile IDs instead of OCFile objects as parameters
+ true,
+ mStorageManager);
+ WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());
+ mLastRemoteOperation.execute(wc, this, mHandler);
+
+ boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
+ getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
+ }
+ }
+
+
+ /**
+ * Removes the file from local storage
+ */
+ @Override
+ public void onNeutral(String callerTag) {
+ // TODO this code should be made in a secondary thread,
+ if (mFile.isDown()) { // checks it is still there
+ stopPreview(true);
+ File f = new File(mFile.getStoragePath());
+ f.delete();
+ mFile.setStoragePath(null);
+ mStorageManager.saveFile(mFile);
+ finish();
+ }
+ }
+
+ /**
+ * User cancelled the removal action.
+ */
+ @Override
+ public void onCancel(String callerTag) {
+ // nothing to do here
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public OCFile getFile(){
+ return mFile;
+ }
+
+ /*
+ /**
+ * Use this method to signal this Activity that it shall update its view.
+ *
+ * @param file : An {@link OCFile}
+ *-/
+ public void updateFileDetails(OCFile file, Account ocAccount) {
+ mFile = file;
+ if (ocAccount != null && (
+ mStorageManager == null ||
+ (mAccount != null && !mAccount.equals(ocAccount))
+ )) {
+ mStorageManager = new FileDataStorageManager(ocAccount, getActivity().getApplicationContext().getContentResolver());
+ }
+ mAccount = ocAccount;
+ updateFileDetails(false);
+ }
+ */
+
+
+ /**
+ * Helper method to test if an {@link OCFile} can be passed to a {@link PreviewMediaFragment} to be previewed.
+ *
+ * @param file File to test if can be previewed.
+ * @return 'True' if the file can be handled by the fragment.
+ */
+ public static boolean canBePreviewed(OCFile file) {
+ return (file != null && (file.isAudio() || file.isVideo()));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
+ if (operation.equals(mLastRemoteOperation)) {
+ if (operation instanceof RemoveFileOperation) {
+ onRemoveFileOperationFinish((RemoveFileOperation)operation, result);
+ }
+ }
+ }
+
+ private void onRemoveFileOperationFinish(RemoveFileOperation operation, RemoteOperationResult result) {
+ boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;
+ getActivity().dismissDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);
+
+ if (result.isSuccess()) {
+ Toast msg = Toast.makeText(getActivity().getApplicationContext(), R.string.remove_success_msg, Toast.LENGTH_LONG);
+ msg.show();
+ finish();
+
+ } else {
+ Toast msg = Toast.makeText(getActivity(), R.string.remove_fail_msg, Toast.LENGTH_LONG);
+ msg.show();
+ if (result.isSslRecoverableException()) {
+ // TODO show the SSL warning dialog
+ }
+ }
+ }
+
+ private void stopPreview(boolean stopAudio) {
+ if (mFile.isAudio() && stopAudio) {
+ mMediaServiceBinder.pause();
+
+ } else if (mFile.isVideo()) {
+ mVideoPreview.stopPlayback();
+ }
+ }
+
+
+
+ /**
+ * Finishes the preview
+ */
+ private void finish() {
+ Activity container = getActivity();
+ if (container instanceof FileDisplayActivity) {
+ // double pane
+ FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
+ transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null), FileDetailFragment.FTAG); // empty FileDetailFragment
+ transaction.commit();
+ ((FileFragment.ContainerActivity)container).onFileStateChanged();
+ } else {
+ container.finish();
+ }
+ }
+
+}
--- /dev/null
+/* ownCloud Android client application
+ * Copyright (C) 2012-2013 ownCloud Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.ui.preview;
+
+import android.accounts.Account;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnCompletionListener;
+import android.media.MediaPlayer.OnErrorListener;
+import android.media.MediaPlayer.OnPreparedListener;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.widget.MediaController;
+import android.widget.VideoView;
+
+import com.owncloud.android.AccountUtils;
+import com.owncloud.android.R;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.media.MediaService;
+
+/**
+ * Activity implementing a basic video player.
+ *
+ * Used as an utility to preview video files contained in an ownCloud account.
+ *
+ * Currently, it always plays in landscape mode, full screen. When the playback ends,
+ * the activity is finished.
+ *
+ * @author David A. Velasco
+ */
+public class PreviewVideoActivity extends Activity implements OnCompletionListener, OnPreparedListener, OnErrorListener {
+
+ /** Key to receive an {@link OCFile} to play as an extra value in an {@link Intent} */
+ public static final String EXTRA_FILE = "FILE";
+
+ /** Key to receive the ownCloud {@link Account} where the file to play is saved as an extra value in an {@link Intent} */
+ public static final String EXTRA_ACCOUNT = "ACCOUNT";
+
+ /** Key to receive a flag signaling if the video should be started immediately */
+ public static final String EXTRA_AUTOPLAY = "AUTOPLAY";
+
+ /** Key to receive the position of the playback where the video should be put at start */
+ public static final String EXTRA_START_POSITION = "START_POSITION";
+
+ private static final String TAG = PreviewVideoActivity.class.getSimpleName();
+
+ private OCFile mFile; // video file to play
+ private Account mAccount; // ownCloud account holding mFile
+ private int mSavedPlaybackPosition; // in the unit time handled by MediaPlayer.getCurrentPosition()
+ private boolean mAutoplay; // when 'true', the playback starts immediately with the activity
+ private VideoView mVideoPlayer; // view to play the file; both performs and show the playback
+ private MediaController mMediaController; // panel control used by the user to control the playback
+
+ /**
+ * Called when the activity is first created.
+ *
+ * Searches for an {@link OCFile} and ownCloud {@link Account} holding it in the starting {@link Intent}.
+ *
+ * The {@link Account} is unnecessary if the file is downloaded; else, the {@link Account} is used to
+ * try to stream the remote file - TODO get the streaming works
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.e(TAG, "ACTIVITY\t\tonCreate");
+
+ setContentView(R.layout.video_layout);
+
+ if (savedInstanceState == null) {
+ Bundle extras = getIntent().getExtras();
+ mFile = extras.getParcelable(EXTRA_FILE);
+ mAccount = extras.getParcelable(EXTRA_ACCOUNT);
+ mSavedPlaybackPosition = extras.getInt(EXTRA_START_POSITION);
+ mAutoplay = extras.getBoolean(EXTRA_AUTOPLAY);
+
+ } else {
+ mFile = savedInstanceState.getParcelable(EXTRA_FILE);
+ mAccount = savedInstanceState.getParcelable(EXTRA_ACCOUNT);
+ mSavedPlaybackPosition = savedInstanceState.getInt(EXTRA_START_POSITION);
+ mAutoplay = savedInstanceState.getBoolean(EXTRA_AUTOPLAY);
+ }
+
+ mVideoPlayer = (VideoView) findViewById(R.id.videoPlayer);
+
+ // set listeners to get more contol on the playback
+ mVideoPlayer.setOnPreparedListener(this);
+ mVideoPlayer.setOnCompletionListener(this);
+ mVideoPlayer.setOnErrorListener(this);
+
+ // keep the screen on while the playback is performed (prevents screen off by battery save)
+ mVideoPlayer.setKeepScreenOn(true);
+
+ if (mFile != null) {
+ if (mFile.isDown()) {
+ mVideoPlayer.setVideoPath(mFile.getStoragePath());
+
+ } else if (mAccount != null) {
+ // not working now
+ String url = AccountUtils.constructFullURLForAccount(this, mAccount) + mFile.getRemotePath();
+ mVideoPlayer.setVideoURI(Uri.parse(url));
+
+ } else {
+ onError(null, MediaService.OC_MEDIA_ERROR, R.string.media_err_no_account);
+ }
+
+ // create and prepare control panel for the user
+ mMediaController = new MediaController(this);
+ mMediaController.setMediaPlayer(mVideoPlayer);
+ mMediaController.setAnchorView(mVideoPlayer);
+ mVideoPlayer.setMediaController(mMediaController);
+
+ } else {
+ onError(null, MediaService.OC_MEDIA_ERROR, R.string.media_err_nothing_to_play);
+ }
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ Log.e(TAG, "ACTIVITY\t\tonSaveInstanceState");
+ outState.putParcelable(PreviewVideoActivity.EXTRA_FILE, mFile);
+ outState.putParcelable(PreviewVideoActivity.EXTRA_ACCOUNT, mAccount);
+ outState.putInt(PreviewVideoActivity.EXTRA_START_POSITION, mVideoPlayer.getCurrentPosition());
+ outState.putBoolean(PreviewVideoActivity.EXTRA_AUTOPLAY , mVideoPlayer.isPlaying());
+ }
+
+
+ @Override
+ public void onBackPressed() {
+ Log.e(TAG, "ACTIVTIY\t\tonBackPressed");
+ Intent i = new Intent();
+ i.putExtra(EXTRA_AUTOPLAY, mVideoPlayer.isPlaying());
+ i.putExtra(EXTRA_START_POSITION, mVideoPlayer.getCurrentPosition());
+ setResult(RESULT_OK, i);
+ super.onBackPressed();
+ }
+
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ Log.e(TAG, "ACTIVTIY\t\tonResume");
+ }
+
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ Log.e(TAG, "ACTIVTIY\t\tonStart");
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ Log.e(TAG, "ACTIVITY\t\tonDestroy");
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ Log.e(TAG, "ACTIVTIY\t\tonStop");
+ }
+
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ Log.e(TAG, "ACTIVTIY\t\tonPause");
+ }
+
+
+ /**
+ * Called when the file is ready to be played.
+ *
+ * Just starts the playback.
+ *
+ * @param mp {@link MediaPlayer} instance performing the playback.
+ */
+ @Override
+ public void onPrepared(MediaPlayer mp) {
+ Log.e(TAG, "ACTIVITY\t\tonPrepare");
+ mVideoPlayer.seekTo(mSavedPlaybackPosition);
+ if (mAutoplay) {
+ mVideoPlayer.start();
+ }
+ mMediaController.show(5000);
+ }
+
+
+ /**
+ * Called when the file is finished playing.
+ *
+ * Rewinds the video
+ *
+ * @param mp {@link MediaPlayer} instance performing the playback.
+ */
+ @Override
+ public void onCompletion(MediaPlayer mp) {
+ mVideoPlayer.seekTo(0);
+ }
+
+
+ /**
+ * Called when an error in playback occurs.
+ *
+ * @param mp {@link MediaPlayer} instance performing the playback.
+ * @param what Type of error
+ * @param extra Extra code specific to the error
+ */
+ @Override
+ public boolean onError(MediaPlayer mp, int what, int extra) {
+ Log.e(TAG, "Error in video playback, what = " + what + ", extra = " + extra);
+
+ if (mMediaController != null) {
+ mMediaController.hide();
+ }
+
+ if (mVideoPlayer.getWindowToken() != null) {
+ String message = MediaService.getMessageForMediaError(this, what, extra);
+ new AlertDialog.Builder(this)
+ .setMessage(message)
+ .setPositiveButton(android.R.string.VideoView_error_button,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+ PreviewVideoActivity.this.onCompletion(null);
+ }
+ })
+ .setCancelable(false)
+ .show();
+ }
+ return true;
+ }
+
+
+ /**
+ * Screen touches trigger the appearance of the control panel for a limited time.
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean onTouchEvent (MotionEvent ev){
+ /*if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ if (mMediaController.isShowing()) {
+ mMediaController.hide();
+ } else {
+ mMediaController.show(MediaService.MEDIA_CONTROL_SHORT_LIFE);
+ }
+ return true;
+ } else {
+ return false;
+ }*/
+ return false;
+ }
+
+
+}
\ No newline at end of file
import java.io.File;
+import android.annotation.SuppressLint;
import android.net.Uri;
import android.os.Environment;
import android.os.StatFs;
+import android.util.Log;
import com.owncloud.android.datamodel.OCFile;
-
+import com.owncloud.android.files.services.InstantUploadService;
/**
* Static methods to help in access to local file system.
* @author David A. Velasco
*/
public class FileStorageUtils {
-
+ private static final String LOG_TAG = "FileStorageUtils";
+
public static final String getSavePath(String accountName) {
File sdCard = Environment.getExternalStorageDirectory();
- return sdCard.getAbsolutePath() + "/owncloud/" + Uri.encode(accountName, "@");
- // URL encoding is an 'easy fix' to overcome that NTFS and FAT32 don't allow ":" in file names, that can be in the accountName since 0.1.190B
+ return sdCard.getAbsolutePath() + "/owncloud/" + Uri.encode(accountName, "@");
+ // URL encoding is an 'easy fix' to overcome that NTFS and FAT32 don't allow ":" in file names, that can be in the accountName since 0.1.190B
}
-
+
public static final String getDefaultSavePathFor(String accountName, OCFile file) {
return getSavePath(accountName) + file.getRemotePath();
}
-
+
public static final String getTemporalPath(String accountName) {
File sdCard = Environment.getExternalStorageDirectory();
return sdCard.getAbsolutePath() + "/owncloud/tmp/" + Uri.encode(accountName, "@");
// URL encoding is an 'easy fix' to overcome that NTFS and FAT32 don't allow ":" in file names, that can be in the accountName since 0.1.190B
}
+ @SuppressLint("NewApi")
public static final long getUsableSpace(String accountName) {
File savePath = Environment.getExternalStorageDirectory();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) {
return savePath.getUsableSpace();
-
+
} else {
StatFs stats = new StatFs(savePath.getAbsolutePath());
return stats.getAvailableBlocks() * stats.getBlockSize();
}
-
+
+ }
+
+ // to ensure we will not add the slash twice between filename and
+ // folder-name
+ private static String getFileName(String filepath) {
+ if (filepath != null && !"".equals(filepath)) {
+ int psi = filepath.lastIndexOf('/');
+ String filename = filepath;
+ if (psi > -1) {
+ filename = filepath.substring(psi + 1, filepath.length());
+ Log.d(LOG_TAG, "extracted filename :" + filename);
+ }
+ return filename;
+ } else {
+ // Toast
+ Log.w(LOG_TAG, "the given filename was null or empty");
+ return null;
+ }
+ }
+
+ public static String getInstantUploadFilePath(String fileName) {
+ return InstantUploadService.INSTANT_UPLOAD_DIR + "/" + getFileName(fileName);
}
-
}
\ No newline at end of file
import org.apache.commons.httpclient.methods.RequestEntity;
import com.owncloud.android.Log_OC;
+import com.owncloud.android.network.ProgressiveDataTransferer;
import eu.alefzero.webdav.OnDatatransferProgressListener;
-import android.util.Log;
-
/**
* A RequestEntity that represents a PIECE of a file.
*
* @author David A. Velasco
*/
-public class ChunkFromFileChannelRequestEntity implements RequestEntity {
+public class ChunkFromFileChannelRequestEntity implements RequestEntity, ProgressiveDataTransferer {
private static final String TAG = ChunkFromFileChannelRequestEntity.class.getSimpleName();
return true;
}
- public void addOnDatatransferProgressListener(OnDatatransferProgressListener listener) {
- mDataTransferListeners.add(listener);
+ @Override
+ public void addDatatransferProgressListener(OnDatatransferProgressListener listener) {
+ synchronized (mDataTransferListeners) {
+ mDataTransferListeners.add(listener);
+ }
}
- public void addOnDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
- mDataTransferListeners.addAll(listeners);
+ @Override
+ public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
+ synchronized (mDataTransferListeners) {
+ mDataTransferListeners.addAll(listeners);
+ }
}
- public void removeOnDatatransferProgressListener(OnDatatransferProgressListener listener) {
- mDataTransferListeners.remove(listener);
+ @Override
+ public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
+ synchronized (mDataTransferListeners) {
+ mDataTransferListeners.remove(listener);
+ }
}
out.write(mBuffer.array(), 0, readCount);
mBuffer.clear();
mTransferred += readCount;
- it = mDataTransferListeners.iterator();
- while (it.hasNext()) {
- it.next().onTransferProgress(readCount, mTransferred, size, mFile.getName());
+ synchronized (mDataTransferListeners) {
+ it = mDataTransferListeners.iterator();
+ while (it.hasNext()) {
+ it.next().onTransferProgress(readCount, mTransferred, size, mFile.getName());
+ }
}
}
import org.apache.commons.httpclient.methods.RequestEntity;
import com.owncloud.android.Log_OC;
+import com.owncloud.android.network.ProgressiveDataTransferer;
import eu.alefzero.webdav.OnDatatransferProgressListener;
-import android.util.Log;
-
/**
* A RequestEntity that represents a File.
*
*/
-public class FileRequestEntity implements RequestEntity {
+public class FileRequestEntity implements RequestEntity, ProgressiveDataTransferer {
final File mFile;
final String mContentType;
public boolean isRepeatable() {
return true;
}
-
- public void addOnDatatransferProgressListener(OnDatatransferProgressListener listener) {
- mDataTransferListeners.add(listener);
+
+ @Override
+ public void addDatatransferProgressListener(OnDatatransferProgressListener listener) {
+ synchronized (mDataTransferListeners) {
+ mDataTransferListeners.add(listener);
+ }
}
- public void addOnDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
- mDataTransferListeners.addAll(listeners);
+ @Override
+ public void addDatatransferProgressListeners(Collection<OnDatatransferProgressListener> listeners) {
+ synchronized (mDataTransferListeners) {
+ mDataTransferListeners.addAll(listeners);
+ }
}
- public void removeOnDatatransferProgressListener(OnDatatransferProgressListener listener) {
- mDataTransferListeners.remove(listener);
+ @Override
+ public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) {
+ synchronized (mDataTransferListeners) {
+ mDataTransferListeners.remove(listener);
+ }
}
out.write(tmp.array(), 0, readResult);
tmp.clear();
transferred += readResult;
- it = mDataTransferListeners.iterator();
- while (it.hasNext()) {
- it.next().onTransferProgress(readResult, transferred, size, mFile.getName());
+ synchronized (mDataTransferListeners) {
+ it = mDataTransferListeners.iterator();
+ while (it.hasNext()) {
+ it.next().onTransferProgress(readResult, transferred, size, mFile.getName());
+ }
}
}
exhaustResponse(get.getResponseBodyAsStream());
}
Log_OC.e(TAG, "Download of " + remoteFilePath + " to " + targetFile + " finished with HTTP status " + status + (!ret?"(FAIL)":""));
+
} catch (Exception e) {
logException(e, "dowloading " + remoteFilePath);
ret = (status == HttpStatus.SC_OK || status == HttpStatus.SC_ACCEPTED || status == HttpStatus.SC_NO_CONTENT);
exhaustResponse(delete.getResponseBodyAsStream());
- Log.e(TAG, "DELETE of " + remoteFilePath + " finished with HTTP status " + status + (!ret?"(FAIL)":""));
+ Log_OC.e(TAG, "DELETE of " + remoteFilePath + " finished with HTTP status " + status + (!ret?"(FAIL)":""));
} catch (Exception e) {
logException(e, "deleting " + remoteFilePath);
try {
File f = new File(localFile);
FileRequestEntity entity = new FileRequestEntity(f, contentType);
- entity.addOnDatatransferProgressListener(mDataTransferListener);
+ entity.addDatatransferProgressListener(mDataTransferListener);
put.setRequestEntity(entity);
status = executeMethod(put);
}
}
-
/**
* Requests the received method with the received timeout (milliseconds).
*
}
}
-
/**
* Logs an exception triggered in a HTTP request.
*