Android
Inhalt Anbieter
Suche…
Bemerkungen
Inhaltsanbieter verwalten den Zugriff auf strukturierte Daten. Sie kapseln die Daten und bieten Mechanismen zur Definition der Datensicherheit. Inhaltsanbieter sind die Standardschnittstelle, die Daten in einem Prozess mit Code verbindet, der in einem anderen Prozess ausgeführt wird.
Wenn Sie auf Daten in einem Inhaltsanbieter zugreifen möchten, verwenden Sie das ContentResolver
Objekt im Context
Ihrer Anwendung, um mit dem Anbieter als Client zu kommunizieren. Das ContentResolver
Objekt kommuniziert mit dem Provider-Objekt, einer Instanz einer Klasse, die ContentProvider
implementiert. Das Provider-Objekt empfängt Datenanforderungen von Clients, führt die angeforderte Aktion aus und gibt die Ergebnisse zurück.
Sie müssen keinen eigenen Anbieter entwickeln, wenn Sie Ihre Daten nicht für andere Anwendungen freigeben möchten. Sie benötigen jedoch einen eigenen Anbieter, um benutzerdefinierte Suchvorschläge in Ihrer eigenen Anwendung bereitzustellen. Sie benötigen auch einen eigenen Provider, wenn Sie komplexe Daten oder Dateien aus Ihrer Anwendung in andere Anwendungen kopieren und einfügen möchten.
Android selbst umfasst Inhaltsanbieter, die Daten wie Audio, Video, Bilder und persönliche Kontaktinformationen verwalten. Einige davon sind in der Referenzdokumentation für das android.provider
Paket aufgeführt. Mit einigen Einschränkungen sind diese Anbieter für jede Android-Anwendung verfügbar.
Implementieren einer grundlegenden Klasse von Inhaltsanbietern
1) Erstellen Sie eine Vertragsklasse
Eine Vertragsklasse definiert Konstanten, mit deren Hilfe Anwendungen mit den Inhalts-URIs, Spaltennamen, Absichtsaktionen und anderen Funktionen eines Inhaltsanbieters zusammenarbeiten können. Vertragsklassen werden bei einem Anbieter nicht automatisch berücksichtigt. Der Entwickler des Providers muss diese definieren und anderen Entwicklern zur Verfügung stellen.
Ein Anbieter hat normalerweise eine einzige Autorität, die als Android-interner Name dient. Verwenden Sie eine eindeutige Inhaltsautorität, um Konflikte mit anderen Anbietern zu vermeiden. Da diese Empfehlung auch für Android-Paketnamen gilt, können Sie Ihre Anbieterberechtigung als Erweiterung des Namens des Pakets definieren, das den Anbieter enthält. Wenn Ihr Android-Paketname beispielsweise com.example.appname
, sollten Sie Ihrem Provider die Berechtigung 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";
}
Ein Inhalts-URI ist ein URI, der Daten in einem Anbieter identifiziert. Inhalts-URIs enthalten den symbolischen Namen des gesamten Providers (seine Autorität) und einen Namen, der auf eine Tabelle oder Datei (einen Pfad) verweist. Der optionale ID-Teil verweist auf eine einzelne Zeile in einer Tabelle. Jede Datenzugriffsmethode von ContentProvider hat einen Inhalts-URI als Argument. Auf diese Weise können Sie die Tabelle, Zeile oder Datei bestimmen, auf die zugegriffen werden soll. Definieren Sie diese in der Vertragsklasse.
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) Erstellen Sie die Helfer-Klasse
Eine Hilfsklasse verwaltet die Datenbankerstellung und die Versionsverwaltung.
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) Erstellen Sie eine Klasse, die die ContentProvider-Klasse erweitert
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;
Ein UriMatcher ordnet Autorität und Pfad einem ganzzahligen Wert zu. Die Methode match()
gibt einen eindeutigen ganzzahligen Wert für eine URI zurück (es kann eine beliebige Zahl sein, solange sie eindeutig ist). Eine switch-Anweisung wählt zwischen der Abfrage der gesamten Tabelle und der Abfrage eines einzelnen Datensatzes. Unser UriMatcher gibt 100 zurück, wenn der URI der Inhalts-URI von Table ist, und 101, wenn der URI auf eine bestimmte Zeile in dieser Tabelle verweist. Sie können das Platzhalterzeichen #
, um mit einer beliebigen Zahl abzugleichen, und *
, um mit einer beliebigen Zeichenfolge übereinzustimmen.
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;
}
WICHTIG: Die Bestellung von addURI()
ruft das hervor! Der UriMatcher sucht in sequenzieller Reihenfolge vom ersten bis zum letzten Hinzufügen. Da Platzhalter wie #
und *
gierig sind, müssen Sie sicherstellen, dass Sie Ihre URIs richtig bestellt haben. Zum Beispiel:
uriMatcher.addURI(CONTENT_AUTHORITY, "/example", 1);
uriMatcher.addURI(CONTENT_AUTHORITY, "/*", 2);
ist die richtige Reihenfolge, da der Matcher zuerst nach /example
sucht, bevor er zum /*
-Match greift. Wenn diese Methodenaufrufe rückgängig gemacht wurden und Sie uriMatcher.match("/example")
aufgerufen haben, uriMatcher.match("/example")
der UriMatcher auf, nach Übereinstimmungen zu suchen, sobald er auf den Pfad /*
trifft, und liefert das falsche Ergebnis!
Sie müssen dann diese Funktionen überschreiben:
onCreate () : Initialisieren Sie Ihren Provider. Das Android-System ruft diese Methode unmittelbar nach der Erstellung Ihres Providers auf. Beachten Sie, dass Ihr Provider erst erstellt wird, wenn ein ContentResolver-Objekt versucht, darauf zuzugreifen.
@Override
public boolean onCreate() {
dbhelper = new DatabaseHelper(getContext());
return true;
}
getType () : Gibt den MIME-Typ zurück, der einem Inhalts-URI entspricht
@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);
}
}
Abfrage () : Rufen Sie Daten von Ihrem Provider ab. Verwenden Sie die Argumente, um die abzurufende Tabelle, die zurückzugebenden Zeilen und Spalten und die Sortierreihenfolge des Ergebnisses auszuwählen. Gibt die Daten als Cursorobjekt zurück.
@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;
}
Fügen Sie eine neue Zeile in Ihren Provider ein. Verwenden Sie die Argumente, um die Zieltabelle auszuwählen und die zu verwendenden Spaltenwerte abzurufen. Gibt einen Inhalts-URI für die neu eingefügte Zeile zurück.
@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 () : Löscht Zeilen von Ihrem Provider. Verwenden Sie die Argumente, um die Tabelle und die zu löschenden Zeilen auszuwählen. Gibt die Anzahl der gelöschten Zeilen zurück.
@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 () : Aktualisieren Sie vorhandene Zeilen in Ihrem Provider. Verwenden Sie die Argumente, um die zu aktualisierende Tabelle und Zeilen auszuwählen und die neuen Spaltenwerte abzurufen. Gibt die Anzahl der aktualisierten Zeilen zurück.
@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) Manifestdatei aktualisieren
<provider
android:authorities="com.example.myApp"
android:name=".DatabaseProvider"/>