Ricerca…


Osservazioni

I fornitori di contenuti gestiscono l'accesso a un insieme strutturato di dati. Incapsulano i dati e forniscono meccanismi per la definizione della sicurezza dei dati. I fornitori di contenuti sono l'interfaccia standard che collega i dati in un processo con codice in esecuzione in un altro processo.

Quando si desidera accedere ai dati in un provider di contenuti, utilizzare l'oggetto ContentResolver nel Context dell'applicazione per comunicare con il provider come client. L'oggetto ContentResolver comunica con l'oggetto provider, un'istanza di una classe che implementa ContentProvider . L'oggetto provider riceve richieste di dati dai client, esegue l'azione richiesta e restituisce i risultati.

Non è necessario sviluppare il proprio provider se non si intende condividere i dati con altre applicazioni. Tuttavia, è necessario il proprio provider per fornire suggerimenti di ricerca personalizzati nella propria applicazione. È inoltre necessario il proprio provider se si desidera copiare e incollare dati o file complessi dall'applicazione ad altre applicazioni.

Lo stesso Android include fornitori di contenuti che gestiscono dati come audio, video, immagini e informazioni di contatto personali. Puoi vedere alcuni di essi elencati nella documentazione di riferimento per il pacchetto android.provider . Con alcune restrizioni, questi provider sono accessibili a qualsiasi applicazione Android.

Implementazione di una classe di provider di contenuti di base

1) Creare una classe di contratto

Una classe del contratto definisce le costanti che aiutano le applicazioni a lavorare con gli URI del contenuto, i nomi delle colonne, le azioni intent e altre caratteristiche di un fornitore di contenuti. Le classi di contratto non sono incluse automaticamente con un fornitore; lo sviluppatore del provider deve definirli e renderli disponibili ad altri sviluppatori.

Un provider di solito ha una singola autorità, che funge da nome interno Android. Per evitare conflitti con altri fornitori, utilizzare un'autorità di contenuto univoca. Poiché questo consiglio vale anche per i nomi dei pacchetti Android, è possibile definire l'autorizzazione del provider come un'estensione del nome del pacchetto contenente il provider. Ad esempio, se il nome del pacchetto Android è com.example.appname , è necessario fornire all'autorità di com.example.appname.provider l'autorità com.example.appname.provider .

public class MyContract {
    public static final String CONTENT_AUTHORITY = "com.example.myApp";
    public static final String PATH_DATATABLE = "dataTable";
    public static final String TABLE_NAME = "dataTable";
}

Un URI di contenuto è un URI che identifica i dati in un provider. Gli URI di contenuto includono il nome simbolico dell'intero provider (la sua autorità) e un nome che punta a una tabella o file (un percorso). La parte id opzionale indica una singola riga in una tabella. Ogni metodo di accesso ai dati di ContentProvider ha un URI di contenuto come argomento; questo ti permette di determinare la tabella, riga o file per accedere. Definire questi nella classe di contratto.

public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);
public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon().appendPath(PATH_DATATABLE).build();

// define all columns of table and common functions required

2) Crea la classe di supporto

Una classe helper gestisce la creazione del database e la gestione delle versioni.

public class DatabaseHelper extends SQLiteOpenHelper {

    // Increment the version when there is a change in the structure of database
    public static final int DATABASE_VERSION = 1;
    // The name of the database in the filesystem, you can choose this to be anything
    public static final String DATABASE_NAME = "weather.db";

    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        // Called when the database is created for the first time. This is where the
        // creation of tables and the initial population of the tables should happen.
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // Called when the database needs to be upgraded. The implementation
        // should use this method to drop tables, add tables, or do anything else it
        // needs to upgrade to the new schema version.
    }
}

3) Creare una classe che estende la classe ContentProvider

public class MyProvider extends ContentProvider {

public DatabaseHelper dbHelper;

public static final UriMatcher matcher = buildUriMatcher();
public static final int DATA_TABLE = 100;
public static final int DATA_TABLE_DATE = 101;

Un UriMatcher associa un'autorità e un percorso a un valore intero. Il metodo match() restituisce un valore intero univoco per un URI (può essere qualsiasi numero arbitrario, purché sia ​​univoco). Un'istruzione switch sceglie tra l'interrogazione dell'intera tabella e l'interrogazione per un singolo record. Il nostro UriMatcher restituisce 100 se l'URI è l'URI contenuto di Tabella e 101 se l'URI punta a una riga specifica all'interno di quella tabella. Puoi usare il # carattere jolly per abbinarlo con qualsiasi numero e * per abbinarlo a qualsiasi stringa.

public static UriMatcher buildUriMatcher() {
    UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    uriMatcher.addURI(CONTENT_AUTHORITY, MyContract.PATH_DATATABLE,        DATA_TABLE);
    uriMatcher.addURI(CONTENT_AUTHORITY, MyContract.PATH_DATATABLE + "/#", DATA_TABLE_DATE);
    return uriMatcher;
}

IMPORTANTE: l'ordine delle chiamate ad addURI() importante! UriMatcher guarderà in ordine sequenziale dal primo aggiunto all'ultimo. Poiché i caratteri jolly come # e * sono golosi, dovrai assicurarti di aver ordinato correttamente gli URI. Per esempio:

uriMatcher.addURI(CONTENT_AUTHORITY, "/example", 1);
uriMatcher.addURI(CONTENT_AUTHORITY, "/*",       2);

è l'ordine corretto, dal momento che il matcher cercherà /example prima di ricorrere alla corrispondenza /* . Se queste chiamate al metodo sono state annullate e hai chiamato uriMatcher.match("/example") , UriMatcher smetterà di cercare le corrispondenze una volta che incontra il percorso /* e restituisce il risultato errato!

Dovrai quindi eseguire l'override di queste funzioni:

onCreate () : inizializza il tuo provider. Il sistema Android chiama questo metodo subito dopo aver creato il tuo provider. Si noti che il proprio provider non viene creato fino a quando un oggetto ContentResolver tenta di accedervi.

@Override
public boolean onCreate() {
    dbhelper = new DatabaseHelper(getContext());
    return true;
}

getType () : restituisce il tipo MIME corrispondente a un URI di contenuto

@Override
public String getType(Uri uri) {
    final int match = matcher.match(uri);
    switch (match) {
        case DATA_TABLE:
            return ContentResolver.CURSOR_DIR_BASE_TYPE + "/" + MyContract.CONTENT_AUTHORITY + "/" + MyContract.PATH_DATATABLE;
        case DATA_TABLE_DATE:
            return ContentResolver.ANY_CURSOR_ITEM_TYPE + "/" + MyContract.CONTENT_AUTHORITY + "/" + MyContract.PATH_DATATABLE;
        default:
            throw new UnsupportedOperationException("Unknown Uri: " + uri);

    }
}

query () : recupera i dati dal tuo provider. Utilizzare gli argomenti per selezionare la tabella da interrogare, le righe e le colonne da restituire e l'ordinamento del risultato. Restituisce i dati come oggetto Cursore.

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    Cursor retCursor = dbHelper.getReadableDatabase().query(
        MyContract.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
    retCursor.setNotificationUri(getContext().getContentResolver(), uri);
    return retCursor;
}

Inserisci una nuova riga nel tuo provider. Utilizzare gli argomenti per selezionare la tabella di destinazione e ottenere i valori della colonna da utilizzare. Restituisce un URI di contenuto per la riga appena inserita.

@Override
public Uri insert(Uri uri, ContentValues values)
{
    final SQLiteDatabase db = dbHelper.getWritableDatabase();
    long id = db.insert(MyContract.TABLE_NAME, null, values);
    return ContentUris.withAppendedId(MyContract.CONTENT_URI, ID);
}

delete () : elimina le righe dal tuo provider. Utilizzare gli argomenti per selezionare la tabella e le righe da eliminare. Restituisce il numero di righe cancellate.

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
    SQLiteDatabase db = dbHelper.getWritableDatabase();
    int rowsDeleted = db.delete(MyContract.TABLE_NAME, selection, selectionArgs);
    getContext().getContentResolver().notifyChange(uri, null);
    return rowsDeleted;
}

update () : aggiorna le righe esistenti nel tuo provider. Utilizzare gli argomenti per selezionare la tabella e le righe da aggiornare e ottenere i nuovi valori di colonna. Restituisce il numero di righe aggiornate.

@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    SQLiteDatabase db = dbHelper.getWritableDatabase();
    int rowsUpdated = db.update(MyContract.TABLE_NAME, values, selection, selectionArgs);
    getContext().getContentResolver().notifyChange(uri, null);
    return rowsUpdated;
}

4) Aggiorna file manifest

<provider
        android:authorities="com.example.myApp"
        android:name=".DatabaseProvider"/>


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow