gt:             if (inputChannel != null) inputChannel.close();
context: /*
   * Copyright (C) 2007-2008 OpenIntents.org
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package com.yalantis.ucrop.util;
  
  import android.annotation.SuppressLint;
  import android.content.ContentUris;
  import android.content.Context;
  import android.database.Cursor;
  import android.net.Uri;
  import android.os.Build;
  import android.os.Environment;
  import android.provider.DocumentsContract;
  import android.provider.MediaStore;
  import android.support.annotation.NonNull;
  import android.util.Log;
  
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.nio.channels.FileChannel;
  import java.util.Locale;
  
  /**
   * @author Peli
   * @author paulburke (ipaulpro)
   * @version 2013-12-11
   */
  public class FileUtils {
  
      /**
       * TAG for log messages.
       */
      static final String TAG = "FileUtils";
  
      private FileUtils() {
      }
  
      /**
       * @param uri The Uri to check.
       * @return Whether the Uri authority is ExternalStorageProvider.
       * @author paulburke
       */
      public static boolean isExternalStorageDocument(Uri uri) {
          return "com.android.externalstorage.documents".equals(uri.getAuthority());
      }
  
      /**
       * @param uri The Uri to check.
       * @return Whether the Uri authority is DownloadsProvider.
       * @author paulburke
       */
      public static boolean isDownloadsDocument(Uri uri) {
          return "com.android.providers.downloads.documents".equals(uri.getAuthority());
      }
  
      /**
       * @param uri The Uri to check.
       * @return Whether the Uri authority is MediaProvider.
       * @author paulburke
       */
      public static boolean isMediaDocument(Uri uri) {
          return "com.android.providers.media.documents".equals(uri.getAuthority());
      }
  
      /**
       * @param uri The Uri to check.
       * @return Whether the Uri authority is Google Photos.
       */
      public static boolean isGooglePhotosUri(Uri uri) {
          return "com.google.android.apps.photos.content".equals(uri.getAuthority());
      }
  
      /**
       * Get the value of the data column for this Uri. This is useful for
       * MediaStore Uris, and other file-based ContentProviders.
       *
       * @param context       The context.
       * @param uri           The Uri to query.
       * @param selection     (Optional) Filter used in the query.
       * @param selectionArgs (Optional) Selection arguments used in the query.
       * @return The value of the _data column, which is typically a file path.
       * @author paulburke
       */
      public static String getDataColumn(Context context, Uri uri, String selection,
                                         String[] selectionArgs) {
  
          Cursor cursor = null;
          final String column = "_data";
          final String[] projection = {
                  column
          };
  
          try {
              cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                      null);
              if (cursor != null && cursor.moveToFirst()) {
                  final int column_index = cursor.getColumnIndexOrThrow(column);
                  return cursor.getString(column_index);
              }
          } catch (IllegalArgumentException ex) {
              Log.i(TAG, String.format(Locale.getDefault(), "getDataColumn: _data - [%s]", ex.getMessage()));
          } finally {
              if (cursor != null) {
                  cursor.close();
              }
          }
          return null;
      }
  
      /**
       * Get a file path from a Uri. This will get the the path for Storage Access
       * Framework Documents, as well as the _data field for the MediaStore and
       * other file-based ContentProviders.<br>
       * <br>
       * Callers should check whether the path is local before assuming it
       * represents a local file.
       *
       * @param context The context.
       * @param uri     The Uri to query.
       * @author paulburke
       */
      @SuppressLint("NewApi")
      public static String getPath(final Context context, final Uri uri) {
          final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
  
          // DocumentProvider
          if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
              if (isExternalStorageDocument(uri)) {
                  final String docId = DocumentsContract.getDocumentId(uri);
                  final String[] split = docId.split(":");
                  final String type = split[0];
  
                  if ("primary".equalsIgnoreCase(type)) {
                      return Environment.getExternalStorageDirectory() + "/" + split[1];
                  }
  
                  // TODO handle non-primary volumes
              }
              // DownloadsProvider
              else if (isDownloadsDocument(uri)) {
  
                  final String id = DocumentsContract.getDocumentId(uri);
                  final Uri contentUri = ContentUris.withAppendedId(
                          Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
  
                  return getDataColumn(context, contentUri, null, null);
              }
              // MediaProvider
              else if (isMediaDocument(uri)) {
                  final String docId = DocumentsContract.getDocumentId(uri);
                  final String[] split = docId.split(":");
                  final String type = split[0];
  
                  Uri contentUri = null;
                  if ("image".equals(type)) {
                      contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                  } else if ("video".equals(type)) {
                      contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                  } else if ("audio".equals(type)) {
                      contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                  }
  
                  final String selection = "_id=?";
                  final String[] selectionArgs = new String[]{
                          split[1]
                  };
  
                  return getDataColumn(context, contentUri, selection, selectionArgs);
              }
          }
          // MediaStore (and general)
          else if ("content".equalsIgnoreCase(uri.getScheme())) {
  
              // Return the remote address
              if (isGooglePhotosUri(uri)) {
                  return uri.getLastPathSegment();
              }
  
              return getDataColumn(context, uri, null, null);
          }
          // File
          else if ("file".equalsIgnoreCase(uri.getScheme())) {
              return uri.getPath();
          }
  
          return null;
      }
  
      /**
       * Copies one file into the other with the given paths.
       * In the event that the paths are the same, trying to copy one file to the other
       * will cause both files to become null.
       * Simply skipping this step if the paths are identical.
       */
      public static void copyFile(@NonNull String pathFrom, @NonNull String pathTo) throws IOException {
          if (pathFrom.equalsIgnoreCase(pathTo)) {
              return;
          }
  
          FileChannel outputChannel = null;
          FileChannel inputChannel = null;
          try {
              inputChannel = new FileInputStream(new File(pathFrom)).getChannel();
              outputChannel = new FileOutputStream(new File(pathTo)).getChannel();
              inputChannel.transferTo(0, inputChannel.size(), outputChannel);
              inputChannel.close();
          } finally {
  