Question

I am currently trying to retrieve music files within a specific folder from the ContentResolver. I only want the files in that folder, not from a subfolder. I achieved to get these files by doing this:

String pattern = f.getAbsolutePath() + "/[^/]*"; // f is the folder where I want to search
ArrayList<TrackInfo> retVal = new ArrayList<TrackInfo>();
Cursor mCursor = null;

String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0 AND " + DATA + " LIKE '" + f.getAbsolutePath() + "/%'";

Uri contentUri = Media.getContentUriForPath(Environment.getExternalStorageDirectory().getPath());
String projection[] = new String[]{DATA};

mCursor = context.getContentResolver().query(contentUri, projection, selection, null, DATA);

String data, fileName[];
while(mCursor.moveToNext()){

    data = mCursor.getString(0);        
    if(data.matches(pattern)){
        fileName = data.split("/");

        retVal.add(new TrackInfo(fileName[fileName.length-1], null, data, null, -1, R.drawable.notes, false));
    }           
}

mCursor.close();

This worked out for most cases. But now I seem to have an issue with my pattern. The problem is that if the pattern contains parentheses, data.matches(pattern) always returns false. Examples I tried were:

String pattern1 = "/mnt/somepath/folder(with-parentheses)/[^/]*";
String pattern2 = "/mnt/somepath/folder/[^/]*";

String string1 = "/mnt/somepath/folder(with-parentheses)/test1";
String string2 = "/mnt/somepath/folder/test2";

System.out.println("\"" + string1 + "\"" + ".matches(\"" + pattern1 + "\") = " + string1.matches(pattern1));
System.out.println("\"" + string2 + "\".matches(\"" + pattern2 + "\") = " + string2.matches(pattern2));

The output was:

"/mnt/somepath/folder(with-parentheses)/test1*".matches("/mnt/somepath/folder(with-parentheses)/[^/]*") = false
"/mnt/somepath/folder/test2".matches("/mnt/somepath/folder/[^/]*") = true

My question now is:
Is there a more effective way to get all music files within a folder? - I have already tried to check every file within a folder for a pattern (containing the supported media formats I found here). The problem with that approach is that these formats are only Core Media Formats - the phone may support more than that.
And why is my pattern not working?

Thanks a lot.

Was it helpful?

Solution

(, ) (and many others such as +,*,[,], .) are special characters in regex. Therefore, it is necessary to escape them, i.e. \(, \) in order to specify the literal character.

However, in this case, since you obtain the pattern by concatenating f.getAbsolutePath(), it is strongly recommended that you use Pattern.quote(String) to make all characters in f.getAbsolutePath() literal. It will make sure none of the character are interpreted as special character in regex.

String pattern = Pattern.quote(f.getAbsolutePath()) + "/[^/]*";

(When you print out the pattern after applying Pattern.quote, you may notice that it adds \Q and \E to the original string. It is the way to escape all characters in a long string, supported by Java regex and several other regex flavors).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top