From: David A. Velasco Date: Thu, 16 Jan 2014 16:55:28 +0000 (-0800) Subject: Merge pull request #330 from LukeOwncloud/update_jackrabbit X-Git-Tag: oc-android-1.5.5~78 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/95afa6c8bff4b1d87a17e228339f71b4a7a9e1f8?hp=f050eda3394820e2bb7f56fb4e955621fdc04171 Merge pull request #330 from LukeOwncloud/update_jackrabbit Update jackrabbit library, with dependencies now in separate files. --- diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 205e5acb..80fc7e3c 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -18,8 +18,8 @@ along with this program. If not, see . --> + android:versionCode="105002" + android:versionName="1.5.2" xmlns:android="http://schemas.android.com/apk/res/android"> diff --git a/oc_framework-test-project/AndroidManifest.xml b/oc_framework-test-project/AndroidManifest.xml index c913bf06..3c98ffe1 100644 --- a/oc_framework-test-project/AndroidManifest.xml +++ b/oc_framework-test-project/AndroidManifest.xml @@ -9,9 +9,11 @@ - - - + + + + diff --git a/oc_framework-test-project/assets/fileToUpload.png b/oc_framework-test-project/assets/fileToUpload.png new file mode 100644 index 00000000..915ec22c Binary files /dev/null and b/oc_framework-test-project/assets/fileToUpload.png differ diff --git a/oc_framework-test-project/assets/fileToUploadChunks.MP4 b/oc_framework-test-project/assets/fileToUploadChunks.MP4 new file mode 100644 index 00000000..2422025e Binary files /dev/null and b/oc_framework-test-project/assets/fileToUploadChunks.MP4 differ diff --git a/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/CreateFolderTest.java b/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/CreateFolderTest.java index 84145022..0c099b15 100644 --- a/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/CreateFolderTest.java +++ b/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/CreateFolderTest.java @@ -1,3 +1,20 @@ +/* ownCloud Android client application + * Copyright (C) 2012-2013 ownCloud Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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 . + * + */ + package com.owncloud.android.oc_framework_test_project.test; import java.text.SimpleDateFormat; diff --git a/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/DeleteFileTest.java b/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/DeleteFileTest.java index b8ab2b0c..2086257d 100644 --- a/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/DeleteFileTest.java +++ b/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/DeleteFileTest.java @@ -1,3 +1,20 @@ +/* ownCloud Android client application + * Copyright (C) 2012-2013 ownCloud Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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 . + * + */ + package com.owncloud.android.oc_framework_test_project.test; import com.owncloud.android.oc_framework.operations.RemoteOperationResult; @@ -6,6 +23,12 @@ import com.owncloud.android.oc_framework_test_project.TestActivity; import android.test.ActivityInstrumentationTestCase2; +/** + * Class to test Delete a File Operation + * @author masensio + * + */ + public class DeleteFileTest extends ActivityInstrumentationTestCase2 { /* Folder data to delete. */ diff --git a/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/DownloadFileTest.java b/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/DownloadFileTest.java new file mode 100644 index 00000000..040deecd --- /dev/null +++ b/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/DownloadFileTest.java @@ -0,0 +1,123 @@ +/* ownCloud Android client application + * Copyright (C) 2012-2013 ownCloud Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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 . + * + */ + +package com.owncloud.android.oc_framework_test_project.test; + +import java.text.SimpleDateFormat; +import java.util.Date; + +import com.owncloud.android.oc_framework.operations.RemoteFile; +import com.owncloud.android.oc_framework.operations.RemoteOperationResult; +import com.owncloud.android.oc_framework_test_project.TestActivity; + +import android.test.ActivityInstrumentationTestCase2; + +/** + * Class to test Download File Operation + * @author masensio + * + */ + +public class DownloadFileTest extends ActivityInstrumentationTestCase2 { + + + /* Files to download. These files must exist on the account */ + private final String mRemoteFilePng = "/fileToDownload.png"; + private final String mRemoteFileChunks = "/fileToDownload.mp4"; + private final String mRemoteFileSpecialChars = "/@file@download.png"; + private final String mRemoteFileSpecialCharsChunks = "/@file@download.mp4"; + private final String mRemoteFileNotFound = "/fileNotFound.png"; /* This file mustn't exist on the account */ + + private String mCurrentDate; + + + private TestActivity mActivity; + + public DownloadFileTest() { + super(TestActivity.class); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss"); + mCurrentDate = sdf.format(new Date()); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + setActivityInitialTouchMode(false); + mActivity = getActivity(); + } + + /** + * Test Download a File + */ + public void testDownloadFile() { + String temporalFolder = "/download" + mCurrentDate; + + RemoteFile remoteFile= new RemoteFile(mRemoteFilePng); + + RemoteOperationResult result = mActivity.downloadFile(remoteFile, temporalFolder); + assertTrue(result.isSuccess()); + } + + /** + * Test Download a File with chunks + */ + public void testDownloadFileChunks() { + String temporalFolder = "/download" + mCurrentDate; + + RemoteFile remoteFile= new RemoteFile(mRemoteFileChunks); + + RemoteOperationResult result = mActivity.downloadFile(remoteFile, temporalFolder); + assertTrue(result.isSuccess()); + } + + /** + * Test Download a File with special chars + */ + public void testDownloadFileSpecialChars() { + String temporalFolder = "/download" + mCurrentDate; + + RemoteFile remoteFile= new RemoteFile(mRemoteFileSpecialChars); + + RemoteOperationResult result = mActivity.downloadFile(remoteFile, temporalFolder); + assertTrue(result.isSuccess()); + } + + /** + * Test Download a File with special chars and chunks + */ + public void testDownloadFileSpecialCharsChunks() { + String temporalFolder = "/download" + mCurrentDate; + + RemoteFile remoteFile= new RemoteFile(mRemoteFileSpecialCharsChunks); + + RemoteOperationResult result = mActivity.downloadFile(remoteFile, temporalFolder); + assertTrue(result.isSuccess()); + } + + /** + * Test Download a Not Found File + */ + public void testDownloadFileNotFound() { + String temporalFolder = "/download" + mCurrentDate; + + RemoteFile remoteFile = new RemoteFile(mRemoteFileNotFound); + + RemoteOperationResult result = mActivity.downloadFile(remoteFile, temporalFolder); + assertFalse(result.isSuccess()); + } +} diff --git a/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/ReadFileTest.java b/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/ReadFileTest.java new file mode 100644 index 00000000..b75732b1 --- /dev/null +++ b/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/ReadFileTest.java @@ -0,0 +1,61 @@ +/* ownCloud Android client application + * Copyright (C) 2012-2013 ownCloud Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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 . + * + */ + +package com.owncloud.android.oc_framework_test_project.test; + +import com.owncloud.android.oc_framework.operations.RemoteOperationResult; +import com.owncloud.android.oc_framework_test_project.TestActivity; + +import android.test.ActivityInstrumentationTestCase2; + +/** + * Class to test Read File Operation + * @author masensio + * + */ + +public class ReadFileTest extends ActivityInstrumentationTestCase2 { + + /* File data to read. This file must exist on the account */ + private final String mRemoteFolderPath = "/fileToRead.txt"; + + + private TestActivity mActivity; + + public ReadFileTest() { + super(TestActivity.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + setActivityInitialTouchMode(false); + mActivity = getActivity(); + } + + /** + * Test Read File + */ + public void testReadFile() { + + RemoteOperationResult result = mActivity.readFile(mRemoteFolderPath); + assertTrue(result.getData().size() == 1); + assertTrue(result.isSuccess()); + } + + +} diff --git a/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/ReadFolderTest.java b/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/ReadFolderTest.java index c3399158..ed9ccef6 100644 --- a/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/ReadFolderTest.java +++ b/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/ReadFolderTest.java @@ -1,5 +1,21 @@ -package com.owncloud.android.oc_framework_test_project.test; +/* ownCloud Android client application + * Copyright (C) 2012-2013 ownCloud Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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 . + * + */ +package com.owncloud.android.oc_framework_test_project.test; import com.owncloud.android.oc_framework.operations.RemoteOperationResult; import com.owncloud.android.oc_framework_test_project.TestActivity; diff --git a/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/RenameFileTest.java b/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/RenameFileTest.java index e21c6ff8..7de35535 100644 --- a/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/RenameFileTest.java +++ b/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/RenameFileTest.java @@ -1,3 +1,20 @@ +/* ownCloud Android client application + * Copyright (C) 2012-2013 ownCloud Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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 . + * + */ + package com.owncloud.android.oc_framework_test_project.test; import com.owncloud.android.oc_framework.operations.RemoteOperationResult; diff --git a/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/UploadFileTest.java b/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/UploadFileTest.java new file mode 100644 index 00000000..67103718 --- /dev/null +++ b/oc_framework-test-project/oc_framework-test-test/src/com/owncloud/android/oc_framework_test_project/test/UploadFileTest.java @@ -0,0 +1,161 @@ +/* ownCloud Android client application + * Copyright (C) 2012-2013 ownCloud Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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 . + * + */ + +package com.owncloud.android.oc_framework_test_project.test; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.SimpleDateFormat; +import java.util.Date; + +import android.content.res.AssetManager; +import android.os.Environment; +import android.test.ActivityInstrumentationTestCase2; +import android.util.Log; + +import com.owncloud.android.oc_framework.operations.RemoteOperationResult; +import com.owncloud.android.oc_framework_test_project.TestActivity; + +/** + * Class to test Update File Operation + * @author masensio + * + */ + +public class UploadFileTest extends ActivityInstrumentationTestCase2 { + + /* Files to upload. These files must exists on the device */ + private final String mFileToUpload = "fileToUpload.png"; + private final String mMimeType = "image/png"; + + private final String mFileToUploadWithChunks = "fileToUploadChunks.MP4"; + private final String mMimeTypeWithChunks = "video/mp4"; + + private final String mFileNotFound = "fileNotFound.png"; + + private final String mStoragePath = "/owncloud/tmp/uploadTest"; + private String mPath; + + private String mCurrentDate; + + private TestActivity mActivity; + + public UploadFileTest() { + super(TestActivity.class); + + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + setActivityInitialTouchMode(false); + mActivity = getActivity(); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss"); + mCurrentDate = sdf.format(new Date()); + + File sdCard = Environment.getExternalStorageDirectory(); + mPath = sdCard.getAbsolutePath() + "/" + mStoragePath + mCurrentDate; + + //mActivity.createFolder(mPath, true); + + copyAssets(); + } + + /** + * Copy Files to ulpload to SdCard + */ + private void copyAssets() { + AssetManager assetManager = getActivity().getAssets(); + String[] files = { mFileToUpload, mFileToUploadWithChunks }; + + // Folder with contents + File folder = new File(mPath); + folder.mkdirs(); + + + for(String filename : files) { + InputStream in = null; + OutputStream out = null; + try { + in = assetManager.open(filename); + File outFile = new File(folder, filename); + out = new FileOutputStream(outFile); + copyFile(in, out); + in.close(); + in = null; + out.flush(); + out.close(); + out = null; + } catch(IOException e) { + Log.e("tag", "Failed to copy asset file: " + filename, e); + } + } + } + + private void copyFile(InputStream in, OutputStream out) throws IOException { + byte[] buffer = new byte[1024]; + int read; + while((read = in.read(buffer)) != -1){ + out.write(buffer, 0, read); + } + } + + + /** + * Test Upload File without chunks + */ + public void testUploadFile() { + + String storagePath = mPath + "/" + mFileToUpload; + //String remotePath = "/uploadTest" + mCurrentDate + "/" + mFileToUpload; + String remotePath = "/" + mFileToUpload; + + RemoteOperationResult result = mActivity.uploadFile(storagePath, remotePath, mMimeType); + assertTrue(result.isSuccess()); + } + + /** + * Test Upload File with chunks + */ + public void testUploadFileWithChunks() { + + String storagePath = mPath + "/" + mFileToUploadWithChunks; + //String remotePath = "/uploadTest" + mCurrentDate + "/" +mFileToUploadWithChunks; + String remotePath = "/" + mFileToUploadWithChunks; + + RemoteOperationResult result = mActivity.uploadFile(storagePath, remotePath, mMimeTypeWithChunks); + assertTrue(result.isSuccess()); + } + + /** + * Test Upload Not Found File + */ + public void testUploadFileNotFound() { + + String storagePath = mPath + "/" + mFileNotFound; + //String remotePath = "/uploadTest" + mCurrentDate + "/" + mFileToUpload; + String remotePath = "/" + mFileNotFound; + + RemoteOperationResult result = mActivity.uploadFile(storagePath, remotePath, mMimeType); + assertFalse(result.isSuccess()); + } + +} diff --git a/oc_framework-test-project/src/com/owncloud/android/oc_framework_test_project/TestActivity.java b/oc_framework-test-project/src/com/owncloud/android/oc_framework_test_project/TestActivity.java index db38ea5c..2030a8f2 100644 --- a/oc_framework-test-project/src/com/owncloud/android/oc_framework_test_project/TestActivity.java +++ b/oc_framework-test-project/src/com/owncloud/android/oc_framework_test_project/TestActivity.java @@ -1,15 +1,39 @@ +/* ownCloud Android client application + * Copyright (C) 2012-2013 ownCloud Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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 . + * + */ + package com.owncloud.android.oc_framework_test_project; +import java.io.File; + import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory; import com.owncloud.android.oc_framework.network.webdav.WebdavClient; +import com.owncloud.android.oc_framework.operations.RemoteFile; import com.owncloud.android.oc_framework.operations.RemoteOperationResult; +import com.owncloud.android.oc_framework.operations.remote.ChunkedUploadRemoteFileOperation; import com.owncloud.android.oc_framework.operations.remote.CreateRemoteFolderOperation; +import com.owncloud.android.oc_framework.operations.remote.DownloadRemoteFileOperation; import com.owncloud.android.oc_framework.operations.remote.ReadRemoteFolderOperation; import com.owncloud.android.oc_framework.operations.remote.RemoveRemoteFileOperation; import com.owncloud.android.oc_framework.operations.remote.RenameRemoteFileOperation; +import com.owncloud.android.oc_framework.operations.remote.UploadRemoteFileOperation; import android.net.Uri; import android.os.Bundle; +import android.os.Environment; import android.app.Activity; import android.view.Menu; @@ -18,12 +42,14 @@ import android.view.Menu; * @author masensio * @author David A. Velasco */ + public class TestActivity extends Activity { // This account must exists on the simulator / device private static final String mServerUri = "https://beta.owncloud.com/owncloud/remote.php/webdav"; private static final String mUser = "testandroid"; private static final String mPass = "testandroid"; + private static final boolean mChunked = true; //private Account mAccount = null; private WebdavClient mClient; @@ -105,4 +131,43 @@ public class TestActivity extends Activity { return result; } + /** + * Access to the library method to Download a File + * @param remotePath + * + * @return + */ + public RemoteOperationResult downloadFile(RemoteFile remoteFile, String temporalFolder) { + // Create folder + String path = "/owncloud/tmp/" + temporalFolder; + File sdCard = Environment.getExternalStorageDirectory(); + File folder = new File(sdCard.getAbsolutePath() + "/" + path); + folder.mkdirs(); + + DownloadRemoteFileOperation downloadOperation = new DownloadRemoteFileOperation(remoteFile, folder.getAbsolutePath()); + RemoteOperationResult result = downloadOperation.execute(mClient); + + return result; + } + + /** Access to the library method to Upload a File + * @param storagePath + * @param remotePath + * @param mimeType + * + * @return + */ + public RemoteOperationResult uploadFile(String storagePath, String remotePath, String mimeType) { + + UploadRemoteFileOperation uploadOperation; + if ( mChunked && (new File(storagePath)).length() > ChunkedUploadRemoteFileOperation.CHUNK_SIZE ) { + uploadOperation = new ChunkedUploadRemoteFileOperation(storagePath, remotePath, mimeType); + } else { + uploadOperation = new UploadRemoteFileOperation(storagePath, remotePath, mimeType); + } + + RemoteOperationResult result = uploadOperation.execute(mClient); + + return result; + } } diff --git a/oc_framework/src/com/owncloud/android/oc_framework/operations/RemoteFile.java b/oc_framework/src/com/owncloud/android/oc_framework/operations/RemoteFile.java index 07f45b7b..922b270a 100644 --- a/oc_framework/src/com/owncloud/android/oc_framework/operations/RemoteFile.java +++ b/oc_framework/src/com/owncloud/android/oc_framework/operations/RemoteFile.java @@ -22,6 +22,7 @@ import java.io.Serializable; import android.os.Parcel; import android.os.Parcelable; +import com.owncloud.android.oc_framework.network.webdav.WebdavEntry; import com.owncloud.android.oc_framework.utils.FileUtils; /** @@ -33,7 +34,7 @@ import com.owncloud.android.oc_framework.utils.FileUtils; public class RemoteFile implements Parcelable, Serializable { /** Generated - should be refreshed every time the class changes!! */ - private static final long serialVersionUID = 7256606476031992757L; + private static final long serialVersionUID = 532139091191390616L; private String mRemotePath; private String mMimeType; @@ -108,6 +109,15 @@ public class RemoteFile implements Parcelable, Serializable { } mRemotePath = path; } + + public RemoteFile(WebdavEntry we) { + this(we.decodedPath()); + this.setCreationTimestamp(we.createTimestamp()); + this.setLength(we.contentLength()); + this.setMimeType(we.contentType()); + this.setModifiedTimestamp(we.modifiedTimestamp()); + this.setEtag(we.etag()); + } /** * Used internally. Reset all file properties diff --git a/oc_framework/src/com/owncloud/android/oc_framework/operations/RemoteOperationResult.java b/oc_framework/src/com/owncloud/android/oc_framework/operations/RemoteOperationResult.java index 666e3129..58accf9f 100644 --- a/oc_framework/src/com/owncloud/android/oc_framework/operations/RemoteOperationResult.java +++ b/oc_framework/src/com/owncloud/android/oc_framework/operations/RemoteOperationResult.java @@ -99,7 +99,7 @@ public class RemoteOperationResult implements Serializable { private String mRedirectedLocation; private ArrayList mFiles; - + public RemoteOperationResult(ResultCode code) { mCode = code; mSuccess = (code == ResultCode.OK || code == ResultCode.OK_SSL || code == ResultCode.OK_NO_SSL); @@ -320,7 +320,7 @@ public class RemoteOperationResult implements Serializable { } else if (mCode == ResultCode.ACCOUNT_NOT_THE_SAME) { return "Authenticated with a different account than the one updating"; } else if (mCode == ResultCode.INVALID_CHARACTER_IN_NAME) { - return "The file name contains an forbidden character"; + return "The file name contains an forbidden character"; } return "Operation finished with HTTP status code " + mHttpCode + " (" + (isSuccess() ? "success" : "fail") + ")"; diff --git a/oc_framework/src/com/owncloud/android/oc_framework/operations/remote/ChunkedUploadRemoteFileOperation.java b/oc_framework/src/com/owncloud/android/oc_framework/operations/remote/ChunkedUploadRemoteFileOperation.java new file mode 100644 index 00000000..4df5fea6 --- /dev/null +++ b/oc_framework/src/com/owncloud/android/oc_framework/operations/remote/ChunkedUploadRemoteFileOperation.java @@ -0,0 +1,94 @@ +/* ownCloud Android client application + * Copyright (C) 2012 Bartek Przybylski + * Copyright (C) 2012-2013 ownCloud Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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 . + * + */ + +package com.owncloud.android.oc_framework.operations.remote; + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.channels.FileChannel; +import java.util.Random; + +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.methods.PutMethod; + +import com.owncloud.android.oc_framework.network.ProgressiveDataTransferer; +import com.owncloud.android.oc_framework.network.webdav.ChunkFromFileChannelRequestEntity; +import com.owncloud.android.oc_framework.network.webdav.WebdavClient; +import com.owncloud.android.oc_framework.network.webdav.WebdavUtils; + + +import android.util.Log; + + +public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation { + + public static final long CHUNK_SIZE = 1024000; + private static final String OC_CHUNKED_HEADER = "OC-Chunked"; + private static final String TAG = ChunkedUploadRemoteFileOperation.class.getSimpleName(); + + public ChunkedUploadRemoteFileOperation(String storagePath, String remotePath, String mimeType) { + super(storagePath, remotePath, mimeType); + } + + @Override + protected int uploadFile(WebdavClient client) throws HttpException, IOException { + int status = -1; + + FileChannel channel = null; + RandomAccessFile raf = null; + try { + File file = new File(mStoragePath); + raf = new RandomAccessFile(file, "r"); + channel = raf.getChannel(); + mEntity = new ChunkFromFileChannelRequestEntity(channel, mMimeType, CHUNK_SIZE, file); + //((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(getDataTransferListeners()); + synchronized (mDataTransferListeners) { + ((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(mDataTransferListeners); + } + + long offset = 0; + String uriPrefix = client.getBaseUri() + WebdavUtils.encodePath(mRemotePath) + "-chunking-" + Math.abs((new Random()).nextInt(9000)+1000) + "-" ; + long chunkCount = (long) Math.ceil((double)file.length() / CHUNK_SIZE); + for (int chunkIndex = 0; chunkIndex < chunkCount ; chunkIndex++, offset += CHUNK_SIZE) { + if (mPutMethod != null) { + mPutMethod.releaseConnection(); // let the connection available for other methods + } + mPutMethod = new PutMethod(uriPrefix + chunkCount + "-" + chunkIndex); + mPutMethod.addRequestHeader(OC_CHUNKED_HEADER, OC_CHUNKED_HEADER); + ((ChunkFromFileChannelRequestEntity)mEntity).setOffset(offset); + mPutMethod.setRequestEntity(mEntity); + status = client.executeMethod(mPutMethod); + client.exhaustResponse(mPutMethod.getResponseBodyAsStream()); + Log.d(TAG, "Upload of " + mStoragePath + " to " + mRemotePath + ", chunk index " + chunkIndex + ", count " + chunkCount + ", HTTP result status " + status); + if (!isSuccess(status)) + break; + } + + } finally { + if (channel != null) + channel.close(); + if (raf != null) + raf.close(); + if (mPutMethod != null) + mPutMethod.releaseConnection(); // let the connection available for other methods + } + return status; + } + +} diff --git a/oc_framework/src/com/owncloud/android/oc_framework/operations/remote/DownloadRemoteFileOperation.java b/oc_framework/src/com/owncloud/android/oc_framework/operations/remote/DownloadRemoteFileOperation.java new file mode 100644 index 00000000..e3e7ee07 --- /dev/null +++ b/oc_framework/src/com/owncloud/android/oc_framework/operations/remote/DownloadRemoteFileOperation.java @@ -0,0 +1,169 @@ +/* ownCloud Android client application + * Copyright (C) 2012-2013 ownCloud Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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 . + * + */ + +package com.owncloud.android.oc_framework.operations.remote; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Date; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.http.HttpStatus; + +import android.util.Log; + +import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener; +import com.owncloud.android.oc_framework.network.webdav.WebdavClient; +import com.owncloud.android.oc_framework.network.webdav.WebdavUtils; +import com.owncloud.android.oc_framework.operations.OperationCancelledException; +import com.owncloud.android.oc_framework.operations.RemoteFile; +import com.owncloud.android.oc_framework.operations.RemoteOperation; +import com.owncloud.android.oc_framework.operations.RemoteOperationResult; + +/** + * Remote operation performing the download of a remote file in the ownCloud server. + * + * @author David A. Velasco + * @author masensio + */ + +public class DownloadRemoteFileOperation extends RemoteOperation { + + private static final String TAG = DownloadRemoteFileOperation.class.getSimpleName(); + + private Set mDataTransferListeners = new HashSet(); + private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false); + private long mModificationTimestamp = 0; + private GetMethod mGet; + + private RemoteFile mRemoteFile; + private String mTemporalFolder; + + public DownloadRemoteFileOperation(RemoteFile remoteFile, String temporalFolder) { + mRemoteFile = remoteFile; + mTemporalFolder = temporalFolder; + } + + @Override + protected RemoteOperationResult run(WebdavClient client) { + RemoteOperationResult result = null; + + /// download will be performed to a temporal file, then moved to the final location + File tmpFile = new File(getTmpPath()); + + /// perform the download + try { + tmpFile.getParentFile().mkdirs(); + int status = downloadFile(client, tmpFile); + result = new RemoteOperationResult(isSuccess(status), status, (mGet != null ? mGet.getResponseHeaders() : null)); + Log.i(TAG, "Download of " + mRemoteFile.getRemotePath() + " to " + getTmpPath() + ": " + result.getLogMessage()); + + } catch (Exception e) { + result = new RemoteOperationResult(e); + Log.e(TAG, "Download of " + mRemoteFile.getRemotePath() + " to " + getTmpPath() + ": " + result.getLogMessage(), e); + } + + return result; + } + + + protected int downloadFile(WebdavClient client, File targetFile) throws HttpException, IOException, OperationCancelledException { + int status = -1; + boolean savedFile = false; + mGet = new GetMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemoteFile.getRemotePath())); + Iterator it = null; + + FileOutputStream fos = null; + try { + status = client.executeMethod(mGet); + if (isSuccess(status)) { + targetFile.createNewFile(); + BufferedInputStream bis = new BufferedInputStream(mGet.getResponseBodyAsStream()); + fos = new FileOutputStream(targetFile); + long transferred = 0; + + byte[] bytes = new byte[4096]; + int readResult = 0; + while ((readResult = bis.read(bytes)) != -1) { + synchronized(mCancellationRequested) { + if (mCancellationRequested.get()) { + mGet.abort(); + throw new OperationCancelledException(); + } + } + fos.write(bytes, 0, readResult); + transferred += readResult; + synchronized (mDataTransferListeners) { + it = mDataTransferListeners.iterator(); + while (it.hasNext()) { + it.next().onTransferProgress(readResult, transferred, mRemoteFile.getLength(), targetFile.getName()); + } + } + } + savedFile = true; + Header modificationTime = mGet.getResponseHeader("Last-Modified"); + if (modificationTime != null) { + Date d = WebdavUtils.parseResponseDate((String) modificationTime.getValue()); + mModificationTimestamp = (d != null) ? d.getTime() : 0; + } + + } else { + client.exhaustResponse(mGet.getResponseBodyAsStream()); + } + + } finally { + if (fos != null) fos.close(); + if (!savedFile && targetFile.exists()) { + targetFile.delete(); + } + mGet.releaseConnection(); // let the connection available for other methods + } + return status; + } + + private boolean isSuccess(int status) { + return (status == HttpStatus.SC_OK); + } + + private String getTmpPath() { + return mTemporalFolder + mRemoteFile.getRemotePath(); + } + + public void addDatatransferProgressListener (OnDatatransferProgressListener listener) { + synchronized (mDataTransferListeners) { + mDataTransferListeners.add(listener); + } + } + + public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) { + synchronized (mDataTransferListeners) { + mDataTransferListeners.remove(listener); + } + } + + public void cancel() { + mCancellationRequested.set(true); // atomic set; there is no need of synchronizing it + } +} diff --git a/oc_framework/src/com/owncloud/android/oc_framework/operations/remote/ExistenceCheckRemoteOperation.java b/oc_framework/src/com/owncloud/android/oc_framework/operations/remote/ExistenceCheckRemoteOperation.java new file mode 100644 index 00000000..88e6e81d --- /dev/null +++ b/oc_framework/src/com/owncloud/android/oc_framework/operations/remote/ExistenceCheckRemoteOperation.java @@ -0,0 +1,97 @@ +/* ownCloud Android client application + * Copyright (C) 2012 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 . + * + */ + +package com.owncloud.android.oc_framework.operations.remote; + +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.methods.HeadMethod; + +import com.owncloud.android.oc_framework.network.webdav.WebdavClient; +import com.owncloud.android.oc_framework.operations.RemoteOperation; +import com.owncloud.android.oc_framework.operations.RemoteOperationResult; +import com.owncloud.android.oc_framework.network.webdav.WebdavUtils; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.util.Log; + +/** + * Operation to check the existence or absence of a path in a remote server. + * + * @author David A. Velasco + */ +public class ExistenceCheckRemoteOperation extends RemoteOperation { + + /** Maximum time to wait for a response from the server in MILLISECONDs. */ + public static final int TIMEOUT = 10000; + + private static final String TAG = ExistenceCheckRemoteOperation.class.getSimpleName(); + + private String mPath; + private Context mContext; + private boolean mSuccessIfAbsent; + + + /** + * Full constructor. Success of the operation will depend upon the value of successIfAbsent. + * + * @param path Path to append to the URL owned by the client instance. + * @param context Android application context. + * @param successIfAbsent When 'true', the operation finishes in success if the path does NOT exist in the remote server (HTTP 404). + */ + public ExistenceCheckRemoteOperation(String path, Context context, boolean successIfAbsent) { + mPath = (path != null) ? path : ""; + mContext = context; + mSuccessIfAbsent = successIfAbsent; + } + + + @Override + protected RemoteOperationResult run(WebdavClient client) { + if (!isOnline()) { + return new RemoteOperationResult(RemoteOperationResult.ResultCode.NO_NETWORK_CONNECTION); + } + RemoteOperationResult result = null; + HeadMethod head = null; + try { + head = new HeadMethod(client.getBaseUri() + WebdavUtils.encodePath(mPath)); + int status = client.executeMethod(head, TIMEOUT, TIMEOUT); + client.exhaustResponse(head.getResponseBodyAsStream()); + boolean success = (status == HttpStatus.SC_OK && !mSuccessIfAbsent) || (status == HttpStatus.SC_NOT_FOUND && mSuccessIfAbsent); + result = new RemoteOperationResult(success, status, head.getResponseHeaders()); + Log.d(TAG, "Existence check for " + client.getBaseUri() + WebdavUtils.encodePath(mPath) + " targeting for " + (mSuccessIfAbsent ? " absence " : " existence ") + "finished with HTTP status " + status + (!success?"(FAIL)":"")); + + } catch (Exception e) { + result = new RemoteOperationResult(e); + Log.e(TAG, "Existence check for " + client.getBaseUri() + WebdavUtils.encodePath(mPath) + " targeting for " + (mSuccessIfAbsent ? " absence " : " existence ") + ": " + result.getLogMessage(), result.getException()); + + } finally { + if (head != null) + head.releaseConnection(); + } + return result; + } + + private boolean isOnline() { + ConnectivityManager cm = (ConnectivityManager) mContext + .getSystemService(Context.CONNECTIVITY_SERVICE); + return cm != null && cm.getActiveNetworkInfo() != null + && cm.getActiveNetworkInfo().isConnectedOrConnecting(); + } + + +} diff --git a/oc_framework/src/com/owncloud/android/oc_framework/operations/remote/ReadRemoteFileOperation.java b/oc_framework/src/com/owncloud/android/oc_framework/operations/remote/ReadRemoteFileOperation.java new file mode 100644 index 00000000..6cdacad8 --- /dev/null +++ b/oc_framework/src/com/owncloud/android/oc_framework/operations/remote/ReadRemoteFileOperation.java @@ -0,0 +1,108 @@ +/* ownCloud Android client application + * Copyright (C) 2012-2013 ownCloud Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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 . + * + */ +package com.owncloud.android.oc_framework.operations.remote; + +import java.util.ArrayList; + +import org.apache.http.HttpStatus; +import org.apache.jackrabbit.webdav.DavConstants; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.client.methods.PropFindMethod; + +import android.util.Log; + +import com.owncloud.android.oc_framework.network.webdav.WebdavClient; +import com.owncloud.android.oc_framework.network.webdav.WebdavEntry; +import com.owncloud.android.oc_framework.network.webdav.WebdavUtils; +import com.owncloud.android.oc_framework.operations.RemoteFile; +import com.owncloud.android.oc_framework.operations.RemoteOperation; +import com.owncloud.android.oc_framework.operations.RemoteOperationResult; + + +/** + * Remote operation performing the read a file from the ownCloud server. + * + * @author David A. Velasco + * @author masensio + */ + +public class ReadRemoteFileOperation extends RemoteOperation { + + private static final String TAG = ReadRemoteFileOperation.class.getSimpleName(); + private static final int SYNC_READ_TIMEOUT = 10000; + private static final int SYNC_CONNECTION_TIMEOUT = 5000; + + private String mRemotePath; + + + /** + * Constructor + * + * @param remotePath Remote path of the file. + */ + public ReadRemoteFileOperation(String remotePath) { + mRemotePath = remotePath; + } + + /** + * Performs the read operation. + * + * @param client Client object to communicate with the remote ownCloud server. + */ + @Override + protected RemoteOperationResult run(WebdavClient client) { + PropFindMethod propfind = null; + RemoteOperationResult result = null; + + /// take the duty of check the server for the current state of the file there + try { + propfind = new PropFindMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemotePath), + DavConstants.PROPFIND_ALL_PROP, + DavConstants.DEPTH_0); + int status; + status = client.executeMethod(propfind, SYNC_READ_TIMEOUT, SYNC_CONNECTION_TIMEOUT); + + boolean isMultiStatus = status == HttpStatus.SC_MULTI_STATUS; + if (isMultiStatus) { + // Parse response + MultiStatus resp = propfind.getResponseBodyAsMultiStatus(); + WebdavEntry we = new WebdavEntry(resp.getResponses()[0], client.getBaseUri().getPath()); + RemoteFile remoteFile = new RemoteFile(we); + ArrayList files = new ArrayList(); + files.add(remoteFile); + + // Result of the operation + result = new RemoteOperationResult(true, status, propfind.getResponseHeaders()); + result.setData(files); + + } else { + client.exhaustResponse(propfind.getResponseBodyAsStream()); + result = new RemoteOperationResult(false, status, propfind.getResponseHeaders()); + } + + } catch (Exception e) { + result = new RemoteOperationResult(e); + e.printStackTrace(); + Log.e(TAG, "Synchronizing file " + mRemotePath + ": " + result.getLogMessage(), result.getException()); + } finally { + if (propfind != null) + propfind.releaseConnection(); + } + return result; + } + +} diff --git a/oc_framework/src/com/owncloud/android/oc_framework/operations/remote/UploadRemoteFileOperation.java b/oc_framework/src/com/owncloud/android/oc_framework/operations/remote/UploadRemoteFileOperation.java new file mode 100644 index 00000000..91e21b49 --- /dev/null +++ b/oc_framework/src/com/owncloud/android/oc_framework/operations/remote/UploadRemoteFileOperation.java @@ -0,0 +1,147 @@ +/* ownCloud Android client application + * Copyright (C) 2012-2013 ownCloud Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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 . + * + */ + +package com.owncloud.android.oc_framework.operations.remote; + +import java.io.File; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.methods.PutMethod; +import org.apache.commons.httpclient.methods.RequestEntity; +import org.apache.http.HttpStatus; + +import com.owncloud.android.oc_framework.network.ProgressiveDataTransferer; +import com.owncloud.android.oc_framework.network.webdav.FileRequestEntity; +import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener; +import com.owncloud.android.oc_framework.network.webdav.WebdavClient; +import com.owncloud.android.oc_framework.network.webdav.WebdavUtils; +import com.owncloud.android.oc_framework.operations.OperationCancelledException; +import com.owncloud.android.oc_framework.operations.RemoteOperation; +import com.owncloud.android.oc_framework.operations.RemoteOperationResult; + +/** + * Remote operation performing the upload of a remote file to the ownCloud server. + * + * @author David A. Velasco + * @author masensio + */ + +public class UploadRemoteFileOperation extends RemoteOperation { + + + protected String mStoragePath; + protected String mRemotePath; + protected String mMimeType; + protected PutMethod mPutMethod = null; + + private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false); + protected Set mDataTransferListeners = new HashSet(); + + protected RequestEntity mEntity = null; + + public UploadRemoteFileOperation(String storagePath, String remotePath, String mimeType) { + mStoragePath = storagePath; + mRemotePath = remotePath; + mMimeType = mimeType; + } + + @Override + protected RemoteOperationResult run(WebdavClient client) { + RemoteOperationResult result = null; + + try { + // / perform the upload + synchronized (mCancellationRequested) { + if (mCancellationRequested.get()) { + throw new OperationCancelledException(); + } else { + mPutMethod = new PutMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemotePath)); + } + } + + int status = uploadFile(client); + + result = new RemoteOperationResult(isSuccess(status), status, (mPutMethod != null ? mPutMethod.getResponseHeaders() : null)); + + } catch (Exception e) { + // TODO something cleaner with cancellations + if (mCancellationRequested.get()) { + result = new RemoteOperationResult(new OperationCancelledException()); + } else { + result = new RemoteOperationResult(e); + } + } + return result; + } + + public boolean isSuccess(int status) { + return ((status == HttpStatus.SC_OK || status == HttpStatus.SC_CREATED || status == HttpStatus.SC_NO_CONTENT)); + } + + protected int uploadFile(WebdavClient client) throws HttpException, IOException, OperationCancelledException { + int status = -1; + try { + File f = new File(mStoragePath); + mEntity = new FileRequestEntity(f, mMimeType); + synchronized (mDataTransferListeners) { + ((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(mDataTransferListeners); + } + mPutMethod.setRequestEntity(mEntity); + status = client.executeMethod(mPutMethod); + client.exhaustResponse(mPutMethod.getResponseBodyAsStream()); + + } finally { + mPutMethod.releaseConnection(); // let the connection available for other methods + } + return status; + } + + public Set getDataTransferListeners() { + return mDataTransferListeners; + } + + public void addDatatransferProgressListener (OnDatatransferProgressListener listener) { + synchronized (mDataTransferListeners) { + mDataTransferListeners.add(listener); + } + if (mEntity != null) { + ((ProgressiveDataTransferer)mEntity).addDatatransferProgressListener(listener); + } + } + + public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) { + synchronized (mDataTransferListeners) { + mDataTransferListeners.remove(listener); + } + if (mEntity != null) { + ((ProgressiveDataTransferer)mEntity).removeDatatransferProgressListener(listener); + } + } + + public void cancel() { + synchronized (mCancellationRequested) { + mCancellationRequested.set(true); + if (mPutMethod != null) + mPutMethod.abort(); + } + } + +} diff --git a/oc_framework/src/com/owncloud/android/oc_framework/utils/FileUtils.java b/oc_framework/src/com/owncloud/android/oc_framework/utils/FileUtils.java index a7674e4f..192c267b 100644 --- a/oc_framework/src/com/owncloud/android/oc_framework/utils/FileUtils.java +++ b/oc_framework/src/com/owncloud/android/oc_framework/utils/FileUtils.java @@ -66,4 +66,6 @@ public class FileUtils { } return result; } + + } diff --git a/oc_jb_workaround/AndroidManifest.xml b/oc_jb_workaround/AndroidManifest.xml index 1b12fb49..46e92691 100644 --- a/oc_jb_workaround/AndroidManifest.xml +++ b/oc_jb_workaround/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="0100011" + android:versionName="1.0.11" > + diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml index cbda0e71..499d68a1 100644 --- a/res/values-ar/strings.xml +++ b/res/values-ar/strings.xml @@ -7,12 +7,12 @@ الملفات إنشاء دليل تعديلات + تفاصيل عام المزيد حسابات المساعدة الدمغة. - عنوان الخادم إسم المستخدم كلمات السر جديد لـ %1$s ؟ @@ -32,19 +32,23 @@ النوع عُدل انزال + تحديث ملف تم تغيير اسم الملف إلى %1$s أثناء الرفع نعم لا تم + إلغاء تحميل إلغاء رفع الملفات الغاء خطأ + تحميل ... حدث خطأ غير معروف. حول عدل كلمة السر حذف الحساب حساب جديد رفع من + اسم المسار يتم الرفع %1$d%% رفع %2$s تم الرفع بنجاح @@ -56,6 +60,7 @@ تم تحميل %1$s بنجاح فشل التحميل تحميل %1$s قد لا يكون كاملاَ + لم يتم تحميلها بعد اختر حساب تعذر إكمال التزامن لـ %1$s كلمة السر غير صالحة لـ %1$s @@ -79,9 +84,27 @@ الغى هل تود حقاَ إزالة %1$s ؟ هل ترغب في إزالة %1$s و جهات الاتصال التابعة له؟ + المحتويات المحلية فقط حذف من الخادم يتم الحذف بنجاح لقد فشل الحذف + أدخل اسما جديدا فضلاً, انتظر لم يتم اختيار أي ملف + تفاصيل + إخفاء + الاسم الشائع: + منظمة: + الوحدة التنظيمية: + البلد: + المكان: + من: + إلى: + التوقيع: + الخوارزمية: + 389 KB + 12:23:45 + معاينة الصورة + هذه الصورة لا يمكن أن تظهر + تحديد الكل diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml new file mode 100644 index 00000000..c757504a --- /dev/null +++ b/res/values-az/strings.xml @@ -0,0 +1,2 @@ + + diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml index c757504a..8be48850 100644 --- a/res/values-be/strings.xml +++ b/res/values-be/strings.xml @@ -1,2 +1,7 @@ - + + Налады + Так + Не + Памылка + diff --git a/res/values-bg-rBG/strings.xml b/res/values-bg-rBG/strings.xml index c84d7057..335b1b4c 100644 --- a/res/values-bg-rBG/strings.xml +++ b/res/values-bg-rBG/strings.xml @@ -10,7 +10,6 @@ Профили Своевременно качване на снимки направени с камерата Помощ - Адрес на сървъра Потребител Парола Файлове diff --git a/res/values-bn-rBD/strings.xml b/res/values-bn-rBD/strings.xml index a9080e66..2454ad33 100644 --- a/res/values-bn-rBD/strings.xml +++ b/res/values-bn-rBD/strings.xml @@ -8,7 +8,6 @@ বেশী একাউন্ট সহায়িকা - সার্ভার ঠিকানা ব্যবহারকারি কূটশব্দ ফাইল diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml index ee1c3e16..ebdee27c 100644 --- a/res/values-ca/strings.xml +++ b/res/values-ca/strings.xml @@ -30,7 +30,7 @@ Proveu %1$s a un telèfon avançat! Vull convidar-te a usar l\'aplicació %1$s al teu telèfon avançat!\nBaixa\'l aquí: %2$s Comprova el servidor - Adreça del servidor + Adreça del servidor https://… Nom d\'usuari Contrasenya Nou a %1$s? diff --git a/res/values-cs-rCZ/strings.xml b/res/values-cs-rCZ/strings.xml index ae216340..9af81e4f 100644 --- a/res/values-cs-rCZ/strings.xml +++ b/res/values-cs-rCZ/strings.xml @@ -30,7 +30,7 @@ Zkuste %1$s na vašem smartphonu! Chtěl bych vás pozvat k používání %1$s na vašem smartphonu.\nKe stažení zde: %2$s Zkontrolovat server - Adresa serveru + Adresa serveru https://... Uživatelské jméno Heslo Nováček s %1$s? diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml index 85489a17..14d3ed0a 100644 --- a/res/values-da/strings.xml +++ b/res/values-da/strings.xml @@ -24,9 +24,13 @@ Dette viser de optagne logger Slet Historik Hjælp + Anbefal til en ven + Feedback Imprint + Prøv %1$s på din smartphone! + Jeg ønsker at invitere dig til at bruge %1$s på din smartphone!\nHent den her: %2$s Check Server - Serveradresse + Server addresse https://… Brugernavn Kodeord Uvant med %1$s @@ -91,6 +95,7 @@ Visse lokale filer blev glemt %1$d filer ud af %2$s mappe kunne ikke kopieres ind i Fra version 1.3.16 bliver filer uploadet fra denne enhed kopieret til mappen %1$s for at forhindre datatab når en enkelt fil synkroniseres med flere konti.\n\nPå grund af denne ændring blev alle filer uploadet i tidligere versioner af denne app kopieret til mappen %2$s. Imidlertid forhindrede en fejl færdiggørelsen af denne operation under konto-synkronisering. Du kan enten lade filerne være som de er og fjerne linket til %3$s eller flytte filerne til mappen %1$s og beholde linket til %4$s.\n\nHerunder er en liste med de lokale filer og de eksterne filer i %5$s, som de var knyttet til. + Mappen %1$s eksistere ikke længere Flyt alle Alle filer blev flyttet Visse filer kunne ikke flyttes @@ -130,12 +135,14 @@ Forbindelse oprettet Afprøver forbindelse ... Misdannet server konfiguration + En konto for den samme bruger og server eksisterer allerede på enheden Ukendt fejl opstod! Kunne ikke finde host Server instans blev ikke fundet Serveren var for længe om at svare Deform URL SSL initialisering fejlede + Kunne ikke bekræfte SSl-serverens identitet Ikke genkendt server version Ikke ikke oprette forbindelse Sikker forbindelse oprettet @@ -143,7 +150,12 @@ Mislykket godkendelse Adgang afvist af autorisationsserver Uventet tilstand; angiv server-URL\'en igen + Din godkendelse udløb. Gentag godkendelse Indtast venligst dit nuværende kodeord + Din session udløb. Forbind venligst igen + Forbinder til godkendelsesserver ... + Serveren understøtter ikke denne godkendelsesmetode + %1$s understøtter ikke multiple konti Hold fil opdateret Omdøb Fjern @@ -161,9 +173,11 @@ Ekstern fil kunne ikke kontrolleres Filindholdet allerede synkroniseret Mappe kunne ikke oprettes + Ugyldige tegn: / \\ < > : \" | ? * Vent et øjeblik Uforventet problem; prøv venligst anden applikation til at vælge filen Ingen fil blev valgt + Log på med oAuth2 Forbinder til oAuth2 server... Sidens identitet kunne ikke verificeres - Serverens certifikat er ikke troværdigt diff --git a/res/values-de-rCH/strings.xml b/res/values-de-rCH/strings.xml index 0d5cde23..d995da1c 100644 --- a/res/values-de-rCH/strings.xml +++ b/res/values-de-rCH/strings.xml @@ -27,7 +27,6 @@ Rückmeldungen Impressum Server überprüfen - Adresse des Servers Benutzername Passwort Ist %1$s neu für Sie? diff --git a/res/values-de-rDE/strings.xml b/res/values-de-rDE/strings.xml index 50597463..63a2446a 100644 --- a/res/values-de-rDE/strings.xml +++ b/res/values-de-rDE/strings.xml @@ -30,7 +30,7 @@ Probieren Sie %1$s auf Ihrem Smartphone! Ich möchte Sie zum Benutzen von %1$s auf Ihrem Smartphone einladen!\nLaden Sie es hier herunter: %2$s Server überprüfen - Adresse des Servers + Server-Adresse https://… Benutzername Passwort Ist %1$s neu für Sie? diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 5668477f..588837a4 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -30,7 +30,7 @@ Probiere %1$s auf Deinem Smartphone! Ich möchte Dich zu %1$s für Dein Smartphone einladen!\nLade es hier herunter: %2$s Überprüfe den Server - Adresse des Servers + Server-Adresse https://… Benutzername Passwort Ist %1$s neu für dich? diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml index f747b1ba..7f5fb583 100644 --- a/res/values-el/strings.xml +++ b/res/values-el/strings.xml @@ -30,9 +30,10 @@ Δοκιμάστε %1$s στο κινητό σας! Θέλω να σας προσκαλέσω να χρησιμοποιήσετε το %1$s στο κινητό σας!\nΚατεβάστε το εδώ: %2$s Έλεγχος Διακομιστή - Διεύθυνση εξυπηρέτη + Διεύθυνση εξυπηρέτη https://… Όνομα χρήστη Συνθηματικό + Νέος στο %1$s; Αρχεία Σύνδεση Μεταφόρτωση @@ -110,6 +111,10 @@ Εσφαλμένο PIN της εφαρμογής Αφαιρέθηκε το PIN της εφαρμογής Το PIN της εφαρμογής αποθηκεύτηκε + %1$s αναπαραγωγή μουσικής + %1$s (αναπαραγωγή) + %1$s (φόρτωση) + %1$s αναπαραγωγή τελείωσε Δεν βρέθηκε αρχείο πολυμέσων Δεν δόθηκε λογαριασμός Το αρχείο δεν βρίσκεται σε έγκυρο λογαριασμό @@ -119,7 +124,12 @@ Λήξη χρόνου κατά την προσπάθεια αναπαραγωγής Το αρχείο πολυμέσων δεν μπορεί να μεταδοθεί Το αρχείο πολυμέσων δεν μπορεί να αναπαραχθεί με την παρεχόμενη εφαρμογή αναπαραγωγής πολυμέσων + Σφάλμα ασφαλείας κατά την προσπάθεια αναπαραγωγής του %1$s + Σφάλμα εισόδου κατά την προσπάθεια αναπαραγωγής του %1$s + Απροσδόκτο σφάλμα κατά την προσπάθεια αναπαραγωγής του %1$s + Κουμπί επαναφοράς Κουμπί αναπαραγωγής ή παύσης + Κουμπί προώθησης Προσπάθεια σύνδεσης... Δεν υπάρχει σύνδεση στο δίκτυο Μη διαθέσιμη ασφαλής σύνδεση. @@ -209,6 +219,9 @@ Προεπισκόπηση εικόνας Αυτή η εικόνε δεν μπόρεσε να προβληθεί %1$s δεν μπορεσε να αντιγραφθεί στον %2$s τοπικο καταλόγο + Αποτυχημένη στιγμιαία φόρτωση + Αποτυχημένες στιγμιαίες φορτώσεις + Σύνοψη όλων των αποτυχημένων φορτώσεων επιλογή όλων επανάληψη για όλα τα επιλεγμένα διαγραφή όλων των επιλεγμένων από τη λίστα προς μεταφόρτωση diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml index 8d062f3d..0562dd7c 100644 --- a/res/values-en-rGB/strings.xml +++ b/res/values-en-rGB/strings.xml @@ -30,7 +30,7 @@ Try %1$s on your smartphone! I want to invite you to use %1$s on your smartphone!\nDownload here: %2$s Check Server - Server address + Server address https://… Username Password New to %1$s? diff --git a/res/values-eo/strings.xml b/res/values-eo/strings.xml index debd2948..c69e2c4e 100644 --- a/res/values-eo/strings.xml +++ b/res/values-eo/strings.xml @@ -15,7 +15,6 @@ Kapabligi tujan alŝuton Tuje alŝuti fotojn faritajn per fotilo Helpo - Servila adreso Uzantonomo Pasvorto Dosieroj diff --git a/res/values-es-rAR/strings.xml b/res/values-es-rAR/strings.xml index f9196dd5..92e67e3f 100644 --- a/res/values-es-rAR/strings.xml +++ b/res/values-es-rAR/strings.xml @@ -27,7 +27,6 @@ Sugerencias Imprint Verificar Servidor - Dirección del servidor Nombre de usuario Contraseña ¿Sos nuevo para %1$s? diff --git a/res/values-es-rCL/strings.xml b/res/values-es-rCL/strings.xml new file mode 100644 index 00000000..a3281431 --- /dev/null +++ b/res/values-es-rCL/strings.xml @@ -0,0 +1,15 @@ + + + Subir + Archivos + Crear directorio + Configuración + General + Cuentas + Usuario + Clave + Archivos + Conectar + Subir + No se encuentra la cuenta + diff --git a/res/values-es-rMX/strings.xml b/res/values-es-rMX/strings.xml index c757504a..aaaf3feb 100644 --- a/res/values-es-rMX/strings.xml +++ b/res/values-es-rMX/strings.xml @@ -1,2 +1,233 @@ - + + App Android %1$s + versión %1$s + Actualizar cuenta + Subir archivo + Contenido de otras aplicaciones + Archivos + Abrir con + Crear directorio + Ajustes + Detalles + General + Más + Cuentas + Gestionar cuentas + PIN de aplicación + Proteja su cliente + Habilita la subida instantánea + Subir instantáneamente las fotos tomadas por la cámara + Habilitar registro + Esto es usado para registrar problemas + Historia del Registro + Esto muestra los registros grabados + Eliminar Historial + Ayuda + Recomendar a un amigo + Mensajes de retroalimentación + Imprint + Prueba %1$s en tu smarthphone! + Quiero invitarte a usar %1$s en tu smarthphone!⏎\nDescargalo aquí: %2$s + Compruebe el servidor. + Dirección del servidor https://… + Nombre de usuario + Contraseña + New to %1$s? + Archivos + Conectar + Subir + Escoja el directorio de carga: + No se encontraron cuentas + No hay cuentas de %1$s en tu dispositivo. Por favor configura una cuenta primero. + Configuración + Salir + No hay contenido para subir + Ningún contenido ha sido recibido. No hay nada que subir. + %1$s no está autorizado para acceder al contenido compartido + Enviando + No hay archivos en esta carpeta.\nPuedes añadir nuevos archivos con la opción \"Subir\" del menú. + Pulsa sobre un archivo para mostrar información adicional. + Tamaño: + Tipo: + Creado: + Modificado: + Descargar + Actualizar archivo + El archivo fue renombrado como %1$s durante la subida + Sí + No + Aceptar + Cancelar descarga + Cancelar subida + Cancelar + Guardar & Salir + Error + Cargando ... + Error desconocido + Acerca de + Cambiar contraseña + Eliminar cuenta + Crear cuenta + Subir + Nombre de directorio + Subiendo... + %1$d%% Subiendo %2$s + Subido con éxito + %1$s se ha subido con éxito + Error en la subida + La subida de %1$s no se pudo completar + Descargando ... + %1$s Descargada de %2$s + Descarga completa + %1$s se ha descargado con éxito + Falló la descarga + La descarga de %1$s no se pudo completar + No descargado + Elige una cuenta + Falló la sincronización + La sincronización de %1$s s no se pudo completar + Contraseña no válida para %1$s + Se encontraron conflictos + Falló la sincronización de contenidos de %1$d archivos + Fallos en la sincronización de contenidos + Los contenidos de %1$d archivos no fueron sincronizados (%2$d conflictos) + Algunos archivos locales se han perdido + %1$d archivos de %2$s no han podido ser copiados + Como versión 1.3.16, los archivos subidos desde este dispositivo son copiados a un archivo %1$s local para prevenir perdida de datos cuando un simple archivo es sincronizado con multiples cuentas.\n\nDebido a este cambio, todos los archivos subidos en versiones previas de esta aplicación han sido copiados a la carpeta %2$s. No obtante, un error previno el completado de esta operación durante la sincronización de cuenta. Debería dejar el o los archivos así y eliminar el enlace a %3$s o mover el o los archivos al %1$s directorio y conservar el enlace a %4$s.\n\nListado abajo tiene los enlaces a los archivos locales y archivos remotos en %5$s + La carpeta local %1$s no existe. + Mover todo + Todos los archivos fueron movidos + Algunos archivos no han podido ser movidos + Local: %1$s + Remoto: %1$s + No hay suficiente espacio para copiar los archivos seleccionados en la carpeta %1$s. ¿Quiere moverlos en lugar de copiarlos? + Por favor, inserta tu PIN de aplicación + Introduzca un PIN para la aplicación + Se solicitará el PIN cada vez que se inicie la aplicación + Repita el PIN para la aplicación, por favor + Borre su PIN de aplicación + Los PIN introducidos no son iguales + PIN de aplicación incorrecto + PIN de aplicación borrado + PIN de aplicación guardado + Reproductor de música %1$s + %1$s (reproduciendo) + %1$s (cargando) + %1$s reproducción finalizada + No se encuentra archivo de medio + No se ha proporcionado cuenta + El archivo no esta en una cuenta valida + Codec No Soportado + El archivo de medios no pudo ser leído + Archivo no codificado correctamente + Tiempo de espera agotado en el intento de reproducción + Archivo de medio no puede ser transmitido + El archivo de medios no se puede reproducir con el reproductor de medios por defecto + Error de seguridad al intentar reproducir %1$s + Error de entrada al intentar reproducir %1$s + Error inesperado intentando reproducir %1$s + Botón Rebobinado + Botón de reproducción o pausa + Botón avance rápido + Intentado iniciar sesión... + Sin conexión de red + Conexión segura no disponible. + Conexión establecida + Probando conexión... + Configuración de servidor en formato incorrecto + Una cuenta para el mismo usuario y servidor ya existen en el dispositivo + El usuario introducido no concuerda con el usuario de esta cuenta + Ocurrió un error desconocido + No se pudo encontrar la dirección + Instancia de servidor no encontrada + El servidor ha tardado demasiado en responder + URL no válida + Falló la inicialización SSL + No fue posible verificar la identidad del servidor SLL + No se reconoce la versión del servidor + No se ha podido establecer la conexión + Conexión segura establecida + Nombre de usuario o contraseña incorrecta + Autorización no satisfactoria + Acceso denegado por servidor de autorización + Estado inesperado; por favor, introduzca la URL del servidor de nuevo + Su autorización ha expirado. Por favor, autorice de nuevo + Por favor, introduzca la contraseña actual. + Su sesión ha expirado. Favor de conectarse de nuevo + Conectando al servidor de autenticación... + El servidor no soporta este método de autenticación + %1$s no soporta cuentas múltiples + Mantener el archivo actualizado + Renombrar + Borrar + ¿Está seguro que desea borrar %1$s ? + ¿Desea elimiar %1$s y sus descendientes? + Sólo local + Sólo archivos locales + Eliminar del servidor + Tanto remoto como local + Borrado correctamente + El borrado no pudo ser completado + Introduzca un nombre nuevo + No se pudo cambiar el nombre de la copia local, trata con un nombre differente + No se pudo cambiar el nombre + No pudo comprobarse el archivo remoto + Ya está sincronizado + El directorio no pudo ser creado + Carácteres ilegales: / \\ < > : \" | ? * + Espere un momento + Problema inesperado; por favor, prueba otra app para seleccionar el archivo + No fué seleccionado ningún archivo + Ingresar con oAuth2 + Conectando al servidor oAuth2... + La identidad del sitio no puede ser verificada + - El certificado del servidor no es de confianza + - El certificado del servidor expiró + - El certificado del servidor es demasiado reciente + - La URL no coincide con el nombre de dominio del certificado + ¿Confías de todas formas en este certificado? + El certificado no pudo ser guardado + Detalles + Ocultar + Emitido para: + Emitido por: + Nombre común: + Organización: + Unidad organizativa + Pais: + Estado: + Ubicación: + Validez: + De: + A: + Firma: + Algoritmo: + Esto es un marcador de posición + marcadordeposición.txt + Imagen PNG + 389 KB + 2012/05/18 12:23 PM + 12:23:45 + Subir imágenes sólo via WiFi + /SubidasInstantáneas + Conflicto en la actualización + El archivo remoto %s no está sincronizado con el archivo local. Si continúa, se reemplazará el contenido del archivo en el servidor. + Mantener ambas + Sobrescribir + No subir + Previsualización de imagen + No se puede mostrar la imagen + %1$s no puede ser copiado al %2$s directorio local + Carga instantánea fallida + Cargas instantáneas fallidas + Resumen de todas las cargas instantáneas fallidas + Seleccionar todos + Reintentar todos los seleccionados + Eliminar todo de la cola de subida + Reintentar subida de imagen: + Cargar mas imágenes + No hacer nada no está conectado para subida instantánea + Mensaje de error: + Por favor revise su configuración de servidor, posiblemente su cuota se haya excedido. + diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index 46d4393d..b8188011 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -3,12 +3,12 @@ App Android %1$s versión %1$s Actualizar cuenta - Subir archivo + Subir Contenido de otras aplicaciones Archivos Abrir con Crear directorio - Ajustes + Configuración Detalles General Más @@ -16,7 +16,7 @@ Gestionar cuentas PIN de aplicación Proteja su cliente - Habilita la subida instantánea + Habilitar la subida instantánea Subir instantáneamente las fotos tomadas por la cámara Habilitar registro Esto es usado para registrar problemas @@ -30,7 +30,7 @@ Prueba %1$s en tu smarthphone! Quiero invitarte a usar %1$s en tu smarthphone!⏎\nDescargalo aquí: %2$s Compruebe el servidor. - Dirección del servidor + Dirección del servidor https://… Nombre de usuario Contraseña New to %1$s? @@ -38,14 +38,14 @@ Conectar Subir Escoja el directorio de carga: - No se encontraron cuentas + No se encontró la cuenta No hay cuentas de %1$s en tu dispositivo. Por favor configura una cuenta primero. Configuración Salir No hay contenido para subir Ningún contenido ha sido recibido. No hay nada que subir. %1$s no está autorizado para acceder al contenido compartido - Enviando + Subiendo... No hay archivos en esta carpeta.\nPuedes añadir nuevos archivos con la opción \"Subir\" del menú. Pulsa sobre un archivo para mostrar información adicional. Tamaño: diff --git a/res/values-et-rEE/strings.xml b/res/values-et-rEE/strings.xml index 3a07fcdb..ea088b76 100644 --- a/res/values-et-rEE/strings.xml +++ b/res/values-et-rEE/strings.xml @@ -30,7 +30,7 @@ Proovi oma nutitelefonil rakendust %1$s! Soovin sind kutsuda kasutama oma nutitelefonil rakendust %1$s!\nLae alla siit: %2$s Kontrolli serverit - Serveri aadress + Serveri aadress https://... Kasutajanimi Parool Uus %1$s kasutaja? diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml index 4938ab57..2b870906 100644 --- a/res/values-eu/strings.xml +++ b/res/values-eu/strings.xml @@ -25,11 +25,11 @@ Ezabatu historia Laguntza Lagun bati aholkatu + Oharrak Imprint Probatu %1$s zure telefono adimentsuan! Nik %1$s zure telefono adimentsuan erabitzera gonbidatu nahi zaitut!\nDeskargatu hemen: %2$s Egiaztatu zerbitzaria - Zerbitzariaren helbidea Erabiltzaile izena Pasahitza Berria %1$s-n? diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml index 15690cc7..d37ecfe4 100644 --- a/res/values-fa/strings.xml +++ b/res/values-fa/strings.xml @@ -26,7 +26,6 @@ راه‌نما باز خورد مهر زدن - آدرس سرور نام کاربری رمز عبور پرونده‌ها diff --git a/res/values-fi-rFI/strings.xml b/res/values-fi-rFI/strings.xml index d2f780b6..a29c7cef 100644 --- a/res/values-fi-rFI/strings.xml +++ b/res/values-fi-rFI/strings.xml @@ -27,7 +27,7 @@ Kokeile %1$sia älypuhelimellasi! Ota %1$s käyttöösi älypuhelimessa!\nLataa tästä: %2$s Tarkista palvelin - Palvelimen osoite + Palvelinosoite https://… Käyttäjätunnus Salasana Onko %1$s uusi tuttavuus sinulle? diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index 40d759f5..6c19d05e 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -3,7 +3,7 @@ %1$s Android App version %1$s Actualiser le compte - Téléverser + Charger Contenu d\'une autre application Fichiers Ouvrir avec @@ -30,7 +30,7 @@ Essayez %1$s sur votre smartphone ! J\'aimerais vous inviter à utiliser %1$s sur votre smartphone !\nTéléchargez-le ici : %2$s Vérifier le serveur - Adresse du serveur + Adresse du serveur https://... Nom d\'utilisateur Mot de passe Nouveau dans %1$s ? diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml index fe9e7d0f..e656654d 100644 --- a/res/values-gl/strings.xml +++ b/res/values-gl/strings.xml @@ -30,7 +30,7 @@ Tente %1$s no seu teléfono intelixente! Quero convidalo a empregar %1$s no seu teléfono intelixente!⏎\nDescárgueo de aquí:%2$s Comprobar o servidor - Enderezo do servidor + Enderezo do servidor https://… Nome de usuario Contrasinal Novo en %1$s? diff --git a/res/values-he/strings.xml b/res/values-he/strings.xml index 71c8b9df..36de5a7f 100644 --- a/res/values-he/strings.xml +++ b/res/values-he/strings.xml @@ -15,7 +15,6 @@ הפעלת העלאות מהירות העלאה מהירה של תמונות שמצולמות במצלמה שלך עזרה - כתובת שרת שם משתמש ססמה קבצים diff --git a/res/values-hu-rHU/strings.xml b/res/values-hu-rHU/strings.xml index dc760791..24b3fd46 100644 --- a/res/values-hu-rHU/strings.xml +++ b/res/values-hu-rHU/strings.xml @@ -30,7 +30,7 @@ Próbálja ki %1$s-t az okostelefonján! Kérem próbálja ki %1$s-t az okostelefonján!\nInnen tölthető le: %2$s Szerver állapot ellenörzés - A kiszolgáló címe + Kiszolgáló címe https://... Felhasználói név Jelszó Új vagy a %1$s területen? @@ -175,6 +175,7 @@ A távoli fájl nem volt ellenőrizhető Az állományok már szinkonizálva vannak A mappa nem hozható létre + Nem megendedett karakterek: / \\ < > : \" | ? * Egy pillanat... Váratlan hiba; válassza ki a fájlt más programból Egy fájl sincs kiválasztva @@ -218,6 +219,7 @@ Előnézeti kép Ez a kép nem jelenik meg %1$s-t nem sikerült átmásolni ide: %2$s + Sikertelen azonnali feltöltés\" Sikertelen Azonnali feltöltés Összefoglaló az összes sikertelen instant feltöltésről Összes kijelölése diff --git a/res/values-ia/strings.xml b/res/values-ia/strings.xml index 5db09aac..ecfaa300 100644 --- a/res/values-ia/strings.xml +++ b/res/values-ia/strings.xml @@ -3,6 +3,7 @@ Incargar Files Configurationes + General Plus Adjuta Nomine de usator diff --git a/res/values-id/strings.xml b/res/values-id/strings.xml index 3eb4ccb0..bd151ad1 100644 --- a/res/values-id/strings.xml +++ b/res/values-id/strings.xml @@ -1,27 +1,228 @@ + %1$s Apl Android + versi %1$s + Segarkan akun Unggah + Konten dari apl lain Berkas + Bukan dengan + Buat folder pengaturan + Rincian umum Lainnya + Akun + Kelola Akun + PIN Apl + Lindungi klien Anda + Aktifkan unggah instan + Unggah langsung foto yang diambil oleh kamera + Aktifkan Pencatatan + Ini digunakan untuk mencatat masalah + Riwayat Catatan + Ini menampilkan catatan yang disimpan + Riwayat Hapus Bantuan + Rekomendasikan ke teman + Umpan balik Imprint - alamat server - nama pengguna - kata kunci + Coba %1$s pada smartphone Anda! + Saya mengundang Anda untuk menggunakan %1$s pada smartphone Anda!\nUnduh di sini: %2$s + Periksa Server + Alamat server https://… + Nama Pengguna + Sandi + Baru di %1$s? Berkas + Sambungkan Unggah + Pilih folder unggah + Tidak ada akun yang ditemukan + Belum ada akun %1$s pada perangkat Anda. Silahkan buat akun terlebih dahulu. + Pengaturan Keluar - unduh + Tidak ada konten untuk diunggah + Tidak ada konten yang diterima. Tidak ada yang diunggah + %1$s tidak diizinkan mengakses konten berbagi + Mengunggah + Tidak ada berkas dalam folder ini.\nBerkas baru dapat ditambahkan dengan opsi menu \"Unggah\". + Sentuh pada berkas untuk menampilkan informasi tambahan + Ukuran: + Tipe: + Dibuat: + Diubah: + Unduh + Segarkan berkas + Berkas diubah namanya menjadi %1$s saat pengunggahan Ya Tidak Oke + Batal mengunduh Batal mengunggah - batal - kesalahan + Batal + Simpan & Keluar + Kesalahan + Memuat ... + Galat tidak diketahui + Tentang Ubah sandi + Hapus akun + Buat akun + Unggah dari... + Nama folder + Mengungggah... + %1$d%% Mengunggah %2$s + Berhasil mengunggah + %1$s berhasil diunggah + Gagal mengunggah + Unggah %1$s tidak selesai + Mengunduh... + %1$d%% Mengunduh %2$s + Berhasil mengunduh + %1$s berhasil diunduh + Gagal Mengunduh + Mengunduh %1$s tidak selesai + Belum diunduh + Pilih akun + Sinkronisasi gagal + Sinkronisasi %1$s tidak selesai + Sandi salah untuk %1$s + Konflik ditemukan + Konten berkas %1$d tidak dapat disinkronasikan (%2$d konflik) + Beberapa berkas lokal terlupakan + %1$d berkas dari direktori %2$s tidak dapat disalin ke + Folder %1$s tidak ada lagi + Pindahkan semua + Semua berkas sudah dipindahkan + Beberapa berkas tidak dapat dipindahkan + Lokal: %1$s + Jauh: %1$s + Silakan masukkan PIN Apl + Masukkan PIN Apl + PIN akan selalu diminta setiap kali apl dijalankan + Silakan masukkan ulang PIN Apl + Hapus PIN Apl + PIN Apl tidak sama + PIN Apl salah + PIN Apl dihapus + PIN Apl disimpan + Pemutar musik %1$s + %1$s (dimainkan) + %1$s (sedang dimuat) + Tidak ditemukan berkas media + Tidak ada akun yang diberikan + Brkas tidak didalam akun yang sah + Kodek media tidak didukung + Berkas media tidak dapat dibaca + Berkas media tidak di enkode dengan benar + Waktu habis saat mencoba untuk main + Berkas media tidak bisa dialirkan + Berkas media tidak dapat dimainkan dengan pemutar media + Kesalahan keamanan saat mencoba memutar %1$s + Kesalahan masukkan saat mencoba memutar %1$s + Kesalahan tak terduga saat mencoba memutar %1$s + Tombol mundur + Tombol main dan jeda + Tombol maju + Mencoba untuk masuk... + Tidak ada koneksi internet + Sambungan aman tidak tersedia + Sambungan dibuat + Pengetesan koneksi ... + Konfigurasi server cacat + Akun untuk pengguna dan server yang sama sudah ada dalam perangkat + Pengguna yang dimasukkan tidak cocok dengan pengguna akun ini + Terjadi kesalahan yang tidak diketahui! + Tidak menemukan host + Instansi server tidak ditemukan + Server terlalu lama merespon + Format URL salah + Menginisiasi SSL gagal + Tidak dapat memverifikasi identitas server SSL + Versi server tidak dikenal + Tidak dapat membuat koneksi + Sambungan aman dibuat + Nama pengguna dan sandi salah + Otorisasi tidak berhasil + Akses ditolak oleh server otorisasi + Keadaan tak terduga, silahkan masukkan URL server yang lagi + Otorisasi Anda telah berakhir. Silakan mengotorisasi lagi + Silakan mesukkan sandi saat ini + Sesi Anda telah berakhir. Silakan masuk kembali + Menyambungkan ke server otentikasi... + Server tidak mendukung medote otentikasi ini + %1$s tidak mendukung banyak akun + Biarkan berkas tetap terbaru Ubah nama - hilangkan - sembunyikan + Hapus + Apakah Anda yakin ingin menghapus %1$s ? + Apakah Anda benar-benar ingin menghapus %1$s beserta isinya? + Lokal saja + Konten lokal saja + Hapus dari server + Jarak jauh dan lokal + Penghapusan berhasil + Penghapusan gagal + Masukkan nama baru + Salinan lokal tidak dapat diubah nama, coba dengan nama yang berbeda + Mengubah nama tidak selesai + Berkas jauh tidak dapat diperiksa + Isi berkas sudah diselaraskan + Folder tidak dapat dibuat + Karakter yang dilarang: / \\ < > : \" | ? * + Tunggu sejenak + Masalah tidak terduga, silahkan pilih berkas dari apl yang berbeda + Tidak ada berkas yang terpilih + Masuk dengan oAuth2 + Menyambungkan ke server oAuth2... + Identitas situs tidak dapat diverfikasi + - Sertifikat server tidak terpercaya + - Sertifikat server kadaluarsa + - Tanggal sertifikat server yang valid adalah di masa depan + - URL tidak cocok dengan nama host dalam sertifikat + Apakah Anda percaya dengan sertifikat ini? + Sertifikat tidak dapat disimpan + Rincian + Sembunyikan + Diterbitkan untuk: + Diterbitkan oleh: + Nama panggilan: + Organisasi: + Unit Organisasi: + Negara: + Negara bagian: + Lokasi: + Masa berlaku: + Dari: + Untuk: + Tanda tangan: + Algoritma: + Ini adalah placeholder + placeholder.txt + Gambar PNG + 389 KB + 18/05/2012 12:23 PM + 12:23:45 + Hanya unggah gambar via WiFi + /UnggahInstan + Perbarui benturan + Berkas jauh %s tidak sinkron dengan berkas lokal. Melanjutkan akan menggantikan konten berkas di server. + Biarkan keduannya + Timpa + Jangan mengunggah + Pratilik gambar + Gambar ini tidak dapat ditampilkan + %1$s tidak dapat disalin ke direktori lokal %2$s + UnggahInsatan Gagal + Unggahan instan gagal + Ringkasan dari semua unggahan instan yang gagal + pilih semua + Ulangi semua yang terpilih + hapus semua yang terpilih dari antrian unggahan + ulangi unggah gambar: + Muat Gambar selengkapnya + Tidak melakukan apapun, Anda tidak sedang online + Pesan Kegagalan: + Silakan periksa konfigurasi server Anda, kemungkinan kuota terlampaui. diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml index 6a2f9873..e7d228b9 100644 --- a/res/values-is/strings.xml +++ b/res/values-is/strings.xml @@ -5,7 +5,6 @@ Stillingar Meira Hjálp - Host nafn netþjóns Notendanafn Lykilorð Skrár diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml index 2242f74e..72061d2c 100644 --- a/res/values-it/strings.xml +++ b/res/values-it/strings.xml @@ -30,7 +30,7 @@ Prova %1$s sul tuo smartphone! Vorrei invitarti ad usare %1$s sul tuo smartphone!⏎\nScarica qui: %2$s Verifica server - Indirizzo del server + Indirizzo server https://... Nome utente Password Prima volta su %1$s? diff --git a/res/values-ja-rJP/strings.xml b/res/values-ja-rJP/strings.xml index 918872c2..3870de62 100644 --- a/res/values-ja-rJP/strings.xml +++ b/res/values-ja-rJP/strings.xml @@ -30,7 +30,7 @@ スマートフォンで %1$s を試してください! スマートフォンで %1$s を利用してみませんか!\nここからダウンロードしてください: %2$s サーバーを確認する - サーバアドレス + サーバーアドレス https://… ユーザー名 パスワード %1$sは初めてですか? diff --git a/res/values-ka-rGE/strings.xml b/res/values-ka-rGE/strings.xml index 56a17fa5..0ff4bee3 100644 --- a/res/values-ka-rGE/strings.xml +++ b/res/values-ka-rGE/strings.xml @@ -16,7 +16,6 @@ დახმარება უკუკავშირი ბეჭედი - სერვერის მისამართი მომხმარებლის სახელი პაროლი ფაილები diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml index 26d42b8e..c18708c9 100644 --- a/res/values-ko/strings.xml +++ b/res/values-ko/strings.xml @@ -28,8 +28,9 @@ 피드백 임프린트 %1$s 을 스마트폰에서 사용해보세요! + 당신을 %1$s 로 초대합니다!\n여기서 받으세요: %2$s 서버 확인 - 서버 주소 + 서버 주소 https://… 사용자 이름 암호 %1$s의 새로운 사용자입니까? @@ -120,6 +121,7 @@ 지원하지 않는 미디어 코덱 미디어 파일을 읽을수 미디어 파일이 제대로 인코드 되지 않았습니다 + 재생 시도 중 시간이 초과됨 미디어 파일을 스트리밍 할수 없습니다 내장된 미디어 플레이어에서는 이 미디어 파일을 재생할수 없습니다 %1$s 를 재생하는 중에 보안오류가 발생함 @@ -134,6 +136,8 @@ 연결됨 연결 테스트 중... 서버 설정이 잘못됨 + 같은 사용자와 서버에 대한 계정이 이미 존재합니다 + 입력된 사용자가 이 계정의 사용자와 일치하지 않음 알 수 없는 오류가 발생하였습니다! 호스트를 찾을 수 없음 서버 인스턴스를 찾을 수 없음 @@ -171,6 +175,7 @@ 원격 파일을 확인할 수 없었습니다 파일 내용이 이미 동기화되었습니다 디렉터리를 만들 수 없었습니다 + 사용할수 없는 문자들: / \\ < > : \" | ? * 잠시 기다려 주십시오 예상하지 못한 오류입니다. 다른 앱에서 파일을 선택하십시오 선택한 파일 없음 @@ -200,7 +205,7 @@ 알고리즘: 이것은 플레이스홀더입니다 placeholder.txt - PNG 파일 + PNG 그림 389 KB 2012/05/18 12:23 PM 12:23:45 @@ -214,6 +219,7 @@ 그림 미리보기 이 그림을 볼수 없습니다 %1$s를 %2$s 로컬 디렉토리로 복사하지 못했습니다. + 자동 업로드가 실패했습니다 자동 업로드 실패함 실패된 자동 업로드 전체 요약 전체 선택 @@ -221,6 +227,7 @@ 선택된 업로드 큐 전체 삭제 이미지 업로드 재시도: 더 많은 사진 불러오기 + 현재 온라인이 아니셔서 자동 업로드를 할수 없습니다 실패 메시지: 서버 설정을 확인해주세요, 아마 업로드 제한을 초과하셨을겁니다. diff --git a/res/values-ku-rIQ/strings.xml b/res/values-ku-rIQ/strings.xml index c40ddc53..5e87456f 100644 --- a/res/values-ku-rIQ/strings.xml +++ b/res/values-ku-rIQ/strings.xml @@ -3,7 +3,6 @@ بارکردن ده‌ستكاری یارمەتی - ناونیشانی ڕاژه ناوی به‌کارهێنه‌ر وشەی تێپەربو بارکردن diff --git a/res/values-lb/strings.xml b/res/values-lb/strings.xml index f7a0fe66..6031cfcf 100644 --- a/res/values-lb/strings.xml +++ b/res/values-lb/strings.xml @@ -13,7 +13,6 @@ App PIN Hëllef Feedback - Server Adress Benotzernumm Passwuert Dateien diff --git a/res/values-lt-rLT/strings.xml b/res/values-lt-rLT/strings.xml index ad283043..ed04b6aa 100644 --- a/res/values-lt-rLT/strings.xml +++ b/res/values-lt-rLT/strings.xml @@ -30,7 +30,6 @@ Išbandykite %1$s savo išmaniajame telefone! Siūlau pabandyti %1$s savo išmaniajame telefone!\nParsisiųskite štai čia: %2$s Patikrinti Serverį - Serverio adresas Prisijungimo vardas Slaptažodis Failai diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml index 37eb6b97..e52b10f1 100644 --- a/res/values-lv/strings.xml +++ b/res/values-lv/strings.xml @@ -14,7 +14,6 @@ Aktivēt tūlītējo augšupielādēšanu Nekavējoties augšupielādēt kameras uzņemtos attēlus Palīdzība - Servera adrese Lietotājvārds Parole Datnes diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml index 720e4da0..2c514f52 100644 --- a/res/values-mk/strings.xml +++ b/res/values-mk/strings.xml @@ -16,7 +16,6 @@ Помош Препорачај на пријател Повратен одговор - Адреса на сервер Корисничко име Лозинка Датотеки diff --git a/res/values-ms-rMY/strings.xml b/res/values-ms-rMY/strings.xml index b2b8fdfe..0ca0b780 100644 --- a/res/values-ms-rMY/strings.xml +++ b/res/values-ms-rMY/strings.xml @@ -9,7 +9,6 @@ Akaun PIN App Bantuan - Alamat pelayan Nama pengguna Kata laluan Fail-fail diff --git a/res/values-nb-rNO/strings.xml b/res/values-nb-rNO/strings.xml index f7c70fd7..48b731b7 100644 --- a/res/values-nb-rNO/strings.xml +++ b/res/values-nb-rNO/strings.xml @@ -10,7 +10,6 @@ Kontoer Last opp bilder tatt med kamera øyeblikkelig Hjelp - Server-adresse Brukernavn Passord Filer diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index 8c06d3ed..f60574b8 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -30,7 +30,7 @@ Probeer %1$s op uw smartphone! Uitnodiging om %1$s op uw smartphone uit te proberen!\nDownload hier: %2$s Controleer server - Server adres + Serveradres https://… Gebruikersnaam Wachtwoord Nieuw bij %1$s? diff --git a/res/values-nn-rNO/strings.xml b/res/values-nn-rNO/strings.xml index 12eba287..0d76c8ec 100644 --- a/res/values-nn-rNO/strings.xml +++ b/res/values-nn-rNO/strings.xml @@ -11,7 +11,6 @@ Last opp kamerabilete med ein gong du tek dei Hjelp Impressum - Tenaradresse Brukarnamn Passord Filer diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml index 7d9f60a6..d3a28367 100644 --- a/res/values-pa/strings.xml +++ b/res/values-pa/strings.xml @@ -15,7 +15,6 @@ ਲਾਗ ਰੱਖਣਾ ਚਾਲੂ ਲਾਗ ਰੱਖਣ ਅਤੀਤ ਅਤੀਤ ਹਟਆਓ - ਸਰਵਰ ਐਡਰੈਸ ਯੂਜ਼ਰ-ਨਾਂ ਪਾਸਵਰ %1$s ਲਈ ਨਵੇਂ ਹੋ? diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index 6dd15a0a..de65dbf7 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -30,7 +30,7 @@ Wypróbuj %1$s na swoim smartphonie! Chcę was zaprosić do korzystania z %1$ s na twoim smartfonie!\nPobierz tutaj: %2$s Sprawdź serwer - Adres Serwera + Adres serwera https://... Nazwa użytkownika Hasło Nowe %1$s? @@ -175,6 +175,7 @@ Nie można sprawdzić zdalnego pliku Zawartość pliku została już synchronizowana Nie można utworzyć katalogu + Znaki zabronione: / \\ < > : \" | ? * Poczekaj chwilę Nieoczekiwany problem; spróbuj wybrać plik z innej aplikacji Nie wybrano żadnych plików @@ -218,6 +219,7 @@ Podgląd Obraz nie może zostać wyświetlony %1$s nie może zostać skopiowany do lokalnego %2$s katalogu + InstantUpload nie powiódł się Błąd automatycznego przesyłania Podsumowanie wszystkich nieudanych transferów zaznacz wszystkie diff --git a/res/values-pt-rBR/strings.xml b/res/values-pt-rBR/strings.xml index c43a22b4..072c19d0 100644 --- a/res/values-pt-rBR/strings.xml +++ b/res/values-pt-rBR/strings.xml @@ -30,7 +30,7 @@ Tentar %1$s em seu smartfone! Gostaria de lhe convidar para usar %1$s em seu smartfone!\nBaixe aqui: %2$s Verificar Servidor - Endereço do servidor + Endereço do servidor https://... Nome de usuário Senha Novo para %1$s? diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index f082b521..8cc99853 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -30,7 +30,7 @@ Experimente %1$s no seu smartphone! Quero convidá-lo para experimentar %1$s no seu smartphone!\nDescarregue aqui: %2$s Verificar Servidor - Endereço do servidor + Endereço do servidor https://.. Nome de Utilizador Palavra-passe Novo em %1$s? diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml index a35bbdc5..05692777 100644 --- a/res/values-ro/strings.xml +++ b/res/values-ro/strings.xml @@ -11,7 +11,6 @@ Administrare conturi Activează încărcarea instant Ajutor - Adresa server-ului Nume utilizator Parolă Fișiere diff --git a/res/values-ru-rRU/strings.xml b/res/values-ru-rRU/strings.xml index b7d3c62a..6675918b 100644 --- a/res/values-ru-rRU/strings.xml +++ b/res/values-ru-rRU/strings.xml @@ -16,7 +16,6 @@ Включить немедленную загрузку Мгновенно загрузить фотографии, сделанные камерой Помощь - URL Имя пользователя Пароль Я новичок в %1$s diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index ccc16997..ed9a7b84 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -30,7 +30,7 @@ Попробуйте %1$s на вашем смартфоне! Хочу предложить вам пользоваться %1$s на вашем смартфоне!\nДля загрузки: %2$s Проверить сервер - Адрес сервера + Адрес сервера https://... Пользователь Пароль Впервые с %1$s? diff --git a/res/values-si-rLK/strings.xml b/res/values-si-rLK/strings.xml index 59a85318..7f0cf887 100644 --- a/res/values-si-rLK/strings.xml +++ b/res/values-si-rLK/strings.xml @@ -12,7 +12,6 @@ ක්‍ෂණික උඩුගත කිරීම් සක්‍රිය කරන්න කැමරාවෙන් ගත් රූප ක්‍ෂණිකව උඩුගත කරන්න උදව් - සේවාදායකයේ ලිපිනය පරිශීලක නම මුර පදය ගොනු diff --git a/res/values-sk-rSK/strings.xml b/res/values-sk-rSK/strings.xml index 79a72f18..996544ed 100644 --- a/res/values-sk-rSK/strings.xml +++ b/res/values-sk-rSK/strings.xml @@ -30,7 +30,7 @@ Skúste %1$s na vašom telefóne! Chcem vás pozvať na používanie %1$s na vašom smartphone!\nNa stiahnutie tu: %2$s Skontrolovať Server - Adresa servera + Adresa servera https://... Používateľské meno Heslo Ste nový v %1$s? diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml index c757504a..1eb12a48 100644 --- a/res/values-sk/strings.xml +++ b/res/values-sk/strings.xml @@ -1,2 +1,7 @@ - + + Nastavenia + Všeobecné + Stiahnuť + Zrušiť + diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml index 17616d61..b951d634 100644 --- a/res/values-sl/strings.xml +++ b/res/values-sl/strings.xml @@ -30,7 +30,7 @@ Preizkusi %1$s na pametnem telefonu! Želim ti predstaviti program %1$s za pametni telefon!\nPrejmeš ga lahko na: %2$s Preveri strežnik - Naslov strežnika + Naslov strežnika https://… Uporabniško ime Geslo Ali ste novi uporabnik sistema %1$s? diff --git a/res/values-sr-rSP/strings.xml b/res/values-sr-rSP/strings.xml index 663c462a..eefd16d8 100644 --- a/res/values-sr-rSP/strings.xml +++ b/res/values-sr-rSP/strings.xml @@ -2,16 +2,52 @@ Pošalji Fajlovi + Novi folder Podešavanja + Detaljnije + Opšte + Nalozi + Upravljaj nalozima Pomoć Korisničko ime Lozinka Fajlovi Pošalji + Nalog nije nađen + Šalje se + Veličina: + Tip: Preuzmi Da Ne Otkaži Greška Izmeni lozinku + Ukloni nalog + Novi nalog + Otpremanje... + Uspešno otpremljeno + Otpremanje nije uspelo + Preuzimanje... + Uspešno preuzeto + Preuzimanje nije uspelo + Odaberite nalog + Nema konekcije + Sigurna konekcija nije dostupna. + Konekcija uspostavljena + Preimenij + Ukloni + Da li želite da uklonite %1$s ? + Uklanjanje je uspelo + Uklanjanje nije uspelo + Molim pričekajte + Detaljnije + Sakrij + Organizacija: + Država: + Lokacija: + Od: + Za: + Potpis: + Zadrži oboje diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml index 446a6ee9..83ce42df 100644 --- a/res/values-sr/strings.xml +++ b/res/values-sr/strings.xml @@ -10,7 +10,6 @@ Налози Тренутно отпремај фотографије сликане камером Помоћ - Адреса сервера Корисничко име Лозинка Фајлови diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml index 9b4a1366..af6e2590 100644 --- a/res/values-sv/strings.xml +++ b/res/values-sv/strings.xml @@ -30,7 +30,6 @@ Försök %1$s på din smarttelefon! Jag vill bjuda in dig till att anända %1$s på din smarttelefon!\nLadda ner här: %2$s Kontrollera Server - Serveradress Användarnamn Lösenord Ny på %1$s? diff --git a/res/values-ta-rLK/strings.xml b/res/values-ta-rLK/strings.xml index 9b888c44..2f1f51cc 100644 --- a/res/values-ta-rLK/strings.xml +++ b/res/values-ta-rLK/strings.xml @@ -15,7 +15,6 @@ உடனடி பதிவேற்றலை இயலுமைப்படுத்துக கமராவினால் எடுக்கப்பட்ட படங்கள் உடனடியாக பதிவேற்றப்பட்டன உதவி - சேவையக முகவரி பயனாளர் பெயர் கடவுச்சொல் கோப்புகள் diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml index b827eda2..ca33f4ea 100644 --- a/res/values-te/strings.xml +++ b/res/values-te/strings.xml @@ -3,7 +3,6 @@ అమరికలు మరిన్ని సహాయం - సేవకి చిరునామా వాడుకరి పేరు సంకేతపదం అవును diff --git a/res/values-th-rTH/strings.xml b/res/values-th-rTH/strings.xml index 521ad4a8..77451fac 100644 --- a/res/values-th-rTH/strings.xml +++ b/res/values-th-rTH/strings.xml @@ -15,7 +15,6 @@ เปิดใช้งานระบบอัพโหลดได้ทันที อัพโหลดรูปภาพจากกล้องขึ้นไปทันที ช่วยเหลือ - ที่อยู่เซิร์ฟเวอร์ ชื่อผู้ใช้ รหัสผ่าน ไฟล์ diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml index 52aa97a6..5db0dd50 100644 --- a/res/values-tr/strings.xml +++ b/res/values-tr/strings.xml @@ -3,11 +3,11 @@ %1$s Android Uygulaması sürüm %1$s Hesabı yenile - Dosya yükle + Yükle Diğer uygulamalardan içerik Dosyalar ile aç - Klasör oluştur + Dizin oluştur Ayarlar Detaylar Genel @@ -30,7 +30,7 @@ %1$s uygulamasını akıllı telefonunda dene! Sana, akıllı telefonunda kullanmak üzere %1$s daveti yapıyorum!\nBuradan indirebilirsin: %2$s Sunucuyu kontrol et - Sunucu Adresi + Sunucu Adresi https://… Kullanıcı Adi: Şifre: %1$s senin için yeni mi? @@ -38,8 +38,8 @@ Bağlan Yükle Yükleme dizinini seçiniz: - Hesap bulunamadi - Cihazınızda %1$s hesabı bulunmamaktadır. Lütfen öncelikle bir hesap ayarı giriniz. + Hesap bulunamadı + Cihazınızda %1$s hesabı bulunmamaktadır. Lütfen öncelikle bir hesap ayarlayın. Kurulum Çıkış Yüklenecek içerik yok @@ -47,7 +47,7 @@ %1$s, paylaşılan içeriğe erişim izni vermiyor Yükleniyor Klasörde dosya yok. Yeni dosyalar yükle\'ye tıklayarak eklenebilir. - Ek bilgileri görmek için dosyaya tıklayınız. + Ek bilgileri görmek için dosyaya dokunun. Boyut: Tür: Oluşturulma: @@ -86,12 +86,12 @@ Henüz indirilemedi Hesap seçiniz Eşitleme başarısız - %1$s Senkronizasyonu tamamlanamadı + %1$s eşitlemesi tamamlanamadı %1$s için geçersiz parola Çakışma bulundu - %1$d korumalı senkronizasyon dosyası, senkronize edilemedi - Korunan dosya senkronizasyonu başarısız - %1$d dosya senkronize edilemedi (%2$d hata) + %1$d korumalı eşitleme dosyası, eşitlenemedi + Korunan dosya eşitlemesi başarısız + %1$d dosya eşitlenemedi (%2$d çakışma) Bazı yerel dosyalar unutuldu %1$d dosya %2$s dizinine kopyalanamadı 1.3.16 sürümünden sonra, bu aygıttan yüklenen dosyalar bir dosya birden fazla hesapla eşitlendiğinde veri kaybının önlenebilmesi için %1$s yerel klasörüne kopyalanır.\n\nBu değişiklikten dolayı, bu uygulamanın yüklenmiş tüm önceki sürümündeki dosyalar %2$s klasörüne kopyalandı. Ancak hesap eşitlenmesi sırasında bu işlemin tamamlanmasını engelleyen bir hata oluştu. Dosyayı/dosyaları olduğu gibi bırakabilir ve %3$s bağlantısını kaldırabilirsiniz veya dosyayı/dosyaları %1$s dizinine taşıyıp %4$s bağlantılarını koruyabilirsiniz.\n\nAşağıda listelenenler yerel dosyalar ve bağlı oldukları %5$s içerisindeki uzak dosyalardır. @@ -127,9 +127,9 @@ %1$s oynatılmaya çalışılırken güvenlik hatası oluştu %1$s oynatılmaya çalışılırken girdi hatası oluştu %1$s oynatılmaya çalışılırken beklenmeyen bir hata oluştu - Başa sar butonu - Oynat veya duraklat butonu - Hızlı ileri butonu + Başa sar düğmesi + Oynat veya duraklat düğmesi + Hızlı ileri düğmesi Giriş için deneniyor Ağ bağlantısı yok Günvenli bağlantı mevcut değil. @@ -140,7 +140,7 @@ Girilen kullanıcı bu hesabın kullanıcısı ile eşleşmiyor Bilinmeyen hata oluştu. Anabilgisayar bulunamadı - sunucu servisi bulunamadı. + Sunucu örneği bulunamadı. Sunucu çok geç cevap veriyor Hatalı biçimlendirilmiş URL SSL başlatılmasında hata @@ -173,7 +173,7 @@ Yerel kopya adlandırılamaz; farklı bir ad deneyin Yeniden adlandırılma tamamlanmadı Dosya teslim edilemedi - Dosyalar başarıyla senkronize edildi + Dosya içerikleri zaten eşitlenmiş Dizin oluşturulamadı Yasaklı karakterler: / \\ < > : \" | ? * Bir süre bekleyin @@ -212,7 +212,7 @@ Resimleri sadece WiFi bağlantısında yükle /AnındaYükle Çakışmayı güncelle - Uzaktaki %s dosyası, yerel dosya ile senkronize edilemedi. işleme devam etmek sunucudaki dosyanın içeriğini değiştirecektir. + Uzaktaki %s dosyası, yerel dosya ile eşitlenemedi. İşleme devam etmek sunucudaki dosyanın içeriğini değiştirecektir. İkisini de koru Üzerine yaz Yükleme diff --git a/res/values-ug/strings.xml b/res/values-ug/strings.xml index 41798ce2..16a441ad 100644 --- a/res/values-ug/strings.xml +++ b/res/values-ug/strings.xml @@ -9,7 +9,6 @@ ھېساباتلار ياردەم قايتۇرما ئىنكاس - مۇلازىمېتىر ئادرىسى ئىشلەتكۈچى ئاتى ئىم ھۆججەتلەر diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml index 749321ea..a3adb7db 100644 --- a/res/values-uk/strings.xml +++ b/res/values-uk/strings.xml @@ -17,7 +17,6 @@ Допомога Зворотній зв\'язок Відбиток - Адреса сервера Ім\'я користувача Пароль Файли diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml new file mode 100644 index 00000000..c757504a --- /dev/null +++ b/res/values-ur/strings.xml @@ -0,0 +1,2 @@ + + diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml index d5f060bf..2334d654 100644 --- a/res/values-vi/strings.xml +++ b/res/values-vi/strings.xml @@ -25,7 +25,6 @@ Xóa lịch sử Giúp đỡ Kiểm tra máy chủ - Địa chỉ máy chủ Tên người dùng Mật khẩu Lần đầu mới đến %1$s? diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index 366d2e3b..2b83a782 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -24,7 +24,6 @@ 反馈 版本说明 检查服务器 - 服务器地址 用户名 密码 文件 diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml index 2b14a233..bc0a2554 100644 --- a/res/values-zh-rTW/strings.xml +++ b/res/values-zh-rTW/strings.xml @@ -27,7 +27,6 @@ 反饋 法律聲明 檢查伺服器 - 伺服器位址 使用者名稱 密碼 新增到 %1$s? diff --git a/res/values/strings.xml b/res/values/strings.xml index 05c7ecf8..2c06bb82 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -34,7 +34,7 @@ "I want to invite you to use %1$s on your smartphone!\nDownload here: %2$s" Check Server - Server address + Server address https://… Username Password New to %1$s? diff --git a/src/com/owncloud/android/authentication/AuthenticatorActivity.java b/src/com/owncloud/android/authentication/AuthenticatorActivity.java index 85f4914a..456e284b 100644 --- a/src/com/owncloud/android/authentication/AuthenticatorActivity.java +++ b/src/com/owncloud/android/authentication/AuthenticatorActivity.java @@ -57,13 +57,13 @@ import com.owncloud.android.oc_framework.accounts.AccountTypeUtils; import com.owncloud.android.oc_framework.accounts.OwnCloudAccount; import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory; import com.owncloud.android.oc_framework.network.webdav.WebdavClient; -import com.owncloud.android.operations.ExistenceCheckOperation; import com.owncloud.android.operations.OAuth2GetAccessToken; import com.owncloud.android.oc_framework.operations.OnRemoteOperationListener; import com.owncloud.android.operations.OwnCloudServerCheckOperation; import com.owncloud.android.oc_framework.operations.RemoteOperation; import com.owncloud.android.oc_framework.operations.RemoteOperationResult; import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode; +import com.owncloud.android.oc_framework.operations.remote.ExistenceCheckRemoteOperation; import com.owncloud.android.ui.dialog.SamlWebViewDialog; import com.owncloud.android.ui.dialog.SslValidatorDialog; import com.owncloud.android.ui.dialog.SslValidatorDialog.OnSslValidatorListener; @@ -131,7 +131,7 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList private final Handler mHandler = new Handler(); private Thread mOperationThread; private OwnCloudServerCheckOperation mOcServerChkOperation; - private ExistenceCheckOperation mAuthCheckOperation; + private ExistenceCheckRemoteOperation mAuthCheckOperation; private RemoteOperationResult mLastSslUntrustedServerResult; private Uri mNewCapturedUriFromOAuth2Redirection; @@ -716,7 +716,7 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList showDialog(DIALOG_LOGIN_PROGRESS); /// test credentials accessing the root folder - mAuthCheckOperation = new ExistenceCheckOperation("", this, false); + mAuthCheckOperation = new ExistenceCheckRemoteOperation("", this, false); WebdavClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, true); client.setBasicCredentials(username, password); mOperationThread = mAuthCheckOperation.execute(client, this, mHandler); @@ -765,7 +765,7 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList String webdav_path = AccountUtils.getWebdavPath(mDiscoveredVersion, mAuthTokenType); /// test credentials accessing the root folder - mAuthCheckOperation = new ExistenceCheckOperation("", this, false); + mAuthCheckOperation = new ExistenceCheckRemoteOperation("", this, false); WebdavClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, false); mOperationThread = mAuthCheckOperation.execute(client, this, mHandler); @@ -785,12 +785,12 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList } else if (operation instanceof OAuth2GetAccessToken) { onGetOAuthAccessTokenFinish((OAuth2GetAccessToken)operation, result); - } else if (operation instanceof ExistenceCheckOperation) { + } else if (operation instanceof ExistenceCheckRemoteOperation) { if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(mAuthTokenType)) { onSamlBasedFederatedSingleSignOnAuthorizationStart(operation, result); } else { - onAuthorizationCheckFinish((ExistenceCheckOperation)operation, result); + onAuthorizationCheckFinish((ExistenceCheckRemoteOperation)operation, result); } } } @@ -1084,7 +1084,7 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList /// time to test the retrieved access token on the ownCloud server mAuthToken = ((OAuth2GetAccessToken)operation).getResultTokenMap().get(OAuth2Constants.KEY_ACCESS_TOKEN); Log_OC.d(TAG, "Got ACCESS TOKEN: " + mAuthToken); - mAuthCheckOperation = new ExistenceCheckOperation("", this, false); + mAuthCheckOperation = new ExistenceCheckRemoteOperation("", this, false); WebdavClient client = OwnCloudClientFactory.createOwnCloudClient(Uri.parse(mHostBaseUrl + webdav_path), this, true); client.setBearerCredentials(mAuthToken); mAuthCheckOperation.execute(client, this, mHandler); @@ -1105,7 +1105,7 @@ implements OnRemoteOperationListener, OnSslValidatorListener, OnFocusChangeList * @param operation Access check performed. * @param result Result of the operation. */ - private void onAuthorizationCheckFinish(ExistenceCheckOperation operation, RemoteOperationResult result) { + private void onAuthorizationCheckFinish(ExistenceCheckRemoteOperation operation, RemoteOperationResult result) { try { dismissDialog(DIALOG_LOGIN_PROGRESS); } catch (IllegalArgumentException e) { diff --git a/src/com/owncloud/android/files/managers/OCNotificationManager.java b/src/com/owncloud/android/files/managers/OCNotificationManager.java index 11a8c377..47fb491d 100644 --- a/src/com/owncloud/android/files/managers/OCNotificationManager.java +++ b/src/com/owncloud/android/files/managers/OCNotificationManager.java @@ -22,6 +22,7 @@ import java.util.HashMap; import java.util.Map; import com.owncloud.android.R; +import com.owncloud.android.utils.DisplayUtils; import android.app.Notification; import android.app.NotificationManager; @@ -101,7 +102,7 @@ public class OCNotificationManager { switch (type) { case NOTIFICATION_SIMPLE: - notification = new Notification(R.drawable.icon, data.getText(), System.currentTimeMillis()); + notification = new Notification(DisplayUtils.getSeasonalIconId(), data.getText(), System.currentTimeMillis()); break; case NOTIFICATION_PROGRESS: notification = new Notification(); @@ -139,7 +140,7 @@ public class OCNotificationManager { false); return true; case NOTIFICATION_SIMPLE: - pair.mNotificaiton = new Notification(R.drawable.icon, + pair.mNotificaiton = new Notification(DisplayUtils.getSeasonalIconId(), data.getText(), System.currentTimeMillis()); mNM.notify(notification_id, pair.mNotificaiton); return true; diff --git a/src/com/owncloud/android/files/services/FileDownloader.java b/src/com/owncloud/android/files/services/FileDownloader.java index 232a042a..5d2a8246 100644 --- a/src/com/owncloud/android/files/services/FileDownloader.java +++ b/src/com/owncloud/android/files/services/FileDownloader.java @@ -43,6 +43,7 @@ import com.owncloud.android.ui.activity.FileActivity; import com.owncloud.android.ui.activity.FileDisplayActivity; import com.owncloud.android.ui.preview.PreviewImageActivity; import com.owncloud.android.ui.preview.PreviewImageFragment; +import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.Log_OC; import android.accounts.Account; @@ -409,12 +410,12 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis private void notifyDownloadStart(DownloadFileOperation download) { /// create status notification with a progress bar mLastPercent = 0; - mNotification = new Notification(R.drawable.icon, getString(R.string.downloader_download_in_progress_ticker), System.currentTimeMillis()); + mNotification = new Notification(DisplayUtils.getSeasonalIconId(), getString(R.string.downloader_download_in_progress_ticker), System.currentTimeMillis()); mNotification.flags |= Notification.FLAG_ONGOING_EVENT; mNotification.contentView = new RemoteViews(getApplicationContext().getPackageName(), R.layout.progressbar_layout); mNotification.contentView.setProgressBar(R.id.status_progress, 100, 0, download.getSize() < 0); mNotification.contentView.setTextViewText(R.id.status_text, String.format(getString(R.string.downloader_download_in_progress_content), 0, new File(download.getSavePath()).getName())); - mNotification.contentView.setImageViewResource(R.id.status_icon, R.drawable.icon); + mNotification.contentView.setImageViewResource(R.id.status_icon, DisplayUtils.getSeasonalIconId()); /// includes a pending intent in the notification showing the details view of the file Intent showDetailsIntent = null; @@ -439,10 +440,10 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, String fileName) { int percent = (int)(100.0*((double)totalTransferredSoFar)/((double)totalToTransfer)); if (percent != mLastPercent) { - mNotification.contentView.setProgressBar(R.id.status_progress, 100, percent, totalToTransfer < 0); - String text = String.format(getString(R.string.downloader_download_in_progress_content), percent, fileName); - mNotification.contentView.setTextViewText(R.id.status_text, text); - mNotificationManager.notify(R.string.downloader_download_in_progress_ticker, mNotification); + mNotification.contentView.setProgressBar(R.id.status_progress, 100, percent, totalToTransfer < 0); + String text = String.format(getString(R.string.downloader_download_in_progress_content), percent, fileName); + mNotification.contentView.setTextViewText(R.id.status_text, text); + mNotificationManager.notify(R.string.downloader_download_in_progress_ticker, mNotification); } mLastPercent = percent; } @@ -468,7 +469,7 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis if (!downloadResult.isCancelled()) { int tickerId = (downloadResult.isSuccess()) ? R.string.downloader_download_succeeded_ticker : R.string.downloader_download_failed_ticker; int contentId = (downloadResult.isSuccess()) ? R.string.downloader_download_succeeded_content : R.string.downloader_download_failed_content; - Notification finalNotification = new Notification(R.drawable.icon, getString(tickerId), System.currentTimeMillis()); + Notification finalNotification = new Notification(DisplayUtils.getSeasonalIconId(), getString(tickerId), System.currentTimeMillis()); finalNotification.flags |= Notification.FLAG_AUTO_CANCEL; boolean needsToUpdateCredentials = (downloadResult.getCode() == ResultCode.UNAUTHORIZED || // (downloadResult.isTemporalRedirection() && downloadResult.isIdPRedirection() diff --git a/src/com/owncloud/android/files/services/FileUploader.java b/src/com/owncloud/android/files/services/FileUploader.java index 61f61791..35952634 100644 --- a/src/com/owncloud/android/files/services/FileUploader.java +++ b/src/com/owncloud/android/files/services/FileUploader.java @@ -28,36 +28,31 @@ import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import org.apache.http.HttpStatus; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.MultiStatus; -import org.apache.jackrabbit.webdav.client.methods.PropFindMethod; - import com.owncloud.android.R; import com.owncloud.android.authentication.AuthenticatorActivity; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.db.DbHandler; -import com.owncloud.android.operations.ChunkedUploadFileOperation; import com.owncloud.android.operations.CreateFolderOperation; -import com.owncloud.android.operations.ExistenceCheckOperation; +import com.owncloud.android.oc_framework.operations.RemoteFile; import com.owncloud.android.oc_framework.operations.RemoteOperation; import com.owncloud.android.oc_framework.operations.RemoteOperationResult; import com.owncloud.android.operations.UploadFileOperation; import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode; +import com.owncloud.android.oc_framework.operations.remote.ExistenceCheckRemoteOperation; +import com.owncloud.android.oc_framework.operations.remote.ReadRemoteFileOperation; import com.owncloud.android.oc_framework.utils.OwnCloudVersion; import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener; import com.owncloud.android.oc_framework.accounts.OwnCloudAccount; import com.owncloud.android.oc_framework.network.webdav.OwnCloudClientFactory; import com.owncloud.android.oc_framework.network.webdav.WebdavClient; -import com.owncloud.android.oc_framework.network.webdav.WebdavEntry; -import com.owncloud.android.oc_framework.network.webdav.WebdavUtils; import com.owncloud.android.ui.activity.FailedUploadActivity; import com.owncloud.android.ui.activity.FileActivity; import com.owncloud.android.ui.activity.FileDisplayActivity; import com.owncloud.android.ui.activity.InstantUploadActivity; import com.owncloud.android.ui.preview.PreviewImageActivity; import com.owncloud.android.ui.preview.PreviewImageFragment; +import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.Log_OC; import android.accounts.Account; @@ -251,7 +246,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe files[i] = obtainNewOCFileToUpload(remotePaths[i], localPaths[i], ((mimeTypes != null) ? mimeTypes[i] : (String) null), storageManager); if (files[i] == null) { - // TODO @andomaex add failure Notiification + // TODO @andomaex add failure Notification return Service.START_NOT_STICKY; } } @@ -265,12 +260,8 @@ public class FileUploader extends Service implements OnDatatransferProgressListe try { for (int i = 0; i < files.length; i++) { uploadKey = buildRemoteName(account, files[i].getRemotePath()); - if (chunked) { - newUpload = new ChunkedUploadFileOperation(account, files[i], isInstant, forceOverwrite, - localAction); - } else { - newUpload = new UploadFileOperation(account, files[i], isInstant, forceOverwrite, localAction); - } + newUpload = new UploadFileOperation(account, files[i], chunked, isInstant, forceOverwrite, localAction, + getApplicationContext()); if (isInstant) { newUpload.setRemoteFolderToBeCreated(); } @@ -559,7 +550,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe * @return An {@link OCFile} instance corresponding to the folder where the file will be uploaded. */ private RemoteOperationResult grantFolderExistence(String pathToGrant) { - RemoteOperation operation = new ExistenceCheckOperation(pathToGrant, this, false); + RemoteOperation operation = new ExistenceCheckRemoteOperation(pathToGrant, this, false); RemoteOperationResult result = operation.execute(mUploadClient); if (!result.isSuccess() && result.getCode() == ResultCode.FILE_NOT_FOUND && mCurrentUpload.isRemoteFolderToBeCreated()) { operation = new CreateFolderOperation( pathToGrant, @@ -614,40 +605,15 @@ public class FileUploader extends Service implements OnDatatransferProgressListe long syncDate = System.currentTimeMillis(); file.setLastSyncDateForData(syncDate); - // / new PROPFIND to keep data consistent with server in theory, should - // return the same we already have - PropFindMethod propfind = null; - RemoteOperationResult result = null; - try { - propfind = new PropFindMethod(mUploadClient.getBaseUri() + WebdavUtils.encodePath(mCurrentUpload.getRemotePath()), - DavConstants.PROPFIND_ALL_PROP, - DavConstants.DEPTH_0); - int status = mUploadClient.executeMethod(propfind); - boolean isMultiStatus = (status == HttpStatus.SC_MULTI_STATUS); - if (isMultiStatus) { - MultiStatus resp = propfind.getResponseBodyAsMultiStatus(); - WebdavEntry we = new WebdavEntry(resp.getResponses()[0], mUploadClient.getBaseUri().getPath()); - updateOCFile(file, we); - file.setLastSyncDateForProperties(syncDate); - - } else { - mUploadClient.exhaustResponse(propfind.getResponseBodyAsStream()); - } - - result = new RemoteOperationResult(isMultiStatus, status, propfind.getResponseHeaders()); - Log_OC.i(TAG, "Update: synchronizing properties for uploaded " + mCurrentUpload.getRemotePath() + ": " - + result.getLogMessage()); - - } catch (Exception e) { - result = new RemoteOperationResult(e); - Log_OC.e(TAG, "Update: synchronizing properties for uploaded " + mCurrentUpload.getRemotePath() + ": " - + result.getLogMessage(), e); - - } finally { - if (propfind != null) - propfind.releaseConnection(); + // new PROPFIND to keep data consistent with server + // in theory, should return the same we already have + ReadRemoteFileOperation operation = new ReadRemoteFileOperation(mCurrentUpload.getRemotePath()); + RemoteOperationResult result = operation.execute(mUploadClient); + if (result.isSuccess()) { + updateOCFile(file, result.getData().get(0)); + file.setLastSyncDateForProperties(syncDate); } - + // / maybe this would be better as part of UploadFileOperation... or // maybe all this method if (mCurrentUpload.wasRenamed()) { @@ -664,13 +630,13 @@ public class FileUploader extends Service implements OnDatatransferProgressListe mStorageManager.saveFile(file); } - private void updateOCFile(OCFile file, WebdavEntry we) { - file.setCreationTimestamp(we.createTimestamp()); - file.setFileLength(we.contentLength()); - file.setMimetype(we.contentType()); - file.setModificationTimestamp(we.modifiedTimestamp()); - file.setModificationTimestampAtLastSyncForData(we.modifiedTimestamp()); - // file.setEtag(mCurrentUpload.getEtag()); // TODO Etag, where available + private void updateOCFile(OCFile file, RemoteFile remoteFile) { + file.setCreationTimestamp(remoteFile.getCreationTimestamp()); + file.setFileLength(remoteFile.getLength()); + file.setMimetype(remoteFile.getMimeType()); + file.setModificationTimestamp(remoteFile.getModifiedTimestamp()); + file.setModificationTimestampAtLastSyncForData(remoteFile.getModifiedTimestamp()); + // file.setEtag(remoteFile.getEtag()); // TODO Etag, where available } private OCFile obtainNewOCFileToUpload(String remotePath, String localPath, String mimeType, @@ -714,7 +680,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe private void notifyUploadStart(UploadFileOperation upload) { // / create status notification with a progress bar mLastPercent = 0; - mNotification = new Notification(R.drawable.icon, getString(R.string.uploader_upload_in_progress_ticker), + mNotification = new Notification(DisplayUtils.getSeasonalIconId(), getString(R.string.uploader_upload_in_progress_ticker), System.currentTimeMillis()); mNotification.flags |= Notification.FLAG_ONGOING_EVENT; mDefaultNotificationContentView = mNotification.contentView; @@ -723,7 +689,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe mNotification.contentView.setProgressBar(R.id.status_progress, 100, 0, false); mNotification.contentView.setTextViewText(R.id.status_text, String.format(getString(R.string.uploader_upload_in_progress_content), 0, upload.getFileName())); - mNotification.contentView.setImageViewResource(R.id.status_icon, R.drawable.icon); + mNotification.contentView.setImageViewResource(R.id.status_icon, DisplayUtils.getSeasonalIconId()); /// includes a pending intent in the notification showing the details view of the file Intent showDetailsIntent = new Intent(this, FileDisplayActivity.class); @@ -791,6 +757,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe } showDetailsIntent.putExtra(FileActivity.EXTRA_FILE, upload.getFile()); showDetailsIntent.putExtra(FileActivity.EXTRA_ACCOUNT, upload.getAccount()); + showDetailsIntent.putExtra(FileActivity.EXTRA_FROM_NOTIFICATION, true); showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); mNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), (int) System.currentTimeMillis(), showDetailsIntent, 0); @@ -810,7 +777,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe // / fail -> explicit failure notification mNotificationManager.cancel(R.string.uploader_upload_in_progress_ticker); - Notification finalNotification = new Notification(R.drawable.icon, + Notification finalNotification = new Notification(DisplayUtils.getSeasonalIconId(), getString(R.string.uploader_upload_failed_ticker), System.currentTimeMillis()); finalNotification.flags |= Notification.FLAG_AUTO_CANCEL; String content = null; diff --git a/src/com/owncloud/android/operations/ChunkedUploadFileOperation.java b/src/com/owncloud/android/operations/ChunkedUploadFileOperation.java deleted file mode 100644 index fd8a5a6d..00000000 --- a/src/com/owncloud/android/operations/ChunkedUploadFileOperation.java +++ /dev/null @@ -1,97 +0,0 @@ -/* ownCloud Android client application - * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2012-2013 ownCloud Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License 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 . - * - */ - -package com.owncloud.android.operations; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.channels.FileChannel; -import java.util.Random; - -import org.apache.commons.httpclient.HttpException; -import org.apache.commons.httpclient.methods.PutMethod; - -import com.owncloud.android.datamodel.OCFile; -import com.owncloud.android.oc_framework.network.ProgressiveDataTransferer; -import com.owncloud.android.oc_framework.network.webdav.ChunkFromFileChannelRequestEntity; -import com.owncloud.android.oc_framework.network.webdav.WebdavClient; -import com.owncloud.android.oc_framework.network.webdav.WebdavUtils; -import com.owncloud.android.utils.Log_OC; - - -import android.accounts.Account; - - -public class ChunkedUploadFileOperation extends UploadFileOperation { - - private static final long CHUNK_SIZE = 1024000; - private static final String OC_CHUNKED_HEADER = "OC-Chunked"; - private static final String TAG = ChunkedUploadFileOperation.class.getSimpleName(); - - public ChunkedUploadFileOperation( Account account, - OCFile file, - boolean isInstant, - boolean forceOverwrite, - int localBehaviour) { - - super(account, file, isInstant, forceOverwrite, localBehaviour); - } - - @Override - protected int uploadFile(WebdavClient client) throws HttpException, IOException { - int status = -1; - - FileChannel channel = null; - RandomAccessFile raf = null; - try { - File file = new File(getStoragePath()); - raf = new RandomAccessFile(file, "r"); - channel = raf.getChannel(); - mEntity = new ChunkFromFileChannelRequestEntity(channel, getMimeType(), CHUNK_SIZE, file); - ((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(getDataTransferListeners()); - long offset = 0; - String uriPrefix = client.getBaseUri() + WebdavUtils.encodePath(getRemotePath()) + "-chunking-" + Math.abs((new Random()).nextInt(9000)+1000) + "-" ; - long chunkCount = (long) Math.ceil((double)file.length() / CHUNK_SIZE); - for (int chunkIndex = 0; chunkIndex < chunkCount ; chunkIndex++, offset += CHUNK_SIZE) { - if (mPutMethod != null) { - mPutMethod.releaseConnection(); // let the connection available for other methods - } - mPutMethod = new PutMethod(uriPrefix + chunkCount + "-" + chunkIndex); - mPutMethod.addRequestHeader(OC_CHUNKED_HEADER, OC_CHUNKED_HEADER); - ((ChunkFromFileChannelRequestEntity)mEntity).setOffset(offset); - mPutMethod.setRequestEntity(mEntity); - status = client.executeMethod(mPutMethod); - client.exhaustResponse(mPutMethod.getResponseBodyAsStream()); - Log_OC.d(TAG, "Upload of " + getStoragePath() + " to " + getRemotePath() + ", chunk index " + chunkIndex + ", count " + chunkCount + ", HTTP result status " + status); - if (!isSuccess(status)) - break; - } - - } finally { - if (channel != null) - channel.close(); - if (raf != null) - raf.close(); - if (mPutMethod != null) - mPutMethod.releaseConnection(); // let the connection available for other methods - } - return status; - } - -} diff --git a/src/com/owncloud/android/operations/DownloadFileOperation.java b/src/com/owncloud/android/operations/DownloadFileOperation.java index eb45d4ba..8d89f636 100644 --- a/src/com/owncloud/android/operations/DownloadFileOperation.java +++ b/src/com/owncloud/android/operations/DownloadFileOperation.java @@ -17,28 +17,18 @@ package com.owncloud.android.operations; -import java.io.BufferedInputStream; import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.HttpException; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.http.HttpStatus; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener; import com.owncloud.android.oc_framework.network.webdav.WebdavClient; -import com.owncloud.android.oc_framework.network.webdav.WebdavUtils; -import com.owncloud.android.oc_framework.operations.OperationCancelledException; +import com.owncloud.android.oc_framework.operations.RemoteFile; import com.owncloud.android.oc_framework.operations.RemoteOperation; import com.owncloud.android.oc_framework.operations.RemoteOperationResult; +import com.owncloud.android.oc_framework.operations.remote.DownloadRemoteFileOperation; import com.owncloud.android.utils.FileStorageUtils; import com.owncloud.android.utils.Log_OC; @@ -46,9 +36,10 @@ import android.accounts.Account; import android.webkit.MimeTypeMap; /** - * Remote operation performing the download of a file to an ownCloud server + * Remote mDownloadOperation performing the download of a file to an ownCloud server * * @author David A. Velasco + * @author masensio */ public class DownloadFileOperation extends RemoteOperation { @@ -57,9 +48,9 @@ public class DownloadFileOperation extends RemoteOperation { private Account mAccount; private OCFile mFile; private Set mDataTransferListeners = new HashSet(); - private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false); private long mModificationTimestamp = 0; - private GetMethod mGet; + + private DownloadRemoteFileOperation mDownloadOperation; public DownloadFileOperation(Account account, OCFile file) { @@ -70,6 +61,7 @@ public class DownloadFileOperation extends RemoteOperation { mAccount = account; mFile = file; + } @@ -93,6 +85,10 @@ public class DownloadFileOperation extends RemoteOperation { return FileStorageUtils.getTemporalPath(mAccount.name) + mFile.getRemotePath(); } + public String getTmpFolder() { + return FileStorageUtils.getTemporalPath(mAccount.name); + } + public String getRemotePath() { return mFile.getRemotePath(); } @@ -121,19 +117,6 @@ public class DownloadFileOperation extends RemoteOperation { public long getModificationTimestamp() { return (mModificationTimestamp > 0) ? mModificationTimestamp : mFile.getModificationTimestamp(); } - - - public void addDatatransferProgressListener (OnDatatransferProgressListener listener) { - synchronized (mDataTransferListeners) { - mDataTransferListeners.add(listener); - } - } - - public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) { - synchronized (mDataTransferListeners) { - mDataTransferListeners.remove(listener); - } - } @Override protected RemoteOperationResult run(WebdavClient client) { @@ -144,93 +127,46 @@ public class DownloadFileOperation extends RemoteOperation { /// download will be performed to a temporal file, then moved to the final location File tmpFile = new File(getTmpPath()); + String tmpFolder = getTmpFolder(); + RemoteFile remoteFile = FileStorageUtils.fillRemoteFile(mFile); + /// perform the download - try { - tmpFile.getParentFile().mkdirs(); - int status = downloadFile(client, tmpFile); - if (isSuccess(status)) { - newFile = new File(getSavePath()); - newFile.getParentFile().mkdirs(); - moved = tmpFile.renameTo(newFile); - } + mDownloadOperation = new DownloadRemoteFileOperation(remoteFile, tmpFolder); + Iterator listener = mDataTransferListeners.iterator(); + while (listener.hasNext()) { + mDownloadOperation.addDatatransferProgressListener(listener.next()); + } + result = mDownloadOperation.execute(client); + + if (result.isSuccess()) { + newFile = new File(getSavePath()); + newFile.getParentFile().mkdirs(); + moved = tmpFile.renameTo(newFile); + if (!moved) result = new RemoteOperationResult(RemoteOperationResult.ResultCode.LOCAL_STORAGE_NOT_MOVED); - else - result = new RemoteOperationResult(isSuccess(status), status, (mGet != null ? mGet.getResponseHeaders() : null)); - Log_OC.i(TAG, "Download of " + mFile.getRemotePath() + " to " + getSavePath() + ": " + result.getLogMessage()); - - } catch (Exception e) { - result = new RemoteOperationResult(e); - Log_OC.e(TAG, "Download of " + mFile.getRemotePath() + " to " + getSavePath() + ": " + result.getLogMessage(), e); } + Log_OC.i(TAG, "Download of " + mFile.getRemotePath() + " to " + getSavePath() + ": " + result.getLogMessage()); + return result; } - - public boolean isSuccess(int status) { - return (status == HttpStatus.SC_OK); + public void cancel() { + mDownloadOperation.cancel(); } - - - protected int downloadFile(WebdavClient client, File targetFile) throws HttpException, IOException, OperationCancelledException { - int status = -1; - boolean savedFile = false; - mGet = new GetMethod(client.getBaseUri() + WebdavUtils.encodePath(mFile.getRemotePath())); - Iterator it = null; - - FileOutputStream fos = null; - try { - status = client.executeMethod(mGet); - if (isSuccess(status)) { - targetFile.createNewFile(); - BufferedInputStream bis = new BufferedInputStream(mGet.getResponseBodyAsStream()); - fos = new FileOutputStream(targetFile); - long transferred = 0; - byte[] bytes = new byte[4096]; - int readResult = 0; - while ((readResult = bis.read(bytes)) != -1) { - synchronized(mCancellationRequested) { - if (mCancellationRequested.get()) { - mGet.abort(); - throw new OperationCancelledException(); - } - } - fos.write(bytes, 0, readResult); - transferred += readResult; - synchronized (mDataTransferListeners) { - it = mDataTransferListeners.iterator(); - while (it.hasNext()) { - it.next().onTransferProgress(readResult, transferred, mFile.getFileLength(), targetFile.getName()); - } - } - } - savedFile = true; - Header modificationTime = mGet.getResponseHeader("Last-Modified"); - if (modificationTime != null) { - Date d = WebdavUtils.parseResponseDate((String) modificationTime.getValue()); - mModificationTimestamp = (d != null) ? d.getTime() : 0; - } - - } else { - client.exhaustResponse(mGet.getResponseBodyAsStream()); - } - - } finally { - if (fos != null) fos.close(); - if (!savedFile && targetFile.exists()) { - targetFile.delete(); - } - mGet.releaseConnection(); // let the connection available for other methods + + public void addDatatransferProgressListener (OnDatatransferProgressListener listener) { + synchronized (mDataTransferListeners) { + mDataTransferListeners.add(listener); } - return status; } - - public void cancel() { - mCancellationRequested.set(true); // atomic set; there is no need of synchronizing it + public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) { + synchronized (mDataTransferListeners) { + mDataTransferListeners.remove(listener); + } } - - + } diff --git a/src/com/owncloud/android/operations/ExistenceCheckOperation.java b/src/com/owncloud/android/operations/ExistenceCheckOperation.java deleted file mode 100644 index d92190c1..00000000 --- a/src/com/owncloud/android/operations/ExistenceCheckOperation.java +++ /dev/null @@ -1,97 +0,0 @@ -/* ownCloud Android client application - * Copyright (C) 2012 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 . - * - */ - -package com.owncloud.android.operations; - -import org.apache.commons.httpclient.HttpStatus; -import org.apache.commons.httpclient.methods.HeadMethod; - -import com.owncloud.android.oc_framework.network.webdav.WebdavClient; -import com.owncloud.android.oc_framework.operations.RemoteOperation; -import com.owncloud.android.oc_framework.operations.RemoteOperationResult; -import com.owncloud.android.oc_framework.network.webdav.WebdavUtils; -import com.owncloud.android.utils.Log_OC; - -import android.content.Context; -import android.net.ConnectivityManager; - -/** - * Operation to check the existence or absence of a path in a remote server. - * - * @author David A. Velasco - */ -public class ExistenceCheckOperation extends RemoteOperation { - - /** Maximum time to wait for a response from the server in MILLISECONDs. */ - public static final int TIMEOUT = 10000; - - private static final String TAG = ExistenceCheckOperation.class.getSimpleName(); - - private String mPath; - private Context mContext; - private boolean mSuccessIfAbsent; - - - /** - * Full constructor. Success of the operation will depend upon the value of successIfAbsent. - * - * @param path Path to append to the URL owned by the client instance. - * @param context Android application context. - * @param successIfAbsent When 'true', the operation finishes in success if the path does NOT exist in the remote server (HTTP 404). - */ - public ExistenceCheckOperation(String path, Context context, boolean successIfAbsent) { - mPath = (path != null) ? path : ""; - mContext = context; - mSuccessIfAbsent = successIfAbsent; - } - - - @Override - protected RemoteOperationResult run(WebdavClient client) { - if (!isOnline()) { - return new RemoteOperationResult(RemoteOperationResult.ResultCode.NO_NETWORK_CONNECTION); - } - RemoteOperationResult result = null; - HeadMethod head = null; - try { - head = new HeadMethod(client.getBaseUri() + WebdavUtils.encodePath(mPath)); - int status = client.executeMethod(head, TIMEOUT, TIMEOUT); - client.exhaustResponse(head.getResponseBodyAsStream()); - boolean success = (status == HttpStatus.SC_OK && !mSuccessIfAbsent) || (status == HttpStatus.SC_NOT_FOUND && mSuccessIfAbsent); - result = new RemoteOperationResult(success, status, head.getResponseHeaders()); - Log_OC.d(TAG, "Existence check for " + client.getBaseUri() + WebdavUtils.encodePath(mPath) + " targeting for " + (mSuccessIfAbsent ? " absence " : " existence ") + "finished with HTTP status " + status + (!success?"(FAIL)":"")); - - } catch (Exception e) { - result = new RemoteOperationResult(e); - Log_OC.e(TAG, "Existence check for " + client.getBaseUri() + WebdavUtils.encodePath(mPath) + " targeting for " + (mSuccessIfAbsent ? " absence " : " existence ") + ": " + result.getLogMessage(), result.getException()); - - } finally { - if (head != null) - head.releaseConnection(); - } - return result; - } - - private boolean isOnline() { - ConnectivityManager cm = (ConnectivityManager) mContext - .getSystemService(Context.CONNECTIVITY_SERVICE); - return cm != null && cm.getActiveNetworkInfo() != null - && cm.getActiveNetworkInfo().isConnectedOrConnecting(); - } - - -} diff --git a/src/com/owncloud/android/operations/SynchronizeFileOperation.java b/src/com/owncloud/android/operations/SynchronizeFileOperation.java index f087aa5e..71d7f721 100644 --- a/src/com/owncloud/android/operations/SynchronizeFileOperation.java +++ b/src/com/owncloud/android/operations/SynchronizeFileOperation.java @@ -18,33 +18,32 @@ package com.owncloud.android.operations; -import org.apache.http.HttpStatus; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.MultiStatus; -import org.apache.jackrabbit.webdav.client.methods.PropFindMethod; - import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.services.FileDownloader; import com.owncloud.android.files.services.FileUploader; import com.owncloud.android.oc_framework.network.webdav.WebdavClient; -import com.owncloud.android.oc_framework.network.webdav.WebdavEntry; -import com.owncloud.android.oc_framework.network.webdav.WebdavUtils; import com.owncloud.android.oc_framework.operations.RemoteOperation; import com.owncloud.android.oc_framework.operations.RemoteOperationResult; import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode; +import com.owncloud.android.oc_framework.operations.remote.ReadRemoteFileOperation; +import com.owncloud.android.utils.FileStorageUtils; import com.owncloud.android.utils.Log_OC; import android.accounts.Account; import android.content.Context; import android.content.Intent; +/** + * Remote operation performing the read of remote file in the ownCloud server. + * + * @author David A. Velasco + * @author masensio + */ public class SynchronizeFileOperation extends RemoteOperation { private String TAG = SynchronizeFileOperation.class.getSimpleName(); - private static final int SYNC_READ_TIMEOUT = 10000; - private static final int SYNC_CONNECTION_TIMEOUT = 5000; private OCFile mLocalFile; private OCFile mServerFile; @@ -74,103 +73,83 @@ public class SynchronizeFileOperation extends RemoteOperation { @Override protected RemoteOperationResult run(WebdavClient client) { - - PropFindMethod propfind = null; + RemoteOperationResult result = null; mTransferWasRequested = false; - try { - if (!mLocalFile.isDown()) { - /// easy decision - requestForDownload(mLocalFile); - result = new RemoteOperationResult(ResultCode.OK); - - } else { - /// local copy in the device -> need to think a bit more before do anything - - if (mServerFile == null) { - /// take the duty of check the server for the current state of the file there - propfind = new PropFindMethod(client.getBaseUri() + WebdavUtils.encodePath(mLocalFile.getRemotePath()), - DavConstants.PROPFIND_ALL_PROP, - DavConstants.DEPTH_0); - int status = client.executeMethod(propfind, SYNC_READ_TIMEOUT, SYNC_CONNECTION_TIMEOUT); - boolean isMultiStatus = status == HttpStatus.SC_MULTI_STATUS; - if (isMultiStatus) { - MultiStatus resp = propfind.getResponseBodyAsMultiStatus(); - WebdavEntry we = new WebdavEntry(resp.getResponses()[0], - client.getBaseUri().getPath()); - mServerFile = fillOCFile(we); - mServerFile.setLastSyncDateForProperties(System.currentTimeMillis()); - - } else { - client.exhaustResponse(propfind.getResponseBodyAsStream()); - result = new RemoteOperationResult(false, status, propfind.getResponseHeaders()); - } + if (!mLocalFile.isDown()) { + /// easy decision + requestForDownload(mLocalFile); + result = new RemoteOperationResult(ResultCode.OK); + + } else { + /// local copy in the device -> need to think a bit more before do anything + + if (mServerFile == null) { + String remotePath = mLocalFile.getRemotePath(); + ReadRemoteFileOperation operation = new ReadRemoteFileOperation(remotePath); + result = operation.execute(client); + if (result.isSuccess()){ + mServerFile = FileStorageUtils.fillOCFile(result.getData().get(0)); + mServerFile.setLastSyncDateForProperties(System.currentTimeMillis()); } - - if (result == null) { // true if the server was not checked. nothing was wrong with the remote request - - /// check changes in server and local file - boolean serverChanged = false; - /* time for eTag is coming, but not yet + } + + if (result.isSuccess()) { + + /// check changes in server and local file + boolean serverChanged = false; + /* time for eTag is coming, but not yet if (mServerFile.getEtag() != null) { serverChanged = (!mServerFile.getEtag().equals(mLocalFile.getEtag())); // TODO could this be dangerous when the user upgrades the server from non-tagged to tagged? } else { */ - // server without etags - serverChanged = (mServerFile.getModificationTimestamp() > mLocalFile.getModificationTimestampAtLastSyncForData()); - //} - boolean localChanged = (mLocalFile.getLocalModificationTimestamp() > mLocalFile.getLastSyncDateForData()); - // TODO this will be always true after the app is upgraded to database version 2; will result in unnecessary uploads - - /// decide action to perform depending upon changes - //if (!mLocalFile.getEtag().isEmpty() && localChanged && serverChanged) { - if (localChanged && serverChanged) { - result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT); - - } else if (localChanged) { - if (mSyncFileContents) { - requestForUpload(mLocalFile); - // the local update of file properties will be done by the FileUploader service when the upload finishes - } else { - // NOTHING TO DO HERE: updating the properties of the file in the server without uploading the contents would be stupid; - // So, an instance of SynchronizeFileOperation created with syncFileContents == false is completely useless when we suspect - // that an upload is necessary (for instance, in FileObserverService). - } - result = new RemoteOperationResult(ResultCode.OK); - - } else if (serverChanged) { - 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 - } else { - // TODO CHECK: is this really useful in some point in the code? - mServerFile.setKeepInSync(mLocalFile.keepInSync()); - mServerFile.setLastSyncDateForData(mLocalFile.getLastSyncDateForData()); - mServerFile.setStoragePath(mLocalFile.getStoragePath()); - mServerFile.setParentId(mLocalFile.getParentId()); - mStorageManager.saveFile(mServerFile); - - } - result = new RemoteOperationResult(ResultCode.OK); - + // server without etags + serverChanged = (mServerFile.getModificationTimestamp() != mLocalFile.getModificationTimestampAtLastSyncForData()); + //} + boolean localChanged = (mLocalFile.getLocalModificationTimestamp() > mLocalFile.getLastSyncDateForData()); + // TODO this will be always true after the app is upgraded to database version 2; will result in unnecessary uploads + + /// decide action to perform depending upon changes + //if (!mLocalFile.getEtag().isEmpty() && localChanged && serverChanged) { + if (localChanged && serverChanged) { + result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT); + + } else if (localChanged) { + if (mSyncFileContents) { + requestForUpload(mLocalFile); + // the local update of file properties will be done by the FileUploader service when the upload finishes } else { - // nothing changed, nothing to do - result = new RemoteOperationResult(ResultCode.OK); + // NOTHING TO DO HERE: updating the properties of the file in the server without uploading the contents would be stupid; + // So, an instance of SynchronizeFileOperation created with syncFileContents == false is completely useless when we suspect + // that an upload is necessary (for instance, in FileObserverService). } - - } - - } - - Log_OC.i(TAG, "Synchronizing " + mAccount.name + ", file " + mLocalFile.getRemotePath() + ": " + result.getLogMessage()); - - } catch (Exception e) { - result = new RemoteOperationResult(e); - Log_OC.e(TAG, "Synchronizing " + mAccount.name + ", file " + (mLocalFile != null ? mLocalFile.getRemotePath() : "NULL") + ": " + result.getLogMessage(), result.getException()); - - } finally { - if (propfind != null) - propfind.releaseConnection(); + result = new RemoteOperationResult(ResultCode.OK); + + } else if (serverChanged) { + 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 + } else { + // TODO CHECK: is this really useful in some point in the code? + mServerFile.setKeepInSync(mLocalFile.keepInSync()); + mServerFile.setLastSyncDateForData(mLocalFile.getLastSyncDateForData()); + mServerFile.setStoragePath(mLocalFile.getStoragePath()); + mServerFile.setParentId(mLocalFile.getParentId()); + mStorageManager.saveFile(mServerFile); + + } + result = new RemoteOperationResult(ResultCode.OK); + + } else { + // nothing changed, nothing to do + result = new RemoteOperationResult(ResultCode.OK); + } + + } + } + + Log_OC.i(TAG, "Synchronizing " + mAccount.name + ", file " + mLocalFile.getRemotePath() + ": " + result.getLogMessage()); + return result; } @@ -207,24 +186,6 @@ public class SynchronizeFileOperation extends RemoteOperation { } - /** - * Creates and populates a new {@link OCFile} object with the data read from the server. - * - * @param we WebDAV entry read from the server for a WebDAV resource (remote file or folder). - * @return New OCFile instance representing the remote resource described by we. - */ - private OCFile fillOCFile(WebdavEntry we) { - OCFile file = new OCFile(we.decodedPath()); - file.setCreationTimestamp(we.createTimestamp()); - file.setFileLength(we.contentLength()); - file.setMimetype(we.contentType()); - file.setModificationTimestamp(we.modifiedTimestamp()); - file.setEtag(we.etag()); - - return file; - } - - public boolean transferWasRequested() { return mTransferWasRequested; } diff --git a/src/com/owncloud/android/operations/SynchronizeFolderOperation.java b/src/com/owncloud/android/operations/SynchronizeFolderOperation.java index e93736c4..ff387c0f 100644 --- a/src/com/owncloud/android/operations/SynchronizeFolderOperation.java +++ b/src/com/owncloud/android/operations/SynchronizeFolderOperation.java @@ -30,9 +30,6 @@ import java.util.Map; import java.util.Vector; import org.apache.http.HttpStatus; -import org.apache.jackrabbit.webdav.DavConstants; -import org.apache.jackrabbit.webdav.client.methods.PropFindMethod; - import android.accounts.Account; import android.content.Context; import android.content.Intent; @@ -40,11 +37,10 @@ import android.content.Intent; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.oc_framework.network.webdav.WebdavClient; -import com.owncloud.android.oc_framework.network.webdav.WebdavEntry; -import com.owncloud.android.oc_framework.network.webdav.WebdavUtils; import com.owncloud.android.oc_framework.operations.RemoteOperation; import com.owncloud.android.oc_framework.operations.RemoteOperationResult; import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode; +import com.owncloud.android.oc_framework.operations.remote.ReadRemoteFileOperation; import com.owncloud.android.oc_framework.operations.remote.ReadRemoteFolderOperation; import com.owncloud.android.oc_framework.operations.RemoteFile; import com.owncloud.android.syncadapter.FileSyncService; @@ -188,48 +184,27 @@ public class SynchronizeFolderOperation extends RemoteOperation { mRemoteFolderChanged = false; RemoteOperationResult result = null; String remotePath = null; - PropFindMethod query = null; - - try { + remotePath = mLocalFolder.getRemotePath(); Log_OC.d(TAG, "Checking changes in " + mAccount.name + remotePath); // remote request - query = new PropFindMethod(client.getBaseUri() + WebdavUtils.encodePath(remotePath), - DavConstants.PROPFIND_ALL_PROP, - DavConstants.DEPTH_0); - int status = client.executeMethod(query); - - // check and process response - if (isMultiStatus(status)) { - // parse data from remote folder - WebdavEntry we = new WebdavEntry(query.getResponseBodyAsMultiStatus().getResponses()[0], client.getBaseUri().getPath()); - OCFile remoteFolder = fillOCFile(we); - - // check if remote and local folder are different - mRemoteFolderChanged = !(remoteFolder.getEtag().equalsIgnoreCase(mLocalFolder.getEtag())); - - result = new RemoteOperationResult(ResultCode.OK); + ReadRemoteFileOperation operation = new ReadRemoteFileOperation(remotePath); + result = operation.execute(client); + if (result.isSuccess()){ + OCFile remoteFolder = FileStorageUtils.fillOCFile(result.getData().get(0)); + // check if remote and local folder are different + mRemoteFolderChanged = !(remoteFolder.getEtag().equalsIgnoreCase(mLocalFolder.getEtag())); + + result = new RemoteOperationResult(ResultCode.OK); + + Log_OC.i(TAG, "Checked " + mAccount.name + remotePath + " : " + (mRemoteFolderChanged ? "changed" : "not changed")); } else { // check failed - client.exhaustResponse(query.getResponseBodyAsStream()); - if (status == HttpStatus.SC_NOT_FOUND) { + if (result.getCode() == ResultCode.FILE_NOT_FOUND) { removeLocalFolder(); } - result = new RemoteOperationResult(false, status, query.getResponseHeaders()); - } - - } catch (Exception e) { - result = new RemoteOperationResult(e); - - - } finally { - if (query != null) - query.releaseConnection(); // let the connection available for other methods - if (result.isSuccess()) { - Log_OC.i(TAG, "Checked " + mAccount.name + remotePath + " : " + (mRemoteFolderChanged ? "changed" : "not changed")); - } else { if (result.isException()) { Log_OC.e(TAG, "Checked " + mAccount.name + remotePath + " : " + result.getLogMessage(), result.getException()); } else { @@ -237,7 +212,6 @@ public class SynchronizeFolderOperation extends RemoteOperation { } } - } return result; } @@ -398,23 +372,6 @@ public class SynchronizeFolderOperation extends RemoteOperation { return (status == HttpStatus.SC_MULTI_STATUS); } - - /** - * Creates and populates a new {@link OCFile} object with the data read from the server. - * - * @param we WebDAV entry read from the server for a WebDAV resource (remote file or folder). - * @return New OCFile instance representing the remote resource described by we. - */ - private OCFile fillOCFile(WebdavEntry we) { - OCFile file = new OCFile(we.decodedPath()); - file.setCreationTimestamp(we.createTimestamp()); - file.setFileLength(we.contentLength()); - file.setMimetype(we.contentType()); - file.setModificationTimestamp(we.modifiedTimestamp()); - file.setEtag(we.etag()); - return file; - } - /** * Creates and populates a new {@link OCFile} object with the data read from the server. * diff --git a/src/com/owncloud/android/operations/UploadFileOperation.java b/src/com/owncloud/android/operations/UploadFileOperation.java index 80a3463b..9ceb9751 100644 --- a/src/com/owncloud/android/operations/UploadFileOperation.java +++ b/src/com/owncloud/android/operations/UploadFileOperation.java @@ -24,29 +24,30 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.HashSet; +import java.util.Iterator; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; -import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.methods.PutMethod; import org.apache.commons.httpclient.methods.RequestEntity; -import org.apache.http.HttpStatus; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.services.FileUploader; import com.owncloud.android.oc_framework.network.ProgressiveDataTransferer; -import com.owncloud.android.oc_framework.network.webdav.FileRequestEntity; import com.owncloud.android.oc_framework.network.webdav.OnDatatransferProgressListener; import com.owncloud.android.oc_framework.network.webdav.WebdavClient; -import com.owncloud.android.oc_framework.network.webdav.WebdavUtils; import com.owncloud.android.oc_framework.operations.OperationCancelledException; import com.owncloud.android.oc_framework.operations.RemoteOperation; import com.owncloud.android.oc_framework.operations.RemoteOperationResult; import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode; +import com.owncloud.android.oc_framework.operations.remote.ChunkedUploadRemoteFileOperation; +import com.owncloud.android.oc_framework.operations.remote.ExistenceCheckRemoteOperation; +import com.owncloud.android.oc_framework.operations.remote.UploadRemoteFileOperation; import com.owncloud.android.utils.FileStorageUtils; import com.owncloud.android.utils.Log_OC; import android.accounts.Account; +import android.content.Context; /** @@ -62,6 +63,7 @@ public class UploadFileOperation extends RemoteOperation { private OCFile mFile; private OCFile mOldFile; private String mRemotePath = null; + private boolean mChunked = false; private boolean mIsInstant = false; private boolean mRemoteFolderToBeCreated = false; private boolean mForceOverwrite = false; @@ -72,15 +74,20 @@ public class UploadFileOperation extends RemoteOperation { PutMethod mPutMethod = null; private Set mDataTransferListeners = new HashSet(); private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false); + private Context mContext; + + private UploadRemoteFileOperation mUploadOperation; protected RequestEntity mEntity = null; public UploadFileOperation( Account account, OCFile file, + boolean chunked, boolean isInstant, boolean forceOverwrite, - int localBehaviour) { + int localBehaviour, + Context context) { if (account == null) throw new IllegalArgumentException("Illegal NULL account in UploadFileOperation creation"); if (file == null) @@ -95,11 +102,13 @@ public class UploadFileOperation extends RemoteOperation { mAccount = account; mFile = file; mRemotePath = file.getRemotePath(); + mChunked = chunked; mIsInstant = isInstant; mForceOverwrite = forceOverwrite; mLocalBehaviour = localBehaviour; mOriginalStoragePath = mFile.getStoragePath(); mOriginalFileName = mFile.getFileName(); + mContext = context; } public Account getAccount() { @@ -199,7 +208,7 @@ public class UploadFileOperation extends RemoteOperation { // !!! expectedFile = new File(expectedPath); - // / check location of local file; if not the expected, copy to a + // check location of local file; if not the expected, copy to a // temporal file before upload (if COPY is the expected behaviour) if (!mOriginalStoragePath.equals(expectedPath) && mLocalBehaviour == FileUploader.LOCAL_BEHAVIOUR_COPY) { @@ -260,19 +269,23 @@ public class UploadFileOperation extends RemoteOperation { } localCopyPassed = true; - // / perform the upload - synchronized (mCancellationRequested) { - if (mCancellationRequested.get()) { - throw new OperationCancelledException(); - } else { - mPutMethod = new PutMethod(client.getBaseUri() + WebdavUtils.encodePath(mFile.getRemotePath())); - } + /// perform the upload + if ( mChunked && (new File(mFile.getStoragePath())).length() > ChunkedUploadRemoteFileOperation.CHUNK_SIZE ) { + mUploadOperation = new ChunkedUploadRemoteFileOperation(mFile.getStoragePath(), mFile.getRemotePath(), + mFile.getMimetype()); + } else { + mUploadOperation = new UploadRemoteFileOperation(mFile.getStoragePath(), mFile.getRemotePath(), + mFile.getMimetype()); + } + Iterator listener = mDataTransferListeners.iterator(); + while (listener.hasNext()) { + mUploadOperation.addDatatransferProgressListener(listener.next()); } - int status = uploadFile(client); + result = mUploadOperation.execute(client); - // / move local temporal file or original file to its corresponding + /// move local temporal file or original file to its corresponding // location in the ownCloud local folder - if (isSuccess(status)) { + if (result.isSuccess()) { if (mLocalBehaviour == FileUploader.LOCAL_BEHAVIOUR_FORGET) { mFile.setStoragePath(null); @@ -305,8 +318,6 @@ public class UploadFileOperation extends RemoteOperation { } } - result = new RemoteOperationResult(isSuccess(status), status, (mPutMethod != null ? mPutMethod.getResponseHeaders() : null)); - } catch (Exception e) { // TODO something cleaner with cancellations if (mCancellationRequested.get()) { @@ -358,29 +369,6 @@ public class UploadFileOperation extends RemoteOperation { mFile = newFile; } - public boolean isSuccess(int status) { - return ((status == HttpStatus.SC_OK || status == HttpStatus.SC_CREATED || status == HttpStatus.SC_NO_CONTENT)); - } - - protected int uploadFile(WebdavClient client) throws HttpException, IOException, OperationCancelledException { - int status = -1; - try { - File f = new File(mFile.getStoragePath()); - mEntity = new FileRequestEntity(f, getMimeType()); - synchronized (mDataTransferListeners) { - ((ProgressiveDataTransferer)mEntity).addDatatransferProgressListeners(mDataTransferListeners); - } - mPutMethod.setRequestEntity(mEntity); - status = client.executeMethod(mPutMethod); - client.exhaustResponse(mPutMethod.getResponseBodyAsStream()); - - } finally { - mPutMethod.releaseConnection(); // let the connection available for - // other methods - } - return status; - } - /** * Checks if remotePath does not exist in the server and returns it, or adds * a suffix to it in order to avoid the server file is overwritten. @@ -389,7 +377,7 @@ public class UploadFileOperation extends RemoteOperation { * @return */ private String getAvailableRemotePath(WebdavClient wc, String remotePath) throws Exception { - boolean check = wc.existsFile(remotePath); + boolean check = existsFile(wc, remotePath); if (!check) { return remotePath; } @@ -404,10 +392,12 @@ public class UploadFileOperation extends RemoteOperation { int count = 2; do { suffix = " (" + count + ")"; - if (pos >= 0) - check = wc.existsFile(remotePath + suffix + "." + extension); - else - check = wc.existsFile(remotePath + suffix); + if (pos >= 0) { + check = existsFile(wc, remotePath + suffix + "." + extension); + } + else { + check = existsFile(wc, remotePath + suffix); + } count++; } while (check); @@ -418,12 +408,14 @@ public class UploadFileOperation extends RemoteOperation { } } + private boolean existsFile(WebdavClient client, String remotePath){ + ExistenceCheckRemoteOperation existsOperation = new ExistenceCheckRemoteOperation(remotePath, mContext, false); + RemoteOperationResult result = existsOperation.execute(client); + return result.isSuccess(); + } + public void cancel() { - synchronized (mCancellationRequested) { - mCancellationRequested.set(true); - if (mPutMethod != null) - mPutMethod.abort(); - } + mUploadOperation.cancel(); } } diff --git a/src/com/owncloud/android/syncadapter/ContactSyncAdapter.java b/src/com/owncloud/android/syncadapter/ContactSyncAdapter.java index 9bf5d835..db7f4c29 100644 --- a/src/com/owncloud/android/syncadapter/ContactSyncAdapter.java +++ b/src/com/owncloud/android/syncadapter/ContactSyncAdapter.java @@ -24,7 +24,6 @@ import java.io.IOException; import org.apache.http.client.methods.HttpPut; import org.apache.http.entity.ByteArrayEntity; -import com.owncloud.android.authentication.AccountAuthenticator; import com.owncloud.android.authentication.AccountUtils; import com.owncloud.android.oc_framework.accounts.OwnCloudAccount; diff --git a/src/com/owncloud/android/syncadapter/FileSyncAdapter.java b/src/com/owncloud/android/syncadapter/FileSyncAdapter.java index f0bc8709..058cfbc4 100644 --- a/src/com/owncloud/android/syncadapter/FileSyncAdapter.java +++ b/src/com/owncloud/android/syncadapter/FileSyncAdapter.java @@ -26,7 +26,6 @@ import java.util.Map; import org.apache.jackrabbit.webdav.DavException; -import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.authentication.AuthenticatorActivity; import com.owncloud.android.datamodel.FileDataStorageManager; @@ -36,6 +35,7 @@ import com.owncloud.android.operations.SynchronizeFolderOperation; import com.owncloud.android.operations.UpdateOCVersionOperation; import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode; import com.owncloud.android.ui.activity.ErrorsWhileCopyingHandlerActivity; +import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.Log_OC; @@ -322,8 +322,8 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { private void fetchChildren(OCFile parent, List files, boolean parentEtagChanged) { int i; OCFile newFile = null; - String etag = null; - boolean syncDown = false; + //String etag = null; + //boolean syncDown = false; for (i=0; i < files.size() && !mCancellation; i++) { newFile = files.get(i); if (newFile.isFolder()) { @@ -368,7 +368,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { * Notifies the user about a failed synchronization through the status notification bar */ private void notifyFailedSynchronization() { - Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_fail_ticker), System.currentTimeMillis()); + Notification notification = new Notification(DisplayUtils.getSeasonalIconId(), getContext().getString(R.string.sync_fail_ticker), System.currentTimeMillis()); notification.flags |= Notification.FLAG_AUTO_CANCEL; boolean needsToUpdateCredentials = (mLastFailedResult != null && ( mLastFailedResult.getCode() == ResultCode.UNAUTHORIZED || @@ -410,7 +410,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { */ private void notifyFailsInFavourites() { if (mFailedResultsCounter > 0) { - Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_fail_in_favourites_ticker), System.currentTimeMillis()); + Notification notification = new Notification(DisplayUtils.getSeasonalIconId(), getContext().getString(R.string.sync_fail_in_favourites_ticker), System.currentTimeMillis()); notification.flags |= Notification.FLAG_AUTO_CANCEL; // TODO put something smart in the contentIntent below notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0); @@ -421,7 +421,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { ((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(R.string.sync_fail_in_favourites_ticker, notification); } else { - Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_conflicts_in_favourites_ticker), System.currentTimeMillis()); + Notification notification = new Notification(DisplayUtils.getSeasonalIconId(), getContext().getString(R.string.sync_conflicts_in_favourites_ticker), System.currentTimeMillis()); notification.flags |= Notification.FLAG_AUTO_CANCEL; // TODO put something smart in the contentIntent below notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0); @@ -443,7 +443,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { * We won't consider a synchronization as failed when foreign files can not be copied to the ownCloud local directory. */ private void notifyForgottenLocalFiles() { - Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_foreign_files_forgotten_ticker), System.currentTimeMillis()); + Notification notification = new Notification(DisplayUtils.getSeasonalIconId(), getContext().getString(R.string.sync_foreign_files_forgotten_ticker), System.currentTimeMillis()); notification.flags |= Notification.FLAG_AUTO_CANCEL; /// includes a pending intent in the notification showing a more detailed explanation diff --git a/src/com/owncloud/android/syncadapter/FileSyncService.java b/src/com/owncloud/android/syncadapter/FileSyncService.java index 1e1e11fd..9ae051ca 100644 --- a/src/com/owncloud/android/syncadapter/FileSyncService.java +++ b/src/com/owncloud/android/syncadapter/FileSyncService.java @@ -17,8 +17,6 @@ */ package com.owncloud.android.syncadapter; -import com.owncloud.android.utils.Log_OC; - import android.app.Service; import android.content.Intent; import android.os.IBinder; diff --git a/src/com/owncloud/android/ui/activity/AccountSelectActivity.java b/src/com/owncloud/android/ui/activity/AccountSelectActivity.java index b1ff8453..3632b5e4 100644 --- a/src/com/owncloud/android/ui/activity/AccountSelectActivity.java +++ b/src/com/owncloud/android/ui/activity/AccountSelectActivity.java @@ -27,7 +27,6 @@ import android.accounts.Account; import android.accounts.AccountManager; import android.accounts.AccountManagerCallback; import android.accounts.AccountManagerFuture; -import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.os.Bundle; @@ -50,6 +49,7 @@ import com.actionbarsherlock.view.MenuItem; import com.owncloud.android.authentication.AuthenticatorActivity; import com.owncloud.android.authentication.AccountUtils; import com.owncloud.android.oc_framework.accounts.OwnCloudAccount; +import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.Log_OC; import com.owncloud.android.MainApp; import com.owncloud.android.R; @@ -75,9 +75,10 @@ public class AccountSelectActivity extends SherlockListActivity implements mPreviousAccount = AccountUtils.getCurrentOwnCloudAccount(this); } - ActionBar action_bar = getSupportActionBar(); - action_bar.setDisplayShowTitleEnabled(true); - action_bar.setDisplayHomeAsUpEnabled(false); + ActionBar actionBar = getSupportActionBar(); + actionBar.setIcon(DisplayUtils.getSeasonalIconId()); + actionBar.setDisplayShowTitleEnabled(true); + actionBar.setDisplayHomeAsUpEnabled(false); } @Override diff --git a/src/com/owncloud/android/ui/activity/ConflictsResolveActivity.java b/src/com/owncloud/android/ui/activity/ConflictsResolveActivity.java index 2d13a66b..5b22c341 100644 --- a/src/com/owncloud/android/ui/activity/ConflictsResolveActivity.java +++ b/src/com/owncloud/android/ui/activity/ConflictsResolveActivity.java @@ -18,12 +18,14 @@ package com.owncloud.android.ui.activity; +import com.actionbarsherlock.app.ActionBar; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.services.FileUploader; import com.owncloud.android.ui.dialog.ConflictsResolveDialog; import com.owncloud.android.ui.dialog.ConflictsResolveDialog.Decision; import com.owncloud.android.ui.dialog.ConflictsResolveDialog.OnConflictDecisionMadeListener; +import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.Log_OC; import android.content.Intent; @@ -43,10 +45,12 @@ public class ConflictsResolveActivity extends FileActivity implements OnConflict @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + ActionBar actionBar = getSupportActionBar(); + actionBar.setIcon(DisplayUtils.getSeasonalIconId()); } @Override - public void ConflictDecisionMade(Decision decision) { + public void conflictDecisionMade(Decision decision) { Intent i = new Intent(getApplicationContext(), FileUploader.class); switch (decision) { diff --git a/src/com/owncloud/android/ui/activity/FileActivity.java b/src/com/owncloud/android/ui/activity/FileActivity.java index 59b44433..937d45dd 100644 --- a/src/com/owncloud/android/ui/activity/FileActivity.java +++ b/src/com/owncloud/android/ui/activity/FileActivity.java @@ -47,6 +47,7 @@ public abstract class FileActivity extends SherlockFragmentActivity { public static final String EXTRA_FILE = "com.owncloud.android.ui.activity.FILE"; public static final String EXTRA_ACCOUNT = "com.owncloud.android.ui.activity.ACCOUNT"; public static final String EXTRA_WAITING_TO_PREVIEW = "com.owncloud.android.ui.activity.WAITING_TO_PREVIEW"; + public static final String EXTRA_FROM_NOTIFICATION= "com.owncloud.android.ui.activity.FROM_NOTIFICATION"; public static final String TAG = FileActivity.class.getSimpleName(); @@ -65,6 +66,9 @@ public abstract class FileActivity extends SherlockFragmentActivity { /** Flag to signal when the value of mAccount was restored from a saved state */ private boolean mAccountWasRestored; + + /** Flag to signal if the activity is launched by a notification */ + private boolean mFromNotification; /** @@ -82,9 +86,11 @@ public abstract class FileActivity extends SherlockFragmentActivity { if(savedInstanceState != null) { account = savedInstanceState.getParcelable(FileActivity.EXTRA_ACCOUNT); mFile = savedInstanceState.getParcelable(FileActivity.EXTRA_FILE); + mFromNotification = savedInstanceState.getBoolean(FileActivity.EXTRA_FROM_NOTIFICATION); } else { account = getIntent().getParcelableExtra(FileActivity.EXTRA_ACCOUNT); mFile = getIntent().getParcelableExtra(FileActivity.EXTRA_FILE); + mFromNotification = getIntent().getBooleanExtra(FileActivity.EXTRA_FROM_NOTIFICATION, false); } setAccount(account, savedInstanceState != null); @@ -191,6 +197,7 @@ public abstract class FileActivity extends SherlockFragmentActivity { super.onSaveInstanceState(outState); outState.putParcelable(FileActivity.EXTRA_FILE, mFile); outState.putParcelable(FileActivity.EXTRA_ACCOUNT, mAccount); + outState.putBoolean(FileActivity.EXTRA_FROM_NOTIFICATION, mFromNotification); } @@ -223,6 +230,12 @@ public abstract class FileActivity extends SherlockFragmentActivity { return mAccount; } + /** + * @return Value of mFromNotification: True if the Activity is launched by a notification + */ + public boolean fromNotification() { + return mFromNotification; + } /** * @return 'True' when the Activity is finishing to enforce the setup of a new account. diff --git a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java index 0bf82075..04f525ed 100644 --- a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java @@ -88,6 +88,7 @@ import com.owncloud.android.ui.fragment.OCFileListFragment; import com.owncloud.android.ui.preview.PreviewImageActivity; import com.owncloud.android.ui.preview.PreviewMediaFragment; import com.owncloud.android.ui.preview.PreviewVideoActivity; +import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.Log_OC; @@ -161,6 +162,8 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa // PIN CODE request ; best location is to decide, let's try this first if (getIntent().getAction() != null && getIntent().getAction().equals(Intent.ACTION_MAIN) && savedInstanceState == null) { requestPinCode(); + } else if (getIntent().getAction() == null && savedInstanceState == null) { + requestPinCode(); } /// file observer @@ -192,13 +195,16 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa // Action bar setup mDirectories = new CustomArrayAdapter(this, R.layout.sherlock_spinner_dropdown_item); getSupportActionBar().setHomeButtonEnabled(true); // mandatory since Android ICS, according to the official documentation - setSupportProgressBarIndeterminateVisibility(mSyncInProgress); // always AFTER setContentView(...) ; to work around bug in its implementation - - + setSupportProgressBarIndeterminateVisibility(mSyncInProgress); // always AFTER setContentView(...) ; to work around bug in its implementation Log_OC.d(TAG, "onCreate() end"); } - + + @Override + protected void onStart() { + super.onStart(); + getSupportActionBar().setIcon(DisplayUtils.getSeasonalIconId()); + } @Override protected void onDestroy() { @@ -1151,19 +1157,6 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa } -// private void updateDisplayHomeAtSync(){ -// ActionBar actionBar = getSupportActionBar(); -// OCFile currentDir = getCurrentDir(); -// if (currentDir.getParentId() != DataStorageManager.ROOT_PARENT_ID) { -// actionBar.setHomeButtonEnabled(!mSyncInProgress); -// actionBar.setDisplayHomeAsUpEnabled(!mSyncInProgress); -// } -// else { -// actionBar.setHomeButtonEnabled(true); -// actionBar.setDisplayHomeAsUpEnabled(false); -// } -// } -// /** * {@inheritDoc} */ diff --git a/src/com/owncloud/android/ui/activity/GenericExplanationActivity.java b/src/com/owncloud/android/ui/activity/GenericExplanationActivity.java index b971c40c..901434e2 100644 --- a/src/com/owncloud/android/ui/activity/GenericExplanationActivity.java +++ b/src/com/owncloud/android/ui/activity/GenericExplanationActivity.java @@ -30,8 +30,10 @@ import android.widget.ListAdapter; import android.widget.ListView; import android.widget.TextView; +import com.actionbarsherlock.app.ActionBar; import com.actionbarsherlock.app.SherlockFragmentActivity; import com.owncloud.android.R; +import com.owncloud.android.utils.DisplayUtils; /** @@ -74,6 +76,9 @@ public class GenericExplanationActivity extends SherlockFragmentActivity { } else { listView.setVisibility(View.GONE); } + + ActionBar actionBar = getSupportActionBar(); + actionBar.setIcon(DisplayUtils.getSeasonalIconId()); } public class ExplanationListAdapterView extends ArrayAdapter { diff --git a/src/com/owncloud/android/ui/activity/LogHistoryActivity.java b/src/com/owncloud/android/ui/activity/LogHistoryActivity.java index e879cc7e..ca454d41 100644 --- a/src/com/owncloud/android/ui/activity/LogHistoryActivity.java +++ b/src/com/owncloud/android/ui/activity/LogHistoryActivity.java @@ -34,6 +34,7 @@ import com.actionbarsherlock.app.SherlockPreferenceActivity; import com.actionbarsherlock.view.MenuItem; import com.owncloud.android.R; import com.owncloud.android.ui.adapter.LogListAdapter; +import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.FileStorageUtils; @@ -50,6 +51,7 @@ public class LogHistoryActivity extends SherlockPreferenceActivity implements On setContentView(R.layout.log_send_file); setTitle("Log History"); ActionBar actionBar = getSherlock().getActionBar(); + actionBar.setIcon(DisplayUtils.getSeasonalIconId()); actionBar.setDisplayHomeAsUpEnabled(true); ListView listView = (ListView) findViewById(android.R.id.list); Button deleteHistoryButton = (Button) findViewById(R.id.deleteLogHistoryButton); diff --git a/src/com/owncloud/android/ui/activity/PinCodeActivity.java b/src/com/owncloud/android/ui/activity/PinCodeActivity.java index c962fb2f..39b973d0 100644 --- a/src/com/owncloud/android/ui/activity/PinCodeActivity.java +++ b/src/com/owncloud/android/ui/activity/PinCodeActivity.java @@ -18,8 +18,10 @@ package com.owncloud.android.ui.activity; import java.util.Arrays; +import com.actionbarsherlock.app.ActionBar; import com.actionbarsherlock.app.SherlockFragmentActivity; import com.owncloud.android.R; +import com.owncloud.android.utils.DisplayUtils; import android.app.AlertDialog; import android.content.DialogInterface; @@ -44,23 +46,23 @@ public class PinCodeActivity extends SherlockFragmentActivity { public final static String EXTRA_ACTIVITY = "com.owncloud.android.ui.activity.PinCodeActivity.ACTIVITY"; public final static String EXTRA_NEW_STATE = "com.owncloud.android.ui.activity.PinCodeActivity.NEW_STATE"; - Button bCancel; - TextView mPinHdr; - TextView mPinHdrExplanation; - EditText mText1; - EditText mText2; - EditText mText3; - EditText mText4; + private Button mBCancel; + private TextView mPinHdr; + private TextView mPinHdrExplanation; + private EditText mText1; + private EditText mText2; + private EditText mText3; + private EditText mText4; - String [] tempText ={"","","",""}; + private String [] mTempText ={"","","",""}; - String activity; + private String mActivity; - boolean confirmingPinCode = false; - boolean pinCodeChecked = false; - boolean newPasswordEntered = false; - boolean bChange = true; // to control that only one blocks jump - int tCounter ; // Count the number of attempts an user could introduce the PIN code + private boolean mConfirmingPinCode = false; + private boolean mPinCodeChecked = false; + private boolean mNewPasswordEntered = false; + private boolean mBChange = true; // to control that only one blocks jump + //private int mTCounter ; // Count the number of attempts an user could introduce the PIN code protected void onCreate(Bundle savedInstanceState) { @@ -68,9 +70,9 @@ public class PinCodeActivity extends SherlockFragmentActivity { setContentView(R.layout.pincodelock); Intent intent = getIntent(); - activity = intent.getStringExtra(EXTRA_ACTIVITY); + mActivity = intent.getStringExtra(EXTRA_ACTIVITY); - bCancel = (Button) findViewById(R.id.cancel); + mBCancel = (Button) findViewById(R.id.cancel); mPinHdr = (TextView) findViewById(R.id.pinHdr); mPinHdrExplanation = (TextView) findViewById(R.id.pinHdrExpl); mText1 = (EditText) findViewById(R.id.txt1); @@ -88,23 +90,23 @@ public class PinCodeActivity extends SherlockFragmentActivity { // In a previous version settings is allow from start if ( (appPrefs.getString("PrefPinCode1", null) == null ) ){ setChangePincodeView(true); - pinCodeChecked = true; - newPasswordEntered = true; + mPinCodeChecked = true; + mNewPasswordEntered = true; }else{ if (appPrefs.getBoolean("set_pincode", false)){ // pincode activated - if (activity.equals("preferences")){ + if (mActivity.equals("preferences")){ // PIN has been activated yet mPinHdr.setText(R.string.pincode_configure_your_pin); mPinHdrExplanation.setVisibility(View.VISIBLE); - pinCodeChecked = true ; // No need to check it + mPinCodeChecked = true ; // No need to check it setChangePincodeView(true); }else{ // PIN active - bCancel.setVisibility(View.INVISIBLE); - bCancel.setVisibility(View.GONE); + mBCancel.setVisibility(View.INVISIBLE); + mBCancel.setVisibility(View.GONE); mPinHdr.setText(R.string.pincode_enter_pin_code); mPinHdrExplanation.setVisibility(View.INVISIBLE); setChangePincodeView(false); @@ -114,28 +116,29 @@ public class PinCodeActivity extends SherlockFragmentActivity { // pincode removal mPinHdr.setText(R.string.pincode_remove_your_pincode); mPinHdrExplanation.setVisibility(View.INVISIBLE); - pinCodeChecked = false; + mPinCodeChecked = false; setChangePincodeView(true); } } setTextListeners(); - + ActionBar actionBar = getSupportActionBar(); + actionBar.setIcon(DisplayUtils.getSeasonalIconId()); } protected void setInitVars(){ - confirmingPinCode = false; - pinCodeChecked = false; - newPasswordEntered = false; + mConfirmingPinCode = false; + mPinCodeChecked = false; + mNewPasswordEntered = false; } protected void setInitView(){ - bCancel.setVisibility(View.INVISIBLE); - bCancel.setVisibility(View.GONE); + mBCancel.setVisibility(View.INVISIBLE); + mBCancel.setVisibility(View.GONE); mPinHdr.setText(R.string.pincode_enter_pin_code); mPinHdrExplanation.setVisibility(View.INVISIBLE); } @@ -144,8 +147,8 @@ public class PinCodeActivity extends SherlockFragmentActivity { protected void setChangePincodeView(boolean state){ if(state){ - bCancel.setVisibility(View.VISIBLE); - bCancel.setOnClickListener(new OnClickListener() { + mBCancel.setVisibility(View.VISIBLE); + mBCancel.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { @@ -192,8 +195,8 @@ public class PinCodeActivity extends SherlockFragmentActivity { @Override public void afterTextChanged(Editable s) { if (s.length() > 0) { - if (!confirmingPinCode){ - tempText[0] = mText1.getText().toString(); + if (!mConfirmingPinCode){ + mTempText[0] = mText1.getText().toString(); } mText2.requestFocus(); @@ -221,8 +224,8 @@ public class PinCodeActivity extends SherlockFragmentActivity { @Override public void afterTextChanged(Editable s) { if (s.length() > 0) { - if (!confirmingPinCode){ - tempText[1] = mText2.getText().toString(); + if (!mConfirmingPinCode){ + mTempText[1] = mText2.getText().toString(); } mText3.requestFocus(); @@ -234,16 +237,16 @@ public class PinCodeActivity extends SherlockFragmentActivity { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_DEL && bChange) { + if (keyCode == KeyEvent.KEYCODE_DEL && mBChange) { mText1.setText(""); mText1.requestFocus(); - if (!confirmingPinCode) - tempText[0] = ""; - bChange= false; + if (!mConfirmingPinCode) + mTempText[0] = ""; + mBChange= false; - }else if(!bChange){ - bChange=true; + }else if(!mBChange){ + mBChange=true; } return false; @@ -285,8 +288,8 @@ public class PinCodeActivity extends SherlockFragmentActivity { @Override public void afterTextChanged(Editable s) { if (s.length() > 0) { - if (!confirmingPinCode){ - tempText[2] = mText3.getText().toString(); + if (!mConfirmingPinCode){ + mTempText[2] = mText3.getText().toString(); } mText4.requestFocus(); } @@ -297,15 +300,15 @@ public class PinCodeActivity extends SherlockFragmentActivity { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_DEL && bChange) { + if (keyCode == KeyEvent.KEYCODE_DEL && mBChange) { mText2.requestFocus(); - if (!confirmingPinCode) - tempText[1] = ""; + if (!mConfirmingPinCode) + mTempText[1] = ""; mText2.setText(""); - bChange= false; + mBChange= false; - }else if(!bChange){ - bChange=true; + }else if(!mBChange){ + mBChange=true; } return false; @@ -353,18 +356,19 @@ public class PinCodeActivity extends SherlockFragmentActivity { public void afterTextChanged(Editable s) { if (s.length() > 0) { - if (!confirmingPinCode){ - tempText[3] = mText4.getText().toString(); + if (!mConfirmingPinCode){ + mTempText[3] = mText4.getText().toString(); } mText1.requestFocus(); - if (!pinCodeChecked){ - pinCodeChecked = checkPincode(); + if (!mPinCodeChecked){ + mPinCodeChecked = checkPincode(); } - if (pinCodeChecked && activity.equals("FileDisplayActivity")){ + if (mPinCodeChecked && + ( mActivity.equals("FileDisplayActivity") || mActivity.equals("PreviewImageActivity") ) ){ finish(); - } else if (pinCodeChecked){ + } else if (mPinCodeChecked){ Intent intent = getIntent(); String newState = intent.getStringExtra(EXTRA_NEW_STATE); @@ -380,7 +384,7 @@ public class PinCodeActivity extends SherlockFragmentActivity { }else{ - if (!confirmingPinCode){ + if (!mConfirmingPinCode){ pinCodeChangeRequest(); } else { @@ -400,15 +404,15 @@ public class PinCodeActivity extends SherlockFragmentActivity { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_DEL && bChange) { + if (keyCode == KeyEvent.KEYCODE_DEL && mBChange) { mText3.requestFocus(); - if (!confirmingPinCode) - tempText[2]=""; + if (!mConfirmingPinCode) + mTempText[2]=""; mText3.setText(""); - bChange= false; + mBChange= false; - }else if(!bChange){ - bChange=true; + }else if(!mBChange){ + mBChange=true; } return false; } @@ -453,7 +457,7 @@ public class PinCodeActivity extends SherlockFragmentActivity { clearBoxes(); mPinHdr.setText(R.string.pincode_reenter_your_pincode); mPinHdrExplanation.setVisibility(View.INVISIBLE); - confirmingPinCode =true; + mConfirmingPinCode =true; } @@ -469,16 +473,16 @@ public class PinCodeActivity extends SherlockFragmentActivity { String pText3 = appPrefs.getString("PrefPinCode3", null); String pText4 = appPrefs.getString("PrefPinCode4", null); - if ( tempText[0].equals(pText1) && - tempText[1].equals(pText2) && - tempText[2].equals(pText3) && - tempText[3].equals(pText4) ) { + if ( mTempText[0].equals(pText1) && + mTempText[1].equals(pText2) && + mTempText[2].equals(pText3) && + mTempText[3].equals(pText4) ) { return true; }else { - Arrays.fill(tempText, null); + Arrays.fill(mTempText, null); AlertDialog aDialog = new AlertDialog.Builder(this).create(); CharSequence errorSeq = getString(R.string.common_error); aDialog.setTitle(errorSeq); @@ -497,8 +501,8 @@ public class PinCodeActivity extends SherlockFragmentActivity { clearBoxes(); mPinHdr.setText(R.string.pincode_enter_pin_code); mPinHdrExplanation.setVisibility(View.INVISIBLE); - newPasswordEntered = true; - confirmingPinCode = false; + mNewPasswordEntered = true; + mConfirmingPinCode = false; } @@ -508,23 +512,23 @@ public class PinCodeActivity extends SherlockFragmentActivity { protected void confirmPincode(){ - confirmingPinCode = false; + mConfirmingPinCode = false; String rText1 = mText1.getText().toString(); String rText2 = mText2.getText().toString(); String rText3 = mText3.getText().toString(); String rText4 = mText4.getText().toString(); - if ( tempText[0].equals(rText1) && - tempText[1].equals(rText2) && - tempText[2].equals(rText3) && - tempText[3].equals(rText4) ) { + if ( mTempText[0].equals(rText1) && + mTempText[1].equals(rText2) && + mTempText[2].equals(rText3) && + mTempText[3].equals(rText4) ) { savePincodeAndExit(); } else { - Arrays.fill(tempText, null); + Arrays.fill(mTempText, null); AlertDialog aDialog = new AlertDialog.Builder(this).create(); CharSequence errorSeq = getString(R.string.common_error); aDialog.setTitle(errorSeq); @@ -581,10 +585,10 @@ public class PinCodeActivity extends SherlockFragmentActivity { SharedPreferences.Editor appPrefs = PreferenceManager .getDefaultSharedPreferences(getApplicationContext()).edit(); - appPrefs.putString("PrefPinCode1", tempText[0]); - appPrefs.putString("PrefPinCode2",tempText[1]); - appPrefs.putString("PrefPinCode3", tempText[2]); - appPrefs.putString("PrefPinCode4", tempText[3]); + appPrefs.putString("PrefPinCode1", mTempText[0]); + appPrefs.putString("PrefPinCode2",mTempText[1]); + appPrefs.putString("PrefPinCode3", mTempText[2]); + appPrefs.putString("PrefPinCode4", mTempText[3]); appPrefs.putBoolean("set_pincode",true); appPrefs.commit(); @@ -609,7 +613,7 @@ public class PinCodeActivity extends SherlockFragmentActivity { public boolean onKeyDown(int keyCode, KeyEvent event){ if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount()== 0){ - if (activity.equals("preferences")){ + if (mActivity.equals("preferences")){ SharedPreferences.Editor appPrefsE = PreferenceManager .getDefaultSharedPreferences(getApplicationContext()).edit(); diff --git a/src/com/owncloud/android/ui/activity/Preferences.java b/src/com/owncloud/android/ui/activity/Preferences.java index 678dad6d..05a631d0 100644 --- a/src/com/owncloud/android/ui/activity/Preferences.java +++ b/src/com/owncloud/android/ui/activity/Preferences.java @@ -17,8 +17,6 @@ */ package com.owncloud.android.ui.activity; -import java.util.Vector; - import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageInfo; @@ -38,8 +36,8 @@ import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuItem; import com.owncloud.android.R; import com.owncloud.android.db.DbHandler; +import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.Log_OC; -import com.owncloud.android.utils.OwnCloudSession; /** @@ -51,15 +49,11 @@ import com.owncloud.android.utils.OwnCloudSession; public class Preferences extends SherlockPreferenceActivity { private static final String TAG = "OwnCloudPreferences"; - private final int mNewSession = 47; - private final int mEditSession = 48; private DbHandler mDbHandler; - private Vector mSessions; private CheckBoxPreference pCode; //private CheckBoxPreference pLogging; //private Preference pLoggingHistory; private Preference pAboutApp; - private int mSelectedMenuItem; @SuppressWarnings("deprecation") @@ -67,10 +61,10 @@ public class Preferences extends SherlockPreferenceActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mDbHandler = new DbHandler(getBaseContext()); - mSessions = new Vector(); addPreferencesFromResource(R.xml.preferences); //populateAccountList(); ActionBar actionBar = getSherlock().getActionBar(); + actionBar.setIcon(DisplayUtils.getSeasonalIconId()); actionBar.setDisplayHomeAsUpEnabled(true); Preference p = findPreference("manage_account"); diff --git a/src/com/owncloud/android/ui/activity/UploadFilesActivity.java b/src/com/owncloud/android/ui/activity/UploadFilesActivity.java index 7c941e8e..7eff9b45 100644 --- a/src/com/owncloud/android/ui/activity/UploadFilesActivity.java +++ b/src/com/owncloud/android/ui/activity/UploadFilesActivity.java @@ -40,6 +40,7 @@ import com.owncloud.android.ui.dialog.IndeterminateProgressDialog; import com.owncloud.android.ui.fragment.ConfirmationDialogFragment; import com.owncloud.android.ui.fragment.LocalFileListFragment; import com.owncloud.android.ui.fragment.ConfirmationDialogFragment.ConfirmationDialogFragmentListener; +import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.FileStorageUtils; import com.owncloud.android.utils.Log_OC; @@ -111,6 +112,7 @@ public class UploadFilesActivity extends FileActivity implements // Action bar setup ActionBar actionBar = getSupportActionBar(); + actionBar.setIcon(DisplayUtils.getSeasonalIconId()); actionBar.setHomeButtonEnabled(true); // mandatory since Android ICS, according to the official documentation actionBar.setDisplayHomeAsUpEnabled(mCurrentDir != null && mCurrentDir.getName() != null); actionBar.setDisplayShowTitleEnabled(false); diff --git a/src/com/owncloud/android/ui/activity/Uploader.java b/src/com/owncloud/android/ui/activity/Uploader.java index 08e2d215..85c9e40d 100644 --- a/src/com/owncloud/android/ui/activity/Uploader.java +++ b/src/com/owncloud/android/ui/activity/Uploader.java @@ -28,9 +28,6 @@ import java.util.Vector; import com.owncloud.android.MainApp; import com.owncloud.android.R; -import com.owncloud.android.R.id; -import com.owncloud.android.R.layout; -import com.owncloud.android.R.string; import com.owncloud.android.authentication.AccountAuthenticator; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; diff --git a/src/com/owncloud/android/ui/dialog/ChangelogDialog.java b/src/com/owncloud/android/ui/dialog/ChangelogDialog.java index 676bea57..eef9d09b 100644 --- a/src/com/owncloud/android/ui/dialog/ChangelogDialog.java +++ b/src/com/owncloud/android/ui/dialog/ChangelogDialog.java @@ -25,6 +25,7 @@ import android.webkit.WebView; import com.actionbarsherlock.app.SherlockDialogFragment; import com.owncloud.android.R; +import com.owncloud.android.utils.DisplayUtils; /** @@ -63,7 +64,7 @@ public class ChangelogDialog extends SherlockDialogFragment { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); Dialog dialog = builder.setView(webview) - .setIcon(R.drawable.icon) + .setIcon(DisplayUtils.getSeasonalIconId()) //.setTitle(R.string.whats_new) .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() { diff --git a/src/com/owncloud/android/ui/dialog/ConflictsResolveDialog.java b/src/com/owncloud/android/ui/dialog/ConflictsResolveDialog.java index 1998fcb8..91cfbfde 100644 --- a/src/com/owncloud/android/ui/dialog/ConflictsResolveDialog.java +++ b/src/com/owncloud/android/ui/dialog/ConflictsResolveDialog.java @@ -28,6 +28,7 @@ import android.support.v4.app.FragmentTransaction; import com.actionbarsherlock.app.SherlockDialogFragment; import com.actionbarsherlock.app.SherlockFragmentActivity; import com.owncloud.android.R; +import com.owncloud.android.utils.DisplayUtils; /** @@ -59,7 +60,7 @@ public class ConflictsResolveDialog extends SherlockDialogFragment { public Dialog onCreateDialog(Bundle savedInstanceState) { String remotepath = getArguments().getString("remotepath"); return new AlertDialog.Builder(getSherlockActivity()) - .setIcon(R.drawable.icon) + .setIcon(DisplayUtils.getSeasonalIconId()) .setTitle(R.string.conflict_title) .setMessage(String.format(getString(R.string.conflict_message), remotepath)) .setPositiveButton(R.string.conflict_overwrite, @@ -68,7 +69,7 @@ public class ConflictsResolveDialog extends SherlockDialogFragment { @Override public void onClick(DialogInterface dialog, int which) { if (mListener != null) - mListener.ConflictDecisionMade(Decision.OVERWRITE); + mListener.conflictDecisionMade(Decision.OVERWRITE); } }) .setNeutralButton(R.string.conflict_keep_both, @@ -76,7 +77,7 @@ public class ConflictsResolveDialog extends SherlockDialogFragment { @Override public void onClick(DialogInterface dialog, int which) { if (mListener != null) - mListener.ConflictDecisionMade(Decision.KEEP_BOTH); + mListener.conflictDecisionMade(Decision.KEEP_BOTH); } }) .setNegativeButton(R.string.conflict_dont_upload, @@ -84,7 +85,7 @@ public class ConflictsResolveDialog extends SherlockDialogFragment { @Override public void onClick(DialogInterface dialog, int which) { if (mListener != null) - mListener.ConflictDecisionMade(Decision.CANCEL); + mListener.conflictDecisionMade(Decision.CANCEL); } }) .create(); @@ -112,10 +113,10 @@ public class ConflictsResolveDialog extends SherlockDialogFragment { @Override public void onCancel(DialogInterface dialog) { - mListener.ConflictDecisionMade(Decision.CANCEL); + mListener.conflictDecisionMade(Decision.CANCEL); } public interface OnConflictDecisionMadeListener { - public void ConflictDecisionMade(Decision decision); + public void conflictDecisionMade(Decision decision); } } diff --git a/src/com/owncloud/android/ui/preview/PreviewImageActivity.java b/src/com/owncloud/android/ui/preview/PreviewImageActivity.java index fde70df0..edafa65d 100644 --- a/src/com/owncloud/android/ui/preview/PreviewImageActivity.java +++ b/src/com/owncloud/android/ui/preview/PreviewImageActivity.java @@ -22,8 +22,10 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; +import android.content.SharedPreferences; import android.os.Bundle; import android.os.IBinder; +import android.preference.PreferenceManager; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; @@ -45,8 +47,10 @@ import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder; import com.owncloud.android.files.services.FileUploader.FileUploaderBinder; import com.owncloud.android.ui.activity.FileActivity; import com.owncloud.android.ui.activity.FileDisplayActivity; +import com.owncloud.android.ui.activity.PinCodeActivity; import com.owncloud.android.ui.dialog.LoadingDialog; import com.owncloud.android.ui.fragment.FileFragment; +import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.Log_OC; @@ -90,9 +94,15 @@ public class PreviewImageActivity extends FileActivity implements FileFragment.C setContentView(R.layout.preview_image_activity); ActionBar actionBar = getSupportActionBar(); + actionBar.setIcon(DisplayUtils.getSeasonalIconId()); actionBar.setDisplayHomeAsUpEnabled(true); actionBar.hide(); + // PIN CODE request + if (getIntent().getExtras() != null && savedInstanceState == null && fromNotification()) { + requestPinCode(); + } + mFullScreen = true; if (savedInstanceState != null) { mRequestWaitingForBinder = savedInstanceState.getBoolean(KEY_WAITING_FOR_BINDER); @@ -457,4 +467,18 @@ public class PreviewImageActivity extends FileActivity implements FileFragment.C } + /** + * Launch an intent to request the PIN code to the user before letting him use the app + */ + private void requestPinCode() { + boolean pinStart = false; + SharedPreferences appPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); + pinStart = appPrefs.getBoolean("set_pincode", false); + if (pinStart) { + Intent i = new Intent(getApplicationContext(), PinCodeActivity.class); + i.putExtra(PinCodeActivity.EXTRA_ACTIVITY, "PreviewImageActivity"); + startActivity(i); + } + } + } diff --git a/src/com/owncloud/android/utils/DisplayUtils.java b/src/com/owncloud/android/utils/DisplayUtils.java index e4bdd999..680107b8 100644 --- a/src/com/owncloud/android/utils/DisplayUtils.java +++ b/src/com/owncloud/android/utils/DisplayUtils.java @@ -19,13 +19,13 @@ package com.owncloud.android.utils; import java.util.Arrays; +import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Set; import com.owncloud.android.R; -import com.owncloud.android.R.drawable; /** * A helper class for some string operations. @@ -190,4 +190,13 @@ public class DisplayUtils { Date date = new Date(milliseconds); return date.toLocaleString(); } + + + public static int getSeasonalIconId() { + if (Calendar.getInstance().get(Calendar.DAY_OF_YEAR) >= 354) { + return R.drawable.winter_holidays_icon; + } else { + return R.drawable.icon; + } + } } diff --git a/src/com/owncloud/android/utils/FileStorageUtils.java b/src/com/owncloud/android/utils/FileStorageUtils.java index 25206443..d4042f50 100644 --- a/src/com/owncloud/android/utils/FileStorageUtils.java +++ b/src/com/owncloud/android/utils/FileStorageUtils.java @@ -22,6 +22,7 @@ import java.io.File; import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.oc_framework.operations.RemoteFile; import android.annotation.SuppressLint; import android.content.Context; @@ -82,5 +83,38 @@ public class FileStorageUtils { parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath : parentPath + OCFile.PATH_SEPARATOR; return parentPath; } + + /** + * Creates and populates a new {@link OCFile} object with the data read from the server. + * + * @param remote remote file read from the server (remote file or folder). + * @return New OCFile instance representing the remote resource described by we. + */ + public static OCFile fillOCFile(RemoteFile remote) { + OCFile file = new OCFile(remote.getRemotePath()); + file.setCreationTimestamp(remote.getCreationTimestamp()); + file.setFileLength(remote.getLength()); + file.setMimetype(remote.getMimeType()); + file.setModificationTimestamp(remote.getModifiedTimestamp()); + file.setEtag(remote.getEtag()); + + return file; + } + + /** + * Creates and populates a new {@link RemoteFile} object with the data read from an {@link OCFile}. + * + * @param oCFile OCFile + * @return New RemoteFile instance representing the resource described by ocFile. + */ + public static RemoteFile fillRemoteFile(OCFile ocFile){ + RemoteFile file = new RemoteFile(ocFile.getRemotePath()); + file.setCreationTimestamp(ocFile.getCreationTimestamp()); + file.setLength(ocFile.getFileLength()); + file.setMimeType(ocFile.getMimetype()); + file.setModifiedTimestamp(ocFile.getModificationTimestamp()); + file.setEtag(ocFile.getEtag()); + return file; + } } \ No newline at end of file