Android
Поставщик услуг
Поиск…
замечания
Поставщики контента управляют доступом к структурированному набору данных. Они инкапсулируют данные и предоставляют механизмы для определения безопасности данных. Поставщики контента - это стандартный интерфейс, который соединяет данные в одном процессе с кодом, запущенным в другом процессе.
Когда вы хотите получить доступ к данным в поставщике контента, вы используете объект 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"/>