X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/blobdiff_plain/fa6d145f9147aea0101359d43da3d81107c71597..9aab2d26da38f26e7ff03a0b5db3bd01b51bce05:/src/com/owncloud/android/ui/activity/FileDisplayActivity.java diff --git a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java index 2bfab6d4..9b204f36 100644 --- a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java @@ -19,21 +19,21 @@ package com.owncloud.android.ui.activity; import java.io.File; -import java.util.ArrayList; import android.accounts.Account; -import android.accounts.AccountManager; import android.app.AlertDialog; import android.app.ProgressDialog; import android.app.AlertDialog.Builder; import android.app.Dialog; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.IntentFilter; +import android.content.ServiceConnection; import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; @@ -42,6 +42,7 @@ import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.Handler; +import android.os.IBinder; import android.preference.PreferenceManager; import android.provider.MediaStore; import android.support.v4.app.FragmentTransaction; @@ -61,16 +62,22 @@ import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; import com.actionbarsherlock.view.Window; import com.owncloud.android.AccountUtils; -import com.owncloud.android.CrashHandler; import com.owncloud.android.authenticator.AccountAuthenticator; import com.owncloud.android.datamodel.DataStorageManager; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.services.FileDownloader; +import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder; +import com.owncloud.android.files.services.FileObserverService; import com.owncloud.android.files.services.FileUploader; +import com.owncloud.android.files.services.FileUploader.FileUploaderBinder; +import com.owncloud.android.network.OwnCloudClientUtils; +import com.owncloud.android.operations.RemoteOperationResult; import com.owncloud.android.syncadapter.FileSyncService; +import com.owncloud.android.ui.dialog.SslValidatorDialog; +import com.owncloud.android.ui.dialog.SslValidatorDialog.OnSslValidatorListener; import com.owncloud.android.ui.fragment.FileDetailFragment; -import com.owncloud.android.ui.fragment.FileListFragment; +import com.owncloud.android.ui.fragment.OCFileListFragment; import com.owncloud.android.R; import eu.alefzero.webdav.WebdavClient; @@ -83,86 +90,182 @@ import eu.alefzero.webdav.WebdavClient; */ public class FileDisplayActivity extends SherlockFragmentActivity implements - FileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNavigationListener, OnClickListener, android.view.View.OnClickListener { + OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNavigationListener, OnSslValidatorListener { private ArrayAdapter mDirectories; - private OCFile mCurrentDir; - private String[] mDirs = null; + private OCFile mCurrentDir = null; + private OCFile mCurrentFile = null; private DataStorageManager mStorageManager; private SyncBroadcastReceiver mSyncBroadcastReceiver; private UploadFinishReceiver mUploadFinishReceiver; private DownloadFinishReceiver mDownloadFinishReceiver; + private FileDownloaderBinder mDownloaderBinder = null; + private FileUploaderBinder mUploaderBinder = null; + private ServiceConnection mDownloadConnection = null, mUploadConnection = null; + private RemoteOperationResult mLastSslUntrustedServerResult = null; - private View mLayoutView = null; - private FileListFragment mFileList; + private OCFileListFragment mFileList; private boolean mDualPane; - private boolean mForcedLoginToCreateFirstAccount = false; - - private static final String KEY_DIR_ARRAY = "DIR_ARRAY"; - private static final String KEY_CURRENT_DIR = "DIR"; - private static final int DIALOG_SETUP_ACCOUNT = 0; private static final int DIALOG_CREATE_DIR = 1; private static final int DIALOG_ABOUT_APP = 2; public static final int DIALOG_SHORT_WAIT = 3; + private static final int DIALOG_CHOOSE_UPLOAD_SOURCE = 4; + private static final int DIALOG_SSL_VALIDATOR = 5; + private static final int DIALOG_CERT_NOT_SAVED = 6; + - private static final int ACTION_SELECT_FILE = 1; + private static final int ACTION_SELECT_CONTENT_FROM_APPS = 1; + private static final int ACTION_SELECT_MULTIPLE_FILES = 2; private static final String TAG = "FileDisplayActivity"; - @Override public void onCreate(Bundle savedInstanceState) { - Log.i(getClass().toString(), "onCreate() start"); + Log.d(getClass().toString(), "onCreate() start"); super.onCreate(savedInstanceState); - requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); - - Thread.setDefaultUncaughtExceptionHandler(new CrashHandler(getApplicationContext())); - + /// Load of parameters from received intent + mCurrentDir = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_FILE); // no check necessary, mCurrenDir == null if the parameter is not in the intent + Account account = getIntent().getParcelableExtra(FileDetailFragment.EXTRA_ACCOUNT); + if (account != null) + AccountUtils.setCurrentOwnCloudAccount(this, account.name); + + /// Load of saved instance state: keep this always before initDataFromCurrentAccount() if(savedInstanceState != null) { - mDirs = savedInstanceState.getStringArray(KEY_DIR_ARRAY); - mDirectories = new CustomArrayAdapter(this, R.layout.sherlock_spinner_dropdown_item); - mDirectories.add(OCFile.PATH_SEPARATOR); - if (mDirs != null) - for (String s : mDirs) - mDirectories.insert(s, 0); + // TODO - test if savedInstanceState should take precedence over file in the intent ALWAYS (now), NEVER, or SOME TIMES mCurrentDir = savedInstanceState.getParcelable(FileDetailFragment.EXTRA_FILE); } - mLayoutView = getLayoutInflater().inflate(R.layout.files, null); // always inflate this at onCreate() ; just once! - - if (AccountUtils.accountsAreSetup(this)) { + if (!AccountUtils.accountsAreSetup(this)) { + /// no account available: FORCE ACCOUNT CREATION + mStorageManager = null; + createFirstAccount(); - initDelayedTilAccountAvailabe(); + } else { /// at least an account is available - // PIN CODE request ; best location is to decide, let's try this first - //if (savedInstanceState == null) { - if (getIntent().getAction() != null && getIntent().getAction().equals(Intent.ACTION_MAIN) && savedInstanceState == null) { - requestPinCode(); - } + initDataFromCurrentAccount(); // it checks mCurrentDir and mCurrentFile with the current account + } + + mUploadConnection = new ListServiceConnection(); + mDownloadConnection = new ListServiceConnection(); + bindService(new Intent(this, FileUploader.class), mUploadConnection, Context.BIND_AUTO_CREATE); + bindService(new Intent(this, FileDownloader.class), mDownloadConnection, Context.BIND_AUTO_CREATE); + + // PIN CODE request ; best location is to decide, let's try this first + if (getIntent().getAction() != null && getIntent().getAction().equals(Intent.ACTION_MAIN) && savedInstanceState == null) { + requestPinCode(); + } + + // file observer + Intent observer_intent = new Intent(this, FileObserverService.class); + observer_intent.putExtra(FileObserverService.KEY_FILE_CMD, FileObserverService.CMD_INIT_OBSERVED_LIST); + startService(observer_intent); + - } else { + /// USER INTERFACE + requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); + + // Drop-down navigation + mDirectories = new CustomArrayAdapter(this, R.layout.sherlock_spinner_dropdown_item); + OCFile currFile = mCurrentDir; + while(currFile != null && currFile.getFileName() != OCFile.PATH_SEPARATOR) { + mDirectories.add(currFile.getFileName()); + currFile = mStorageManager.getFileById(currFile.getParentId()); + } + mDirectories.add(OCFile.PATH_SEPARATOR); + + // Inflate and set the layout view + setContentView(R.layout.files); + mFileList = (OCFileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList); + mDualPane = (findViewById(R.id.file_details_container) != null); + if (mDualPane) { + initFileDetailsInDualPane(); + } - setContentView(R.layout.no_account_available); - getSupportActionBar().setNavigationMode(ActionBar.DISPLAY_SHOW_TITLE); - findViewById(R.id.setup_account).setOnClickListener(this); + // Action bar setup + ActionBar actionBar = getSupportActionBar(); + actionBar.setHomeButtonEnabled(true); // mandatory since Android ICS, according to the official documentation + actionBar.setDisplayHomeAsUpEnabled(mCurrentDir != null && mCurrentDir.getParentId() != 0); + actionBar.setDisplayShowTitleEnabled(false); + actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); + actionBar.setListNavigationCallbacks(mDirectories, this); + setSupportProgressBarIndeterminateVisibility(false); // always AFTER setContentView(...) ; to workaround bug in its implementation + + Log.d(getClass().toString(), "onCreate() end"); + } - setSupportProgressBarIndeterminateVisibility(false); + + /** + * Launches the account creation activity. To use when no ownCloud account is available + */ + private void createFirstAccount() { + Intent intent = new Intent(android.provider.Settings.ACTION_ADD_ACCOUNT); + intent.putExtra(android.provider.Settings.EXTRA_AUTHORITIES, new String[] { AccountAuthenticator.AUTH_TOKEN_TYPE }); + startActivity(intent); // the new activity won't be created until this.onStart() and this.onResume() are finished; + } - Intent intent = new Intent(android.provider.Settings.ACTION_ADD_ACCOUNT); - intent.putExtra(android.provider.Settings.EXTRA_AUTHORITIES, new String[] { AccountAuthenticator.AUTH_TOKEN_TYPE }); - startActivity(intent); // although the code is here, the activity won't be created until this.onStart() and this.onResume() are finished; - mForcedLoginToCreateFirstAccount = true; + + /** + * Load of state dependent of the existence of an ownCloud account + */ + private void initDataFromCurrentAccount() { + /// Storage manager initialization - access to local database + mStorageManager = new FileDataStorageManager( + AccountUtils.getCurrentOwnCloudAccount(this), + getContentResolver()); + + /// Check if mCurrentDir is a directory + if(mCurrentDir != null && !mCurrentDir.isDirectory()) { + mCurrentFile = mCurrentDir; + mCurrentDir = mStorageManager.getFileById(mCurrentDir.getParentId()); } - Log.i(getClass().toString(), "onCreate() end"); + /// Check if mCurrentDir and mCurrentFile are in the current account, and update them + if (mCurrentDir != null) { + mCurrentDir = mStorageManager.getFileByPath(mCurrentDir.getRemotePath()); // mCurrentDir == null if it is not in the current account + } + if (mCurrentFile != null) { + if (mCurrentFile.fileExists()) { + mCurrentFile = mStorageManager.getFileByPath(mCurrentFile.getRemotePath()); // mCurrentFile == null if it is not in the current account + } // else : keep mCurrentFile with the received value; this is currently the case of an upload in progress, when the user presses the status notification in a landscape tablet + } + + /// Default to root if mCurrentDir was not found + if (mCurrentDir == null) { + mCurrentDir = mStorageManager.getFileByPath("/"); // will be NULL if the database was never synchronized + } + } + + + private void initFileDetailsInDualPane() { + if (mDualPane && getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG) == null) { + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + if (mCurrentFile != null) { + transaction.replace(R.id.file_details_container, new FileDetailFragment(mCurrentFile, AccountUtils.getCurrentOwnCloudAccount(this)), FileDetailFragment.FTAG); // empty FileDetailFragment + mCurrentFile = null; + } else { + transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null), FileDetailFragment.FTAG); // empty FileDetailFragment + } + transaction.commit(); + } + } + + + @Override + public void onDestroy() { + super.onDestroy(); + if (mDownloadConnection != null) + unbindService(mDownloadConnection); + if (mUploadConnection != null) + unbindService(mUploadConnection); } + @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getSherlock().getMenuInflater(); @@ -179,21 +282,11 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements break; } case R.id.startSync: { - ContentResolver.cancelSync(null, "org.owncloud"); // cancel the current synchronizations of any ownCloud account - Bundle bundle = new Bundle(); - bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); - ContentResolver.requestSync( - AccountUtils.getCurrentOwnCloudAccount(this), - "org.owncloud", bundle); + startSynchronization(); break; } case R.id.action_upload: { - Intent action = new Intent(Intent.ACTION_GET_CONTENT); - action = action.setType("*/*") - .addCategory(Intent.CATEGORY_OPENABLE); - startActivityForResult( - Intent.createChooser(action, getString(R.string.upload_chooser_title)), - ACTION_SELECT_FILE); + showDialog(DIALOG_CHOOSE_UPLOAD_SOURCE); break; } case R.id.action_settings: { @@ -217,12 +310,27 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements return retval; } + private void startSynchronization() { + ContentResolver.cancelSync(null, AccountAuthenticator.AUTH_TOKEN_TYPE); // cancel the current synchronizations of any ownCloud account + Bundle bundle = new Bundle(); + bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); + ContentResolver.requestSync( + AccountUtils.getCurrentOwnCloudAccount(this), + AccountAuthenticator.AUTH_TOKEN_TYPE, bundle); + } + + @Override public boolean onNavigationItemSelected(int itemPosition, long itemId) { int i = itemPosition; while (i-- != 0) { onBackPressed(); } + // the next operation triggers a new call to this method, but it's necessary to + // ensure that the name exposed in the action bar is the current directory when the + // user selected it in the navigation list + if (itemPosition != 0) + getSupportActionBar().setSelectedNavigationItem(0); return true; } @@ -230,61 +338,93 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements * Called, when the user selected something for uploading */ public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (requestCode == ACTION_SELECT_FILE) { - if (resultCode == RESULT_OK) { - String filepath = null; - try { - Uri selectedImageUri = data.getData(); - - String filemanagerstring = selectedImageUri.getPath(); - String selectedImagePath = getPath(selectedImageUri); - - if (selectedImagePath != null) - filepath = selectedImagePath; - else - filepath = filemanagerstring; - - } catch (Exception e) { - Log.e("FileDisplay", "Unexpected exception when trying to read the result of Intent.ACTION_GET_CONTENT", e); - e.printStackTrace(); - - } finally { - if (filepath == null) { - Log.e("FileDisplay", "Couldnt resolve path to file"); - 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, - AccountUtils.getCurrentOwnCloudAccount(this)); - 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; - remotepath += new File(filepath).getName(); - - i.putExtra(FileUploader.KEY_LOCAL_FILE, filepath); - i.putExtra(FileUploader.KEY_REMOTE_FILE, remotepath); - i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE); - startService(i); + + if (requestCode == ACTION_SELECT_CONTENT_FROM_APPS && resultCode == RESULT_OK) { + requestSimpleUpload(data); + + } else if (requestCode == ACTION_SELECT_MULTIPLE_FILES && resultCode == RESULT_OK) { + requestMultipleUpload(data); + + } + } + + private void requestMultipleUpload(Intent data) { + String[] filePaths = data.getStringArrayExtra(UploadFilesActivity.EXTRA_CHOSEN_FILES); + if (filePaths != null) { + String[] remotePaths = new String[filePaths.length]; + String remotePathBase = ""; + for (int j = mDirectories.getCount() - 2; j >= 0; --j) { + remotePathBase += OCFile.PATH_SEPARATOR + mDirectories.getItem(j); + } + if (!remotePathBase.endsWith(OCFile.PATH_SEPARATOR)) + remotePathBase += OCFile.PATH_SEPARATOR; + for (int j = 0; j< remotePaths.length; j++) { + remotePaths[j] = remotePathBase + (new File(filePaths[j])).getName(); } + + Intent i = new Intent(this, FileUploader.class); + i.putExtra(FileUploader.KEY_ACCOUNT, AccountUtils.getCurrentOwnCloudAccount(this)); + i.putExtra(FileUploader.KEY_LOCAL_FILE, filePaths); + i.putExtra(FileUploader.KEY_REMOTE_FILE, remotePaths); + i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_MULTIPLE_FILES); + startService(i); + + } else { + Log.d("FileDisplay", "User clicked on 'Update' with no selection"); + Toast t = Toast.makeText(this, getString(R.string.filedisplay_no_file_selected), Toast.LENGTH_LONG); + t.show(); + return; + } + } + + + private void requestSimpleUpload(Intent data) { + String filepath = null; + try { + Uri selectedImageUri = data.getData(); + + String filemanagerstring = selectedImageUri.getPath(); + String selectedImagePath = getPath(selectedImageUri); + + if (selectedImagePath != null) + filepath = selectedImagePath; + else + filepath = filemanagerstring; + + } catch (Exception e) { + Log.e("FileDisplay", "Unexpected exception when trying to read the result of Intent.ACTION_GET_CONTENT", e); + e.printStackTrace(); - }/* dvelasco: WIP - not working as expected ... yet :) - else if (requestCode == ACTION_CREATE_FIRST_ACCOUNT) { - if (resultCode != RESULT_OK) { - finish(); // the user cancelled the AuthenticatorActivity + } finally { + if (filepath == null) { + Log.e("FileDisplay", "Couldnt resolve path to file"); + 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, + AccountUtils.getCurrentOwnCloudAccount(this)); + 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; + remotepath += new File(filepath).getName(); + + i.putExtra(FileUploader.KEY_LOCAL_FILE, filepath); + i.putExtra(FileUploader.KEY_REMOTE_FILE, remotepath); + i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE); + startService(i); } + @Override public void onBackPressed() { - if (mDirectories == null || mDirectories.getCount() <= 1) { + if (mDirectories.getCount() <= 1) { finish(); return; } @@ -298,7 +438,7 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements if (fileDetails != null && !fileDetails.isEmpty()) { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.remove(fileDetails); - transaction.add(R.id.file_details_container, new FileDetailFragment(null, null)); + transaction.add(R.id.file_details_container, new FileDetailFragment(null, null), FileDetailFragment.FTAG); transaction.commit(); } } @@ -311,34 +451,37 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements @Override protected void onSaveInstanceState(Bundle outState) { - // responsability of restore is prefered in onCreate() before than in onRestoreInstanceState when there are Fragments involved - Log.i(getClass().toString(), "onSaveInstanceState() start"); + // responsibility of restore is preferred in onCreate() before than in onRestoreInstanceState when there are Fragments involved + Log.d(getClass().toString(), "onSaveInstanceState() start"); super.onSaveInstanceState(outState); - if(mDirectories != null && mDirectories.getCount() != 0){ - mDirs = new String[mDirectories.getCount()-1]; - for (int j = mDirectories.getCount() - 2, i = 0; j >= 0; --j, ++i) { - mDirs[i] = mDirectories.getItem(j); + outState.putParcelable(FileDetailFragment.EXTRA_FILE, mCurrentDir); + if (mDualPane) { + FileDetailFragment fragment = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG); + if (fragment != null) { + OCFile file = fragment.getDisplayedFile(); + if (file != null) { + outState.putParcelable(FileDetailFragment.EXTRA_FILE, file); + } } } - outState.putStringArray(KEY_DIR_ARRAY, mDirs); - outState.putParcelable(FileDetailFragment.EXTRA_FILE, mCurrentDir); - Log.i(getClass().toString(), "onSaveInstanceState() end"); + Log.d(getClass().toString(), "onSaveInstanceState() end"); } @Override protected void onResume() { - Log.i(getClass().toString(), "onResume() start"); + Log.d(getClass().toString(), "onResume() start"); super.onResume(); if (AccountUtils.accountsAreSetup(this)) { - // at least an account exist: normal operation - // set the layout only if it couldn't be set in onCreate - if (mForcedLoginToCreateFirstAccount) { - initDelayedTilAccountAvailabe(); - mForcedLoginToCreateFirstAccount = false; + if (mStorageManager == null) { + // this is necessary for handling the come back to FileDisplayActivity when the first ownCloud account is created + initDataFromCurrentAccount(); + if (mDualPane) { + initFileDetailsInDualPane(); + } } - + // Listen for sync messages IntentFilter syncIntentFilter = new IntentFilter(FileSyncService.SYNC_MESSAGE); mSyncBroadcastReceiver = new SyncBroadcastReceiver(); @@ -354,77 +497,22 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements mDownloadFinishReceiver = new DownloadFinishReceiver(); registerReceiver(mDownloadFinishReceiver, downloadIntentFilter); - // Storage manager initialization - mStorageManager = new FileDataStorageManager( - AccountUtils.getCurrentOwnCloudAccount(this), - getContentResolver()); - - // File list fragments - mFileList = (FileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList); - - - // Figure out what directory to list. - // Priority: Intent (here), savedInstanceState (onCreate), root dir (dir is null) - if(getIntent().hasExtra(FileDetailFragment.EXTRA_FILE)){ - mCurrentDir = (OCFile) getIntent().getParcelableExtra(FileDetailFragment.EXTRA_FILE); - if(mCurrentDir != null && !mCurrentDir.isDirectory()){ - mCurrentDir = mStorageManager.getFileById(mCurrentDir.getParentId()); - } + // List current directory + mFileList.listDirectory(mCurrentDir); // TODO we should find the way to avoid the need of this (maybe it's not necessary yet; to check) - // Clear intent extra, so rotating the screen will not return us to this directory - getIntent().removeExtra(FileDetailFragment.EXTRA_FILE); - } + } else { - if (mCurrentDir == null) - mCurrentDir = mStorageManager.getFileByPath("/"); - - // Drop-Down navigation and file list restore - mDirectories = new CustomArrayAdapter(this, R.layout.sherlock_spinner_dropdown_item); - - - // Given the case we have a file to display: - if(mCurrentDir != null){ - ArrayList files = new ArrayList(); - OCFile currFile = mCurrentDir; - while(currFile != null){ - files.add(currFile); - currFile = mStorageManager.getFileById(currFile.getParentId()); - } + mStorageManager = null; // an invalid object will be there if all the ownCloud accounts are removed + showDialog(DIALOG_SETUP_ACCOUNT); - // Insert in mDirs - mDirs = new String[files.size()]; - for(int i = files.size() - 1; i >= 0; i--){ - mDirs[i] = files.get(i).getFileName(); - } - } - - if (mDirs != null) { - for (String s : mDirs) - mDirectories.add(s); - } else { - mDirectories.add(OCFile.PATH_SEPARATOR); - } - - // Actionbar setup - ActionBar action_bar = getSupportActionBar(); - action_bar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); - action_bar.setDisplayShowTitleEnabled(false); - action_bar.setListNavigationCallbacks(mDirectories, this); - if(mCurrentDir != null && mCurrentDir.getParentId() != 0){ - action_bar.setDisplayHomeAsUpEnabled(true); - } else { - action_bar.setDisplayHomeAsUpEnabled(false); - } - - // List dir here - mFileList.listDirectory(mCurrentDir); } - Log.i(getClass().toString(), "onResume() end"); + Log.d(getClass().toString(), "onResume() end"); } + @Override protected void onPause() { - Log.i(getClass().toString(), "onPause() start"); + Log.d(getClass().toString(), "onPause() start"); super.onPause(); if (mSyncBroadcastReceiver != null) { unregisterReceiver(mSyncBroadcastReceiver); @@ -438,32 +526,55 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements unregisterReceiver(mDownloadFinishReceiver); mDownloadFinishReceiver = null; } + if (!AccountUtils.accountsAreSetup(this)) { + dismissDialog(DIALOG_SETUP_ACCOUNT); + } - getIntent().putExtra(FileDetailFragment.EXTRA_FILE, mCurrentDir); - Log.i(getClass().toString(), "onPause() end"); + Log.d(getClass().toString(), "onPause() end"); } + + @Override + protected void onPrepareDialog(int id, Dialog dialog, Bundle args) { + if (id == DIALOG_SSL_VALIDATOR && mLastSslUntrustedServerResult != null) { + ((SslValidatorDialog)dialog).updateResult(mLastSslUntrustedServerResult); + } + } + + @Override protected Dialog onCreateDialog(int id) { Dialog dialog = null; AlertDialog.Builder builder; switch (id) { - case DIALOG_SETUP_ACCOUNT: + case DIALOG_SETUP_ACCOUNT: { builder = new AlertDialog.Builder(this); builder.setTitle(R.string.main_tit_accsetup); builder.setMessage(R.string.main_wrn_accsetup); builder.setCancelable(false); - builder.setPositiveButton(android.R.string.ok, this); - builder.setNegativeButton(android.R.string.cancel, this); + builder.setPositiveButton(android.R.string.ok, new OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + createFirstAccount(); + dialog.dismiss(); + } + }); + builder.setNegativeButton(R.string.common_exit, new OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + finish(); + } + }); + //builder.setNegativeButton(android.R.string.cancel, this); dialog = builder.create(); break; + } case DIALOG_ABOUT_APP: { builder = new AlertDialog.Builder(this); builder.setTitle(getString(R.string.about_title)); PackageInfo pkg; try { pkg = getPackageManager().getPackageInfo(getPackageName(), 0); - builder.setMessage("ownCloud android client\n\nversion: " + pkg.versionName ); + builder.setMessage(String.format(getString(R.string.about_message), pkg.versionName)); builder.setIcon(android.R.drawable.ic_menu_info_details); dialog = builder.create(); } catch (NameNotFoundException e) { @@ -476,7 +587,6 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements case DIALOG_CREATE_DIR: { builder = new Builder(this); final EditText dirNameInput = new EditText(getBaseContext()); - final Account a = AccountUtils.getCurrentOwnCloudAccount(this); builder.setView(dirNameInput); builder.setTitle(R.string.uploader_info_dirname); int typed_color = getResources().getColor(R.color.setup_text_typed); @@ -504,7 +614,7 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements // Create directory path += directoryName + OCFile.PATH_SEPARATOR; - Thread thread = new Thread(new DirectoryCreator(path, a, new Handler())); + Thread thread = new Thread(new DirectoryCreator(path, AccountUtils.getCurrentOwnCloudAccount(FileDisplayActivity.this), new Handler())); thread.start(); dialog.dismiss(); @@ -530,6 +640,50 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements dialog = working_dialog; break; } + case DIALOG_CHOOSE_UPLOAD_SOURCE: { + final String [] items = { getString(R.string.actionbar_upload_files), + getString(R.string.actionbar_upload_from_apps) }; + builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.actionbar_upload); + builder.setItems(items, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int item) { + if (item == 0) { + //if (!mDualPane) { + Intent action = new Intent(FileDisplayActivity.this, UploadFilesActivity.class); + 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); + startActivityForResult( + Intent.createChooser(action, getString(R.string.upload_chooser_title)), + ACTION_SELECT_CONTENT_FROM_APPS); + } + } + }); + dialog = builder.create(); + break; + } + case DIALOG_SSL_VALIDATOR: { + dialog = SslValidatorDialog.newInstance(this, mLastSslUntrustedServerResult, this); + 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; } @@ -539,27 +693,6 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements /** - * Responds to the "There are no ownCloud Accounts setup" dialog - * TODO: Dialog is 100% useless -> Remove - */ - @Override - public void onClick(DialogInterface dialog, int which) { - // In any case - we won't need it anymore - dialog.dismiss(); - switch (which) { - case DialogInterface.BUTTON_POSITIVE: - Intent intent = new Intent("android.settings.ADD_ACCOUNT_SETTINGS"); - intent.putExtra("authorities", - new String[] { AccountAuthenticator.AUTH_TOKEN_TYPE }); - startActivity(intent); - break; - case DialogInterface.BUTTON_NEGATIVE: - finish(); - } - - } - - /** * Translates a content URI of an image to a physical path * on the disk * @param uri The URI to resolve @@ -602,26 +735,17 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements private class DirectoryCreator implements Runnable { private String mTargetPath; private Account mAccount; - private AccountManager mAm; private Handler mHandler; public DirectoryCreator(String targetPath, Account account, Handler handler) { mTargetPath = targetPath; mAccount = account; - mAm = (AccountManager) getSystemService(ACCOUNT_SERVICE); mHandler = handler; } @Override public void run() { - WebdavClient wdc = new WebdavClient(mAccount, getApplicationContext()); - - String username = mAccount.name.substring(0, - mAccount.name.lastIndexOf('@')); - String password = mAm.getPassword(mAccount); - - wdc.setCredentials(username, password); - wdc.allowSelfsignedCertificates(); + WebdavClient wdc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getApplicationContext()); boolean created = wdc.createDirectory(mTargetPath); if (created) { mHandler.post(new Runnable() { @@ -636,7 +760,7 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements mStorageManager.saveFile(newDir); // Display the new folder right away - mFileList.listDirectory(mCurrentDir); + mFileList.listDirectory(); } }); @@ -687,6 +811,7 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements } private class SyncBroadcastReceiver extends BroadcastReceiver { + /** * {@link BroadcastReceiver} to enable syncing feedback in UI */ @@ -714,16 +839,24 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements || fillBlankRoot ) { if (!fillBlankRoot) mCurrentDir = getStorageManager().getFileByPath(synchFolderRemotePath); - FileListFragment fileListFragment = (FileListFragment) getSupportFragmentManager() + OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager() .findFragmentById(R.id.fileList); if (fileListFragment != null) { - fileListFragment.listDirectory(mCurrentDir); + fileListFragment.listDirectory(mCurrentDir); } } setSupportProgressBarIndeterminateVisibility(inProgress); } + + RemoteOperationResult synchResult = (RemoteOperationResult)intent.getSerializableExtra(FileSyncService.SYNC_RESULT); + if (synchResult != null) { + if (synchResult.getCode().equals(RemoteOperationResult.ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED)) { + mLastSslUntrustedServerResult = synchResult; + showDialog(DIALOG_SSL_VALIDATOR); + } + } } } @@ -746,7 +879,7 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements parentDir.equals(mCurrentDir) ) ) { - FileListFragment fileListFragment = (FileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList); + OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList); if (fileListFragment != null) { fileListFragment.listDirectory(); } @@ -767,25 +900,13 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements if (accountName.equals(AccountUtils.getCurrentOwnCloudAccount(context).name) && mCurrentDir != null && mCurrentDir.getFileId() == mStorageManager.getFileByPath(downloadedRemotePath).getParentId()) { - FileListFragment fileListFragment = (FileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList); + OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList); if (fileListFragment != null) { fileListFragment.listDirectory(); } } } } - - - @Override - public void onClick(View v) { - if (v.getId() == R.id.setup_account) { - Intent intent = new Intent(android.provider.Settings.ACTION_ADD_ACCOUNT); - intent.putExtra(android.provider.Settings.EXTRA_AUTHORITIES, new String[] { AccountAuthenticator.AUTH_TOKEN_TYPE }); - startActivity(intent); - mForcedLoginToCreateFirstAccount = true; - } - } - @@ -814,7 +935,7 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements if (fileDetails != null && !fileDetails.isEmpty()) { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.remove(fileDetails); - transaction.add(R.id.file_details_container, new FileDetailFragment(null, null)); + transaction.add(R.id.file_details_container, new FileDetailFragment(null, null), FileDetailFragment.FTAG); transaction.commit(); } } @@ -838,7 +959,7 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements } else { // small or medium screen device -> new Activity Intent showDetailsIntent = new Intent(this, FileDetailActivity.class); showDetailsIntent.putExtra(FileDetailFragment.EXTRA_FILE, file); - showDetailsIntent.putExtra(FileDownloader.EXTRA_ACCOUNT, AccountUtils.getCurrentOwnCloudAccount(this)); + showDetailsIntent.putExtra(FileDetailFragment.EXTRA_ACCOUNT, AccountUtils.getCurrentOwnCloudAccount(this)); startActivity(showDetailsIntent); } } @@ -848,37 +969,79 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements * {@inheritDoc} */ @Override + public OCFile getInitialDirectory() { + return mCurrentDir; + } + + + /** + * {@inheritDoc} + */ + @Override public void onFileStateChanged() { - FileListFragment fileListFragment = (FileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList); + OCFileListFragment fileListFragment = (OCFileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList); if (fileListFragment != null) { fileListFragment.listDirectory(); } } + + /** + * {@inheritDoc} + */ + @Override + public FileDownloaderBinder getFileDownloaderBinder() { + return mDownloaderBinder; + } + /** - * Operations in this method should be preferably performed in onCreate to have a lighter onResume method. - * - * But we need to delay them to onResume for the first start of the application, when no account exists and the login activity must be shown; and - * put instead the ugly view that shows the 'Setup' button to restart the login activity. - * - * In other way, if the users cancels or presses BACK in the login page that first time (users can be cruel sometimes) would show a blank view (the - * FragmentList view empty). - * - * This is temporal, until we found out how to get a result in this activity after launching the ADD_ACCOUNT Intent with startActivityForResult (not trivial) + * {@inheritDoc} */ - private void initDelayedTilAccountAvailabe() { - setContentView(mLayoutView); - mDualPane = (findViewById(R.id.file_details_container) != null); - if (mDualPane && getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG) == null) { - FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); - transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null)); // empty FileDetailFragment - transaction.commit(); - } - setSupportProgressBarIndeterminateVisibility(false); + @Override + public FileUploaderBinder getFileUploaderBinder() { + return mUploaderBinder; } + + /** Defines callbacks for service binding, passed to bindService() */ + private class ListServiceConnection implements ServiceConnection { + + @Override + public void onServiceConnected(ComponentName component, IBinder service) { + if (component.equals(new ComponentName(FileDisplayActivity.this, FileDownloader.class))) { + Log.d(TAG, "Download service connected"); + mDownloaderBinder = (FileDownloaderBinder) service; + } else if (component.equals(new ComponentName(FileDisplayActivity.this, FileUploader.class))) { + Log.d(TAG, "Upload service connected"); + mUploaderBinder = (FileUploaderBinder) service; + } else { + return; + } + // a new chance to get the mDownloadBinder through getFileDownloadBinder() - THIS IS A MESS + if (mFileList != null) + mFileList.listDirectory(); + if (mDualPane) { + FileDetailFragment fragment = (FileDetailFragment) getSupportFragmentManager().findFragmentByTag(FileDetailFragment.FTAG); + if (fragment != null) + fragment.updateFileDetails(); + } + } + + @Override + public void onServiceDisconnected(ComponentName component) { + if (component.equals(new ComponentName(FileDisplayActivity.this, FileDownloader.class))) { + Log.d(TAG, "Download service disconnected"); + mDownloaderBinder = null; + } else if (component.equals(new ComponentName(FileDisplayActivity.this, FileUploader.class))) { + Log.d(TAG, "Upload service disconnected"); + mUploaderBinder = null; + } + } + }; + + /** * Launch an intent to request the PIN code to the user before letting him use the app */ @@ -893,5 +1056,17 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements } } - + + @Override + public void onSavedCertificate() { + startSynchronization(); + } + + + @Override + public void onFailedSavingCertificate() { + showDialog(DIALOG_CERT_NOT_SAVED); + } + + }