From: David A. Velasco Date: Wed, 22 Apr 2015 09:01:52 +0000 (+0200) Subject: Merge pull request #957 from owncloud/fix_crash_invalid_server_url X-Git-Tag: test~29 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/2fcffbd3d580f41ecc114248f4d74a19a34b622b?hp=870b8c0726b80ed84b951b698e4801c5fc078294 Merge pull request #957 from owncloud/fix_crash_invalid_server_url Fix crash when typed invalid URL --- diff --git a/oc_jb_workaround/AndroidManifest.xml b/oc_jb_workaround/AndroidManifest.xml index c08002c4..65fc3648 100644 --- a/oc_jb_workaround/AndroidManifest.xml +++ b/oc_jb_workaround/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="0100023" + android:versionName="1.0.23" > Настъпи грешка при опита за споделяне на този файл или папка. Неуспешен опит за прекратяване на споделянето. Моля, провери дали файла съществува. Настъпи грешка при опита за премахване на споделянето на този файл или папка. + Въведи Парола + Вие трябва да въведете парола Изпращане Копиране на връзката Копирана @@ -300,5 +302,7 @@ Сигурност Качване на видео път Свалянето на директорията %1$s не може да бъде завършено + %1$s споделено \"%2$s\" с теб + Обнови връзката Адрес на сървъра diff --git a/res/values-et-rEE/strings.xml b/res/values-et-rEE/strings.xml index b3ad7dd8..d7fa6ac8 100644 --- a/res/values-et-rEE/strings.xml +++ b/res/values-et-rEE/strings.xml @@ -165,6 +165,7 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi Võrguühendust pole Turvaline ühendus pole saadaval Saadi ühendus + Ühenduse testimine Vigases vormingus server seadistus Sama konto kasutaja ja server on juba selles seadmes olemas Sisestatud kasutaja ei kattu selle konto kasutajaga @@ -191,6 +192,7 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi Server ei tagasta korrektset kasutaja ID-d. Palun kontakteeru administraatoriga. ⇥ Ei suuda autoriseerida selle serveriga. + Kontot pole veel seadmes Hoia faili ajakohasena Nimeta ümber Eemalda @@ -264,6 +266,8 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi Faili või kausta jagamisel esines viga Liigutamise lõpetamine ebaõnnestus. Palun kontrolli, kas fail on olemas Faili või kausta jagamise tühistamisel esines viga + Sisesta parool + Sa pead parooli sisestama Saada Kopeeri link Kopeeritud lõikepuhvrisse @@ -286,6 +290,9 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi Turvaline ühendus suunatakse läbi turvamata ühenduse. Logid Saada ajalugu + Logide saatmise rakendust ei leitud. Paigalda postirakendus! + %1$s Androidi rakenduse logid + Andmete laadimine... Autentimine on vajalik Vale parool Tõsta ümber @@ -298,5 +305,9 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi selle faili liigutamiseks Kohesed üleslaadimised Turvalisus + Video üleslaadimise asukoht + Kausta %1$s allalaadimine ei õnnestunud + %1$s jagas sinuga \"%2$s\" + Värskenda ühendust Serveri aadress diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml index 055fa978..72ead355 100644 --- a/res/values-zh-rTW/strings.xml +++ b/res/values-zh-rTW/strings.xml @@ -161,6 +161,7 @@ 沒有網際網路連線 安全連線不可用。 連線已建立 + 測試連線 伺服器設定有問題 已經有相同使用者與伺服器的帳號存在於這個裝置 輸入的使用者與這個帳戶的使用者不一致 @@ -187,6 +188,7 @@ 你的伺服器並沒有傳回正確的使用者 ID, 請聯絡伺服器的管理員 無法在這個伺服器上取得認證 + 帳號目前不存在於本裝置 讓檔案保持最新的 重新命名 移除 @@ -260,6 +262,8 @@ 在分享檔案或目錄時發生了錯誤 無法取消分享這個檔案或目錄. 請檢查它們是否存在 在取消分享檔案或目錄時發生了錯誤 + 輸入密碼 + 您必須輸入密碼 寄出 複製連結 複製至剪貼簿中 @@ -299,5 +303,7 @@ 安全性 影片上傳路徑 %1$s 目錄的下載未完成 + %1$s 分享了 \"%2$s\" 給您 + 重新連線 伺服器位址 diff --git a/src/com/owncloud/android/authentication/AccountUtils.java b/src/com/owncloud/android/authentication/AccountUtils.java index bd3a8e79..1e67aa67 100644 --- a/src/com/owncloud/android/authentication/AccountUtils.java +++ b/src/com/owncloud/android/authentication/AccountUtils.java @@ -24,24 +24,28 @@ import java.util.Locale; import com.owncloud.android.MainApp; import com.owncloud.android.lib.common.accounts.AccountTypeUtils; +import com.owncloud.android.lib.common.accounts.AccountUtils.Constants; +import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.resources.status.OwnCloudVersion; import android.accounts.Account; import android.accounts.AccountManager; import android.content.Context; import android.content.SharedPreferences; +import android.net.Uri; import android.preference.PreferenceManager; public class AccountUtils { - public static final String WEBDAV_PATH_1_2 = "/webdav/owncloud.php"; - public static final String WEBDAV_PATH_2_0 = "/files/webdav.php"; - public static final String WEBDAV_PATH_4_0 = "/remote.php/webdav"; + + private static final String TAG = AccountUtils.class.getSimpleName(); + + public static final String WEBDAV_PATH_4_0_AND_LATER = "/remote.php/webdav"; private static final String ODAV_PATH = "/remote.php/odav"; private static final String SAML_SSO_PATH = "/remote.php/webdav"; - public static final String CARDDAV_PATH_2_0 = "/apps/contacts/carddav.php"; - public static final String CARDDAV_PATH_4_0 = "/remote/carddav.php"; public static final String STATUS_PATH = "/status.php"; + public static final int ACCOUNT_VERSION = 1; + /** * Can be used to get the currently selected ownCloud {@link Account} in the * application preferences. @@ -105,19 +109,6 @@ public class AccountUtils { } - /** - * Checks, whether or not there are any ownCloud accounts setup. - * - * @return true, if there is at least one account. - */ - public static boolean accountsAreSetup(Context context) { - AccountManager accMan = AccountManager.get(context); - Account[] accounts = accMan - .getAccountsByType(MainApp.getAccountType()); - return accounts.length > 0; - } - - public static boolean setCurrentOwnCloudAccount(Context context, String accountName) { boolean result = false; if (accountName != null) { @@ -145,8 +136,10 @@ public class AccountUtils { * according to its version and the authorization method used. * * @param version Version of ownCloud server. - * @param authTokenType Authorization token type, matching some of the AUTH_TOKEN_TYPE_* constants in {@link AccountAuthenticator}. - * @return WebDAV path for given OC version and authorization method, null if OC version is unknown. + * @param authTokenType Authorization token type, matching some of the AUTH_TOKEN_TYPE_* constants in + * {@link AccountAuthenticator}. + * @return WebDAV path for given OC version and authorization method, null if OC version + * is unknown; versions prior to ownCloud 4 are not supported anymore */ public static String getWebdavPath(OwnCloudVersion version, String authTokenType) { if (version != null) { @@ -156,15 +149,105 @@ public class AccountUtils { if (AccountTypeUtils.getAuthTokenTypeSamlSessionCookie(MainApp.getAccountType()).equals(authTokenType)) { return SAML_SSO_PATH; } - if (version.compareTo(OwnCloudVersion.owncloud_v4) >= 0) - return WEBDAV_PATH_4_0; - if (version.compareTo(OwnCloudVersion.owncloud_v3) >= 0 - || version.compareTo(OwnCloudVersion.owncloud_v2) >= 0) - return WEBDAV_PATH_2_0; - if (version.compareTo(OwnCloudVersion.owncloud_v1) >= 0) - return WEBDAV_PATH_1_2; + return WEBDAV_PATH_4_0_AND_LATER; } return null; } - + + + /** + * Update the accounts in AccountManager to meet the current version of accounts expected by the app, if needed. + * + * Introduced to handle a change in the structure of stored account names needed to allow different OC servers + * in the same domain, but not in the same path. + * + * @param context Used to access the AccountManager. + */ + public static void updateAccountVersion(Context context) { + Account currentAccount = AccountUtils.getCurrentOwnCloudAccount(context); + AccountManager accountMgr = AccountManager.get(context); + + if ( currentAccount != null ) { + String currentAccountVersion = accountMgr.getUserData(currentAccount, Constants.KEY_OC_ACCOUNT_VERSION); + + if (currentAccountVersion == null) { + Log_OC.i(TAG, "Upgrading accounts to account version #" + ACCOUNT_VERSION); + Account[] ocAccounts = accountMgr.getAccountsByType(MainApp.getAccountType()); + String serverUrl, username, newAccountName, password; + Account newAccount; + for (Account account : ocAccounts) { + // build new account name + serverUrl = accountMgr.getUserData(account, Constants.KEY_OC_BASE_URL); + username = account.name.substring(0, account.name.lastIndexOf('@')); + newAccountName = com.owncloud.android.lib.common.accounts.AccountUtils. + buildAccountName(Uri.parse(serverUrl), username); + + // migrate to a new account, if needed + if (!newAccountName.equals(account.name)) { + Log_OC.d(TAG, "Upgrading " + account.name + " to " + newAccountName); + + // create the new account + newAccount = new Account(newAccountName, MainApp.getAccountType()); + password = accountMgr.getPassword(account); + accountMgr.addAccountExplicitly(newAccount, (password != null) ? password : "", null); + + // copy base URL + accountMgr.setUserData(newAccount, Constants.KEY_OC_BASE_URL, serverUrl); + + // copy server version + accountMgr.setUserData( + newAccount, + Constants.KEY_OC_VERSION, + accountMgr.getUserData(account, Constants.KEY_OC_VERSION) + ); + + // copy cookies + accountMgr.setUserData( + newAccount, + Constants.KEY_COOKIES, + accountMgr.getUserData(account, Constants.KEY_COOKIES) + ); + + // copy type of authentication + String isSamlStr = accountMgr.getUserData(account, Constants.KEY_SUPPORTS_SAML_WEB_SSO); + boolean isSaml = "TRUE".equals(isSamlStr); + if (isSaml) { + accountMgr.setUserData(newAccount, Constants.KEY_SUPPORTS_SAML_WEB_SSO, "TRUE"); + } + + String isOauthStr = accountMgr.getUserData(account, Constants.KEY_SUPPORTS_OAUTH2); + boolean isOAuth = "TRUE".equals(isOauthStr); + if (isOAuth) { + accountMgr.setUserData(newAccount, Constants.KEY_SUPPORTS_OAUTH2, "TRUE"); + } + /* TODO - study if it's possible to run this method in a background thread to copy the authToken + if (isOAuth || isSaml) { + accountMgr.setAuthToken(newAccount, mAuthTokenType, mAuthToken); + } + */ + + // don't forget the account saved in preferences as the current one + if (currentAccount != null && currentAccount.name.equals(account.name)) { + AccountUtils.setCurrentOwnCloudAccount(context, newAccountName); + } + + // remove the old account + accountMgr.removeAccount(account, null, null); // will assume it succeeds, not a big deal otherwise + + } else { + // servers which base URL is in the root of their domain need no change + Log_OC.d(TAG, account.name + " needs no upgrade "); + newAccount = account; + } + + // at least, upgrade account version + Log_OC.d(TAG, "Setting version " + ACCOUNT_VERSION + " to " + newAccountName); + accountMgr.setUserData(newAccount, Constants.KEY_OC_ACCOUNT_VERSION, Integer.toString(ACCOUNT_VERSION)); + + } + } + } + } + + } diff --git a/src/com/owncloud/android/authentication/AuthenticatorActivity.java b/src/com/owncloud/android/authentication/AuthenticatorActivity.java index ccb0f854..713851ba 100644 --- a/src/com/owncloud/android/authentication/AuthenticatorActivity.java +++ b/src/com/owncloud/android/authentication/AuthenticatorActivity.java @@ -1120,13 +1120,9 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity // TODO remove, if possible private String trimUrlWebdav(String url){ - if(url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_4_0)){ - url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_4_0.length()); - } else if(url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_2_0)){ - url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_2_0.length()); - } else if (url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_1_2)){ - url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_1_2.length()); - } + if(url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_4_0_AND_LATER)){ + url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_4_0_AND_LATER.length()); + } return (url != null ? url : ""); } @@ -1488,6 +1484,13 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity ); } + // include account version with the new account + mAccountMgr.setUserData( + mAccount, + Constants.KEY_OC_ACCOUNT_VERSION, + Integer.toString(AccountUtils.ACCOUNT_VERSION) + ); + /// add the new account as default in preferences, if there is none already Account defaultAccount = AccountUtils.getCurrentOwnCloudAccount(this); if (defaultAccount == null) { diff --git a/src/com/owncloud/android/datamodel/FileDataStorageManager.java b/src/com/owncloud/android/datamodel/FileDataStorageManager.java index a197e080..c32dbbce 100644 --- a/src/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/src/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -168,7 +168,6 @@ public class FileDataStorageManager { return ret; } - public boolean saveFile(OCFile file) { boolean overriden = false; ContentValues cv = new ContentValues(); diff --git a/src/com/owncloud/android/db/ProviderMeta.java b/src/com/owncloud/android/db/ProviderMeta.java index 1f789d14..25e8fbd1 100644 --- a/src/com/owncloud/android/db/ProviderMeta.java +++ b/src/com/owncloud/android/db/ProviderMeta.java @@ -31,7 +31,7 @@ import com.owncloud.android.MainApp; public class ProviderMeta { public static final String DB_NAME = "filelist"; - public static final int DB_VERSION = 9; + public static final int DB_VERSION = 10; private ProviderMeta() { } diff --git a/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java b/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java index b52c36d9..47f7127b 100644 --- a/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java +++ b/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java @@ -89,7 +89,7 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver { Account account = AccountUtils.getCurrentOwnCloudAccount(context); if (account == null) { - Log_OC.w(TAG, "No owncloud account found for instant upload, aborting"); + Log_OC.w(TAG, "No ownCloud account found for instant upload, aborting"); return; } diff --git a/src/com/owncloud/android/operations/GetServerInfoOperation.java b/src/com/owncloud/android/operations/GetServerInfoOperation.java index 8e911000..1b4b7a9b 100644 --- a/src/com/owncloud/android/operations/GetServerInfoOperation.java +++ b/src/com/owncloud/android/operations/GetServerInfoOperation.java @@ -23,7 +23,6 @@ package com.owncloud.android.operations; import java.util.ArrayList; -import com.owncloud.android.MainApp; import com.owncloud.android.authentication.AccountUtils; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperation; @@ -118,12 +117,8 @@ public class GetServerInfoOperation extends RemoteOperation { if (url.endsWith("/")) { url = url.substring(0, url.length() - 1); } - if(url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_4_0)){ - url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_4_0.length()); - } else if(url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_2_0)){ - url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_2_0.length()); - } else if (url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_1_2)){ - url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_1_2.length()); + if(url.toLowerCase().endsWith(AccountUtils.WEBDAV_PATH_4_0_AND_LATER)){ + url = url.substring(0, url.length() - AccountUtils.WEBDAV_PATH_4_0_AND_LATER.length()); } } return url; diff --git a/src/com/owncloud/android/providers/FileContentProvider.java b/src/com/owncloud/android/providers/FileContentProvider.java index 737c6646..a4e50cec 100644 --- a/src/com/owncloud/android/providers/FileContentProvider.java +++ b/src/com/owncloud/android/providers/FileContentProvider.java @@ -22,15 +22,23 @@ package com.owncloud.android.providers; +import java.io.File; +import java.security.Provider; import java.util.ArrayList; import java.util.HashMap; +import com.owncloud.android.MainApp; import com.owncloud.android.R; +import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.db.ProviderMeta; import com.owncloud.android.db.ProviderMeta.ProviderTableMeta; +import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.resources.shares.ShareType; +import com.owncloud.android.utils.FileStorageUtils; +import android.accounts.Account; +import android.accounts.AccountManager; import android.content.ContentProvider; import android.content.ContentProviderOperation; import android.content.ContentProviderResult; @@ -85,7 +93,7 @@ public class FileContentProvider extends ContentProvider { ProviderTableMeta.FILE_KEEP_IN_SYNC); mFileProjectionMap.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, ProviderTableMeta.FILE_ACCOUNT_OWNER); - mFileProjectionMap.put(ProviderTableMeta.FILE_ETAG, + mFileProjectionMap.put(ProviderTableMeta.FILE_ETAG, ProviderTableMeta.FILE_ETAG); mFileProjectionMap.put(ProviderTableMeta.FILE_SHARE_BY_LINK, ProviderTableMeta.FILE_SHARE_BY_LINK); @@ -107,7 +115,7 @@ public class FileContentProvider extends ContentProvider { private static final int SHARES = 4; private static final String TAG = FileContentProvider.class.getSimpleName(); - + // Projection for ocshares table private static HashMap mOCSharesProjectionMap; static { @@ -142,9 +150,9 @@ public class FileContentProvider extends ContentProvider { mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, ProviderTableMeta.OCSHARES_ACCOUNT_OWNER); } - + private UriMatcher mUriMatcher; - + @Override public int delete(Uri uri, String where, String[] whereArgs) { //Log_OC.d(TAG, "Deleting " + uri + " at provider " + this); @@ -160,7 +168,7 @@ public class FileContentProvider extends ContentProvider { getContext().getContentResolver().notifyChange(uri, null); return count; } - + private int delete(SQLiteDatabase db, Uri uri, String where, String[] whereArgs) { int count = 0; switch (mUriMatcher.match(uri)) { @@ -199,7 +207,6 @@ public class FileContentProvider extends ContentProvider { if (children != null && children.moveToFirst()) { long childId; boolean isDir; - //String remotePath; while (!children.isAfterLast()) { childId = children.getLong(children.getColumnIndex(ProviderTableMeta._ID)); isDir = "DIR".equals(children.getString( @@ -208,16 +215,16 @@ public class FileContentProvider extends ContentProvider { //remotePath = children.getString(children.getColumnIndex(ProviderTableMeta.FILE_PATH)); if (isDir) { count += delete( - db, - ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, childId), - null, + db, + ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, childId), + null, null ); } else { count += delete( - db, + db, ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, childId), - null, + null, null ); } @@ -281,7 +288,7 @@ public class FileContentProvider extends ContentProvider { getContext().getContentResolver().notifyChange(newUri, null); return newUri; } - + private Uri insert(SQLiteDatabase db, Uri uri, ContentValues values) { switch (mUriMatcher.match(uri)){ case ROOT_DIRECTORY: @@ -289,19 +296,19 @@ public class FileContentProvider extends ContentProvider { String remotePath = values.getAsString(ProviderTableMeta.FILE_PATH); String accountName = values.getAsString(ProviderTableMeta.FILE_ACCOUNT_OWNER); String[] projection = new String[] { - ProviderTableMeta._ID, ProviderTableMeta.FILE_PATH, - ProviderTableMeta.FILE_ACCOUNT_OWNER + ProviderTableMeta._ID, ProviderTableMeta.FILE_PATH, + ProviderTableMeta.FILE_ACCOUNT_OWNER }; - String where = ProviderTableMeta.FILE_PATH + "=? AND " + + String where = ProviderTableMeta.FILE_PATH + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?"; String[] whereArgs = new String[] {remotePath, accountName}; Cursor doubleCheck = query(db, uri, projection, where, whereArgs, null); - // ugly patch; serious refactorization is needed to reduce work in + // ugly patch; serious refactorization is needed to reduce work in // FileDataStorageManager and bring it to FileContentProvider - if (doubleCheck == null || !doubleCheck.moveToFirst()) { + if (doubleCheck == null || !doubleCheck.moveToFirst()) { long rowId = db.insert(ProviderTableMeta.FILE_TABLE_NAME, null, values); if (rowId > 0) { - Uri insertedFileUri = + Uri insertedFileUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, rowId); return insertedFileUri; } else { @@ -310,33 +317,33 @@ public class FileContentProvider extends ContentProvider { } else { // file is already inserted; race condition, let's avoid a duplicated entry Uri insertedFileUri = ContentUris.withAppendedId( - ProviderTableMeta.CONTENT_URI_FILE, + ProviderTableMeta.CONTENT_URI_FILE, doubleCheck.getLong(doubleCheck.getColumnIndex(ProviderTableMeta._ID)) ); doubleCheck.close(); return insertedFileUri; } - + case SHARES: String path = values.getAsString(ProviderTableMeta.OCSHARES_PATH); String accountNameShare= values.getAsString(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER); String[] projectionShare = new String[] { - ProviderTableMeta._ID, ProviderTableMeta.OCSHARES_PATH, - ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + ProviderTableMeta._ID, ProviderTableMeta.OCSHARES_PATH, + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER }; - String whereShare = ProviderTableMeta.OCSHARES_PATH + "=? AND " + + String whereShare = ProviderTableMeta.OCSHARES_PATH + "=? AND " + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?"; String[] whereArgsShare = new String[] {path, accountNameShare}; Uri insertedShareUri = null; - Cursor doubleCheckShare = + Cursor doubleCheckShare = query(db, uri, projectionShare, whereShare, whereArgsShare, null); - // ugly patch; serious refactorization is needed to reduce work in + // ugly patch; serious refactorization is needed to reduce work in // FileDataStorageManager and bring it to FileContentProvider - if (doubleCheckShare == null || !doubleCheckShare.moveToFirst()) { + if (doubleCheckShare == null || !doubleCheckShare.moveToFirst()) { long rowId = db.insert(ProviderTableMeta.OCSHARES_TABLE_NAME, null, values); if (rowId >0) { - insertedShareUri = + insertedShareUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_SHARE, rowId); } else { throw new SQLException("ERROR " + uri); @@ -345,7 +352,7 @@ public class FileContentProvider extends ContentProvider { } else { // file is already inserted; race condition, let's avoid a duplicated entry insertedShareUri = ContentUris.withAppendedId( - ProviderTableMeta.CONTENT_URI_SHARE, + ProviderTableMeta.CONTENT_URI_SHARE, doubleCheckShare.getLong( doubleCheckShare.getColumnIndex(ProviderTableMeta._ID) ) @@ -354,37 +361,37 @@ public class FileContentProvider extends ContentProvider { } updateFilesTableAccordingToShareInsertion(db, uri, values); return insertedShareUri; - + default: throw new IllegalArgumentException("Unknown uri id: " + uri); } - + } - + private void updateFilesTableAccordingToShareInsertion( SQLiteDatabase db, Uri uri, ContentValues shareValues ) { ContentValues fileValues = new ContentValues(); fileValues.put( - ProviderTableMeta.FILE_SHARE_BY_LINK, - ShareType.PUBLIC_LINK.getValue() == - shareValues.getAsInteger(ProviderTableMeta.OCSHARES_SHARE_TYPE)? 1 : 0 + ProviderTableMeta.FILE_SHARE_BY_LINK, + ShareType.PUBLIC_LINK.getValue() == + shareValues.getAsInteger(ProviderTableMeta.OCSHARES_SHARE_TYPE) ? 1 : 0 ); - String whereShare = ProviderTableMeta.FILE_PATH + "=? AND " + + String whereShare = ProviderTableMeta.FILE_PATH + "=? AND " + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?"; String[] whereArgsShare = new String[] { - shareValues.getAsString(ProviderTableMeta.OCSHARES_PATH), + shareValues.getAsString(ProviderTableMeta.OCSHARES_PATH), shareValues.getAsString(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER) }; db.update(ProviderTableMeta.FILE_TABLE_NAME, fileValues, whereShare, whereArgsShare); } - + @Override public boolean onCreate() { mDbHelper = new DataBaseHelper(getContext()); - + String authority = getContext().getResources().getString(R.string.authority); mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); mUriMatcher.addURI(authority, null, ROOT_DIRECTORY); @@ -394,20 +401,20 @@ public class FileContentProvider extends ContentProvider { mUriMatcher.addURI(authority, "dir/#", DIRECTORY); mUriMatcher.addURI(authority, "shares/", SHARES); mUriMatcher.addURI(authority, "shares/#", SHARES); - + return true; } - + @Override public Cursor query( - Uri uri, - String[] projection, - String selection, - String[] selectionArgs, + Uri uri, + String[] projection, + String selection, + String[] selectionArgs, String sortOrder ) { - + Cursor result = null; SQLiteDatabase db = mDbHelper.getReadableDatabase(); db.beginTransaction(); @@ -419,16 +426,16 @@ public class FileContentProvider extends ContentProvider { } return result; } - + private Cursor query( - SQLiteDatabase db, - Uri uri, - String[] projection, - String selection, - String[] selectionArgs, + SQLiteDatabase db, + Uri uri, + String[] projection, + String selection, + String[] selectionArgs, String sortOrder ) { - + SQLiteQueryBuilder sqlQuery = new SQLiteQueryBuilder(); sqlQuery.setTables(ProviderTableMeta.FILE_TABLE_NAME); @@ -448,7 +455,7 @@ public class FileContentProvider extends ContentProvider { + uri.getPathSegments().get(1)); } break; - case SHARES: + case SHARES: sqlQuery.setTables(ProviderTableMeta.OCSHARES_TABLE_NAME); sqlQuery.setProjectionMap(mOCSharesProjectionMap); if (uri.getPathSegments().size() > 1) { @@ -481,7 +488,7 @@ public class FileContentProvider extends ContentProvider { @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - + int count = 0; SQLiteDatabase db = mDbHelper.getWritableDatabase(); db.beginTransaction(); @@ -494,14 +501,14 @@ public class FileContentProvider extends ContentProvider { getContext().getContentResolver().notifyChange(uri, null); return count; } - - + + private int update( - SQLiteDatabase db, - Uri uri, - ContentValues values, - String selection, + SQLiteDatabase db, + Uri uri, + ContentValues values, + String selection, String[] selectionArgs ) { switch (mUriMatcher.match(uri)) { @@ -516,14 +523,14 @@ public class FileContentProvider extends ContentProvider { ProviderTableMeta.FILE_TABLE_NAME, values, selection, selectionArgs ); } - } + } - /* + /* private int updateFolderSize(SQLiteDatabase db, String folderId) { int count = 0; String [] whereArgs = new String[] { folderId }; - - // read current size saved for the folder + + // read current size saved for the folder long folderSize = 0; long folderParentId = -1; Uri selectFolderUri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, folderId); @@ -535,7 +542,7 @@ public class FileContentProvider extends ContentProvider { folderParentId = folderCursor.getLong(folderCursor.getColumnIndex(ProviderTableMeta.FILE_PARENT));; } folderCursor.close(); - + // read and sum sizes of children long childrenSize = 0; Uri selectChildrenUri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, folderId); @@ -549,14 +556,14 @@ public class FileContentProvider extends ContentProvider { } } childrenCursor.close(); - + // update if needed if (folderSize != childrenSize) { Log_OC.d("FileContentProvider", "Updating " + folderSize + " to " + childrenSize); ContentValues cv = new ContentValues(); cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, childrenSize); count = db.update(ProviderTableMeta.FILE_TABLE_NAME, cv, folderWhere, whereArgs); - + // propagate update until root if (folderParentId > FileDataStorageManager.ROOT_PARENT_ID) { Log_OC.d("FileContentProvider", "Propagating update to " + folderParentId); @@ -570,15 +577,15 @@ public class FileContentProvider extends ContentProvider { return count; } */ - + @Override - public ContentProviderResult[] applyBatch (ArrayList operations) + public ContentProviderResult[] applyBatch (ArrayList operations) throws OperationApplicationException { - Log_OC.d("FileContentProvider", "applying batch in provider " + this + + Log_OC.d("FileContentProvider", "applying batch in provider " + this + " (temporary: " + isTemporary() + ")" ); ContentProviderResult[] results = new ContentProviderResult[operations.size()]; int i=0; - + SQLiteDatabase db = mDbHelper.getWritableDatabase(); db.beginTransaction(); // it's supposed that transactions can be nested try { @@ -621,7 +628,7 @@ public class FileContentProvider extends ContentProvider { + ProviderTableMeta.FILE_KEEP_IN_SYNC + " INTEGER, " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " INTEGER, " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " INTEGER, " - + ProviderTableMeta.FILE_ETAG + " TEXT, " + + ProviderTableMeta.FILE_ETAG + " TEXT, " + ProviderTableMeta.FILE_SHARE_BY_LINK + " INTEGER, " + ProviderTableMeta.FILE_PUBLIC_LINK + " TEXT, " + ProviderTableMeta.FILE_PERMISSIONS + " TEXT null," @@ -629,7 +636,7 @@ public class FileContentProvider extends ContentProvider { + ProviderTableMeta.FILE_UPDATE_THUMBNAIL + " INTEGER," //boolean + ProviderTableMeta.FILE_IS_DOWNLOADING + " INTEGER);" //boolean ); - + // Create table ocshares db.execSQL("CREATE TABLE " + ProviderTableMeta.OCSHARES_TABLE_NAME + "(" + ProviderTableMeta._ID + " INTEGER PRIMARY KEY, " @@ -645,14 +652,14 @@ public class FileContentProvider extends ContentProvider { + ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME + " TEXT, " + ProviderTableMeta.OCSHARES_IS_DIRECTORY + " INTEGER, " // boolean + ProviderTableMeta.OCSHARES_USER_ID + " INTEGER, " - + ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + " INTEGER," + + ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + " INTEGER," + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + " TEXT );" ); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log_OC.i("SQL", "Entering in onUpgrade"); - boolean upgraded = false; + boolean upgraded = false; if (oldVersion == 1 && newVersion >= 2) { Log_OC.i("SQL", "Entering in the #1 ADD in onUpgrade"); db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + @@ -665,15 +672,15 @@ public class FileContentProvider extends ContentProvider { db.beginTransaction(); try { db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + - " ADD COLUMN " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + + " ADD COLUMN " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " INTEGER " + " DEFAULT 0"); - + // assume there are not local changes pending to upload - db.execSQL("UPDATE " + ProviderTableMeta.FILE_TABLE_NAME + - " SET " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " = " - + System.currentTimeMillis() + + db.execSQL("UPDATE " + ProviderTableMeta.FILE_TABLE_NAME + + " SET " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " = " + + System.currentTimeMillis() + " WHERE " + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL"); - + upgraded = true; db.setTransactionSuccessful(); } finally { @@ -684,15 +691,15 @@ public class FileContentProvider extends ContentProvider { Log_OC.i("SQL", "Entering in the #3 ADD in onUpgrade"); db.beginTransaction(); try { - db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + - " ADD COLUMN " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + - " INTEGER " + " DEFAULT 0"); - - db.execSQL("UPDATE " + ProviderTableMeta.FILE_TABLE_NAME + + db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + + " ADD COLUMN " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + + " INTEGER " + " DEFAULT 0"); + + db.execSQL("UPDATE " + ProviderTableMeta.FILE_TABLE_NAME + " SET " + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " = " + ProviderTableMeta.FILE_MODIFIED + " WHERE " + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL"); - + upgraded = true; db.setTransactionSuccessful(); } finally { @@ -700,17 +707,17 @@ public class FileContentProvider extends ContentProvider { } } if (!upgraded) - Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + + Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion); - + if (oldVersion < 5 && newVersion >= 5) { Log_OC.i("SQL", "Entering in the #4 ADD in onUpgrade"); db.beginTransaction(); try { - db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + + db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + " ADD COLUMN " + ProviderTableMeta.FILE_ETAG + " TEXT " + " DEFAULT NULL"); - + upgraded = true; db.setTransactionSuccessful(); } finally { @@ -718,7 +725,7 @@ public class FileContentProvider extends ContentProvider { } } if (!upgraded) - Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + + Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion); if (oldVersion < 6 && newVersion >= 6) { @@ -728,7 +735,7 @@ public class FileContentProvider extends ContentProvider { db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + " ADD COLUMN " + ProviderTableMeta.FILE_SHARE_BY_LINK + " INTEGER " + " DEFAULT 0"); - + db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + " ADD COLUMN " + ProviderTableMeta.FILE_PUBLIC_LINK + " TEXT " + " DEFAULT NULL"); @@ -741,15 +748,15 @@ public class FileContentProvider extends ContentProvider { + ProviderTableMeta.OCSHARES_SHARE_TYPE + " INTEGER, " + ProviderTableMeta.OCSHARES_SHARE_WITH + " TEXT, " + ProviderTableMeta.OCSHARES_PATH + " TEXT, " - + ProviderTableMeta.OCSHARES_PERMISSIONS+ " INTEGER, " + + ProviderTableMeta.OCSHARES_PERMISSIONS + " INTEGER, " + ProviderTableMeta.OCSHARES_SHARED_DATE + " INTEGER, " + ProviderTableMeta.OCSHARES_EXPIRATION_DATE + " INTEGER, " + ProviderTableMeta.OCSHARES_TOKEN + " TEXT, " + ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME + " TEXT, " + ProviderTableMeta.OCSHARES_IS_DIRECTORY + " INTEGER, " // boolean + ProviderTableMeta.OCSHARES_USER_ID + " INTEGER, " - + ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + " INTEGER," - + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + " TEXT );" ); + + ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + " INTEGER," + + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + " TEXT );"); upgraded = true; db.setTransactionSuccessful(); @@ -758,21 +765,21 @@ public class FileContentProvider extends ContentProvider { } } if (!upgraded) - Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + + Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion); if (oldVersion < 7 && newVersion >= 7) { Log_OC.i("SQL", "Entering in the #7 ADD in onUpgrade"); db.beginTransaction(); try { - db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + + db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + " ADD COLUMN " + ProviderTableMeta.FILE_PERMISSIONS + " TEXT " + " DEFAULT NULL"); - db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + + db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + " ADD COLUMN " + ProviderTableMeta.FILE_REMOTE_ID + " TEXT " + " DEFAULT NULL"); - + upgraded = true; db.setTransactionSuccessful(); } finally { @@ -780,14 +787,14 @@ public class FileContentProvider extends ContentProvider { } } if (!upgraded) - Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + + Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion); if (oldVersion < 8 && newVersion >= 8) { Log_OC.i("SQL", "Entering in the #8 ADD in onUpgrade"); db.beginTransaction(); try { - db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + + db.execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME + " ADD COLUMN " + ProviderTableMeta.FILE_UPDATE_THUMBNAIL + " INTEGER " + " DEFAULT 0"); @@ -818,7 +825,131 @@ public class FileContentProvider extends ContentProvider { if (!upgraded) Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion); + + if (oldVersion < 10 && newVersion >= 10) { + Log_OC.i("SQL", "Entering in the #10 ADD in onUpgrade"); + updateAccountName(db); + upgraded = true; + } + if (!upgraded) + Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + + ", newVersion == " + newVersion); + } + } + + + /** + * Version 10 of database does not modify its scheme. It coincides with the upgrade of the ownCloud account names + * structure to include in it the path to the server instance. Updating the account names and path to local files + * in the files table is a must to keep the existing account working and the database clean. + * + * See {@link com.owncloud.android.authentication.AccountUtils#updateAccountVersion(android.content.Context)} + * + * @param db Database where table of files is included. + */ + private void updateAccountName(SQLiteDatabase db){ + Log_OC.d("SQL", "THREAD: "+ Thread.currentThread().getName()); + AccountManager ama = AccountManager.get(getContext()); + try { + // get accounts from AccountManager ; we can't be sure if accounts in it are updated or not although + // we know the update was previously done in {link @FileActivity#onCreate} because the changes through + // AccountManager are not synchronous + Account[] accounts = AccountManager.get(getContext()).getAccountsByType( + MainApp.getAccountType()); + String serverUrl, username, oldAccountName, newAccountName; + for (Account account : accounts) { + // build both old and new account name + serverUrl = ama.getUserData(account, AccountUtils.Constants.KEY_OC_BASE_URL); + username = account.name.substring(0, account.name.lastIndexOf('@')); + oldAccountName = AccountUtils.buildAccountNameOld(Uri.parse(serverUrl), username); + newAccountName = AccountUtils.buildAccountName(Uri.parse(serverUrl), username); + + // update values in database + db.beginTransaction(); + try { + ContentValues cv = new ContentValues(); + cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, newAccountName); + int num = db.update(ProviderTableMeta.FILE_TABLE_NAME, + cv, + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?", + new String[]{oldAccountName}); + + Log_OC.d("SQL", "Updated account in database: old name == " + oldAccountName + + ", new name == " + newAccountName + " (" + num + " rows updated )"); + + // update path for downloaded files + updateDownloadedFiles(db, newAccountName, oldAccountName); + + db.setTransactionSuccessful(); + + } catch (SQLException e) { + Log_OC.e(TAG, "SQL Exception upgrading account names or paths in database", e); + } finally { + db.endTransaction(); + } + } + } catch (Exception e) { + Log_OC.e(TAG, "Exception upgrading account names or paths in database", e); + } + } + + + /** + * Rename the local ownCloud folder of one account to match the a rename of the account itself. Updates the + * table of files in database so that the paths to the local files keep being the same. + * + * @param db Database where table of files is included. + * @param newAccountName New name for the target OC account. + * @param oldAccountName Old name of the target OC account. + */ + private void updateDownloadedFiles(SQLiteDatabase db, String newAccountName, + String oldAccountName) { + + String whereClause = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL"; + + Cursor c = db.query(ProviderTableMeta.FILE_TABLE_NAME, + null, + whereClause, + new String[] { newAccountName }, + null, null, null); + + try { + if (c.moveToFirst()) { + // create storage path + String oldAccountPath = FileStorageUtils.getSavePath(oldAccountName); + String newAccountPath = FileStorageUtils.getSavePath(newAccountName); + + // move files + File oldAccountFolder = new File(oldAccountPath); + File newAccountFolder = new File(newAccountPath); + oldAccountFolder.renameTo(newAccountFolder); + + // update database + do { + // Update database + String oldPath = c.getString( + c.getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH)); + OCFile file = new OCFile( + c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PATH))); + String newPath = FileStorageUtils.getDefaultSavePathFor(newAccountName, file); + + ContentValues cv = new ContentValues(); + cv.put(ProviderTableMeta.FILE_STORAGE_PATH, newPath); + db.update(ProviderTableMeta.FILE_TABLE_NAME, + cv, + ProviderTableMeta.FILE_STORAGE_PATH + "=?", + new String[]{oldPath}); + + Log_OC.v("SQL", "Updated path of downloaded file: old file name == " + oldPath + + ", new file name == " + newPath); + + } while (c.moveToNext()); + } + } finally { + c.close(); } + } } diff --git a/src/com/owncloud/android/syncadapter/ContactSyncAdapter.java b/src/com/owncloud/android/syncadapter/ContactSyncAdapter.java deleted file mode 100644 index d3ab06c1..00000000 --- a/src/com/owncloud/android/syncadapter/ContactSyncAdapter.java +++ /dev/null @@ -1,125 +0,0 @@ -/** - * ownCloud Android client application - * - * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2015 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.syncadapter; - -import java.io.FileInputStream; -import java.io.IOException; - -import org.apache.http.client.methods.HttpPut; -import org.apache.http.entity.ByteArrayEntity; - -import com.owncloud.android.authentication.AccountUtils; -import com.owncloud.android.lib.common.accounts.AccountUtils.Constants; - - -import android.accounts.Account; -import android.accounts.AccountManager; -import android.accounts.AuthenticatorException; -import android.accounts.OperationCanceledException; -import android.content.ContentProviderClient; -import android.content.Context; -import android.content.SyncResult; -import android.content.res.AssetFileDescriptor; -import android.database.Cursor; -import android.net.Uri; -import android.os.Bundle; -import android.provider.ContactsContract; - -public class ContactSyncAdapter extends AbstractOwnCloudSyncAdapter { - private String mAddrBookUri; - - public ContactSyncAdapter(Context context, boolean autoInitialize) { - super(context, autoInitialize); - mAddrBookUri = null; - } - - @Override - public void onPerformSync(Account account, Bundle extras, String authority, - ContentProviderClient provider, SyncResult syncResult) { - setAccount(account); - setContentProviderClient(provider); - Cursor c = getLocalContacts(false); - if (c.moveToFirst()) { - do { - String lookup = c.getString(c - .getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)); - String a = getAddressBookUri(); - String uri = a + lookup + ".vcf"; - FileInputStream f; - try { - f = getContactVcard(lookup); - HttpPut query = new HttpPut(uri); - byte[] b = new byte[f.available()]; - f.read(b); - query.setEntity(new ByteArrayEntity(b)); - fireRawRequest(query); - } catch (IOException e) { - e.printStackTrace(); - return; - } catch (OperationCanceledException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (AuthenticatorException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } while (c.moveToNext()); - // } while (c.moveToNext()); - } - - } - - private String getAddressBookUri() { - if (mAddrBookUri != null) - return mAddrBookUri; - - AccountManager am = getAccountManager(); - @SuppressWarnings("deprecation") - String uri = am.getUserData(getAccount(), - Constants.KEY_OC_URL).replace( - AccountUtils.WEBDAV_PATH_2_0, AccountUtils.CARDDAV_PATH_2_0); - uri += "/addressbooks/" - + getAccount().name.substring(0, - getAccount().name.lastIndexOf('@')) + "/default/"; - mAddrBookUri = uri; - return uri; - } - - private FileInputStream getContactVcard(String lookupKey) - throws IOException { - Uri uri = Uri.withAppendedPath( - ContactsContract.Contacts.CONTENT_VCARD_URI, lookupKey); - AssetFileDescriptor fd = getContext().getContentResolver() - .openAssetFileDescriptor(uri, "r"); - return fd.createInputStream(); - } - - private Cursor getLocalContacts(boolean include_hidden_contacts) { - return getContext().getContentResolver().query( - ContactsContract.Contacts.CONTENT_URI, - new String[] { ContactsContract.Contacts._ID, - ContactsContract.Contacts.LOOKUP_KEY }, - ContactsContract.Contacts.IN_VISIBLE_GROUP + " = ?", - new String[] { (include_hidden_contacts ? "0" : "1") }, - ContactsContract.Contacts._ID + " DESC"); - } - -} diff --git a/src/com/owncloud/android/syncadapter/ContactSyncService.java b/src/com/owncloud/android/syncadapter/ContactSyncService.java deleted file mode 100644 index d907bb49..00000000 --- a/src/com/owncloud/android/syncadapter/ContactSyncService.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * ownCloud Android client application - * - * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2015 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.syncadapter; - -import android.app.Service; -import android.content.Intent; -import android.os.IBinder; - -public class ContactSyncService extends Service { - private static final Object syncAdapterLock = new Object(); - private static AbstractOwnCloudSyncAdapter mSyncAdapter = null; - - @Override - public void onCreate() { - synchronized (syncAdapterLock) { - if (mSyncAdapter == null) { - mSyncAdapter = new ContactSyncAdapter(getApplicationContext(), - true); - } - } - } - - @Override - public IBinder onBind(Intent arg0) { - return mSyncAdapter.getSyncAdapterBinder(); - } - -} diff --git a/src/com/owncloud/android/ui/activity/FileActivity.java b/src/com/owncloud/android/ui/activity/FileActivity.java index a566ccdb..17aa8c04 100644 --- a/src/com/owncloud/android/ui/activity/FileActivity.java +++ b/src/com/owncloud/android/ui/activity/FileActivity.java @@ -61,7 +61,6 @@ import com.owncloud.android.operations.SynchronizeFolderOperation; import com.owncloud.android.operations.UnshareLinkOperation; import com.owncloud.android.services.OperationsService; import com.owncloud.android.services.OperationsService.OperationsServiceBinder; -import com.owncloud.android.ui.dialog.CreateFolderDialogFragment; import com.owncloud.android.ui.dialog.LoadingDialog; import com.owncloud.android.ui.dialog.SharePasswordDialogFragment; import com.owncloud.android.utils.ErrorMessageAdapter; @@ -152,6 +151,8 @@ public class FileActivity extends SherlockFragmentActivity mFromNotification = getIntent().getBooleanExtra(FileActivity.EXTRA_FROM_NOTIFICATION, false); } + AccountUtils.updateAccountVersion(this); // best place, before any access to AccountManager or database + setAccount(account, savedInstanceState != null); mOperationsServiceConnection = new OperationsServiceConnection(); @@ -168,7 +169,16 @@ public class FileActivity extends SherlockFragmentActivity } - + @Override + protected void onNewIntent (Intent intent) { + Log_OC.v(TAG, "onNewIntent() start"); + Account current = AccountUtils.getCurrentOwnCloudAccount(this); + if (current != null && mAccount != null && !mAccount.name.equals(current.name)) { + mAccount = current; + } + Log_OC.v(TAG, "onNewIntent() stop"); + } + /** * Since ownCloud {@link Account}s can be managed from the system setting menu, * the existence of the {@link Account} associated to the instance must be checked @@ -176,46 +186,54 @@ public class FileActivity extends SherlockFragmentActivity */ @Override protected void onRestart() { + Log_OC.v(TAG, "onRestart() start"); super.onRestart(); - boolean validAccount = (mAccount != null && AccountUtils.setCurrentOwnCloudAccount(getApplicationContext(), mAccount.name)); + boolean validAccount = (mAccount != null && AccountUtils.exists(mAccount, this)); if (!validAccount) { swapToDefaultAccount(); } + Log_OC.v(TAG, "onRestart() end"); } @Override protected void onStart() { + Log_OC.v(TAG, "onStart() start"); super.onStart(); if (mAccountWasSet) { onAccountSet(mAccountWasRestored); } + Log_OC.v(TAG, "onStart() end"); } @Override protected void onResume() { + Log_OC.v(TAG, "onResume() start"); super.onResume(); if (mOperationsServiceBinder != null) { doOnResumeAndBound(); } - + Log_OC.v(TAG, "onResume() end"); } @Override protected void onPause() { - + Log_OC.v(TAG, "onPause() start"); + if (mOperationsServiceBinder != null) { mOperationsServiceBinder.removeOperationListener(this); } super.onPause(); + Log_OC.v(TAG, "onPause() end"); } @Override protected void onDestroy() { + Log_OC.v(TAG, "onDestroy() start"); if (mOperationsServiceConnection != null) { unbindService(mOperationsServiceConnection); mOperationsServiceBinder = null; @@ -230,6 +248,7 @@ public class FileActivity extends SherlockFragmentActivity } super.onDestroy(); + Log_OC.v(TAG, "onDestroy() end"); } @@ -245,7 +264,8 @@ public class FileActivity extends SherlockFragmentActivity */ protected void setAccount(Account account, boolean savedAccount) { Account oldAccount = mAccount; - boolean validAccount = (account != null && AccountUtils.setCurrentOwnCloudAccount(getApplicationContext(), account.name)); + boolean validAccount = + (account != null && AccountUtils.setCurrentOwnCloudAccount(getApplicationContext(), account.name)); if (validAccount) { mAccount = account; mAccountWasSet = true; @@ -546,7 +566,9 @@ public class FileActivity extends SherlockFragmentActivity } } - private void onSynchronizeFolderOperationFinish(SynchronizeFolderOperation operation, RemoteOperationResult result) { + private void onSynchronizeFolderOperationFinish( + SynchronizeFolderOperation operation, RemoteOperationResult result + ) { if (!result.isSuccess() && result.getCode() != ResultCode.CANCELLED){ Toast t = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), Toast.LENGTH_LONG); diff --git a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java index 3ea6822b..83a49024 100644 --- a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java @@ -29,12 +29,9 @@ import android.accounts.AccountManager; import android.accounts.AuthenticatorException; import android.annotation.TargetApi; import android.app.AlertDialog; -import android.app.Dialog; -import android.app.ProgressDialog; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; -import android.content.ContentUris; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -47,16 +44,12 @@ import android.database.Cursor; import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.os.Environment; import android.os.IBinder; import android.preference.PreferenceManager; -import android.provider.DocumentsContract; -import android.provider.MediaStore; import android.provider.OpenableColumns; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; -import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; @@ -97,9 +90,11 @@ import com.owncloud.android.operations.RefreshFolderOperation; import com.owncloud.android.operations.UnshareLinkOperation; import com.owncloud.android.services.observer.FileObserverService; import com.owncloud.android.syncadapter.FileSyncAdapter; +import com.owncloud.android.ui.dialog.ConfirmationDialogFragment; import com.owncloud.android.ui.dialog.CreateFolderDialogFragment; import com.owncloud.android.ui.dialog.SslUntrustedCertDialog; import com.owncloud.android.ui.dialog.SslUntrustedCertDialog.OnSslUntrustedCertListener; +import com.owncloud.android.ui.dialog.UploadSourceDialogFragment; import com.owncloud.android.ui.fragment.FileDetailFragment; import com.owncloud.android.ui.fragment.FileFragment; import com.owncloud.android.ui.fragment.OCFileListFragment; @@ -136,14 +131,10 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { private static final String KEY_SYNC_IN_PROGRESS = "SYNC_IN_PROGRESS"; private static final String KEY_WAITING_TO_SEND = "WAITING_TO_SEND"; - public static final int DIALOG_SHORT_WAIT = 0; - private static final int DIALOG_CHOOSE_UPLOAD_SOURCE = 1; - private static final int DIALOG_CERT_NOT_SAVED = 2; - public static final String ACTION_DETAILS = "com.owncloud.android.ui.activity.action.DETAILS"; - private static final int ACTION_SELECT_CONTENT_FROM_APPS = 1; - private static final int ACTION_SELECT_MULTIPLE_FILES = 2; + public static final int ACTION_SELECT_CONTENT_FROM_APPS = 1; + public static final int ACTION_SELECT_MULTIPLE_FILES = 2; public static final int ACTION_MOVE_FILES = 3; private static final String TAG = FileDisplayActivity.class.getSimpleName(); @@ -155,8 +146,12 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { private boolean mSyncInProgress = false; - private String DIALOG_UNTRUSTED_CERT; - + private static String DIALOG_UNTRUSTED_CERT = "DIALOG_UNTRUSTED_CERT"; + private static String DIALOG_CREATE_FOLDER = "DIALOG_CREATE_FOLDER"; + private static String DIALOG_UPLOAD_SOURCE = "DIALOG_UPLOAD_SOURCE"; + private static String DIALOG_CERT_NOT_SAVED = "DIALOG_CERT_NOT_SAVED"; + + private OCFile mWaitingToSend; @Override @@ -214,13 +209,17 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { @Override protected void onStart() { + Log_OC.d(TAG, "onStart() start"); super.onStart(); getSupportActionBar().setIcon(DisplayUtils.getSeasonalIconId()); + Log_OC.d(TAG, "onStart() end"); } @Override protected void onDestroy() { + Log_OC.d(TAG, "onDestroy() start"); super.onDestroy(); + Log_OC.d(TAG, "onDestroy() end"); } /** @@ -478,9 +477,8 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { boolean retval = true; switch (item.getItemId()) { case R.id.action_create_dir: { - CreateFolderDialogFragment dialog = - CreateFolderDialogFragment.newInstance(getCurrentDir()); - dialog.show(getSupportFragmentManager(), "createdirdialog"); + CreateFolderDialogFragment dialog = CreateFolderDialogFragment.newInstance(getCurrentDir()); + dialog.show(getSupportFragmentManager(), DIALOG_CREATE_FOLDER); break; } case R.id.action_sync_account: { @@ -488,7 +486,9 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { break; } case R.id.action_upload: { - showDialog(DIALOG_CHOOSE_UPLOAD_SOURCE); + UploadSourceDialogFragment dialog = UploadSourceDialogFragment.newInstance(getAccount()); + dialog.show(getSupportFragmentManager(), DIALOG_UPLOAD_SOURCE); + break; } case R.id.action_settings: { @@ -608,8 +608,8 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { * */ @TargetApi(Build.VERSION_CODES.JELLY_BEAN) + @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); if (requestCode == ACTION_SELECT_CONTENT_FROM_APPS && (resultCode == RESULT_OK || resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE)) { //getClipData is only supported on api level 16+, Jelly Bean @@ -638,7 +638,11 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { }, DELAY_TO_REQUEST_OPERATION_ON_ACTIVITY_RESULTS ); + + } else { + super.onActivityResult(requestCode, resultCode, data); } + } private void requestMultipleUpload(Intent data, int resultCode) { @@ -675,7 +679,7 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { private void requestSimpleUpload(Intent data, int resultCode) { - String filepath = null; + String filePath = null; String mimeType = null; Uri selectedImageUri = data.getData(); @@ -683,67 +687,60 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { try { mimeType = getContentResolver().getType(selectedImageUri); - String filemanagerstring = selectedImageUri.getPath(); - String selectedImagePath = getPath(selectedImageUri); + String fileManagerString = selectedImageUri.getPath(); + String selectedImagePath = UriUtils.getLocalPath(selectedImageUri, this); if (selectedImagePath != null) - filepath = selectedImagePath; + filePath = selectedImagePath; else - filepath = filemanagerstring; + filePath = fileManagerString; } catch (Exception e) { Log_OC.e(TAG, "Unexpected exception when trying to read the result of Intent.ACTION_GET_CONTENT", e); - e.printStackTrace(); } finally { - if (filepath == null) { + if (filePath == null) { Log_OC.e(TAG, "Couldn't resolve path to file"); - Toast t = Toast.makeText(this, getString(R.string.filedisplay_unexpected_bad_get_content), Toast.LENGTH_LONG); + Toast t = Toast.makeText( + this, getString(R.string.filedisplay_unexpected_bad_get_content), Toast.LENGTH_LONG + ); t.show(); return; } } Intent i = new Intent(this, FileUploader.class); - i.putExtra(FileUploader.KEY_ACCOUNT, - getAccount()); - String remotepath = new String(); - for (int j = mDirectories.getCount() - 2; j >= 0; --j) { - remotepath += OCFile.PATH_SEPARATOR + mDirectories.getItem(j); - } - if (!remotepath.endsWith(OCFile.PATH_SEPARATOR)) - remotepath += OCFile.PATH_SEPARATOR; - - if (filepath.startsWith(UriUtils.URI_CONTENT_SCHEME)) { - - Cursor cursor = MainApp.getAppContext().getContentResolver() - .query(Uri.parse(filepath), null, null, null, null, null); + i.putExtra(FileUploader.KEY_ACCOUNT, getAccount()); + OCFile currentDir = getCurrentDir(); + String remotePath = (currentDir != null) ? currentDir.getRemotePath() : OCFile.ROOT_PATH; + if (filePath.startsWith(UriUtils.URI_CONTENT_SCHEME)) { + Cursor cursor = getContentResolver().query(Uri.parse(filePath), null, null, null, null); try { if (cursor != null && cursor.moveToFirst()) { - String displayName = cursor.getString( - cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); - Log.i(TAG, "Display Name: " + displayName + "; mimeType: " + mimeType); + String displayName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); + Log_OC.v(TAG, "Display Name: " + displayName ); displayName.replace(File.separatorChar, '_'); displayName.replace(File.pathSeparatorChar, '_'); - remotepath += displayName + DisplayUtils.getComposedFileExtension(filepath); + remotePath += displayName + DisplayUtils.getComposedFileExtension(filePath); } + // and what happens in case of error?; wrong target name for the upload } finally { cursor.close(); } } else { - remotepath += new File(filepath).getName(); + remotePath += new File(filePath).getName(); } - i.putExtra(FileUploader.KEY_LOCAL_FILE, filepath); - i.putExtra(FileUploader.KEY_REMOTE_FILE, remotepath); + i.putExtra(FileUploader.KEY_LOCAL_FILE, filePath); + i.putExtra(FileUploader.KEY_REMOTE_FILE, remotePath); i.putExtra(FileUploader.KEY_MIME_TYPE, mimeType); i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE); if (resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE) - i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_MOVE); + i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_MOVE); startService(i); } @@ -798,9 +795,9 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { @Override protected void onResume() { - super.onResume(); Log_OC.d(TAG, "onResume() start"); - + super.onResume(); + // refresh list of files refreshListOfFilesFragment(); @@ -847,148 +844,8 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { } - Log_OC.d(TAG, "onPause() end"); super.onPause(); - } - - - @Override - protected Dialog onCreateDialog(int id) { - Dialog dialog = null; - AlertDialog.Builder builder; - switch (id) { - case DIALOG_SHORT_WAIT: { - ProgressDialog working_dialog = new ProgressDialog(this); - working_dialog.setMessage(getResources().getString( - R.string.wait_a_moment)); - working_dialog.setIndeterminate(true); - working_dialog.setCancelable(false); - dialog = working_dialog; - break; - } - case DIALOG_CHOOSE_UPLOAD_SOURCE: { - - - String[] allTheItems = { getString(R.string.actionbar_upload_files), - getString(R.string.actionbar_upload_from_apps) }; - - builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.actionbar_upload); - builder.setItems(allTheItems, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int item) { - if (item == 0) { - // if (!mDualPane) { - Intent action = new Intent(FileDisplayActivity.this, UploadFilesActivity.class); - action.putExtra(UploadFilesActivity.EXTRA_ACCOUNT, FileDisplayActivity.this.getAccount()); - startActivityForResult(action, ACTION_SELECT_MULTIPLE_FILES); - // } else { - // TODO create and handle new fragment - // LocalFileListFragment - // } - } else if (item == 1) { - Intent action = new Intent(Intent.ACTION_GET_CONTENT); - action = action.setType("*/*").addCategory(Intent.CATEGORY_OPENABLE); - //Intent.EXTRA_ALLOW_MULTIPLE is only supported on api level 18+, Jelly Bean - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - action.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); - } - startActivityForResult(Intent.createChooser(action, getString(R.string.upload_chooser_title)), - ACTION_SELECT_CONTENT_FROM_APPS); - } - } - }); - dialog = builder.create(); - break; - } - case DIALOG_CERT_NOT_SAVED: { - builder = new AlertDialog.Builder(this); - builder.setMessage(getResources().getString(R.string.ssl_validator_not_saved)); - builder.setCancelable(false); - builder.setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - }; - }); - dialog = builder.create(); - break; - } - default: - dialog = null; - } - - return dialog; - } - - /** - * Translates a content URI of an content to a physical path on the disk - * - * @param uri The URI to resolve - * @return The path to the content or null if it could not be found - */ - public String getPath(Uri uri) { - final boolean isKitKatOrLater = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; - - // DocumentProvider - if (isKitKatOrLater && DocumentsContract.isDocumentUri(getApplicationContext(), uri)) { - // ExternalStorageProvider - if (UriUtils.isExternalStorageDocument(uri)) { - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - - if ("primary".equalsIgnoreCase(type)) { - return Environment.getExternalStorageDirectory() + "/" + split[1]; - } - } - // DownloadsProvider - else if (UriUtils.isDownloadsDocument(uri)) { - - final String id = DocumentsContract.getDocumentId(uri); - final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), - Long.valueOf(id)); - - return UriUtils.getDataColumn(getApplicationContext(), contentUri, null, null); - } - // MediaProvider - else if (UriUtils.isMediaDocument(uri)) { - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - - Uri contentUri = null; - if ("image".equals(type)) { - contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; - } else if ("video".equals(type)) { - contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; - } else if ("audio".equals(type)) { - contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; - } - - final String selection = "_id=?"; - final String[] selectionArgs = new String[] { split[1] }; - - return UriUtils.getDataColumn(getApplicationContext(), contentUri, selection, selectionArgs); - } - // Documents providers returned as content://... - else if (UriUtils.isContentDocument(uri)) { - return uri.toString(); - } - } - // MediaStore (and general) - else if ("content".equalsIgnoreCase(uri.getScheme())) { - - // Return the remote address - if (UriUtils.isGooglePhotosUri(uri)) - return uri.getLastPathSegment(); - - return UriUtils.getDataColumn(getApplicationContext(), uri, null, null); - } - // File - else if ("file".equalsIgnoreCase(uri.getScheme())) { - return uri.getPath(); - } - return null; + Log_OC.d(TAG, "onPause() end"); } /** @@ -1492,7 +1349,10 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { @Override public void onFailedSavingCertificate() { - showDialog(DIALOG_CERT_NOT_SAVED); + ConfirmationDialogFragment dialog = ConfirmationDialogFragment.newInstance( + R.string.ssl_validator_not_saved, new String[]{}, R.string.common_ok, -1, -1 + ); + dialog.show(getSupportFragmentManager(), DIALOG_CERT_NOT_SAVED); } @Override @@ -1932,4 +1792,5 @@ OnSslUntrustedCertListener, OnEnforceableRefreshListener { private void sortByName(boolean ascending){ getListOfFilesFragment().sortByName(ascending); } + } diff --git a/src/com/owncloud/android/ui/activity/Preferences.java b/src/com/owncloud/android/ui/activity/Preferences.java index 5585024d..70ca9dee 100644 --- a/src/com/owncloud/android/ui/activity/Preferences.java +++ b/src/com/owncloud/android/ui/activity/Preferences.java @@ -616,6 +616,7 @@ public class Preferences extends SherlockPreferenceActivity FileDisplayActivity.class ); i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); startActivity(i); } else { finish(); diff --git a/src/com/owncloud/android/ui/activity/UploadFilesActivity.java b/src/com/owncloud/android/ui/activity/UploadFilesActivity.java index 7563ea66..fce4ddce 100644 --- a/src/com/owncloud/android/ui/activity/UploadFilesActivity.java +++ b/src/com/owncloud/android/ui/activity/UploadFilesActivity.java @@ -64,11 +64,13 @@ public class UploadFilesActivity extends FileActivity implements private Account mAccountOnCreation; private DialogFragment mCurrentDialog; - public static final String EXTRA_CHOSEN_FILES = UploadFilesActivity.class.getCanonicalName() + ".EXTRA_CHOSEN_FILES"; + public static final String EXTRA_CHOSEN_FILES = + UploadFilesActivity.class.getCanonicalName() + ".EXTRA_CHOSEN_FILES"; public static final int RESULT_OK_AND_MOVE = RESULT_FIRST_USER; - private static final String KEY_DIRECTORY_PATH = UploadFilesActivity.class.getCanonicalName() + ".KEY_DIRECTORY_PATH"; + private static final String KEY_DIRECTORY_PATH = + UploadFilesActivity.class.getCanonicalName() + ".KEY_DIRECTORY_PATH"; private static final String TAG = "UploadFilesActivity"; private static final String WAIT_DIALOG_TAG = "WAIT"; private static final String QUERY_TO_MOVE_DIALOG_TAG = "QUERY_TO_MOVE"; @@ -180,7 +182,8 @@ public class UploadFilesActivity extends FileActivity implements @Override protected void onSaveInstanceState(Bundle outState) { - // responsibility of restore is preferred in onCreate() before than in onRestoreInstanceState when there are Fragments involved + // responsibility of restore is preferred in onCreate() before than in + // onRestoreInstanceState when there are Fragments involved Log_OC.d(TAG, "onSaveInstanceState() start"); super.onSaveInstanceState(outState); outState.putString(UploadFilesActivity.KEY_DIRECTORY_PATH, mCurrentDir.getAbsolutePath()); @@ -317,7 +320,7 @@ public class UploadFilesActivity extends FileActivity implements File localFile = new File(localPath); total += localFile.length(); } - return (FileStorageUtils.getUsableSpace(mAccountOnCreation.name) >= total); + return (new Boolean(FileStorageUtils.getUsableSpace(mAccountOnCreation.name) >= total)); } /** @@ -341,9 +344,12 @@ public class UploadFilesActivity extends FileActivity implements finish(); } else { - // show a dialog to query the user if wants to move the selected files to the ownCloud folder instead of copying + // show a dialog to query the user if wants to move the selected files + // to the ownCloud folder instead of copying String[] args = {getString(R.string.app_name)}; - ConfirmationDialogFragment dialog = ConfirmationDialogFragment.newInstance(R.string.upload_query_move_foreign_files, args, R.string.common_yes, -1, R.string.common_no); + ConfirmationDialogFragment dialog = ConfirmationDialogFragment.newInstance( + R.string.upload_query_move_foreign_files, args, R.string.common_yes, -1, R.string.common_no + ); dialog.setOnConfirmationListener(UploadFilesActivity.this); dialog.show(getSupportFragmentManager(), QUERY_TO_MOVE_DIALOG_TAG); } @@ -354,7 +360,8 @@ public class UploadFilesActivity extends FileActivity implements public void onConfirmation(String callerTag) { Log_OC.d(TAG, "Positive button in dialog was clicked; dialog tag is " + callerTag); if (callerTag.equals(QUERY_TO_MOVE_DIALOG_TAG)) { - // return the list of selected files to the caller activity (success), signaling that they should be moved to the ownCloud folder, instead of copied + // return the list of selected files to the caller activity (success), + // signaling that they should be moved to the ownCloud folder, instead of copied Intent data = new Intent(); data.putExtra(EXTRA_CHOSEN_FILES, mFileListFragment.getCheckedFilePaths()); setResult(RESULT_OK_AND_MOVE, data); diff --git a/src/com/owncloud/android/ui/dialog/ConfirmationDialogFragment.java b/src/com/owncloud/android/ui/dialog/ConfirmationDialogFragment.java index 29ed3908..48aabe5c 100644 --- a/src/com/owncloud/android/ui/dialog/ConfirmationDialogFragment.java +++ b/src/com/owncloud/android/ui/dialog/ConfirmationDialogFragment.java @@ -93,7 +93,9 @@ public class ConfirmationDialogFragment extends SherlockDialogFragment { builder.setPositiveButton(posBtn, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { - mListener.onConfirmation(getTag()); + if (mListener != null) { + mListener.onConfirmation(getTag()); + } dialog.dismiss(); } }); @@ -101,7 +103,9 @@ public class ConfirmationDialogFragment extends SherlockDialogFragment { builder.setNeutralButton(neuBtn, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { - mListener.onNeutral(getTag()); + if (mListener != null) { + mListener.onNeutral(getTag()); + } dialog.dismiss(); } }); @@ -110,7 +114,9 @@ public class ConfirmationDialogFragment extends SherlockDialogFragment { new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - mListener.onCancel(getTag()); + if (mListener != null) { + mListener.onCancel(getTag()); + } dialog.dismiss(); } }); diff --git a/src/com/owncloud/android/ui/dialog/UploadSourceDialogFragment.java b/src/com/owncloud/android/ui/dialog/UploadSourceDialogFragment.java new file mode 100644 index 00000000..2f6eeadf --- /dev/null +++ b/src/com/owncloud/android/ui/dialog/UploadSourceDialogFragment.java @@ -0,0 +1,104 @@ +/** + * ownCloud Android client application + * + * @author David A. Velasco + * Copyright (C) 2015 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.ui.dialog; + +import android.accounts.Account; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; + +import com.actionbarsherlock.app.SherlockDialogFragment; +import com.owncloud.android.R; +import com.owncloud.android.lib.common.utils.Log_OC; +import com.owncloud.android.ui.activity.FileActivity; +import com.owncloud.android.ui.activity.UploadFilesActivity; + + +/** + * Dialog showing two options to allow the user upload files from the filesystem or from other apps. + * + * Assumes that its parent activity extends {@link FileActivity} + */ +public class UploadSourceDialogFragment extends SherlockDialogFragment { + + private final static String TAG = UploadSourceDialogFragment.class.getSimpleName(); + private final static String ARG_ACCOUNT = UploadSourceDialogFragment.class.getSimpleName() + ".ARG_ACCOUNT"; + + public static final int ACTION_SELECT_CONTENT_FROM_APPS = 1; + public static final int ACTION_SELECT_MULTIPLE_FILES = 2; + + public static UploadSourceDialogFragment newInstance(Account account) { + UploadSourceDialogFragment f = new UploadSourceDialogFragment(); + Bundle args = new Bundle(); + args.putParcelable(ARG_ACCOUNT, account); + f.setArguments(args); + return f; + } + + public UploadSourceDialogFragment() { + super(); + Log_OC.v(TAG, "constructor"); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + + String[] allTheItems = { + getString(R.string.actionbar_upload_files), + getString(R.string.actionbar_upload_from_apps) + }; + + AlertDialog.Builder builder = new AlertDialog.Builder(getSherlockActivity()); + builder.setTitle(R.string.actionbar_upload); + builder.setItems(allTheItems, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int item) { + if (item == 0) { + Intent action = new Intent(getSherlockActivity(), UploadFilesActivity.class); + action.putExtra( + UploadFilesActivity.EXTRA_ACCOUNT, + ((FileActivity)getSherlockActivity()).getAccount() + ); + //startActivityForResult(action, ACTION_SELECT_MULTIPLE_FILES); // this flow seems broken; + // Actionbarsherlock, maybe? + getSherlockActivity().startActivityForResult(action, ACTION_SELECT_MULTIPLE_FILES); + + } else if (item == 1) { + Intent action = new Intent(Intent.ACTION_GET_CONTENT); + action = action.setType("*/*").addCategory(Intent.CATEGORY_OPENABLE); + //Intent.EXTRA_ALLOW_MULTIPLE is only supported on api level 18+, Jelly Bean + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + action.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); + } + //startActivityForResult( // this flow seems broken; + // Actionbarsherlock, maybe? + getSherlockActivity().startActivityForResult( + Intent.createChooser(action, getString(R.string.upload_chooser_title)), + ACTION_SELECT_CONTENT_FROM_APPS + ); + } + } + }); + return builder.create(); + } + +} diff --git a/src/com/owncloud/android/utils/UriUtils.java b/src/com/owncloud/android/utils/UriUtils.java index 8070e360..2972ee55 100644 --- a/src/com/owncloud/android/utils/UriUtils.java +++ b/src/com/owncloud/android/utils/UriUtils.java @@ -19,16 +19,30 @@ package com.owncloud.android.utils; +import android.annotation.TargetApi; +import android.content.ContentUris; import android.content.Context; import android.database.Cursor; import android.net.Uri; +import android.os.Build; +import android.os.Environment; +import android.provider.DocumentsContract; +import android.provider.MediaStore; +import android.provider.OpenableColumns; + +import com.owncloud.android.MainApp; +import com.owncloud.android.lib.common.utils.Log_OC; + +import java.io.File; /** * A helper class for some Uri operations. */ public class UriUtils { - + + public static final String TAG = UriUtils.class.getSimpleName(); + public static final String URI_CONTENT_SCHEME = "content://"; @@ -102,4 +116,78 @@ public class UriUtils { public static boolean isContentDocument(Uri uri) { return uri.toString().startsWith(URI_CONTENT_SCHEME); } + + + /** + * Translates a content:// URI referred to a local file file to a path on the local filesystem + * + * @param uri The URI to resolve + * @return The path in the file system to the content or null if it could not be found (not a file) + */ + @TargetApi(Build.VERSION_CODES.KITKAT) + public static String getLocalPath(Uri uri, Context context) { + final boolean isKitKatOrLater = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; + + // DocumentProvider + if (isKitKatOrLater && DocumentsContract.isDocumentUri(context, uri)) { + // ExternalStorageProvider + if (UriUtils.isExternalStorageDocument(uri)) { + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + if ("primary".equalsIgnoreCase(type)) { + return Environment.getExternalStorageDirectory() + "/" + split[1]; + } + } + // DownloadsProvider + else if (UriUtils.isDownloadsDocument(uri)) { + + final String id = DocumentsContract.getDocumentId(uri); + final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), + Long.valueOf(id)); + + return UriUtils.getDataColumn(context, contentUri, null, null); + } + // MediaProvider + else if (UriUtils.isMediaDocument(uri)) { + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + Uri contentUri = null; + if ("image".equals(type)) { + contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; + } else if ("video".equals(type)) { + contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; + } else if ("audio".equals(type)) { + contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + } + + final String selection = "_id=?"; + final String[] selectionArgs = new String[] { split[1] }; + + return UriUtils.getDataColumn(context, contentUri, selection, selectionArgs); + } + // Documents providers returned as content://... + else if (UriUtils.isContentDocument(uri)) { + return uri.toString(); + } + } + // MediaStore (and general) + else if ("content".equalsIgnoreCase(uri.getScheme())) { + + // Return the remote address + if (UriUtils.isGooglePhotosUri(uri)) + return uri.getLastPathSegment(); + + return UriUtils.getDataColumn(context, uri, null, null); + } + // File + else if ("file".equalsIgnoreCase(uri.getScheme())) { + return uri.getPath(); + } + return null; + } + }