Big picture: GUI shows user a list of their playlists. User picks one. Program passes chosen playlist to next activity which displays the songs in that playlist.
Problem: I can display the playlists and register the users choice, but I can't seem to display the songs of that play list.
Yes, I've see the following questions:
How to query for songs in playlists on Android SDK?
Given an Android music playlist name, how can one find the songs in the playlist?
What is the String 'volumeName' argument of MediaStore.Audio.Playlists.Members.getContentUri referring to?
As you can see in my code, I've done my best to implement those solutions, but to no avail.
Things to keep in mind: I'm testing this on a Galaxy Nexus, so no SDcard. Just internal storage and music in the cloud. I need it to work in any scenario (internal, external, or cloud). It currently works in none of those.
//#SuppressWarnings ("serial)")
public class CreationActivity extends Activity {
private final String [] STAR= {"*"};
//reads in all songs to an array
#Override
public void onCreate (Bundle savedInstanceState){
super.onCreate(savedInstanceState);
//set layout view and assign to variable
setContentView(R.layout.creation);
TableLayout myLayout = (TableLayout)findViewById(R.id.creationLayout);
try {
Bundle extras = getIntent().getExtras();
if (extras!=null){
//get the desired playlist and ID
String playlist = extras.getString("playlist");
Long playlistID = extras.getLong("playlistID");
ArrayList<song> songs = new ArrayList<song>();
//read in the songs from the playlist
String[] proj = {MediaStore.Audio.Playlists.Members.TITLE,
MediaStore.Audio.Playlists.Members.ARTIST,
MediaStore.Audio.Playlists.Members.DURATION};
//method 1
Cursor songCursor = getContentResolver().query(MediaStore.Audio.Playlists.Members.getContentUri(null,playlistID),
proj,
null,
null,
null);
//method 2
/*
Cursor songCursor = getContentResolver().query(Uri.parse("content://com.google.android.music.MusicContent/playlists/members"),
proj,
null,
null,
null);
*/
//method 3
/*
Uri membersUri = MediaStore.Audio.Playlists.Members.getContentUri("internal", playlistID);
Cursor membersCursor = managedQuery(membersUri, STAR, null, null, null);
*/
//then this part with methods 1 and 2
/*
if (songCursor.getCount() > 0) {
songCursor.moveToFirst();
do {
song currSong = new song();
currSong.title = songCursor.getString(0);
currSong.artist = songCursor.getString(1);
songs.add(currSong);
} while (songCursor.moveToNext());
}
songCursor.close();
*/
//or this part with method 3
/*
membersCursor.moveToFirst();
for(int s= 0; s<membersCursor.getCount(); s++,
membersCursor.moveToNext()){
song currSong = new song();
currSong.title = songCursor.getString(0);
currSong.artist = songCursor.getString(1);
songs.add(currSong);
}
membersCursor.close();
*/
}else{
Toast.makeText(getBaseContext(), "No songs",Toast.LENGTH_LONG).show();
}
} catch (NumberFormatException e){
}
}
}
No errors during compiling. But "Unfortunately Music App has unexpectedly quit." every time.
Thanks for the help!
I figured it out. The key was to use the playlist ID as a string immediately within the URI. See code below.
This is the part that will get the playlist names and IDs:
String[] proj = {MediaStore.Audio.Playlists.NAME, MediaStore.Audio.Playlists._ID};
Uri playlistUri = Uri.parse("content://com.google.android.music.MusicContent/playlists");
Cursor playlistCursor = getContentResolver().query(playlistUri, proj, null, null, null);
if (playlistCursor.getCount() > 0) {
playlistCursor.moveToFirst();
do {
nameList.add(playlistCursor.getString(0));
idList.add(playlistCursor.getLong(1));
} while (playlistCursor.moveToNext());
}
Then once you have the playlist ID you can query for the songs in the playlist. This is the part of code that actually queries for the info and puts it all in an array list. NOTE: "song" is a class I have defined elsewhere, where readSong is a method that assigns values to various values (title, artist, etc).
ArrayList<song> songs = new ArrayList<song>();
//read songs into library from the correct playlist
String[] proj = {MediaStore.Audio.Playlists.Members.TITLE, MediaStore.Audio.Playlists.Members.ARTIST, MediaStore.Audio.Playlists.Members.DURATION, MediaStore.Audio.Playlists.Members._ID};
Uri songUri = Uri.parse("content://com.google.android.music.MusicContent/playlists/" + playlistID + "/members");
Cursor songCursor = getContentResolver().query(songUri, proj, null, null, null);
if (songCursor.getCount() > 0) {
songCursor.moveToFirst();
do {
//create dummy song
song currSong = new song();
//read info to dummy var
currSong.readSong(songCursor);
//add instance to collection
songs.add(currSong);
} while (songCursor.moveToNext());
}
songCursor.close();
I hope this helps anybody else who was struggling with this!! Let me know if you have any comments on my method or ways to make it better!
Related
I am recording the screen and saving it in a Particular folder and then after saving it i have a button to show all the videos in that folder.
newly saved videos are not updating but if i go in file-explorer and open that folder there the video is showing and then if i again see all videos of that folder in my app ,now the video appears there too .How to make that video appear first time only i.e after saving the video if i click (view all video) button the video should be there.
My code for fetching all videos from folder
private void init()
{
recyclerView = findViewById(R.id.recycler_view);
swipeRefreshLayout = findViewById(R.id.pullToRefresh);
layoutManager = new GridLayoutManager(getApplicationContext(),4);
recyclerView.setLayoutManager(layoutManager);
arrayList = new ArrayList<>();
videoAdapter = new VideoAdapter(getApplicationContext(),arrayList,Video_Main.this);
recyclerView.setAdapter(videoAdapter);
fetch_videos();
}
private void fetch_videos()
{
Uri uri;
Cursor cursor;
int column_index_data,thum;
String absolutePathImage = null;
uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
String[] projection = {
MediaStore.MediaColumns.DATA,
MediaStore.Video.Media.BUCKET_DISPLAY_NAME,
MediaStore.Video.Media._ID,
MediaStore.Video.Thumbnails.DATA
};
String selection=MediaStore.Video.Media.DATA +" like?";
String[] selectionArgs=new String[]{"%Paint App%"};
String orderBy = MediaStore.Images.Media.DATE_TAKEN;
cursor = getApplicationContext().getContentResolver().query(uri,projection,selection,selectionArgs,orderBy +" DESC");
String root = Environment.getExternalStorageDirectory().getAbsolutePath().toString();
column_index_data = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
thum = cursor.getColumnIndexOrThrow(MediaStore.Video.Thumbnails.DATA);
while(cursor.moveToNext())
{
absolutePathImage = cursor.getString(column_index_data);
VideoModel videoModel = new VideoModel();
videoModel.setBoolean_selected(false);
videoModel.setStr_path(absolutePathImage);
videoModel.setStr_thumbnail(cursor.getString(thum));
arrayList.add(videoModel);
}
videoAdapter.setVideoList(arrayList);
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,Uri.parse(root + "/Paint App")));
}
}
You need to create a method in the adapter like,
public void setVideoList(YourArray arrayList){
this.yourList.clear();
this.yourList.addAll(arrayList);
notifyDataSeChanged();
}
then remove below lines and add it outside the method but above that method,
VideoAdapter videoAdapter = new
VideoAdapter(getApplicationContext(),arrayList,Video_Main.this);
recyclerView.setAdapter(videoAdapter);
Also, call the method from adapter from where you removed the lines,
videoAdapter.setVideoList(arrayList);
then when you add record the file just call the method again fetch_videos(); It will work.
Thanks for the help,i got the solution my sendBroadcast was wrong.It should be
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,Uri.fromFile(file)));
The following code gets me image thumbnails from local pictures on the phone/sd cards:
public Task<List<Album>> GetAllAlbumsAndPhotos(object activity)
{
Activity activ = activity as Activity;
List<Album> albums = new List<Album>();
// which image properties are we querying
String[] projection = new String[]
{
MediaStore.Images.Media.InterfaceConsts.BucketId,
MediaStore.Images.Media.InterfaceConsts.BucketDisplayName,
MediaStore.Images.Media.InterfaceConsts.DateTaken,
MediaStore.Images.Media.InterfaceConsts.DateAdded,
MediaStore.Images.Media.InterfaceConsts.Data
};
// Get the base URI for the People table in the Contacts content provider.
AndroidNet.Uri images = MediaStore.Images.Media.ExternalContentUri;
// Make the query.
var cursor = activ.ContentResolver.Query(images,
projection, // Which columns to return
"", // Which rows to return (all rows)
null, // Selection arguments (none)
"" // Ordering
);
if (cursor.MoveToFirst())
{
int bucketColumn = cursor.GetColumnIndex(MediaStore.Images.Media.InterfaceConsts.BucketDisplayName);
int takenColumn = cursor.GetColumnIndex(MediaStore.Images.Media.InterfaceConsts.DateTaken);
int addedColumn = cursor.GetColumnIndex(MediaStore.Images.Media.InterfaceConsts.DateAdded);
int dataColumn = cursor.GetColumnIndex(MediaStore.Images.Media.InterfaceConsts.Data);
do
{
.
.
.
} while (cursor.MoveToNext());
}
return Task.FromResult(albums);
}
How do I include Video thumbnails? Can It be done with the same code or does it have to be done independently from this block of code?
i need to get all the MMS Data detalis like mms_image, address,date and type.
i am using following logic. In this i am using two cursors, one for images and other for remaining fields. but the size of two cursors are different. so, i am unable to match both image and other fields.
//for date,address,type
Cursor curPdu = getContentResolver ().query(Uri.parse("content://mms"), null, null, null, null);
while(curPdu.moveToNext())
{
String id = curPdu.getString (curPdu.getColumnIndex ("_id"));
String date = curPdu.getString (curPdu.getColumnIndex ("date"));
mms_add.add(getAddressNumber(Integer.parseInt(id)));
int type = Integer.parseInt(curPdu.getString(curPdu.getColumnIndex("m_type")));
mms_type.add((type==128)?"2":"1");
mms_date.add(getDate(Long.parseLong(date)));
}
//for image
Cursor curPart = getContentResolver (). query (Uri.parse ("content://mms/part"), null, null, null, null);
while(curPart.moveToNext())
{
coloumns = curPart.getColumnNames();
if(values == null)
values = new String[coloumns.length];
for(int i=0; i< curPart.getColumnCount(); i++)
{
values[i] = curPart.getString(i);
}
if(values[3].equals("image/jpeg"))
{
mms_image.add(GetMmsAttachment(values[0],values[12],values[4]));
}else{
mms_image.add("null");
}
}
so, please guide me how to get all the details using one cusor if possible.
You can try the solution and url provided here.
And may i know why you need 2 cursor ? I assume there is some mms without image attached so that's the reason you get a different count.
I have created a Project having many activities. One activity is to record the video, that is working fine. I can see the recorded video in my specified folder without restart my tablet.
But when I try to find all the videos in that folder in some other activity using query, see code below. Then I can't see my recorded video until I restart my tablet. I can see just old recorded videos before starting my tablet. I couldn't understand this strange behavior.
Can anyone put some light on this issue??
Thanks.
private void initVideosId() { // getting the videos id in Video Folder of SD Card
try {
// Here we set up a string array of the thumbnail ID column we want
// to get back
String[] proj = { _ID };
//Querying for the videos in VideoGallery folder of SD card
// Now we create the cursor pointing to the external thumbnail store
_cursor = managedQuery(_contentUri, proj, // Which columns to return
MEDIA_DATA + " like ? ", // WHERE clause; which rows to
// return (all rows)
new String[] { "%VideoGallery%" }, // WHERE clause selection
// arguments (none)
null); // Order-by clause (ascending by name)
int count = _cursor.getCount();
// We now get the column index of the thumbnail id
_columnIndex = _cursor.getColumnIndex(_ID);
// initialize
_videosId = new int[count];
// move position to first element
_cursor.moveToFirst();
for (int i = 0; i < count; i++) {
int id = _cursor.getInt(_columnIndex);
//
_videosId[i] = id;
//
_cursor.moveToNext();
//
}
} catch (Exception ex) {
showToast(ex.getMessage().toString());
}
}
If you stored the file on external storage, you need to use MediaScannerConnection to get the MediaStore to index that file, such as:
MediaScannerConnection.scanFile(
this,
new String[] {file.getAbsolutePath()},
null,
new OnScanCompletedListener() {
#Override
public void onScanCompleted(String path, Uri uri) {
// do something if you want
}
});
I am working on simple audio media player. I am using media store to get information of all songs stored on the sdcard. So far So good. Everything is working fine.
But I am stuck now. How can I get last added (recently added) songs using media store?
Regards,
Niral
This is from the source of the Default Music Player in Android 2.3
private void playRecentlyAdded() {
// do a query for all songs added in the last X weeks
int X = MusicUtils.getIntPref(this, "numweeks", 2) * (3600 * 24 * 7);
final String[] ccols = new String[] { MediaStore.Audio.Media._ID};
String where = MediaStore.MediaColumns.DATE_ADDED + ">" + (System.currentTimeMillis() / 1000 - X);
Cursor cursor = MusicUtils.query(this, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
ccols, where, null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
if (cursor == null) {
// Todo: show a message
return;
}
try {
int len = cursor.getCount();
long [] list = new long[len];
for (int i = 0; i < len; i++) {
cursor.moveToNext();
list[i] = cursor.getLong(0);
}
MusicUtils.playAll(this, list, 0);
} catch (SQLiteException ex) {
} finally {
cursor.close();
}
}
I'm not sure if this is what you are looking for, but when I looked up at the default android music player source, i found out that there is a "recently added" playlist in media store. Its id in MediaStore.Audio.Playlists is -1.
EDIT:
After further research, I found out that -1 is just a value to indicate that it does not exist on the Playlist table.
You may use the following solution instead:
Upon querying MediaStore.Audio.Media, add this to your where clause condition:
MediaStore.Audio.Media.DATE_ADDED + ">" + (System.currentTimeMillis() / 1000 - NUM_OF_DAYS);
NUM_OF_DAYS refers to how old your audio file is stored in your SD card.
Take Note: query from MediaStore.Audio.Media, not MediaStore.Audio.Playlist.
In your custom list that you maintain add one more integer field 'dateAdded' and to access that use
int dateAddedIndex = internalContentCursor.getColumnIndex(MediaStore.Audio.Media.DATE_ADDED);
if (dateAddedIndex != -1) {
songs.setDateAdded(externalContentCursor.getInt(externalContentCursor.getColumnIndex(MediaStore.Audio.Media.DATE_ADDED)));
}
After getting this sort the list according to the time they were added
public static List<Songs> getTopRecentAdded(List<Songs> list) {
Collections.sort(list, new Comparator<Songs>() {
#Override
public int compare(Songs left, Songs right) {
return left.getDateAdded() - right.getDateAdded();
}
});
Collections.reverse(list);
return list;
}
This will return the list which contain song at first which was added last.