Problems With Android's Urimatcher
Solution 1:
There are three rules that aren't well documented but that are crucial to understanding the matching mechanism of UriMatcher:
- UriMatcher tries to match the entire Uri against the pattern. Much like the matches() method of java.util.regex.Matcher that returns true only if the entire region sequence matches the matcher's pattern (compared to the find() method that returns true for partial matches).
- Wildcards are applied to one path segment only, meaning * or SDS2MobileDemo/* will never match SDS2MobileDemo/reverse/C_1 but */*/* or */*/C_1 will.
- Once it finds a match for a path segment it won't find any alternative match for that particular path segment.
Here are some examples using the following url: content://dsndata.sds2mobile.jobprovider/SDS2MobileDemo/reverse/C_1
The first two rules are easy to understand:
- SDS2MobileDemo/*/* will match
- */reverse/* will match
- */* won't match because it matches only two path segments
- SDS2MobileDemo won't match because it matches only one path segment
The third rule is a little harder to understand. If you add the following Uris in this exact order:
- */wrong/C_1
- SDS2MobileDemo/reverse/C_1
then it won't find a match because that translates into the following (pseudo) code:
if ("*".matches("SDS2MobileDemo")) {
// tries to match the other parts but fails
}
elseif ("SDS2MobileDemo".matches("SDS2MobileDemo")) {
// will never be executed
}
If you reverse the order the (pseudo) code becomes:
if ("SDS2MobileDemo".matches("SDS2MobileDemo")) {
// tries to match the other parts and succeeds
}
elseif ("*".matches("SDS2MobileDemo")) {
// will never be executed
}
Now as far as the original question goes. SDS2MobileDemo/reverse/C_1 will get matched by */reverse/* but not e.g. JobNames/reverse/C_1 because that one will go down the JobNames/* path... Also it's clear that moving */reverse/* to the top isn't the solution because all other patterns not starting with * won't match any more. There's really no telling what the correct solution is as long as it's unknown which patterns should match which Uris.
Solution 2:
Hum .... Ah typo ? Seems there is some whitespace after /reverse/
uriMatcher.addURI(JobMetaData.AUTHORITY, "*/reverse/*", REVERSE_URI);
should work
EDIT
The example below works, try with your values and check your LogCat Window for warnings
Check the value in JobMetaData.AUTHORITY.
publicstaticfinalStringPROVIDER="org.dummy.provider" ;
publicstaticvoiddoTest()
{
testUri("content://"+PROVIDER +"/test/reverse/xb32") ;
testUri("content://"+PROVIDER +"/JobNames/YES/") ;
}
privatestaticvoidtestUri(String pStr)
{
Uriuri= Uri.parse(pStr);
Log.w("Test", "uri = " + pStr) ;
intresult= uriMatcher.match(uri) ;
Log.w("Test", "result = " + result) ;
List<String> list = uri.getPathSegments() ;
for (inti=0 ; i < list.size() ; i++)
Log.w("Test", "Segment" + i + " = " + uri.getPathSegments().get(i)) ;
}
Solution 3:
We can use Regex as a look around solution.
Here is the expression
https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?
It should work!
Solution 4:
I just ran into a UriMatcher problem and solved it. Make sure that you always put wild cards exact matches. If you don', the UriMatcher code goes down the wildcard path and doesn't go back up if it chose the wrong path.
Unfortunately, I don't see exactly what's wrong in your case. I would try moving JOBNAME_COLLECTION_URI to the very top or removing it; I wonder if that's causing a problem.
Post a Comment for "Problems With Android's Urimatcher"