2  *   ownCloud Android client application 
   4  *   @author David A. Velasco 
   5  *   Copyright (C) 2015 ownCloud Inc. 
   7  *   This program is free software: you can redistribute it and/or modify 
   8  *   it under the terms of the GNU General Public License version 2, 
   9  *   as published by the Free Software Foundation. 
  11  *   This program is distributed in the hope that it will be useful, 
  12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of 
  13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  14  *   GNU General Public License for more details. 
  16  *   You should have received a copy of the GNU General Public License 
  17  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. 
  21 package com
.owncloud
.android
.ui
.activity
; 
  24 import java
.util
.ArrayList
; 
  26 import android
.accounts
.Account
; 
  27 import android
.content
.Context
; 
  28 import android
.content
.Intent
; 
  29 import android
.os
.AsyncTask
; 
  30 import android
.os
.Bundle
; 
  31 import android
.os
.Handler
; 
  32 import android
.support
.v4
.app
.DialogFragment
; 
  33 import android
.support
.v7
.app
.AppCompatActivity
; 
  34 import android
.text
.method
.ScrollingMovementMethod
; 
  35 import android
.view
.LayoutInflater
; 
  36 import android
.view
.View
; 
  37 import android
.view
.View
.OnClickListener
; 
  38 import android
.view
.ViewGroup
; 
  39 import android
.widget
.ArrayAdapter
; 
  40 import android
.widget
.Button
; 
  41 import android
.widget
.ListView
; 
  42 import android
.widget
.TextView
; 
  43 import android
.widget
.Toast
; 
  45 import com
.owncloud
.android
.R
; 
  46 import com
.owncloud
.android
.datamodel
.FileDataStorageManager
; 
  47 import com
.owncloud
.android
.datamodel
.OCFile
; 
  48 import com
.owncloud
.android
.lib
.common
.utils
.Log_OC
; 
  50 import com
.owncloud
.android
.ui
.dialog
.IndeterminateProgressDialog
; 
  51 import com
.owncloud
.android
.utils
.FileStorageUtils
; 
  56  * Activity reporting errors occurred when local files uploaded to an ownCloud account with an app 
  57  * in version under 1.3.16 where being copied to the ownCloud local folder. 
  59  * Allows the user move the files to the ownCloud local folder. let them unlinked to the remote 
  62  * Shown when the error notification summarizing the list of errors is clicked by the user. 
  64 public class ErrorsWhileCopyingHandlerActivity  
extends AppCompatActivity
 
  65         implements OnClickListener 
{ 
  67     private static final String TAG 
= ErrorsWhileCopyingHandlerActivity
.class.getSimpleName(); 
  69     public static final String EXTRA_ACCOUNT 
= 
  70             ErrorsWhileCopyingHandlerActivity
.class.getCanonicalName() + ".EXTRA_ACCOUNT"; 
  71     public static final String EXTRA_LOCAL_PATHS 
= 
  72             ErrorsWhileCopyingHandlerActivity
.class.getCanonicalName() + ".EXTRA_LOCAL_PATHS"; 
  73     public static final String EXTRA_REMOTE_PATHS 
= 
  74             ErrorsWhileCopyingHandlerActivity
.class.getCanonicalName() + ".EXTRA_REMOTE_PATHS"; 
  76     private static final String WAIT_DIALOG_TAG 
= "WAIT_DIALOG"; 
  78     protected Account mAccount
; 
  79     protected FileDataStorageManager mStorageManager
; 
  80     protected ArrayList
<String
> mLocalPaths
; 
  81     protected ArrayList
<String
> mRemotePaths
; 
  82     protected ArrayAdapter
<String
> mAdapter
; 
  83     protected Handler mHandler
; 
  84     private DialogFragment mCurrentDialog
; 
  90     protected void onCreate(Bundle savedInstanceState
) { 
  91         super.onCreate(savedInstanceState
); 
  93         /// read extra parameters in intent 
  94         Intent intent 
= getIntent(); 
  95         mAccount 
= intent
.getParcelableExtra(EXTRA_ACCOUNT
); 
  96         mRemotePaths 
= intent
.getStringArrayListExtra(EXTRA_REMOTE_PATHS
); 
  97         mLocalPaths 
= intent
.getStringArrayListExtra(EXTRA_LOCAL_PATHS
); 
  98         mStorageManager 
= new FileDataStorageManager(mAccount
, getContentResolver()); 
  99         mHandler 
= new Handler(); 
 100         if (mCurrentDialog 
!= null
) { 
 101             mCurrentDialog
.dismiss(); 
 102             mCurrentDialog 
= null
; 
 105         /// load generic layout 
 106         setContentView(R
.layout
.generic_explanation
); 
 108         /// customize text message 
 109         TextView textView 
= (TextView
) findViewById(R
.id
.message
); 
 110         String appName 
= getString(R
.string
.app_name
); 
 111         String message 
= String
.format(getString(R
.string
.sync_foreign_files_forgotten_explanation
), 
 112                 appName
, appName
, appName
, appName
, mAccount
.name
); 
 113         textView
.setText(message
); 
 114         textView
.setMovementMethod(new ScrollingMovementMethod()); 
 116         /// load the list of local and remote files that failed 
 117         ListView listView 
= (ListView
) findViewById(R
.id
.list
); 
 118         if (mLocalPaths 
!= null 
&& mLocalPaths
.size() > 0) { 
 119             mAdapter 
= new ErrorsWhileCopyingListAdapter(); 
 120             listView
.setAdapter(mAdapter
); 
 122             listView
.setVisibility(View
.GONE
); 
 126         /// customize buttons 
 127         Button cancelBtn 
= (Button
) findViewById(R
.id
.cancel
); 
 128         Button okBtn 
= (Button
) findViewById(R
.id
.ok
); 
 130         okBtn
.setText(R
.string
.foreign_files_move
); 
 131         cancelBtn
.setOnClickListener(this); 
 132         okBtn
.setOnClickListener(this); 
 137      * Customized adapter, showing the local files as main text in two-lines list item and the 
 138      * remote files as the secondary text. 
 140     public class ErrorsWhileCopyingListAdapter 
extends ArrayAdapter
<String
> { 
 142         ErrorsWhileCopyingListAdapter() { 
 143             super(ErrorsWhileCopyingHandlerActivity
.this, android
.R
.layout
.two_line_list_item
, 
 144                     android
.R
.id
.text1
, mLocalPaths
); 
 148         public boolean isEnabled(int position
) { 
 156         public View 
getView (int position
, View convertView
, ViewGroup parent
) { 
 157             View view 
= convertView
; 
 159                 LayoutInflater vi 
= (LayoutInflater
) getSystemService( 
 160                         Context
.LAYOUT_INFLATER_SERVICE
); 
 161                 view 
= vi
.inflate(android
.R
.layout
.two_line_list_item
, null
); 
 164                 String localPath 
= getItem(position
); 
 165                 if (localPath 
!= null
) { 
 166                     TextView text1 
= (TextView
) view
.findViewById(android
.R
.id
.text1
); 
 168                         text1
.setText(String
.format(getString(R
.string
.foreign_files_local_text
), localPath
)); 
 171                 if (mRemotePaths 
!= null 
&& mRemotePaths
.size() > 0 && position 
>= 0 && 
 172                         position 
< mRemotePaths
.size()) { 
 173                     TextView text2 
= (TextView
) view
.findViewById(android
.R
.id
.text2
); 
 174                     String remotePath 
= mRemotePaths
.get(position
); 
 175                     if (text2 
!= null 
&& remotePath 
!= null
) { 
 176                         text2
.setText(String
.format(getString(R
.string
.foreign_files_remote_text
), remotePath
)); 
 186      * Listener method to perform the MOVE / CANCEL action available in this activity. 
 188      * @param v     Clicked view (button MOVE or CANCEL) 
 191     public void onClick(View v
) { 
 192         if (v
.getId() == R
.id
.ok
) { 
 193             /// perform movement operation in background thread 
 194             Log_OC
.d(TAG
, "Clicked MOVE, start movement"); 
 195             new MoveFilesTask().execute();             
 197         } else if (v
.getId() == R
.id
.cancel
) { 
 199             Log_OC
.d(TAG
, "Clicked CANCEL, bye"); 
 203             Log_OC
.e(TAG
, "Clicked phantom button, id: " + v
.getId()); 
 209      * Asynchronous task performing the move of all the local files to the ownCloud folder. 
 211     private class MoveFilesTask 
extends AsyncTask
<Void
, Void
, Boolean
> { 
 214          * Updates the UI before trying the movement 
 217         protected void onPreExecute () { 
 218             /// progress dialog and disable 'Move' button 
 219             mCurrentDialog 
= IndeterminateProgressDialog
.newInstance(R
.string
.wait_a_moment
, false
); 
 220             mCurrentDialog
.show(getSupportFragmentManager(), WAIT_DIALOG_TAG
); 
 221             findViewById(R
.id
.ok
).setEnabled(false
); 
 226          * Performs the movement 
 228          * @return     'False' when the movement of any file fails. 
 231         protected Boolean 
doInBackground(Void
... params
) { 
 232             while (!mLocalPaths
.isEmpty()) { 
 233                 String currentPath 
= mLocalPaths
.get(0); 
 234                 File currentFile 
= new File(currentPath
); 
 235                 String expectedPath 
= FileStorageUtils
.getSavePath(mAccount
.name
) + mRemotePaths
.get(0); 
 236                 File expectedFile 
= new File(expectedPath
); 
 238                 if (expectedFile
.equals(currentFile
) || currentFile
.renameTo(expectedFile
)) { 
 240                     OCFile file 
= mStorageManager
.getFileByPath(mRemotePaths
.get(0)); 
 241                     file
.setStoragePath(expectedPath
); 
 242                     mStorageManager
.saveFile(file
); 
 243                     mRemotePaths
.remove(0); 
 244                     mLocalPaths
.remove(0); 
 255          * Updates the activity UI after the movement of local files is tried. 
 257          * If the movement was successful for all the files, finishes the activity immediately. 
 259          * In other case, the list of remaining files is still available to retry the movement. 
 261          * @param result      'True' when the movement was successful. 
 264         protected void onPostExecute(Boolean result
) { 
 265             mAdapter
.notifyDataSetChanged(); 
 266             mCurrentDialog
.dismiss(); 
 267             mCurrentDialog 
= null
; 
 268             findViewById(R
.id
.ok
).setEnabled(true
); 
 271                 // nothing else to do in this activity 
 272                 Toast t 
= Toast
.makeText(ErrorsWhileCopyingHandlerActivity
.this, 
 273                         getString(R
.string
.foreign_files_success
), Toast
.LENGTH_LONG
); 
 278                 Toast t 
= Toast
.makeText(ErrorsWhileCopyingHandlerActivity
.this, 
 279                         getString(R
.string
.foreign_files_fail
), Toast
.LENGTH_LONG
);