Getting all MP3 files on the external card - android

What i'm trying to achieve is getting all the mp3 files'URL and Title in an arraylist to return it. All from the folder: /ext_card/Music/ and all subfolders.
the options i've explored all seem to get stuck, and all the answers i've looked up on the internet point to mediastore, but i have no idea how to use it
And don't give me the RTFM bullshit, because the explanations i've found for mediastore is retarded at best.
SO can anyone please help me out or give me an example of a simple working mediastore query for all mp3 files?

Use this it will help you to get all MP3 Song from SD CARD
private static ArrayList<genericSongClass> songs = null;
public void BindAllSongs() {
/** Making custom drawable */
String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0";
final String[] projection = new String[] {
MediaStore.Audio.Media.DISPLAY_NAME,
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.DATA};
final String sortOrder = MediaStore.Audio.AudioColumns.TITLE
+ " COLLATE LOCALIZED ASC";
try {
// the uri of the table that we want to query
Uri uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
// query the db
cursor = getBaseContext().getContentResolver().query(uri,
projection, selection, null, sortOrder);
if (cursor != null) {
songs = new ArrayList<genericSongClass>(cursor.getCount());
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
GSC = new genericSongClass();
GSC.songTitle = cursor.getString(0);
GSC.songArtist = cursor.getString(1);
GSC.songData = cursor.getString(2);
songs.add(GSC);
cursor.moveToNext();
}
}
} catch (Exception ex) {
} finally {
if (cursor != null) {
cursor.close();
}
}
}
public class genericSongClass {
String songTitle = "";
String songArtist = "";
String songData = "";
String isChecked = "false";
}

Here is a recursive way to do such thing,
getMp3s(Arraylist<File> list, File dir){
File[] files = dir.listFiles();
for(File file : files){
if(file.isDirectory()){
getMp3s(list, file);
}else{
//add mp3s to list here
}
}
}

Related

MediaStore.Files.FileColumns.DATA deprecated, how fix this?

I would like to replace function below because DATA is deprecated
It's necessary to list only path in the base directory
If I using "MediaStore.Files.FileColumns._ID", I can return Uri Lists, but I lost external storage path
The goal is to open the PDF viewer on a PDF file that is in "Documents" (in external storage)
Can you help me please?
public static Vector<String> getFilesListInExternalStorage(Context context, String mimeType, String baseDirectory) {
Vector<String> list = new Vector<>();
Uri collection;
String selection = "";
String[] selectionArgs = {""};
final String[] projection = new String[]{
MediaStore.Files.FileColumns.DISPLAY_NAME,
MediaStore.Files.FileColumns.DATE_ADDED,
MediaStore.Files.FileColumns.DATA,
MediaStore.Files.FileColumns.MIME_TYPE,
};
final String sortOrder = MediaStore.Files.FileColumns.DATE_ADDED + " DESC";
if(baseDirectory==null || baseDirectory.isEmpty())
{
selection = MediaStore.Files.FileColumns.MIME_TYPE + " = ?";
selectionArgs = new String[]{mimeType};
}
else
{
selection = MediaStore.Files.FileColumns.MIME_TYPE + " = ? AND "+ MediaStore.Files.FileColumns.DATA + " like ? ";
selectionArgs = new String[]{mimeType, "%"+baseDirectory+"%"};
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
collection = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL);
}else{
collection = MediaStore.Files.getContentUri("external");
}
try (Cursor cursor = Objects.requireNonNull(context).getContentResolver().query(collection, projection, selection, selectionArgs, sortOrder)) {
assert cursor != null;
if (cursor.moveToFirst()) {
int columnData = cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA);
do {
list.add((cursor.getString(columnData)));
} while (cursor.moveToNext());
}
}
return list;
}
Thank you very much
Have a nice day
Loïc
try (Cursor cursor = context.getContentResolver().query(collection, Constants.FILE_PROJECTION, sb.toString(), strArr2, sort)) {
if (cursor.moveToFirst()) {
int columnData = cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA);
do {
String path = cursor.getString(columnData);
File file = new File(path);
if (file.exists()) {
fileList.add(new File(cursor.getString(columnData)));
}
} while (cursor.moveToNext());
cursor.close();
}
}
return fileList;
try this

How can I get Uri of a private Folder in Android?

I am trying to make an android camera app with image gallery. The images captured are saved to a private directory: Android/data/com.example.newcamera/files/pictures.
Whenever I am using INTERNAL_CONTENT_URI or, EXTERNAL_CONTENT_URI as Uri, The app is bringing all the public pictures of my phone but not the one in the private directory. But I need only those with private directory. How can I get it? Please help me. My code snippet is as follows:
Thanks in advance.
protected String doInBackground(String... args) {
String xml = "";
String path = null;
String album = null;
String timestamp = null;
String countPhoto = null;
Uri uriInternal = MediaStore.Images.Media.INTERNAL_CONTENT_URI;
Uri uriExternal = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Uri myUri = Uri.fromFile(new File(getApplicationContext().getFilesDir().getAbsolutePath()));
String[] projection = { MediaStore.MediaColumns.DATA,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME, MediaStore.MediaColumns.DATE_MODIFIED };
Cursor cursorExternal = getContentResolver().query(uriExternal, projection, "_data IS NOT NULL) GROUP BY (bucket_display_name",
null, null);
Cursor cursorInternal = getContentResolver().query(uriInternal, projection, "_data IS NOT NULL) GROUP BY (bucket_display_name",
null, null);
Cursor myCursor = getContentResolver().query(myUri, projection, "_data IS NOT NULL) GROUP BY (bucket_display_name",
null, null);
Cursor cursor = new MergeCursor(new Cursor[]{cursorExternal, cursorInternal, myCursor});
while (cursor.moveToNext()) {
path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA));
album = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME));
timestamp = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATE_MODIFIED));
countPhoto = Function.getCount(getApplicationContext(), album);
albumList.add(Function.mappingInbox(album, path, timestamp, Function.converToTime(timestamp), countPhoto));
}
cursor.close();
Collections.sort(albumList, new MapComparator(Function.KEY_TIMESTAMP, "dsc")); // Arranging photo album by timestamp decending
return xml;
}
You can fetch your files from particular folder by:
File folder = new File(Environment.getExternalStorageDirectory().toString() + "/Folder Name/");
folder.mkdirs();
File[] allFiles = folder.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return (name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".png"));
}
});
You can convert file path to Uri by Uri.fromFile(YOUR FILE)

How to delete image file from Android Internal when path is stored in SQLite DB

I Know this is already answered question.But I'm unable to figure it out when using SQLite DB. My app captures some documents and will be stores in phone memory. I'm using SQLite DB in my app which stores the path of the above image. How can i delete the image from phone memory if i delete the image in SQLite DB.
String photoPath = cursor.getString(i_COL_PICTURE);
--My path is
`"content://com.google.android.apps.photos.contentprovider/-1/1/content%3A%2F%2Fmedia%2Fexternal%2Fimages%2Fmedia%2F153/ORIGINAL/NONE/1743496576"
`
When you want delete some file in your storage, Just do this.
File file = new File(yourFilePathHere);
deleted = file.delete();
I am considering you have required permissions because you are able to write files in storage.
Edit
You are using MediaStore for getting images. So now when you want delete file you should delete file from MediaStore also. I have a method which will help you.
public static int deleteFileFromMediaStore(final ContentResolver contentResolver, final File file) {
String canonicalPath;
try {
canonicalPath = file.getCanonicalPath();
} catch (IOException e) {
canonicalPath = file.getAbsolutePath();
}
final Uri uri = MediaStore.Files.getContentUri("external");
final int result = contentResolver.delete(uri,
MediaStore.Files.FileColumns.DATA + "=?", new String[]{canonicalPath});
if (result == 0) {
final String absolutePath = file.getAbsolutePath();
if (!absolutePath.equals(canonicalPath)) {
int deletedRow = contentResolver.delete(uri,
MediaStore.Files.FileColumns.DATA + "=?", new String[]{absolutePath});
return deletedRow;
}
} else return result;
return result;
}
Call it in your Activity like
deleteFileFromMediaStore(getContentResolver(), fileToDelete)
Note Check if you are getting absolute path by MediaStore. Here is my method to get all gallery images if you have problem with your code.
public static ArrayList<ModelBucket> getImageBuckets(Context context) {
ArrayList<ModelBucket> list = new ArrayList<>();
String absolutePathOfImage;
String absoluteFolder;
boolean same_folder = false;
int pos = 0;
Uri uri;
Cursor cursor;
int column_index_data, column_index_folder_name;
uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.MediaColumns.DATA, MediaStore.Images.Media.BUCKET_DISPLAY_NAME};
final String orderBy = MediaStore.Images.Media.DATE_TAKEN;
cursor = context.getContentResolver().query(uri, projection, null, null, orderBy + " DESC");
if (cursor == null) return null;
column_index_data = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
column_index_folder_name = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
while (cursor.moveToNext()) {
absolutePathOfImage = cursor.getString(column_index_data);
absoluteFolder = cursor.getString(column_index_folder_name);
Log.d("Column", absolutePathOfImage);
Log.d("Folder", absoluteFolder);
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getFolderName().equals(absoluteFolder)) {
same_folder = true;
pos = i;
break;
} else {
same_folder = false;
}
}
if (same_folder) {
ArrayList<String> al_path = new ArrayList<>(list.get(pos).getAllFilesPath());
al_path.add(absolutePathOfImage);
list.get(pos).setAllFilesPath(al_path);
} else {
ArrayList<String> al_path = new ArrayList<>();
al_path.add(absolutePathOfImage);
ModelBucket modelBucket = new ModelBucket();
modelBucket.setFolderName(absoluteFolder);
modelBucket.setAllFilesPath(al_path);
list.add(modelBucket);
}
}
return list;
}
here ModelBucket.class is a model class.
public class ModelBucket {
String folderName;
ArrayList<String> allFilesPath;
ArrayList<ModelFile> files;
// make getter setter
}
before deleting the image get the path of the image and pass the path to below code
File fdelete = new File(path);
if (fdelete.exists()) {
if (fdelete.delete()) {
System.out.println("file Deleted :" + path);
} else {
System.out.println("file not Deleted :" + path);
}
}
after this remove the path from sqlite db
If you have your Uri pointing to the file you can do :
String pathToFile = myUri.getEncodedPath(); // this gives your the real path to the file, like /emulated/0/sdcard/myImageFile.jpg
File file = new File(pathToFile);
if(file.exists()){
file.delete();
}

How to get the date when an image was taken from MediaStore if I have the file path?

I know that I can retrieve the id of image using the following code:
String[] projection = { MediaStore.Images.Media._ID };
String selection = MediaStore.Images.Media.DATA + " = ?";
String[] selectionArgs = new String[] { mediaFile.mediaFile().getAbsolutePath() };
Uri queryUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
ContentResolver contentResolver = context.getContentResolver();
Cursor cursor = contentResolver.query(queryUri, projection, selection, selectionArgs, null);
if(cursor!=null) {
if (cursor.moveToFirst()) {
long id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID));
}
cursor.close();
}
I wonder, if there is any possible way to MediaStore.Images.Media.DATA_TAKEN, MediaStore.Images.Media.LONGITUDE, andMediaStore.Images.Media.LATITUDE using the same approach?
Provided you have the file path, you can get the date this way:
File file = new File(filePath);
if(file.exists()) //Extra check, Just to validate the given path
{
Date lastModDate = new Date(file.lastModified());
Log.i("Dated : "+ lastModDate.toString());//Dispaly lastModDate. You can do/use it your own way
}
An alternative option to find this would be from the EXIF data of the image, if its available:
ExifInterface intf = null;
try
{
intf = new ExifInterface(path);
}
catch(IOException e)
{
e.printStackTrace();
}
if(intf != null)
{
String dateString = intf.getAttribute(ExifInterface.TAG_DATETIME);
Log.i("Dated : "+ dateString.toString()); //Dispaly dateString. You can do/use it your own way
}

Perform slow task on lots of data in RecyclerView

I am building a music player that gets the BPM ID3v2 tag from all mp3 files on a device and allows sorting and filtering by BPM. To get the tag, I am using the mp3agic library. It turns out that this tag fetching takes some time for each song, and performing the fetch when adding each song to my list of songs renders the player without function for a while. I am not sure if I should use an AsyncTask on the entire list when it is done building or an AsyncTask for each item to retrieve its BPM and insert it into the song or even using some other, faster method of getting the BPM value. Can anyone offer any guidance?
Here is my code to get the BPM:
public int getBpmFromId(long id) {
int bpm = -1;
Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, Long.toString(id));
try {
Mp3File file = new Mp3File(getRealPathFromURI(getApplicationContext(), uri));
if(file.hasId3v2Tag()) {
ID3v2 id3v2Tag = file.getId3v2Tag();
bpm = id3v2Tag.getBPM();
Log.d("MP3AGIC", "Got BPM for track: " + id + ": " + bpm);
}
} catch (Exception e) {
e.printStackTrace();
}
return bpm;
}
and here is the code I am using to build my list of songs:
public void getSongList() {
ContentResolver musicResolver = getContentResolver();
Uri musicUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String selectionMimeType = MediaStore.Files.FileColumns.MIME_TYPE + "=?";
String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0 AND " + selectionMimeType;
String sortOrder = null;
String[] projection = null;
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("mp3");
String[] selectionArgsMp3 = new String[] { mimeType };
Cursor musicCursor = musicResolver.query(musicUri, projection, selection, selectionArgsMp3, sortOrder);
if(musicCursor != null && musicCursor.moveToFirst()) {
int idColumn = musicCursor.getColumnIndex(MediaStore.Audio.Media._ID);
int titleColumn = musicCursor.getColumnIndex(MediaStore.Audio.Media.TITLE);
int artistColumn = musicCursor.getColumnIndex(MediaStore.Audio.Media.ARTIST);
do {
long id = musicCursor.getLong(idColumn);
String title = musicCursor.getString(titleColumn);
String artist = musicCursor.getString(artistColumn);
//bpm processing
int bpm = getBpmFromId(id);
songList.add(new Song(id, title, artist));
} while (musicCursor.moveToNext());
}
if(musicCursor != null)
musicCursor.close();
}
EDIT: It seems that what might be taking so long is getting the file path from the Uri, which is done in this method:
public String getRealPathFromURI(Context context, Uri contentUri) {
Cursor cursor = null;
try {
String[] proj = { MediaStore.Images.Media.DATA };
cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} finally {
if (cursor != null) {
cursor.close();
}
}
}
I'm not sure how, or if I can, optimize this.
The decision to use one asynctask for the entire list or use the list as a queue for many asynctasks depends on your desire for concurrency.
If you plan to parallelize the tag-getting, then use multiple asynctasks (this would be good if the operation involves a lot of disk IO rather than CPU time).
Otherwise if you plan to execute them in sequence, then you should use only one asynctask. There is no need to create, then destroy tens/hundreds of background threads. This is inefficient.

Categories

Resources