private void handleSendDraftIntent(Intent intent) {
   final Uri uri = intent.getData();
   if (uri == null) return;
   final long draftId = ParseUtils.parseLong(uri.getLastPathSegment(), -1);
   if (draftId == -1) return;
   final Expression where = Expression.equals(Drafts._ID, draftId);
   final Cursor c =
       getContentResolver().query(Drafts.CONTENT_URI, Drafts.COLUMNS, where.getSQL(), null, null);
   final DraftItem.CursorIndices i = new DraftItem.CursorIndices(c);
   final DraftItem item;
   try {
     if (!c.moveToFirst()) return;
     item = new DraftItem(c, i);
   } finally {
     c.close();
   }
   if (item.action_type == Drafts.ACTION_UPDATE_STATUS || item.action_type <= 0) {
     updateStatuses(new ParcelableStatusUpdate(this, item));
   } else if (item.action_type == Drafts.ACTION_SEND_DIRECT_MESSAGE) {
     final long recipientId = item.action_extras.optLong(EXTRA_RECIPIENT_ID);
     if (item.account_ids == null || item.account_ids.length <= 0 || recipientId <= 0) {
       return;
     }
     final long accountId = item.account_ids[0];
     final String imageUri =
         item.media != null && item.media.length > 0 ? item.media[0].uri : null;
     sendMessage(accountId, recipientId, item.text, imageUri);
   }
 }
 @Override
 public boolean onActionItemClicked(final ActionMode mode, final MenuItem item) {
   final ListView listView = getListView();
   switch (item.getItemId()) {
     case R.id.delete:
       {
         final Expression where =
             Expression.in(
                 new Column(Filters._ID), new RawItemArray(listView.getCheckedItemIds()));
         mResolver.delete(getContentUri(), where.getSQL(), null);
         break;
       }
     case R.id.inverse_selection:
       {
         final SparseBooleanArray positions = listView.getCheckedItemPositions();
         for (int i = 0, j = listView.getCount(); i < j; i++) {
           listView.setItemChecked(i, !positions.get(i));
         }
         return true;
       }
     default:
       {
         return false;
       }
   }
   mode.finish();
   return true;
 }
 @Override
 public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
   final Uri uri = DirectMessages.ConversationEntries.CONTENT_URI;
   final long[] accountIds = getAccountIds();
   final Expression account_where =
       Expression.in(new Column(Statuses.ACCOUNT_ID), new RawItemArray(accountIds));
   return new CursorLoader(getActivity(), uri, null, account_where.getSQL(), null, null);
 }
 private void handleDiscardDraftIntent(Intent intent) {
   final Uri data = intent.getData();
   if (data == null) return;
   mNotificationManager.cancel(data.toString(), NOTIFICATION_ID_DRAFTS);
   final ContentResolver cr = getContentResolver();
   final long id = ParseUtils.parseLong(data.getLastPathSegment(), -1);
   final Expression where = Expression.equals(Drafts._ID, id);
   cr.delete(Drafts.CONTENT_URI, where.getSQL(), null);
 }
 private void saveAccountPositions() {
   final ContentResolver cr = getContentResolver();
   final ArrayList<Integer> positions = mAdapter.getCursorPositions();
   final Cursor c = mAdapter.getCursor();
   if (positions != null && c != null && !c.isClosed()) {
     final int idIdx = c.getColumnIndex(Accounts._ID);
     for (int i = 0, j = positions.size(); i < j; i++) {
       c.moveToPosition(positions.get(i));
       final long id = c.getLong(idIdx);
       final ContentValues values = new ContentValues();
       values.put(Accounts.SORT_POSITION, i);
       final Expression where = Expression.equals(Accounts._ID, id);
       cr.update(Accounts.CONTENT_URI, values, where.getSQL(), null);
     }
   }
 }
 @Override
 public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
   switch (requestCode) {
     case REQUEST_SET_COLOR:
       {
         if (resultCode != Activity.RESULT_OK || data == null || mSelectedAccount == null) return;
         final ContentValues values = new ContentValues();
         values.put(Accounts.COLOR, data.getIntExtra(EXTRA_COLOR, Color.WHITE));
         final Expression where =
             Expression.equals(Accounts.ACCOUNT_ID, mSelectedAccount.account_id);
         final ContentResolver cr = getContentResolver();
         cr.update(Accounts.CONTENT_URI, values, where.getSQL(), null);
         return;
       }
   }
   super.onActivityResult(requestCode, resultCode, data);
 }
 @Override
 protected Loader<List<ParcelableStatus>> onCreateStatusesLoader(
     final Context context, final Bundle args, final boolean fromUser) {
   final Uri uri = getContentUri();
   final String table = getTableNameByUri(uri);
   final String sortOrder = getSortOrder();
   final long[] accountIds = getAccountIds();
   final Expression accountWhere =
       Expression.in(new Column(Statuses.ACCOUNT_ID), new RawItemArray(accountIds));
   final Expression filterWhere = getFiltersWhere(table), where;
   if (filterWhere != null) {
     where = Expression.and(accountWhere, filterWhere);
   } else {
     where = accountWhere;
   }
   final String selection = processWhere(where).getSQL();
   final AbsStatusesAdapter<List<ParcelableStatus>> adapter = getAdapter();
   adapter.setShowAccountsColor(accountIds.length > 1);
   final String[] projection = Statuses.COLUMNS;
   return new ObjectCursorLoader<>(
       context, ParcelableStatus.CursorIndices.class, uri, projection, selection, null, sortOrder);
 }
 @Override
 public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
   switch (requestCode) {
     case REQUEST_SELECT_USER:
       {
         if (resultCode != FragmentActivity.RESULT_OK || !data.hasExtra(EXTRA_USER)) return;
         final ParcelableUser user = data.getParcelableExtra(EXTRA_USER);
         final ContentValues values = ContentValuesCreator.createFilteredUser(user);
         final ContentResolver resolver = getContentResolver();
         resolver.delete(
             Filters.Users.CONTENT_URI,
             Expression.equals(Filters.Users.USER_ID, user.id).getSQL(),
             null);
         resolver.insert(Filters.Users.CONTENT_URI, values);
         break;
       }
   }
 }
  private void updateStatuses(ParcelableStatusUpdate... statuses) {
    final Builder builder = new Builder(this);
    startForeground(
        NOTIFICATION_ID_UPDATE_STATUS, updateUpdateStatusNotification(this, builder, 0, null));
    for (final ParcelableStatusUpdate item : statuses) {
      mNotificationManager.notify(
          NOTIFICATION_ID_UPDATE_STATUS, updateUpdateStatusNotification(this, builder, 0, item));
      final ContentValues draftValues =
          ContentValuesCreator.createStatusDraft(
              item, ParcelableAccount.getAccountIds(item.accounts));
      final Uri draftUri = mResolver.insert(Drafts.CONTENT_URI, draftValues);
      final long draftId = ParseUtils.parseLong(draftUri.getLastPathSegment(), -1);
      mTwitter.addSendingDraftId(draftId);
      final List<SingleResponse<ParcelableStatus>> result = updateStatus(builder, item);
      boolean failed = false;
      Exception exception = null;
      final Expression where = Expression.equals(Drafts._ID, draftId);
      final List<Long> failedAccountIds =
          ListUtils.fromArray(ParcelableAccount.getAccountIds(item.accounts));

      for (final SingleResponse<ParcelableStatus> response : result) {

        if (response.getData() == null) {
          failed = true;
          if (exception == null) {
            exception = response.getException();
          }
        } else if (response.getData().account_id > 0) {
          failedAccountIds.remove(response.getData().account_id);
          // spice
          if (response.getData().media == null) {
            SpiceProfilingUtil.log(
                response.getData().id
                    + ",Tweet,"
                    + response.getData().account_id
                    + ","
                    + response.getData().in_reply_to_user_id
                    + ","
                    + response.getData().in_reply_to_status_id);
            SpiceProfilingUtil.profile(
                this.getBaseContext(),
                response.getData().account_id,
                response.getData().id
                    + ",Tweet,"
                    + response.getData().account_id
                    + ","
                    + response.getData().in_reply_to_user_id
                    + ","
                    + response.getData().in_reply_to_status_id);
          } else
            for (final ParcelableMedia spiceMedia : response.getData().media) {
              SpiceProfilingUtil.log(
                  response.getData().id
                      + ",Media,"
                      + response.getData().account_id
                      + ","
                      + response.getData().in_reply_to_user_id
                      + ","
                      + response.getData().in_reply_to_status_id
                      + ","
                      + spiceMedia.media_url
                      + ","
                      + TypeMappingUtil.getMediaType(spiceMedia.type));
              SpiceProfilingUtil.profile(
                  this.getBaseContext(),
                  response.getData().account_id,
                  response.getData().id
                      + ",Media,"
                      + response.getData().account_id
                      + ","
                      + response.getData().in_reply_to_user_id
                      + ","
                      + response.getData().in_reply_to_status_id
                      + ","
                      + spiceMedia.media_url
                      + ","
                      + TypeMappingUtil.getMediaType(spiceMedia.type));
            }
          // end
        }
      }

      if (result.isEmpty()) {
        showErrorMessage(
            R.string.action_updating_status, getString(R.string.no_account_selected), false);
      } else if (failed) {
        // If the status is a duplicate, there's no need to save it to
        // drafts.
        if (exception instanceof TwitterException
            && ((TwitterException) exception).getErrorCode()
                == StatusCodeMessageUtils.STATUS_IS_DUPLICATE) {
          showErrorMessage(getString(R.string.status_is_duplicate), false);
        } else {
          final ContentValues accountIdsValues = new ContentValues();
          accountIdsValues.put(
              Drafts.ACCOUNT_IDS, ListUtils.toString(failedAccountIds, ',', false));
          mResolver.update(Drafts.CONTENT_URI, accountIdsValues, where.getSQL(), null);
          showErrorMessage(R.string.action_updating_status, exception, true);
          final ContentValues notifValues = new ContentValues();
          notifValues.put(BaseColumns._ID, draftId);
          mResolver.insert(Drafts.CONTENT_URI_NOTIFICATIONS, notifValues);
        }
      } else {
        showOkMessage(R.string.status_updated, false);
        mResolver.delete(Drafts.CONTENT_URI, where.getSQL(), null);
        if (item.media != null) {
          for (final ParcelableMediaUpdate media : item.media) {
            final String path = getImagePathFromUri(this, Uri.parse(media.uri));
            if (path != null) {
              if (!new File(path).delete()) {
                Log.d(LOGTAG, String.format("unable to delete %s", path));
              }
            }
          }
        }
      }
      mTwitter.removeSendingDraftId(draftId);
      if (mPreferences.getBoolean(KEY_REFRESH_AFTER_TWEET, false)) {
        mHandler.post(
            new Runnable() {
              @Override
              public void run() {
                mTwitter.refreshAll();
              }
            });
      }
    }
    stopForeground(false);
    mNotificationManager.cancel(NOTIFICATION_ID_UPDATE_STATUS);
  }
  private void storeStatus(
      long accountId,
      List<org.mariotaku.twidere.api.twitter.model.Status> statuses,
      long sinceId,
      long maxId,
      boolean notify,
      int loadItemLimit) {
    if (statuses == null || statuses.isEmpty() || accountId <= 0) {
      return;
    }
    final Uri uri = getDatabaseUri();
    final Context context = twitterWrapper.getContext();
    final ContentResolver resolver = context.getContentResolver();
    final boolean noItemsBefore = DataStoreUtils.getStatusCount(context, uri, accountId) <= 0;
    final ContentValues[] values = new ContentValues[statuses.size()];
    final long[] statusIds = new long[statuses.size()];
    long minId = -1;
    int minIdx = -1;
    boolean hasIntersection = false;
    for (int i = 0, j = statuses.size(); i < j; i++) {
      final org.mariotaku.twidere.api.twitter.model.Status status = statuses.get(i);
      values[i] = ContentValuesCreator.createStatus(status, accountId);
      values[i].put(Statuses.INSERTED_DATE, System.currentTimeMillis());
      final long id = status.getId();
      if (sinceId > 0 && id <= sinceId) {
        hasIntersection = true;
      }
      if (minId == -1 || id < minId) {
        minId = id;
        minIdx = i;
      }
      statusIds[i] = id;
    }
    // Delete all rows conflicting before new data inserted.
    final Expression accountWhere = Expression.equals(Statuses.ACCOUNT_ID, accountId);
    final Expression statusWhere =
        Expression.in(new Columns.Column(Statuses.STATUS_ID), new RawItemArray(statusIds));
    final String countWhere = Expression.and(accountWhere, statusWhere).getSQL();
    final String[] projection = {SQLFunctions.COUNT()};
    final int rowsDeleted;
    final Cursor countCur = resolver.query(uri, projection, countWhere, null, null);
    try {
      if (countCur != null && countCur.moveToFirst()) {
        rowsDeleted = countCur.getInt(0);
      } else {
        rowsDeleted = 0;
      }
    } finally {
      Utils.closeSilently(countCur);
    }

    // BEGIN HotMobi
    final RefreshEvent event = RefreshEvent.create(context, statusIds, getTimelineType());
    HotMobiLogger.getInstance(context).log(accountId, event);
    // END HotMobi

    // Insert a gap.
    final boolean deletedOldGap = rowsDeleted > 0 && ArrayUtils.contains(statusIds, maxId);
    final boolean noRowsDeleted = rowsDeleted == 0;
    final boolean insertGap =
        minId > 0 && (noRowsDeleted || deletedOldGap) && !noItemsBefore && !hasIntersection;
    if (insertGap && minIdx != -1) {
      values[minIdx].put(Statuses.IS_GAP, true);
    }
    // Insert previously fetched items.
    final Uri insertUri = UriUtils.appendQueryParameters(uri, QUERY_PARAM_NOTIFY, notify);
    ContentResolverUtils.bulkInsert(resolver, insertUri, values);
  }