Java – manually add songs to mediastore as music tracks
I want to create a music player that can download songs online and add them to the mediastore I am using the download manager and allow mediascanner to scan this file when the download is complete
DownloadManager.Request request .... request.allowScanningByMediaScanner(); ... downloadManager.enqueue(request);
It works well in Android 5.0 and later However, this song is downloaded using the codec (OPUS), which does not support the lollipop version of Android, so mediascanner will not add this file to mediastore
This is my problem. My app can play opus codec, but after downloading, the song in mediastore does not exist, so my app can't find this song
How to force mediascanner to add downloaded files to mediastore Audio as music track If not, how can I manually add this song to mediastore After audio download:
public class BroadcastDownloadComplete extends BroadcastReceiver { @Override public void onReceive(Context context,Intent intent) { if (intent.getAction().equals("android.intent.action.DOWNLOAD_COMPLETE")) { //addSongToMediaStore(intent); } } }
Solution
From the source code here, we can see that the final implementation of the scanner has two steps to scan audio files If one of these two steps fails, the audio file will not be inserted into the media provider
Step 1 check the file extension
static bool FileHasAcceptableExtension(const char *extension) { static const char *kValidExtensions[] = { ".mp3",".mp4",".m4a",".3gp",".3gpp",".3g2",".3gpp2",".mpeg",".ogg",".mid",".smf",".imy",".wma",".aac",".wav",".amr",".midi",".xmf",".rtttl",".rtx",".ota",".mkv",".mka",".webm",".ts",".fl",".flac",".mxmf",".avi",".mpg" }; static const size_t kNumValidExtensions = sizeof(kValidExtensions) / sizeof(kValidExtensions[0]); for (size_t i = 0; i < kNumValidExtensions; ++i) { if (!strcasecmp(extension,kValidExtensions[i])) { return true; } } return false; }
Since Android 5.0, more extensions have been added The general container of Opus codec is Ogg, which existed before Android 5.0 Assuming your audio file extension is Ogg, the scanning process is very good in this step
Step 2 retrieve metadata
After the first step is passed, the scanner needs to retrieve the metadata of the media for later database insertion I think the scanner performs a codec level check at this step
sp<MediaMetadataRetriever> mRetriever(new MediaMetadataRetriever); int fd = open(path,O_RDONLY | O_LARGEFILE); status_t status; if (fd < 0) { // Couldn't open it locally,maybe the media server can? status = mRetriever->setDataSource(path); } else { status = mRetriever->setDataSource(fd,0x7ffffffffffffffL); close(fd); } if (status) { return MEDIA_SCAN_RESULT_ERROR; }
For Android versions before 5.0, the scanner may fail in this step Due to the lack of built - in opus codec support, setdatasource will eventually fail Media files will not eventually be added to the media provider
Suggested solution
Because we know that audio files will be added to
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
We can operate the database manually If you want the audio file to be consistent with other audio files in the database, you must retrieve all metadata yourself Since you can play opus files, I think it's easy to retrieve metadata
// retrieve more Metadata,duration etc. ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.Audio.AudioColumns.DATA,"/mnt/sdcard/Music/example.opus"); contentValues.put(MediaStore.Audio.AudioColumns.TITLE,"Example track"); contentValues.put(MediaStore.Audio.AudioColumns.DISPLAY_NAME,"example"); // more columns should be filled from here Uri uri = getContentResolver().insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,contentValues); Log.d(TAG,uri.toString());
After that, your application can find the audio file
getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI...