Merge branch 'develop' into sorting_files_2

Conflicts:
	src/com/owncloud/android/ui/adapter/FileListListAdapter.java
This commit is contained in:
jabarros 2014-10-23 10:18:20 +02:00
commit 2fad1e1a99
86 changed files with 2885 additions and 666 deletions

View file

@ -1,15 +1,20 @@
language: java
language: android
android:
components:
- build-tools-20.0.0
- android-19
- android-17
- android-14
- extra-android-support
licenses:
- 'android-sdk-license-5be876d5'
- 'android-sdk-license-598b93a6'
jdk: oraclejdk7
before_install:
# Install base Android SDK
- sudo apt-get update -qq
- sudo apt-get install -qq libstdc++6:i386 lib32z1 expect
- export COMPONENTS="build-tools-20.0.0,android-14,android-17,android-19,sysimg-19,extra-android-support"
- export LICENSES="android-sdk-license-5be876d5|android-sdk-license-598b93a6"
- curl -3L https://raw.github.com/embarkmobile/android-sdk-installer/version-2/android-sdk-installer | bash /dev/stdin --install=$COMPONENTS --accept=$LICENSES
- source ~/.android-sdk-installer/env
- rm pom.xml
- ./setup_env.sh
- rm pom.xml
- ./setup_env.sh
script:
- ant clean

View file

@ -18,8 +18,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<manifest package="com.owncloud.android"
android:versionCode="10500800"
android:versionName="1.5.8" xmlns:android="http://schemas.android.com/apk/res/android">
android:versionCode="10600000"
android:versionName="1.6.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" />

View file

@ -1,10 +1,14 @@
If you want to start help developing ownCloud please follow the [contribution guidelines][0] and observe these instructions:
### 1. Fork and download android/develop repository:
If you want to start help developing ownCloud please follow the [contribution guidelines][0] and observe these instructions.
NOTE: You must have git in your environment path variable to perform the next operations.
If you have any problems, start again with 1) and work your way down. If something still does not work as described here, please open a new issue describing exactly what you did, what happened, and what should have happened.
### 1) Fork and download android/develop repository:
NOTE: Android SDK with platforms 8, 14 and 19 (and maybe others) need to be installed.
You must have the Android SDK 'tools/', and 'platforms-tools/' folders in your environment path variable.
"git" need to be installed and in your environment path variable.
* Navigate to https://github.com/owncloud/android, click fork.
* Clone your new repo: "git clone git@github.com:YOURGITHUBNAME/android.git"
* Move to the project folder with "cd android"
@ -14,16 +18,16 @@ NOTE: You must have git in your environment path variable to perform the next op
* Make sure to get the latest changes from official android/develop branch: "git pull upstream develop"
* Complete the setup of project properties and resolve pending dependencies running "setup_env.bat" or "./setup_env.sh" .
At this point you can continue using different tools to build the project. Section 2, 3 and 4 describe some of the existing alternatives.
At this point you can continue using different tools to build the project. Sections 2a), 2b), and 2c) describe some of the existing alternatives.
### 2. Building with Ant:
### 2a) Building with Ant:
NOTE: You must have the Android SDK 'tools/', and 'platforms-tools/' folders in your environment path variable.
* Run "ant clean" .
* Run "ant debug" to generate a debuggable version of the ownCloud app.
### 3. Building with console/maven:
### 2b) Building with console/maven:
NOTE: You must have mvn (version >= 3.1.1) in your environment path. Current Android 'platforms-tools' need to be installed.
@ -39,7 +43,7 @@ Download/install Android plugin for Maven, install owncloud-android-library, the
Now you can create ownCloud APK using "mvn package"
### 4. Building with Eclipse:
### 2c) Building with Eclipse:
NOTE: You must have the Android SDK 'tools/', and 'platforms-tools/' folders in your environment path variable.
@ -47,11 +51,12 @@ NOTE: You must have the Android SDK 'tools/', and 'platforms-tools/' folders in
* Open Eclipse and create new "Android Project from Existing Code". Choose android/actionbarsherlock/library as root.
* Clean project and compile.
* If any error appear, check the project properties; in the 'Android' section, API Level should be greater or equal than 14.
* If "error loading libz.so.1" appears, try "sudo apt-get install lib32z1"
* Make sure android/actionbarsherlock/library/bin/library.jar was created.
* Create a new "Android Project from Existing Code". Choose android/owncloud-android-library as root.
* Create a new "Android Project from Existing Code". Choose android/owncloud-android-library as root. (test and sample clients are not required.)
* Clean project and compile.
* If any error appear, check the project properties; in the 'Android' section, API Level should be 19 or greater.
* Make sure android/owncloud-android-library/bin/classes.jar was created.
* Make sure 'android/owncloud-android-library/bin/owncloud android library.jar' was created.
* Import ownCloud Android project.
* Clean project and compile.
* If any error appears, check the project properties of owncloud-android project; in the 'Android' section:
@ -61,7 +66,7 @@ NOTE: You must have the Android SDK 'tools/', and 'platforms-tools/' folders in
NOTE: Even though API level is set to 19, APK also runs on older devices because in AndroidManifest.xml minSdkVersion is set to 8.
### 5. Create pull request:
### 3) Create pull request:
NOTE: You must sign the [Contributor Agreement][1] before your changes can be accepted!
@ -72,7 +77,7 @@ NOTE: You must sign the [Contributor Agreement][1] before your changes can be ac
* Again, click "Edit" and set "compare:develop"
* Enter description and send pull request.
### 6. Create another pull request:
### 4) Create another pull request:
To make sure your new pull request does not contain commits which are already contained in previous PRs, create a new branch which is a clone of upstream/develop.

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.owncloud.android.workaround.accounts"
android:versionCode="0100017"
android:versionName="1.0.17" >
android:versionCode="0100018"
android:versionName="1.0.18" >
<uses-sdk
android:minSdkVersion="16"

@ -1 +1 @@
Subproject commit ff0de72ea5352ba22a21cdac289e9314706cdb2e
Subproject commit 5bd0d7387712ce3f53869294761ac4d8537841cd

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 609 B

After

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 413 B

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 793 B

After

Width:  |  Height:  |  Size: 934 B

View file

@ -16,6 +16,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fileDownloadLL"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"

View file

@ -43,7 +43,7 @@
android:layout_centerInParent="true"
/>
<com.ortiz.touch.TouchImageView
<com.owncloud.android.utils.TouchImageViewCustom
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"

View file

@ -250,4 +250,5 @@
<string name="prefs_category_accounts">حسابات</string>
<string name="saml_authentication_wrong_pass">كلمة مرور خاطئة</string>
<string name="move_choose_button_text">اختيار</string>
<string name="prefs_category_security">الأمان</string>
</resources>

View file

@ -263,7 +263,6 @@
<string name="downloader_download_file_not_found">Файлът вече не се намира на този сървър</string>
<string name="prefs_category_accounts">Профили</string>
<string name="prefs_add_account">Добавяне на профил</string>
<string name="auth_redirect_non_secure_connection_title">Сигурна връзка е пренасочена по несигурен път.</string>
<string name="actionbar_logger">Доклади</string>
<string name="log_send_history_button">Изпрати История</string>
<string name="log_mail_subject">ownCloud Android доклади</string>
@ -278,4 +277,5 @@
<string name="move_file_invalid_overwrite">Файлът вече съществува в отдалечената папка.</string>
<string name="move_file_error">Настъпи грешка при опита за преместване на този файл или папка.</string>
<string name="forbidden_permissions_move">за да преместиш този файл</string>
<string name="prefs_category_security">Сигурност</string>
</resources>

View file

@ -259,10 +259,10 @@
<string name="downloader_download_file_not_found">সার্ভারে এই ফাইলটি আর প্রাপ্তব্য নয়</string>
<string name="prefs_category_accounts">একাউন্ট</string>
<string name="prefs_add_account">একাউন্ট যোগ কর</string>
<string name="auth_redirect_non_secure_connection_title">নিরাপদ সংযোগকে একটি অনিরাপদ পথে দিকবদল করা হয়েছে</string>
<string name="saml_authentication_wrong_pass">ভুল কুটশব্দ</string>
<string name="actionbar_move">সরাও</string>
<string name="file_list_empty_moving">এখানে কিছু নেই। একটি ফোল্ডার যোগ করতে পারেন!</string>
<string name="move_choose_button_text">বেছে নিন</string>
<string name="move_file_not_found">সরাতে ব্যার্থ হলো। ফাইলটি রয়েছে কিনা দেখুন।</string>
<string name="prefs_category_security">নিরাপত্তা</string>
</resources>

View file

@ -257,8 +257,8 @@
<string name="downloader_download_file_not_found">El fitxer ja no està disponible en el servidor</string>
<string name="prefs_category_accounts">Comptes</string>
<string name="prefs_add_account">Afegeix compte</string>
<string name="auth_redirect_non_secure_connection_title">La connexió segura està essent redirigida a través d\'una ruta insegura</string>
<string name="saml_authentication_required_text">Es requereix autenticació</string>
<string name="saml_authentication_wrong_pass">Contrasenya incorrecta</string>
<string name="move_choose_button_text">Escull</string>
<string name="prefs_category_security">Seguretat</string>
</resources>

View file

@ -15,9 +15,9 @@
<string name="prefs_category_more">Více</string>
<string name="prefs_accounts">Účty</string>
<string name="prefs_manage_accounts">Spravovat účty</string>
<string name="prefs_pincode">PIN aplikace</string>
<string name="prefs_pincode">PIN do aplikace</string>
<string name="prefs_pincode_summary">Chraňte svého klienta</string>
<string name="prefs_instant_upload">Okamžité nahrání obrázků</string>
<string name="prefs_instant_upload">Okamžité nahrání obrázků</string>
<string name="prefs_instant_upload_summary">Okamžitě nahrávat vytvořené fotografie</string>
<string name="prefs_instant_video_upload">Okamžité nahrávání videa</string>
<string name="prefs_instant_video_upload_summary">Okamžitě odesílat nahrané video</string>
@ -27,7 +27,7 @@
<string name="prefs_log_summary_history">Zobrazuje zaznamenané logy</string>
<string name="prefs_log_delete_history_button">Smazat historii</string>
<string name="prefs_help">Nápověda</string>
<string name="prefs_recommend">Doporučit příteli</string>
<string name="prefs_recommend">Doporučit přátelům</string>
<string name="prefs_feedback">Odezva</string>
<string name="prefs_imprint">Imprint</string>
<string name="recommend_subject">Zkuste %1$s na vašem smartphonu!</string>
@ -226,7 +226,7 @@
<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">Odesílat obrázky pouze skrze WiFi</string>
<string name="instant_upload_on_wifi">Odesílat obrázky pouze přes WiFi</string>
<string name="instant_video_upload_on_wifi">Nahrávat videa pouze přes WiFi</string>
<string name="instant_upload_path">/InstantUpload</string>
<string name="conflict_title">Konflikt při aktualizaci</string>
@ -237,6 +237,7 @@
<string name="preview_image_description">Náhled obrázku</string>
<string name="preview_image_error_unknown_format">Obrázek nelze zobrazit</string>
<string name="error__upload__local_file_not_copied">%1$s nelze zkopírovat do místního adresáře %2$s</string>
<string name="prefs_instant_upload_path_title">Cesta pro nahrání</string>
<string name="share_link_no_support_share_api">Je nám líto, ale sdílení není na vašem serveru povoleno. Kontaktujte svého
administrátora.</string>
<string name="share_link_file_no_exist">Nelze sdílet. Zkontrolujte prosím že soubor existuje</string>
@ -262,7 +263,7 @@ administrátora.</string>
<string name="downloader_download_file_not_found">Tento soubor již není dostupný na serveru</string>
<string name="prefs_category_accounts">Účty</string>
<string name="prefs_add_account">Přidat účet</string>
<string name="auth_redirect_non_secure_connection_title">Zabezpečené spojení je přesměrováváno nezabezpečenou trasou.</string>
<string name="auth_redirect_non_secure_connection_title">Bezpečné spojení je přesměrováno na nezabezpečenou trasu.</string>
<string name="actionbar_logger">Logy</string>
<string name="log_send_history_button">Odeslat historii</string>
<string name="log_mail_subject">Logy aplikace ownCloud pro Android</string>
@ -277,4 +278,6 @@ administrátora.</string>
<string name="move_file_invalid_overwrite">Soubor již v cílovém adresáři existuje</string>
<string name="move_file_error">Při pokusu o přesun tohoto souboru či složky nastala chyba</string>
<string name="forbidden_permissions_move">pro přesun tohoto souboru</string>
<string name="prefs_category_instant_uploading">Okamžitá odesílání</string>
<string name="prefs_category_security">Zabezpečení</string>
</resources>

View file

@ -261,7 +261,6 @@
<string name="downloader_download_file_not_found">Filen er ikke længere tilgængelig på serveren</string>
<string name="prefs_category_accounts">Konti</string>
<string name="prefs_add_account">Tilføj konto</string>
<string name="auth_redirect_non_secure_connection_title">Sikker forbindelse videredirigeres gennem en usikker rute.</string>
<string name="actionbar_logger">Logge</string>
<string name="log_send_history_button">Send historik</string>
<string name="log_mail_subject">App-logregistreringer for ownCloud Android</string>
@ -276,4 +275,5 @@
<string name="move_file_invalid_overwrite">Filen findes allerede i destinationsmappen</string>
<string name="move_file_error">Der opstod en fejl under forsøg på at flytte denne mappe eller fil</string>
<string name="forbidden_permissions_move">til at flytte denne fil</string>
<string name="prefs_category_security">Sikkerhed</string>
</resources>

View file

@ -198,4 +198,5 @@
<string name="empty"></string>
<string name="prefs_category_accounts">Konten</string>
<string name="move_choose_button_text">Auswählen</string>
<string name="prefs_category_security">Sicherheit</string>
</resources>

View file

@ -238,6 +238,7 @@
<string name="preview_image_description">Bildvorschau</string>
<string name="preview_image_error_unknown_format">Dieses Bild kann nicht angezeigt werden</string>
<string name="error__upload__local_file_not_copied">%1$s konnte nicht in den lokalen %2$s Ordner kopiert werden</string>
<string name="prefs_instant_upload_path_title">Pfad hochladen</string>
<string name="share_link_no_support_share_api">Entschuldigung, Freigaben sind auf Ihrem Server nicht aktiviert. Bitte kontaktieren Sie Ihren
⇥⇥Administrator.</string>
<string name="share_link_file_no_exist">Teilen nicht möglich. Prüfen Sie, dass die Datei existiert</string>
@ -278,4 +279,6 @@
<string name="move_file_invalid_overwrite">Die Datei ist bereits im Zielordner vorhanden</string>
<string name="move_file_error">Es ist ein Fehler beim Verschieben dieser Datei oder dieses Ordners aufgetreten.</string>
<string name="forbidden_permissions_move">um diese Datei zu verschieben</string>
<string name="prefs_category_instant_uploading">Sofortiges Hochladen</string>
<string name="prefs_category_security">Sicherheit</string>
</resources>

View file

@ -111,7 +111,7 @@
<string name="sync_fail_in_favourites_content">Inhalte von %1$d konnte nicht synchronisiert werden (%2$d Konflikte)</string>
<string name="sync_foreign_files_forgotten_ticker">Einige lokale Dateien wurden vergessen</string>
<string name="sync_foreign_files_forgotten_content">%1$d Dateien aus dem %2$s Verzeichnis konnten nicht kopiert werden nach</string>
<string name="sync_foreign_files_forgotten_explanation">Mit Version 1.3.16 werden Dateien die von diesem Gerät aus hochgeladen werden in den lokalen Ordner %1$s kopiert um Datenverlust zu vermeiden, wenn eine einzelne Datei mit mehreren Accounts synchronisiert wird.\n\nInfolge dieser Änderung wurden alle Dateien, die mit vorherigen Versionen dieser App hochgeladen wurden, in den Ordner %2$s verschoben. Jedoch ist während der Account-Synchronisation ein Fehler aufgetreten, der das Abschließen dieses Vorgangs verhindert. Du kannst die Datei(en) entweder wie sie sind belassen und den Link zu %3$s entfernen oder die Datei(en) in den %1$s Ordner verschieben und den Link zu %4$s beibehalten.\n\nUnten befindet sich eine Liste der lokalen Datei(en) und der mit ihnen verbundenen Remote-Datei(en) in %5$s.</string>
<string name="sync_foreign_files_forgotten_explanation">Mit Version 1.3.16 werden Dateien die von diesem Gerät aus hochgeladen werden in den lokalen Ordner %1$s kopiert um Datenverlust zu vermeiden, wenn eine einzelne Datei mit mehreren Accounts synchronisiert wird.\n\nInfolge dieser Änderung wurden alle Dateien, die mit vorherigen Versionen dieser App hochgeladen wurden, in den Ordner %2$s verschoben. Jedoch ist während der Account-Synchronisation ein Fehler aufgetreten, der das Abschließen dieses Vorgangs verhindert. Du kannst die Datei(en) entweder wie sie sind belassen und den Link zu %3$s entfernen oder die Datei(en) in den Ordner %1$s verschieben und den Link zu %4$s beibehalten.\n\nUnten befindet sich eine Liste der lokalen Datei(en) und der mit ihnen verbundenen Remote-Datei(en) in %5$s.</string>
<string name="sync_current_folder_was_removed">Das Verzeichnis %1$s existiert nicht mehr</string>
<string name="foreign_files_move">Verschiebe alle</string>
<string name="foreign_files_success">Alle Dateien wurden verschoben</string>
@ -245,6 +245,7 @@
<string name="preview_image_description">Bildvorschau</string>
<string name="preview_image_error_unknown_format">Dieses Bild kann nicht angezeigt werden</string>
<string name="error__upload__local_file_not_copied">%1$s konnte nicht in den lokalen %2$s Ordner kopiert werden</string>
<string name="prefs_instant_upload_path_title">Pfad hochladen</string>
<string name="share_link_no_support_share_api">Entschuldigung, Freigaben sind auf Deinem Server nicht aktiviert. Bitte kontaktiere Deinen
⇥⇥Administrator.</string>
<string name="share_link_file_no_exist">Teilen nicht möglich. Prüfe, dass die Datei existiert</string>
@ -281,8 +282,10 @@
<string name="file_list_empty_moving">Nichts vorhanden. Du kannst einen Ordner hinzufügen!</string>
<string name="move_choose_button_text">Auswählen</string>
<string name="move_file_not_found">Verschieben nicht möglich. Prüfe, dass die Datei existiert</string>
<string name="move_file_invalid_into_descendent">Es ist nicht möglich einen Ordner eine Ebene tiefer zu verschieben</string>
<string name="move_file_invalid_into_descendent">Es ist nicht möglich, einen Ordner in einen seiner Unterordner zu verschieben</string>
<string name="move_file_invalid_overwrite">Die Datei ist bereits im Zielordner vorhanden</string>
<string name="move_file_error">Es ist ein Fehler beim Verschieben dieser Datei oder Ordners aufgetreten.</string>
<string name="forbidden_permissions_move">zum Datei verschieben</string>
<string name="move_file_error">Es ist ein Fehler beim Verschieben der Datei oder des Ordners aufgetreten.</string>
<string name="forbidden_permissions_move">um diese Datei zu verschieben</string>
<string name="prefs_category_instant_uploading">Sofortiges Hochladen</string>
<string name="prefs_category_security">Sicherheit</string>
</resources>

View file

@ -260,7 +260,6 @@
<string name="downloader_download_file_not_found">Αυτό το αρχείο δεν είναι πια διαθέσιμο στο διακομιστή</string>
<string name="prefs_category_accounts">Λογαριασμοί</string>
<string name="prefs_add_account">Προσθήκη λογαριασμού</string>
<string name="auth_redirect_non_secure_connection_title">Ασφαλής σύνδεση ανακατευθύνεται μέσω μιας μη ασφαλούς διαδρομής.</string>
<string name="actionbar_logger">Αρχεία καταγραφών</string>
<string name="log_send_history_button">Αποστολή ιστορικού</string>
<string name="log_progress_dialog_text">Φόρτωση δεδομένων....</string>
@ -270,4 +269,5 @@
<string name="move_choose_button_text">Επιλέξτε</string>
<string name="move_file_invalid_overwrite">Το αρχείο υπάρχει ήδη στο φάκελο προορισμού</string>
<string name="forbidden_permissions_move">για μετακίνηση αυτού του αρχείου</string>
<string name="prefs_category_security">Ασφάλεια</string>
</resources>

View file

@ -238,6 +238,7 @@
<string name="preview_image_description">Image preview</string>
<string name="preview_image_error_unknown_format">This image cannot be shown</string>
<string name="error__upload__local_file_not_copied">%1$s could not be copied to %2$s local folder</string>
<string name="prefs_instant_upload_path_title">Upload Path</string>
<string name="share_link_no_support_share_api">Sorry, sharing is not enabled on your server. Please contact your
administrator.</string>
<string name="share_link_file_no_exist">Unable to share. Please check whether the file exists</string>
@ -263,7 +264,7 @@
<string name="downloader_download_file_not_found">The file is no longer available on the server</string>
<string name="prefs_category_accounts">Accounts</string>
<string name="prefs_add_account">Add account</string>
<string name="auth_redirect_non_secure_connection_title">Secure connection is redirected through an unsecured route.</string>
<string name="auth_redirect_non_secure_connection_title">Secure connection is redirected to an unsecured route.</string>
<string name="actionbar_logger">Logs</string>
<string name="log_send_history_button">Send History</string>
<string name="log_mail_subject">ownCloud Android app logs</string>
@ -278,4 +279,6 @@
<string name="move_file_invalid_overwrite">The file exists already in the destination folder</string>
<string name="move_file_error">An error occurred whilst trying to move this file or folder</string>
<string name="forbidden_permissions_move">to move this file</string>
<string name="prefs_category_instant_uploading">Instant Uploads</string>
<string name="prefs_category_security">Security</string>
</resources>

View file

@ -186,4 +186,5 @@
<string name="saml_authentication_required_text">Aŭtentiĝo nepras</string>
<string name="saml_authentication_wrong_pass">Malĝusta pasvorto</string>
<string name="move_choose_button_text">Elekti</string>
<string name="prefs_category_security">Sekuro</string>
</resources>

View file

@ -241,4 +241,5 @@
<string name="saml_authentication_required_text">Autentificación requerida</string>
<string name="saml_authentication_wrong_pass">Clave incorrecta</string>
<string name="move_choose_button_text">Elegir</string>
<string name="prefs_category_security">Seguridad</string>
</resources>

View file

@ -215,4 +215,5 @@
<string name="prefs_category_accounts">Cuentas</string>
<string name="saml_authentication_wrong_pass">Contraseña incorrecta</string>
<string name="move_choose_button_text">Seleccionar</string>
<string name="prefs_category_security">Seguridad</string>
</resources>

View file

@ -101,7 +101,7 @@
<string name="sync_conflicts_in_favourites_ticker">Se encontraron conflictos</string>
<string name="sync_conflicts_in_favourites_content">Falló la sincronización de contenidos de %1$d ficheros</string>
<string name="sync_fail_in_favourites_ticker">Fallos en la sincronización de contenidos</string>
<string name="sync_fail_in_favourites_content">Los contenidos de %1$d ficheros no se han sincronizado (%2$d conflictos)</string>
<string name="sync_fail_in_favourites_content">Los contenidos de %1$d archivos no pudieron sincronizarse (%2$d conflictos)</string>
<string name="sync_foreign_files_forgotten_ticker">Algunos archivos locales se han perdido</string>
<string name="sync_foreign_files_forgotten_content">%1$d archivos en la carpeta %2$s no pudieron ser copiados a</string>
<string name="sync_foreign_files_forgotten_explanation">A partir de la versión 1.3.16, los ficheros subidos desde este dispositivo se copian en la carpeta local %1$s para evitar la pérdida de datos cuando se sincroniza un único archivo con varias cuentas.\n\nDebido a este cambio, todos los ficheros subidos con versiones anteriores de esta aplicación fueron copiados a la carpeta %2$s. Sin embargo, un error impidió que se completara esta operación durante la sincronización de la cuenta. Puede dejar los archivos tal y como están y eliminar el enlace a %3$s o mover los archivos a la carpeta %1$s y mantener el enlace a %4$s.\n\nDebajo se muestran los archivos locales y los archivos remotos en %5$s a los que fueron enlazados.</string>
@ -150,12 +150,12 @@
<string name="auth_account_not_new">Ya existe una cuenta en este dispositivo con los mismos datos de Usuario y Servidor</string>
<string name="auth_account_not_the_same">El usuario introducido no concuerda con el usuario de esta cuenta</string>
<string name="auth_unknown_error_title">Ocurrió un error desconocido</string>
<string name="auth_unknown_host_title">No se pudo encontrar la dirección</string>
<string name="auth_unknown_host_title">Error: no se pudo encontrar el host</string>
<string name="auth_incorrect_path_title">Instancia de servidor no encontrada</string>
<string name="auth_timeout_title">El servidor ha tardado demasiado en responder</string>
<string name="auth_incorrect_address_title">URL no válida</string>
<string name="auth_ssl_general_error_title">Falló la inicialización SSL</string>
<string name="auth_ssl_unverified_server_title">No fue posible verificar la identidad del servidor SLL</string>
<string name="auth_ssl_unverified_server_title">No fue posible verificar la identidad del servidor SSL</string>
<string name="auth_bad_oc_version_title">No se reconoce la versión del servidor </string>
<string name="auth_wrong_connection_title">No se ha podido establecer la conexión</string>
<string name="auth_secure_connection">Conexión segura establecida</string>
@ -200,7 +200,7 @@
<string name="ssl_validator_header">La identidad del sitio no puede ser verificada</string>
<string name="ssl_validator_reason_cert_not_trusted">- El certificado del servidor no es de confianza</string>
<string name="ssl_validator_reason_cert_expired">- El certificado del servidor expiró</string>
<string name="ssl_validator_reason_cert_not_yet_valid">- El certificado del servidor es demasiado reciente</string>
<string name="ssl_validator_reason_cert_not_yet_valid">- El certificado del servidor es de una fecha que aún no llega</string>
<string name="ssl_validator_reason_hostname_not_verified">- La URL no coincide con el nombre de dominio del certificado</string>
<string name="ssl_validator_question">¿Confías de todas formas en este certificado?</string>
<string name="ssl_validator_not_saved">El certificado no pudo ser guardado</string>
@ -237,7 +237,8 @@
<string name="conflict_dont_upload">No subir</string>
<string name="preview_image_description">Previsualización de imagen</string>
<string name="preview_image_error_unknown_format">No se puede mostrar la imagen</string>
<string name="error__upload__local_file_not_copied">%1$s no pudo ser copiado a la carpeta local %2$s</string>
<string name="error__upload__local_file_not_copied">%1$s se pudo copiar a la carpeta local %2$s</string>
<string name="prefs_instant_upload_path_title">Ruta de subida</string>
<string name="share_link_no_support_share_api">La función Compartir no está activada en su servidor. Contacte a su
administrador.</string>
<string name="share_link_file_no_exist">No se puede compartir. Revise si el archivo existe</string>
@ -257,14 +258,14 @@
<string name="forbidden_permissions_rename">para renombrar este archivo</string>
<string name="forbidden_permissions_delete">para eliminar este archivo</string>
<string name="share_link_forbidden_permissions">para compartir este archivo</string>
<string name="unshare_link_forbidden_permissions">para ya no compartir este archivo</string>
<string name="unshare_link_forbidden_permissions">para dejar de compartir este archivo</string>
<string name="forbidden_permissions_create">para crear el archivo</string>
<string name="uploader_upload_forbidden_permissions">para subir archivos a esta carpeta</string>
<string name="downloader_download_file_not_found">Este archivo ya no se encuentra en el servidor</string>
<string name="prefs_category_accounts">Cuentas</string>
<string name="prefs_add_account">Agregar cuenta</string>
<string name="auth_redirect_non_secure_connection_title">La conexión segura está siendo redirigida por una ruta insegura.</string>
<string name="actionbar_logger">Trazas</string>
<string name="auth_redirect_non_secure_connection_title">La conexión segura está siendo desviada por una ruta insegura.</string>
<string name="actionbar_logger">Logs</string>
<string name="log_send_history_button">Enviar historial</string>
<string name="log_mail_subject">Logs de las apps ownCloud Android</string>
<string name="log_progress_dialog_text">Cargando datos...</string>
@ -274,8 +275,10 @@
<string name="file_list_empty_moving">Aquí no hay nada. ¡Puede agregar una carpeta!</string>
<string name="move_choose_button_text">Seleccionar</string>
<string name="move_file_not_found">No se puede mover. Revise si el archivo existe</string>
<string name="move_file_invalid_into_descendent">No se puede mover una carpeta dentro de una de sus descendientes.</string>
<string name="move_file_invalid_into_descendent">No se puede mover una carpeta dentro de una de SUS subcarpetas.</string>
<string name="move_file_invalid_overwrite">El archivo ya existe en la carpeta de destino</string>
<string name="move_file_error">Hubo un error al tratar de mover este archivo o carpeta</string>
<string name="forbidden_permissions_move">para mover este archivo</string>
<string name="prefs_category_instant_uploading">Subidas instantáneas</string>
<string name="prefs_category_security">Seguridad</string>
</resources>

View file

@ -31,6 +31,7 @@
<string name="prefs_feedback">Tagasiside</string>
<string name="prefs_imprint">Impressum</string>
<string name="recommend_subject">Proovi oma nutitelefonil rakendust %1$s!</string>
<string name="recommend_text">Kutsun sind kasutama oma nutitelefonis rakendust %1$s!\nLaadi see alla siit: %2$s</string>
<string name="auth_check_server">Kontrolli serverit</string>
<string name="auth_host_url">Serveri aadress https://...</string>
<string name="auth_username">Kasutajanimi</string>
@ -241,6 +242,7 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi
<string name="preview_image_description">Pildi eelvaade</string>
<string name="preview_image_error_unknown_format">Seda pilti ei saa näidata</string>
<string name="error__upload__local_file_not_copied">%1$s ei suudetud kopeerida kohalikku kataloogi %2$s</string>
<string name="prefs_instant_upload_path_title">Üleslaadimise rada</string>
<string name="share_link_no_support_share_api">Vabandust, server ei toeta jagamist. Palun kontakteeru
⇥⇥administraatoriga.</string>
<string name="share_link_file_no_exist">Jagamine ebaõnnestus. Palun kontrolli, kas fail on olemas</string>
@ -266,7 +268,11 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi
<string name="downloader_download_file_not_found">Fail ei ole serveris enam kättesaadav</string>
<string name="prefs_category_accounts">Kontod</string>
<string name="prefs_add_account">Lisa konto</string>
<string name="auth_redirect_non_secure_connection_title">Turvalist ühendust suunatakse läbi turvamata ühenduse.</string>
<string name="auth_redirect_non_secure_connection_title">Turvaline ühendus suunatakse läbi turvamata ühenduse.</string>
<string name="actionbar_logger">Logid</string>
<string name="log_send_history_button">Saada ajalugu</string>
<string name="log_mail_subject">ownCloud Android rakenduse logid</string>
<string name="log_progress_dialog_text">Andmete laadimine...</string>
<string name="saml_authentication_required_text">Autentimine on vajalik</string>
<string name="saml_authentication_wrong_pass">Vale parool</string>
<string name="actionbar_move">Tõsta ümber</string>
@ -277,4 +283,6 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi
<string name="move_file_invalid_overwrite">See fail on juba sihtkaustas olemas</string>
<string name="move_file_error">Selle faili või kausta liigutamisel tekkis tõrge</string>
<string name="forbidden_permissions_move">selle faili liigutamiseks</string>
<string name="prefs_category_instant_uploading">Kohesed üleslaadimised</string>
<string name="prefs_category_security">Turvalisus</string>
</resources>

View file

@ -258,8 +258,8 @@ Mesedez, baimendu berriz</string>
<string name="downloader_download_file_not_found">Fitxategia jadanik ez dago eskuragarri zerbitzarian</string>
<string name="prefs_category_accounts">Kontuak</string>
<string name="prefs_add_account">Gehitu kontua</string>
<string name="auth_redirect_non_secure_connection_title">Konexio segurua birbideratu da segurua ez den bide batetik.</string>
<string name="saml_authentication_required_text">Autentikazioa beharrezkoa</string>
<string name="saml_authentication_wrong_pass">Pasahitz okerra</string>
<string name="move_choose_button_text">Aukeratu</string>
<string name="prefs_category_security">Segurtasuna</string>
</resources>

View file

@ -232,4 +232,5 @@
<string name="saml_authentication_required_text">احراز هویت مورد نیاز است</string>
<string name="saml_authentication_wrong_pass">رمز عبور اشتباه است</string>
<string name="move_choose_button_text">انتخاب کردن</string>
<string name="prefs_category_security">امنیت</string>
</resources>

View file

@ -218,6 +218,7 @@
<string name="conflict_dont_upload">Älä lähetä</string>
<string name="preview_image_description">Kuvan esikatselu</string>
<string name="preview_image_error_unknown_format">Tätä kuvaa ei voi näyttää</string>
<string name="prefs_instant_upload_path_title">Lähetyspolku</string>
<string name="share_link_no_support_share_api">Jakaminen ei ole käytössä palvelimellasi. Ota yhteys
ylläpitäjään.</string>
<string name="share_link_file_error">Virhe tiedoston tai kansion jakamista yrittäessä</string>
@ -240,7 +241,6 @@
<string name="downloader_download_file_not_found">Tämä tiedosto ei ole enää palvelimella käytettävissä</string>
<string name="prefs_category_accounts">Tilit</string>
<string name="prefs_add_account">Lisää tili</string>
<string name="auth_redirect_non_secure_connection_title">Salattu yhteys on ohjattu uudelleen salaamatonta reittiä pitkin.</string>
<string name="actionbar_logger">Lokit</string>
<string name="log_send_history_button">Lähetä historia</string>
<string name="log_mail_subject">ownCloudin Android-sovelluksen lokit</string>
@ -253,4 +253,6 @@
<string name="move_file_not_found">Siirto ei onnistu. Tarkista, ettei tiedostoa ole jo olemassa</string>
<string name="move_file_invalid_overwrite">Tiedosto on jo olemassa kohdekansiossa</string>
<string name="move_file_error">Tämän tiedoston tai kansion siirtoa yrittäessä tapahtui virhe</string>
<string name="prefs_category_instant_uploading">Välittömät lähetykset</string>
<string name="prefs_category_security">Tietoturva</string>
</resources>

View file

@ -164,7 +164,7 @@ Ci-dessous la liste des fichiers locaux, et les fichiers distants dans %5$s auxq
<string name="auth_bad_oc_version_title">La version du serveur n\'est pas reconnue</string>
<string name="auth_wrong_connection_title">Impossible d\'établir la connexion</string>
<string name="auth_secure_connection">Connexion sécurisée établie</string>
<string name="auth_unauthorized">Nom d\'utilisateur ou mot de passe invalide</string>
<string name="auth_unauthorized">Nom d\'utilisateur ou mot de passe incorrect</string>
<string name="auth_oauth_error">Echec d\'autorisation</string>
<string name="auth_oauth_error_access_denied">Accès refusé par le serveur d\'autorisation</string>
<string name="auth_wtf_reenter_URL">État inattendu ; veuillez entrer à nouveau l\'URL du serveur</string>
@ -267,19 +267,19 @@ Ci-dessous la liste des fichiers locaux, et les fichiers distants dans %5$s auxq
<string name="downloader_download_file_not_found">Ce fichier nest plus disponible sur le serveur</string>
<string name="prefs_category_accounts">Comptes</string>
<string name="prefs_add_account">Ajouter un compte</string>
<string name="auth_redirect_non_secure_connection_title">Le connexion sécurisée est redirigée vers une route non-sécurisée.</string>
<string name="actionbar_logger">Journaux</string>
<string name="log_send_history_button">Historique des envois</string>
<string name="log_send_history_button">Envoyer l\'historique</string>
<string name="log_mail_subject">Journaux de l\'application Android ownCloud</string>
<string name="log_progress_dialog_text">Chargement des données...</string>
<string name="saml_authentication_required_text">Authentification requise</string>
<string name="saml_authentication_wrong_pass">Mot de passe incorrect</string>
<string name="actionbar_move">Déplacer</string>
<string name="file_list_empty_moving">Il n\'y rien ici. Vous pouvez ajouter un dossier !</string>
<string name="file_list_empty_moving">Il n\'y a rien ici. Vous pouvez ajouter un dossier !</string>
<string name="move_choose_button_text">Choisir</string>
<string name="move_file_not_found">Impossible de supprimer. Vérifiez que le fichier est bien présent</string>
<string name="move_file_not_found">Impossible de déplacer. Vérifiez que le fichier existe</string>
<string name="move_file_invalid_into_descendent">Il n\'est pas possible de déplacer un dossier vers un de ses descendants</string>
<string name="move_file_invalid_overwrite">Le fichier existe déjà dans le dossier destinataire</string>
<string name="move_file_invalid_overwrite">Le fichier existe déjà dans le dossier de destination</string>
<string name="move_file_error">Une erreur est survenue lors de la tentative de déplacement de ce fichier ou dossier</string>
<string name="forbidden_permissions_move">de déplacer ce fichier</string>
<string name="prefs_category_security">Sécurité</string>
</resources>

View file

@ -259,9 +259,9 @@
<string name="downloader_download_file_not_found">O ficheiro xa non está dispoñíbel no servidor</string>
<string name="prefs_category_accounts">Contas</string>
<string name="prefs_add_account">Engadir unha conta</string>
<string name="auth_redirect_non_secure_connection_title">A conexión segura está a ser redirixida a través dunha ruta non segura.</string>
<string name="saml_authentication_required_text">Requírese autenticación</string>
<string name="saml_authentication_wrong_pass">Contrasinal incorrecto</string>
<string name="actionbar_move">Mover</string>
<string name="move_choose_button_text">Escoller</string>
<string name="prefs_category_security">Seguranza</string>
</resources>

View file

@ -260,6 +260,6 @@
<string name="downloader_download_file_not_found">הקובץ אינו זמין יותר על השרת</string>
<string name="prefs_category_accounts">חשבונות</string>
<string name="prefs_add_account">הוספת חשבון</string>
<string name="auth_redirect_non_secure_connection_title">חיבור מאובטח מנותב דרך נתיב לא מאובטח</string>
<string name="move_choose_button_text">בחירה</string>
<string name="prefs_category_security">אבטחה</string>
</resources>

View file

@ -36,4 +36,5 @@
<string name="saml_authentication_required_text">Potrebna autentikacija</string>
<string name="saml_authentication_wrong_pass">Pogrešna lozinka</string>
<string name="move_choose_button_text">Izaberi</string>
<string name="prefs_category_security">Sigurnost</string>
</resources>

View file

@ -242,4 +242,5 @@
<string name="saml_authentication_required_text">Felhasználóazonosítás szükséges</string>
<string name="saml_authentication_wrong_pass">Hibás jelszó</string>
<string name="move_choose_button_text">Válasszon</string>
<string name="prefs_category_security">Biztonság</string>
</resources>

View file

@ -6,17 +6,21 @@
<string name="actionbar_upload">Unggah</string>
<string name="actionbar_upload_from_apps">Konten dari apl lain</string>
<string name="actionbar_upload_files">Berkas</string>
<string name="actionbar_open_with">Bukan dengan</string>
<string name="actionbar_open_with">Buka dengan</string>
<string name="actionbar_mkdir">Folder baru</string>
<string name="actionbar_settings">pengaturan</string>
<string name="actionbar_settings">Pengaturan</string>
<string name="actionbar_see_details">Rincian</string>
<string name="actionbar_send_file">Kirim</string>
<string name="prefs_category_general">umum</string>
<string name="prefs_category_general">Umum</string>
<string name="prefs_category_more">Lainnya</string>
<string name="prefs_accounts">Akun</string>
<string name="prefs_manage_accounts">Kelola Akun</string>
<string name="prefs_pincode">PIN Apl</string>
<string name="prefs_pincode_summary">Lindungi klien Anda</string>
<string name="prefs_instant_upload">Unggah gambar cepat</string>
<string name="prefs_instant_upload_summary">Unggah gambar yang diambil kamera dengan cepat</string>
<string name="prefs_instant_video_upload">Unggah video cepat</string>
<string name="prefs_instant_video_upload_summary">Unggah video yang direkam kamera dengan cepat</string>
<string name="prefs_log_title">Aktifkan Pencatatan</string>
<string name="prefs_log_summary">Ini digunakan untuk mencatat masalah</string>
<string name="prefs_log_title_history">Riwayat Catatan</string>
@ -25,8 +29,9 @@
<string name="prefs_help">Bantuan</string>
<string name="prefs_recommend">Rekomendasikan ke teman</string>
<string name="prefs_feedback">Umpan balik</string>
<string name="prefs_imprint">Imprint</string>
<string name="recommend_subject">Coba %1$s pada smartphone Anda!</string>
<string name="prefs_imprint">Jejak</string>
<string name="recommend_subject">Cobalah %1$s pada ponsel cerdas Anda!</string>
<string name="recommend_text">Saya ingin mengajak Anda untuk menggunakan %1$s di ponsel cerdas Anda!\nUnduh gratis disini: %2$s</string>
<string name="auth_check_server">Periksa Server</string>
<string name="auth_host_url">Alamat server https://…</string>
<string name="auth_username">Nama Pengguna</string>
@ -35,6 +40,7 @@
<string name="sync_string_files">Berkas</string>
<string name="setup_btn_connect">Sambungkan</string>
<string name="uploader_btn_upload_text">Unggah</string>
<string name="uploader_top_message">Pilih folder unggah:</string>
<string name="uploader_wrn_no_account_title">Tidak ada akun yang ditemukan</string>
<string name="uploader_wrn_no_account_text">Belum ada akun %1$s pada perangkat Anda. Silahkan buat akun terlebih dahulu.</string>
<string name="uploader_wrn_no_account_setup_btn_text">Pengaturan</string>
@ -44,6 +50,8 @@
<string name="uploader_error_forbidden_content">%1$s tidak diizinkan mengakses konten berbagi</string>
<string name="uploader_info_uploading">Mengunggah</string>
<string name="file_list_empty">Tidak ada apa-apa di sini. Unggah sesuatu!</string>
<string name="file_list_loading">Memuat...</string>
<string name="local_file_list_empty">Tidak ada satupun berkas dalam folder ini.</string>
<string name="filedetails_select_file">Sentuh pada berkas untuk menampilkan informasi tambahan</string>
<string name="filedetails_size">Ukuran:</string>
<string name="filedetails_type">Tipe:</string>
@ -53,6 +61,7 @@
<string name="filedetails_sync_file">Segarkan berkas</string>
<string name="filedetails_renamed_in_upload_msg">Berkas diubah namanya menjadi %1$s saat pengunggahan</string>
<string name="action_share_file">Bagikan tautan</string>
<string name="action_unshare_file">Batal bagikan tautan</string>
<string name="common_yes">Ya</string>
<string name="common_no">Tidak</string>
<string name="common_ok">Oke</string>
@ -82,19 +91,26 @@
<string name="downloader_download_failed_ticker">Gagal Mengunduh</string>
<string name="downloader_download_failed_content">Mengunduh %1$s tidak selesai</string>
<string name="downloader_not_downloaded_yet">Belum diunduh</string>
<string name="downloader_download_failed_credentials_error">Gagal mengunduh, Anda perlu masuk kembali</string>
<string name="common_choose_account">Pilih akun</string>
<string name="sync_fail_ticker">Sinkronisasi gagal</string>
<string name="sync_fail_ticker_unauthorized">Sinkronisasi gagal, Anda perlu masuk kembali</string>
<string name="sync_fail_content">Sinkronisasi %1$s tidak selesai</string>
<string name="sync_fail_content_unauthorized">Sandi salah untuk %1$s</string>
<string name="sync_conflicts_in_favourites_ticker">Konflik ditemukan</string>
<string name="sync_conflicts_in_favourites_content">%1$d berkas kept-in-sync tidak dapat disinkronkan</string>
<string name="sync_fail_in_favourites_ticker">Berkas kept-in-sync gagal</string>
<string name="sync_fail_in_favourites_content">Konten berkas %1$d tidak dapat disinkronasikan (%2$d konflik)</string>
<string name="sync_foreign_files_forgotten_ticker">Beberapa berkas lokal terlupakan</string>
<string name="sync_foreign_files_forgotten_content">%1$d berkas diluar folder %2$s tidak dapat disalin kedalamnya</string>
<string name="sync_foreign_files_forgotten_explanation">Sejak versi 1.3.16, berkas-berkas yang diunggah dari piranti ini akan disalin kedalam folder %1$s lokal untuk mencagah kehilangan data ketika berkas tunggal disinkronkan dengan akun lebih dari satu.\n\nAkibat perubahan ini, semua berkas yang diunggah di versi aplikasi sebelumnya disalin kedalam folder %2$s. Namun, sebuah kesalahan mencegah penyelesaian operasi ini saat sinkronisasi berlangsung akun. Anda boleh meninggalkan berkas seperti ini dan menghapus tautan ke %3$s atau memindahkan berkas kedalam folder %1$s dan membiarkan tautan ke %4$s.\n\nYang tampak dibawah adalah berkas lokal, dan berkas remote didalam %5$s yang dihubungkan dengannya.</string>
<string name="sync_current_folder_was_removed">Folder %1$s tidak ada lagi</string>
<string name="foreign_files_move">Pindahkan semua</string>
<string name="foreign_files_success">Semua berkas sudah dipindahkan</string>
<string name="foreign_files_fail">Beberapa berkas tidak dapat dipindahkan</string>
<string name="foreign_files_local_text">Lokal: %1$s</string>
<string name="foreign_files_remote_text">Jauh: %1$s</string>
<string name="upload_query_move_foreign_files">Ruang tidak cukup untuk menyalin berkas terpilih kedalam folder %1$s. Apakah Anda ingin memindahkannya saja?</string>
<string name="pincode_enter_pin_code">Silakan masukkan PIN Apl</string>
<string name="pincode_configure_your_pin">Masukkan PIN Apl</string>
<string name="pincode_configure_your_pin_explanation">PIN akan selalu diminta setiap kali apl dijalankan</string>
@ -107,6 +123,7 @@
<string name="media_notif_ticker">Pemutar musik %1$s</string>
<string name="media_state_playing">%1$s (dimainkan)</string>
<string name="media_state_loading">%1$s (sedang dimuat)</string>
<string name="media_event_done">%1$s pemutaran selesai</string>
<string name="media_err_nothing_to_play">Tidak ditemukan berkas media</string>
<string name="media_err_no_account">Tidak ada akun yang diberikan</string>
<string name="media_err_not_in_owncloud">Brkas tidak didalam akun yang sah</string>
@ -122,6 +139,7 @@
<string name="media_rewind_description">Tombol mundur</string>
<string name="media_play_pause_description">Tombol main dan jeda</string>
<string name="media_forward_description">Tombol maju</string>
<string name="auth_getting_authorization">Mendapatkan otorisasi...</string>
<string name="auth_trying_to_login">Mencoba untuk masuk...</string>
<string name="auth_no_net_conn_title">Tidak ada koneksi internet</string>
<string name="auth_nossl_plain_ok_title">Sambungan aman tidak tersedia</string>
@ -150,9 +168,12 @@
<string name="auth_connecting_auth_server">Menyambungkan ke server otentikasi...</string>
<string name="auth_unsupported_auth_method">Server tidak mendukung medote otentikasi ini</string>
<string name="auth_unsupported_multiaccount">%1$s tidak mendukung banyak akun </string>
<string name="auth_can_not_auth_against_server">Tidak dapat mengotentikasi pada server ini</string>
<string name="fd_keep_in_sync">Biarkan berkas tetap terbaru</string>
<string name="common_rename">Ubah nama</string>
<string name="common_remove">Hapus</string>
<string name="confirmation_remove_alert">Apakah Anda yakin ingin menghapus %1$s?</string>
<string name="confirmation_remove_folder_alert">Apakah Anda yakin ingin menghapus %1$s dan isinya?</string>
<string name="confirmation_remove_local">Lokal saja</string>
<string name="confirmation_remove_folder_local">Konten lokal saja</string>
<string name="confirmation_remove_remote">Hapus dari server</string>
@ -164,10 +185,13 @@
<string name="rename_server_fail_msg">Mengubah nama tidak selesai</string>
<string name="sync_file_fail_msg">Berkas jauh tidak dapat diperiksa</string>
<string name="sync_file_nothing_to_do_msg">Isi berkas sudah diselaraskan</string>
<string name="create_dir_fail_msg">Folder tidak dapat dibuat</string>
<string name="filename_forbidden_characters">Karakter yang dilarang: / \\ &lt; &gt; : \" | ? *</string>
<string name="wait_a_moment">Tunggu sejenak</string>
<string name="filename_empty">Nama berkas tidak boleh kosong</string>
<string name="wait_a_moment">Tunggu sebentar</string>
<string name="filedisplay_unexpected_bad_get_content">Masalah tidak terduga, silahkan pilih berkas dari apl yang berbeda</string>
<string name="filedisplay_no_file_selected">Tidak ada berkas yang terpilih</string>
<string name="activity_chooser_title">Kirim taukan ke</string>
<string name="oauth_check_onoff">Masuk dengan oAuth2</string>
<string name="oauth_login_connection">Menyambungkan ke server oAuth2...</string>
<string name="ssl_validator_header">Identitas situs tidak dapat diverfikasi</string>
@ -192,6 +216,8 @@
<string name="ssl_validator_label_validity_to">Untuk:</string>
<string name="ssl_validator_label_signature">Tanda tangan:</string>
<string name="ssl_validator_label_signature_algorithm">Algoritma:</string>
<string name="ssl_validator_null_cert">Sertifikat tidak dapat ditampilkan.</string>
<string name="ssl_validator_no_info_about_error">- Tidak ada informasi tantang terror</string>
<string name="placeholder_sentence">Ini adalah placeholder</string>
<string name="placeholder_filename">placeholder.txt</string>
<string name="placeholder_filetype">Gambar PNG</string>
@ -199,6 +225,7 @@
<string name="placeholder_timestamp">18/05/2012 12:23 PM</string>
<string name="placeholder_media_time">12:23:45</string>
<string name="instant_upload_on_wifi">Hanya unggah gambar via WiFi</string>
<string name="instant_video_upload_on_wifi">Hanya unggah video via WiFi</string>
<string name="instant_upload_path">/UnggahInstan</string>
<string name="conflict_title">Perbarui benturan</string>
<string name="conflict_message">Berkas jauh %s tidak sinkron dengan berkas lokal. Melanjutkan akan menggantikan konten berkas di server.</string>
@ -206,10 +233,13 @@
<string name="conflict_overwrite">Timpa</string>
<string name="conflict_dont_upload">Jangan mengunggah</string>
<string name="preview_image_description">Pratilik gambar</string>
<string name="preview_image_error_unknown_format">Gambar ini tidak dapat ditampilkan</string>
<string name="activity_chooser_send_file_title">Kirim</string>
<string name="clipboard_text_copied">Disalin ke papan klip</string>
<string name="empty"></string>
<string name="prefs_category_accounts">Akun</string>
<string name="saml_authentication_required_text">Diperlukan otentikasi</string>
<string name="saml_authentication_wrong_pass">Sandi salah</string>
<string name="move_choose_button_text">Pilih</string>
<string name="prefs_category_security">Keamanan</string>
</resources>

View file

@ -263,7 +263,6 @@
<string name="downloader_download_file_not_found">Il file non è più disponibile sul server</string>
<string name="prefs_category_accounts">Account</string>
<string name="prefs_add_account">Aggiungi account</string>
<string name="auth_redirect_non_secure_connection_title">La connessione sicura è rediretta attraverso un percorso non sicuro.</string>
<string name="actionbar_logger">Registri</string>
<string name="log_send_history_button">Invia cronologia</string>
<string name="log_mail_subject">Registri applicazione ownCloud Android</string>
@ -278,4 +277,5 @@
<string name="move_file_invalid_overwrite">Il file esiste già nella cartella di destinazione</string>
<string name="move_file_error">Si è verificato un errore durante il tentativo di spostare il file o la cartella</string>
<string name="forbidden_permissions_move">per spostare questo file</string>
<string name="prefs_category_security">Protezione</string>
</resources>

View file

@ -264,7 +264,6 @@
<string name="downloader_download_file_not_found">ファイルはサーバー上で利用できません</string>
<string name="prefs_category_accounts">アカウント</string>
<string name="prefs_add_account">アカウントを追加</string>
<string name="auth_redirect_non_secure_connection_title">暗号化されていない接続を経て、暗号化接続へリダイレクトされました。</string>
<string name="actionbar_logger">ログ</string>
<string name="log_send_history_button">ログを送信</string>
<string name="log_mail_subject">ownCloud Android アプリログ</string>
@ -279,4 +278,5 @@
<string name="move_file_invalid_overwrite">そのファイルは、宛先フォルダに既に存在しています。</string>
<string name="move_file_error">このファイルまたはフォルダーを移動する際にエラーが発生しました</string>
<string name="forbidden_permissions_move">このファイルを移動</string>
<string name="prefs_category_security">セキュリティ</string>
</resources>

View file

@ -149,4 +149,5 @@
<string name="empty"></string>
<string name="prefs_category_accounts">ანგარიში</string>
<string name="move_choose_button_text">არჩევა</string>
<string name="prefs_category_security">უსაფრთხოება</string>
</resources>

View file

@ -83,4 +83,5 @@
<string name="prefs_category_accounts">គណនី</string>
<string name="saml_authentication_wrong_pass">ខុស​ពាក្យ​សម្ងាត់</string>
<string name="move_choose_button_text">ជ្រើស</string>
<string name="prefs_category_security">សុវត្ថិភាព</string>
</resources>

View file

@ -217,4 +217,5 @@
<string name="saml_authentication_required_text">인증 필요함</string>
<string name="saml_authentication_wrong_pass">잘못된 암호</string>
<string name="move_choose_button_text">선택</string>
<string name="prefs_category_security">보안</string>
</resources>

View file

@ -234,4 +234,5 @@
<string name="prefs_category_accounts">Paskyros</string>
<string name="saml_authentication_wrong_pass">Neteisingas slaptažodis</string>
<string name="move_choose_button_text">Pasirinkite</string>
<string name="prefs_category_security">Saugumas</string>
</resources>

View file

@ -143,4 +143,5 @@
<string name="empty"></string>
<string name="prefs_category_accounts">Konti</string>
<string name="move_choose_button_text">Izvēlieties</string>
<string name="prefs_category_security">Drošība</string>
</resources>

View file

@ -122,4 +122,5 @@
<string name="saml_authentication_required_text">Потребна е автентификација</string>
<string name="saml_authentication_wrong_pass">Погрешна лозинка</string>
<string name="move_choose_button_text">Избери</string>
<string name="prefs_category_security">Безбедност</string>
</resources>

View file

@ -263,7 +263,6 @@
<string name="downloader_download_file_not_found">Filen finnes ikke på serveren lenger</string>
<string name="prefs_category_accounts">Kontoer</string>
<string name="prefs_add_account">Legg til en konto</string>
<string name="auth_redirect_non_secure_connection_title">Sikker tilkobling videresendes gjennom en usikker rute.</string>
<string name="actionbar_logger">Logger</string>
<string name="log_send_history_button">Send historikk</string>
<string name="log_mail_subject">logger for ownCloud Android app</string>
@ -278,4 +277,5 @@
<string name="move_file_invalid_overwrite">Filen finnes allerede i målmappen</string>
<string name="move_file_error">En feil oppstod ved flytting av denne filen eller mappen</string>
<string name="forbidden_permissions_move">å flytte denne filen</string>
<string name="prefs_category_security">Sikkerhet</string>
</resources>

View file

@ -241,6 +241,7 @@ Hieronder staan de lokale bestanden en de externe bestanden in %5$s waar ze naar
<string name="preview_image_description">Afbeelding voorbeeld</string>
<string name="preview_image_error_unknown_format">Deze afbeelding kan niet worden getoond</string>
<string name="error__upload__local_file_not_copied">%1$s kon niet worden gekopieerd naar de %2$s lokale map</string>
<string name="prefs_instant_upload_path_title">Upload pad</string>
<string name="share_link_no_support_share_api">Sorry, delen is niet mogelijk op uw server. Neem contact op met uw
beheerder.</string>
<string name="share_link_file_no_exist">Kan dit niet delen. Controleer of dit bestand wel bestaat.</string>
@ -266,7 +267,7 @@ Hieronder staan de lokale bestanden en de externe bestanden in %5$s waar ze naar
<string name="downloader_download_file_not_found">Dit bestand is niet langer beschikbaar op de server</string>
<string name="prefs_category_accounts">Accounts</string>
<string name="prefs_add_account">Toevoegen account</string>
<string name="auth_redirect_non_secure_connection_title">De beveiligde verbinding is omgeleid via een onveilige route.</string>
<string name="auth_redirect_non_secure_connection_title">De beveiligde verbinding is omgeleid naar een onveilige route.</string>
<string name="actionbar_logger">Logs</string>
<string name="log_send_history_button">Verstuur geschiedenis</string>
<string name="log_mail_subject">ownCloud Android app logs</string>
@ -281,4 +282,6 @@ Hieronder staan de lokale bestanden en de externe bestanden in %5$s waar ze naar
<string name="move_file_invalid_overwrite">Het bestand bestaat al in de doelmap</string>
<string name="move_file_error">Er trad een fout op bij uw poging dit bestand of deze map te verplaatsen</string>
<string name="forbidden_permissions_move">om dit bestand te verplaatsen</string>
<string name="prefs_category_instant_uploading">Directe uploads</string>
<string name="prefs_category_security">Beveiliging</string>
</resources>

View file

@ -129,4 +129,5 @@
<string name="prefs_category_accounts">Kontoar</string>
<string name="saml_authentication_wrong_pass">Feil passord</string>
<string name="move_choose_button_text">Vel</string>
<string name="prefs_category_security">Tryggleik</string>
</resources>

View file

@ -263,7 +263,6 @@
<string name="downloader_download_file_not_found">Ten plik nie jest już dostępny na serwerze</string>
<string name="prefs_category_accounts">Konta</string>
<string name="prefs_add_account">Dodaj konto</string>
<string name="auth_redirect_non_secure_connection_title">Bezpieczne połączenie jest przekierowywane przez niezabezpieczone trasy.</string>
<string name="actionbar_logger">Logi</string>
<string name="log_send_history_button">Wyślij historię</string>
<string name="log_progress_dialog_text">Ładuję dane...</string>
@ -277,4 +276,5 @@
<string name="move_file_invalid_overwrite">Plik istnieje już w folderze docelowym</string>
<string name="move_file_error">Pojawił się błąd podczas próby przeniesienia tego pliku lub folderu</string>
<string name="forbidden_permissions_move">aby przenieść ten plik</string>
<string name="prefs_category_security">Bezpieczeństwo</string>
</resources>

View file

@ -238,6 +238,7 @@
<string name="preview_image_description">Pré-visualização da imagem</string>
<string name="preview_image_error_unknown_format">Esta imagem não pode ser mostrada</string>
<string name="error__upload__local_file_not_copied">%1$s não pôde ser copiado para pasta local %2$s</string>
<string name="prefs_instant_upload_path_title">Enviar Caminho</string>
<string name="share_link_no_support_share_api">Desculpe, o compartilhamento não está habilitado em seu servidor. Entre em contato com seu
⇥⇥ administrador.</string>
<string name="share_link_file_no_exist">Não é possível compartilhar. Por favor verifique se o arquivo existe</string>
@ -263,7 +264,7 @@
<string name="downloader_download_file_not_found">Este arquivo não mais está disponível neste servidor</string>
<string name="prefs_category_accounts">Contas</string>
<string name="prefs_add_account">Adicionar uma conta</string>
<string name="auth_redirect_non_secure_connection_title">A conexão segura está redirecionada através de uma rota insegura.</string>
<string name="auth_redirect_non_secure_connection_title">Conexão segura esta redirecionada para uma rota não segura.</string>
<string name="actionbar_logger">Logs</string>
<string name="log_send_history_button">Enviar Histórico</string>
<string name="log_mail_subject">Logs do aplicativo ownCloud Android</string>
@ -278,4 +279,6 @@
<string name="move_file_invalid_overwrite">O arquivo já existe na pasta de destino</string>
<string name="move_file_error">Ocorreu um erro ao tentar mover este arquivo ou pasta</string>
<string name="forbidden_permissions_move">mover este arquivo</string>
<string name="prefs_category_instant_uploading">Envios Instantâneos</string>
<string name="prefs_category_security">Segurança</string>
</resources>

View file

@ -31,6 +31,7 @@
<string name="prefs_feedback">Resposta</string>
<string name="prefs_imprint">Imprint</string>
<string name="recommend_subject">Experimente %1$s no seu smartphone!</string>
<string name="recommend_text">Quero convidar-te a usares %1$s no teu smartphone!\nFaz download aqui: %2$s</string>
<string name="auth_check_server">Verificar Servidor</string>
<string name="auth_host_url">Endereço do servidor https://..</string>
<string name="auth_username">Nome de Utilizador</string>
@ -236,9 +237,11 @@
<string name="preview_image_description">Pré-Visualização da imagem</string>
<string name="preview_image_error_unknown_format">Esta imagem não pode ser mostrada</string>
<string name="error__upload__local_file_not_copied">Não foi possível copiar %1$s para a pasta local %2$s</string>
<string name="prefs_instant_upload_path_title">Caminho de Upload</string>
<string name="share_link_no_support_share_api">Lamentamos mas não é possível partilhar através do seu servidor. Por favor contacte o seu administrador.</string>
<string name="share_link_file_no_exist">Não é possivel partilhar. Por favor verifique se o ficheiro existe</string>
<string name="share_link_file_error">Ocorreu um erro enquanto tentava partilhar este ficheiro ou pasta</string>
<string name="unshare_link_file_no_exist">Não é possível retirar a partilha. Verifique se o ficheiro existe</string>
<string name="unshare_link_file_error">Ocorreu um erro enquanto retirava a partilha deste ficheiro ou pasta</string>
<string name="activity_chooser_send_file_title">Enviar</string>
<string name="copy_link">Copiar ligação</string>
@ -259,14 +262,21 @@
<string name="downloader_download_file_not_found">O ficheiro não está mais disponível no servidor</string>
<string name="prefs_category_accounts">Contas</string>
<string name="prefs_add_account">Adicionar conta</string>
<string name="auth_redirect_non_secure_connection_title">Uma ligação segura foi redireccionada por uma rota insegura.</string>
<string name="auth_redirect_non_secure_connection_title">Ligação segura é redireccionada para um caminho inseguro.</string>
<string name="actionbar_logger">Logs</string>
<string name="log_send_history_button">Enviar Histórico</string>
<string name="log_mail_subject">Logs da app ownCloud Android</string>
<string name="log_progress_dialog_text">A carregar os dados...</string>
<string name="saml_authentication_required_text">Autenticação necessária</string>
<string name="saml_authentication_wrong_pass">Password errada</string>
<string name="actionbar_move">Mover</string>
<string name="file_list_empty_moving">Não está aqui nada. Pode adicionar uma pasta!</string>
<string name="move_choose_button_text">Escolha</string>
<string name="move_file_not_found">Não é possível mover. Verifique se o ficheiro existe</string>
<string name="move_file_invalid_into_descendent">Não é possível mover esta pasta deste modo</string>
<string name="move_file_invalid_overwrite">O ficheiro já existe na pasta de destino</string>
<string name="move_file_error">Um erro ocorreu ao tentar mover este ficheiro ou pasta</string>
<string name="forbidden_permissions_move">para mover este ficheiro</string>
<string name="prefs_category_instant_uploading">Uploads Instantâneos</string>
<string name="prefs_category_security">Segurança</string>
</resources>

View file

@ -259,4 +259,5 @@
<string name="prefs_category_accounts">Conturi</string>
<string name="saml_authentication_wrong_pass">Parolă greșită</string>
<string name="move_choose_button_text">Alege</string>
<string name="prefs_category_security">Securitate</string>
</resources>

View file

@ -263,7 +263,6 @@
<string name="downloader_download_file_not_found">Этот файл больше недоступен на сервере</string>
<string name="prefs_category_accounts">Учётные записи</string>
<string name="prefs_add_account">Добавить учетную запись</string>
<string name="auth_redirect_non_secure_connection_title">Безопасное соединение перенаправлено через небезопасный маршрут.</string>
<string name="actionbar_logger">Журналы</string>
<string name="log_send_history_button">История Отправлений</string>
<string name="log_mail_subject">Журналы Андроид-приложения ownCloud</string>
@ -278,4 +277,5 @@
<string name="move_file_invalid_overwrite">Файл уже существует в папке назначения</string>
<string name="move_file_error">Произошла ошибка при попытке перемещения этого файла или папки</string>
<string name="forbidden_permissions_move">переместить этот файл</string>
<string name="prefs_category_security">Безопасность</string>
</resources>

View file

@ -259,9 +259,9 @@
<string name="downloader_download_file_not_found">Súbor už na serveri nie je dostupný</string>
<string name="prefs_category_accounts">Účty</string>
<string name="prefs_add_account">Pridať účet</string>
<string name="auth_redirect_non_secure_connection_title">Zabezpečené spojenie je presmerované nezabezpečenou cestou.</string>
<string name="saml_authentication_required_text">Vyžaduje sa overenie</string>
<string name="saml_authentication_wrong_pass">Nesprávne heslo</string>
<string name="actionbar_move">Presunúť</string>
<string name="move_choose_button_text">Vybrať</string>
<string name="prefs_category_security">Zabezpečenie</string>
</resources>

View file

@ -263,7 +263,6 @@
<string name="downloader_download_file_not_found">Datoteka na strežniku ni več na voljo.</string>
<string name="prefs_category_accounts">Računi</string>
<string name="prefs_add_account">Dodaj račun</string>
<string name="auth_redirect_non_secure_connection_title">Varna povezava je preusmerjena preko ne-varne poti.</string>
<string name="actionbar_logger">Dnevnik</string>
<string name="log_send_history_button">Pošlji zgodovino</string>
<string name="log_mail_subject">Dnevnik programa ownCloud</string>
@ -278,4 +277,5 @@
<string name="move_file_invalid_overwrite">Datoteka v ciljni mapi že obstaja.</string>
<string name="move_file_error">Prišlo je do napake med premikanjem datoteke v mapo</string>
<string name="forbidden_permissions_move">med premikanjem datoteke</string>
<string name="prefs_category_security">Varnost</string>
</resources>

View file

@ -72,4 +72,5 @@
<string name="prefs_category_accounts">Llogarit</string>
<string name="saml_authentication_wrong_pass">Fjalëkalim i gabuar</string>
<string name="move_choose_button_text">Zgjidh</string>
<string name="prefs_category_security">Siguria</string>
</resources>

View file

@ -109,4 +109,5 @@
<string name="empty"></string>
<string name="prefs_category_accounts">Налози</string>
<string name="move_choose_button_text">Одабери</string>
<string name="prefs_category_security">Безбедност</string>
</resources>

View file

@ -30,7 +30,8 @@
<string name="prefs_recommend">Rekommendera till en vän</string>
<string name="prefs_feedback">Feedback</string>
<string name="prefs_imprint">Imprint</string>
<string name="recommend_subject">Försök %1$s på din smarttelefon!</string>
<string name="recommend_subject">Prova %1$s på din smartphone!</string>
<string name="recommend_text">Jag skullje vilja bjuda in dig till att prova %1$s på din smartphone!\nLadda ner appen från Google Play här: %2$s</string>
<string name="auth_check_server">Kontrollera Server</string>
<string name="auth_host_url">Serveradress https://...</string>
<string name="auth_username">Användarnamn</string>
@ -50,6 +51,7 @@
<string name="uploader_info_uploading">Laddar upp</string>
<string name="file_list_empty">Ingenting här. Ladda upp något!</string>
<string name="file_list_loading">Laddar...</string>
<string name="local_file_list_empty">Det finns inga filer i den här mappen.</string>
<string name="filedetails_select_file">Peka på en fil för att visa mer information.</string>
<string name="filedetails_size">Storlek:</string>
<string name="filedetails_type">Typ:</string>
@ -93,6 +95,7 @@
<string name="downloader_download_failed_credentials_error">Nerladda misslyckades, måste du logga in igen</string>
<string name="common_choose_account">Välj konto</string>
<string name="sync_fail_ticker">Synkroniseringen misslyckades</string>
<string name="sync_fail_ticker_unauthorized">Synkroniseringen misslyckades, du måste logga in på nytt.</string>
<string name="sync_fail_content">Synkronisering av %1$s kunde inte slutföras</string>
<string name="sync_fail_content_unauthorized">Felaktigt lösenord för %1$s</string>
<string name="sync_conflicts_in_favourites_ticker">Konflikter uppstod</string>
@ -247,8 +250,23 @@
<string name="network_error_connect_timeout_exception">Ett fel uppstod i väntan på servern, operationen kunde inte ha gjorts</string>
<string name="network_host_not_available">Åtgärden kunte inte slutföras, servern är ej tillgänglig</string>
<string name="empty"></string>
<string name="forbidden_permissions">Du har inga rättigheter %s</string>
<string name="forbidden_permissions_rename">att döpa om denna fil</string>
<string name="forbidden_permissions_delete">att radera denna fil</string>
<string name="share_link_forbidden_permissions">att dela denna fil</string>
<string name="unshare_link_forbidden_permissions">att avbryta delningen utav denna fil</string>
<string name="forbidden_permissions_create">att skapa filen</string>
<string name="uploader_upload_forbidden_permissions">att ladda upp i den här mappen</string>
<string name="downloader_download_file_not_found">Filen är inte längre tillgänglig på servern</string>
<string name="prefs_category_accounts">Konton</string>
<string name="prefs_add_account">Lägg till konto</string>
<string name="log_progress_dialog_text">Laddar data...</string>
<string name="saml_authentication_required_text">Autentisering krävs</string>
<string name="saml_authentication_wrong_pass">Fel lösenord</string>
<string name="actionbar_move">Flytta</string>
<string name="file_list_empty_moving">Ingenting här. Du kan skapa en mapp!</string>
<string name="move_choose_button_text">Välj</string>
<string name="move_file_not_found">Gick inte att flytta. Vänligen kontrollera att filen existerar</string>
<string name="forbidden_permissions_move">att flytta den här filen</string>
<string name="prefs_category_security">Säkerhet</string>
</resources>

View file

@ -238,6 +238,7 @@
<string name="preview_image_description">Resim önizleme</string>
<string name="preview_image_error_unknown_format">Bu resim gösterilemiyor</string>
<string name="error__upload__local_file_not_copied">%1$s, %2$s yerel klasörüne kopyalanamadı</string>
<string name="prefs_instant_upload_path_title">Yükleme Yolu</string>
<string name="share_link_no_support_share_api">Üzgünüz, paylaşım sunucunuzda etkin değil. Lütfen yöneticinizle
iletişime geçin.</string>
<string name="share_link_file_no_exist">Paylaşma başarısız. Lütfen dosyanın mevcut olup olmadığını denetleyin</string>
@ -263,7 +264,7 @@
<string name="downloader_download_file_not_found">Bu dosya artık sunucuda mevcut değil</string>
<string name="prefs_category_accounts">Hesaplar</string>
<string name="prefs_add_account">Hesap ekle</string>
<string name="auth_redirect_non_secure_connection_title">Güvenli bağlantı, güvenli olmayan bir rotaya yönlendiriliyor.</string>
<string name="auth_redirect_non_secure_connection_title">Güvenli bağlantı, güvenli olmayan bir rotaya yönlendirildi.</string>
<string name="actionbar_logger">Günlükler</string>
<string name="log_send_history_button">Geçmişi Gönder</string>
<string name="log_mail_subject">ownCloud Android uygulama kayıtları</string>
@ -278,4 +279,6 @@
<string name="move_file_invalid_overwrite">Dosya zaten hedef klasörde mevcut</string>
<string name="move_file_error">Bu dosya veya klasörü taşımaya çalışılırken bir hata oluştu</string>
<string name="forbidden_permissions_move">bu dosyayı taşımak için</string>
<string name="prefs_category_instant_uploading">Anında Yüklemeler</string>
<string name="prefs_category_security">Güvenlik</string>
</resources>

View file

@ -41,4 +41,5 @@
<string name="activity_chooser_send_file_title">يوللا</string>
<string name="empty"></string>
<string name="prefs_category_accounts">ھېساباتلار</string>
<string name="prefs_category_security">بىخەتەرلىك</string>
</resources>

View file

@ -1,8 +1,12 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="about_android">%1$s Android App</string>
<string name="about_version">версія %1$s</string>
<string name="actionbar_sync">Оновити account</string>
<string name="actionbar_upload">Відвантажити</string>
<string name="actionbar_upload_from_apps">Вміст із інших програм</string>
<string name="actionbar_upload_files">Файли</string>
<string name="actionbar_open_with">Відкрити за допомогою</string>
<string name="actionbar_mkdir">Нова тека</string>
<string name="actionbar_settings">Налаштування</string>
<string name="actionbar_see_details">Деталі</string>
@ -13,14 +17,30 @@
<string name="prefs_manage_accounts">Управління обліковими записами</string>
<string name="prefs_pincode">App програмний PIN</string>
<string name="prefs_pincode_summary">Захист Вашог App клієнта</string>
<string name="prefs_instant_upload">Миттєві зображення</string>
<string name="prefs_instant_upload_summary">Миттєві зображення з камери</string>
<string name="prefs_instant_video_upload">Миттєві відео</string>
<string name="prefs_instant_video_upload_summary">Миттєві відео з камери</string>
<string name="prefs_log_title">Ввімкнути журнал</string>
<string name="prefs_log_summary">Використовується для реєстрації помилок</string>
<string name="prefs_log_title_history">Журнал</string>
<string name="prefs_log_summary_history">Тут показані записи журналу</string>
<string name="prefs_log_delete_history_button">Видалити історію записів</string>
<string name="prefs_help">Допомога</string>
<string name="prefs_recommend">Порадити товаришу</string>
<string name="prefs_feedback">Зворотній зв\'язок</string>
<string name="prefs_imprint">Відбиток</string>
<string name="recommend_subject">Спробуйте %1$s на своєму смартфоні!</string>
<string name="recommend_text">Пропоную вам користуватися %1$s на вашому смартфоні!\nЗавантажити можна за посиланням: %2$s</string>
<string name="auth_check_server">Перевірити сервер</string>
<string name="auth_host_url">Адреса серверу https://…</string>
<string name="auth_username">Ім\'я користувача</string>
<string name="auth_password">Пароль</string>
<string name="auth_register">Вперше в %1$s?</string>
<string name="sync_string_files">Файли</string>
<string name="setup_btn_connect">З\'єднати</string>
<string name="uploader_btn_upload_text">Відвантажити</string>
<string name="uploader_top_message">Оберіть теку для завантаження:</string>
<string name="uploader_wrn_no_account_title">Не знайдено облікового запису</string>
<string name="uploader_wrn_no_account_text">На Вашому пристрої відсутні облікові записи %1$s. Будь ласка, спочатку створіть запис.</string>
<string name="uploader_wrn_no_account_setup_btn_text">Налаштування</string>
@ -30,14 +50,18 @@
<string name="uploader_error_forbidden_content">%1$s не може отримати доступ до спільного контенту</string>
<string name="uploader_info_uploading">Завантаження</string>
<string name="file_list_empty">Тут нічого немає. Відвантажте що-небудь!</string>
<string name="file_list_loading">Завантаження...</string>
<string name="local_file_list_empty">В цій теці немає файлів.</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_renamed_in_upload_msg">Файл був переіменований в %1$s протягом вивантаження</string>
<string name="action_share_file">Опублікувати посилання</string>
<string name="action_unshare_file">Видалити посилання</string>
<string name="common_yes">Так</string>
<string name="common_no">Ні</string>
<string name="common_ok">OK</string>
@ -46,6 +70,7 @@
<string name="common_cancel">Відмінити</string>
<string name="common_save_exit">Зберегти &amp; Вихід</string>
<string name="common_error">Помилка</string>
<string name="common_loading">Завантаження...</string>
<string name="common_error_unknown">Невідома помилка</string>
<string name="about_title">Про</string>
<string name="change_password">Змінити пароль</string>
@ -59,25 +84,34 @@
<string name="uploader_upload_succeeded_content_single">%1$s було успішно завантажено</string>
<string name="uploader_upload_failed_ticker">Помилка завантаження</string>
<string name="uploader_upload_failed_content_single">Завантаження %1$s не може завершитись</string>
<string name="uploader_upload_failed_credentials_error">Завантажити не вдалося, необхідно повторити вхід</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$s успішно завантажено</string>
<string name="downloader_download_failed_ticker">Завантаження не вдалося</string>
<string name="downloader_download_failed_content">Завантаження %1$s не вдається завершити</string>
<string name="downloader_not_downloaded_yet">Ще не завантажене</string>
<string name="downloader_download_failed_credentials_error">Зберегти не вдалося, необхідно повторити вхід</string>
<string name="common_choose_account">Оберіть обліковий запис</string>
<string name="sync_fail_ticker">Помилка синхронізації</string>
<string name="sync_fail_ticker_unauthorized">Синхронізація не вдалася, необхідно повторити вхід</string>
<string name="sync_fail_content">Синхронізація %1$s не вдалась</string>
<string name="sync_fail_content_unauthorized">Невірний пароль для %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="sync_foreign_files_forgotten_ticker">Деякі локальні файли були забуті</string>
<string name="sync_foreign_files_forgotten_content">Неможливо скопіювати %1$d файли з теки %2$s</string>
<string name="sync_foreign_files_forgotten_explanation">\"Починаючи з версії 1.3.16, файли, завантажені з цього пристрою копіюються в локальну теку %1$s для запобігання втрати даних під час синхронізації одного файлу з кількома обліковими записами.\n\nТому всі файли, завантажені в попередніх версіях цього додатку були скопійовані в теку %2$s. Однак, під час синхронізації сталася помилка. Ви можете залишити файл(и) як є та видалити посилання на %3$s, або перемістити файл(и) в директорію %1$s і зберегти посилання на %4$s.\n\nНижче наведені локальні та віддалені файли у %5$s з якою вони були пов\'язані.</string>
<string name="sync_current_folder_was_removed">Тека %1$s білше не існує</string>
<string name="foreign_files_move">Перемістити все</string>
<string name="foreign_files_success">Всі файли були переміщені</string>
<string name="foreign_files_fail">Деякі файли не можуть бути переміщені</string>
<string name="foreign_files_local_text">Локально: %1$s</string>
<string name="foreign_files_remote_text">Віддалено: %1$s</string>
<string name="upload_query_move_foreign_files">Недостатньо місця для копіювання обраних файлів у теку %1$s. Чи бажаєте ви перемістити їх замість копіювання?</string>
<string name="pincode_enter_pin_code">Будь ласка, введіть свій програмний PIN</string>
<string name="pincode_configure_your_pin">Введіть програмний PIN</string>
<string name="pincode_configure_your_pin_explanation">PIN необхідно буде вводити щоразу при запуску цієї програми</string>
@ -87,24 +121,62 @@
<string name="pincode_wrong">Не вірний App програмний PIN</string>
<string name="pincode_removed">App програмний PIN видалено</string>
<string name="pincode_stored">App програмний PIN збережено</string>
<string name="media_notif_ticker">%1$s музичний плеєр</string>
<string name="media_state_playing">%1$s (відтворення)</string>
<string name="media_state_loading">%1$s (завантаження)</string>
<string name="media_event_done">%1$s відтворення завершене</string>
<string name="media_err_nothing_to_play">Медіа-файлів не знайдено</string>
<string name="media_err_no_account">Обліковий запис не налаштований</string>
<string name="media_err_not_in_owncloud">Файл в невірному обліковому записі</string>
<string name="media_err_unsupported">Кодек не підтримується</string>
<string name="media_err_io">Медіа-файл не читається</string>
<string name="media_err_malformed">Медіа-файл невірно закодований</string>
<string name="media_err_timeout">Вийшов час на спробу відтворення</string>
<string name="media_err_invalid_progressive_playback">Неможливо потоком відтворити файл</string>
<string name="media_err_unknown">Медіа-файл неможливо відтворити вбудованим програвачем</string>
<string name="media_err_security_ex">Помилка безпеки при відтворені %1$s</string>
<string name="media_err_io_ex">Помилка вводу при відтворені %1$s</string>
<string name="media_err_unexpected">Несподівана помилка при відтворені %1$s</string>
<string name="media_rewind_description">Перемтка назад</string>
<string name="media_play_pause_description">Відтворення або пауза</string>
<string name="media_forward_description">Перемотка вперед</string>
<string name="auth_getting_authorization">Виконується вхід...</string>
<string name="auth_trying_to_login">Спроба входу…</string>
<string name="auth_no_net_conn_title">Відсутнє підключення до мережі</string>
<string name="auth_nossl_plain_ok_title">Безпечне з\'єднання не доступне.</string>
<string name="auth_connection_established">З\'єднання встановлено</string>
<string name="auth_testing_connection">Перевірка з\'єднання…</string>
<string name="auth_not_configured_title">Не вірні налаштування сервер </string>
<string name="auth_account_not_new">Такий обліковий запис вже існує на пристрої</string>
<string name="auth_account_not_the_same">Введений користувач не відповідає обліковому запису</string>
<string name="auth_unknown_error_title">Виникла невідома помилка!</string>
<string name="auth_unknown_host_title">Не вдалося знайти хост</string>
<string name="auth_incorrect_path_title">Не знайдено примірник сервер</string>
<string name="auth_timeout_title">Сервер занадто довго не відповідає</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">Не вдалося визначити версію сервер серверу</string>
<string name="auth_wrong_connection_title">Не вдалося встановити з\'єднання</string>
<string name="auth_secure_connection">Встановлено захищене з\'єднання</string>
<string name="auth_unauthorized">Невірне ім\'я користувача або пароль</string>
<string name="auth_oauth_error">Невдала авторизація</string>
<string name="auth_oauth_error_access_denied">Доступ заборонений сервером авторизації</string>
<string name="auth_wtf_reenter_URL">Несподівана відповідь; будь ласка, введіть адресу сервера знову</string>
<string name="auth_expired_oauth_token_toast">Час авторизації минув. Будь ласка, увійдіть знову</string>
<string name="auth_expired_basic_auth_toast">Будь ласка, введіть пароль</string>
<string name="auth_expired_saml_sso_token_toast">Час сесії минув. Будь ласка, підключіться знов</string>
<string name="auth_connecting_auth_server">Підключення до серверу аутентифікації...</string>
<string name="auth_unsupported_auth_method">Сервер не підтримує обраний метод аутентифікації</string>
<string name="auth_unsupported_multiaccount">%1$s не підтримує одночасно декілька облікових записів</string>
<string name="auth_fail_get_user_name">Ваш сервер не повертає коректний ідентифікатор користувача, будь ласка зверніться до адміністратора
</string>
<string name="auth_can_not_auth_against_server">Аутентифікація на цьому сервері неможлива</string>
<string name="fd_keep_in_sync">Оновлювати файл</string>
<string name="common_rename">Перейменувати</string>
<string name="common_remove">Видалити</string>
<string name="confirmation_remove_alert">Ви дійсно бажаєте видалити %1$s?</string>
<string name="confirmation_remove_folder_alert">Ви дійсно бажаєте видалити %1$s та весь вміст?</string>
<string name="confirmation_remove_local">Лише локально</string>
<string name="confirmation_remove_folder_local">Лише локальний зміст</string>
<string name="confirmation_remove_remote">Видалити із серверу</string>
@ -116,9 +188,15 @@
<string name="rename_server_fail_msg">Перейменування не вдалося</string>
<string name="sync_file_fail_msg">Неможливо перевірити віддалений файл</string>
<string name="sync_file_nothing_to_do_msg">Зміст файлу вже синхронізовано</string>
<string name="create_dir_fail_msg">Не вдалося створити теку</string>
<string name="filename_forbidden_characters">Заборонені символи: / \\ &lt; &gt; : \" | ? *</string>
<string name="filename_empty"> Ім\'я файлу не може бути порожнім.</string>
<string name="wait_a_moment">Зачекайте хвилинку</string>
<string name="filedisplay_unexpected_bad_get_content">Несподівані проблеми ; будь ласка, спробуйте використати іншу програму для вибору файлу</string>
<string name="filedisplay_no_file_selected">Не обрано файл</string>
<string name="activity_chooser_title">Надіслати посилання...</string>
<string name="oauth_check_onoff">Увійти через oAuth2</string>
<string name="oauth_login_connection">Підключення до серверу oAuth2...</string>
<string name="ssl_validator_header">Не вдалося перевірити ідентифікацію сайта</string>
<string name="ssl_validator_reason_cert_not_trusted">- Не довірений сертифікат серверу</string>
<string name="ssl_validator_reason_cert_expired">- Сертифікат серверу втратив чинність</string>
@ -141,17 +219,65 @@
<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="ssl_validator_null_cert">Не вдалося показати сертифікат.</string>
<string name="ssl_validator_no_info_about_error">- Інформація про помилку відсутня</string>
<string name="placeholder_sentence">Це заповнювач</string>
<string name="placeholder_filename">placeholder.txt</string>
<string name="placeholder_filetype">PNG зображення</string>
<string name="placeholder_filesize">389 КБ</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">Завантажувати зображення тільки через WiFi</string>
<string name="instant_video_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="conflict_overwrite">Замінити</string>
<string name="conflict_dont_upload">Не завантажувати</string>
<string name="preview_image_description">Попередній перегляд зображення</string>
<string name="preview_image_error_unknown_format">Не вдалося показати зображення</string>
<string name="error__upload__local_file_not_copied">%1$s неможливо скопіювати до %2$s</string>
<string name="prefs_instant_upload_path_title">Завантажити шлях</string>
<string name="share_link_no_support_share_api">На жаль, обмін не включений на вашому сервері. Будь ласка, зв\'яжіться з вашим адмінистратором.</string>
<string name="share_link_file_no_exist">Неможливо поділитися. Будь ласка, перевірте, чи існує файл</string>
<string name="share_link_file_error">Виникла помилка при спробі поділитися файлом або текою</string>
<string name="unshare_link_file_no_exist">Неможливо заборонити доступ. Будь ласка, перевірте, чи існує файл</string>
<string name="unshare_link_file_error">Виникла помилка при спробі заборонити доступ до файлу або теки</string>
<string name="activity_chooser_send_file_title">Надіслати</string>
<string name="copy_link">Копіювати посилання</string>
<string name="clipboard_text_copied">Скопійовано в буфер обміну</string>
<string name="error_cant_bind_to_operations_service">Критична помилка: виконання операції неможливе</string>
<string name="network_error_socket_exception">Виникла помилка при підключені до сервера.</string>
<string name="network_error_socket_timeout_exception">Під час очікування на сервер виникла помилка, операцію неможливо завершити</string>
<string name="network_error_connect_timeout_exception">Під час очікування на сервер виникла помилка, операцію неможливо завершити</string>
<string name="network_host_not_available">Неможливо завершити операцію, сервер недоступний</string>
<string name="empty"></string>
<string name="forbidden_permissions">У вас немає повноважень %s</string>
<string name="forbidden_permissions_rename">на перейменування цього файла</string>
<string name="forbidden_permissions_delete">на видалення цього файла</string>
<string name="share_link_forbidden_permissions">для надання доступу до файла</string>
<string name="unshare_link_forbidden_permissions">для закриття доступу до файла</string>
<string name="forbidden_permissions_create">для створення файла</string>
<string name="uploader_upload_forbidden_permissions">для завантаження в цю теку</string>
<string name="downloader_download_file_not_found">Файл більше не доступний на сервері</string>
<string name="prefs_category_accounts">Облікові записи</string>
<string name="prefs_add_account">Додати обліковий запис</string>
<string name="auth_redirect_non_secure_connection_title">Безпечне підключення перенаправляється через незабезпечений маршрут.</string>
<string name="actionbar_logger">Журнали</string>
<string name="log_send_history_button">Надіслати історію</string>
<string name="log_mail_subject">Журнали Android-додатка ownCloud</string>
<string name="log_progress_dialog_text">Завантаження даних...</string>
<string name="saml_authentication_required_text">Потрібна аутентифікація</string>
<string name="saml_authentication_wrong_pass">Невірний пароль</string>
<string name="actionbar_move">Перемістити</string>
<string name="file_list_empty_moving">Тут нічого немає. Ви можете додати теку!</string>
<string name="move_choose_button_text">Обрати</string>
<string name="move_file_not_found">Неможливо перемістити. Будь ласка, перевірте, чи існує файл</string>
<string name="move_file_invalid_into_descendent">Неможливо перемістити теку до теки-нащадка</string>
<string name="move_file_invalid_overwrite">Файл вже існує в теці призначення</string>
<string name="move_file_error">Виникла помилка при спробі перемістити файл або теку</string>
<string name="forbidden_permissions_move">перемістити цей файл</string>
<string name="prefs_category_instant_uploading">Миттєво завантаження</string>
<string name="prefs_category_security">Безпека</string>
</resources>

View file

@ -31,6 +31,8 @@
<string name="prefs_feedback">反馈</string>
<string name="prefs_imprint">版本说明</string>
<string name="recommend_subject">在您的智能手机上试用一下 %1$s</string>
<string name="recommend_text">“我邀请你使用在你的智能手机上使用 %1$s在这下载%2$s”
</string>
<string name="auth_check_server">检查服务器</string>
<string name="auth_host_url">服务器地址 https://...</string>
<string name="auth_username">用户名</string>
@ -103,6 +105,7 @@
<string name="sync_fail_in_favourites_content">无法同步 %1$d 文件内容(与 %2$d 冲突)</string>
<string name="sync_foreign_files_forgotten_ticker">某些本地文件已被遗忘</string>
<string name="sync_foreign_files_forgotten_content">%2$s 目录中的 %1$d 个文件不能被复制到</string>
<string name="sync_foreign_files_forgotten_explanation">从 1.3.16 版起,从此设备上传的文件将被复制到本地的 %1$s 文件夹,以防止某个单一文件在多个账户间同步而造成的数据损失。\n\n 由于此项变化,此应用之前的版本上传的全部文件都已被复制到了 %2$s 文件夹。然而,账户同步期间有一个错误阻止了此操作的完成。您可能想保持文件不动,并移除指向 %3$s 的链接,或将文件移动到 %1$s 文件夹中并保持其到 %4$s 的链接。下面列出的是本地文件,以及它们被链接到的 %5$s 中的远程文件。</string>
<string name="sync_current_folder_was_removed">文件夹%1$s 不存在</string>
<string name="foreign_files_move">移动所有</string>
<string name="foreign_files_success">所有文件已被移动</string>
@ -260,14 +263,19 @@
<string name="downloader_download_file_not_found">该文件在服务器上不可用</string>
<string name="prefs_category_accounts">账号</string>
<string name="prefs_add_account">添加账号</string>
<string name="auth_redirect_non_secure_connection_title">安全连接是通过一个非安全路由定向的。</string>
<string name="actionbar_logger">日志</string>
<string name="log_send_history_button">发送历史</string>
<string name="log_mail_subject">ownCloud安卓客户端日志</string>
<string name="log_progress_dialog_text">加载数据中...</string>
<string name="saml_authentication_required_text">需要认证</string>
<string name="saml_authentication_wrong_pass">错误密码</string>
<string name="actionbar_move">移动</string>
<string name="file_list_empty_moving">这里还什么都没有。上传些东西吧!</string>
<string name="move_choose_button_text">选择(&amp;C)...</string>
<string name="move_file_not_found">无法移动。请检查文件是否存在</string>
<string name="move_file_invalid_into_descendent">b不能够把一个目录移动到它的下级</string>
<string name="move_file_invalid_overwrite">该文件已经存在在目标文件夹</string>
<string name="move_file_error">尝试移动该文件或文件夹时发生错误</string>
<string name="forbidden_permissions_move">移动该文件</string>
<string name="prefs_category_security">安全</string>
</resources>

View file

@ -31,6 +31,7 @@
<string name="prefs_feedback">反饋</string>
<string name="prefs_imprint">法律聲明</string>
<string name="recommend_subject">在您的手機中試用%1$s!</string>
<string name="recommend_text">我想邀請您在您的手機上使用 %1$s ! 可以由這兒下載: %2$s</string>
<string name="auth_check_server">檢查伺服器</string>
<string name="auth_host_url">伺服器位址 https://...</string>
<string name="auth_username">使用者名稱</string>
@ -49,6 +50,8 @@
<string name="uploader_error_forbidden_content">%1$s 並沒有被允許存取分享的內容</string>
<string name="uploader_info_uploading">上傳中</string>
<string name="file_list_empty">這裡還沒有東西,上傳一些吧!</string>
<string name="file_list_loading">載入中…</string>
<string name="local_file_list_empty">這個目錄中沒有任何檔案.</string>
<string name="filedetails_select_file">在檔案上輕觸來顯示更多資訊。</string>
<string name="filedetails_size">容量:</string>
<string name="filedetails_type">類型:</string>
@ -92,6 +95,7 @@
<string name="downloader_download_failed_credentials_error">下傳失敗, 您需要重新登入</string>
<string name="common_choose_account">選擇帳號</string>
<string name="sync_fail_ticker">同步失敗</string>
<string name="sync_fail_ticker_unauthorized">同步作業失敗, 您需要重新登入</string>
<string name="sync_fail_content">同步 %1$s 未完成</string>
<string name="sync_fail_content_unauthorized">無效的密碼 %1$s</string>
<string name="sync_conflicts_in_favourites_ticker">出現衝突</string>
@ -100,12 +104,14 @@
<string name="sync_fail_in_favourites_content">%1$d 未被同步 (%2$d 衝突)</string>
<string name="sync_foreign_files_forgotten_ticker">有些本地端的檔案已遺失</string>
<string name="sync_foreign_files_forgotten_content">%1$d 檔案超過 %2$s 資料夾可能不能複製進去</string>
<string name="sync_foreign_files_forgotten_explanation">在 1.3.16 版之前, 檔案上傳時會先複製到本地的 %1$s 目錄以避免在多帳戶內同步造成遺失.\n\n由於這個改變, 所以在之前版本上傳的檔案被複製到 %2$s 目錄中. 為了避免同步發生問題. 你可以保留那些檔案並刪除連結 %3$s, 或搬移檔案到 %1$s 目錄並取得連結到 %4$s.\n\n下面列表是本地檔案, 與被連結遠端檔案 %5$s.</string>
<string name="sync_current_folder_was_removed">資料夾 %1$s 不存在</string>
<string name="foreign_files_move">移動全部</string>
<string name="foreign_files_success">所有文件已被移動</string>
<string name="foreign_files_fail">部份文件無法被移動</string>
<string name="foreign_files_local_text">本地: %1$s</string>
<string name="foreign_files_remote_text">遠端: %1$s</string>
<string name="upload_query_move_foreign_files">無足夠的空間可以複製檔案到 %1$s 目錄. 是否使用移動的方式來處理? </string>
<string name="pincode_enter_pin_code">請輸入您的 App 密碼</string>
<string name="pincode_configure_your_pin">輸入您的 App 密碼</string>
<string name="pincode_configure_your_pin_explanation">這個密碼在你每次啟動這程式時都會被要求輸入</string>
@ -232,9 +238,12 @@
<string name="preview_image_description">圖片預覽</string>
<string name="preview_image_error_unknown_format">無法顯示圖片</string>
<string name="error__upload__local_file_not_copied">%1$s 無法被複製到本地目錄 %2$s</string>
<string name="prefs_instant_upload_path_title">上傳目錄</string>
<string name="share_link_no_support_share_api">很抱歉, 您的伺服器並未開啟分享的功能. 請聯絡您的
伺服器管理員.</string>
<string name="share_link_file_no_exist">無法分享這個檔案或目錄. 請檢查它們是否存在</string>
<string name="share_link_file_error">在分享檔案或目錄時發生了錯誤</string>
<string name="unshare_link_file_no_exist">無法取消分享這個檔案或目錄. 請檢查它們是否存在</string>
<string name="unshare_link_file_error">在取消分享檔案或目錄時發生了錯誤</string>
<string name="activity_chooser_send_file_title">寄出</string>
<string name="copy_link">複製連結</string>
@ -245,8 +254,31 @@
<string name="network_error_connect_timeout_exception">在等待伺服器回應時發生了錯誤, 這個操作將無法被完成</string>
<string name="network_host_not_available">這個操作無法完成, 無法使用伺服器</string>
<string name="empty"></string>
<string name="forbidden_permissions">您沒有權限 %s</string>
<string name="forbidden_permissions_rename">重新命名檔案</string>
<string name="forbidden_permissions_delete">刪除檔案</string>
<string name="share_link_forbidden_permissions">分享檔案</string>
<string name="unshare_link_forbidden_permissions">取消分享檔案</string>
<string name="forbidden_permissions_create">建立檔案</string>
<string name="uploader_upload_forbidden_permissions">上傳這個目錄</string>
<string name="downloader_download_file_not_found">這個檔案已經不存在於伺服器中</string>
<string name="prefs_category_accounts">帳號</string>
<string name="prefs_add_account">新增帳號</string>
<string name="auth_redirect_non_secure_connection_title">安全連線被轉向到一個非安全的連線</string>
<string name="actionbar_logger">紀錄</string>
<string name="log_send_history_button">傳送歷史記錄</string>
<string name="log_mail_subject">ownCloud Android 應用程式記錄</string>
<string name="log_progress_dialog_text">資料載入中...</string>
<string name="saml_authentication_required_text">必須驗證</string>
<string name="saml_authentication_wrong_pass">密碼錯誤</string>
<string name="actionbar_move">移動</string>
<string name="file_list_empty_moving">找不到任何檔案. 你可以新增一個目錄!</string>
<string name="move_choose_button_text">選擇</string>
<string name="move_file_not_found">無法搬移. 請檢查該檔案是否存在</string>
<string name="move_file_invalid_into_descendent">把一個目錄搬移到其底下的子目錄是不可能的</string>
<string name="move_file_invalid_overwrite">這個檔案已經存在於目的目錄中</string>
<string name="move_file_error">在移動檔案或目錄時發生了錯誤</string>
<string name="forbidden_permissions_move">移動這個檔案</string>
<string name="prefs_category_instant_uploading">即時上傳</string>
<string name="prefs_category_security">安全性</string>
</resources>

View file

@ -258,6 +258,7 @@
<string name="preview_image_error_unknown_format">This image cannot be shown</string>
<string name="error__upload__local_file_not_copied">%1$s could not be copied to %2$s local folder</string>
<string name="prefs_instant_upload_path_title">Upload Path</string>
<string name="share_link_no_support_share_api">Sorry, sharing is not enabled on your server. Please contact your
administrator.</string>
@ -290,7 +291,7 @@
<string name="prefs_category_accounts">Accounts</string>
<string name="prefs_add_account">Add account</string>
<string name="auth_redirect_non_secure_connection_title">Secure connection is redirected through an unsecured route.</string>
<string name="auth_redirect_non_secure_connection_title">Secure connection is redirected to an unsecured route.</string>
<string name="actionbar_logger">Logs</string>
<string name="log_send_history_button">Send History</string>
@ -309,4 +310,7 @@
<string name="move_file_error">An error occurred while trying to move this file or folder</string>
<string name="forbidden_permissions_move">to move this file</string>
<string name="prefs_category_instant_uploading">Instant Uploads</string>
<string name="prefs_category_security">Security</string>
</resources>

View file

@ -21,35 +21,41 @@
<PreferenceCategory android:title="@string/prefs_category_accounts" android:key="accounts_category">
</PreferenceCategory>
<PreferenceCategory android:title="@string/prefs_category_general">
<!-- ListPreference
android:key="select_oc_account"
android:title="@string/prefs_select_oc_account"
android:summary="@string/prefs_summary_select_oc_account"
/ -->
<com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle android:title="@string/prefs_pincode" android:key="set_pincode"
<PreferenceCategory android:title="@string/prefs_category_security">
<!-- ListPreference
android:key="select_oc_account"
android:title="@string/prefs_select_oc_account"
android:summary="@string/prefs_summary_select_oc_account"
/ -->
<com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle android:title="@string/prefs_pincode" android:key="set_pincode"
android:summary="@string/prefs_pincode_summary"/>
<com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle android:key="instant_uploading"
android:title="@string/prefs_instant_upload"
android:summary="@string/prefs_instant_upload_summary"/>
<com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle android:dependency="instant_uploading"
android:disableDependentsState="true"
android:title="@string/instant_upload_on_wifi"
android:key="instant_upload_on_wifi"/>
<com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle android:key="instant_video_uploading"
android:title="@string/prefs_instant_video_upload"
android:summary="@string/prefs_instant_video_upload_summary"/>
<com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle android:dependency="instant_video_uploading"
android:disableDependentsState="true"
android:title="@string/instant_video_upload_on_wifi"
android:key="instant_video_upload_on_wifi"/>
<!-- DISABLED FOR RELEASE UNTIL FIXED
CheckBoxPreference android:key="log_to_file"
android:title="@string/prefs_log_title"
android:summary="@string/prefs_log_summary"/>
<Preference android:key="log_history"
android:title="@string/prefs_log_title_history"
android:summary="@string/prefs_log_summary_history"/ -->
</PreferenceCategory>
<PreferenceCategory android:title="@string/prefs_category_instant_uploading">
<EditTextPreference android:title="@string/prefs_instant_upload_path_title"
android:defaultValue="@string/instant_upload_path"
android:key="instant_upload_path"/>
<com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle android:key="instant_uploading"
android:title="@string/prefs_instant_upload"
android:summary="@string/prefs_instant_upload_summary"/>
<com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle android:dependency="instant_uploading"
android:disableDependentsState="true"
android:title="@string/instant_upload_on_wifi"
android:key="instant_upload_on_wifi"/>
<com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle android:key="instant_video_uploading"
android:title="@string/prefs_instant_video_upload"
android:summary="@string/prefs_instant_video_upload_summary"/>
<com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle android:dependency="instant_video_uploading"
android:disableDependentsState="true"
android:title="@string/instant_video_upload_on_wifi"
android:key="instant_video_upload_on_wifi"/>
<!-- DISABLED FOR RELEASE UNTIL FIXED
CheckBoxPreference android:key="log_to_file"
android:title="@string/prefs_log_title"
android:summary="@string/prefs_log_summary"/>
<Preference android:key="log_history"
android:title="@string/prefs_log_title_history"
android:summary="@string/prefs_log_summary_history"/ -->
</PreferenceCategory>
@ -65,4 +71,4 @@
</PreferenceCategory>
</PreferenceScreen>
</PreferenceScreen>

View file

@ -1,4 +1,4 @@
#!/bin/bash
#!/bin/bash -e
git submodule init
git submodule update

View file

@ -19,6 +19,7 @@ package com.owncloud.android;
import android.app.Application;
import android.content.Context;
import com.owncloud.android.datamodel.ThumbnailsCacheManager;
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory.Policy;
import com.owncloud.android.lib.common.utils.Log_OC;
@ -55,6 +56,9 @@ public class MainApp extends Application {
OwnCloudClientManagerFactory.setDefaultPolicy(Policy.ALWAYS_NEW_CLIENT);
}
// initialise thumbnails cache on background thread
new ThumbnailsCacheManager.InitDiskCacheTask().execute();
if (BuildConfig.DEBUG) {
String dataFolder = getDataFolder();

View file

@ -246,13 +246,17 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
if (mAccount != null) {
boolean oAuthRequired =
(mAccountMgr.getUserData(mAccount, Constants.KEY_SUPPORTS_OAUTH2) != null);
boolean samlWebSsoRequired =
(mAccountMgr.getUserData(mAccount, Constants.KEY_SUPPORTS_SAML_WEB_SSO) != null);
boolean samlWebSsoRequired = (
mAccountMgr.getUserData(
mAccount, Constants.KEY_SUPPORTS_SAML_WEB_SSO
) != null
);
mAuthTokenType = chooseAuthTokenType(oAuthRequired, samlWebSsoRequired);
} else {
boolean oAuthSupported = AUTH_ON.equals(getString(R.string.auth_method_oauth2));
boolean samlWebSsoSupported = AUTH_ON.equals(getString(R.string.auth_method_saml_web_sso));
boolean samlWebSsoSupported =
AUTH_ON.equals(getString(R.string.auth_method_saml_web_sso));
mAuthTokenType = chooseAuthTokenType(oAuthSupported, samlWebSsoSupported);
}
}
@ -321,7 +325,8 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
if (savedInstanceState == null) {
if (mAccount != null) {
mServerInfo.mBaseUrl = mAccountMgr.getUserData(mAccount, Constants.KEY_OC_BASE_URL);
mServerInfo.mIsSslConn = mServerInfo.mBaseUrl.startsWith("https://"); // TODO do this in a setter for mBaseUrl
// TODO do next in a setter for mBaseUrl
mServerInfo.mIsSslConn = mServerInfo.mBaseUrl.startsWith("https://");
String ocVersion = mAccountMgr.getUserData(mAccount, Constants.KEY_OC_VERSION);
if (ocVersion != null) {
mServerInfo.mVersion = new OwnCloudVersion(ocVersion);
@ -405,8 +410,12 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
@Override
public boolean onTouch(View view, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType) &&
mHostUrlInput.hasFocus()) {
if (
AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(
MainApp.getAccountType()
).equals(mAuthTokenType) &&
mHostUrlInput.hasFocus()
) {
checkOcServer();
}
}
@ -534,8 +543,9 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
/**
* Saves relevant state before {@link #onPause()}
*
* Do NOT save {@link #mNewCapturedUriFromOAuth2Redirection}; it keeps a temporal flag, intended to defer the
* processing of the redirection caught in {@link #onNewIntent(Intent)} until {@link #onResume()}
* Do NOT save {@link #mNewCapturedUriFromOAuth2Redirection}; it keeps a temporal flag,
* intended to defer the processing of the redirection caught in
* {@link #onNewIntent(Intent)} until {@link #onResume()}
*
* See {@link #loadSavedInstanceState(Bundle)}
*/
@ -574,11 +584,11 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
/**
* The redirection triggered by the OAuth authentication server as response to the GET AUTHORIZATION request
* is caught here.
* The redirection triggered by the OAuth authentication server as response to the
* GET AUTHORIZATION request is caught here.
*
* To make this possible, this activity needs to be qualified with android:launchMode = "singleTask" in the
* AndroidManifest.xml file.
* To make this possible, this activity needs to be qualified with android:launchMode =
* "singleTask" in the AndroidManifest.xml file.
*/
@Override
protected void onNewIntent (Intent intent) {
@ -591,8 +601,8 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
/**
* The redirection triggered by the OAuth authentication server as response to the GET AUTHORIZATION, and
* deferred in {@link #onNewIntent(Intent)}, is processed here.
* The redirection triggered by the OAuth authentication server as response to the
* GET AUTHORIZATION, and deferred in {@link #onNewIntent(Intent)}, is processed here.
*/
@Override
protected void onResume() {
@ -733,7 +743,10 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
Intent getServerInfoIntent = new Intent();
getServerInfoIntent.setAction(OperationsService.ACTION_GET_SERVER_INFO);
getServerInfoIntent.putExtra(OperationsService.EXTRA_SERVER_URL, uri);
getServerInfoIntent.putExtra(
OperationsService.EXTRA_SERVER_URL,
normalizeUrlSuffix(uri)
);
if (mOperationsServiceBinder != null) {
mWaitingForOpId = mOperationsServiceBinder.newOperation(getServerInfoIntent);
} else {
@ -777,7 +790,8 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
}
private boolean isPasswordVisible() {
return ((mPasswordInput.getInputType() & InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) == InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
return ((mPasswordInput.getInputType() & InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) ==
InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
}
private void hidePasswordButton() {
@ -785,12 +799,16 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
}
private void showPassword() {
mPasswordInput.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
mPasswordInput.setInputType(
InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
);
showViewPasswordButton();
}
private void hidePassword() {
mPasswordInput.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
mPasswordInput.setInputType(
InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD
);
showViewPasswordButton();
}
@ -822,9 +840,13 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
return;
}
if (AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType()).equals(mAuthTokenType)) {
if (AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType()).
equals(mAuthTokenType)) {
startOauthorization();
} else if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) {
} else if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).
equals(mAuthTokenType)) {
startSamlBasedFederatedSingleSignOnAuthorization();
} else {
checkBasicAuthorization();
@ -879,10 +901,18 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
// GET AUTHORIZATION request
Uri uri = Uri.parse(mOAuthAuthEndpointText.getText().toString().trim());
Uri.Builder uriBuilder = uri.buildUpon();
uriBuilder.appendQueryParameter(OAuth2Constants.KEY_RESPONSE_TYPE, getString(R.string.oauth2_response_type));
uriBuilder.appendQueryParameter(OAuth2Constants.KEY_REDIRECT_URI, getString(R.string.oauth2_redirect_uri));
uriBuilder.appendQueryParameter(OAuth2Constants.KEY_CLIENT_ID, getString(R.string.oauth2_client_id));
uriBuilder.appendQueryParameter(OAuth2Constants.KEY_SCOPE, getString(R.string.oauth2_scope));
uriBuilder.appendQueryParameter(
OAuth2Constants.KEY_RESPONSE_TYPE, getString(R.string.oauth2_response_type)
);
uriBuilder.appendQueryParameter(
OAuth2Constants.KEY_REDIRECT_URI, getString(R.string.oauth2_redirect_uri)
);
uriBuilder.appendQueryParameter(
OAuth2Constants.KEY_CLIENT_ID, getString(R.string.oauth2_client_id)
);
uriBuilder.appendQueryParameter(
OAuth2Constants.KEY_SCOPE, getString(R.string.oauth2_scope)
);
uri = uriBuilder.build();
Log_OC.d(TAG, "Starting browser to view " + uri.toString());
Intent i = new Intent(Intent.ACTION_VIEW, uri);
@ -927,7 +957,8 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
} else if (operation instanceof ExistenceCheckRemoteOperation) {
//Log_OC.wtf(TAG, "received detection response through callback" );
if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) {
if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).
equals(mAuthTokenType)) {
onSamlBasedFederatedSingleSignOnAuthorizationStart(result);
} else {
@ -1080,16 +1111,20 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
url = "http://" + url;
}
}
url = trimUrlWebdav(url);
if (url.endsWith("/")) {
url = url.substring(0, url.length() - 1);
}
url = normalizeUrlSuffix(url);
}
return (url != null ? url : "");
}
private String normalizeUrlSuffix(String url) {
if (url.endsWith("/")) {
url = url.substring(0, url.length() - 1);
}
url = trimUrlWebdav(url);
return url;
}
// TODO remove, if possible
@ -1299,7 +1334,6 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
@SuppressWarnings("unchecked")
Map<String, String> tokens = (Map<String, String>)(result.getData().get(0));
mAuthToken = tokens.get(OAuth2Constants.KEY_ACCESS_TOKEN);
//mAuthToken = ((OAuth2GetAccessToken)operation).getResultTokenMap().get(OAuth2Constants.KEY_ACCESS_TOKEN);
Log_OC.d(TAG, "Got ACCESS TOKEN: " + mAuthToken);
accessRootFolderRemoteOperation("", "");
@ -1358,7 +1392,7 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
showRefreshButton(true);
mOkButton.setEnabled(false);
// very special case (TODO: move to a common place for all the remote operations) (dangerous here?)
// very special case (TODO: move to a common place for all the remote operations)
if (result.getCode() == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED) {
showUntrustedCertDialog(result);
}
@ -1374,23 +1408,27 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
/**
* Sets the proper response to get that the Account Authenticator that started this activity saves
* a new authorization token for mAccount.
* Sets the proper response to get that the Account Authenticator that started this activity
* saves a new authorization token for mAccount.
*/
private void updateToken() {
Bundle response = new Bundle();
response.putString(AccountManager.KEY_ACCOUNT_NAME, mAccount.name);
response.putString(AccountManager.KEY_ACCOUNT_TYPE, mAccount.type);
if (AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType()).equals(mAuthTokenType)) {
if (AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType()).
equals(mAuthTokenType)) {
response.putString(AccountManager.KEY_AUTHTOKEN, mAuthToken);
// the next line is necessary; by now, notifications are calling directly to the AuthenticatorActivity to update, without AccountManager intervention
// the next line is necessary, notifications are calling directly to the
// AuthenticatorActivity to update, without AccountManager intervention
mAccountMgr.setAuthToken(mAccount, mAuthTokenType, mAuthToken);
} else if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) {
} else if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).
equals(mAuthTokenType)) {
response.putString(AccountManager.KEY_AUTHTOKEN, mAuthToken);
// the next line is necessary; by now, notifications are calling directly to the AuthenticatorActivity to update, without AccountManager intervention
// the next line is necessary; by now, notifications are calling directly to the
// AuthenticatorActivity to update, without AccountManager intervention
mAccountMgr.setAuthToken(mAccount, mAuthTokenType, mAuthToken);
} else {
@ -1411,8 +1449,10 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
*/
private boolean createAccount() {
/// create and save new ownCloud account
boolean isOAuth = AccountTypeUtils.getAuthTokenTypeAccessToken(MainApp.getAccountType()).equals(mAuthTokenType);
boolean isSaml = AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType);
boolean isOAuth = AccountTypeUtils.
getAuthTokenTypeAccessToken(MainApp.getAccountType()).equals(mAuthTokenType);
boolean isSaml = AccountTypeUtils.
getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType);
Uri uri = Uri.parse(mServerInfo.mBaseUrl);
String username = mUsernameInput.getText().toString().trim();
@ -1434,9 +1474,12 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
mAccount = newAccount;
if (isOAuth || isSaml) {
mAccountMgr.addAccountExplicitly(mAccount, "", null); // with external authorizations, the password is never input in the app
// with external authorizations, the password is never input in the app
mAccountMgr.addAccountExplicitly(mAccount, "", null);
} else {
mAccountMgr.addAccountExplicitly(mAccount, mPasswordInput.getText().toString(), null);
mAccountMgr.addAccountExplicitly(
mAccount, mPasswordInput.getText().toString(), null
);
}
/// add the new account as default in preferences, if there is none already
@ -1449,7 +1492,8 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
}
/// prepare result to return to the Authenticator
// TODO check again what the Authenticator makes with it; probably has the same effect as addAccountExplicitly, but it's not well done
// TODO check again what the Authenticator makes with it; probably has the same
// effect as addAccountExplicitly, but it's not well done
final Intent intent = new Intent();
intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, MainApp.getAccountType());
intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, mAccount.name);
@ -1459,9 +1503,14 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
if (isOAuth || isSaml) {
mAccountMgr.setAuthToken(mAccount, mAuthTokenType, mAuthToken);
}
/// add user data to the new account; TODO probably can be done in the last parameter addAccountExplicitly, or in KEY_USERDATA
mAccountMgr.setUserData(mAccount, Constants.KEY_OC_VERSION, mServerInfo.mVersion.getVersion());
mAccountMgr.setUserData(mAccount, Constants.KEY_OC_BASE_URL, mServerInfo.mBaseUrl);
/// add user data to the new account; TODO probably can be done in the last parameter
// addAccountExplicitly, or in KEY_USERDATA
mAccountMgr.setUserData(
mAccount, Constants.KEY_OC_VERSION, mServerInfo.mVersion.getVersion()
);
mAccountMgr.setUserData(
mAccount, Constants.KEY_OC_BASE_URL, mServerInfo.mBaseUrl
);
if (isSaml) {
mAccountMgr.setUserData(mAccount, Constants.KEY_SUPPORTS_SAML_WEB_SSO, "TRUE");
@ -1483,7 +1532,9 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
* @param view 'Account register' button
*/
public void onRegisterClick(View view) {
Intent register = new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.welcome_link_url)));
Intent register = new Intent(
Intent.ACTION_VIEW, Uri.parse(getString(R.string.welcome_link_url))
);
setResult(RESULT_CANCELED);
startActivity(register);
}
@ -1583,18 +1634,21 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
/**
* Called when the 'action' button in an IME is pressed ('enter' in software keyboard).
*
* Used to trigger the authentication check when the user presses 'enter' after writing the password,
* or to throw the server test when the only field on screen is the URL input field.
* Used to trigger the authentication check when the user presses 'enter' after writing the
* password, or to throw the server test when the only field on screen is the URL input field.
*/
@Override
public boolean onEditorAction(TextView inputField, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE && inputField != null && inputField.equals(mPasswordInput)) {
if (actionId == EditorInfo.IME_ACTION_DONE && inputField != null &&
inputField.equals(mPasswordInput)) {
if (mOkButton.isEnabled()) {
mOkButton.performClick();
}
} else if (actionId == EditorInfo.IME_ACTION_NEXT && inputField != null && inputField.equals(mHostUrlInput)) {
if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) {
} else if (actionId == EditorInfo.IME_ACTION_NEXT && inputField != null &&
inputField.equals(mHostUrlInput)) {
if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).
equals(mAuthTokenType)) {
checkOcServer();
}
}
@ -1622,8 +1676,10 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
final int x = (int) event.getX();
final int y = (int) event.getY();
final Rect bounds = rightDrawable.getBounds();
if (x >= (view.getRight() - bounds.width() - fuzz) && x <= (view.getRight() - view.getPaddingRight() + fuzz)
&& y >= (view.getPaddingTop() - fuzz) && y <= (view.getHeight() - view.getPaddingBottom()) + fuzz) {
if ( x >= (view.getRight() - bounds.width() - fuzz) &&
x <= (view.getRight() - view.getPaddingRight() + fuzz) &&
y >= (view.getPaddingTop() - fuzz) &&
y <= (view.getHeight() - view.getPaddingBottom()) + fuzz) {
return onDrawableTouch(event);
}
@ -1672,7 +1728,8 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
@Override
public boolean onTouchEvent(MotionEvent event) {
if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType) &&
if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).
equals(mAuthTokenType) &&
mHostUrlInput.hasFocus() && event.getAction() == MotionEvent.ACTION_DOWN) {
checkOcServer();
}
@ -1683,13 +1740,16 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
/**
* Show untrusted cert dialog
*/
public void showUntrustedCertDialog(X509Certificate x509Certificate, SslError error, SslErrorHandler handler) {
public void showUntrustedCertDialog(
X509Certificate x509Certificate, SslError error, SslErrorHandler handler
) {
// Show a dialog with the certificate info
SslUntrustedCertDialog dialog = null;
if (x509Certificate == null) {
dialog = SslUntrustedCertDialog.newInstanceForEmptySslError(error, handler);
} else {
dialog = SslUntrustedCertDialog.newInstanceForFullSslError(x509Certificate, error, handler);
dialog = SslUntrustedCertDialog.
newInstanceForFullSslError(x509Certificate, error, handler);
}
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
@ -1703,7 +1763,8 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
*/
private void showUntrustedCertDialog(RemoteOperationResult result) {
// Show a dialog with the certificate info
SslUntrustedCertDialog dialog = SslUntrustedCertDialog.newInstanceForFullSslError((CertificateCombinedException)result.getException());
SslUntrustedCertDialog dialog = SslUntrustedCertDialog.
newInstanceForFullSslError((CertificateCombinedException)result.getException());
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.addToBackStack(null);
@ -1717,7 +1778,8 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
public void onSavedCertificate() {
Fragment fd = getSupportFragmentManager().findFragmentByTag(SAML_DIALOG_TAG);
if (fd == null) {
// if SAML dialog is not shown, the SslDialog was shown due to an SSL error in the server check
// if SAML dialog is not shown,
// the SslDialog was shown due to an SSL error in the server check
checkOcServer();
}
}
@ -1767,7 +1829,9 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
@Override
public void onServiceConnected(ComponentName component, IBinder service) {
if (component.equals(new ComponentName(AuthenticatorActivity.this, OperationsService.class))) {
if (component.equals(
new ComponentName(AuthenticatorActivity.this, OperationsService.class)
)) {
//Log_OC.wtf(TAG, "Operations service connected");
mOperationsServiceBinder = (OperationsServiceBinder) service;
@ -1781,7 +1845,9 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
@Override
public void onServiceDisconnected(ComponentName component) {
if (component.equals(new ComponentName(AuthenticatorActivity.this, OperationsService.class))) {
if (component.equals(
new ComponentName(AuthenticatorActivity.this, OperationsService.class)
)) {
Log_OC.e(TAG, "Operations service crashed");
mOperationsServiceBinder = null;
}
@ -1797,7 +1863,8 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
public void createAuthenticationDialog(WebView webView, HttpAuthHandler handler) {
// Show a dialog with the certificate info
CredentialsDialogFragment dialog = CredentialsDialogFragment.newInstanceForCredentials(webView, handler);
CredentialsDialogFragment dialog =
CredentialsDialogFragment.newInstanceForCredentials(webView, handler);
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.addToBackStack(null);
@ -1805,7 +1872,11 @@ SsoWebViewClientListener, OnSslUntrustedCertListener {
dialog.show(ft, CREDENTIALS_DIALOG_TAG);
if (!mIsFirstAuthAttempt) {
Toast.makeText(getApplicationContext(), getText(R.string.saml_authentication_wrong_pass), Toast.LENGTH_LONG).show();
Toast.makeText(
getApplicationContext(),
getText(R.string.saml_authentication_wrong_pass),
Toast.LENGTH_LONG
).show();
} else {
mIsFirstAuthAttempt = false;
}

View file

@ -151,7 +151,7 @@ public class FileDataStorageManager {
public Vector<OCFile> getFolderImages(OCFile folder) {
Vector<OCFile> ret = new Vector<OCFile>();
if (folder != null) {
// TODO better implementation, filtering in the access to database (if possible) instead of here
// TODO better implementation, filtering in the access to database instead of here
Vector<OCFile> tmp = getFolderContent(folder);
OCFile current = null;
for (int i=0; i<tmp.size(); i++) {
@ -169,7 +169,10 @@ public class FileDataStorageManager {
boolean overriden = false;
ContentValues cv = new ContentValues();
cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData());
cv.put(
ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
file.getModificationTimestampAtLastSyncForData()
);
cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
@ -192,7 +195,7 @@ public class FileDataStorageManager {
boolean sameRemotePath = fileExists(file.getRemotePath());
if (sameRemotePath ||
fileExists(file.getFileId()) ) { // for renamed files; no more delete and create
fileExists(file.getFileId()) ) { // for renamed files
OCFile oldFile = null;
if (sameRemotePath) {
@ -260,17 +263,24 @@ public class FileDataStorageManager {
* @param files
* @param removeNotUpdated
*/
public void saveFolder(OCFile folder, Collection<OCFile> updatedFiles, Collection<OCFile> filesToRemove) {
public void saveFolder(
OCFile folder, Collection<OCFile> updatedFiles, Collection<OCFile> filesToRemove
) {
Log_OC.d(TAG, "Saving folder " + folder.getRemotePath() + " with " + updatedFiles.size() + " children and " + filesToRemove.size() + " files to remove");
Log_OC.d(TAG, "Saving folder " + folder.getRemotePath() + " with " + updatedFiles.size()
+ " children and " + filesToRemove.size() + " files to remove");
ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(updatedFiles.size());
ArrayList<ContentProviderOperation> operations =
new ArrayList<ContentProviderOperation>(updatedFiles.size());
// prepare operations to insert or update files to save in the given folder
for (OCFile file : updatedFiles) {
ContentValues cv = new ContentValues();
cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData());
cv.put(
ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
file.getModificationTimestampAtLastSyncForData()
);
cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
@ -302,29 +312,40 @@ public class FileDataStorageManager {
} else {
// adding a new file
operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).withValues(cv).build());
operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).
withValues(cv).build());
}
}
// prepare operations to remove files in the given folder
String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " +
ProviderTableMeta.FILE_PATH + "=?";
String [] whereArgs = null;
for (OCFile file : filesToRemove) {
if (file.getParentId() == folder.getFileId()) {
whereArgs = new String[]{mAccount.name, file.getRemotePath()};
//Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, "" + file.getFileId());
if (file.isFolder()) {
operations.add(ContentProviderOperation
.newDelete(ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, file.getFileId())).withSelection(where, whereArgs)
.build());
// TODO remove local folder
operations.add(ContentProviderOperation.newDelete(
ContentUris.withAppendedId(
ProviderTableMeta.CONTENT_URI_DIR, file.getFileId()
)
).withSelection(where, whereArgs).build());
File localFolder =
new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
if (localFolder.exists()) {
removeLocalFolder(localFolder);
}
} else {
operations.add(ContentProviderOperation
.newDelete(ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId())).withSelection(where, whereArgs)
.build());
operations.add(ContentProviderOperation.newDelete(
ContentUris.withAppendedId(
ProviderTableMeta.CONTENT_URI_FILE, file.getFileId()
)
).withSelection(where, whereArgs).build());
if (file.isDown()) {
new File(file.getStoragePath()).delete();
// TODO move the deletion of local contents after success of deletions
}
}
}
@ -333,9 +354,12 @@ public class FileDataStorageManager {
// update metadata of folder
ContentValues cv = new ContentValues();
cv.put(ProviderTableMeta.FILE_MODIFIED, folder.getModificationTimestamp());
cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, folder.getModificationTimestampAtLastSyncForData());
cv.put(
ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
folder.getModificationTimestampAtLastSyncForData()
);
cv.put(ProviderTableMeta.FILE_CREATION, folder.getCreationTimestamp());
cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, 0); // FileContentProvider calculates the right size
cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, 0);
cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, folder.getMimetype());
cv.put(ProviderTableMeta.FILE_NAME, folder.getFileName());
cv.put(ProviderTableMeta.FILE_PARENT, folder.getParentId());
@ -409,18 +433,21 @@ public class FileDataStorageManager {
// Log_OC.d(TAG, "Updating size of " + id);
// if (getContentResolver() != null) {
// getContentResolver().update(ProviderTableMeta.CONTENT_URI_DIR,
// new ContentValues(), // won't be used, but cannot be null; crashes in KLP
// new ContentValues(),
// won't be used, but cannot be null; crashes in KLP
// ProviderTableMeta._ID + "=?",
// new String[] { String.valueOf(id) });
// } else {
// try {
// getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_DIR,
// new ContentValues(), // won't be used, but cannot be null; crashes in KLP
// new ContentValues(),
// won't be used, but cannot be null; crashes in KLP
// ProviderTableMeta._ID + "=?",
// new String[] { String.valueOf(id) });
//
// } catch (RemoteException e) {
// Log_OC.e(TAG, "Exception in update of folder size through compatibility patch " + e.getMessage());
// Log_OC.e(
// TAG, "Exception in update of folder size through compatibility patch " + e.getMessage());
// }
// }
// } else {
@ -437,9 +464,12 @@ public class FileDataStorageManager {
} else {
if (removeDBData) {
//Uri file_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, ""+file.getFileId());
Uri file_uri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId());
String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
Uri file_uri = ContentUris.withAppendedId(
ProviderTableMeta.CONTENT_URI_FILE,
file.getFileId()
);
String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " +
ProviderTableMeta.FILE_PATH + "=?";
String [] whereArgs = new String[]{mAccount.name, file.getRemotePath()};
int deleted = 0;
if (getContentProviderClient() != null) {
@ -481,8 +511,10 @@ public class FileDataStorageManager {
}
private boolean removeFolderInDb(OCFile folder) {
Uri folder_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, ""+ folder.getFileId()); // URI for recursive deletion
String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
Uri folder_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, "" +
folder.getFileId()); // URI for recursive deletion
String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " +
ProviderTableMeta.FILE_PATH + "=?";
String [] whereArgs = new String[]{mAccount.name, folder.getRemotePath()};
int deleted = 0;
if (getContentProviderClient() != null) {
@ -552,43 +584,67 @@ public class FileDataStorageManager {
public void moveFolder(OCFile folder, String newPath) {
// TODO check newPath
if (folder != null && folder.isFolder() && folder.fileExists() && !OCFile.ROOT_PATH.equals(folder.getFileName())) {
if ( folder != null && folder.isFolder() &&
folder.fileExists() && !OCFile.ROOT_PATH.equals(folder.getFileName())
) {
/// 1. get all the descendants of 'dir' in a single QUERY (including 'dir')
Cursor c = null;
if (getContentProviderClient() != null) {
try {
c = getContentProviderClient().query(ProviderTableMeta.CONTENT_URI,
null,
ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ? ",
new String[] { mAccount.name, folder.getRemotePath() + "%" }, ProviderTableMeta.FILE_PATH + " ASC ");
c = getContentProviderClient().query (
ProviderTableMeta.CONTENT_URI,
null,
ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " +
ProviderTableMeta.FILE_PATH + " LIKE ? ",
new String[] { mAccount.name, folder.getRemotePath() + "%" },
ProviderTableMeta.FILE_PATH + " ASC "
);
} catch (RemoteException e) {
Log_OC.e(TAG, e.getMessage());
}
} else {
c = getContentResolver().query(ProviderTableMeta.CONTENT_URI,
null,
ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ? ",
new String[] { mAccount.name, folder.getRemotePath() + "%" }, ProviderTableMeta.FILE_PATH + " ASC ");
c = getContentResolver().query (
ProviderTableMeta.CONTENT_URI,
null,
ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " +
ProviderTableMeta.FILE_PATH + " LIKE ? ",
new String[] { mAccount.name, folder.getRemotePath() + "%" },
ProviderTableMeta.FILE_PATH + " ASC "
);
}
/// 2. prepare a batch of update operations to change all the descendants
ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(c.getCount());
ArrayList<ContentProviderOperation> operations =
new ArrayList<ContentProviderOperation>(c.getCount());
int lengthOfOldPath = folder.getRemotePath().length();
String defaultSavePath = FileStorageUtils.getSavePath(mAccount.name);
int lengthOfOldStoragePath = defaultSavePath.length() + lengthOfOldPath;
if (c.moveToFirst()) {
do {
ContentValues cv = new ContentValues(); // don't take the constructor out of the loop and clear the object
ContentValues cv = new ContentValues(); // keep the constructor in the loop
OCFile child = createFileInstance(c);
cv.put(ProviderTableMeta.FILE_PATH, newPath + child.getRemotePath().substring(lengthOfOldPath));
if (child.getStoragePath() != null && child.getStoragePath().startsWith(defaultSavePath)) {
cv.put(ProviderTableMeta.FILE_STORAGE_PATH, defaultSavePath + newPath + child.getStoragePath().substring(lengthOfOldStoragePath));
cv.put(
ProviderTableMeta.FILE_PATH,
newPath + child.getRemotePath().substring(lengthOfOldPath)
);
if ( child.getStoragePath() != null &&
child.getStoragePath().startsWith(defaultSavePath) ) {
cv.put(
ProviderTableMeta.FILE_STORAGE_PATH,
defaultSavePath + newPath +
child.getStoragePath().substring(lengthOfOldStoragePath)
);
}
operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
operations.add(
ContentProviderOperation.
newUpdate(ProviderTableMeta.CONTENT_URI).
withValues(cv).
withSelection( ProviderTableMeta._ID + "=?",
new String[] { String.valueOf(child.getFileId()) })
.build());
withSelection(
ProviderTableMeta._ID + "=?",
new String[] { String.valueOf(child.getFileId()) }
).
build()
);
} while (c.moveToNext());
}
c.close();
@ -603,10 +659,12 @@ public class FileDataStorageManager {
}
} catch (OperationApplicationException e) {
Log_OC.e(TAG, "Fail to update descendants of " + folder.getFileId() + " in database", e);
Log_OC.e(TAG, "Fail to update descendants of " +
folder.getFileId() + " in database", e);
} catch (RemoteException e) {
Log_OC.e(TAG, "Fail to update desendants of " + folder.getFileId() + " in database", e);
Log_OC.e(TAG, "Fail to update desendants of " +
folder.getFileId() + " in database", e);
}
}
@ -851,7 +909,9 @@ public class FileDataStorageManager {
file.setStoragePath(c.getString(c
.getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH)));
if (file.getStoragePath() == null) {
// try to find existing file and bind it with current account; - with the current update of SynchronizeFolderOperation, this won't be necessary anymore after a full synchronization of the account
// try to find existing file and bind it with current account;
// with the current update of SynchronizeFolderOperation, this won't be
// necessary anymore after a full synchronization of the account
File f = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
if (f.exists()) {
file.setStoragePath(f.getAbsolutePath());
@ -930,13 +990,16 @@ public class FileDataStorageManager {
cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, share.getSharedWithDisplayName());
cv.put(
ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME,
share.getSharedWithDisplayName()
);
cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared());
cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, mAccount.name);
if (shareExists(share.getIdRemoteShared())) { // for renamed files; no more delete and create
if (shareExists(share.getIdRemoteShared())) { // for renamed files
overriden = true;
if (getContentResolver() != null) {
@ -1038,7 +1101,9 @@ public class FileDataStorageManager {
share.setIsFolder(c.getInt(
c.getColumnIndex(ProviderTableMeta.OCSHARES_IS_DIRECTORY)) == 1 ? true : false);
share.setUserId(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_USER_ID)));
share.setIdRemoteShared(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED)));
share.setIdRemoteShared(
c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED))
);
}
return share;
@ -1090,7 +1155,9 @@ public class FileDataStorageManager {
} else {
try {
getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs);
getContentProviderClient().update(
ProviderTableMeta.CONTENT_URI, cv, where, whereArgs
);
} catch (RemoteException e) {
Log_OC.e(TAG, "Exception in cleanSharedFiles" + e.getMessage());
@ -1102,7 +1169,8 @@ public class FileDataStorageManager {
ContentValues cv = new ContentValues();
cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, false);
cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, "");
String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PARENT + "=?";
String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " +
ProviderTableMeta.FILE_PARENT + "=?";
String [] whereArgs = new String[] { mAccount.name , String.valueOf(folder.getFileId()) };
if (getContentResolver() != null) {
@ -1110,7 +1178,9 @@ public class FileDataStorageManager {
} else {
try {
getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs);
getContentProviderClient().update(
ProviderTableMeta.CONTENT_URI, cv, where, whereArgs
);
} catch (RemoteException e) {
Log_OC.e(TAG, "Exception in cleanSharedFilesInFolder " + e.getMessage());
@ -1127,7 +1197,9 @@ public class FileDataStorageManager {
} else {
try {
getContentProviderClient().delete(ProviderTableMeta.CONTENT_URI_SHARE, where, whereArgs);
getContentProviderClient().delete(
ProviderTableMeta.CONTENT_URI_SHARE, where, whereArgs
);
} catch (RemoteException e) {
Log_OC.e(TAG, "Exception in cleanShares" + e.getMessage());
@ -1138,7 +1210,8 @@ public class FileDataStorageManager {
public void saveShares(Collection<OCShare> shares) {
cleanShares();
if (shares != null) {
ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(shares.size());
ArrayList<ContentProviderOperation> operations =
new ArrayList<ContentProviderOperation>(shares.size());
// prepare operations to insert or update files to save in the given folder
for (OCShare share : shares) {
@ -1152,7 +1225,10 @@ public class FileDataStorageManager {
cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, share.getSharedWithDisplayName());
cv.put(
ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME,
share.getSharedWithDisplayName()
);
cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared());
@ -1160,15 +1236,23 @@ public class FileDataStorageManager {
if (shareExists(share.getIdRemoteShared())) {
// updating an existing file
operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI_SHARE).
operations.add(
ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI_SHARE).
withValues(cv).
withSelection( ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?",
new String[] { String.valueOf(share.getIdRemoteShared()) })
.build());
withSelection(
ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?",
new String[] { String.valueOf(share.getIdRemoteShared()) }
).
build()
);
} else {
// adding a new file
operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI_SHARE).withValues(cv).build());
operations.add(
ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI_SHARE).
withValues(cv).
build()
);
}
}
@ -1176,10 +1260,13 @@ public class FileDataStorageManager {
if (operations.size() > 0) {
@SuppressWarnings("unused")
ContentProviderResult[] results = null;
Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
Log_OC.d(TAG, "Sending " + operations.size() +
" operations to FileContentProvider");
try {
if (getContentResolver() != null) {
results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);
results = getContentResolver().applyBatch(
MainApp.getAuthority(), operations
);
} else {
results = getContentProviderClient().applyBatch(operations);
@ -1200,13 +1287,17 @@ public class FileDataStorageManager {
cleanSharedFiles();
if (sharedFiles != null) {
ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(sharedFiles.size());
ArrayList<ContentProviderOperation> operations =
new ArrayList<ContentProviderOperation>(sharedFiles.size());
// prepare operations to insert or update files to save in the given folder
for (OCFile file : sharedFiles) {
ContentValues cv = new ContentValues();
cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData());
cv.put(
ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
file.getModificationTimestampAtLastSyncForData()
);
cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
@ -1218,27 +1309,40 @@ public class FileDataStorageManager {
}
cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
cv.put(
ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA,
file.getLastSyncDateForData()
);
cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail() ? 1 : 0);
cv.put(
ProviderTableMeta.FILE_UPDATE_THUMBNAIL,
file.needsUpdateThumbnail() ? 1 : 0
);
boolean existsByPath = fileExists(file.getRemotePath());
if (existsByPath || fileExists(file.getFileId())) {
// updating an existing file
operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
operations.add(
ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
withValues(cv).
withSelection( ProviderTableMeta._ID + "=?",
new String[] { String.valueOf(file.getFileId()) })
.build());
withSelection(
ProviderTableMeta._ID + "=?",
new String[] { String.valueOf(file.getFileId()) }
).build()
);
} else {
// adding a new file
operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).withValues(cv).build());
operations.add(
ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).
withValues(cv).
build()
);
}
}
@ -1246,10 +1350,13 @@ public class FileDataStorageManager {
if (operations.size() > 0) {
@SuppressWarnings("unused")
ContentProviderResult[] results = null;
Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
Log_OC.d(TAG, "Sending " + operations.size() +
" operations to FileContentProvider");
try {
if (getContentResolver() != null) {
results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);
results = getContentResolver().applyBatch(
MainApp.getAuthority(), operations
);
} else {
results = getContentProviderClient().applyBatch(operations);
@ -1268,7 +1375,8 @@ public class FileDataStorageManager {
public void removeShare(OCShare share){
Uri share_uri = ProviderTableMeta.CONTENT_URI_SHARE;
String where = ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
String where = ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?" + " AND " +
ProviderTableMeta.FILE_PATH + "=?";
String [] whereArgs = new String[]{mAccount.name, share.getPath()};
if (getContentProviderClient() != null) {
try {
@ -1325,7 +1433,10 @@ public class FileDataStorageManager {
cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, share.getSharedWithDisplayName());
cv.put(
ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME,
share.getSharedWithDisplayName()
);
cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared());
@ -1334,7 +1445,8 @@ public class FileDataStorageManager {
/*
if (shareExists(share.getIdRemoteShared())) {
// updating an existing share resource
operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI_SHARE).
operations.add(
ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI_SHARE).
withValues(cv).
withSelection( ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?",
new String[] { String.valueOf(share.getIdRemoteShared()) })
@ -1343,7 +1455,11 @@ public class FileDataStorageManager {
} else {
*/
// adding a new share resource
operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI_SHARE).withValues(cv).build());
operations.add(
ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI_SHARE).
withValues(cv).
build()
);
//}
}
}
@ -1372,18 +1488,23 @@ public class FileDataStorageManager {
}
private ArrayList<ContentProviderOperation> prepareRemoveSharesInFolder(OCFile folder, ArrayList<ContentProviderOperation> preparedOperations) {
private ArrayList<ContentProviderOperation> prepareRemoveSharesInFolder(
OCFile folder, ArrayList<ContentProviderOperation> preparedOperations
) {
if (folder != null) {
String where = ProviderTableMeta.OCSHARES_PATH + "=?" + " AND " + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?";
String where = ProviderTableMeta.OCSHARES_PATH + "=?" + " AND "
+ ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?";
String [] whereArgs = new String[]{ "", mAccount.name };
Vector<OCFile> files = getFolderContent(folder);
for (OCFile file : files) {
whereArgs[0] = file.getRemotePath();
preparedOperations.add(ContentProviderOperation.newDelete(ProviderTableMeta.CONTENT_URI_SHARE)
.withSelection(where, whereArgs)
.build());
preparedOperations.add(
ContentProviderOperation.newDelete(ProviderTableMeta.CONTENT_URI_SHARE).
withSelection(where, whereArgs).
build()
);
}
}
return preparedOperations;

View file

@ -0,0 +1,265 @@
/* ownCloud Android client application
* Copyright (C) 2012-2014 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* 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.datamodel;
import java.io.File;
import java.lang.ref.WeakReference;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.ThumbnailUtils;
import android.os.AsyncTask;
import android.util.TypedValue;
import android.widget.ImageView;
import com.owncloud.android.MainApp;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.ui.adapter.DiskLruImageCache;
import com.owncloud.android.utils.BitmapUtils;
import com.owncloud.android.utils.DisplayUtils;
/**
* Manager for concurrent access to thumbnails cache.
*
* @author Tobias Kaminsky
* @author David A. Velasco
*/
public class ThumbnailsCacheManager {
private static final String TAG = ThumbnailsCacheManager.class.getSimpleName();
private static final String CACHE_FOLDER = "thumbnailCache";
private static final Object mThumbnailsDiskCacheLock = new Object();
private static DiskLruImageCache mThumbnailCache = null;
private static boolean mThumbnailCacheStarting = true;
private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB
private static final CompressFormat mCompressFormat = CompressFormat.JPEG;
private static final int mCompressQuality = 70;
public static Bitmap mDefaultImg =
BitmapFactory.decodeResource(
MainApp.getAppContext().getResources(),
DisplayUtils.getResourceId("image/png", "default.png")
);
public static class InitDiskCacheTask extends AsyncTask<File, Void, Void> {
@Override
protected Void doInBackground(File... params) {
synchronized (mThumbnailsDiskCacheLock) {
mThumbnailCacheStarting = true;
if (mThumbnailCache == null) {
try {
// Check if media is mounted or storage is built-in, if so,
// try and use external cache dir; otherwise use internal cache dir
final String cachePath =
MainApp.getAppContext().getExternalCacheDir().getPath() +
File.separator + CACHE_FOLDER;
Log_OC.d(TAG, "create dir: " + cachePath);
final File diskCacheDir = new File(cachePath);
mThumbnailCache = new DiskLruImageCache(
diskCacheDir,
DISK_CACHE_SIZE,
mCompressFormat,
mCompressQuality
);
} catch (Exception e) {
Log_OC.d(TAG, "Thumbnail cache could not be opened ", e);
mThumbnailCache = null;
}
}
mThumbnailCacheStarting = false; // Finished initialization
mThumbnailsDiskCacheLock.notifyAll(); // Wake any waiting threads
}
return null;
}
}
public static void addBitmapToCache(String key, Bitmap bitmap) {
synchronized (mThumbnailsDiskCacheLock) {
if (mThumbnailCache != null) {
mThumbnailCache.put(key, bitmap);
}
}
}
public static Bitmap getBitmapFromDiskCache(String key) {
synchronized (mThumbnailsDiskCacheLock) {
// Wait while disk cache is started from background thread
while (mThumbnailCacheStarting) {
try {
mThumbnailsDiskCacheLock.wait();
} catch (InterruptedException e) {}
}
if (mThumbnailCache != null) {
return (Bitmap) mThumbnailCache.getBitmap(key);
}
}
return null;
}
public static boolean cancelPotentialWork(OCFile file, ImageView imageView) {
final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
if (bitmapWorkerTask != null) {
final OCFile bitmapData = bitmapWorkerTask.mFile;
// If bitmapData is not yet set or it differs from the new data
if (bitmapData == null || bitmapData != file) {
// Cancel previous task
bitmapWorkerTask.cancel(true);
} else {
// The same work is already in progress
return false;
}
}
// No task associated with the ImageView, or an existing task was cancelled
return true;
}
public static ThumbnailGenerationTask getBitmapWorkerTask(ImageView imageView) {
if (imageView != null) {
final Drawable drawable = imageView.getDrawable();
if (drawable instanceof AsyncDrawable) {
final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
return asyncDrawable.getBitmapWorkerTask();
}
}
return null;
}
public static class ThumbnailGenerationTask extends AsyncTask<OCFile, Void, Bitmap> {
private final WeakReference<ImageView> mImageViewReference;
private OCFile mFile;
private FileDataStorageManager mStorageManager;
public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager) {
// Use a WeakReference to ensure the ImageView can be garbage collected
mImageViewReference = new WeakReference<ImageView>(imageView);
if (storageManager == null)
throw new IllegalArgumentException("storageManager must not be NULL");
mStorageManager = storageManager;
}
// Decode image in background.
@Override
protected Bitmap doInBackground(OCFile... params) {
Bitmap thumbnail = null;
try {
mFile = params[0];
final String imageKey = String.valueOf(mFile.getRemoteId());
// Check disk cache in background thread
thumbnail = getBitmapFromDiskCache(imageKey);
// Not found in disk cache
if (thumbnail == null || mFile.needsUpdateThumbnail()) {
// Converts dp to pixel
Resources r = MainApp.getAppContext().getResources();
int px = (int) Math.round(TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 150, r.getDisplayMetrics()
));
if (mFile.isDown()){
Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
mFile.getStoragePath(), px, px);
if (bitmap != null) {
thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
// Add thumbnail to cache
addBitmapToCache(imageKey, thumbnail);
mFile.setNeedsUpdateThumbnail(false);
mStorageManager.saveFile(mFile);
}
}
}
} catch (Throwable t) {
// the app should never break due to a problem with thumbnails
Log_OC.e(TAG, "Generation of thumbnail for " + mFile + " failed", t);
if (t instanceof OutOfMemoryError) {
System.gc();
}
}
return thumbnail;
}
protected void onPostExecute(Bitmap bitmap){
if (isCancelled()) {
bitmap = null;
}
if (mImageViewReference != null && bitmap != null) {
final ImageView imageView = mImageViewReference.get();
final ThumbnailGenerationTask bitmapWorkerTask =
getBitmapWorkerTask(imageView);
if (this == bitmapWorkerTask && imageView != null) {
if (imageView.getTag().equals(mFile.getFileId())) {
imageView.setImageBitmap(bitmap);
}
}
}
}
}
public static class AsyncDrawable extends BitmapDrawable {
private final WeakReference<ThumbnailGenerationTask> bitmapWorkerTaskReference;
public AsyncDrawable(
Resources res, Bitmap bitmap, ThumbnailGenerationTask bitmapWorkerTask
) {
super(res, bitmap);
bitmapWorkerTaskReference =
new WeakReference<ThumbnailGenerationTask>(bitmapWorkerTask);
}
public ThumbnailGenerationTask getBitmapWorkerTask() {
return bitmapWorkerTaskReference.get();
}
}
/**
* Remove from cache the remoteId passed
* @param fileRemoteId: remote id of mFile passed
*/
public static void removeFileFromCache(String fileRemoteId){
synchronized (mThumbnailsDiskCacheLock) {
if (mThumbnailCache != null) {
mThumbnailCache.removeKey(fileRemoteId);
}
mThumbnailsDiskCacheLock.notifyAll(); // Wake any waiting threads
}
}
}

View file

@ -398,6 +398,7 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
file.setMimetype(mCurrentDownload.getMimeType());
file.setStoragePath(mCurrentDownload.getSavePath());
file.setFileLength((new File(mCurrentDownload.getSavePath()).length()));
file.setRemoteId(mCurrentDownload.getFile().getRemoteId());
mStorageManager.saveFile(file);
}

View file

@ -630,7 +630,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
// coincidence; nothing else is needed, the storagePath is right
// in the instance returned by mCurrentUpload.getFile()
}
file.setNeedsUpdateThumbnail(true);
mStorageManager.saveFile(file);
}
@ -641,6 +641,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
file.setModificationTimestamp(remoteFile.getModifiedTimestamp());
file.setModificationTimestampAtLastSyncForData(remoteFile.getModifiedTimestamp());
// file.setEtag(remoteFile.getEtag()); // TODO Etag, where available
file.setRemoteId(remoteFile.getRemoteId());
}
private OCFile obtainNewOCFileToUpload(String remotePath, String localPath, String mimeType,

View file

@ -84,21 +84,36 @@ public class CreateFolderOperation extends SyncOperation implements OnRemoteOper
}
}
/**
* Save new directory in local database
*/
public void saveFolderInDB() {
OCFile newDir = new OCFile(mRemotePath);
newDir.setMimetype("DIR");
long parentId = getStorageManager().getFileByPath(FileStorageUtils.getParentPath(mRemotePath)).getFileId();
newDir.setParentId(parentId);
newDir.setModificationTimestamp(System.currentTimeMillis());
getStorageManager().saveFile(newDir);
if (mCreateFullPath && getStorageManager().
getFileByPath(FileStorageUtils.getParentPath(mRemotePath)) == null){// When parent
// of remote path
// is not created
String[] subFolders = mRemotePath.split("/");
String composedRemotePath = "/";
Log_OC.d(TAG, "Create directory " + mRemotePath + " in Database");
// For each antecesor folders create them recursively
for (int i=0; i<subFolders.length; i++) {
String subFolder = subFolders[i];
if (!subFolder.isEmpty()) {
composedRemotePath = composedRemotePath + subFolder + "/";
mRemotePath = composedRemotePath;
saveFolderInDB();
}
}
} else { // Create directory on DB
OCFile newDir = new OCFile(mRemotePath);
newDir.setMimetype("DIR");
long parentId = getStorageManager().
getFileByPath(FileStorageUtils.getParentPath(mRemotePath)).getFileId();
newDir.setParentId(parentId);
newDir.setModificationTimestamp(System.currentTimeMillis());
getStorageManager().saveFile(newDir);
Log_OC.d(TAG, "Create directory " + mRemotePath + " in Database");
}
}
}

View file

@ -170,6 +170,8 @@ public class SynchronizeFileOperation extends SyncOperation {
result = new RemoteOperationResult(ResultCode.OK);
} else if (serverChanged) {
mLocalFile.setRemoteId(mServerFile.getRemoteId());
if (mSyncFileContents) {
requestForDownload(mLocalFile); // local, not server; we won't to keep the value of keepInSync!
// the update of local data will be done later by the FileUploader service when the upload finishes

View file

@ -70,8 +70,10 @@ public class SynchronizeFolderOperation extends RemoteOperation {
private static final String TAG = SynchronizeFolderOperation.class.getSimpleName();
public static final String EVENT_SINGLE_FOLDER_CONTENTS_SYNCED = SynchronizeFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_CONTENTS_SYNCED";
public static final String EVENT_SINGLE_FOLDER_SHARES_SYNCED = SynchronizeFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_SHARES_SYNCED";
public static final String EVENT_SINGLE_FOLDER_CONTENTS_SYNCED =
SynchronizeFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_CONTENTS_SYNCED";
public static final String EVENT_SINGLE_FOLDER_SHARES_SYNCED =
SynchronizeFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_SHARES_SYNCED";
/** Time stamp for the synchronization process in progress */
private long mCurrentSyncTime;
@ -97,16 +99,19 @@ public class SynchronizeFolderOperation extends RemoteOperation {
/** Counter of failed operations in synchronization of kept-in-sync files */
private int mFailsInFavouritesFound;
/** Map of remote and local paths to files that where locally stored in a location out of the ownCloud folder and couldn't be copied automatically into it */
/**
* Map of remote and local paths to files that where locally stored in a location
* out of the ownCloud folder and couldn't be copied automatically into it
**/
private Map<String, String> mForgottenLocalFiles;
/** 'True' means that this operation is part of a full account synchronization */
private boolean mSyncFullAccount;
/** 'True' means that Share resources bound to the files into the folder should be refreshed also */
/** 'True' means that Share resources bound to the files into should be refreshed also */
private boolean mIsShareSupported;
/** 'True' means that the remote folder changed from last synchronization and should be fetched */
/** 'True' means that the remote folder changed and should be fetched */
private boolean mRemoteFolderChanged;
/** 'True' means that Etag will be ignored */
@ -118,9 +123,12 @@ public class SynchronizeFolderOperation extends RemoteOperation {
*
* @param remoteFolderPath Remote folder to synchronize.
* @param currentSyncTime Time stamp for the synchronization process in progress.
* @param localFolderId Identifier in the local database of the folder to synchronize.
* @param updateFolderProperties 'True' means that the properties of the folder should be updated also, not just its content.
* @param syncFullAccount 'True' means that this operation is part of a full account synchronization.
* @param localFolderId Identifier in the local database of the folder
* to synchronize.
* @param updateFolderProperties 'True' means that the properties of the folder should
* be updated also, not just its content.
* @param syncFullAccount 'True' means that this operation is part of a full account
* synchronization.
* @param dataStorageManager Interface with the local database.
* @param account ownCloud account where the folder is located.
* @param context Application context.
@ -159,7 +167,8 @@ public class SynchronizeFolderOperation extends RemoteOperation {
}
/**
* Returns the list of files and folders contained in the synchronized folder, if called after synchronization is complete.
* Returns the list of files and folders contained in the synchronized folder,
* if called after synchronization is complete.
*
* @return List of files and folders contained in the synchronized folder.
*/
@ -194,7 +203,9 @@ public class SynchronizeFolderOperation extends RemoteOperation {
}
if (!mSyncFullAccount) {
sendLocalBroadcast(EVENT_SINGLE_FOLDER_CONTENTS_SYNCED, mLocalFolder.getRemotePath(), result);
sendLocalBroadcast(
EVENT_SINGLE_FOLDER_CONTENTS_SYNCED, mLocalFolder.getRemotePath(), result
);
}
if (result.isSuccess() && mIsShareSupported && !mSyncFullAccount) {
@ -202,7 +213,9 @@ public class SynchronizeFolderOperation extends RemoteOperation {
}
if (!mSyncFullAccount) {
sendLocalBroadcast(EVENT_SINGLE_FOLDER_SHARES_SYNCED, mLocalFolder.getRemotePath(), result);
sendLocalBroadcast(
EVENT_SINGLE_FOLDER_SHARES_SYNCED, mLocalFolder.getRemotePath(), result
);
}
return result;
@ -235,12 +248,14 @@ public class SynchronizeFolderOperation extends RemoteOperation {
if (!mIgnoreETag) {
// check if remote and local folder are different
mRemoteFolderChanged = !(remoteFolder.getEtag().equalsIgnoreCase(mLocalFolder.getEtag()));
mRemoteFolderChanged =
!(remoteFolder.getEtag().equalsIgnoreCase(mLocalFolder.getEtag()));
}
result = new RemoteOperationResult(ResultCode.OK);
Log_OC.i(TAG, "Checked " + mAccount.name + remotePath + " : " + (mRemoteFolderChanged ? "changed" : "not changed"));
Log_OC.i(TAG, "Checked " + mAccount.name + remotePath + " : " +
(mRemoteFolderChanged ? "changed" : "not changed"));
} else {
// check failed
@ -248,9 +263,11 @@ public class SynchronizeFolderOperation extends RemoteOperation {
removeLocalFolder();
}
if (result.isException()) {
Log_OC.e(TAG, "Checked " + mAccount.name + remotePath + " : " + result.getLogMessage(), result.getException());
Log_OC.e(TAG, "Checked " + mAccount.name + remotePath + " : " +
result.getLogMessage(), result.getException());
} else {
Log_OC.e(TAG, "Checked " + mAccount.name + remotePath + " : " + result.getLogMessage());
Log_OC.e(TAG, "Checked " + mAccount.name + remotePath + " : " +
result.getLogMessage());
}
}
@ -267,7 +284,8 @@ public class SynchronizeFolderOperation extends RemoteOperation {
if (result.isSuccess()) {
synchronizeData(result.getData(), client);
if (mConflictsFound > 0 || mFailsInFavouritesFound > 0) {
result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT); // should be different result, but will do the job
result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);
// should be a different result code, but will do the job
}
} else {
if (result.getCode() == ResultCode.FILE_NOT_FOUND)
@ -281,7 +299,13 @@ public class SynchronizeFolderOperation extends RemoteOperation {
private void removeLocalFolder() {
if (mStorageManager.fileExists(mLocalFolder.getFileId())) {
String currentSavePath = FileStorageUtils.getSavePath(mAccount.name);
mStorageManager.removeFolder(mLocalFolder, true, (mLocalFolder.isDown() && mLocalFolder.getStoragePath().startsWith(currentSavePath)));
mStorageManager.removeFolder(
mLocalFolder,
true,
( mLocalFolder.isDown() &&
mLocalFolder.getStoragePath().startsWith(currentSavePath)
)
);
}
}
@ -296,7 +320,7 @@ public class SynchronizeFolderOperation extends RemoteOperation {
*
* @param client Client instance to the remote server where the data were
* retrieved.
* @return 'True' when any change was made in the local data, 'false' otherwise.
* @return 'True' when any change was made in the local data, 'false' otherwise
*/
private void synchronizeData(ArrayList<Object> folderAndFiles, OwnCloudClient client) {
// get 'fresh data' from the database
@ -307,7 +331,8 @@ public class SynchronizeFolderOperation extends RemoteOperation {
remoteFolder.setParentId(mLocalFolder.getParentId());
remoteFolder.setFileId(mLocalFolder.getFileId());
Log_OC.d(TAG, "Remote folder " + mLocalFolder.getRemotePath() + " changed - starting update of local data ");
Log_OC.d(TAG, "Remote folder " + mLocalFolder.getRemotePath()
+ " changed - starting update of local data ");
List<OCFile> updatedFiles = new Vector<OCFile>(folderAndFiles.size() - 1);
List<SynchronizeFileOperation> filesToSyncContents = new Vector<SynchronizeFileOperation>();
@ -327,30 +352,38 @@ public class SynchronizeFolderOperation extends RemoteOperation {
remoteFile.setParentId(mLocalFolder.getFileId());
/// retrieve local data for the read file
//localFile = mStorageManager.getFileByPath(remoteFile.getRemotePath());
// localFile = mStorageManager.getFileByPath(remoteFile.getRemotePath());
localFile = localFilesMap.remove(remoteFile.getRemotePath());
/// add to the remoteFile (the new one) data about LOCAL STATE (not existing in the server side)
/// add to the remoteFile (the new one) data about LOCAL STATE (not existing in server)
remoteFile.setLastSyncDateForProperties(mCurrentSyncTime);
if (localFile != null) {
// some properties of local state are kept unmodified
remoteFile.setFileId(localFile.getFileId());
remoteFile.setKeepInSync(localFile.keepInSync());
remoteFile.setLastSyncDateForData(localFile.getLastSyncDateForData());
remoteFile.setModificationTimestampAtLastSyncForData(localFile.getModificationTimestampAtLastSyncForData());
remoteFile.setModificationTimestampAtLastSyncForData(
localFile.getModificationTimestampAtLastSyncForData()
);
remoteFile.setStoragePath(localFile.getStoragePath());
remoteFile.setEtag(localFile.getEtag()); // eTag will not be updated unless contents are synchronized (Synchronize[File|Folder]Operation with remoteFile as parameter)
// eTag will not be updated unless contents are synchronized
// (Synchronize[File|Folder]Operation with remoteFile as parameter)
remoteFile.setEtag(localFile.getEtag());
if (remoteFile.isFolder()) {
remoteFile.setFileLength(localFile.getFileLength()); // TODO move operations about size of folders to FileContentProvider
remoteFile.setFileLength(localFile.getFileLength());
// TODO move operations about size of folders to FileContentProvider
}
remoteFile.setPublicLink(localFile.getPublicLink());
remoteFile.setShareByLink(localFile.isShareByLink());
} else {
remoteFile.setEtag(""); // remote eTag will not be updated unless contents are synchronized (Synchronize[File|Folder]Operation with remoteFile as parameter)
// remote eTag will not be updated unless contents are synchronized
// (Synchronize[File|Folder]Operation with remoteFile as parameter)
remoteFile.setEtag("");
}
/// check and fix, if needed, local storage path
checkAndFixForeignStoragePath(remoteFile); // fixing old policy - now local files must be copied into the ownCloud local folder
checkAndFixForeignStoragePath(remoteFile); // policy - local files are COPIED
// into the ownCloud local folder;
searchForLocalFileInDefaultPath(remoteFile); // legacy
/// prepare content synchronization for kept-in-sync files
@ -368,7 +401,7 @@ public class SynchronizeFolderOperation extends RemoteOperation {
updatedFiles.add(remoteFile);
}
// save updated contents in local database; all at once, trying to get a best performance in database update (not a big deal, indeed)
// save updated contents in local database
mStorageManager.saveFolder(remoteFolder, updatedFiles, localFilesMap.values());
// request for the synchronization of file contents AFTER saving current remote properties
@ -378,27 +411,32 @@ public class SynchronizeFolderOperation extends RemoteOperation {
}
/**
* Performs a list of synchronization operations, determining if a download or upload is needed or
* if exists conflict due to changes both in local and remote contents of the each file.
* Performs a list of synchronization operations, determining if a download or upload is needed
* or if exists conflict due to changes both in local and remote contents of the each file.
*
* If download or upload is needed, request the operation to the corresponding service and goes on.
* If download or upload is needed, request the operation to the corresponding service and goes
* on.
*
* @param filesToSyncContents Synchronization operations to execute.
* @param client Interface to the remote ownCloud server.
*/
private void startContentSynchronizations(List<SynchronizeFileOperation> filesToSyncContents, OwnCloudClient client) {
private void startContentSynchronizations(
List<SynchronizeFileOperation> filesToSyncContents, OwnCloudClient client
) {
RemoteOperationResult contentsResult = null;
for (SynchronizeFileOperation op: filesToSyncContents) {
contentsResult = op.execute(mStorageManager, mContext); // returns without waiting for upload or download finishes
contentsResult = op.execute(mStorageManager, mContext); // async
if (!contentsResult.isSuccess()) {
if (contentsResult.getCode() == ResultCode.SYNC_CONFLICT) {
mConflictsFound++;
} else {
mFailsInFavouritesFound++;
if (contentsResult.getException() != null) {
Log_OC.e(TAG, "Error while synchronizing favourites : " + contentsResult.getLogMessage(), contentsResult.getException());
Log_OC.e(TAG, "Error while synchronizing favourites : "
+ contentsResult.getLogMessage(), contentsResult.getException());
} else {
Log_OC.e(TAG, "Error while synchronizing favourites : " + contentsResult.getLogMessage());
Log_OC.e(TAG, "Error while synchronizing favourites : "
+ contentsResult.getLogMessage());
}
}
} // won't let these fails break the synchronization process
@ -430,11 +468,11 @@ public class SynchronizeFolderOperation extends RemoteOperation {
/**
* Checks the storage path of the OCFile received as parameter. If it's out of the local ownCloud folder,
* tries to copy the file inside it.
* Checks the storage path of the OCFile received as parameter.
* If it's out of the local ownCloud folder, tries to copy the file inside it.
*
* If the copy fails, the link to the local file is nullified. The account of forgotten files is kept in
* {@link #mForgottenLocalFiles}
* If the copy fails, the link to the local file is nullified. The account of forgotten
* files is kept in {@link #mForgottenLocalFiles}
*)
* @param file File to check and fix.
*/
@ -456,7 +494,9 @@ public class SynchronizeFolderOperation extends RemoteOperation {
File expectedParent = expectedFile.getParentFile();
expectedParent.mkdirs();
if (!expectedParent.isDirectory()) {
throw new IOException("Unexpected error: parent directory could not be created");
throw new IOException(
"Unexpected error: parent directory could not be created"
);
}
expectedFile.createNewFile();
if (!expectedFile.isFile()) {
@ -480,12 +520,14 @@ public class SynchronizeFolderOperation extends RemoteOperation {
try {
if (in != null) in.close();
} catch (Exception e) {
Log_OC.d(TAG, "Weird exception while closing input stream for " + storagePath + " (ignoring)", e);
Log_OC.d(TAG, "Weird exception while closing input stream for "
+ storagePath + " (ignoring)", e);
}
try {
if (out != null) out.close();
} catch (Exception e) {
Log_OC.d(TAG, "Weird exception while closing output stream for " + expectedPath + " (ignoring)", e);
Log_OC.d(TAG, "Weird exception while closing output stream for "
+ expectedPath + " (ignoring)", e);
}
}
}
@ -497,7 +539,8 @@ public class SynchronizeFolderOperation extends RemoteOperation {
RemoteOperationResult result = null;
// remote request
GetRemoteSharesForFileOperation operation = new GetRemoteSharesForFileOperation(mLocalFolder.getRemotePath(), false, true);
GetRemoteSharesForFileOperation operation =
new GetRemoteSharesForFileOperation(mLocalFolder.getRemotePath(), false, true);
result = operation.execute(client);
if (result.isSuccess()) {
@ -532,13 +575,17 @@ public class SynchronizeFolderOperation extends RemoteOperation {
/**
* Sends a message to any application component interested in the progress of the synchronization.
* Sends a message to any application component interested in the progress
* of the synchronization.
*
* @param event
* @param dirRemotePath Remote path of a folder that was just synchronized (with or without success)
* @param dirRemotePath Remote path of a folder that was just synchronized
* (with or without success)
* @param result
*/
private void sendLocalBroadcast(String event, String dirRemotePath, RemoteOperationResult result) {
private void sendLocalBroadcast(
String event, String dirRemotePath, RemoteOperationResult result
) {
Log_OC.d(TAG, "Send broadcast " + event);
Intent intent = new Intent(event);
intent.putExtra(FileSyncAdapter.EXTRA_ACCOUNT_NAME, mAccount.name);

View file

@ -22,13 +22,12 @@ import java.util.ArrayList;
import java.util.HashMap;
import com.owncloud.android.R;
import com.owncloud.android.datamodel.ThumbnailsCacheManager;
import com.owncloud.android.db.ProviderMeta;
import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.shares.ShareType;
import android.content.ContentProvider;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
@ -165,13 +164,14 @@ public class FileContentProvider extends ContentProvider {
int count = 0;
switch (mUriMatcher.match(uri)) {
case SINGLE_FILE:
/*Cursor c = query(db, uri, null, where, whereArgs, null);
String remotePath = "(unexisting)";
Cursor c = query(db, uri, null, where, whereArgs, null);
String remoteId = "";
if (c != null && c.moveToFirst()) {
remotePath = c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PATH));
remoteId = c.getString(c.getColumnIndex(ProviderTableMeta.FILE_REMOTE_ID));
//ThumbnailsCacheManager.removeFileFromCache(remoteId);
}
Log_OC.d(TAG, "Removing FILE " + remotePath);
*/
Log_OC.d(TAG, "Removing FILE " + remoteId);
count = db.delete(ProviderTableMeta.FILE_TABLE_NAME,
ProviderTableMeta._ID
+ "="
@ -197,16 +197,28 @@ public class FileContentProvider extends ContentProvider {
Cursor children = query(uri, null, null, null, null);
if (children != null && children.moveToFirst()) {
long childId;
boolean isDir;
boolean isDir;
//String remotePath;
while (!children.isAfterLast()) {
childId = children.getLong(children.getColumnIndex(ProviderTableMeta._ID));
isDir = "DIR".equals(children.getString(children.getColumnIndex(ProviderTableMeta.FILE_CONTENT_TYPE)));
isDir = "DIR".equals(children.getString(
children.getColumnIndex(ProviderTableMeta.FILE_CONTENT_TYPE)
));
//remotePath = children.getString(children.getColumnIndex(ProviderTableMeta.FILE_PATH));
if (isDir) {
count += delete(db, ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, childId), null, null);
count += delete(
db,
ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, childId),
null,
null
);
} else {
count += delete(db, ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, childId), null, null);
count += delete(
db,
ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, childId),
null,
null
);
}
children.moveToNext();
}
@ -240,7 +252,6 @@ public class FileContentProvider extends ContentProvider {
}
return count;
}
@Override
public String getType(Uri uri) {
@ -257,7 +268,6 @@ public class FileContentProvider extends ContentProvider {
@Override
public Uri insert(Uri uri, ContentValues values) {
//Log_OC.d(TAG, "Inserting " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
Uri newUri = null;
SQLiteDatabase db = mDbHelper.getWritableDatabase();
db.beginTransaction();
@ -277,23 +287,31 @@ public class FileContentProvider extends ContentProvider {
case SINGLE_FILE:
String remotePath = values.getAsString(ProviderTableMeta.FILE_PATH);
String accountName = values.getAsString(ProviderTableMeta.FILE_ACCOUNT_OWNER);
String[] projection = new String[] {ProviderTableMeta._ID, ProviderTableMeta.FILE_PATH, ProviderTableMeta.FILE_ACCOUNT_OWNER };
String where = ProviderTableMeta.FILE_PATH + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?";
String[] projection = new String[] {
ProviderTableMeta._ID, ProviderTableMeta.FILE_PATH,
ProviderTableMeta.FILE_ACCOUNT_OWNER
};
String where = ProviderTableMeta.FILE_PATH + "=? AND " +
ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?";
String[] whereArgs = new String[] {remotePath, accountName};
Cursor doubleCheck = query(db, uri, projection, where, whereArgs, null);
if (doubleCheck == null || !doubleCheck.moveToFirst()) { // ugly patch; serious refactorization is needed to reduce work in FileDataStorageManager and bring it to FileContentProvider
// ugly patch; serious refactorization is needed to reduce work in
// FileDataStorageManager and bring it to FileContentProvider
if (doubleCheck == null || !doubleCheck.moveToFirst()) {
long rowId = db.insert(ProviderTableMeta.FILE_TABLE_NAME, null, values);
if (rowId > 0) {
Uri insertedFileUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, rowId);
//Log_OC.d(TAG, "Inserted " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
Uri insertedFileUri =
ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, rowId);
return insertedFileUri;
} else {
//Log_OC.d(TAG, "Error while inserting " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
throw new SQLException("ERROR " + uri);
}
} else {
// file is already inserted; race condition, let's avoid a duplicated entry
Uri insertedFileUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, doubleCheck.getLong(doubleCheck.getColumnIndex(ProviderTableMeta._ID)));
Uri insertedFileUri = ContentUris.withAppendedId(
ProviderTableMeta.CONTENT_URI_FILE,
doubleCheck.getLong(doubleCheck.getColumnIndex(ProviderTableMeta._ID))
);
doubleCheck.close();
return insertedFileUri;
@ -302,22 +320,35 @@ public class FileContentProvider extends ContentProvider {
case SHARES:
String path = values.getAsString(ProviderTableMeta.OCSHARES_PATH);
String accountNameShare= values.getAsString(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER);
String[] projectionShare = new String[] {ProviderTableMeta._ID, ProviderTableMeta.OCSHARES_PATH, ProviderTableMeta.OCSHARES_ACCOUNT_OWNER };
String whereShare = ProviderTableMeta.OCSHARES_PATH + "=? AND " + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?";
String[] projectionShare = new String[] {
ProviderTableMeta._ID, ProviderTableMeta.OCSHARES_PATH,
ProviderTableMeta.OCSHARES_ACCOUNT_OWNER
};
String whereShare = ProviderTableMeta.OCSHARES_PATH + "=? AND " +
ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?";
String[] whereArgsShare = new String[] {path, accountNameShare};
Uri insertedShareUri = null;
Cursor doubleCheckShare = query(db, uri, projectionShare, whereShare, whereArgsShare, null);
if (doubleCheckShare == null || !doubleCheckShare.moveToFirst()) { // ugly patch; serious refactorization is needed to reduce work in FileDataStorageManager and bring it to FileContentProvider
Cursor doubleCheckShare =
query(db, uri, projectionShare, whereShare, whereArgsShare, null);
// ugly patch; serious refactorization is needed to reduce work in
// FileDataStorageManager and bring it to FileContentProvider
if (doubleCheckShare == null || !doubleCheckShare.moveToFirst()) {
long rowId = db.insert(ProviderTableMeta.OCSHARES_TABLE_NAME, null, values);
if (rowId >0) {
insertedShareUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_SHARE, rowId);
insertedShareUri =
ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_SHARE, rowId);
} else {
throw new SQLException("ERROR " + uri);
}
} else {
// file is already inserted; race condition, let's avoid a duplicated entry
insertedShareUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_SHARE, doubleCheckShare.getLong(doubleCheckShare.getColumnIndex(ProviderTableMeta._ID)));
insertedShareUri = ContentUris.withAppendedId(
ProviderTableMeta.CONTENT_URI_SHARE,
doubleCheckShare.getLong(
doubleCheckShare.getColumnIndex(ProviderTableMeta._ID)
)
);
doubleCheckShare.close();
}
updateFilesTableAccordingToShareInsertion(db, uri, values);
@ -330,11 +361,17 @@ public class FileContentProvider extends ContentProvider {
}
private void updateFilesTableAccordingToShareInsertion(SQLiteDatabase db, Uri uri, ContentValues shareValues) {
private void updateFilesTableAccordingToShareInsertion(
SQLiteDatabase db, Uri uri, ContentValues shareValues
) {
ContentValues fileValues = new ContentValues();
fileValues.put(ProviderTableMeta.FILE_SHARE_BY_LINK,
ShareType.PUBLIC_LINK.getValue() == shareValues.getAsInteger(ProviderTableMeta.OCSHARES_SHARE_TYPE)? 1 : 0);
String whereShare = ProviderTableMeta.FILE_PATH + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?";
fileValues.put(
ProviderTableMeta.FILE_SHARE_BY_LINK,
ShareType.PUBLIC_LINK.getValue() ==
shareValues.getAsInteger(ProviderTableMeta.OCSHARES_SHARE_TYPE)? 1 : 0
);
String whereShare = ProviderTableMeta.FILE_PATH + "=? AND " +
ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?";
String[] whereArgsShare = new String[] {
shareValues.getAsString(ProviderTableMeta.OCSHARES_PATH),
shareValues.getAsString(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER)
@ -362,7 +399,14 @@ public class FileContentProvider extends ContentProvider {
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
public Cursor query(
Uri uri,
String[] projection,
String selection,
String[] selectionArgs,
String sortOrder
) {
Cursor result = null;
SQLiteDatabase db = mDbHelper.getReadableDatabase();
db.beginTransaction();
@ -375,7 +419,15 @@ public class FileContentProvider extends ContentProvider {
return result;
}
private Cursor query(SQLiteDatabase db, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
private Cursor query(
SQLiteDatabase db,
Uri uri,
String[] projection,
String selection,
String[] selectionArgs,
String sortOrder
) {
SQLiteQueryBuilder sqlQuery = new SQLiteQueryBuilder();
sqlQuery.setTables(ProviderTableMeta.FILE_TABLE_NAME);
@ -429,7 +481,6 @@ public class FileContentProvider extends ContentProvider {
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
//Log_OC.d(TAG, "Updating " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
int count = 0;
SQLiteDatabase db = mDbHelper.getWritableDatabase();
db.beginTransaction();
@ -445,14 +496,24 @@ public class FileContentProvider extends ContentProvider {
private int update(SQLiteDatabase db, Uri uri, ContentValues values, String selection, String[] selectionArgs) {
private int update(
SQLiteDatabase db,
Uri uri,
ContentValues values,
String selection,
String[] selectionArgs
) {
switch (mUriMatcher.match(uri)) {
case DIRECTORY:
return 0; //updateFolderSize(db, selectionArgs[0]);
case SHARES:
return db.update(ProviderTableMeta.OCSHARES_TABLE_NAME, values, selection, selectionArgs);
return db.update(
ProviderTableMeta.OCSHARES_TABLE_NAME, values, selection, selectionArgs
);
default:
return db.update(ProviderTableMeta.FILE_TABLE_NAME, values, selection, selectionArgs);
return db.update(
ProviderTableMeta.FILE_TABLE_NAME, values, selection, selectionArgs
);
}
}
@ -510,8 +571,10 @@ public class FileContentProvider extends ContentProvider {
*/
@Override
public ContentProviderResult[] applyBatch (ArrayList<ContentProviderOperation> operations) throws OperationApplicationException {
Log_OC.d("FileContentProvider", "applying batch in provider " + this + " (temporary: " + isTemporary() + ")" );
public ContentProviderResult[] applyBatch (ArrayList<ContentProviderOperation> operations)
throws OperationApplicationException {
Log_OC.d("FileContentProvider", "applying batch in provider " + this +
" (temporary: " + isTemporary() + ")" );
ContentProviderResult[] results = new ContentProviderResult[operations.size()];
int i=0;
@ -600,12 +663,13 @@ public class FileContentProvider extends ContentProvider {
db.beginTransaction();
try {
db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME +
" ADD COLUMN " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " INTEGER " +
" DEFAULT 0");
" ADD COLUMN " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA +
" INTEGER " + " DEFAULT 0");
// assume there are not local changes pending to upload
db.execSQL("UPDATE " + ProviderTableMeta.FILE_TABLE_NAME +
" SET " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " = " + System.currentTimeMillis() +
" SET " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " = "
+ System.currentTimeMillis() +
" WHERE " + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL");
upgraded = true;
@ -619,11 +683,12 @@ public class FileContentProvider extends ContentProvider {
db.beginTransaction();
try {
db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME +
" ADD COLUMN " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " INTEGER " +
" DEFAULT 0");
" ADD COLUMN " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA +
" INTEGER " + " DEFAULT 0");
db.execSQL("UPDATE " + ProviderTableMeta.FILE_TABLE_NAME +
" SET " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " = " + ProviderTableMeta.FILE_MODIFIED +
" SET " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " = " +
ProviderTableMeta.FILE_MODIFIED +
" WHERE " + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL");
upgraded = true;
@ -633,7 +698,8 @@ public class FileContentProvider extends ContentProvider {
}
}
if (!upgraded)
Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion +
", newVersion == " + newVersion);
if (oldVersion < 5 && newVersion >= 5) {
Log_OC.i("SQL", "Entering in the #4 ADD in onUpgrade");
@ -650,7 +716,8 @@ public class FileContentProvider extends ContentProvider {
}
}
if (!upgraded)
Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion +
", newVersion == " + newVersion);
if (oldVersion < 6 && newVersion >= 6) {
Log_OC.i("SQL", "Entering in the #5 ADD in onUpgrade");
@ -689,7 +756,8 @@ public class FileContentProvider extends ContentProvider {
}
}
if (!upgraded)
Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion +
", newVersion == " + newVersion);
if (oldVersion < 7 && newVersion >= 7) {
Log_OC.i("SQL", "Entering in the #7 ADD in onUpgrade");
@ -710,7 +778,8 @@ public class FileContentProvider extends ContentProvider {
}
}
if (!upgraded)
Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion +
", newVersion == " + newVersion);
if (oldVersion < 8 && newVersion >= 8) {
Log_OC.i("SQL", "Entering in the #8 ADD in onUpgrade");
@ -727,7 +796,8 @@ public class FileContentProvider extends ContentProvider {
}
}
if (!upgraded)
Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);
Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion +
", newVersion == " + newVersion);
}
}

View file

@ -31,7 +31,6 @@ import android.content.res.Resources.NotFoundException;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
@ -64,7 +63,7 @@ import com.owncloud.android.utils.ErrorMessageAdapter;
import com.owncloud.android.lib.common.utils.Log_OC;
public class MoveActivity extends HookActivity implements FileFragment.ContainerActivity,
OnClickListener, SwipeRefreshLayout.OnRefreshListener {
OnClickListener, OnEnforceableRefreshListener {
public static final String EXTRA_CURRENT_FOLDER = UploadFilesActivity.class.getCanonicalName() + ".EXTRA_CURRENT_FOLDER";
public static final String EXTRA_TARGET_FILE = UploadFilesActivity.class.getCanonicalName() + "EXTRA_TARGET_FILE";
@ -554,16 +553,23 @@ public class MoveActivity extends HookActivity implements FileFragment.Container
}
@Override
public void onRefresh() {
refreshList(true);
}
@Override
public void onRefresh(boolean enforced) {
refreshList(enforced);
}
private void refreshList(boolean ignoreETag) {
OCFileListFragment listOfFiles = getListOfFilesFragment();
if (listOfFiles != null) {
OCFile folder = listOfFiles.getCurrentFile();
if (folder != null) {
startSyncFolderOperation(folder, true);
startSyncFolderOperation(folder, ignoreETag);
}
}
}
}

View file

@ -74,6 +74,7 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa
private final Handler mHandler = new Handler();
private String mAccountName;
private boolean mShowContextMenu = false;
private String mUploadPath;
@SuppressWarnings("deprecation")
@ -87,7 +88,9 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa
actionBar.setIcon(DisplayUtils.getSeasonalIconId());
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setTitle(R.string.actionbar_settings);
loadInstantUploadPath();
// Load the accounts category for adding the list of accounts
mAccountsPrefCategory = (PreferenceCategory) findPreference("accounts_category");
@ -239,6 +242,16 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa
preferenceCategory.removePreference(pImprint);
}
}
Preference pInstantUploadPathApp = (Preference) findPreference("instant_upload_path");
pInstantUploadPathApp.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
mUploadPath = updateInstantUploadPath(newValue.toString());
return true;
}
});
/* About App */
pAboutApp = (Preference) findPreference("about_app");
@ -254,6 +267,12 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa
}
}
@Override
protected void onPause() {
saveInstantUploadPathOnPreferences();
super.onPause();
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
@ -462,4 +481,47 @@ public class Preferences extends SherlockPreferenceActivity implements AccountMa
}
/**
* Update the upload path checking that it is a correct path
* @param uploadPath: path write by user
* @return String: uploadPath
*/
private String updateInstantUploadPath(String uploadPath) {
String slashString = "/";
// If slashes are duplicated, replace them for only one slash
uploadPath = uploadPath.replaceAll("/+", slashString);
// Remove last slash from path
if (uploadPath.length() > 0 && uploadPath.charAt(uploadPath.length()-1) == slashString.charAt(0)) {
uploadPath = uploadPath.substring(0, uploadPath.length()-1);
}
if (uploadPath.isEmpty()) { // Set default instant upload path
uploadPath = getString(R.string.instant_upload_path);
}else {
if (!uploadPath.startsWith(slashString)) { // Add initial slash on path if necessary
uploadPath = slashString.concat(uploadPath);
}
}
return uploadPath;
}
/**
* Load upload path set on preferences
*/
private void loadInstantUploadPath() {
SharedPreferences appPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
mUploadPath = appPrefs.getString("instant_upload_path", getString(R.string.instant_upload_path));
}
/**
* Save the "Instant Upload Path" on preferences
*/
private void saveInstantUploadPathOnPreferences() {
SharedPreferences appPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences.Editor editor = appPrefs.edit();
editor.putString("instant_upload_path", mUploadPath);
editor.commit();
}
}

View file

@ -1,3 +1,20 @@
/* ownCloud Android client application
* Copyright (C) 2012-2014 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* 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.adapter;
import java.io.BufferedInputStream;
@ -7,14 +24,10 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.util.Log;
import com.jakewharton.disklrucache.DiskLruCache;
import com.owncloud.android.BuildConfig;
@ -28,16 +41,14 @@ public class DiskLruImageCache {
private static final int CACHE_VERSION = 1;
private static final int VALUE_COUNT = 1;
private static final int IO_BUFFER_SIZE = 8 * 1024;
private static final Pattern CAPITAL_LETTERS = Pattern.compile("[A-Z]");
private StringBuffer mValidKeyBuffer = new StringBuffer(64);
private StringBuffer mConversionBuffer = new StringBuffer(2).append('_');
private static final String TAG = "DiskLruImageCache";
private static final String TAG = DiskLruImageCache.class.getSimpleName();
//public DiskLruImageCache( Context context,String uniqueName, int diskCacheSize,
public DiskLruImageCache(
File diskCacheDir, int diskCacheSize, CompressFormat compressFormat, int quality
) throws IOException {
public DiskLruImageCache( Context context,String uniqueName, int diskCacheSize,
CompressFormat compressFormat, int quality ) throws IOException {
final File diskCacheDir = getDiskCacheDir(context, uniqueName );
mDiskCache = DiskLruCache.open(
diskCacheDir, CACHE_VERSION, VALUE_COUNT, diskCacheSize
);
@ -58,17 +69,6 @@ public class DiskLruImageCache {
}
}
private File getDiskCacheDir(Context context, String uniqueName) {
// Check if media is mounted or storage is built-in, if so, try and use external cache dir
// otherwise use internal cache dir
final String cachePath = context.getExternalCacheDir().getPath();
Log_OC.d(TAG, "create dir: " + cachePath + File.separator + uniqueName);
return new File(cachePath + File.separator + uniqueName);
}
public void put( String key, Bitmap data ) {
DiskLruCache.Editor editor = null;
@ -83,17 +83,17 @@ public class DiskLruImageCache {
mDiskCache.flush();
editor.commit();
if ( BuildConfig.DEBUG ) {
Log.d( "cache_test_DISK_", "image put on disk cache " + validKey );
Log_OC.d( "cache_test_DISK_", "image put on disk cache " + validKey );
}
} else {
editor.abort();
if ( BuildConfig.DEBUG ) {
Log.d( "cache_test_DISK_", "ERROR on: image put on disk cache " + validKey );
Log_OC.d( "cache_test_DISK_", "ERROR on: image put on disk cache " + validKey );
}
}
} catch (IOException e) {
if ( BuildConfig.DEBUG ) {
Log.d( "cache_test_DISK_", "ERROR on: image put on disk cache " + validKey );
Log_OC.d( "cache_test_DISK_", "ERROR on: image put on disk cache " + validKey );
}
try {
if ( editor != null ) {
@ -131,7 +131,8 @@ public class DiskLruImageCache {
}
if ( BuildConfig.DEBUG ) {
Log.d("cache_test_DISK_", bitmap == null ? "not found" : "image read from disk " + validKey);
Log_OC.d("cache_test_DISK_", bitmap == null ?
"not found" : "image read from disk " + validKey);
}
return bitmap;
@ -160,7 +161,7 @@ public class DiskLruImageCache {
public void clearCache() {
if ( BuildConfig.DEBUG ) {
Log.d( "cache_test_DISK_", "disk cache CLEARED");
Log_OC.d( "cache_test_DISK_", "disk cache CLEARED");
}
try {
mDiskCache.delete();
@ -174,16 +175,20 @@ public class DiskLruImageCache {
}
private String convertToValidKey(String key) {
Matcher capitalLettersMatcher = CAPITAL_LETTERS.matcher(key);
mValidKeyBuffer.delete(0, mValidKeyBuffer.length());
mConversionBuffer.delete(1, mConversionBuffer.length());
while (capitalLettersMatcher.find()) {
mConversionBuffer.replace(1, 2, capitalLettersMatcher.group(0).toLowerCase());
capitalLettersMatcher.appendReplacement(mValidKeyBuffer, mConversionBuffer.toString());
}
capitalLettersMatcher.appendTail(mValidKeyBuffer);
return mValidKeyBuffer.toString();
return Integer.toString(key.hashCode());
}
/**
* Remove passed key from cache
* @param key
*/
public void removeKey( String key ) {
String validKey = convertToValidKey(key);
try {
mDiskCache.remove(validKey);
Log_OC.d(TAG, "removeKey from cache: " + validKey);
} catch (IOException e) {
e.printStackTrace();
}
}
}

View file

@ -17,8 +17,8 @@
*/
package com.owncloud.android.ui.adapter;
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.Comparator;
import java.util.Vector;
@ -26,16 +26,8 @@ import java.util.Vector;
import android.accounts.Account;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.ThumbnailUtils;
import android.os.AsyncTask;
import android.preference.PreferenceManager;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -50,11 +42,11 @@ import com.owncloud.android.authentication.AccountUtils;
import com.owncloud.android.datamodel.AlphanumComparator;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.datamodel.ThumbnailsCacheManager;
import com.owncloud.android.datamodel.ThumbnailsCacheManager.AsyncDrawable;
import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.ui.activity.ComponentsGetter;
import com.owncloud.android.utils.BitmapUtils;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.FileStorageUtils;
@ -71,8 +63,6 @@ import com.owncloud.android.utils.FileStorageUtils;
public class FileListListAdapter extends BaseAdapter implements ListAdapter {
private final static String PERMISSION_SHARED_WITH_ME = "S";
private static final String TAG = FileListListAdapter.class.getSimpleName();
private Context mContext;
private OCFile mFile = null;
private Vector<OCFile> mFiles = null;
@ -85,14 +75,6 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
private Boolean sortAscending;
private SharedPreferences appPreferences;
private final Object thumbnailDiskCacheLock = new Object();
private DiskLruImageCache mThumbnailCache;
private boolean mThumbnailCacheStarting = true;
private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB
private static final CompressFormat mCompressFormat = CompressFormat.JPEG;
private static final int mCompressQuality = 70;
private Bitmap defaultImg;
public FileListListAdapter(
boolean justFolders,
Context context,
@ -102,7 +84,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
mJustFolders = justFolders;
mContext = context;
mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);
mTransferServiceGetter = transferServiceGetter;
mTransferServiceGetter = transferServiceGetter;
appPreferences = PreferenceManager
.getDefaultSharedPreferences(mContext);
@ -110,145 +92,12 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
// Read sorting order, default to sort by name ascending
sortOrder = appPreferences
.getInt("sortOrder", 0);
sortAscending = appPreferences.getBoolean("sortAscending", true);
sortAscending = appPreferences.getBoolean("sortAscending", true);
defaultImg = BitmapFactory.decodeResource(mContext.getResources(),
DisplayUtils.getResourceId("image/png", "default.png"));
// Initialise disk cache on background thread
new InitDiskCacheTask().execute();
// initialise thumbnails cache on background thread
new ThumbnailsCacheManager.InitDiskCacheTask().execute();
}
class InitDiskCacheTask extends AsyncTask<File, Void, Void> {
@Override
protected Void doInBackground(File... params) {
synchronized (thumbnailDiskCacheLock) {
try {
mThumbnailCache = new DiskLruImageCache(mContext, "thumbnailCache",
DISK_CACHE_SIZE, mCompressFormat, mCompressQuality);
} catch (Exception e) {
Log_OC.d(TAG, "Thumbnail cache could not be opened ", e);
mThumbnailCache = null;
}
mThumbnailCacheStarting = false; // Finished initialization
thumbnailDiskCacheLock.notifyAll(); // Wake any waiting threads
}
return null;
}
}
static class AsyncDrawable extends BitmapDrawable {
private final WeakReference<ThumbnailGenerationTask> bitmapWorkerTaskReference;
public AsyncDrawable(Resources res, Bitmap bitmap,
ThumbnailGenerationTask bitmapWorkerTask) {
super(res, bitmap);
bitmapWorkerTaskReference =
new WeakReference<ThumbnailGenerationTask>(bitmapWorkerTask);
}
public ThumbnailGenerationTask getBitmapWorkerTask() {
return bitmapWorkerTaskReference.get();
}
}
class ThumbnailGenerationTask extends AsyncTask<OCFile, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private OCFile file;
public ThumbnailGenerationTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference<ImageView>(imageView);
}
// Decode image in background.
@Override
protected Bitmap doInBackground(OCFile... params) {
Bitmap thumbnail = null;
try {
file = params[0];
final String imageKey = String.valueOf(file.getRemoteId());
// Check disk cache in background thread
thumbnail = getBitmapFromDiskCache(imageKey);
// Not found in disk cache
if (thumbnail == null || file.needsUpdateThumbnail()) {
// Converts dp to pixel
Resources r = mContext.getResources();
int px = (int) Math.round(TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 150, r.getDisplayMetrics()
));
if (file.isDown()){
Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
file.getStoragePath(), px, px);
if (bitmap != null) {
thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
// Add thumbnail to cache
addBitmapToCache(imageKey, thumbnail);
file.setNeedsUpdateThumbnail(false);
mStorageManager.saveFile(file);
}
}
}
} catch (Throwable t) {
// the app should never break due to a problem with thumbnails
Log_OC.e(TAG, "Generation of thumbnail for " + file + " failed", t);
if (t instanceof OutOfMemoryError) {
System.gc();
}
}
return thumbnail;
}
protected void onPostExecute(Bitmap bitmap){
if (isCancelled()) {
bitmap = null;
}
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get();
final ThumbnailGenerationTask bitmapWorkerTask =
getBitmapWorkerTask(imageView);
if (this == bitmapWorkerTask && imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}
public void addBitmapToCache(String key, Bitmap bitmap) {
synchronized (thumbnailDiskCacheLock) {
if (mThumbnailCache != null) {
mThumbnailCache.put(key, bitmap);
}
}
}
public Bitmap getBitmapFromDiskCache(String key) {
synchronized (thumbnailDiskCacheLock) {
// Wait while disk cache is started from background thread
while (mThumbnailCacheStarting) {
try {
thumbnailDiskCacheLock.wait();
} catch (InterruptedException e) {}
}
if (mThumbnailCache != null) {
return (Bitmap) mThumbnailCache.getBitmap(key);
}
}
return null;
}
@Override
public boolean areAllItemsEnabled() {
return true;
@ -299,6 +148,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
fileName.setText(name);
ImageView fileIcon = (ImageView) view.findViewById(R.id.imageView1);
fileIcon.setTag(file.getFileId());
ImageView sharedIconV = (ImageView) view.findViewById(R.id.sharedIcon);
ImageView sharedWithMeIconV = (ImageView) view.findViewById(R.id.sharedWithMeIcon);
sharedWithMeIconV.setVisibility(View.GONE);
@ -353,18 +203,28 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
}
// get Thumbnail if file is image
if (file.isImage()){
if (file.isImage() && file.getRemoteId() != null){
// Thumbnail in Cache?
Bitmap thumbnail = getBitmapFromDiskCache(String.valueOf(file.getRemoteId()));
Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
String.valueOf(file.getRemoteId())
);
if (thumbnail != null && !file.needsUpdateThumbnail()){
fileIcon.setImageBitmap(thumbnail);
} else {
// generate new Thumbnail
if (cancelPotentialWork(file, fileIcon)) {
final ThumbnailGenerationTask task =
new ThumbnailGenerationTask(fileIcon);
final AsyncDrawable asyncDrawable =
new AsyncDrawable(mContext.getResources(), defaultImg, task);
if (ThumbnailsCacheManager.cancelPotentialWork(file, fileIcon)) {
final ThumbnailsCacheManager.ThumbnailGenerationTask task =
new ThumbnailsCacheManager.ThumbnailGenerationTask(
fileIcon, mStorageManager
);
if (thumbnail == null) {
thumbnail = ThumbnailsCacheManager.mDefaultImg;
}
final AsyncDrawable asyncDrawable = new AsyncDrawable(
mContext.getResources(),
thumbnail,
task
);
fileIcon.setImageDrawable(asyncDrawable);
task.execute(file);
}
@ -420,35 +280,6 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
return view;
}
public static boolean cancelPotentialWork(OCFile file, ImageView imageView) {
final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
if (bitmapWorkerTask != null) {
final OCFile bitmapData = bitmapWorkerTask.file;
// If bitmapData is not yet set or it differs from the new data
if (bitmapData == null || bitmapData != file) {
// Cancel previous task
bitmapWorkerTask.cancel(true);
} else {
// The same work is already in progress
return false;
}
}
// No task associated with the ImageView, or an existing task was cancelled
return true;
}
private static ThumbnailGenerationTask getBitmapWorkerTask(ImageView imageView) {
if (imageView != null) {
final Drawable drawable = imageView.getDrawable();
if (drawable instanceof AsyncDrawable) {
final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
return asyncDrawable.getBitmapWorkerTask();
}
}
return null;
}
/**
* Local Folder size in human readable format
* @param path String
@ -490,7 +321,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
}
return 0;
}
@Override
public int getViewTypeCount() {
return 1;

View file

@ -32,6 +32,7 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
@ -126,6 +127,13 @@ public class FileDownloadFragment extends FileFragment implements OnClickListene
((ImageButton)mView.findViewById(R.id.cancelBtn)).setOnClickListener(this);
((LinearLayout)mView.findViewById(R.id.fileDownloadLL)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
((PreviewImageActivity) getActivity()).toggleFullScreen();
}
});
if (mError) {
setButtonsForRemote();
} else {

View file

@ -0,0 +1,70 @@
package com.owncloud.android.ui.preview;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import com.owncloud.android.lib.common.utils.Log_OC;
public class ImageViewCustom extends ImageView {
private static final boolean IS_ICS_OR_HIGHER = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;
private Bitmap mBitmap;
public ImageViewCustom(Context context) {
super(context);
}
public ImageViewCustom(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ImageViewCustom(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@SuppressLint("NewApi")
@Override
protected void onDraw(Canvas canvas) {
if(IS_ICS_OR_HIGHER && checkIfMaximumBitmapExceed(canvas)) {
// Set layer type to software one for avoiding exceed
// and problems in visualization
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
super.onDraw(canvas);
}
/**
* Checks if current bitmaps exceed the maximum OpenGL texture size limit
* @param bitmap
* @return boolean
*/
@SuppressLint("NewApi")
private boolean checkIfMaximumBitmapExceed(Canvas canvas) {
Log_OC.d("OC", "Canvas maximum: " + canvas.getMaximumBitmapWidth() + " - " + canvas.getMaximumBitmapHeight());
if (mBitmap!= null && (mBitmap.getWidth() > canvas.getMaximumBitmapWidth()
|| mBitmap.getHeight() > canvas.getMaximumBitmapHeight())) {
return true;
}
return false;
}
/**
* Set current bitmap
* @param bitmap
*/
public void setBitmap (Bitmap bitmap) {
mBitmap = bitmap;
}
}

View file

@ -16,6 +16,12 @@
*/
package com.owncloud.android.ui.preview;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import android.accounts.Account;
@ -40,7 +46,6 @@ import android.widget.TextView;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.ortiz.touch.TouchImageView;
import com.owncloud.android.R;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.FileMenuFilter;
@ -48,6 +53,8 @@ import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
import com.owncloud.android.ui.dialog.RemoveFileDialogFragment;
import com.owncloud.android.ui.fragment.FileFragment;
import com.owncloud.android.utils.TouchImageViewCustom;
/**
@ -60,12 +67,13 @@ import com.owncloud.android.ui.fragment.FileFragment;
* @author David A. Velasco
*/
public class PreviewImageFragment extends FileFragment {
public static final String EXTRA_FILE = "FILE";
public static final String EXTRA_ACCOUNT = "ACCOUNT";
private View mView;
private Account mAccount;
private TouchImageView mImageView;
private TouchImageViewCustom mImageView;
private TextView mMessageView;
private ProgressBar mProgressWheel;
@ -124,7 +132,7 @@ public class PreviewImageFragment extends FileFragment {
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
mView = inflater.inflate(R.layout.preview_image_fragment, container, false);
mImageView = (TouchImageView) mView.findViewById(R.id.image);
mImageView = (TouchImageViewCustom) mView.findViewById(R.id.image);
mImageView.setVisibility(View.GONE);
mImageView.setOnClickListener(new OnClickListener() {
@Override
@ -306,6 +314,7 @@ public class PreviewImageFragment extends FileFragment {
public void onDestroy() {
if (mBitmap != null) {
mBitmap.recycle();
System.gc();
}
super.onDestroy();
}
@ -327,7 +336,7 @@ public class PreviewImageFragment extends FileFragment {
*
* 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;
private final WeakReference<ImageViewCustom> mImageViewRef;
/**
* Weak reference to the target {@link TextView} where error messages will be written.
@ -356,65 +365,27 @@ public class PreviewImageFragment extends FileFragment {
*
* @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);
public BitmapLoader(ImageViewCustom imageView, TextView messageView, ProgressBar progressWheel) {
mImageViewRef = new WeakReference<ImageViewCustom>(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
@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;
File picture = new File(storagePath);
// really load the bitmap
options.inJustDecodeBounds = false; // the next decodeFile call will be real
result = BitmapFactory.decodeFile(storagePath, options);
//Log_OC.d(TAG, "Image loaded - width: " + options.outWidth + ", loaded height: " + options.outHeight);
if (picture != null) {
//Decode file into a bitmap in real size for being able to make zoom on the image
result = BitmapFactory.decodeStream(new FlushedInputStream
(new BufferedInputStream(new FileInputStream(picture))));
}
if (result == null) {
mErrorMessageId = R.string.preview_image_error_unknown_format;
@ -422,8 +393,15 @@ public class PreviewImageFragment extends FileFragment {
}
} catch (OutOfMemoryError e) {
mErrorMessageId = R.string.preview_image_error_unknown_format;
Log_OC.e(TAG, "Out of memory occured for file " + storagePath, e);
// If out of memory error when loading image, try to load it scaled
result = loadScaledImage(storagePath);
if (result == null) {
mErrorMessageId = R.string.preview_image_error_unknown_format;
Log_OC.e(TAG, "File could not be loaded as a bitmap: " + storagePath);
}
} catch (NoSuchFieldError e) {
mErrorMessageId = R.string.common_error_unknown;
@ -446,11 +424,13 @@ public class PreviewImageFragment extends FileFragment {
showErrorMessage();
}
}
@SuppressLint("InlinedApi")
private void showLoadedImage(Bitmap result) {
if (mImageViewRef != null) {
final ImageView imageView = mImageViewRef.get();
final ImageViewCustom imageView = mImageViewRef.get();
if (imageView != null) {
imageView.setBitmap(result);
imageView.setImageBitmap(result);
imageView.setVisibility(View.VISIBLE);
mBitmap = result;
@ -511,8 +491,87 @@ public class PreviewImageFragment extends FileFragment {
container.finish();
}
public TouchImageView getImageView() {
public TouchImageViewCustom getImageView() {
return mImageView;
}
static class FlushedInputStream extends FilterInputStream {
public FlushedInputStream(InputStream inputStream) {
super(inputStream);
}
@Override
public long skip(long n) throws IOException {
long totalBytesSkipped = 0L;
while (totalBytesSkipped < n) {
long bytesSkipped = in.skip(n - totalBytesSkipped);
if (bytesSkipped == 0L) {
int byteValue = read();
if (byteValue < 0) {
break; // we reached EOF
} else {
bytesSkipped = 1; // we read one byte
}
}
totalBytesSkipped += bytesSkipped;
}
return totalBytesSkipped;
}
}
/**
* Load image scaled
* @param storagePath: path of the image
* @return Bitmap
*/
@SuppressWarnings("deprecation")
private Bitmap loadScaledImage(String storagePath) {
Log_OC.d(TAG, "Loading image scaled");
// 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
return BitmapFactory.decodeFile(storagePath, options);
}
}

View file

@ -29,6 +29,7 @@ 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.IBinder;
@ -372,13 +373,15 @@ public class PreviewMediaFragment extends FileFragment implements
mVideoPreview.setOnErrorListener(mVideoHelper);
}
@SuppressWarnings("static-access")
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(getFile().getStoragePath());
Uri uri = Uri.parse(getFile().getStoragePath());
mVideoPreview.setVideoPath(uri.encode(getFile().getStoragePath()));
}

View file

@ -26,6 +26,8 @@ import com.owncloud.android.lib.resources.files.RemoteFile;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.net.Uri;
import android.os.Environment;
import android.os.StatFs;
@ -73,7 +75,9 @@ public class FileStorageUtils {
}
public static String getInstantUploadFilePath(Context context, String fileName) {
String uploadPath = context.getString(R.string.instant_upload_path);
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
String uploadPathdef = context.getString(R.string.instant_upload_path);
String uploadPath = pref.getString("instant_upload_path", uploadPathdef);
String value = uploadPath + OCFile.PATH_SEPARATOR + (fileName == null ? "" : fileName);
return value;
}
@ -120,4 +124,4 @@ public class FileStorageUtils {
return file;
}
}
}

File diff suppressed because it is too large Load diff