2  *   ownCloud Android client application 
   4  *   @author Bartek Przybylski 
   5  *   Copyright (C) 2012  Bartek Przybylski 
   6  *   Copyright (C) 2015 ownCloud Inc. 
   8  *   This program is free software: you can redistribute it and/or modify 
   9  *   it under the terms of the GNU General Public License version 2, 
  10  *   as published by the Free Software Foundation. 
  12  *   This program is distributed in the hope that it will be useful, 
  13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of 
  14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  15  *   GNU General Public License for more details. 
  17  *   You should have received a copy of the GNU General Public License 
  18  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. 
  22 package com
.owncloud
.android
.ui
.activity
; 
  25 import java
.util
.ArrayList
; 
  26 import java
.util
.HashMap
; 
  27 import java
.util
.LinkedList
; 
  28 import java
.util
.List
; 
  29 import java
.util
.Stack
; 
  30 import java
.util
.Vector
; 
  33 import android
.accounts
.Account
; 
  34 import android
.accounts
.AccountManager
; 
  35 import android
.app
.AlertDialog
; 
  36 import android
.app
.AlertDialog
.Builder
; 
  37 import android
.app
.Dialog
; 
  38 import android
.app
.ProgressDialog
; 
  39 import android
.content
.Context
; 
  40 import android
.content
.DialogInterface
; 
  41 import android
.content
.DialogInterface
.OnCancelListener
; 
  42 import android
.content
.DialogInterface
.OnClickListener
; 
  43 import android
.content
.Intent
; 
  44 import android
.content
.SharedPreferences
; 
  45 import android
.content
.res
.Resources
.NotFoundException
; 
  46 import android
.database
.Cursor
; 
  47 import android
.net
.Uri
; 
  48 import android
.os
.Bundle
; 
  49 import android
.os
.Parcelable
; 
  50 import android
.preference
.PreferenceManager
; 
  51 import android
.provider
.MediaStore
; 
  52 import android
.provider
.MediaStore
.Audio
; 
  53 import android
.provider
.MediaStore
.Images
; 
  54 import android
.provider
.MediaStore
.Video
; 
  55 import android
.support
.v4
.app
.Fragment
; 
  56 import android
.support
.v4
.app
.FragmentManager
; 
  57 import android
.support
.v4
.app
.FragmentTransaction
; 
  58 import android
.view
.View
; 
  59 import android
.widget
.AdapterView
; 
  60 import android
.widget
.AdapterView
.OnItemClickListener
; 
  61 import android
.widget
.Button
; 
  62 import android
.widget
.EditText
; 
  63 import android
.widget
.ListView
; 
  64 import android
.widget
.SimpleAdapter
; 
  65 import android
.widget
.Toast
; 
  67 import com
.actionbarsherlock
.app
.ActionBar
; 
  68 import com
.actionbarsherlock
.view
.MenuItem
; 
  69 import com
.owncloud
.android
.MainApp
; 
  70 import com
.owncloud
.android
.R
; 
  71 import com
.owncloud
.android
.authentication
.AccountAuthenticator
; 
  72 import com
.owncloud
.android
.datamodel
.OCFile
; 
  73 import com
.owncloud
.android
.files
.services
.FileUploader
; 
  74 import com
.owncloud
.android
.lib
.common
.operations
.RemoteOperation
; 
  75 import com
.owncloud
.android
.lib
.common
.operations
.RemoteOperationResult
; 
  76 import com
.owncloud
.android
.lib
.common
.utils
.Log_OC
; 
  77 import com
.owncloud
.android
.operations
.CreateFolderOperation
; 
  78 import com
.owncloud
.android
.ui
.dialog
.CreateFolderDialogFragment
; 
  79 import com
.owncloud
.android
.ui
.dialog
.LoadingDialog
; 
  80 import com
.owncloud
.android
.utils
.CopyTmpFileAsyncTask
; 
  81 import com
.owncloud
.android
.utils
.DisplayUtils
; 
  82 import com
.owncloud
.android
.utils
.ErrorMessageAdapter
; 
  86  * This can be used to upload things to an ownCloud instance. 
  88 public class Uploader 
extends FileActivity
 
  89         implements OnItemClickListener
, android
.view
.View
.OnClickListener
, 
  90         CopyTmpFileAsyncTask
.OnCopyTmpFileTaskListener 
{ 
  92     private static final String TAG 
= Uploader
.class.getSimpleName(); 
  94     private AccountManager mAccountManager
; 
  95     private Stack
<String
> mParents
; 
  96     private ArrayList
<Parcelable
> mStreamsToUpload
; 
  97     private boolean mCreateDir
; 
  98     private String mUploadPath
; 
 100     private boolean mAccountSelected
; 
 102     private ArrayList
<String
> mRemoteCacheData
; 
 103     private int mNumCacheFile
; 
 105     private final static int DIALOG_NO_ACCOUNT 
= 0; 
 106     private final static int DIALOG_WAITING 
= 1; 
 107     private final static int DIALOG_NO_STREAM 
= 2; 
 108     private final static int DIALOG_MULTIPLE_ACCOUNT 
= 3; 
 110     private final static int REQUEST_CODE_SETUP_ACCOUNT 
= 0; 
 112     private final static String KEY_PARENTS 
= "PARENTS"; 
 113     private final static String KEY_FILE 
= "FILE"; 
 114     private final static String KEY_ACCOUNT_SELECTED 
= "ACCOUNT_SELECTED"; 
 115     private final static String KEY_NUM_CACHE_FILE 
= "NUM_CACHE_FILE"; 
 116     private final static String KEY_REMOTE_CACHE_DATA 
= "REMOTE_CACHE_DATA"; 
 118     private static final String DIALOG_WAIT_COPY_FILE 
= "DIALOG_WAIT_COPY_FILE"; 
 121     protected void onCreate(Bundle savedInstanceState
) { 
 122         prepareStreamsToUpload(); 
 124         if (savedInstanceState 
== null
) { 
 125             mParents 
= new Stack
<String
>(); 
 126             mAccountSelected 
= false
; 
 129             // ArrayList for files with path in private storage 
 130             mRemoteCacheData 
= new ArrayList
<String
>(); 
 132             mParents 
= (Stack
<String
>) savedInstanceState
.getSerializable(KEY_PARENTS
); 
 133             mFile 
= savedInstanceState
.getParcelable(KEY_FILE
); 
 134             mAccountSelected 
= savedInstanceState
.getBoolean(KEY_ACCOUNT_SELECTED
); 
 135             mNumCacheFile 
= savedInstanceState
.getInt(KEY_NUM_CACHE_FILE
); 
 136             mRemoteCacheData 
= savedInstanceState
.getStringArrayList(KEY_REMOTE_CACHE_DATA
); 
 138         super.onCreate(savedInstanceState
); 
 140         ActionBar actionBar 
= getSupportActionBar(); 
 141         actionBar
.setIcon(DisplayUtils
.getSeasonalIconId()); 
 146     protected void setAccount(Account account
, boolean savedAccount
) { 
 147         if (somethingToUpload()) { 
 148             mAccountManager 
= (AccountManager
) getSystemService(Context
.ACCOUNT_SERVICE
); 
 149             Account
[] accounts 
= mAccountManager
.getAccountsByType(MainApp
.getAccountType()); 
 150             if (accounts
.length 
== 0) { 
 151                 Log_OC
.i(TAG
, "No ownCloud account is available"); 
 152                 showDialog(DIALOG_NO_ACCOUNT
); 
 153             } else if (accounts
.length 
> 1 && !mAccountSelected
) { 
 154                 Log_OC
.i(TAG
, "More than one ownCloud is available"); 
 155                 showDialog(DIALOG_MULTIPLE_ACCOUNT
); 
 158                     setAccount(accounts
[0]); 
 163             showDialog(DIALOG_NO_STREAM
); 
 166         super.setAccount(account
, savedAccount
); 
 170     protected void onAccountSet(boolean stateWasRecovered
) { 
 171         super.onAccountSet(mAccountWasRestored
); 
 173         populateDirectoryList(); 
 177     protected void onSaveInstanceState(Bundle outState
) { 
 178          Log_OC
.d(TAG
, "onSaveInstanceState() start"); 
 179         super.onSaveInstanceState(outState
); 
 180         outState
.putSerializable(KEY_PARENTS
, mParents
); 
 181         //outState.putParcelable(KEY_ACCOUNT, mAccount); 
 182         outState
.putParcelable(KEY_FILE
, mFile
); 
 183         outState
.putBoolean(KEY_ACCOUNT_SELECTED
, mAccountSelected
); 
 184         outState
.putInt(KEY_NUM_CACHE_FILE
, mNumCacheFile
); 
 185         outState
.putStringArrayList(KEY_REMOTE_CACHE_DATA
, mRemoteCacheData
); 
 187         Log_OC
.d(TAG
, "onSaveInstanceState() end"); 
 191     protected Dialog 
onCreateDialog(final int id
) { 
 192         final AlertDialog
.Builder builder 
= new Builder(this); 
 195             ProgressDialog pDialog 
= new ProgressDialog(this); 
 196             pDialog
.setIndeterminate(false
); 
 197             pDialog
.setCancelable(false
); 
 198             pDialog
.setMessage(getResources().getString(R
.string
.uploader_info_uploading
)); 
 200         case DIALOG_NO_ACCOUNT
: 
 201             builder
.setIcon(android
.R
.drawable
.ic_dialog_alert
); 
 202             builder
.setTitle(R
.string
.uploader_wrn_no_account_title
); 
 203             builder
.setMessage(String
.format( 
 204                     getString(R
.string
.uploader_wrn_no_account_text
), getString(R
.string
.app_name
))); 
 205             builder
.setCancelable(false
); 
 206             builder
.setPositiveButton(R
.string
.uploader_wrn_no_account_setup_btn_text
, new OnClickListener() { 
 208                 public void onClick(DialogInterface dialog
, int which
) { 
 209                     if (android
.os
.Build
.VERSION
.SDK_INT 
> android
.os
.Build
.VERSION_CODES
.ECLAIR_MR1
) { 
 210                         // using string value since in API7 this 
 211                         // constatn is not defined 
 212                         // in API7 < this constatant is defined in 
 213                         // Settings.ADD_ACCOUNT_SETTINGS 
 214                         // and Settings.EXTRA_AUTHORITIES 
 215                         Intent intent 
= new Intent(android
.provider
.Settings
.ACTION_ADD_ACCOUNT
); 
 216                         intent
.putExtra("authorities", new String
[] { MainApp
.getAuthTokenType() }); 
 217                         startActivityForResult(intent
, REQUEST_CODE_SETUP_ACCOUNT
); 
 219                         // since in API7 there is no direct call for 
 220                         // account setup, so we need to 
 221                         // show our own AccountSetupAcricity, get 
 222                         // desired results and setup 
 223                         // everything for ourself 
 224                         Intent intent 
= new Intent(getBaseContext(), AccountAuthenticator
.class); 
 225                         startActivityForResult(intent
, REQUEST_CODE_SETUP_ACCOUNT
); 
 229             builder
.setNegativeButton(R
.string
.uploader_wrn_no_account_quit_btn_text
, new OnClickListener() { 
 231                 public void onClick(DialogInterface dialog
, int which
) { 
 235             return builder
.create(); 
 236         case DIALOG_MULTIPLE_ACCOUNT
: 
 237             CharSequence ac
[] = new CharSequence
[ 
 238                     mAccountManager
.getAccountsByType(MainApp
.getAccountType()).length
]; 
 239             for (int i 
= 0; i 
< ac
.length
; ++i
) { 
 240                 ac
[i
] = DisplayUtils
.convertIdn( 
 241                         mAccountManager
.getAccountsByType(MainApp
.getAccountType())[i
].name
, false
); 
 243             builder
.setTitle(R
.string
.common_choose_account
); 
 244             builder
.setItems(ac
, new OnClickListener() { 
 246                 public void onClick(DialogInterface dialog
, int which
) { 
 247                     setAccount(mAccountManager
.getAccountsByType(MainApp
.getAccountType())[which
]); 
 248                     onAccountSet(mAccountWasRestored
); 
 250                     mAccountSelected 
= true
; 
 253             builder
.setCancelable(true
); 
 254             builder
.setOnCancelListener(new OnCancelListener() { 
 256                 public void onCancel(DialogInterface dialog
) { 
 261             return builder
.create(); 
 262         case DIALOG_NO_STREAM
: 
 263             builder
.setIcon(android
.R
.drawable
.ic_dialog_alert
); 
 264             builder
.setTitle(R
.string
.uploader_wrn_no_content_title
); 
 265             builder
.setMessage(R
.string
.uploader_wrn_no_content_text
); 
 266             builder
.setCancelable(false
); 
 267             builder
.setNegativeButton(R
.string
.common_cancel
, new OnClickListener() { 
 269                 public void onClick(DialogInterface dialog
, int which
) { 
 273             return builder
.create(); 
 275             throw new IllegalArgumentException("Unknown dialog id: " + id
); 
 279     class a 
implements OnClickListener 
{ 
 283         public a(String path
, EditText dirname
) { 
 289         public void onClick(DialogInterface dialog
, int which
) { 
 290             Uploader
.this.mUploadPath 
= mPath 
+ mDirname
.getText().toString(); 
 291             Uploader
.this.mCreateDir 
= true
; 
 297     public void onBackPressed() { 
 299         if (mParents
.size() <= 1) { 
 300             super.onBackPressed(); 
 304             populateDirectoryList(); 
 309     public void onItemClick(AdapterView
<?
> parent
, View view
, int position
, long id
) { 
 310         // click on folder in the list 
 311         Log_OC
.d(TAG
, "on item click"); 
 312         Vector
<OCFile
> tmpfiles 
= getStorageManager().getFolderContent(mFile
); 
 313         if (tmpfiles
.size() <= 0) return; 
 315         Vector
<OCFile
> files 
= new Vector
<OCFile
>(); 
 316         for (OCFile f 
: tmpfiles
) 
 319         if (files
.size() < position
) { 
 320             throw new IndexOutOfBoundsException("Incorrect item selected"); 
 322         mParents
.push(files
.get(position
).getFileName()); 
 323         populateDirectoryList(); 
 327     public void onClick(View v
) { 
 330         case R
.id
.uploader_choose_folder
: 
 331             mUploadPath 
= "";   // first element in mParents is root dir, represented by ""; 
 332                                 // init mUploadPath with "/" results in a "//" prefix 
 333             for (String p 
: mParents
) 
 334                 mUploadPath 
+= p 
+ OCFile
.PATH_SEPARATOR
; 
 335             Log_OC
.d(TAG
, "Uploading file to dir " + mUploadPath
); 
 341         case R
.id
.uploader_new_folder
: 
 342             CreateFolderDialogFragment dialog 
= CreateFolderDialogFragment
.newInstance(mFile
); 
 343             dialog
.show(getSupportFragmentManager(), "createdirdialog"); 
 348             throw new IllegalArgumentException("Wrong element clicked"); 
 353     protected void onActivityResult(int requestCode
, int resultCode
, Intent data
) { 
 354         super.onActivityResult(requestCode
, resultCode
, data
); 
 355         Log_OC
.i(TAG
, "result received. req: " + requestCode 
+ " res: " + resultCode
); 
 356         if (requestCode 
== REQUEST_CODE_SETUP_ACCOUNT
) { 
 357             dismissDialog(DIALOG_NO_ACCOUNT
); 
 358             if (resultCode 
== RESULT_CANCELED
) { 
 361             Account
[] accounts 
= mAccountManager
.getAccountsByType(MainApp
.getAuthTokenType()); 
 362             if (accounts
.length 
== 0) { 
 363                 showDialog(DIALOG_NO_ACCOUNT
); 
 365                 // there is no need for checking for is there more then one 
 366                 // account at this point 
 367                 // since account setup can set only one account at time 
 368                 setAccount(accounts
[0]); 
 369                 populateDirectoryList(); 
 374     private void populateDirectoryList() { 
 375         setContentView(R
.layout
.uploader_layout
); 
 377         ListView mListView 
= (ListView
) findViewById(android
.R
.id
.list
); 
 379         String current_dir 
= mParents
.peek(); 
 380         if(current_dir
.equals("")){ 
 381             getSupportActionBar().setTitle(getString(R
.string
.default_display_name_for_root_folder
)); 
 384             getSupportActionBar().setTitle(current_dir
); 
 386         boolean notRoot 
= (mParents
.size() > 1); 
 387         ActionBar actionBar 
= getSupportActionBar(); 
 388         actionBar
.setDisplayHomeAsUpEnabled(notRoot
); 
 389         actionBar
.setHomeButtonEnabled(notRoot
); 
 391         String full_path 
= generatePath(mParents
); 
 393         Log_OC
.d(TAG
, "Populating view with content of : " + full_path
); 
 395         mFile 
= getStorageManager().getFileByPath(full_path
); 
 397             Vector
<OCFile
> files 
= getStorageManager().getFolderContent(mFile
); 
 398             List
<HashMap
<String
, Object
>> data 
= new LinkedList
<HashMap
<String
,Object
>>(); 
 399             for (OCFile f 
: files
) { 
 400                 HashMap
<String
, Object
> h 
= new HashMap
<String
, Object
>(); 
 402                     h
.put("dirname", f
.getFileName()); 
 406             SimpleAdapter sa 
= new SimpleAdapter(this, 
 408                                                 R
.layout
.uploader_list_item_layout
, 
 409                                                 new String
[] {"dirname"}, 
 410                                                 new int[] {R
.id
.textView1
}); 
 412             mListView
.setAdapter(sa
); 
 413             Button btnChooseFolder 
= (Button
) findViewById(R
.id
.uploader_choose_folder
); 
 414             btnChooseFolder
.setOnClickListener(this); 
 416             Button btnNewFolder 
= (Button
) findViewById(R
.id
.uploader_new_folder
); 
 417             btnNewFolder
.setOnClickListener(this); 
 419             mListView
.setOnItemClickListener(this); 
 423     private String 
generatePath(Stack
<String
> dirs
) { 
 424         String full_path 
= ""; 
 426         for (String a 
: dirs
) 
 427             full_path 
+= a 
+ "/"; 
 431     private void prepareStreamsToUpload() { 
 432         if (getIntent().getAction().equals(Intent
.ACTION_SEND
)) { 
 433             mStreamsToUpload 
= new ArrayList
<Parcelable
>(); 
 434             mStreamsToUpload
.add(getIntent().getParcelableExtra(Intent
.EXTRA_STREAM
)); 
 435         } else if (getIntent().getAction().equals(Intent
.ACTION_SEND_MULTIPLE
)) { 
 436             mStreamsToUpload 
= getIntent().getParcelableArrayListExtra(Intent
.EXTRA_STREAM
); 
 440     private boolean somethingToUpload() { 
 441         return (mStreamsToUpload 
!= null 
&& mStreamsToUpload
.get(0) != null
); 
 444     public void uploadFiles() { 
 447             // ArrayList for files with path in external storage 
 448             ArrayList
<String
> local 
= new ArrayList
<String
>(); 
 449             ArrayList
<String
> remote 
= new ArrayList
<String
>(); 
 451             // this checks the mimeType  
 452             for (Parcelable mStream 
: mStreamsToUpload
) { 
 454                 Uri uri 
= (Uri
) mStream
; 
 456                 String filePath 
= ""; 
 459                     if (uri
.getScheme().equals("content")) { 
 460                         String mimeType 
= getContentResolver().getType(uri
); 
 462                         if (mimeType
.contains("image")) { 
 463                             String
[] CONTENT_PROJECTION 
= { Images
.Media
.DATA
, 
 464                                     Images
.Media
.DISPLAY_NAME
, Images
.Media
.MIME_TYPE
, 
 466                             Cursor c 
= getContentResolver().query(uri
, CONTENT_PROJECTION
, null
, 
 469                             int index 
= c
.getColumnIndex(Images
.Media
.DATA
); 
 470                             data 
= c
.getString(index
); 
 471                             filePath 
= mUploadPath 
+ 
 472                                     c
.getString(c
.getColumnIndex(Images
.Media
.DISPLAY_NAME
)); 
 474                         } else if (mimeType
.contains("video")) { 
 475                             String
[] CONTENT_PROJECTION 
= { Video
.Media
.DATA
, 
 476                                    Video
.Media
.DISPLAY_NAME
, Video
.Media
.MIME_TYPE
, 
 477                                    Video
.Media
.SIZE
, Video
.Media
.DATE_MODIFIED 
}; 
 478                             Cursor c 
= getContentResolver().query(uri
, CONTENT_PROJECTION
, null
, 
 481                             int index 
= c
.getColumnIndex(Video
.Media
.DATA
); 
 482                             data 
= c
.getString(index
); 
 483                             filePath 
= mUploadPath 
+ 
 484                                    c
.getString(c
.getColumnIndex(Video
.Media
.DISPLAY_NAME
)); 
 486                         } else if (mimeType
.contains("audio")) { 
 487                             String
[] CONTENT_PROJECTION 
= { Audio
.Media
.DATA
, 
 488                                    Audio
.Media
.DISPLAY_NAME
, Audio
.Media
.MIME_TYPE
, 
 490                             Cursor c 
= getContentResolver().query(uri
, CONTENT_PROJECTION
, null
, 
 493                             int index 
= c
.getColumnIndex(Audio
.Media
.DATA
); 
 494                             data 
= c
.getString(index
); 
 495                             filePath 
= mUploadPath 
+ 
 496                                    c
.getString(c
.getColumnIndex(Audio
.Media
.DISPLAY_NAME
)); 
 499                             Cursor cursor 
= getContentResolver().query(uri
, 
 500                                    new String
[]{MediaStore
.MediaColumns
.DISPLAY_NAME
}, 
 502                             cursor
.moveToFirst(); 
 503                             int nameIndex 
= cursor
.getColumnIndex(cursor
.getColumnNames()[0]); 
 504                             if (nameIndex 
>= 0) { 
 505                                filePath 
= mUploadPath 
+ cursor
.getString(nameIndex
); 
 509                     } else if (uri
.getScheme().equals("file")) { 
 510                         filePath 
= Uri
.decode(uri
.toString()).replace(uri
.getScheme() + 
 512                         if (filePath
.contains("mnt")) { 
 513                            String splitedFilePath
[] = filePath
.split("/mnt"); 
 514                            filePath 
= splitedFilePath
[1]; 
 516                         final File file 
= new File(filePath
); 
 517                         data 
= file
.getAbsolutePath(); 
 518                         filePath 
= mUploadPath 
+ file
.getName(); 
 521                         throw new SecurityException(); 
 524                         mRemoteCacheData
.add(filePath
); 
 525                         CopyTmpFileAsyncTask copyTask 
= new CopyTmpFileAsyncTask(this); 
 526                         Object
[] params 
= { uri
, filePath
, mRemoteCacheData
.size()-1 }; 
 528                         showWaitingCopyDialog(); 
 529                         copyTask
.execute(params
); 
 531                         remote
.add(filePath
); 
 536                     throw new SecurityException(); 
 539                 Intent intent 
= new Intent(getApplicationContext(), FileUploader
.class); 
 540                 intent
.putExtra(FileUploader
.KEY_UPLOAD_TYPE
, FileUploader
.UPLOAD_MULTIPLE_FILES
); 
 541                 intent
.putExtra(FileUploader
.KEY_LOCAL_FILE
, local
.toArray(new String
[local
.size()])); 
 542                 intent
.putExtra(FileUploader
.KEY_REMOTE_FILE
, 
 543                         remote
.toArray(new String
[remote
.size()])); 
 544                 intent
.putExtra(FileUploader
.KEY_ACCOUNT
, getAccount()); 
 545                 startService(intent
); 
 547                 //Save the path to shared preferences 
 548                 SharedPreferences
.Editor appPrefs 
= PreferenceManager
 
 549                         .getDefaultSharedPreferences(getApplicationContext()).edit(); 
 550                 appPrefs
.putString("last_upload_path", mUploadPath
); 
 556         } catch (SecurityException e
) { 
 557             String message 
= String
.format(getString(R
.string
.uploader_error_forbidden_content
), 
 558                     getString(R
.string
.app_name
)); 
 559             Toast
.makeText(this, message
, Toast
.LENGTH_LONG
).show();             
 564     public void onRemoteOperationFinish(RemoteOperation operation
, RemoteOperationResult result
) { 
 565         super.onRemoteOperationFinish(operation
, result
); 
 568         if (operation 
instanceof CreateFolderOperation
) { 
 569             onCreateFolderOperationFinish((CreateFolderOperation
)operation
, result
); 
 575      * Updates the view associated to the activity after the finish of an operation 
 576      * trying create a new folder 
 578      * @param operation     Creation operation performed. 
 579      * @param result        Result of the creation. 
 581     private void onCreateFolderOperationFinish(CreateFolderOperation operation
, 
 582                                                RemoteOperationResult result
) { 
 583         if (result
.isSuccess()) { 
 584             dismissLoadingDialog(); 
 585             populateDirectoryList(); 
 587             dismissLoadingDialog(); 
 589                 Toast msg 
= Toast
.makeText(this,  
 590                         ErrorMessageAdapter
.getErrorCauseMessage(result
, operation
, getResources()),  
 594             } catch (NotFoundException e
) { 
 595                 Log_OC
.e(TAG
, "Error while trying to show fail message " , e
); 
 602      *  Loads the target folder initialize shown to the user. 
 604      *  The target account has to be chosen before this method is called.  
 606     private void initTargetFolder() { 
 607         if (getStorageManager() == null
) { 
 608             throw new IllegalStateException("Do not call this method before " + 
 609                     "initializing mStorageManager"); 
 612         SharedPreferences appPreferences 
= PreferenceManager
 
 613                 .getDefaultSharedPreferences(getApplicationContext()); 
 615         String last_path 
= appPreferences
.getString("last_upload_path", ""); 
 616         // "/" equals root-directory 
 617         if(last_path
.equals("/")) { 
 620             String
[] dir_names 
= last_path
.split("/"); 
 621             for (String dir 
: dir_names
) 
 624         //Make sure that path still exists, if it doesn't pop the stack and try the previous path 
 625         while(!getStorageManager().fileExists(generatePath(mParents
)) && mParents
.size() > 1){ 
 632     public boolean onOptionsItemSelected(MenuItem item
) { 
 633         boolean retval 
= true
; 
 634         switch (item
.getItemId()) { 
 635             case android
.R
.id
.home
: 
 636                 if((mParents
.size() > 1)) { 
 642                 retval 
= super.onOptionsItemSelected(item
); 
 649      * Process the result of CopyTmpFileAsyncTask 
 654     public void OnCopyTmpFileTaskListener(String result
, int index
) { 
 655         if (mNumCacheFile 
-- == 0) { 
 656             dismissWaitingCopyDialog(); 
 658         if (result 
!= null
) { 
 659             Intent intent 
= new Intent(getApplicationContext(), FileUploader
.class); 
 660             intent
.putExtra(FileUploader
.KEY_UPLOAD_TYPE
, FileUploader
.UPLOAD_SINGLE_FILE
); 
 661             intent
.putExtra(FileUploader
.KEY_LOCAL_FILE
, result
); 
 662             intent
.putExtra(FileUploader
.KEY_REMOTE_FILE
, mRemoteCacheData
.get(index
)); 
 663             intent
.putExtra(FileUploader
.KEY_ACCOUNT
, getAccount()); 
 664             startService(intent
); 
 667             String message 
= String
.format(getString(R
.string
.uploader_error_forbidden_content
), 
 668                     getString(R
.string
.app_name
)); 
 669             Toast
.makeText(this, message
, Toast
.LENGTH_LONG
).show(); 
 670             Log_OC
.d(TAG
, message 
); 
 675      * Show waiting for copy dialog 
 677     public void showWaitingCopyDialog() { 
 679         LoadingDialog loading 
= new LoadingDialog( 
 680                 getResources().getString(R
.string
.wait_for_tmp_copy_from_private_storage
)); 
 681         FragmentManager fm 
= getSupportFragmentManager(); 
 682         FragmentTransaction ft 
= fm
.beginTransaction(); 
 683         loading
.show(ft
, DIALOG_WAIT_COPY_FILE
); 
 689      * Dismiss waiting for copy dialog 
 691     public void dismissWaitingCopyDialog(){ 
 692         Fragment frag 
= getSupportFragmentManager().findFragmentByTag(DIALOG_WAIT_COPY_FILE
); 
 694             LoadingDialog loading 
= (LoadingDialog
) frag
;