/**
   * Builds a query that will return all the songs represented by the given parameters.
   *
   * @param type MediaUtils.TYPE_ARTIST, TYPE_ALBUM, or TYPE_SONG.
   * @param id The MediaStore id of the song, artist, or album.
   * @param projection The columns to query.
   * @param select An extra selection to pass to the query, or null.
   * @return The initialized query.
   */
  private static QueryTask buildMediaQuery(int type, long id, String[] projection, String select) {
    Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
    StringBuilder selection = new StringBuilder();
    String sort = DEFAULT_SORT;

    switch (type) {
      case TYPE_SONG:
        selection.append(MediaStore.Audio.Media._ID);
        break;
      case TYPE_ARTIST:
        selection.append(MediaStore.Audio.Media.ARTIST_ID);
        break;
      case TYPE_ALBUM:
        selection.append(MediaStore.Audio.Media.ALBUM_ID);
        sort = ALBUM_SORT;
        break;
      default:
        throw new IllegalArgumentException("Invalid type specified: " + type);
    }

    selection.append('=');
    selection.append(id);
    selection.append(" AND length(_data) AND " + MediaStore.Audio.Media.IS_MUSIC);

    if (select != null) {
      selection.append(" AND ");
      selection.append(select);
    }

    QueryTask result = new QueryTask(media, projection, selection.toString(), null, sort);
    result.type = type;
    return result;
  }
 /**
  * Builds a query that will return all the songs in the playlist with the given id.
  *
  * @param id The id of the playlist in MediaStore.Audio.Playlists.
  * @param projection The columns to query.
  * @param selection The selection to pass to the query, or null.
  * @return The initialized query.
  */
 public static QueryTask buildPlaylistQuery(long id, String[] projection, String selection) {
   Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", id);
   String sort = MediaStore.Audio.Playlists.Members.PLAY_ORDER;
   QueryTask result = new QueryTask(uri, projection, selection, null, sort);
   result.type = TYPE_PLAYLIST;
   return result;
 }
 /**
  * Returns the first matching song (or NULL) of given type + id combination
  *
  * @param resolver A ContentResolver to use.
  * @param type The MediaTye to query
  * @param id The id of given type to query
  */
 public static Song getSongByTypeId(ContentResolver resolver, int type, long id) {
   Song song = new Song(-1);
   QueryTask query = buildQuery(type, id, Song.FILLED_PROJECTION, null);
   Cursor cursor = query.runQuery(resolver);
   if (cursor != null) {
     if (cursor.getCount() > 0) {
       cursor.moveToPosition(0);
       song.populate(cursor);
     }
     cursor.close();
   }
   return song.isFilled() ? song : null;
 }
  /**
   * Build a query that will contain all the media under the given path.
   *
   * @param path The path, e.g. /mnt/sdcard/music/
   * @param projection The columns to query
   * @return The initialized query.
   */
  public static QueryTask buildFileQuery(String path, String[] projection) {
    /* make sure that the path is:
       -> fixed-up to point to the real mountpoint if user browsed to the mediadir symlink
       -> terminated with a / if it is a directory
       -> ended with a % for the LIKE query
    */
    path = addDirEndSlash(sanitizeMediaPath(path)) + "%";
    final String query = "_data LIKE ? AND " + MediaStore.Audio.Media.IS_MUSIC;
    String[] qargs = {path};

    Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
    QueryTask result = new QueryTask(media, projection, query, qargs, DEFAULT_SORT);
    result.type = TYPE_FILE;
    return result;
  }
 @Override
 protected void onPostExecute(FriendSubscribe query) {
   super.onPostExecute(query);
   final FriendFollowing.Friend f = (FriendFollowing.Friend) allFriends.find(id);
   FriendSubscribe.Data d = (FriendSubscribe.Data) query.getData();
   if (d.getAllow()) {
     f.setWatched(1);
     adapter.notifyDataSetChanged();
   } else {
     AlertDialog.Builder b = new AlertDialog.Builder(ac);
     b.setTitle(ac.getResources().getString(R.string.alert))
         .setMessage(ac.getResources().getString(R.string.this_prifile))
         .setNegativeButton(
             ac.getResources().getString(R.string.ok),
             new DialogInterface.OnClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int which) {
                 dialog.cancel();
                 f.setWatched(2);
                 adapter.notifyDataSetChanged();
               }
             });
     AlertDialog dialog = b.create();
     dialog.show();
   }
   adapter.notifyDataSetChanged();
 }
 @Override
 protected void onPostExecute(FriendUnsubsrcibe query) {
   super.onPostExecute(query);
   FriendFollowing.Friend f = (FriendFollowing.Friend) allFriends.find(id);
   f.setWatched(0);
   adapter.notifyDataSetChanged();
 }
 @Override
 protected void onPostExecute(FriendFollowing query) {
   if (checkResult(query)) {
     FriendFollowing.Data data = (FriendFollowing.Data) query.getData();
     for (int i = 0; i < data.friends.size(); i++) {
       FriendFollowing.Friend f = (FriendFollowing.Friend) data.friends.get(i);
       ProfileQuery pq = new ProfileQuery(appSettings, String.valueOf(f.getID()));
       pq.getResponse(WebQuery.GET);
       ProfileQuery.UserProfile p = pq.getData();
       int ii = 0;
       ii++;
     }
     allFriends = data.friends;
     adapter = new FriendsFollowingAdapter(allFriends);
     // adapter.notifyDataSetChanged();
     lvFriends.setAdapter(adapter);
     if (lvFriends.getCount() <= 0) noUsersFound(true);
     else noUsersFound(false);
   }
   super.onPostExecute(query);
 }
  /**
   * Builds a query that will return all the songs in the genre with the given id.
   *
   * @param id The id of the genre in MediaStore.Audio.Genres.
   * @param projection The columns to query.
   * @param selection The selection to pass to the query, or null.
   * @param selectionArgs The arguments to substitute into the selection.
   * @param sort The sort order.
   * @param type The media type to query and return
   * @param returnSongs returns matching songs instead of `type' if true
   */
  public static QueryTask buildGenreQuery(
      long id,
      String[] projection,
      String selection,
      String[] selectionArgs,
      String sort,
      int type,
      boolean returnSongs) {
    // Note: This function works on a raw sql query with way too much internal
    // knowledge about the mediaProvider SQL table layout. Yes: it's ugly.
    // The reason for this mess is that android has a very crippled genre implementation
    // and does, for example, not allow us to query the albumbs beloging to a genre.

    Uri uri = MediaStore.Audio.Genres.Members.getContentUri("external", id);
    String[] clonedProjection =
        projection
            .clone(); // we modify the projection, but this should not be visible to the caller
    String sql = "";
    String authority = "audio";

    if (type == TYPE_ARTIST) authority = "artist_info";
    if (type == TYPE_ALBUM) authority = "album_info";

    // Our raw SQL query includes the album_info table (well: it's actually a view)
    // which shares some columns with audio.
    // This regexp should matche duplicate column names and forces them to use
    // the audio table as a source
    final String _FORCE_AUDIO_SRC = "(^|[ |,\\(])(_id|album(_\\w+)?|artist(_\\w+)?)";

    // Prefix the SELECTed rows with the current table authority name
    for (int i = 0; i < clonedProjection.length; i++) {
      if (clonedProjection[i].equals("0") == false) // do not prefix fake rows
      clonedProjection[i] = (returnSongs ? "audio" : authority) + "." + clonedProjection[i];
    }

    sql += TextUtils.join(", ", clonedProjection);
    sql +=
        " FROM audio_genres_map_noid, audio" + (authority.equals("audio") ? "" : ", " + authority);
    sql += " WHERE(audio._id = audio_id AND genre_id=?)";

    if (selection != null && selection.length() > 0)
      sql += " AND(" + selection.replaceAll(_FORCE_AUDIO_SRC, "$1audio.$2") + ")";

    if (type == TYPE_ARTIST)
      sql +=
          " AND(artist_info._id = audio.artist_id)"
              + (returnSongs ? "" : " GROUP BY artist_info._id");

    if (type == TYPE_ALBUM)
      sql +=
          " AND(album_info._id = audio.album_id)" + (returnSongs ? "" : " GROUP BY album_info._id");

    if (sort != null && sort.length() > 0)
      sql += " ORDER BY " + sort.replaceAll(_FORCE_AUDIO_SRC, "$1audio.$2");

    // We are now turning this into an sql injection. Fun times.
    clonedProjection[0] = sql + " --";

    QueryTask result = new QueryTask(uri, clonedProjection, selection, selectionArgs, sort);
    result.type = TYPE_GENRE;
    return result;
  }
 @Override
 protected void onPreExecute() {
   super.onPreExecute();
   mQueryBusLine.setEnabled(false);
 }