Android - dostawcy treści
Komponent dostawcy treści dostarcza na żądanie dane z jednej aplikacji do innych. Takie żądania są obsługiwane przez metody klasy ContentResolver. Dostawca treści może korzystać z różnych sposobów przechowywania swoich danych, a dane mogą być przechowywane w bazie danych, w plikach, a nawet w sieci.
Dostawca treści
sometimes it is required to share data across applications. This is where content providers become very useful.
Dostawcy zawartości umożliwiają scentralizowanie treści w jednym miejscu i udostępnienie wielu różnym aplikacjom w razie potrzeby. Dostawca zawartości zachowuje się bardzo podobnie do bazy danych, w której można wysyłać do niej zapytania, edytować jej zawartość, a także dodawać lub usuwać zawartość za pomocą metod insert (), update (), delete () i query (). W większości przypadków dane te są przechowywane w plikuSQlite Baza danych.
Dostawca treści jest implementowany jako podklasa ContentProvider class i musi implementować standardowy zestaw interfejsów API, które umożliwiają innym aplikacjom wykonywanie transakcji.
public class My Application extends ContentProvider {
}
Identyfikatory URI treści
Aby zapytać dostawcę treści, określ ciąg zapytania w postaci identyfikatora URI, który ma następujący format -
<prefix>://<authority>/<data_type>/<id>
Oto szczegóły różnych części identyfikatora URI -
Sr.No | Część i opis |
---|---|
1 | prefix To jest zawsze ustawione na content: // |
2 | authority Określa nazwę dostawcy treści, na przykład kontakty , przeglądarkę itp. W przypadku zewnętrznych dostawców treści może to być w pełni kwalifikowana nazwa, na przykład com.tutorialspoint.statusprovider |
3 | data_type Wskazuje rodzaj danych, które dostarcza ten konkretny dostawca. Na przykład, jeśli pobierasz wszystkie kontakty od dostawcy zawartości Kontaktów , ścieżka danych będzie wyglądać następująco: osoby, a identyfikator URI będzie wyglądał następująco : // kontakty / osoby |
4 | id Określa konkretny żądany rekord. Na przykład, jeśli szukasz numeru kontaktu 5 w dostawcy zawartości Kontaktów, identyfikator URI będzie wyglądał następująco : // kontakty / osoby / 5 . |
Utwórz dostawcę treści
Wymaga to wielu prostych kroków, aby utworzyć własnego dostawcę treści.
Przede wszystkim musisz utworzyć klasę Content Provider, która rozszerza klasę ContentProviderbaseclass.
Po drugie, musisz zdefiniować adres URI dostawcy treści, który będzie używany w celu uzyskania dostępu do treści.
Następnie będziesz musiał utworzyć własną bazę danych, aby zachować zawartość. Zazwyczaj system Android używa bazy danych SQLite, a framework musi przesłonić metodę onCreate () , która użyje metody SQLite Open Helper do utworzenia lub otwarcia bazy danych dostawcy. Po uruchomieniu aplikacji procedura obsługi onCreate () każdego z jej dostawców treści jest wywoływana w głównym wątku aplikacji.
Następnie będziesz musiał zaimplementować zapytania dostawcy treści, aby wykonać różne operacje specyficzne dla bazy danych.
Na koniec zarejestruj swojego dostawcę treści w pliku aktywności za pomocą tagu <provider>.
Oto lista metod, które należy zastąpić w klasie dostawcy treści, aby dostawca treści działał -
Dostawca treści
onCreate() Ta metoda jest wywoływana podczas uruchamiania dostawcy.
query()Ta metoda odbiera żądanie od klienta. Wynik jest zwracany jako obiekt Cursor.
insert()Ta metoda wstawia nowy rekord do dostawcy zawartości.
delete() Ta metoda usuwa istniejący rekord od dostawcy zawartości.
update() Ta metoda aktualizuje istniejący rekord od dostawcy zawartości.
getType() Ta metoda zwraca typ MIME danych pod podanym identyfikatorem URI.
Przykład
Ten przykład wyjaśnia, jak utworzyć własny dostawca treści . Wykonajmy więc następujące kroki, podobne do tych, które zastosowaliśmy podczas tworzenia przykładu Hello World -
Krok | Opis |
---|---|
1 | Użyjesz Android StudioIDE do stworzenia aplikacji dla systemu Android i nazwij ją jako Moja aplikacja w pakiecie com.example.MyApplication , z pustą aktywnością. |
2 | Zmodyfikuj główny plik aktywności MainActivity.java, aby dodać dwie nowe metody onClickAddName () i onClickRetrieveStudents () . |
3 | Utwórz nowy plik Java o nazwie StudentsProvider.java w pakiecie com.example.MyApplication, aby zdefiniować rzeczywistego dostawcę i powiązane metody. |
4 | Zarejestruj dostawcę zawartości w pliku AndroidManifest.xml za pomocą tagu <provider ... /> |
5 | Zmodyfikuj domyślną zawartość pliku res / layout / activity_main.xml , tak aby zawierał mały graficzny interfejs użytkownika do dodawania rekordów uczniów. |
6 | Nie trzeba zmieniać string.xml.Android studio zajmie się plikiem string.xml. |
7 | Uruchom aplikację, aby uruchomić emulator Androida i zweryfikować wynik zmian wprowadzonych w aplikacji. |
Poniżej znajduje się zawartość zmodyfikowanego pliku głównego działania src/com.example.MyApplication/MainActivity.java. Ten plik może zawierać każdą z podstawowych metod cyklu życia. Dodaliśmy dwie nowe metody onClickAddName () i onClickRetrieveStudents () do obsługi interakcji użytkownika z aplikacją.
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());
}
}
}
Utwórz nowy plik StudentsProvider.java w pakiecie com.example.MyApplication , a poniżej znajduje się zawartośćsrc/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);
}
}
}
Poniżej znajduje się zmodyfikowana zawartość pliku AndroidManifest.xml . Tutaj dodaliśmy tag <provider ... />, aby uwzględnić naszego dostawcę treści:
<?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>
Poniżej będzie treść res/layout/activity_main.xml plik−
<?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>
Upewnij się, że masz następującą zawartość res/values/strings.xml plik:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">My Application</string>
</resources>;
Spróbujmy uruchomić zmodyfikowany plik My Applicationaplikacja, którą właśnie stworzyliśmy. Zakładam, że stworzyłeś swójAVDpodczas konfigurowania środowiska. Aby uruchomić aplikację z Android Studio IDE, otwórz jeden z plików aktywności projektu i kliknij
Teraz wejdźmy do ucznia Name i Grade i na koniec kliknij Add Namespowoduje to dodanie rekordu ucznia do bazy danych i wyświetlenie komunikatu u dołu zawierającego identyfikator URI ContentProvider wraz z numerem rekordu dodanego do bazy danych. Ta operacja korzysta z naszegoinsert()metoda. Powtórzmy ten proces, aby dodać jeszcze kilku uczniów do bazy danych naszego dostawcy treści.
Gdy skończysz dodawać rekordy do bazy danych, pora poprosić ContentProvider o zwrócenie nam tych rekordów, więc kliknijmy Retrieve Students przycisk, który będzie pobierał i wyświetlał wszystkie rekordy jeden po drugim, zgodnie z naszą implementacją naszego query() metoda.
Możesz pisać działania przeciwko operacjom aktualizacji i usuwania, udostępniając funkcje wywołania zwrotnego w MainActivity.java plik, a następnie zmodyfikuj interfejs użytkownika, aby zawierał przyciski do aktualizacji i usuniętych operacji w taki sam sposób, jak zrobiliśmy dla operacji dodawania i odczytu.
W ten sposób możesz użyć istniejącego dostawcy treści, takiego jak książka adresowa, lub możesz użyć koncepcji dostawcy treści do tworzenia ładnych aplikacji zorientowanych na bazę danych, w których możesz wykonywać wszelkiego rodzaju operacje na bazie danych, takie jak odczyt, zapis, aktualizacja i usuwanie, jak wyjaśniono powyżej w przykładzie.