Контент-провайдеры


Компонент контент-провайдера предоставляет данные из одного приложения в другие по запросу. Такие запросы обрабатываются методами класса ContentResolver. Поставщик контента может использовать различные способы хранения своих данных, и данные могут храниться в базе данных, в файлах или даже по сети.

Контент-провайдеры позволяют вам централизовать контент в одном месте и иметь к нему доступ по мере необходимости. Поставщик контента ведет себя очень похоже на базу данных, в которой вы можете запрашивать его, редактировать его контент, а также добавлять или удалять контент, используя методы insert (), update (), delete () и query (). В большинстве случаев эти данные хранятся в базе данных SQlite .

Поставщик контента реализован как подкласс класса ContentProvider и должен реализовывать стандартный набор API, которые позволяют другим приложениям выполнять транзакции.

public class My Application extends ContentProvider {
}
URI контента
Чтобы запросить контент-провайдера, вы указываете строку запроса в виде URI, который имеет следующий формат –

<prefix>://<authority>/<data_type>/<id>
Вот деталь различных частей URI –

Sr.No Часть & Описание
1
префикс

Это всегда установлено на содержание: //

2
власть

Здесь указывается имя поставщика контента, например, контакты , браузер и т. Д. Для сторонних поставщиков контента это может быть полное имя, например com.tutorialspoint.statusprovider.

3
тип данных

Это указывает на тип данных, которые предоставляет этот конкретный поставщик. Например, если вы получаете все контакты от провайдера контента « Контакты» , то путь данных будет « люди», а URI будет выглядеть следующим образом : // contacts / people

4
Я бы

Это указывает конкретную запрошенную запись. Например, если вы ищете контактный номер 5 в поставщике контента для контактов, то URI будет выглядеть следующим образом : // contacts / people / 5 .

префикс

Это всегда установлено на содержание: //

власть

Здесь указывается имя поставщика контента, например, контакты , браузер и т. Д. Для сторонних поставщиков контента это может быть полное имя, например com.tutorialspoint.statusprovider.

тип данных

Это указывает на тип данных, которые предоставляет этот конкретный поставщик. Например, если вы получаете все контакты от провайдера контента « Контакты» , то путь данных будет « люди», а URI будет выглядеть следующим образом : // contacts / people

Я бы

Это указывает конкретную запрошенную запись. Например, если вы ищете контактный номер 5 в поставщике контента для контактов, то URI будет выглядеть следующим образом : // contacts / people / 5 .

Создать контент-провайдера
Это включает в себя ряд простых шагов для создания собственного поставщика контента.

Прежде всего вам нужно создать класс Content Provider, который расширяет класс ContentProviderbaseclass.

Во-вторых, вам нужно определить адрес URI вашего контент-провайдера, который будет использоваться для доступа к контенту.

Далее вам нужно будет создать собственную базу данных для хранения контента. Как правило, Android использует базу данных SQLite, и инфраструктура должна переопределить метод onCreate (), который будет использовать метод SQLite Open Helper для создания или открытия базы данных провайдера. Когда ваше приложение запускается, обработчик onCreate () каждого из его провайдеров контента вызывается в главном потоке приложения.

Затем вам нужно будет реализовать запросы контент-провайдера для выполнения различных операций с базой данных.

Наконец, зарегистрируйте своего провайдера контента в файле активности, используя тег <provider>.

Прежде всего вам нужно создать класс Content Provider, который расширяет класс ContentProviderbaseclass.

Во-вторых, вам нужно определить адрес URI вашего контент-провайдера, который будет использоваться для доступа к контенту.

Далее вам нужно будет создать собственную базу данных для хранения контента. Как правило, Android использует базу данных SQLite, и инфраструктура должна переопределить метод onCreate (), который будет использовать метод SQLite Open Helper для создания или открытия базы данных провайдера. Когда ваше приложение запускается, обработчик onCreate () каждого из его провайдеров контента вызывается в главном потоке приложения.

Затем вам нужно будет реализовать запросы контент-провайдера для выполнения различных операций с базой данных.

Наконец, зарегистрируйте своего провайдера контента в файле активности, используя тег <provider>.

Вот список методов, которые вам нужно переопределить в классе Content Provider, чтобы ваш Content Content работал:

поставщик услуг
Поставщик услуг
onCreate () Этот метод вызывается при запуске провайдера.

query () Этот метод получает запрос от клиента. Результат возвращается как объект Cursor.

insert () Этот метод вставляет новую запись в контент-провайдера.

delete () Этот метод удаляет существующую запись из провайдера контента.

update () Этот метод обновляет существующую запись от поставщика контента.

getType () Этот метод возвращает MIME-тип данных по указанному URI.

onCreate () Этот метод вызывается при запуске провайдера.

query () Этот метод получает запрос от клиента. Результат возвращается как объект Cursor.

insert () Этот метод вставляет новую запись в контент-провайдера.

delete () Этот метод удаляет существующую запись из провайдера контента.

update () Этот метод обновляет существующую запись от поставщика контента.

getType () Этот метод возвращает MIME-тип данных по указанному URI.

пример
Этот пример объяснит вам, как создать свой собственный ContentProvider . Итак, давайте следуем следующим шагам, аналогичным тому, что мы выполнили при создании Hello World Example –

шаг Описание
1 Вы будете использовать Android StudioIDE для создания приложения Android и назовите его « Мое приложение» в пакете com.example.MyApplication с пустым Activity.
2 Измените основной файл активности MainActivity.java, добавив два новых метода onClickAddName () и onClickRetrieveStudents () .
3 Создайте новый файл Java с именем StudentsProvider.java в пакете com.example.MyApplication, чтобы определить фактического поставщика и связанные методы.
4 Зарегистрируйте поставщика содержимого в файле AndroidManifest.xml с помощью тега <provider … />.
5 Измените содержимое по умолчанию в файле res / layout / activity_main.xml, добавив небольшой графический интерфейс для добавления записей учащихся.
6 Нет необходимости менять string.xml.Android studio позаботится о файле string.xml.
7 Запустите приложение, чтобы запустить эмулятор Android, и проверьте результат изменений, внесенных в приложение.
Ниже приводится содержимое измененного основного файла активности src / com.example.MyApplication / MainActivity.java . Этот файл может включать в себя каждый из основных методов жизненного цикла. Мы добавили два новых метода onClickAddName () и onClickRetrieveStudents () для обработки взаимодействия пользователя с приложением.

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());
}
}
}
Создайте новый файл StudentsProvider.java в пакете com.example.MyApplication , и ниже приведено содержимое 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);
}
}
}
Ниже будет измененный контент файла AndroidManifest.xml . Здесь мы добавили тег <provider … />, чтобы включить нашего поставщика контента:

<?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>
Ниже будет содержимое файла res / layout / activity_main.xml.

<?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>
Убедитесь, что у вас есть следующее содержимое файла res / values ​​/ strings.xml :

<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">My Application</string>
</resources>;
Давайте попробуем запустить наше модифицированное приложение My Application, которое мы только что создали. Я предполагаю, что вы создали свой AVD во время настройки среды. Чтобы запустить приложение из Android Studio IDE, откройте один из файлов деятельности вашего проекта и нажмите «Выполнить». Android StudioRun Icon значок из панели инструментов. Android Studio устанавливает приложение на AVD и запускает его, и, если все в порядке с настройками и приложением, оно будет отображаться после окна эмулятора, наберитесь терпения, поскольку это может занять некоторое время в зависимости от скорости вашего компьютера –

Демо-версия для Android-провайдера
Теперь давайте введем имя и оценку учащегося и, наконец, нажмем кнопку « Добавить имя» , это добавит запись учащегося в базу данных и высветит сообщение внизу с указанием URI ContentProvider вместе с номером записи, добавленным в базу данных. Эта операция использует наш метод insert () . Давайте повторим этот процесс, чтобы добавить еще несколько студентов в базу данных нашего контент-провайдера.

Добавить записи с помощью ContentProvider
Как только вы закончите добавлять записи в базу данных, теперь пришло время попросить ContentProvider вернуть нам эти записи, поэтому давайте нажмем кнопку « Восстановить студентов» , которая будет извлекать и отображать все записи по одной, что соответствует нашей реализации нашего Метод запроса () .

Вы можете записывать действия для операций обновления и удаления, предоставляя функции обратного вызова в файле MainActivity.java, а затем изменять пользовательский интерфейс, чтобы иметь кнопки для операций обновления и удаления таким же образом, как мы это делали для операций добавления и чтения.

Таким образом, вы можете использовать существующий контент-провайдер, такой как адресная книга, или концепцию контент-провайдера при разработке хороших приложений, ориентированных на базу данных, где вы можете выполнять все виды операций с базой данных, такие как чтение, запись, обновление и удаление, как описано выше в примере.