Problems with Android's UriMatcher

喜夏-厌秋 提交于 2019-11-28 19:27:20

There are three rules that aren't well documented but that are crucial to understanding the matching mechanism of UriMatcher:

  1. 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).
  2. Wildcards are applied to one path segment only, meaning * or SDS2MobileDemo/* will never match SDS2MobileDemo/reverse/C_1 but */*/* or */*/C_1 will.
  3. 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    
}
else if ("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    
}    
else if ("*".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.

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.

public static final String PROVIDER ="org.dummy.provider" ;

public static void doTest() 
{
  testUri("content://"+PROVIDER +"/test/reverse/xb32") ; 
  testUri("content://"+PROVIDER +"/JobNames/YES/") ;
}

private static void testUri(String pStr) 
{
    Uri uri = Uri.parse(pStr); 
    Log.w("Test", "uri = " + pStr) ;    
    int result = uriMatcher.match(uri) ;    
    Log.w("Test", "result = " + result) ;  
    List<String> list = uri.getPathSegments() ;   

    for (int i = 0  ; i < list.size() ; i++)
      Log.w("Test", "Segment" + i + " = " + uri.getPathSegments().get(i)) ;   
}

We can use Regex as a look around solution.

Here is the expression

https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?

It should work!

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!