@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) {
        }
      }
    }
    @Override
    protected List<Contact> doInBackground(String... params) {
      Uri groupsUri =
          ContactsContract.Groups.CONTENT_URI
              .buildUpon()
              .appendQueryParameter(RawContacts.ACCOUNT_NAME, params[0])
              .appendQueryParameter(RawContacts.ACCOUNT_TYPE, ACCOUNT_TYPE)
              .build();

      Cursor cursor = getContentResolver().query(groupsUri, null, null, null, null);
      if (cursor == null) return null;

      int myContactGroupId = -1;

      try {
        for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {

          String sourceId =
              cursor.getString(cursor.getColumnIndex(ContactsContract.Groups.SOURCE_ID));
          if (MY_CONTACTS_GROUP.equals(sourceId)) {
            myContactGroupId = cursor.getInt(cursor.getColumnIndex(ContactsContract.Groups._ID));
            break;
          }
        }
      } finally {
        cursor.close();
      }

      if (myContactGroupId >= 0) {
        Uri contactsUri =
            ContactsContract.Data.CONTENT_URI
                .buildUpon()
                .appendQueryParameter(RawContacts.ACCOUNT_NAME, params[0])
                .appendQueryParameter(RawContacts.ACCOUNT_TYPE, ACCOUNT_TYPE)
                .build();
        cursor =
            getContentResolver()
                .query(
                    contactsUri,
                    new String[] {GroupMembership.DISPLAY_NAME, GroupMembership.RAW_CONTACT_ID},
                    GroupMembership.GROUP_ROW_ID + " = " + myContactGroupId,
                    null,
                    "lower(" + GroupMembership.DISPLAY_NAME + ")");

        if (cursor == null) return null;

        ArrayList<Contact> contacts = new ArrayList<Contact>();
        try {
          if (!cursor.moveToFirst()) return contacts;
          do {
            Contact c = new Contact();
            c.rawContactId = cursor.getInt(cursor.getColumnIndex(GroupMembership.RAW_CONTACT_ID));
            c.displayName = cursor.getString(cursor.getColumnIndex(Data.DISPLAY_NAME));
            contacts.add(c);
            if (isCancelled()) return null;
          } while (cursor.moveToNext());
        } finally {
          cursor.close();
        }

        return contacts;
      } else {
        return null;
      }
    }