/**
  * Opens a stream to the given URI.
  *
  * @return Never returns null.
  * @throws Throws an InvalidArgumentException for relative URIs. Relative URIs should be resolved
  *     before being passed into this function.
  * @throws Throws an IOException if the URI cannot be opened.
  */
 public OutputStream openOutputStream(Uri uri, boolean append) throws IOException {
   assertBackgroundThread();
   switch (getUriType(uri)) {
     case URI_TYPE_FILE:
       {
         File localFile = new File(uri.getPath());
         File parent = localFile.getParentFile();
         if (parent != null) {
           parent.mkdirs();
         }
         return new FileOutputStream(localFile, append);
       }
     case URI_TYPE_CONTENT:
     case URI_TYPE_RESOURCE:
       {
         AssetFileDescriptor assetFd =
             contentResolver.openAssetFileDescriptor(uri, append ? "wa" : "w");
         return assetFd.createOutputStream();
       }
   }
   throw new FileNotFoundException("URI not supported by CordovaResourceApi: " + uri);
 }
    @Override
    protected Integer doInBackground(Void... params) {

      byte[] buffer = new byte[4096];
      int bytesRead;
      AssetFileDescriptor fdout = null;
      InputStream is = null;
      OutputStream os = null;

      try {

        // Delete the current picture

        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();

        ops.add(
            ContentProviderOperation.newUpdate(
                    Data.CONTENT_URI
                        .buildUpon()
                        .appendQueryParameter(RawContacts.ACCOUNT_NAME, account)
                        .appendQueryParameter(RawContacts.ACCOUNT_TYPE, ACCOUNT_TYPE)
                        .build())
                .withSelection(GroupMembership.RAW_CONTACT_ID + " = " + pickedRawContact, null)
                .withValue(Photo.PHOTO, null)
                .build());

        try {
          getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
        } catch (RemoteException e1) {
        } catch (OperationApplicationException e1) {
        }

        // Store the image using android API as to update its database

        is = new FileInputStream(cropTemp);

        Uri rawContactPhotoUri =
            Uri.withAppendedPath(
                ContentUris.withAppendedId(RawContacts.CONTENT_URI, pickedRawContact),
                RawContacts.DisplayPhoto.CONTENT_DIRECTORY);
        fdout = getContentResolver().openAssetFileDescriptor(rawContactPhotoUri, "w");
        os = fdout.createOutputStream();

        bytesRead = is.read(buffer);
        while (bytesRead >= 0) {
          os.write(buffer, 0, bytesRead);
          bytesRead = is.read(buffer);
          if (isCancelled()) return RESULT_CANCELLED;
        }

        os.close();
        fdout.close();
        is.close();

        // Wait until its file ID is available

        int fileId = -1;
        Uri contactsUri =
            ContactsContract.Data.CONTENT_URI
                .buildUpon()
                .appendQueryParameter(RawContacts.ACCOUNT_NAME, account)
                .appendQueryParameter(RawContacts.ACCOUNT_TYPE, ACCOUNT_TYPE)
                .build();

        int retryTime = 0;
        for (; retryTime < WAIT_TIME_DB; retryTime += WAIT_TIME_INT) {

          Cursor cursor =
              getContentResolver()
                  .query(
                      contactsUri,
                      new String[] {Photo.PHOTO_FILE_ID, GroupMembership.RAW_CONTACT_ID},
                      GroupMembership.RAW_CONTACT_ID + " = ?",
                      new String[] {pickedRawContact + ""},
                      null);

          try {
            if (cursor.moveToFirst()) {

              int colIndex = cursor.getColumnIndex(Photo.PHOTO_FILE_ID);
              if (!cursor.isNull(colIndex)) {
                fileId = cursor.getInt(colIndex);
                break;
              }
            }
          } finally {
            cursor.close();
          }

          if (isCancelled()) return RESULT_CANCELLED;
        }

        if (fileId < 0) {
          Log.e(TAG, "File ID didn't show up in db after saving");
          return RESULT_IO_ERROR;
        }

        // Wait until the actual file is available

        boolean fileAvailable = false;
        for (; retryTime < WAIT_TIME_DB; retryTime += WAIT_TIME_INT) {
          try {
            fdout = getContentResolver().openAssetFileDescriptor(rawContactPhotoUri, "r");
            is = fdout.createInputStream();
            is.close();
            fdout.close();
            fileAvailable = true;
            break;
          } catch (FileNotFoundException e) {
          } finally {
            try {
              is.close();
            } catch (IOException e) {
            }
            try {
              fdout.close();
            } catch (IOException e) {
            }
          }

          if (isCancelled()) return RESULT_CANCELLED;
        }

        if (!fileAvailable) return RESULT_IO_ERROR;

        // Atomically replace the image file

        if (!rootReplaceImage(cropTemp.getAbsolutePath(), fileId)) return RESULT_NO_ROOT;

        return RESULT_SUCCESS;

      } catch (InterruptedException e) {
        return RESULT_IO_ERROR;
      } catch (IOException e) {
        e.printStackTrace();
        return RESULT_IO_ERROR;
      } finally {
        try {
          if (is != null) is.close();
        } catch (IOException e) {
        }
        try {
          if (os != null) os.close();
        } catch (IOException e) {
        }
        try {
          if (fdout != null) fdout.close();
        } catch (IOException e) {
        }
      }
    }