I want to create scanner that is showing only folders that have music in them. i know only how to create query for getting music from path using MediaStore
public static QueryTask buildFileQuery(String path, String[] projection)
{
// It would be better to use selectionArgs to pass path here, but there
// doesn't appear to be any way to pass the * when using it.
StringBuilder selection = new StringBuilder();
selection.append("_data GLOB ");
DatabaseUtils.appendEscapedSQLString(selection, path);
// delete the quotation mark added by the escape method
selection.deleteCharAt(selection.length() - 1);
selection.append("*' AND is_music!=0");
Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
QueryTask result = new QueryTask(media, projection, selection.toString(), null, DEFAULT_SORT);
result.type = TYPE_FILE;
return result;
}
MediaStore.Audio.Media.DATA column contains filepath
Cursor c = getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
new String[]{MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media.DATA},
MediaStore.Audio.Media.IS_MUSIC + "=1",
null,
MediaStore.Audio.Media.DATA
);
if (c.moveToFirst()) {
do {
Log.d("T", c.getString(0) + " -- " + c.getString(1));
} while (c.moveToNext());
}
This should output the following:
Come On -- /storage/emulated/0/Music/The Rolling Stones/More Hot Rocks Big Hits & Fazed Cookies (Disc 2)/10 Come On.mp3
...
Once you have paths you can restore folder hierarchy
Related
I just need the path of folders that contain at least one file that ends with eg. .mp4 or .jpg . I already checked this thread: Android: how to get all folders with photos? but it's too slow for my use case. Is there a faster way to do that?
So I finally found a solution which is way faster than the mentioned above. I got all directories with images within ~100-150ms (around 3k files). In the example below all image files stored either on the internal or external storage gets checked and the parent directory is added to the array list. I excluded .gif and .giff files.
This method also works with videos therefore a few steps are required:
change queryUri to MediaStore.Video.Media.EXTERNAL_CONTENT_URI
change projection to MediaStore.Video.Media.DATA
change 'image/%' in includeImages to 'video/%'
delete + excludeGif from selection
public static ArrayList<String> getImageDirectories(Context mContext) {
ArrayList<String> directories = new ArrayList<>();
ContentResolver contentResolver = mContext.getContentResolver();
Uri queryUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = new String[]{
MediaStore.Images.Media.DATA
};
String includeImages = MediaStore.Images.Media.MIME_TYPE + " LIKE 'image/%' ";
String excludeGif = " AND " + MediaStore.Images.Media.MIME_TYPE + " != 'image/gif' " + " AND " + MediaStore.Images.Media.MIME_TYPE + " != 'image/giff' ";
String selection = includeImages + excludeGif;
Cursor cursor = contentResolver.query(queryUri, projection, selection, null, null);
if (cursor != null && cursor.moveToFirst()) {
do {
String photoUri = cursor.getString(cursor.getColumnIndex(projection[0]));
if(!directories.contains(new File(photoUri).getParent())){
directories.add(new File(photoUri).getParent());
}
} while (cursor.moveToNext());
}
return directories;
}
I want to fetch file data from specific folder using MediaStore Query but returned cursor result is always null.
I have tried using MediaStore query
File file = new File(Environment.getExternalStorageDirectory() + "/myplayer/");
if (file.isDirectory())
{
Uri uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
String[] projection = { MediaStore.Video.Media._ID
MediaStore.Video.Media.DURATION,
MediaStore.Video.Media.DATA,
MediaStore.Video.Media.DISPLAY_NAME,
MediaStore.Video.Media.SIZE, MediaStore.Video.Media.ALBUM
};
String selection = MediaStore.Video.Media.DATA + " like?";
String[] selectionArgs = new String[]{Environment.getExternalStorageDirectory() + "/myplayer/"};
Cursor cursor = ctx.getContentResolver().query(uri, projection, selection, selectionArgs, null);
if ((cursor != null))
{
Log.d("trace cursor", "not null");
Log.d("trace count", "" + cursor.getCount());
}
}
According to following code, the count of cursor is always 0, but there are some video files in myplayer directory.
The problem is in the selection arguments. Append the ‘%’ character at the end, so it is as “myplayer/%”:
new String[]{Environment.getExternalStorageDirectory() + "/myplayer/%"};
This means to select anything that starts with the prefixed path, and has any string after “myplayer/”, which in this case are the file names.
Said that, consider that both the DATA field, and Environment.getExternalStorageDirectory() have been deprecated in Android Q (API 29). Hence, they will not work as expected in such version, and you should already try to find alternatives if you want your code to work in future Android versions, for example to use the BUCKET_DISPLAY_NAME instead.
I basically can not accomplish this for over 2 weeks now.
I have posted a numerous amount of code over a few questions yet most of them got ignored so I won't flood this question with more code of my own that won't even be read.
How do I search the MediaStore with "LIKE" attributes using a String?
E.G. I type in Shoot To Thrill, I receive song ID with this code:
if(cursor.moveToFirst()){
while(cursor.moveToNext()){
String title = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE));
String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));
String id = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media._ID));
test.setText(title +" " + artist + " " + id);
}
}
Here is something to begin with:
String[] projection = {
BaseColumns._ID,
MediaStore.Audio.Artists.ARTIST,
MediaStore.Audio.Media.TITLE
}
Cursor cursor = this.managedQuery(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, //uri
projection, //projection
//i dont know what to enter,
//i dont know what to enter,
MediaStore.Audio.Media.TITLE);
It's just normal SQL hiding behind the scenes. Normal LIKE operations should work just fine. You can use MediaStore.Audio.Media.TITLE + " LIKE \"%thrill%\"" just like any other SQL query.
String[] projection = { BaseColumns._ID,
MediaStore.Audio.Artists.ARTIST, MediaStore.Audio.Media.TITLE };
String where = MediaStore.Audio.Media.TITLE + " LIKE ?";
String[] params = new String[] { "%life%" };
Cursor q = managedQuery(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
projection, where, params, MediaStore.Audio.Media.TITLE);
try {
while (q.moveToNext()) {
Log.e("song", q.getString(1) + " " + q.getString(2));
}
} finally {
q.close();
}
I have set up the cursor but I am still struggling with actually searching it. How do I search for the track name? How do I get its ID so I can pass it to mediaplayer? I have tried different things but didn't succeed.
Basically, I want to know how to search the mediastore for a certain string (string songToPlay in this case), get the results, get the ID of the best match and pass it to my mediaplayer service to play it in the background. The only thing I am asking you is how to get the ID though.
This is the code I am using:
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String[] songToPlay = value.split("play song");
String[] searchWords = songToPlay[1].split(" ");
String [] keywords = null;
StringBuilder where = new StringBuilder();
where.append(MediaStore.Audio.Media.TITLE + " != ''");
String selection = where.toString();
String[] projection = {
BaseColumns._ID,
MediaStore.Audio.Media.MIME_TYPE,
MediaStore.Audio.Artists.ARTIST,
MediaStore.Audio.Albums.ALBUM,
MediaStore.Audio.Media.TITLE
};
for (int i = 0; i < searchWords.length; i++) {
keywords[i] = '%' + MediaStore.Audio.keyFor(searchWords[i]) + '%';
}
Cursor cursor = this.managedQuery(uri, projection, selection, keywords, MediaStore.Audio.Media.TITLE);
if (cursor.moveToFirst()) {
do{
test.setText(cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME)));
}while(cursor.moveToNext());
}
I'm very confused and most of this code is from the internet. I have been trying to do this for 2 days now, that's why I'm asking here. I've done hours of trying by myself.
edit: Current code. How am I supposed to find the location - music ID or whatever I need to play that song from the cursor?
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String songToPlay = value.replaceAll("play song", "").trim();
int music_column_index;
String[] projection = {
MediaStore.Audio.Media._ID,
MediaStore.Audio.Artists.ARTIST,
MediaStore.Audio.Albums.ALBUM,
MediaStore.Audio.Media.TITLE
};
#SuppressWarnings("deprecation")
Cursor cursor = this.managedQuery(uri,
null,
MediaStore.Audio.Media.TITLE + "=?",
new String[]{songToPlay},
MediaStore.Audio.Media.TITLE + " ASC");
This will search the MediaStore for all songs with title equal to the value of your songToPlay string.
Cursor cursor = getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
null,
MediaStore.Audio.Media.TITLE + "=?",
new String[]{songToPlay},
MediaStore.Audio.Media.TITLE + " ASC");
You can then of course query the cursor to get the ID (and any other column) of any results.
while (cursor.moveToNext()) {
String path = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
long id = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media._ID));
// Whatever else you need
}
However this will require an exact match, you may like to use the LIKE operator for a more fuzzy match.
I am trying to use a cursor with a managed query to filter media content on the device
String[] dirs = new String[] {"%"+ dir + "%"};
String[] musicdata = { BaseColumns._ID,
MediaColumns.DATA,
MediaColumns.DISPLAY_NAME,
MediaColumns.SIZE };
musiccursor = getActivity().getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
musicdata,
MediaColumns.DATA + " like ? ",
dirs,
MediaColumns.DATA + " asc");
The where clause of the query uses a directory that is passed to it in order to filter for music within that folder and sub folders.
What I would like to do is also include a "not like" within the same query.
The reason for doing this is that the user has the ability to exclude a folder from a list view, and that is stored in an array and written to a file in order to retain the selection. I would like the cursor query to take these exclusions into account whilst still being linked to the folder that they pass through to it.
Thanks in advance!
In answer to my own query, here is the code:
//Build the where clause
StringBuilder where = new StringBuilder();
//first add in all values from the exclusion array
for (int i = 0; i < excludedFolders.size(); i++) {
where.append(MediaColumns.DATA + " not like ? ");
where.append(" AND ");
}
//then add in the final like clause, e.g. the folder the user selected
where.append(MediaColumns.DATA + " like ? ");
//convert it to a string
String selection = where.toString();
System.out.println(selection);
////////////////////////////////////////////////////////////////////////////////////////////
//Build the arguments. the array is set to the size of the exlcusion list, plus 1 for the fodler selected
String[] dirs = new String[excludedFolders.size()+1];
System.out.println(excludedFolders.size()+1);
//first add in a value for each excluded folder
for (int i = 0; i < excludedFolders.size(); i++) {
dirs[i] = "%" + excludedFolders.get(i) + "%";
System.out.println(i + " " + dirs[i]);
}
//add the argument value for the like element of the query
dirs[excludedFolders.size()]="%"+ dir + "%";
System.out.println("excludedFolders.size() " + dirs[excludedFolders.size()]);
//start building the cursor
String[] musicdata = { BaseColumns._ID,
MediaColumns.DATA,
MediaColumns.DISPLAY_NAME,
MediaColumns.SIZE };
//run the query
musiccursor = getActivity().getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
musicdata,
selection,
dirs,
MediaColumns.DATA+ " asc");
//done