1 /* ownCloud Android client application 
   2  *   Copyright (C) 2012-2013 ownCloud Inc. 
   4  *   This program is free software: you can redistribute it and/or modify 
   5  *   it under the terms of the GNU General Public License version 2, 
   6  *   as published by the Free Software Foundation. 
   8  *   This program is distributed in the hope that it will be useful, 
   9  *   but WITHOUT ANY WARRANTY; without even the implied warranty of 
  10  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  11  *   GNU General Public License for more details. 
  13  *   You should have received a copy of the GNU General Public License 
  14  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. 
  18 package com
.owncloud
.android
.ui
.activity
; 
  21 import java
.util
.ArrayList
; 
  23 import android
.accounts
.Account
; 
  24 import android
.content
.Context
; 
  25 import android
.content
.Intent
; 
  26 import android
.os
.AsyncTask
; 
  27 import android
.os
.Bundle
; 
  28 import android
.os
.Handler
; 
  29 import android
.support
.v4
.app
.DialogFragment
; 
  30 import android
.text
.method
.ScrollingMovementMethod
; 
  31 import android
.view
.LayoutInflater
; 
  32 import android
.view
.View
; 
  33 import android
.view
.View
.OnClickListener
; 
  34 import android
.view
.ViewGroup
; 
  35 import android
.widget
.ArrayAdapter
; 
  36 import android
.widget
.Button
; 
  37 import android
.widget
.ListView
; 
  38 import android
.widget
.TextView
; 
  39 import android
.widget
.Toast
; 
  41 import com
.actionbarsherlock
.app
.SherlockFragmentActivity
; 
  42 import com
.owncloud
.android
.R
; 
  43 import com
.owncloud
.android
.datamodel
.FileDataStorageManager
; 
  44 import com
.owncloud
.android
.datamodel
.OCFile
; 
  46 import com
.owncloud
.android
.ui
.dialog
.IndeterminateProgressDialog
; 
  47 import com
.owncloud
.android
.utils
.FileStorageUtils
; 
  48 import com
.owncloud
.android
.utils
.Log_OC
; 
  53  * Activity reporting errors occurred when local files uploaded to an ownCloud account with an app in 
  54  * version under 1.3.16 where being copied to the ownCloud local folder. 
  56  * Allows the user move the files to the ownCloud local folder. let them unlinked to the remote 
  59  * Shown when the error notification summarizing the list of errors is clicked by the user. 
  61  * @author David A. Velasco 
  63 public class ErrorsWhileCopyingHandlerActivity  
extends SherlockFragmentActivity 
implements OnClickListener 
{ 
  65     private static final String TAG 
= ErrorsWhileCopyingHandlerActivity
.class.getSimpleName(); 
  67     public static final String EXTRA_ACCOUNT 
= ErrorsWhileCopyingHandlerActivity
.class.getCanonicalName() + ".EXTRA_ACCOUNT"; 
  68     public static final String EXTRA_LOCAL_PATHS 
= ErrorsWhileCopyingHandlerActivity
.class.getCanonicalName() + ".EXTRA_LOCAL_PATHS"; 
  69     public static final String EXTRA_REMOTE_PATHS 
= ErrorsWhileCopyingHandlerActivity
.class.getCanonicalName() + ".EXTRA_REMOTE_PATHS"; 
  71     private static final String WAIT_DIALOG_TAG 
= "WAIT_DIALOG"; 
  73     protected Account mAccount
; 
  74     protected FileDataStorageManager mStorageManager
; 
  75     protected ArrayList
<String
> mLocalPaths
; 
  76     protected ArrayList
<String
> mRemotePaths
; 
  77     protected ArrayAdapter
<String
> mAdapter
; 
  78     protected Handler mHandler
; 
  79     private DialogFragment mCurrentDialog
; 
  85     protected void onCreate(Bundle savedInstanceState
) { 
  86         super.onCreate(savedInstanceState
); 
  88         /// read extra parameters in intent 
  89         Intent intent 
= getIntent(); 
  90         mAccount 
= intent
.getParcelableExtra(EXTRA_ACCOUNT
); 
  91         mRemotePaths 
= intent
.getStringArrayListExtra(EXTRA_REMOTE_PATHS
); 
  92         mLocalPaths 
= intent
.getStringArrayListExtra(EXTRA_LOCAL_PATHS
); 
  93         mStorageManager 
= new FileDataStorageManager(mAccount
, getContentResolver()); 
  94         mHandler 
= new Handler(); 
  95         if (mCurrentDialog 
!= null
) { 
  96             mCurrentDialog
.dismiss(); 
  97             mCurrentDialog 
= null
; 
 100         /// load generic layout 
 101         setContentView(R
.layout
.generic_explanation
); 
 103         /// customize text message 
 104         TextView textView 
= (TextView
) findViewById(R
.id
.message
); 
 105         String appName 
= getString(R
.string
.app_name
); 
 106         String message 
= String
.format(getString(R
.string
.sync_foreign_files_forgotten_explanation
), appName
, appName
, appName
, appName
, mAccount
.name
); 
 107         textView
.setText(message
); 
 108         textView
.setMovementMethod(new ScrollingMovementMethod()); 
 110         /// load the list of local and remote files that failed 
 111         ListView listView 
= (ListView
) findViewById(R
.id
.list
); 
 112         if (mLocalPaths 
!= null 
&& mLocalPaths
.size() > 0) { 
 113             mAdapter 
= new ErrorsWhileCopyingListAdapter(); 
 114             listView
.setAdapter(mAdapter
); 
 116             listView
.setVisibility(View
.GONE
); 
 120         /// customize buttons 
 121         Button cancelBtn 
= (Button
) findViewById(R
.id
.cancel
); 
 122         Button okBtn 
= (Button
) findViewById(R
.id
.ok
); 
 124         okBtn
.setText(R
.string
.foreign_files_move
); 
 125         cancelBtn
.setOnClickListener(this); 
 126         okBtn
.setOnClickListener(this); 
 131      * Customized adapter, showing the local files as main text in two-lines list item and the remote files 
 132      * as the secondary text.  
 134      * @author David A. Velasco 
 136     public class ErrorsWhileCopyingListAdapter 
extends ArrayAdapter
<String
> { 
 138         ErrorsWhileCopyingListAdapter() { 
 139             super(ErrorsWhileCopyingHandlerActivity
.this, android
.R
.layout
.two_line_list_item
, android
.R
.id
.text1
, mLocalPaths
); 
 143         public boolean isEnabled(int position
) { 
 151         public View 
getView (int position
, View convertView
, ViewGroup parent
) { 
 152             View view 
= convertView
; 
 154                 LayoutInflater vi 
= (LayoutInflater
) getSystemService(Context
.LAYOUT_INFLATER_SERVICE
); 
 155                 view 
= vi
.inflate(android
.R
.layout
.two_line_list_item
, null
); 
 158                 String localPath 
= getItem(position
); 
 159                 if (localPath 
!= null
) { 
 160                     TextView text1 
= (TextView
) view
.findViewById(android
.R
.id
.text1
); 
 162                         text1
.setText(String
.format(getString(R
.string
.foreign_files_local_text
), localPath
)); 
 165                 if (mRemotePaths 
!= null 
&& mRemotePaths
.size() > 0 && position 
>= 0 && position 
< mRemotePaths
.size()) { 
 166                     TextView text2 
= (TextView
) view
.findViewById(android
.R
.id
.text2
); 
 167                     String remotePath 
= mRemotePaths
.get(position
); 
 168                     if (text2 
!= null 
&& remotePath 
!= null
) { 
 169                         text2
.setText(String
.format(getString(R
.string
.foreign_files_remote_text
), remotePath
)); 
 179      * Listener method to perform the MOVE / CANCEL action available in this activity. 
 181      * @param v     Clicked view (button MOVE or CANCEL) 
 184     public void onClick(View v
) { 
 185         if (v
.getId() == R
.id
.ok
) { 
 186             /// perform movement operation in background thread 
 187             Log_OC
.d(TAG
, "Clicked MOVE, start movement"); 
 188             new MoveFilesTask().execute();             
 190         } else if (v
.getId() == R
.id
.cancel
) { 
 192             Log_OC
.d(TAG
, "Clicked CANCEL, bye"); 
 196             Log_OC
.e(TAG
, "Clicked phantom button, id: " + v
.getId()); 
 202      * Asynchronous task performing the move of all the local files to the ownCloud folder. 
 204      * @author David A. Velasco 
 206     private class MoveFilesTask 
extends AsyncTask
<Void
, Void
, Boolean
> { 
 209          * Updates the UI before trying the movement 
 212         protected void onPreExecute () { 
 213             /// progress dialog and disable 'Move' button 
 214             mCurrentDialog 
= IndeterminateProgressDialog
.newInstance(R
.string
.wait_a_moment
, false
); 
 215             mCurrentDialog
.show(getSupportFragmentManager(), WAIT_DIALOG_TAG
); 
 216             findViewById(R
.id
.ok
).setEnabled(false
); 
 221          * Performs the movement 
 223          * @return     'False' when the movement of any file fails. 
 226         protected Boolean 
doInBackground(Void
... params
) { 
 227             while (!mLocalPaths
.isEmpty()) { 
 228                 String currentPath 
= mLocalPaths
.get(0); 
 229                 File currentFile 
= new File(currentPath
); 
 230                 String expectedPath 
= FileStorageUtils
.getSavePath(mAccount
.name
) + mRemotePaths
.get(0); 
 231                 File expectedFile 
= new File(expectedPath
); 
 233                 if (expectedFile
.equals(currentFile
) || currentFile
.renameTo(expectedFile
)) { 
 235                     OCFile file 
= mStorageManager
.getFileByPath(mRemotePaths
.get(0)); 
 236                     file
.setStoragePath(expectedPath
); 
 237                     mStorageManager
.saveFile(file
); 
 238                     mRemotePaths
.remove(0); 
 239                     mLocalPaths
.remove(0); 
 250          * Updates the activity UI after the movement of local files is tried. 
 252          * If the movement was successful for all the files, finishes the activity immediately. 
 254          * In other case, the list of remaining files is still available to retry the movement. 
 256          * @param result      'True' when the movement was successful. 
 259         protected void onPostExecute(Boolean result
) { 
 260             mAdapter
.notifyDataSetChanged(); 
 261             mCurrentDialog
.dismiss(); 
 262             mCurrentDialog 
= null
; 
 263             findViewById(R
.id
.ok
).setEnabled(true
); 
 266                 // nothing else to do in this activity 
 267                 Toast t 
= Toast
.makeText(ErrorsWhileCopyingHandlerActivity
.this, getString(R
.string
.foreign_files_success
), Toast
.LENGTH_LONG
); 
 272                 Toast t 
= Toast
.makeText(ErrorsWhileCopyingHandlerActivity
.this, getString(R
.string
.foreign_files_fail
), Toast
.LENGTH_LONG
);