Android content provider downloads

Content provider (Контент-провайдер)

Что такое контент-провайдер

Контент-провайдер или «Поставщик содержимого» (Content Provider) — это оболочка (wrapper), в которую заключены данные. Если ваше приложение использует базу данных SQLite, то только ваше приложение имеет к ней доступ. Но бывают ситуации, когда данные желательно сделать общими. Простой пример — ваши контакты из телефонной книги тоже содержатся в базе данных, но вы хотите иметь доступ к данным, чтобы ваше приложение тоже могло выводить список контактов. Так как вы не имеете доступа к базе данных чужого приложения, был придуман специальный механизм, позволяющий делиться своими данными всем желающим.

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

В Android существует возможность выражения источников данных (или поставщиков данных) при помощи передачи состояния представления — REST, в виде абстракций, называемых поставщиками содержимого. Базу данных SQLite можно заключить в поставщик содержимого. Чтобы получить данные из поставщика содержимого или сохранить в нём новую информацию, нужно использовать набор REST-подобных идентификаторов URI. Например, если бы вам было нужно получить набор книг из поставщика содержимого, в котором заключена электронная библиотека, вам понадобился бы такой URI (по сути запрос к получению всех записей таблицы books):

Чтобы получить из библиотеки конкретную книгу (например, книгу №23), будет использоваться следующий URI (отдельный ряд таблицы):

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

Встроенные поставщики

В Android используются встроенные поставщики содержимого (пакет android.provider). Вот неполный список поставщиков содержимого:

На верхних уровнях иерархии располагаются базы данных, на нижних — таблицы. Так, Browser, СаllLog, Contacts, MediaStore и Settings — это отдельные базы данных SQLite, инкапсулированные в форме поставщиков. Обычно такие базы данных SQLite имеют расширение DB и доступ к ним открыт только из специальных пакетов реализации (implerentation package). Любой доступ к базе данных из-за пределов этого пакета осуществляется через интерфейс поставщика содержимого.

Создание собственного контент-провайдера

Для создания собственного контент-провайдера нужно унаследоваться от абстрактного класса ContentProvider:

В классе необходимо реализовать абстрактные методы query(), insert(), update(), delete(), getType(), onCreate(). Прослеживается некоторое сходство с созданием обычной базы данных.

А также его следует зарегистрировать в манифесте с помощью тега provider с атрибутами name и authorities. Тег authorities служит для описания базового пути URI, по которому ContentResolver может найти базу данных для взаимодействия. Данный тег должен быть уникальным, поэтому рекомендуется использовать имя вашего пакета, чтобы не произошло путаницы с другими приложениями, например:

Источник поставщика содержимого аналогичен доменному имени сайта. Если источник уже зарегистрирован, эти поставщики содержимого будут представлены гиперссылками, начинающимися с соответствующего префикса источника:

Итак, поставщики содержимого, как и веб-сайты, имеют базовое доменное имя, действующее как стартовая URL-страница.

Необходимо отметить, что поставщики содержимого, используемые в Android, могут иметь неполное имя источника. Полное имя источника рекомендуется использовать только со сторонними поставщиками содержимого. Поэтому вам иногда могут встретиться поставщики содержимого, состоящие из одного слова, например contacts, в то время как полное имя такого поставщика содержимого — com.google.android.contacts.

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

URI для идентификации отдельно взятой записи будет иметь вид:

Символ # соответствует конкретной записи (ряд таблицы). Ниже приведено еще несколько примеров URI, которые могут присутствовать в поставщиках содержимого:

Обратите внимание — здесь поставщики содержимого content://media и content://contacts имеют неполную структуру. Это обусловлено тем, что данные поставщики содержимого не являются сторонними и контролируются Android.

Структура унифицированных идентификаторов содержимого (Content URI)

Для получения данных из поставщика содержимого нужно просто активировать URI. Однако при работе с поставщиком содержимого найденные таким образом данные представлены как набор строк и столбцов и образуют объект Android cursor. Рассмотрим структуру URI, которую можно использовать для получения данных.

Унифицированные идентификаторы содержимого (Content URI) в Android напоминают HTTP URI, но начинаются с content и строятся по следующему образцу:

Вот пример URI, при помощи которого в базе данных идентифицируется запись, имеющая номер 23:

После content: в URI содержится унифицированный идентификатор источника, который используется для нахождения поставщика содержимого в соответствующем реестре. Часть URI ru.alexanderklimov.provider.notepad представляет собой источник.

/notes/23 — это раздел пути (path section), специфичный для каждого отдельного поставщика содержимого. Фрагменты notes и 23 раздела пути называются сегментами пути (path segments). Одной из функций поставщика содержимого является документирование и интерпретация раздела и сегментов пути, содержащихся в URI.

Читайте также:  Толкования библии для андроид

UriMatcher

Провайдер имеет специальный объект класса UriMatcher, который получает данные снаружи и на основе полученной информации создаёт нужный запрос к базе данных.

Вам нужно задать специальные константы, по которым провайдер будет понимать дальнейшие действия. Если используется одна таблица, то обычно применяют две константы — любые два целых числа, например, 100 для таблицы и 101 для отдельного ряда таблицы. Схематично можно изобразить так.

URI pattern Code Contant name
content://ru.alexanderklimov.provider.notepad/notes 100 NOTES
content://ru.alexanderklimov.provider.notepad/notes/# 101 NOTES_ID

В коде с помощью switch создаётся ветвление — хотим ли мы получить информацию о всей таблице (код 100) или к конкретному ряду (код 101).

Приложение может быть сложным и иметь несколько таблиц. Тогда и констант будет больше. Например, так.

URI pattern Code Contant name
content://com.android.contacts/contacts 1000 CONTACTS
content://com.android.contacts/contacts/# 1001 CONTACTS_ID
content://com.android.contacts/lookup/* 1002 CONTACTS_LOOKUP
content://com.android.contacts/lookup/*/# 1003 CONTACTS_LOOKUP_ID
. . .
content://com.android.contacts/data 3000 DATA
content://com.android.contacts/data/# 3001 DATA_ID
. . .

Символ решётки (#) отвечает за число, а символ звёздочки (*) за строку.

Метод query()

Метод query() является обязательным для класса ContentProvider. Если мы используем контент-провайдер для обращения к базе данных, то в нём вызывает одноимённый метод SQLiteDatabase. Состав метода практически идентичен.

Вам нужно программно получить необходимые данные для аргументов метода. Обратите внимание на метод ContentUris.parseId(uri), который возвращает последний сегмент адреса, в нашем случае число 3, для Selection Args.

Метод insert()

Метод insert() содержит два параметра — URI и ContenValues. Первый параметр работает аналогично, как в методе query(). Вторая вставляет данные в нужные колонки таблицы.

Для вставки используется вспомогательный метод insertGuest().

Структурирование МIМЕ-типов в Android

Как веб-сайт возвращает тип MIME для заданной гиперссылки (это позволяет браузеру активировать программу, предназначенную для просмотра того или иного типа контента), так и в поставщике содержимого предусмотрена возможность возвращения типа MIME для заданного URI. Благодаря этому достигается определенная гибкость при просмотре данных. Если мы знаем, данные какого именно типа получим, то можем выбрать одну или несколько программ, предназначенных для представления таких данных. Например, если на жестком диске компьютера есть текстовый файл, мы можем выбрать несколько редакторов, которые способны его отобразить.

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

Обозначение MIME состоит из двух частей: типа и подтипа. Ниже приведены примеры некоторых известных пар типов и подтипов MIME:

text/html
text/css
text/xml
image/jpeg
audio/mp3
video/mp4
application/pdf
application/msword

Основные зарегистрированные типы содержимого:

application
audio
image
message
model
multipart
text
video

В Android применяется схожий принцип для определения типов MIME. Обозначение vnd в типах MIME в Android означает, что данные типы и подтипы являются нестандартными, зависящими от производителя. Для обеспечения уникальности в Android типы и подтипы разграничиваются при помощи нескольких компонентов, как и доменные имена. Кроме того, типы MIME в Android, соответствующие каждому типу содержимого, существуют в двух формах: для одиночной записи и для нескольких записей.

Типы MIME широко используются в Android, в частности при работе с намерениями, когда система определяет по МIМЕ-типу данных, какое именно явление следует активировать. Типы MIME всегда воспроизводятся контент-провайдерами на основании соответствующих URI. Работая с типами MIME, необходимо не упускать из виду три аспекта.

  1. Тип и подтип должны быть уникальными для того типа содержимого, который они представляют. Обычно это каталог с элементами или отдельный элемент. В контексте Android разница между каталогом и элементом может быть не такой очевидной, как кажется на первый взгляд.
  2. Если тип или подтип не являются стандартными, им должен предшествовать префикс vnd (обычно это касается конкретных видов записи).
  3. Обычно типы и подтипы относятся к определенному пространству имен в соответствии с вашими нуждами.

Необходимо еще раз подчеркнуть этот момент: основной тип MIME для коллекции элементов, возвращаемый командой cursor в Android, всегда должен иметь вид vnd.android.cursor.dir, а основной тип MIME для одиночного элемента, находимый командой cursor в Android, — вид vnd.android.cursor.item. Если речь идет о подтипе, то поле для маневра расширяется, как в случае с vnd.googlе.note; после компонента vnd. вы можете свободно выбирать любой устраивающий вас подтип.

ContentResolver

Каждый объект Content, принадлежащий приложению, включает в себя экземпляр класса ContentResolver, который можно получить через метод getContentResolver().

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

Источник

Programming VIP

Very Interesting Programming

Android content provider in 2020

Junior to intermediate

1. What is the content provider?

Content Provider is mainly used to realize the function of data sharing between different applications. It provides a complete set of mechanism, which allows one program to access the data in another program, and also ensures the security of the accessed data. Currently, using content providers is the standard way for Android to share data across programs.
different from the two global readable and writable operation modes in file storage and SharedPreferences storage, the content provider can choose which part of the data to share, so as to ensure that the privacy data in our program will not be disclosed.

Читайте также:  Как удалить файлы с андроида без возможности восстановления

2. Use of content providers & what content providers are provided by the system

2.1 use of content providers

We usually use content providers to query data:

Cursor cursor = getContentResolver().query(final Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal)

  • uri, which specifies to query a table under a program
  • Project, specifying the column name of the query
  • selection, which specifies the query condition, equivalent to the condition after where in the sql statement
  • selectionArgs, which provides specific values to placeholders in the selection
  • orderBy, specify the sorting method of query results
  • Cancelationsignal, canceling the semaphore of the operation in progress

you who have written SQLite code must be very familiar with this method! When you see the principle and mechanism of ContentProvider, you will realize it!

if you want to access the shared data in the content provider, you must use the covertresolver class, and you can get an instance of this class through the getContentResolver() method in the Context. A series of methods are provided in ContentResolver for CRUD (add, delete, modify and query) operation of data, among which insert() method is used to add data, update() method is used to update data, delete() method is used to delete data, query() method is used to query data. It seems that SQLite database operation has some problems?
. The content URI establishes a unique identifier for the data in the content provider, which consists of two parts: authority and path. Authority is used to distinguish different applications. In general, in order to avoid conflicts, it uses the way of package name to name. For example, if the package name of a program is com.example.app, the corresponding authority of the program can be named com.example.app.provider. Path is used to distinguish different tables in the same application, which is usually added after authority. For example, there are two tables in the database of a program: table1 and table2. In this case, you can name the path as / table1 and / table2 respectively, and then combine the authority and path. The URI of the content becomes com.example.app.provider/table1 and com.example.app.provider/table2. However, at present, it is difficult to recognize that these two strings are two content URIs. We need to add a protocol declaration to the head of the string. Therefore, the most standard format of content URI is as follows:

after getting the content URI string, we need to parse it into a URI object before we can pass it in as a parameter. The parsing method is also quite simple, and the code is as follows:

just call the static method parse() of URI to parse the content URI string into a URI object.
now, we can query the data in the table1 table through the Uri object. The code is as follows:

The parameters received by the query() method are similar to those received by the query() method in SQLiteDatabase, but in general, this is a little simpler. After all, this is to access data in other programs, so it is unnecessary to build complex query statements. The subscript explains in detail the parameters received by query in the content provider:

After the query is completed, a Cursor object will still be returned. At this time, we can read the data from the Cursor object one by one. The idea of reading is still to traverse the Cursor object, and then take out the data one by one. The code is as follows:

3. How to create content providers that belong to their own applications?

. There are six abstract methods in the ContentProvider class. When we use a subclass to inherit it, we need to rewrite all the six methods. Create a new MyProvider inherits the ContentProvider class. The code is as follows:

1.onCreate() method:
called when the content provider is initialized. Usually, the creation and upgrade of the database will be completed here. Return true to indicate successful content provider initialization, and false to indicate failure. Note that the content provider is initialized only if there is a ContentResolver trying to access data in our program.

2.query() method:
queries data from the content provider. The uri parameter is used to determine which table to query, the project parameter is used to determine which column to query, the selection and selectionArgs parameters are used to constrain which rows to query, the sortOrder parameter is used to sort the results, and the results of the query are stored in the Cursor object and returned.

3.insert() method:
add a piece of data to the content provider. The URI parameter is used to determine the table to be added, and the data to be added is saved in the values parameter. When the addition is complete, a URI representing the new record is returned.

4.update() method:
Update existing data in the content provider. The uri parameter is used to determine which table data to update. The new data is stored in the values parameter. The selection and selectionArgs parameters are used to constrain which rows to update. The number of affected rows will be returned as the return value.

Читайте также:  Восстановить пароль от вайфая андроид

5.delete() method:
delete data from the content provider. The uri parameter is used to determine which table data to delete. The selection and selectionArgs parameters are used to constrain which rows to delete. The number of deleted rows will be returned as the return value.

6.getType() method:
returns the corresponding MIME type based on the incoming content URI.

as you can see, almost every method has the Uri parameter, which is passed when the ContentResolver’s add, delete, modify and query method is called. Now, we need to parse the incoming Uri parameter, from which we can analyze the table and data that the call places the expected access.
recall that a standard content URI is written as follows:

this means that the caller expects to access the data in the table1 table of the application com.example.app. In addition, we can add an id after the content URI as follows:

this means that the caller expects to access the data with id 1 in the table1 table of the application com.example.app. There are two main formats of content URI. The end of the path indicates the expected access to all data in the table, and the result of id indicates the expected access to data with corresponding id in the table. We can use wildcards to match the content URIs of these two formats. The rules are as follows:

  • *: means to match any character of any length.
  • #: any number that matches any length.

Therefore, a content URI format that can match any table can be written as:

and a content URI format that can match any row of data in the table table can be written as:

next, we can easily match the content URI with the help of UriMatcher. UriMatcher provides an addURI() method, which takes three parameters and can pass in authority,path and a custom code. The custom code is actually a final int value. In this way, when the match() method of UriMatcher is called, a URI object can be passed in. The return value is a custom code that can match the URI object. With this code, we can determine which data in the table the caller expects to access. Modify the above MyProvider code as follows:

the above code is just an example of query() method. In fact, the implementation of insert() method, update(),delete() method.
. It is a method that all content providers must provide to get the MIME type corresponding to the URI object. The mime string corresponding to a content URI is mainly composed of three parts. Android has the following format requirements for these three parts:

  • Must start with vnd
  • If the content URI ends with a path, it is followed by android.cursor.dir /, if the content URI ends with an id, it is followed by android.cursor.item /.
  • Finally, connect to vnd.

now, we can continue to improve the content of MyProvider class. This time, we implement the logic of getType() method, and the code is as follows:

here, a complete content provider is created, and now any application can use it ContentResolver to access the data in our program. So, as mentioned above, how can we ensure that the privacy data will not leak out? In fact, thanks to the good mechanism of content provider, this problem has been solved unconsciously. Because all CRUD operations must be matched to the corresponding content URI format, of course, we can’t add the URI of privacy data to the UriMatcher, so this part of data can’t be accessed by external programs at all, and the security problem doesn’t exist.
The function of sequence data sharing.

It’s not over yet? We all know that the four components need to be registered in the Android manifest.xml file. Now that the completed content provider is written, the next step is to register in the Android manifest.xml file, and then the content provider can be used. Let’s take an example to explain. The encapsulation code of a standard content provider is as follows:

The Android manifest.xml file registers the content provider with the label .

the creation process of such a complete content provider is finished.

senior

1. Principle and mechanism of contentleader

In fact, the content provider can be accessed across programs, which can be considered as a way of inter process communication. In fact, the core of its principle is Binder.

2. Some wheels or SDK s do not need to be initialized. why?

Interview questions (test how you learn)

  • 1. What is content provider? (school recruitment & Practice)
  • 2. Talk about how to create the content provider of your own application & usage scenarios. (school recruitment & Practice)
  • 3. Talk about the principle of ContentProvider.
  • 4. What is the relationship among ContentProvider, contentresolver and contentobserver?
  • 5. Talk about the permission management of ContentProvider.

Note: the interview questions at the end of the article are from the author’s own summary, to seek answers or exchange, start author GitHub project AndroidFaceInterview

Updated on: January 17, 2020

Added by lady_bug on Fri, 17 Jan 2020 12:51:11 +0200

Источник

Оцените статью