Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b1963ae
Prepare preferences and project to use user defined storage path
tobiasKaminsky Oct 9, 2015
3fc8d99
rebase
AndyScherzinger Aug 15, 2016
b38b327
Add more migration stuff. cleanup step is still missing
przybylski Nov 8, 2015
67bc271
Add cleanup and rollback step when migrating. Correctly set progress …
przybylski Nov 9, 2015
ebbab22
Code cleanups
przybylski Nov 9, 2015
6722f71
Stop and start logging on migration
przybylski Nov 9, 2015
8ad388f
Soften requirement on cleanup step failures
przybylski Nov 9, 2015
0ea54fa
Fix after rebase
przybylski Nov 9, 2015
cec707b
For more reliability delete old files recursively in migration cleanup
przybylski Nov 22, 2015
2af111b
Add DataStorageUtils to detect connected SD cards
przybylski Dec 6, 2015
9dc51a4
Simplify storage selection process
przybylski Dec 7, 2015
47f522d
Small code cleanups
przybylski Dec 7, 2015
8b587ce
Tabs to spaces
przybylski Dec 7, 2015
70c690c
Use progress dialog instead of alert dialog, for better UX
przybylski Dec 20, 2015
4265c60
Change the way of fetching mounted resources, use system tools and pa…
przybylski Dec 23, 2015
a9f55d5
Handle case of migration of empty src directory
przybylski Dec 30, 2015
5cf019d
Because of multiple underlying implementation of storage mount points…
przybylski Jan 1, 2016
afbe508
use lollipop external storage system
tobiasKaminsky May 8, 2016
e47ebda
rebase fixes
przybylski Jul 2, 2016
d1ebcdd
fixed strings (oC->Nc and ... --> …)
AndyScherzinger Jul 3, 2016
d7d2845
lib version 1.0.2, organizes imports in FileStorageUtils
AndyScherzinger Aug 2, 2016
6e73da2
CR, GPLv3
AndyScherzinger Aug 2, 2016
612199a
further CR fixes, fixed comment in layout/migration_layout.xml
AndyScherzinger Aug 2, 2016
20a0a74
extract/pre-compile the pattern
AndyScherzinger Aug 2, 2016
b09126c
fixed imports after rebase
AndyScherzinger Sep 12, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need further API checks for this for Android 23 support or is this already covered by the given check?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems covered


<application
android:name=".MainApp"
android:icon="@mipmap/ic_launcher"
Expand All @@ -79,6 +82,8 @@
android:taskAffinity=""
android:excludeFromRecents="true"
android:theme="@style/Theme.ownCloud.NoActionBar">
<activity android:name=".ui.activity.LocalDirectorySelectorActivity" />
<activity android:name=".ui.activity.StorageMigrationActivity" />
<intent-filter>
<action android:name="android.intent.action.SEND" />

Expand Down
52 changes: 52 additions & 0 deletions res/layout/migration_layout.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Nextcloud Android client application

Copyright (C) 2016 Bartosz Przybylski
Copyright (C) 2016 Nextcloud

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
License as published by the Free Software Foundation; either
version 3 of the License, or any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU AFFERO GENERAL PUBLIC LICENSE for more details.

You should have received a copy of the GNU Affero General Public
License along with this program. If not, see <http://www.gnu.org/licenses/>.
-->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="vertical">

<ProgressBar
android:id="@+id/migrationProgress"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:paddingLeft="30dp"
android:paddingRight="30dp"
android:progress="50"/>

<TextView
android:id="@+id/migrationText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text=""
android:textAppearance="?android:attr/textAppearanceMedium"/>

<Button
android:id="@+id/finishButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="@string/drawer_close"/>
</LinearLayout>
28 changes: 28 additions & 0 deletions res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,28 @@
<string name="uploader_upload_forbidden_permissions">to upload in this folder</string>
<string name="downloader_download_file_not_found">The file is no longer available on the server</string>

<string name="file_migration_dialog_title">Updating storage path</string>
<string name="file_migration_finish_button">Finish</string>
<string name="file_migration_preparing">Preparing for migration&#8230;</string>
<string name="file_migration_checking_destination">Checking destination&#8230;</string>
<string name="file_migration_saving_accounts_configuration">Saving accounts configuration&#8230;</string>
<string name="file_migration_waiting_for_unfinished_sync">Waiting for unfinished synchronizations&#8230;</string>
<string name="file_migration_migrating">Moving data&#8230;</string>
<string name="file_migration_updating_index">Updating index&#8230;</string>
<string name="file_migration_cleaning">Cleaning&#8230;</string>
<string name="file_migration_restoring_accounts_configuration">Restoring accounts configuration&#8230;</string>
<string name="file_migration_ok_finished">Finished</string>
<string name="file_migration_failed_not_enough_space">ERROR: Not enough space</string>
<string name="file_migration_failed_not_writable">ERROR: File is not writable</string>
<string name="file_migration_failed_not_readable">ERROR: File is not readable</string>
<string name="file_migration_failed_dir_already_exists">ERROR: Nextcloud directory already exists</string>
<string name="file_migration_failed_while_coping">ERROR: While migrating</string>
<string name="file_migration_failed_while_updating_index">ERROR: While updating index</string>

<string name="file_migration_directory_already_exists">Data folder already exists, what to do?</string>
<string name="file_migration_override_data_folder">Override</string>
<string name="file_migration_use_data_folder">Use existing</string>

<string name="prefs_category_accounts">Accounts</string>
<string name="prefs_add_account">Add account</string>
<string name="drawer_manage_accounts">Manage accounts</string>
Expand Down Expand Up @@ -422,6 +444,8 @@
<string name="pref_behaviour_entries_keep_file">kept in original folder</string>
<string name="pref_behaviour_entries_move">moved to app folder</string>
<string name="pref_behaviour_entries_delete_file">deleted</string>
<string name="prefs_storage_path">Storage path</string>
<string name="prefs_common">Common</string>

<string name="share_dialog_title">Sharing</string>
<string name="share_file">Share %1$s</string>
Expand Down Expand Up @@ -506,4 +530,8 @@
<item quantity="other">%d selected</item>
</plurals>

<string name="storage_description_default">Default</string>
<string name="storage_description_sd_no">SD card %1$d</string>
<string name="storage_description_unknown">Unknown</string>

</resources>
5 changes: 5 additions & 0 deletions res/xml/preferences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:title="@string/prefs_category_general">
<ListPreference
android:title="@string/prefs_storage_path"
android:key="storage_path" />
</PreferenceCategory>

<PreferenceCategory android:title="@string/prefs_category_instant_uploading" android:key="instant_uploading_category">
<com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle android:key="instant_uploading"
Expand Down
23 changes: 20 additions & 3 deletions src/com/owncloud/android/MainApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,19 @@
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Environment;
import android.preference.PreferenceManager;

import com.owncloud.android.authentication.PassCodeManager;
import com.owncloud.android.datamodel.ThumbnailsCacheManager;
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
import com.owncloud.android.lib.common.OwnCloudClientManagerFactory.Policy;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.ui.activity.Preferences;


/**
Expand All @@ -54,13 +57,20 @@ public class MainApp extends Application {

private static Context mContext;

private static String storagePath;

private static boolean mOnlyOnDevice = false;


public void onCreate(){
super.onCreate();
MainApp.mContext = getApplicationContext();


SharedPreferences appPrefs =
PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
MainApp.storagePath = appPrefs.getString(Preferences.Keys.STORAGE_PATH, Environment.
getExternalStorageDirectory().getAbsolutePath());

boolean isSamlAuth = AUTH_ON.equals(getString(R.string.auth_method_saml_web_sso));

OwnCloudClientManagerFactory.setUserAgent(getUserAgent());
Expand All @@ -80,8 +90,7 @@ public void onCreate(){
// Set folder for store logs
Log_OC.setLogDataFolder(dataFolder);

//TODO: to be changed/fixed whenever SD card support gets merged.
Log_OC.startLogging(Environment.getExternalStorageDirectory().getAbsolutePath());
Log_OC.startLogging(MainApp.storagePath);
Log_OC.d("Debug", "start logging");
}

Expand Down Expand Up @@ -132,6 +141,14 @@ public static Context getAppContext() {
return MainApp.mContext;
}

public static String getStoragePath(){
return MainApp.storagePath;
}

public static void setStoragePath(String path){
MainApp.storagePath = path;
}

// Methods to obtain Strings referring app_name
// From AccountAuthenticator
// public static final String ACCOUNT_TYPE = "owncloud";
Expand Down
86 changes: 53 additions & 33 deletions src/com/owncloud/android/datamodel/FileDataStorageManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,6 @@
import com.owncloud.android.utils.MimeTypeUtil;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
Expand Down Expand Up @@ -727,44 +722,69 @@ public void copyLocalFile(OCFile file, String targetPath) {
if (!targetFolder.exists()) {
targetFolder.mkdirs();
}
copied = copyFile(localFile, targetFile);
copied = FileStorageUtils.copyFile(localFile, targetFile);
}
Log_OC.d(TAG, "Local file COPIED : " + copied);
}
}

private boolean copyFile(File src, File target) {
boolean ret = true;

InputStream in = null;
OutputStream out = null;
public void migrateStoredFiles(String srcPath, String dstPath) throws Exception {
Cursor c = null;
if (getContentResolver() != null) {
c = getContentResolver().query(ProviderTableMeta.CONTENT_URI_FILE,
null,
ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL",
null,
null);

try {
in = new FileInputStream(src);
out = new FileOutputStream(target);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
} catch (IOException ex) {
ret = false;
} finally {
if (in != null) try {
in.close();
} catch (IOException e) {
e.printStackTrace(System.err);
}
if (out != null) try {
out.close();
} catch (IOException e) {
e.printStackTrace(System.err);
} else {
try {
c = getContentProviderClient().query(ProviderTableMeta.CONTENT_URI_FILE,
new String[]{ProviderTableMeta._ID, ProviderTableMeta.FILE_STORAGE_PATH},
ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL",
null,
null);
} catch (RemoteException e) {
Log_OC.e(TAG, e.getMessage());
throw e;
}
}

return ret;
}
ArrayList<ContentProviderOperation> operations =
new ArrayList<ContentProviderOperation>(c.getCount());
if (c.moveToFirst()) {
do {
ContentValues cv = new ContentValues();
long fileId = c.getLong(c.getColumnIndex(ProviderTableMeta._ID));
String oldFileStoragePath = c.getString(c.getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH));

if (oldFileStoragePath.startsWith(srcPath)) {

cv.put(
ProviderTableMeta.FILE_STORAGE_PATH,
oldFileStoragePath.replaceFirst(srcPath, dstPath));

operations.add(
ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
withValues(cv).
withSelection(
ProviderTableMeta._ID + "=?",
new String[]{String.valueOf(fileId)}
)
.build());
}

} while (c.moveToNext());
}
c.close();

/// 3. apply updates in batch
if (getContentResolver() != null) {
getContentResolver().applyBatch(MainApp.getAuthority(), operations);
} else {
getContentProviderClient().applyBatch(operations);
}
}

private Vector<OCFile> getFolderContent(long parentId, boolean onlyOnDevice) {

Expand Down
Loading