Поиск…


замечания

Поставщики контента управляют доступом к структурированному набору данных. Они инкапсулируют данные и предоставляют механизмы для определения безопасности данных. Поставщики контента - это стандартный интерфейс, который соединяет данные в одном процессе с кодом, запущенным в другом процессе.

Когда вы хотите получить доступ к данным в поставщике контента, вы используете объект ContentResolver в Context вашего приложения для связи с поставщиком как с клиентом. Объект ContentResolver связывается с объектом-провайдером, экземпляром класса, который реализует ContentProvider . Объект поставщика получает запросы данных от клиентов, выполняет запрошенное действие и возвращает результаты.

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

Сам Android включает поставщиков контента, которые управляют данными, такими как аудио, видео, изображения и личные контактные данные. Вы можете увидеть некоторые из них, перечисленные в справочной документации для пакета android.provider . С некоторыми ограничениями эти поставщики доступны для любого приложения Android.

Внедрение базового класса поставщика контента

1) Создать класс контракта

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

У провайдера обычно есть единый орган, который служит его внутренним именем Android. Чтобы избежать конфликтов с другими поставщиками, используйте уникальный контент. Поскольку эта рекомендация верна и для имен пакетов Android, вы можете определить полномочия своего поставщика как расширение имени пакета, содержащего поставщика. Например, если ваше имя пакета Android является com.example.appname , вы должны предоставить вашему провайдеру полномочия 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";
}

URI контента - это URI, который идентифицирует данные в провайдере. Контексты содержимого включают символическое имя всего поставщика (его полномочия) и имя, которое указывает на таблицу или файл (путь). Дополнительная часть id указывает на отдельную строку в таблице. Каждый метод доступа к данным ContentProvider имеет URI контента в качестве аргумента; это позволяет определить таблицу, строку или файл для доступа. Определите их в классе контракта.

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) Создайте класс помощника

Класс-помощник управляет созданием базы данных и управлением версиями.

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) Создайте класс, расширяющий класс 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;

UriMatcher отображает полномочия и путь к целочисленному значению. Метод match() возвращает уникальное целочисленное значение для URI (это может быть любое произвольное число, если оно уникально). Оператор switch выбирает между запросом всей таблицы и запросом для одной записи. Наш UriMatcher возвращает 100, если URI является URI содержимого таблицы и 101, если URI указывает на определенную строку внутри этой таблицы. Вы можете использовать подстановочный символ # чтобы соответствовать любому числу и * чтобы соответствовать любой строке.

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;
}

ВАЖНО: порядок addURI() имеет значение! UriMatcher будет выглядеть в последовательном порядке от первого добавленного к последнему. Так как подстановочные знаки типа # и * являются жадными, вам нужно убедиться, что вы правильно заказали свои URI. Например:

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

это правильный порядок, так как совпадение будет искать /example сначала, прежде чем прибегать к совпадению /* . Если эти вызовы методов были отменены, и вы вызвали uriMatcher.match("/example") , UriMatcher перестанет искать совпадения, как только встретит путь /* и вернет неправильный результат!

Затем вам необходимо переопределить эти функции:

onCreate () : Инициализировать вашего провайдера. Система Android вызывает этот метод сразу же после его создания. Обратите внимание, что ваш провайдер не создается до тех пор, пока объект ContentResolver не попытается получить к нему доступ.

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

getType () : возвращает тип MIME, соответствующий URI содержимого

@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 () : получение данных у вашего провайдера. Используйте аргументы, чтобы выбрать таблицу для запроса, строки и столбцы для возврата, а также порядок сортировки результата. Верните данные как объект Cursor.

@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;
}

Вставьте новую строку в свой провайдер. Используйте аргументы для выбора таблицы назначения и получения значений столбцов. Верните URI содержимого для вновь вставленной строки.

@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 () : удаление строк у вашего провайдера. Используйте аргументы для выбора таблицы и строк для удаления. Верните количество удаленных строк.

@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 () : обновить существующие строки в вашем провайдере. Используйте аргументы для выбора таблицы и строк для обновления и получения новых значений столбца. Верните количество обновленных строк.

@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) Обновить файл манифеста

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


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow