Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Problemas con el UriMatcher de Android

En una respuesta a una pregunta anterior de la mía, alguien indicó que hay algo flakiness (por falta de una palabra mejor) inherente a la clase de UriMatcher de Android. ¿Puede alguien señalar los problemas conocidos con UriMatcher? Estoy diseñando un proveedor de contenido que se basa en UriMatcher para que coincida con mi Uris correctamente (en lugar de incorrectamente supongo). ¿Hay soluciones a los problemas conocidos? ¿O hay una mejor estrategia para emparejar Uris?

Ejemplo:

  • ¿Cuál es la diferencia entre contentprovider y contentResolver en android
  • Custom ContentProvider - openInputStream (), openOutputStream ()
  • El contenido de Android contentprovider lleva mucho tiempo
  • ¿Cómo puedo capturar el proveedor de contenido inicializar?
  • ¿Por qué / debemos implementar BaseColumns cuando se utiliza un proveedor de contenido en Android?
  • Ejemplos de proveedores de contenido que no utilizan SQLite
  • Aquí está el código de configuración de mi UriMatcher

    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); } 

    Añadir otro Uri:

     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); } 

    Y el uri pasado no se reconoce con: uriMatcher.match (uri)

    En la pregunta anterior (mencionada anteriormente) se recomendó mover el Uri ofensivo a la parte superior de las llamadas a UriMatcher.put (String, int). Eso resolvió el problema anterior (y me dejó con un mal sabor en mi boca). Al intentar la misma solución con este código, el primer Uri actual (JOBNAME_SINGLE_URI) no se reconocerá. Estoy bastante seguro de que el problema no está en mi código (he logrado crear un ContentProvider de trabajo utilizando Uris y depurar todos los problemas con ellos antes de este problema), sino más bien es un problema con Uri coincidencia en Android .

    ACTUALIZAR:

     public final static String AUTHORITY = "dsndata.sds2mobile.jobprovider"; 

    Muestra Uri:
    Content: //dsndata.sds2mobile.jobprovider/SDS2MobileDemo/reverse/C_1

  • Redibujar / refrescar Itemizedoverlay? (Android / google maps api)
  • ¿Cómo configurar el fondo de la aplicación Android?
  • Eclipse Juno no creará actividad de Android
  • Fragmentos retenidos con IU y fugas de memoria
  • Android comunicación entre dos aplicaciones
  • FindViewById en DialogFragment - NullPointerException
  • 4 Solutions collect form web for “Problemas con el UriMatcher de Android”

    Hay tres reglas que no están bien documentadas pero que son cruciales para entender el mecanismo de coincidencia de UriMatcher:

    1. UriMatcher intenta igualar el Uri completo contra el patrón. Al igual que el método matches () de java.util.regex.Matcher que devuelve true sólo si la secuencia de la región completa coincide con el patrón del matcher (comparado con el método find () que devuelve true para las coincidencias parciales).
    2. Los comodines se aplican a un solo segmento de ruta, lo que significa que * o SDS2MobileDemo / * nunca coincidirán con SDS2MobileDemo / reverse / C_1 pero * / * / * o * / * / C_1.
    3. Una vez que encuentra una coincidencia para un segmento de ruta, no encontrará ninguna coincidencia alternativa para ese segmento de trayecto en particular.

    Estos son algunos ejemplos de uso de la url siguiente: content: //dsndata.sds2mobile.jobprovider/SDS2MobileDemo/reverse/C_1

    Las dos primeras reglas son fáciles de entender:

    • SDS2MobileDemo / * / * coincidirá
    • * / Reverse / * coincidirá
    • * / * No coincidirá porque sólo coincide con dos segmentos de ruta
    • SDS2MobileDemo no coincidirá porque sólo coincide con un segmento de ruta

    La tercera regla es un poco más difícil de entender. Si agrega los siguientes Uris en este orden exacto:

    • * / Wrong / C_1
    • SDS2MobileDemo / reverse / C_1

    Entonces no encontrará una coincidencia porque eso se traduce en el siguiente código (pseudo):

     if ("*".matches("SDS2MobileDemo")) { // tries to match the other parts but fails } else if ("SDS2MobileDemo".matches("SDS2MobileDemo")) { // will never be executed } 

    Si invierte el orden, el código (pseudo) se convierte en:

     if ("SDS2MobileDemo".matches("SDS2MobileDemo")) { // tries to match the other parts and succeeds } else if ("*".matches("SDS2MobileDemo")) { // will never be executed } 

    Ahora en cuanto a la pregunta original va. SDS2MobileDemo / reverse / C_1 obtendrá emparejado por * / reverse / * pero no por ejemplo JobNames / reverse / C_1 porque ese uno bajará por la ruta JobNames / * … También está claro que mover * / reverse / * a la parte superior isn 'T la solución porque todos los otros patrones que no comienzan con * no coincidirá con más. No hay realmente decir cuál es la solución correcta, siempre y cuando se desconoce qué patrones deben coincidir con que Uris.

    Hum …. Ah typo? Parece que hay algunos espacios en blanco después de / reverse /

     uriMatcher.addURI(JobMetaData.AUTHORITY, "*/reverse/*", REVERSE_URI); 

    Deberia trabajar

    EDITAR

    El ejemplo siguiente funciona, intente con sus valores y verifique la ventana de LogCat para ver las advertencias

    Compruebe el valor en 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)) ; } 

    Podemos usar Regex como una solución alrededor de la solución.

    Aquí está la expresión

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

    ¡Deberia de funcionar!

    Me encontré con un problema de UriMatcher y lo resolví. Asegúrese de que siempre poner comodines coincidencias exactas. Si no lo hace, el código de UriMatcher desciende por la ruta de comodín y no retrocede si elige la ruta incorrecta.

    Desafortunadamente, no veo exactamente lo que está mal en su caso. Intentaría mover JOBNAME_COLLECTION_URI a la parte superior o eliminarlo; Me pregunto si eso está causando un problema.

    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.