/** * 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); }