Android: proveedores de contenido

Un componente de proveedor de contenido proporciona datos de una aplicación a otras bajo petición. Estas solicitudes son manejadas por los métodos de la clase ContentResolver. Un proveedor de contenido puede utilizar diferentes formas de almacenar sus datos y los datos se pueden almacenar en una base de datos, en archivos o incluso en una red.

Proveedor de contenido

sometimes it is required to share data across applications. This is where content providers become very useful.

Los proveedores de contenido le permiten centralizar el contenido en un solo lugar y hacer que muchas aplicaciones diferentes accedan a él según sea necesario. Un proveedor de contenido se comporta de manera muy similar a una base de datos donde puede consultarlo, editar su contenido, así como agregar o eliminar contenido usando los métodos insert (), update (), delete () y query (). En la mayoría de los casos, estos datos se almacenan en unSQlite base de datos.

Un proveedor de contenido se implementa como una subclase de ContentProvider class y debe implementar un conjunto estándar de API que permitan a otras aplicaciones realizar transacciones.

public class My Application extends  ContentProvider {
}

URI de contenido

Para consultar un proveedor de contenido, especifique la cadena de consulta en forma de URI que tiene el siguiente formato:

<prefix>://<authority>/<data_type>/<id>

Aquí está el detalle de varias partes del URI:

No Señor Parte Descripción
1

prefix

Esto siempre se establece en content: //

2

authority

Esto especifica el nombre del proveedor de contenido, por ejemplo , contactos , navegador , etc. Para proveedores de contenido de terceros, este podría ser el nombre completo, como com.tutorialspoint.statusprovider

3

data_type

Esto indica el tipo de datos que proporciona este proveedor en particular. Por ejemplo, si obtiene todos los contactos del proveedor de contenido de Contactos , entonces la ruta de datos sería personas y la URI se vería como este contenido: // contactos / personas

4

id

Esto especifica el registro específico solicitado. Por ejemplo, si está buscando el número de contacto 5 en el proveedor de contenido de Contactos, entonces el URI se vería como este contenido: // contactos / personas / 5 .

Crear proveedor de contenido

Esto implica una serie de sencillos pasos para crear su propio proveedor de contenido.

  • En primer lugar, debe crear una clase de proveedor de contenido que amplíe la clase base ContentProvider.

  • En segundo lugar, debe definir la dirección URI de su proveedor de contenido que se utilizará para acceder al contenido.

  • A continuación, deberá crear su propia base de datos para mantener el contenido. Por lo general, Android usa la base de datos SQLite y el marco necesita anular el método onCreate () que usará el método SQLite Open Helper para crear o abrir la base de datos del proveedor. Cuando se lanza su aplicación, se llama al controlador onCreate () de cada uno de sus proveedores de contenido en el hilo principal de la aplicación.

  • A continuación, deberá implementar consultas del proveedor de contenido para realizar diferentes operaciones específicas de la base de datos.

  • Finalmente, registre su proveedor de contenido en su archivo de actividad usando la etiqueta <provider>.

Aquí está la lista de métodos que debe anular en la clase de proveedor de contenido para que su proveedor de contenido funcione:

Proveedor de contenido

  • onCreate() Este método se llama cuando se inicia el proveedor.

  • query()Este método recibe una solicitud de un cliente. El resultado se devuelve como un objeto Cursor.

  • insert()Este método inserta un nuevo registro en el proveedor de contenido.

  • delete() Este método elimina un registro existente del proveedor de contenido.

  • update() Este método actualiza un registro existente del proveedor de contenido.

  • getType() Este método devuelve el tipo MIME de los datos en el URI dado.

Ejemplo

Este ejemplo le explicará cómo crear su propio ContentProvider . Así que sigamos los siguientes pasos de manera similar a lo que seguimos al crear el ejemplo de Hello World :

Paso Descripción
1 Utilizará Android StudioIDE para crear una aplicación de Android y nombrarla como Mi aplicación en un paquete com.example.MyApplication , con Activity en blanco.
2 Modifique el archivo de actividad principal MainActivity.java para agregar dos nuevos métodos onClickAddName () y onClickRetrieveStudents () .
3 Cree un nuevo archivo Java llamado StudentsProvider.java bajo el paquete com.example.MyApplication para definir su proveedor real y los métodos asociados.
4 Registre su proveedor de contenido en su archivo AndroidManifest.xml usando la etiqueta <proveedor ... />
5 Modifique el contenido predeterminado del archivo res / layout / activity_main.xml para incluir una pequeña GUI para agregar registros de estudiantes.
6 No es necesario cambiar string.xml. Android Studio se encarga del archivo string.xml.
7 Ejecute la aplicación para iniciar el emulador de Android y verifique el resultado de los cambios realizados en la aplicación.

A continuación se muestra el contenido del archivo de actividad principal modificado src/com.example.MyApplication/MainActivity.java. Este archivo puede incluir cada uno de los métodos fundamentales del ciclo de vida. Hemos agregado dos nuevos métodos onClickAddName () y onClickRetrieveStudents () para manejar la interacción del usuario con la aplicación.

package com.example.MyApplication;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;

import android.content.ContentValues;
import android.content.CursorLoader;

import android.database.Cursor;

import android.view.Menu;
import android.view.View;

import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {

   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
   }
   public void onClickAddName(View view) {
      // Add a new student record
      ContentValues values = new ContentValues();
      values.put(StudentsProvider.NAME,
         ((EditText)findViewById(R.id.editText2)).getText().toString());

      values.put(StudentsProvider.GRADE,
         ((EditText)findViewById(R.id.editText3)).getText().toString());

      Uri uri = getContentResolver().insert(
         StudentsProvider.CONTENT_URI, values);

      Toast.makeText(getBaseContext(),
         uri.toString(), Toast.LENGTH_LONG).show();
   }
   public void onClickRetrieveStudents(View view) {
      // Retrieve student records
      String URL = "content://com.example.MyApplication.StudentsProvider";

      Uri students = Uri.parse(URL);
      Cursor c = managedQuery(students, null, null, null, "name");

      if (c.moveToFirst()) {
         do{
            Toast.makeText(this,
               c.getString(c.getColumnIndex(StudentsProvider._ID)) +
                  ", " +  c.getString(c.getColumnIndex( StudentsProvider.NAME)) +
                     ", " + c.getString(c.getColumnIndex( StudentsProvider.GRADE)),
            Toast.LENGTH_SHORT).show();
         } while (c.moveToNext());
      }
   }
}

Cree un nuevo archivo StudentsProvider.java en el paquete com.example.MyApplication y el siguiente es el contenido desrc/com.example.MyApplication/StudentsProvider.java -

package com.example.MyApplication;

import java.util.HashMap;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;

import android.database.Cursor;
import android.database.SQLException;

import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;

import android.net.Uri;
import android.text.TextUtils;

public class StudentsProvider extends ContentProvider {
   static final String PROVIDER_NAME = "com.example.MyApplication.StudentsProvider";
   static final String URL = "content://" + PROVIDER_NAME + "/students";
   static final Uri CONTENT_URI = Uri.parse(URL);

   static final String _ID = "_id";
   static final String NAME = "name";
   static final String GRADE = "grade";

   private static HashMap<String, String> STUDENTS_PROJECTION_MAP;

   static final int STUDENTS = 1;
   static final int STUDENT_ID = 2;

   static final UriMatcher uriMatcher;
   static{
      uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
      uriMatcher.addURI(PROVIDER_NAME, "students", STUDENTS);
      uriMatcher.addURI(PROVIDER_NAME, "students/#", STUDENT_ID);
   }

   /**
      * Database specific constant declarations
   */
   
   private SQLiteDatabase db;
   static final String DATABASE_NAME = "College";
   static final String STUDENTS_TABLE_NAME = "students";
   static final int DATABASE_VERSION = 1;
   static final String CREATE_DB_TABLE =
      " CREATE TABLE " + STUDENTS_TABLE_NAME +
         " (_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
         " name TEXT NOT NULL, " +
         " grade TEXT NOT NULL);";

   /**
      * Helper class that actually creates and manages
      * the provider's underlying data repository.
   */
   
   private static class DatabaseHelper extends SQLiteOpenHelper {
      DatabaseHelper(Context context){
         super(context, DATABASE_NAME, null, DATABASE_VERSION);
      }

      @Override
      public void onCreate(SQLiteDatabase db) {
         db.execSQL(CREATE_DB_TABLE);
      }

      @Override
      public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
         db.execSQL("DROP TABLE IF EXISTS " +  STUDENTS_TABLE_NAME);
         onCreate(db);
      }
   }

   @Override
   public boolean onCreate() {
      Context context = getContext();
      DatabaseHelper dbHelper = new DatabaseHelper(context);

      /**
         * Create a write able database which will trigger its
         * creation if it doesn't already exist.
      */
         
      db = dbHelper.getWritableDatabase();
      return (db == null)? false:true;
   }

   @Override
   public Uri insert(Uri uri, ContentValues values) {
      /**
         * Add a new student record
      */
      long rowID = db.insert(	STUDENTS_TABLE_NAME, "", values);

      /**
         * If record is added successfully
      */
      if (rowID > 0) {
         Uri _uri = ContentUris.withAppendedId(CONTENT_URI, rowID);
         getContext().getContentResolver().notifyChange(_uri, null);
         return _uri;
      }
        
      throw new SQLException("Failed to add a record into " + uri);
   }

   @Override
   public Cursor query(Uri uri, String[] projection, 
      String selection,String[] selectionArgs, String sortOrder) {
      SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
      qb.setTables(STUDENTS_TABLE_NAME);

      switch (uriMatcher.match(uri)) {
         case STUDENTS:
            qb.setProjectionMap(STUDENTS_PROJECTION_MAP);
         break;

         case STUDENT_ID:
            qb.appendWhere( _ID + "=" + uri.getPathSegments().get(1));
         break;
         
         default:   
      }

      if (sortOrder == null || sortOrder == ""){
         /**
            * By default sort on student names
         */
         sortOrder = NAME;
      }
      
      Cursor c = qb.query(db,	projection,	selection, 
         selectionArgs,null, null, sortOrder);
      /**
         * register to watch a content URI for changes
      */
      c.setNotificationUri(getContext().getContentResolver(), uri);
      return c;
   }

   @Override
   public int delete(Uri uri, String selection, String[] selectionArgs) {
      int count = 0;
      switch (uriMatcher.match(uri)){
         case STUDENTS:
            count = db.delete(STUDENTS_TABLE_NAME, selection, selectionArgs);
         break;

         case STUDENT_ID:
            String id = uri.getPathSegments().get(1);
            count = db.delete( STUDENTS_TABLE_NAME, _ID +  " = " + id +
               (!TextUtils.isEmpty(selection) ? " 
               AND (" + selection + ')' : ""), selectionArgs);
            break;
         default:
            throw new IllegalArgumentException("Unknown URI " + uri);
      }

      getContext().getContentResolver().notifyChange(uri, null);
      return count;
   }

   @Override
   public int update(Uri uri, ContentValues values, 
      String selection, String[] selectionArgs) {
      int count = 0;
      switch (uriMatcher.match(uri)) {
         case STUDENTS:
            count = db.update(STUDENTS_TABLE_NAME, values, selection, selectionArgs);
         break;

         case STUDENT_ID:
            count = db.update(STUDENTS_TABLE_NAME, values, 
               _ID + " = " + uri.getPathSegments().get(1) +
               (!TextUtils.isEmpty(selection) ? " 
               AND (" +selection + ')' : ""), selectionArgs);
            break;
         default:
            throw new IllegalArgumentException("Unknown URI " + uri );
      }
        
      getContext().getContentResolver().notifyChange(uri, null);
      return count;
   }

   @Override
   public String getType(Uri uri) {
      switch (uriMatcher.match(uri)){
         /**
            * Get all student records
         */
         case STUDENTS:
            return "vnd.android.cursor.dir/vnd.example.students";
         /**
            * Get a particular student
         */
         case STUDENT_ID:
            return "vnd.android.cursor.item/vnd.example.students";
         default:
            throw new IllegalArgumentException("Unsupported URI: " + uri);
      }
   }
}

A continuación se muestra el contenido modificado del archivo AndroidManifest.xml . Aquí hemos agregado la etiqueta <proveedor ... /> para incluir nuestro proveedor de contenido:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.MyApplication">

   <application
      android:allowBackup="true"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name"
      android:supportsRtl="true"
      android:theme="@style/AppTheme">
         <activity android:name=".MainActivity">
            <intent-filter>
               <action android:name="android.intent.action.MAIN" />
               <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
         </activity>
        
      <provider android:name="StudentsProvider"
         android:authorities="com.example.MyApplication.StudentsProvider"/>
   </application>
</manifest>

A continuación se mostrará el contenido de res/layout/activity_main.xml archivo−

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:paddingBottom="@dimen/activity_vertical_margin"
   android:paddingLeft="@dimen/activity_horizontal_margin"
   android:paddingRight="@dimen/activity_horizontal_margin"
   android:paddingTop="@dimen/activity_vertical_margin"
   tools:context="com.example.MyApplication.MainActivity">

   <TextView
      android:id="@+id/textView1"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Content provider"
      android:layout_alignParentTop="true"
      android:layout_centerHorizontal="true"
      android:textSize="30dp" />

   <TextView
      android:id="@+id/textView2"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Tutorials point "
      android:textColor="#ff87ff09"
      android:textSize="30dp"
      android:layout_below="@+id/textView1"
      android:layout_centerHorizontal="true" />

   <ImageButton
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/imageButton"
      android:src="@drawable/abc"
      android:layout_below="@+id/textView2"
      android:layout_centerHorizontal="true" />

   <Button
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/button2"
      android:text="Add Name"
      android:layout_below="@+id/editText3"
      android:layout_alignRight="@+id/textView2"
      android:layout_alignEnd="@+id/textView2"
      android:layout_alignLeft="@+id/textView2"
      android:layout_alignStart="@+id/textView2"
      android:onClick="onClickAddName"/>

   <EditText
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/editText"
      android:layout_below="@+id/imageButton"
      android:layout_alignRight="@+id/imageButton"
      android:layout_alignEnd="@+id/imageButton" />

   <EditText
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/editText2"
      android:layout_alignTop="@+id/editText"
      android:layout_alignLeft="@+id/textView1"
      android:layout_alignStart="@+id/textView1"
      android:layout_alignRight="@+id/textView1"
      android:layout_alignEnd="@+id/textView1"
      android:hint="Name"
      android:textColorHint="@android:color/holo_blue_light" />

   <EditText
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/editText3"
      android:layout_below="@+id/editText"
      android:layout_alignLeft="@+id/editText2"
      android:layout_alignStart="@+id/editText2"
      android:layout_alignRight="@+id/editText2"
      android:layout_alignEnd="@+id/editText2"
      android:hint="Grade"
      android:textColorHint="@android:color/holo_blue_bright" />

   <Button
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Retrive student"
      android:id="@+id/button"
      android:layout_below="@+id/button2"
      android:layout_alignRight="@+id/editText3"
      android:layout_alignEnd="@+id/editText3"
      android:layout_alignLeft="@+id/button2"
      android:layout_alignStart="@+id/button2"
      android:onClick="onClickRetrieveStudents"/>
</RelativeLayout>

Asegúrate de tener el siguiente contenido de res/values/strings.xml archivo:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">My Application</string>
</resources>;

Intentemos ejecutar nuestro modificado My Applicationaplicación que acabamos de crear. Supongo que habías creado tuAVDmientras realiza la configuración del entorno. Para ejecutar la aplicación desde Android Studio IDE, abra uno de los archivos de actividad de su proyecto y haga clic en el icono Ejecutar en la barra de herramientas. Android Studio instala la aplicación en su AVD y la inicia y si todo está bien con su configuración y aplicación, se mostrará la siguiente ventana del Emulador, tenga paciencia porque puede tomar algún tiempo según la velocidad de su computadora.

Ahora entremos estudiante Name y Grade y finalmente haga clic en Add Name, esto agregará el registro del estudiante en la base de datos y mostrará un mensaje en la parte inferior que muestra el URI de ContentProvider junto con el número de registro agregado en la base de datos. Esta operación hace uso de nuestroinsert()método. Repitamos este proceso para agregar algunos estudiantes más en la base de datos de nuestro proveedor de contenido.

Una vez que haya terminado de agregar registros en la base de datos, ahora es el momento de pedirle a ContentProvider que nos devuelva esos registros, así que hagamos clic Retrieve Students botón que buscará y mostrará todos los registros uno por uno, según la implementación de nuestro query() método.

Puede escribir actividades contra las operaciones de actualización y eliminación proporcionando funciones de devolución de llamada en MainActivity.java archivo y luego modificar la interfaz de usuario para tener botones para actualizar y eliminar operaciones de la misma manera que lo hemos hecho para agregar y leer operaciones.

De esta manera, puede usar un proveedor de contenido existente como la libreta de direcciones o puede usar el concepto de proveedor de contenido para desarrollar aplicaciones agradables orientadas a la base de datos donde puede realizar todo tipo de operaciones de la base de datos como leer, escribir, actualizar y eliminar como se explicó anteriormente en el ejemplo.