Introducción
Proveedor de contenido, uno de los cuatro componentes principales de Android, su función principal es realizar el intercambio de datos (entre aplicaciones) entre varias aplicaciones.
Aquí está involucrado el problema de la comunicación del proceso. Naturalmente, el archivador se usa en Android, pero debido a que la cantidad de datos proporcionados por el proveedor de contenido es generalmente relativamente grande, no se puede transmitir directamente.
Entonces, lo que se usa aquí es un método llamado memoria compartida anónima para la transferencia de datos, y solo se necesita transferir un descriptor de archivo en diferentes procesos.
Tenga una comprensión más intuitiva del proveedor de contenido a través de la siguiente figura:
ContentProvider proporciona un mecanismo para compartir datos entre aplicaciones.
-
El almacenamiento y la recuperación de datos proporciona una interfaz unificada.
-
Encapsule los datos sin preocuparse por los detalles del almacenamiento de datos.
-
Android proporciona un ContentProvider predeterminado para algunos datos comunes (incluidos audio, video, imágenes y contactos, etc.).
Entonces, ¿cómo se da cuenta ContentProvider de compartir datos?
Identificador uniforme de recursos (URI)
El URI representa los datos que se van a operar y se puede utilizar para identificar cada ContentProvider, de modo que pueda encontrar el ContentProvider deseado a través del URI especificado y obtener o modificar datos de él.
El formato de una URI en Android es el siguiente:
URL =
<schema>://<authority>/<path>/<id>
Por ejemplo: contenido://com.jeanboy.provider/User/1
-
tema (esquema)
El prefijo URI de ContentProvider indica un URI de contenido de Android, lo que indica que los datos están controlados por ContentProvider. Esta parte es fija y no se puede cambiar.
-
Información de autorización (autoridad)
La parte de autorización del URI es un identificador único que se utiliza para ubicar el ContentProvider. El formato suele ser el nombre completo de la clase ContentProvider personalizada, que se requiere para el registro. Tales como: com.jeanboy.provider.TestProvider.
-
nombre de la tabla (ruta)
El fragmento de ruta, generalmente el nombre de la tabla, apunta a un nombre de tabla en la base de datos.
-
registro (identificación)
Apunta a un registro específico, como un registro en una tabla (devuelve todos los registros si no se especifica).
tipo de datos MIME
MIME es para especificar un archivo con una extensión para abrir con una aplicación, al igual que usa un navegador para ver un archivo PDF, y el navegador elegirá la aplicación apropiada para abrir.
La forma en que funciona en Android es similar a HTTP, ContentProvider devolverá el tipo MIME según el URI y ContentProvider devolverá una cadena que contiene dos partes.
Composición MIME = tipo + subtipo.
texto/aplicación html/pdf
...
ContentProvider devuelve el tipo MIME según URI
ContentProvider.geType(uri) ;
Android sigue una convención similar para definir tipos MIME, y hay dos formas de tipos MIME de Android para cada tipo de contenido: registros múltiples (colecciones) y registros únicos.
-
Múltiples registros:
vnd.android.cursor.dir/<custom>
-
Registro único:
vnd.android.cursor.item/<custom>
vnd indica que estos tipos y subtipos tienen un formato no estándar específico del proveedor. El tipo en Android se ha corregido y no se puede cambiar. Solo se puede distinguir si es una colección o un solo registro específico. El contenido después del subtipo vnd. se puede completar de acuerdo con el formato.
Al usar Intent, MIME se usará para abrir la actividad que cumpla con las condiciones según el Tipo MIME.
<actividad android:name=".TestActivity"> <intent-filter> <categoría android:name="android.intent.category.DEFAULT" /> <data android:mimeType="vnd.android.cursor.dir/jeanboy. primero" /> </intent-filter> </actividad>
Crear un proveedor de contenido
A continuación, aprenda a crear un ContentProvider personalizado a través de una demostración simple. La fuente de datos puede elegir SQLite, la más utilizada es esta, por supuesto, también puede elegir otra, como SharedPreferences.
Primero, cree una clase TestContentProvider, herede ContentProvider e implemente el método.
clase pública TestContentProvider extiende ContentProvider { @Override public boolean onCreate() { // TODO 做一些初始化操作 return false; } @Override public Cursor query(Uri uri, String[] proyección, String selection, String[] selectionArgs, String sortOrder) { // TODO 查询 return null; } @Override public String getType(Uri uri) { // TODO MIME Type return null; } @Override public Uri insert(Uri uri, valores ContentValues) { // TODO 插入 } return null; @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // TODO 删除 return 0; } @Override public int update(Uri uri, valores de ContentValues, selección de cadenas, cadenas[] argumentos de selección) { // TODO 更新 return 0; } }
Luego, debe registrarse AndroidManifest.xml
con .
<proveedor android:name=".ui.provider.TestProvider" android:authorities="com.jeanboy.testprovider" />
Usar proveedor de contenido
En aplicaciones de terceros, ¿cómo usamos URI para realizar operaciones en datos compartidos? Se hace usando la clase ContentResolver.
El método para obtener una instancia de ContentResolver es:
Resolución de ContentResolver = getContentResolver();
ContentResolver tiene las siguientes operaciones de base de datos: consulta, inserción, actualización, eliminación.
consulta de cursor final pública (uri uri, proyección de cadena [], selección de cadena, argumentos de selección de cadena [], orden de clasificación de cadena) inserción de uri final pública (url de uri, valores de ContentValues) actualización de int final pública (uri de uri, valores de valores de contenido, cadena donde, cadena [] selectionArgs) public final int delete (Uri url, String where, String[] selectionArgs)
Un ejemplo completo es el siguiente:
clase pública ContentProviderActivity extiende BaseActivity { private Uri uriUser = Uri.parse("content://com.jeanboy.testprovider/user"); @Override protected void onCreate(Bundle SavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.actividad_contenido_proveedor); } public void toInsert(View view) { valores de ContentValues = new ContentValues(); valores.put("id", 3); valores.put("nombre", "张三"); Resolución de ContentResolver = getContentResolver(); resolver.insert(uriUser, valores); } public void toUpdate(Ver vista) { Valores de ContentValues = nuevos ContentValues(); valores.put("id", 3); valores.put("nombre", "张三三"); Resolución de ContentResolver = getContentResolver(); resolver.update(uriUser, valores, "id = ?", new String[]{"3"}); } public void toSelect(Ver vista) { ContentResolver resolver = getContentResolver(); Cursor cursor = resolver.query(uriUser, new String[]{"id", "name"}, null, null, null); while (cursor.moveToNext()) { Log.e(TAG, "=========== consulta :" + cursor.getInt(0) + "==" + cursor.getString(1)) ; } cursor.cerrar(); } public void toDelete(Ver vista) { resolver.delete(uriUser, "id = ?", new String[]{"3"}); } }
Permisos de proveedor de contenido
Hay tres parámetros adicionales permiso, readPermission y writePermission en la etiqueta del proveedor en AndroidManifest.xml.
Primero mira el siguiente código:
<proveedor android:name=".ui.provider.TestProvider" android:authorities="com.jeanboy.testprovider" android:exported="true" android:readPermission="com.jeanboy.provider.permission.read" android:writePermission ="com.jeanboy.proveedor.permiso.escribir" android:permiso="com.jeanboy.proveedor.permiso"/>
Hay varios parámetros en este código a los que hay que prestar especial atención:
-
exportado
Este atributo se utiliza para indicar si el servicio se puede invocar o interactuar con otros componentes de la aplicación del programa; el valor es (verdadero | falso).
Si se establece en verdadero, se puede invocar o interactuar con él; de lo contrario, no; cuando se establece en falso, solo los componentes de la misma aplicación o las aplicaciones con el mismo ID de usuario pueden iniciar o vincular el servicio.
-
permiso de lectura
La autoridad necesaria para usar la función de consulta del Proveedor de contenido, es decir, la autoridad para usar query()
las funciones .
-
permiso de escritura
La autoridad necesaria para usar la función de modificación de ContentProvider, es decir, la autoridad para usar las funciones insert()
, update()
y delete()
de ContentProvider.
-
permiso
El nombre del permiso necesario para que el cliente lea y escriba datos en el Proveedor de contenido.
Esta propiedad proporciona un atajo para establecer permisos de lectura y escritura a la vez. Sin embargo, los atributos readPermission y writePermission tienen prioridad sobre esta configuración.
Si también se establece la propiedad readPermission, controlará la lectura del proveedor de contenido. Si se establece el atributo writePermission, también controlará la modificación de los datos del proveedor de contenido.
Es decir, si solo se establece el permiso permiso, entonces la aplicación con este permiso puede leer y escribir el ContentProvider aquí; si tanto el permiso como el permiso de lectura están configurados, entonces solo la aplicación con permiso de lectura puede leer, y solo la aplicación con permiso permiso permiso puede escribir! Es decir, no puede leer solo con el permiso, porque la prioridad del permiso de lectura es mayor que la del permiso; si se configuran al mismo tiempo el permiso de lectura, el permiso de escritura y el permiso, el permiso no será válido.
permiso de uso
Después de declarar el permiso anterior, debe registrarlo en el directorio al mismo nivel que la etiqueta de la aplicación.
<manifiesto...> <permiso android:name="com.jeanboy.provider.permission.read" android:label="provider pomission" android:protectionLevel="normal" /> <aplicación...> ... < /aplicación> </manifiesto>
De esta forma, nuestro permiso quedará registrado en el sistema y se utilizará en aplicaciones de terceros <uses-permission>
para usar permisos.
<usos-permiso android:name="com.jeanboy.provider.permission.read"/>
ContentObserver
La función principal de ContentObserver es monitorear los cambios de la base de datos en el URI especificado.
Primero, cree un ContentObserver.
public class DataObserver extiende ContentObserver { public DataObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { super.onChange(selfChange); // TODO escucha los cambios de datos } }
Registre un ContentObserver.
clase pública ContentProviderActivity extiende BaseActivity { private Uri uriUser = Uri.parse("content://com.jeanboy.myprovider/user"); observador de datos privado observador de datos; @Override protected String getTAG() { return ContentProviderActivity.class.getSimpleName(); } @Override protected void onCreate(Paquete de estado de instancia guardado) { super.onCreate(estado de instancia guardado); setContentView(R.layout.actividad_contenido_proveedor); // 创建 DataObserver dataObserver = new DataObserver(new Handler()); // 注册 DataObserver getContentResolver().registerContentObserver(uriUser, true, observador de datos); } @Anular vacío protegido onDestroy() { super.onDestroy(); // 取消注册 getContentResolver().unregisterContentObserver(dataObserver); } }
Finalmente, observe el uso de la función de escucha registerContentObserver()
registrada :
public final void registerContentObserver(Uri uri, boolean notificar a Descendientes, ContentObserver observador)
-
uri
El URI a observar.
-
notificar a los descendientes
Si es falso, significa coincidencia exacta, es decir, solo coincide con este URI; si es verdadero, significa que puede coincidir con su URI derivado al mismo tiempo.