I want to be able to get the album art of the song that is currently playing. I am able to get the name, album, artist with the use of
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
String cmd = intent.getStringExtra("command");
Log.v("tag ", action + " / " + cmd);
String artist = intent.getStringExtra("artist");
String album = intent.getStringExtra("album");
String track = intent.getStringExtra("track");
Log.v("tag", artist + ":" + album + ":" + track);
Fullname = (artist + ":" + album + ":" + track);
Toast.makeText(MusicPlayer.this, track, Toast.LENGTH_SHORT).show();
update();
However, this does not help me with getting album art. Most of the posts on here that ask for getting album art call for the use of
MediaStore.Audio.AlbumColumns.AlbumArt
But I can't seem to figure out how to work it. When I tried to use
Cursor cursor = getActivity().managedQuery(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
new String[] {MediaStore.Audio.Albums._ID, MediaStore.Audio.Albums.ALBUM_ART},
MediaStore.Audio.Albums._ID+ "=?",
new String[] {String.valueOf(albumId)},
null);
if (cursor.moveToFirst()) {
String path = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM_ART));
// do whatever you need to do
}
(From here ) or anything similar to this I keep running into the problem of not having a albumId. I read that I should set albumid to
album_id = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID))
but I can't seem to get a Long without having another cursor which I can't figure out how to do to without the use of a pre-existing albumid. Any help would be greatly appreciated.
I had the same problem. The intent only has the media id. So we have to get the album id related to that media file.
Here's the solution I used :
//get the song's id from intent
long songId = intent.getLongExtra("id", -1);
//get the albumid using media/song id
if(songId!=-1) {
String selection = MediaStore.Audio.Media._ID + " = "+songId+"";
Cursor cursor = getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, new String[] {
MediaStore.Audio.Media._ID, MediaStore.Audio.Media.ALBUM_ID},
selection, null, null);
if (cursor.moveToFirst()) {
long albumId = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
Log.d("Album ID : ", ""+albumId);
Uri sArtworkUri = Uri.parse("content://media/external/audio/albumart");
Uri albumArtUri = ContentUris.withAppendedId(sArtworkUri, albumId);
//set the album art in imageview
albumArt.setImageURI(albumArtUri);
}
cursor.close();
}
Get Album ID of current playing song and call following function to get Album Art :
public static Bitmap getAlbumart(Context context,Long album_id){
Bitmap bm = null;
BitmapFactory.Options options = new BitmapFactory.Options();
try{
final Uri sArtworkUri = Uri.parse("content://media/external/audio/albumart");
Uri uri = ContentUris.withAppendedId(sArtworkUri, album_id);
ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "r");
if (pfd != null){
FileDescriptor fd = pfd.getFileDescriptor();
bm = BitmapFactory.decodeFileDescriptor(fd, null, options);
pfd = null;
fd = null;
}
} catch(Error ee){}
catch (Exception e) {}
return bm;
}
Related
I'm developing a Chrome OS app and I want to play a song when a song dragged and dropped onto a view in my app. I created a listener and I'm able to get the dragged file with its path. But the problem is; I can't get the information about the dropped song.
Here's what I've tried so far;
class BackingTrackDragListener implements View.OnDragListener {
private final static Uri ARTWORK_URI = Uri.parse("content://media/external/audio/albumart");
BackingTrackViewModel viewModel;
public BackingTrackDragListener(BackingTrackViewModel viewModel) {
super();
this.viewModel = viewModel;
}
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
public boolean onDrag(View v, DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
return true;
case DragEvent.ACTION_DROP:
if (event.getClipDescription().hasMimeType("application/x-arc-uri-list")) {
MainActivity mainActivity = MyApplication.getMainActivity();
if (mainActivity == null) {
break;
}
mainActivity.requestDragAndDropPermissions(event);
ClipData.Item item = event.getClipData().getItemAt(0);
ContentResolver contentResolver = mainActivity.getContentResolver();
try {
String audioPath = new File(new URI(item.getUri().toString()).getPath()).getCanonicalPath();
Cursor cursor = contentResolver.query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
new String[]{
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.DURATION,
MediaStore.Audio.Media.ALBUM_ID
},
MediaStore.Audio.Media.DATA + " = ?",
new String[]{audioPath},
"");
String[] str = cursor.getColumnNames(); // prints the column names
final String displayName = cursor.getString(0);
final long duration = cursor.getLong(1);
final long albumId = cursor.getLong(2);
final Uri imageUri = ContentUris.withAppendedId(ARTWORK_URI, albumId);
if (audioPath.endsWith("mp3") && duration > 15000) {
viewModel.setSelectedAudio(new BackingTrackAudio(displayName, imageUri, audioPath));
} else {
break;
}
cursor.close();
} catch (IOException | URISyntaxException e) {
e.printStackTrace();
}
break;
}
default:
break;
}
return false;
}
}
The actual problem here is I can't read the column data.
I think the problem is occurring when I create the cursor. When I wanted to get a column data from the cursor, my app throws the below error:
Error: android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 0
Error line: final String displayName = cursor.getString(0);
I also tried this using a while loop like cursor.moveToNext() or cursor.moveToFirst() but no luck.
What I want is to get the track name, album cover, and duration from the mp3 file's path. Is there another way to achieve this? I also tried this solution: Android: How to get audio detail from audio file but this one also didn't work :/ Any suggestion would help, thank you.
UPDATE
I also tried:
Cursor cursor = contentResolver.query(
item.getUri(),
new String[]{
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.DURATION,
MediaStore.Audio.Media.ALBUM_ID
},
MediaStore.Audio.Media.DATA + " = ?",
new String[]{audioPath},
"");
And the error was very similar to the previous one:
android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1
Here is the code to get details about the song from the mp3 file.
String path = Environment.getExternalStorageDirectory().getPath() + "/Download/music1.mp3";
File file = new File(path);
String fileName = file.getName();
double bytes = file.length();
String fileSize = String.format("%.2f", bytes / 1024) + " kb";
Log.d("tag", fileName + " " + fileSize);
MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
Uri uri = Uri.fromFile(file);
mediaMetadataRetriever.setDataSource(MainActivity.this, URI);
String songName = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
String artist = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
String album = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
String genre = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE);
String track = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS);
Log.d(TAG, "SongName: " + songName + " Artist: " + artist + " Album: " + album);
Log.d(TAG, "Genre: " + genre + " Track: " + track);
I am creating an audio player and i am using this code to get all the songs
String[] STAR = {"*"};
Cursor cursor;
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0";
File file;
cursor =context.getContentResolver().query(uri, STAR, selection, null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
int i = 0;
do {
String songName = cursor
.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME));
path[i] = cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.DATA));
String albumName = cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.ALBUM));
albumId[i] = cursor
.getInt(cursor
.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
String artist= cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));
String albumname= cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM));
artistId[i]=cursor.getInt(cursor
.getColumnIndex(MediaStore.Audio.Media.ARTIST_ID));
}cursor.close();
This gets me the songs but i get audio of unsupported formats too. such as .wav any idea how to avoid unsupported formats
You can use MimeType to do this. See below example code how it is done for mp3.
ContentResolver contentResolver = context.getContentResolver();
Uri uri = MediaStore.Files.getContentUri("external");
String[] projection = null;
String sortOrder = null;
String selectionMimeType = MediaStore.Files.FileColumns.MIME_TYPE + "=?";
String mimeType = imeTypeMap.getSingleton().getMimeTypeFromExtension("mp3");
String[] selectionArgsMp3 = new String[]{ mimeType };
Cursor mp3Songs = contentResolver.query(uri, projection,selectionMimeType,selectionArgsmp3, sortOrder);
Another approach it that you can check is there any compatible application installed on device using below code while opening/playing application.
private void openRelevantFileHandler(String pathToMusicFile)
{
String extension = MimeTypeMap.getFileExtensionFromUrl(pathToMusicFile);
String type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file://" + pathToMusicFile), type);
PackageManager packageManager = context.getPackageManager();
List activities = packageManager.queryIntentActivities(intent, PackageManager.MATCH_ALL);
boolean isIntentSafe = activities.size() > 0;
if (!isIntentSafe) {
Utility.showToast(context, "No application available on your device to open this type of file.");
}
else
{
context.startActivity(intent);//Start related application
}
}
Hope this will help you in some way :)
I am implementing a pick photo from gallery and then show it in a ImageView. I had the some issues and, thanks to this solution: Null Intent passed back on Samsung, is partially solved. I can take the photo and it's saved in a custom location:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (Helpers.isExternalStorageWritable()) {
Intent imageIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File imagesFolder = new File(Environment.getExternalStorageDirectory(), Globals.Constants.APP_NAME);
imagesFolder.mkdirs();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmm").format(new Date());
File image = new File(imagesFolder, "report" + timeStamp + ".jpg");
Uri uriSavedImage = Uri.fromFile(image);
imageIntent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
getActivity().startActivityForResult(imageIntent, CAMERA_REQUEST);
However when in onActivityResult, when I show the taken picture in a ImageView, I got a random photo from my old photos. Here's my onActivityResult code:
try {
Log.i("TAG", "inside Samsung Phones");
String[] projection = {
MediaStore.Images.Thumbnails._ID, // The columns we want
MediaStore.Images.Thumbnails.IMAGE_ID,
MediaStore.Images.Thumbnails.KIND,
MediaStore.Images.Thumbnails.DATA };
String selection = MediaStore.Images.Thumbnails.KIND + "=" + MediaStore.Images.Thumbnails.MINI_KIND;
String sort = MediaStore.Images.Thumbnails._ID + " DESC";
Cursor myCursor = getActivity().getContentResolver().query(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, projection, selection, null, sort);
long imageId = 0l;
long thumbnailImageId = 0l;
String thumbnailPath = "";
try {
myCursor.moveToFirst();
imageId = myCursor.getLong(myCursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.IMAGE_ID));
thumbnailImageId = myCursor.getLong(myCursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID));
thumbnailPath = myCursor.getString(myCursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.DATA));
} finally {
// myCursor.close();
}
String[] largeFileProjection = {
MediaStore.Images.ImageColumns._ID,
MediaStore.Images.ImageColumns.DATA };
String largeFileSort = MediaStore.Images.ImageColumns._ID + " DESC";
myCursor = getActivity().getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, largeFileProjection, null, null, largeFileSort);
String largeImagePath = "";
try {
myCursor.moveToFirst();
largeImagePath = myCursor.getString(myCursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATA));
mImageCaptureUri_samsung = Uri.fromFile(new File(largeImagePath));
mImageCaptureUri = null;
} finally {
// myCursor.close();
}
Uri uriLargeImage = Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, String.valueOf(imageId));
Uri uriThumbnailImage = Uri.withAppendedPath(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, String.valueOf(thumbnailImageId));
image1.setImageURI(uriThumbnailImage);
}
Another issue is that the .thumbnail neither the actual photo are shown right away, it takes a couple minutes to be shown in the gallery or file manager. But now I would be happy if anyone can help me with the random picture shown. Thank you in advanced!
Is it possible to retrieve bitmap( Album art ) of mp3 file from it's file path or file input stream. Like using BitmapFactory API or some other API.
Yes, it is possible to get mp3 cover art.
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
mmr.setDataSource(mPath);
InputStream inputStream = null;
if (mmr.getEmbeddedPicture() != null) {
inputStream = new ByteArrayInputStream(mmr.getEmbeddedPicture());
}
mmr.release();
bitmap = BitmapFactory.decodeStream(inputStream);
Using the following method you can get the album art uri of an image file.
public Uri getArtUriFromMusicFile(File file) {
final Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
final String[] cursor_cols = { MediaStore.Audio.Media.ALBUM_ID };
final String where = MediaStore.Audio.Media.IS_MUSIC + "=1 AND " + MediaStore.Audio.Media.DATA + " = '"
+ file.getAbsolutePath() + "'";
final Cursor cursor = context.getContentResolver().query(uri, cursor_cols, where, null, null);
Log.d(TAG, "Cursor count:" + cursor.getCount());
/*
* If the cusor count is greater than 0 then parse the data and get the art id.
*/
if (cursor != null && cursor.getCount() > 0) {
cursor.moveToFirst();
Long albumId = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM_ID));
Uri sArtworkUri = Uri.parse("content://media/external/audio/albumart");
Uri albumArtUri = ContentUris.withAppendedId(sArtworkUri, albumId);
cursor.close();
return albumArtUri;
}
return Uri.EMPTY;
}
To extract album art from an mp3 file, there is no direct API available in Android as of now. You need to extract it via FFmpeg for the same.
hello i wanna make an android music app for that i want my listView which shows all the songs to display album art of that song , artist name , duration and song name
i have succeeded showing all the songs in the listview but unable to display album art etc
so can anyone help me in this??
Thanks in advance
You can use content provider for this.
Hope this code may help you to start up.
final Cursor mCursor = getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
new String[] { MediaStore.Audio.Media.DISPLAY_NAME,
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.ALBUM_ID }, null, null,
"LOWER(" + MediaStore.Audio.Media.TITLE + ") ASC");
int count = mCursor.getCount();
String[] songs = new String[count];
if (mCursor.moveToFirst()) {
do {
String songname = mCursor
.getString(mCursor
.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME));
String sonpath = mCursor.getString(mCursor
.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));
String artistname = mCursor.getString(mCursor
.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST));
String albumid = mCursor
.getString(mCursor
.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM_ID));
} while (mCursor.moveToNext());
Constant.sdCardmusic = allsongs;
}
mCursor.close();
}
If you want to get album picture then you can pass album id getting from above code into below method:
private Bitmap getArtistImage(String albumid) {
Bitmap artwork = null;
try {
Uri sArtworkUri = Uri
.parse("content://media/external/audio/albumart");
Uri uri = ContentUris.withAppendedId(sArtworkUri,
Long.valueOf(albumid));
ContentResolver res = mContext.getContentResolver();
InputStream in = res.openInputStream(uri);
artwork = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Exception", e.toString());
}
return artwork;
}
Google has a great example of a music player for phone , chromecast and AUTO on Github https://github.com/googlesamples/android-UniversalMusicPlayer