Q:

Why does the android app freeze while copying files?

I am making a simple file explorer for Android. So, the problem is that when I copy files or folders to any place of file system, the app just freezes until the file/folder is copied. I have to notice that the app doesn't crash, doesn't send errors to the Logcat. The app simply doesn't respond for any actions while files are being copied. 
As I can see, in other file explorers this problem doesn't happen and you can do any actions in the app when files are being copied.
I start copying files in a Fragment. I tried using both own methods of copying files and FileUtils library methods but the result is the same.
Basic things:
import android.support.v7.widget.Toolbar;
...
private Toolbar mToolbar;

onCreateView method:
....
//Start copying files
mToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
        @Override
        public boolean onMenuItemClick(MenuItem menuItem) {
            if(menuItem.getItemId() == R.id.paste_button ){
                if(fileActionMode.equals("copy")){
                    copy();
                }
            }
            if(menuItem.getItemId() == R.id.cancel_button){
                mToolbar.getMenu().removeItem(R.id.paste_button);
                mToolbar.getMenu().removeItem(R.id.cancel_button);
            }
            updateUI();
            return true;
        }
    });
...

Copy method:
 private void copy(){
    mToolbar.getMenu().removeItem(R.id.paste_button);
    mToolbar.getMenu().removeItem(R.id.cancel_button);
    File file = new File(initFilePath);
    if(file.isDirectory()){
        try {
            FileUtils.copyDirectoryToDirectory(file, new File(FileFoldersLab.get(getActivity()).getCurPath()));
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            updateUI();
        }
    }else if(file.isFile()){
        try {
            FileUtils.copyFileToDirectory(file, new File(FileFoldersLab.get(getActivity()).getCurPath()));
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            updateUI();
        }
    }
}

My method that I used instead of FileUtils....:
public void copyFile(File src) throws IOException{
    createFile(src.getName());
    try (InputStream in = new FileInputStream(src)) {
        try (OutputStream out = new FileOutputStream(mCurPath+File.separator+src.getName())) {
            byte[] buf = new byte[1024];
            int len;
            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }
        }
    }
}

A:

The App freezes because the copy() method of yours is a time consuming process.It should also be remembered that, you are performing this time consuming operation on the main thread which is also responsible for maintaining the UI.
Since the UI thread is busy completing your long operation , it avoids refreshing and performing UI operations.As a result the App finally hangs and freezes.
Now there are two ways you can handle this situation,

You can make the User of the App wait until the copy() method of your is completed by showing the spinning loader , just before your copy() method starts and hiding the loader once the method is completed.This loader technique ensures that the User doesn't perform any UI related event(like a button click) until the copy() method is completed.Here is the code for showing loader, sorry the code is in Kotlin.
class DialogUtil private constructor() {

init {
throw AssertionError()
}

companion object {

private var progressDialog: ProgressDialog? = null

fun showAlertDialog(context: Context, message: String?) {
    AlertDialog.Builder(context).setMessage(message)
            .setCancelable(false).setPositiveButton("OK") { 
 dialogInterface, _ -> dialogInterface.dismiss() }.show()
}

fun showProgressDialog(context: Context) {
    progressDialog = ProgressDialog(context)
    progressDialog!!.setProgressStyle(ProgressDialog.STYLE_SPINNER)
    progressDialog!!.requestWindowFeature(Window.FEATURE_NO_TITLE)
    progressDialog!!.setMessage("Please wait...")
    progressDialog!!.setCancelable(false)
    progressDialog!!.isIndeterminate = true
    progressDialog!!.show()
}

fun hideProgressDialog() {
    if (progressDialog != null) {
        progressDialog!!.dismiss()
    }
  }
 }
}

Make a helper class like above for loader and then just above the line where your copy() method starts call this loader like this
    DialogUtil.showProgressDialog(this)

Above this refers to context , so if copy() method is in a fragment you need to pass activity(getActivity() in java) in its place.
Once your copy() method completes , you can hide the spinning loader like this ,
    DialogUtil.hideProgressDialog()

write this line just below your copy() method.

The second way is to start the copy() method in some other thread , so that your UI thread(main thread) need not care about the copy() method and your App is saved from freezing.One advantage of this technique is that even though your copy() method is still in progress , the user can still perform UI related events without experiencing any jitter or lag.I suggest you should use AsyncTask for performing your copy() method since it can perform long tasks in worker thread and then can provide you the opportunity to notify user about task completion on main(UI) thread. The code goes like this,
private class MyTask extends AsyncTask<X, Y, Z>
{

 protected void onPreExecute(){
      //any specific setup before you start copy() method ,  runs on UI 
      // thread
 } 

 protected Z doInBackground(X...x){
     // your copy() method itself, runs on worker thread other than main UI 
     //  thread, don't perform any UI related activities from here , since 
    // it is the worker thread
 }

 protected void onProgressUpdate(Y y){
   //any event you wanna perform , while the task is in progress, runs on 
   //UI main thread
 }

 protected void onPostExecute(Z z){
  //the event you wanna perform once your copy() method is complete, runs 
  //on UI main thread
}
}

After defining the class , you can start this AsyncTask like this,
    MyTask myTask = new MyTask();
    myTask.execute(x);

Wherever I have mentioned UI thread it means , you can perform any task or operation related to UI from there. You should remember that UI events can only be performed from UI thread, if you try to perform UI related operations from thread other than UI thread(main thread) your App can unexpectedly close.
I suggest making this AsyncTask as a inner class , in fragment itself , instead of making a new class entirely.

