title: Problems with Android's UriMatcher
body: <p>In an answer to a previous question of mine someone indicated that there is some flakiness (for lack of a better word) inherent in the Android class UriMatcher. Can anyone pinpoint the known issues with UriMatcher? I'm designing a Content Provider that relies on UriMatcher to match my Uris correctly (as opposed to incorrectly I suppose). Are there workarounds to the known issues? Or is there a better strategy for matching Uris? </p>
  
  <p>Example:</p>
  
  <p>Here is the code setting my UriMatcher</p>
  
  <pre><code>private static final int MEMBER_COLLECTION_URI = 1;
  private static final int MEMBER_SINGLE_URI = 2;
  private static final int SUBMATERIAL_COLLECTION_URI = 3;
  private static final int SUBMATERIAL_SINGLE_URI = 4;
  private static final int JOBNAME_COLLECTION_URI = 5;
  private static final int JOBNAME_SINGLE_URI = 6;
  private static final int ALL_MEMBERS_URI = 7;
  private static final int ALL_SUBMATERIAL_URI = 8;
  
  static
  {
          //return the job and fab for anything matching the provided jobName
          // JobNames/jobName
          uriMatcher.addURI(JobMetaData.AUTHORITY, "JobNames/*/",
                            JOBNAME_SINGLE_URI);
          //return a collection of members
          // jobName/member/attribute/value
          uriMatcher.addURI(JobMetaData.AUTHORITY, "*/member/*/*/",
                            MEMBER_COLLECTION_URI);
          //return a single member
          // jobName/member/memberNumber
          uriMatcher.addURI(JobMetaData.AUTHORITY, "*/member/*/",
                            MEMBER_SINGLE_URI);
          //return a collection of submaterial
          // jobName/submaterial/attribute/value
          uriMatcher.addURI(JobMetaData.AUTHORITY, "*/submaterial/*/*",
                            SUBMATERIAL_COLLECTION_URI);
          //return a single piece of submaterial
          // jobName/submaterial/GUID
          //GUID is the only way to uniquely identify a piece of submaterial    
          uriMatcher.addURI(JobMetaData.AUTHORITY, "*/submaterial/*",
                            SUBMATERIAL_SINGLE_URI);
          //Return everything in the member and submaterial tables
          //that has the provided attribute that matches the provided value
          // jobName/attribute/value
          //not currently used
          uriMatcher.addURI(JobMetaData.AUTHORITY, "JobNames/",
                            JOBNAME_COLLECTION_URI);
          //return all members in a job
          uriMatcher.addURI(JobMetaData.AUTHORITY, "*/members/",
                            ALL_MEMBERS_URI);
  
  }
  </code></pre>
  
  <p>Add another Uri:</p>
  
  <pre><code>private static final int MEMBER_COLLECTION_URI = 1;
  private static final int MEMBER_SINGLE_URI = 2;
  private static final int SUBMATERIAL_COLLECTION_URI = 3;
  private static final int SUBMATERIAL_SINGLE_URI = 4;
  private static final int JOBNAME_COLLECTION_URI = 5;
  private static final int JOBNAME_SINGLE_URI = 6;
  private static final int ALL_MEMBERS_URI = 7;
  private static final int ALL_SUBMATERIAL_URI = 8;
  //ADDITIONAL URI
  private static final int REVERSE_URI = 9;
  
  static
  {
          //return the job and fab for anything matching the provided jobName
          // JobNames/jobName
          uriMatcher.addURI(JobMetaData.AUTHORITY, "JobNames/*/",
                            JOBNAME_SINGLE_URI);
          //return a collection of members
          // jobName/member/attribute/value
          uriMatcher.addURI(JobMetaData.AUTHORITY, "*/member/*/*/",
                            MEMBER_COLLECTION_URI);
          //return a single member
          // jobName/member/memberNumber
          uriMatcher.addURI(JobMetaData.AUTHORITY, "*/member/*/",
                            MEMBER_SINGLE_URI);
          //return a collection of submaterial
          // jobName/submaterial/attribute/value
          uriMatcher.addURI(JobMetaData.AUTHORITY, "*/submaterial/*/*",
                            SUBMATERIAL_COLLECTION_URI);
          //return a single piece of submaterial
          // jobName/submaterial/GUID
          //GUID is the only way to uniquely identify a piece of submaterial    
          uriMatcher.addURI(JobMetaData.AUTHORITY, "*/submaterial/*",
                            SUBMATERIAL_SINGLE_URI);
          //Return everything in the member and submaterial tables
          //that has the provided attribute that matches the provided value
          // jobName/attribute/value
          //not currently used
          uriMatcher.addURI(JobMetaData.AUTHORITY, "JobNames/",
                            JOBNAME_COLLECTION_URI);
          //return all members in a job
          uriMatcher.addURI(JobMetaData.AUTHORITY, "*/members/",
                            ALL_MEMBERS_URI);
          //ADDITIONAL URI
          uriMatcher.addURI(JobMetaData.AUTHORITY, "*/reverse/*",
                            REVERSE_URI);
  
  }
  </code></pre>
  
  <p>And the last Uri is not recognized using:
      uriMatcher.match(uri)</p>
  
  <p>On the previous question (mentioned earlier) it was recommended that I move the offending Uri to the top of the calls to UriMatcher.put(String, int). That solved the previous problem (and left me with a bad taste in my mouth). Trying the same solution with this code results in the current first Uri (JOBNAME_SINGLE_URI) going unrecognized. I'm fairly sure that the issue isn't in my code (I've managed to create a working ContentProvider utilizing Uris and debug all of the problems with them prior to this issue), but rather is an issue with Uri matching in Android.</p>
  
  <p>UPDATE: </p>
  
  <pre><code>public final static String AUTHORITY = "dsndata.sds2mobile.jobprovider";
  </code></pre>
  
  <p>Sample Uri:<br>
      content://dsndata.sds2mobile.jobprovider/SDS2MobileDemo/reverse/C_1</p>