java - studio - Android-Tener autoridad de proveedor en el proyecto de la aplicación
contentprovider (2)
Un proyecto de biblioteca de Android contiene algunos proveedores cuya autoridad se define como la siguiente en una clase de contrato:
public static final String CONTENT_AUTHORITY = "my.com.library.providers.tester";
private static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);
Ahora hay muchos proyectos de aplicaciones que usan este proyecto de biblioteca. El problema que tengo actualmente es que para cada proyecto de aplicación, necesito tener una sucursal separada en el proyecto de la biblioteca para cada aplicación solo por tener una autoridad de contenido única. Esto está creando algunos problemas de administración de la versión (como propagar características / correcciones de errores de una rama a otra rama, etc.). En su lugar, me gustaría delegar la responsabilidad de definir la autoridad de contenido al proyecto de la aplicación. ¿Hay alguna manera de lograr esto?
La aplicación es la única que absolutamente necesita saber acerca de la autoridad, ya que es la que declara el <provider>
en el manifiesto con el atributo android:authorities
.
Por lo tanto, en principio, debería "simplemente funcionar", siempre que elimine toda la lógica específica de la autoridad del proveedor, como por ejemplo:
- esos miembros de datos estáticos (que ahora se mueven a la aplicación de alojamiento)
-
UriMatcher
(ruede algo que no examina la autoridad, sino que se enfoca en el resto delUri
)
Si, por alguna razón, está absolutamente seguro de que su proveedor necesita conocer su autoridad, entonces la aplicación tendrá que suministrársela al proveedor antes de que el proveedor sea utilizado para un trabajo real. Las posibles formas de hacerlo incluyen:
Dado que un
ContentProvider
es un singleton natural, asignarlo a un miembro de datos estáticos, y luego suministrarle la cadena de autoridad mediante un método personalizado desde una clase deApplication
personalizada (ya que los proveedores se inicializan primero, así que esto debería funcionar)Si solo es compatible con el nivel de API 11+, haga que la clase de
Application
personalizada usecall()
enContentResolver
para proporcionar la autoridad alContentProvider
Supongamos que las únicas llamadas reales (por ejemplo, a
query()
,insert()
) son válidas, y solo inicializa tu autoridad de forma perezosa en función de lo que aparece en el primerUri
que ves
Sé que este es un tema antiguo, pero encontré este problema hoy y hemos estado desarrollando durante bastante tiempo, por lo que no estaba listo para revisar todas las estadísticas en nuestro Contrato de Proveedor de Contenido y cambiarlas, también porque nuestro proveedor de contenido y DB son generados por El complemento de Mechanoid para Eclipse (Sí, también soy el autor! :))
La solución que se me ocurrió fue agregar un inicializador estático a nuestro contrato generado que usa la reflexión para buscar una clase y usar un campo CONTENT_AUTHORITY estático en el caso de que exista, en caso de no volver a la configuración predeterminada:
public class QuxContract {
public static final String CONTENT_AUTHORITY = initAuthority();
private static String initAuthority() {
String authority = "com.example.app.data.qux";
try {
ClassLoader loader = QuxContract.class.getClassLoader();
Class<?> clz = loader.loadClass("com.example.app.data.QuxContentProviderAuthority");
Field declaredField = clz.getDeclaredField("CONTENT_AUTHORITY");
authority = declaredField.get(null).toString();
} catch (ClassNotFoundException e) {}
catch (NoSuchFieldException e) {}
catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}
return authority;
}
private static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);
// ...
Ahora en cada proyecto, los enlaces al proyecto de la biblioteca pueden proporcionar su propia autoridad:
package com.example.app.data;
public class QuxContentProviderAuthority {
public static final String CONTENT_AUTHORITY = "com.example.app.data.baz";
}
Además, no olvides cambiar la autoridad en tu manifiesto también.