<span id="Label3"></p><p><p>This document is translated from Android official documentation, combined with your own tests, organized as Follows.</p></p><p><p>Content providers is able to manage structured datasets, encapsulate data, and provide a mechanism for data security. Content providers is a standard interface that can be shared across process Data. Chinese can be called a content provider.</p></p><p><p>When we want to get data from content providers, We can use the Contentresolver object to access the providers the most Clients. The Contentresolver object can communicate with the content provider instance, which is an instance of a subclass of the ContentProvider class that inherits the abstract class. The Content provider receives request data from the client (contentresolver object), executes the request action, and returns the result of the Request.</p></p><p><p>If we do not intend to share data with other applications, we do not need to create our own content Provider. If this is the case, a content provider is required to provide personalized query Suggestions. also, If you want to copy and paste complex data or files from your program into other programs, we should also provide content Provider.</p></p><p><p>The Android system itself also includes content providers for managing videos, audio, images, contacts, and More. Our applications can use these content providers when conditions are met.</p></p>Content Provider Basics<p><p>Content provider is part of an Android application that also provides a UI for interacting with the Data. however, content providers is primarily intended for use by other Programs. The providers and providers clients provide a consistent standard interface for data that can handle cross-process communication and secure access to Data.</p></p><p><p>This section describes the following topics:</p></p> <ul> <ul> <li>Content provider Operation Mechanism.</li> <li>The API that we can use when accessing data through Contentprovider.</li> <li>The API that we can use in Contentprovider.</li> <li>Other APIs for easy operation of Provider.</li> </ul> </ul>Overview<p><p>Content provider can expose data to other applications through one or more tables that resemble tables in a relational database. A row in the table represents a data record, and each column represents a type value for that Record. This doesn't have to be described too much.</p></p><p><p>Note: the provider does not need to provide a primary key, but you must provide a primary key named _id if you want to associate with the LISTVIEW. The following is a detailed Introduction.</p></p>Visit provider<p><p>The application accesses the data in the content provider through an abstract class Contentresovler object, which has the same method as the ContentProvider object and is capable of crud the persisted stored data ( Create,retrieve,update,and delete).</p></p><p><p>The Contentresovler object in the client program process and the ContentProvider object in the program that owns the provider automatically handle cross-process Communication. The ContentProvider object also acts as an abstraction layer for the external representation of datasets and Data.</p></p><p><p>of course, to access provider, you must have the appropriate license (permissions). Here is a detailed description.</p></p><p><p>For example, to query the data in the provider table, we can call <code>ContentResolver.query()</code> , and then the method calls the ContentProvider implementation of the class object <code>query()</code> . For example, the following code:</p></p><pre class="prettyprint"><pre class="prettyprint"><code class="language-java hljs "><span class="hljs-comment">// 在Activity中直接调用getContentResovler()方法获取ContentResovler实例</span>Cursor mCursor = getContentResovler().query( uri, <span class="hljs-comment">// 字符串数组,可设置为null,表示读取所有列</span> <span class="hljs-comment">// 字符串约束条件,可设置为null没有约束</span> <span class="hljs-comment">// 字符串数组,是约束条件的具体取值,</span> <span class="hljs-comment">// 字符串</span></code></pre></pre><p><p>There is a detailed explanation of the cursor object returned below, for the time Being. The following table shows <code>query()</code> how the parameters in the method match the SQL Select Statement:</p></p> <table> <thead> <tr> <th>Parameters</th> <th>corresponding SQL section</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td>Uri</td> <td>From table_name</td> <td>Specify the TABLE_NAME table under the query application</td> </tr> <tr> <td>Mprojection</td> <td>Select Column1,column2 ...</td> <td>Specify the column name of the query</td> </tr> <tr> <td>Mselectionclause</td> <td>WHERE Column1 = value</td> <td>Specify where constraints for a query</td> </tr> <tr> <td>Mselectionargs</td> <td>-</td> <td>Provide a value for a placeholder in where</td> </tr> <tr> <td>Msortorder</td> <td>ORDER by Column1,column2 ...</td> <td>Specify how query results are sorted</td> </tr> </tbody> </table>Content URIs<p><p>The content URI establishes a unique identifier for the data in the content provider, which consists mainly of the permissions (aythority) and the path two Parts. Permissions are provider names that are used to differentiate applications, and the path is the name of the table used to differentiate between different tables in the Program. This forms the content Uri. For example, a provider name is: <code>com.sywyg.provider</code> , a table name Is: <code>table1</code> . The final URI string Is: <code>content://com.sywyg.provider/table1</code> . Which <code>content://</code> is the protocol that represents the URI as the content Uri. After you get the URI string, you can resolve it to a URI object by using the following method:<br><code>Uri uri = Uri.parse("content://com.sywyg.provider/table1");</code></p></p><p><p>Most providers can access a single line by specifying an ID (for example, accessing the second row):<br><code>Uri uri = ContentUris.withAppendedId("content://com.sywyg.provider/table1",2);</code></p></p><p><p>Note: URIs and Uri.builder classes can easily construct a Standard-format uri through a string. The Contenturis class is able to easily add an ID to the uri, such as the example Above.</p></p>Retrieving data from provider<p><p>This section describes how to retrieve data from the Provider.</p></p><p><p>To facilitate the description, the <code>ContentResolver.query()</code> query method is written in the UI thread, but in practice, asynchronous queries should be made in the child THREADS. One of the methods you want to implement in a child thread is to use the Cursorloader class (not yet organized). This section is explained in detail in the loader under the official document activity, which has not been collated yet.</p></p><p><p>Retrieving data from provider requires the following two steps:</p></p> <ol> <ol> <li>Request access permission for provider (permission);</li> <li>Send to Provider query Request.</li> </ol> </ol>Request permission<p><p>To Retrieve/query data, A license is required <code>read access</code> and we cannot set the license when the program is Run. therefore, The license must be specified in the manifest configuration file and the <code><uses-permission></code> permissions defined by the provider are set through the Label.<br>For example, if we want to get contact information, We can manifest the file in our Program:</p></p><p><p><code><uses-permission android:name="android.permission.READ_CONTACTS"/></code></p></p>Building query Statements<p><p>After setting up the license in the previous step, we can query the tables in Provider. <code>query()</code>set specific query statements by Contentresolver object methods, which have been <code>query()</code> used in Detail.</p></p>Handling malicious input<p><p>When manipulating data, be careful with SQL Injection. For example, Enter a <code>query()</code> method in which the parameters are <code>mSelectionClause</code> set to:<br><code>String mSelectionClause = "var = " + mUserInput;</code><br>In this case, it is possible to cause a malicious SQL attack, such as <code>mUserInput</code> being assigned a value of ' Nothing;drop table *; ', then provider may delete all the Tables.</p></p><p><p>therefore, We should assign a value to a constraint by means of a placeholder, in which case the value given by the placeholder is used only as a condition of the query and not connected to the SQL Statement. For example, the above input can be done in the following way:</p></p><pre class="prettyprint"><pre class="prettyprint"><code class="language-java hljs ">String mSelectionClause = <span class="hljs-string">"var = ?"</span>;String[] selectionArgs = {<span class="hljs-string">""</span>};selectionArgs[<span class="hljs-number">0</span>] = mUserInput;</code></pre></pre><p><p>Where Selectionargs is <code>query()</code> the fourth Parameter.</p></p><p><p>Even though the provider does not rely on SQL databases, the methods specified above are also possible with Placeholders.</p></p>Show Query Results<p><p><code>query()</code>method returns a cursor object so that we can read the query results from the Cursor. Provider may restrict access to specific columns, which may result in access to specific columns. If the query result is empty, the method in the cursor <code>getCount()</code> is 0. If the query has an error, the result will depend on the specific provider, some may return null, and some throw an Exception.</p></p><p><p>Because the cursor is a row, it is a good choice to display the data on the ListView via Simplecursoradapter. To display on a listview, the table must have an ID column, which the listview retrieves by ID. therefore, It is generally necessary to provide an ID column for Providers.</p></p>Getting data from query results<p><p>We know that <code>query()</code> . returns a cursor object from which we can obtain the desired Data. Traversing all the cursor lines by moving the cursor, the sample code is as Follows:</p></p><pre class="prettyprint"><code class="language-java hljs "><span class="hljs-comment"><span class="hljs-comment">//determines The column number, which is the column for information</span></span><span class="hljs-keyword"><span class="hljs-keyword">int</span></span>index = Mcursor.getcolumnindex (<span class="hljs-string"><span class="hljs-string">"column1"</span></span>);<span class="hljs-comment">/ <span class="hljs-comment">* * Only executes if the cursor is VALID. * Only if cursor is non-empty</span> * *</span><span class="hljs-keyword"><span class="hljs-keyword">if</span></span>(mcursor! =<span class="hljs-keyword"><span class="hljs-keyword">NULL</span></span>) {<span class="hljs-comment">/ <span class="hljs-comment">* * Moves to the next row in the Cursor. Before the first movement in the cursor, the * ' Row pointer ' is-1, and if you try to retrieve data at that position y OU'LL Get an * Exception. * Moves to the next line, the line number starts at 1, so the first move is to line No. 0. */</span></span> <span class="hljs-keyword"><span class="hljs-keyword"></span> while</span>(mcursor.movetonext ()) {<span class="hljs-comment"><span class="hljs-comment">//read The data in the index column</span></span>Newword = mcursor.getstring (index);<span class="hljs-comment"><span class="hljs-comment">//Insert code here to process the retrieved Word.</span></span>...<span class="hljs-comment"><span class="hljs-comment">//end</span> of While loop</span>} mcursor.close (); }<span class="hljs-keyword"><span class="hljs-keyword">Else</span></span>{<span class="hljs-comment"><span class="hljs-comment">//Insert code here to report a error if the cursor is a null or the provider threw an Exception.</span></span>}}</code></pre><p><p><code>moveToNext()</code>The iterator method moves the cursor to the next line and then passes the value of the <code>getXXX(int)</code> row that can get the corresponding column (is not the usage, as in the case of an iterator,,,,). The cursor has a series of <code>getXXX(int)</code> methods for returning the corresponding value in the column (the column is the value of that type), such as above <code>getString()</code> . The same can be done by <code>getType()</code> returning the type of data in a Column. There are other methods in the cursor <code>getXXX()</code> , such as <code>getColumnIndex("column1")</code> getting the index of the specified column Above.</p></p>Content Provider License (permission)<p><p>Provider The specified license must be declared in a program that uses the Provider. The license ensures that the user knows what kind of data the program wants to Get. An external program cannot use the provider if the license is not set. however, the components in the same program as provider can be arbitrarily acquired, even if there is a license.</p></p><p><p>You can set permissions in the manifest configuration file by using '. When you install the program on android, the user must ensure that all licenses requested by the program are authorized, or the program cannot be Installed.</p></p>Insert/update/delete Data Insert Data<p><p>The <code>ContentResolver.insert()</code> method enables you to insert data into a table in provider, returning the URI of the inserted row. For example:</p></p><pre class="prettyprint"><pre class="prettyprint"><code class="language-java hljs "><span class="hljs-comment">// 接收插入返回值</span>Uri mNewUri;<span class="hljs-comment">// 将要插入的数据保存在ContentValues(内部是hashMap实现)</span><span class="hljs-keyword">new</span> ContentValues();<span class="hljs-comment">// 设置每一列的值,参数为列和值</span>mNewValues.put(<span class="hljs-string">"column1"</span><span class="hljs-string">"example"</span>);<span class="hljs-comment">// 插入到某个表中,参数为Uri和插入的ContentValues</span>mNewUri = getContentResolver().insert(uri,mNewValues);</code></pre></pre><p><p>By setting the value in the table to be inserted by the Contentvalues object, the type of the value set in the object does not need to match the type of the value in the actual Column. If you do not want to set a column, you can <code>putNull("column2")</code> set it by Null. For IDs in provider, you do not need to specify a value that is automatically added as the primary key.</p></p><p><p><code>insert()</code>The URI format returned for the method is as Follows:<br><code>content://authority/table/行号id</code><br>The line can be accessed through this URI by obtaining an <code>ContentUris.parseId(uri)</code> ID (that is, intercepting the last part of the URI with an id).</p></p>Update data<p><p>by <code>ContentResolver.update()</code> Updating the data, you can simply set it to NULL if you want to clear the Value.</p></p><p><p>The simple code is as follows;</p></p><pre class="prettyprint"><pre class="prettyprint"><code class="language-java hljs "><span class="hljs-comment">// 同样使用ContentValues设置更新的数据</span><span class="hljs-keyword">new</span> ContentValues();<span class="hljs-comment">// 定义约束条件,更新第column1列值为example的行。。。。。</span><span class="hljs-string">"column1 = ?"</span>;String[] mSelectionArgs = {<span class="hljs-string">"example"</span>};<span class="hljs-comment">// 接收修改行。</span><span class="hljs-keyword">int</span><span class="hljs-number">0</span>;mUpdateValues.putNull(<span class="hljs-string">"column2"</span>);mRowsUpdated = getContentResolver().update( uri, mUpdateValues, mSelectionClause, mSelectionArgs);</code></pre></pre><p><p><code>update()</code>The four parameters in the <code>query()</code> same as the first four Parameters.</p></p>Delete data<p><p>By <code>ContentResolver.delete()</code> Deleting the data, the method receives three parameters: uri,mselectionclause,mselectionargs. <code>update()</code>only one Contentvalues object is missing compared to the parameters in the Method.</p></p><p><p>The above crud is spelled as a simple SQL statement:</p></p> <ul> <ul> <li>Query: SELECT * FROM table1 where range</li> <li>Insert: INSERT INTO Table1 (column1,column2) values (value1,value2)</li> <li>Updated: Update table1 set column1=value1 where range</li> <li>Delete: Delete from table1 where range</li> </ul> </ul>Data types for Content provider<p><p>Content Provider provides the following types:</p></p> <ul> <ul> <li>Integer</li> <li>Long Integer (long)</li> <li>Floating point</li> <li>Long floating point (double)</li> <li>Text</li> </ul> </ul><p><p>For other data types, provider uses a 64KB byte array blob (Binary Large OBject) to store Data. BLOBs are the types of fields in a database that are used to store binary Files.</p></p><p><p>Provider also supports MIME data types, which are used to represent defined Uris. Here is a detailed explanation.</p></p>Other forms of access to provider<p><p>There are three types of access options available:</p></p> <ul> <ul> <li>Batch Access: batching Form<br>You can implement a set of accesses through the contentprovideroperation class, using <code>ContentResolver.applyBatch()</code> operations.</li> <li>Asynchronous query<br>You need to do data processing in another THREAD. You can use the Cursorloader object Implementation.</li> <li>Access via intents<br>Although it is not possible to send intent directly to provider, it is best to implement the method of modifying provider data by sending intent to the application where provider is Located.</li> </ul> </ul><p><p>The following is a detailed description of batch and the intents approach, as for asynchronous queries, which are described in the loaders documentation in the Activity.</p></p>Batch Access<p><p>Batch access is useful when you need to insert large amounts of row data or insert into multiple tables.</p></p><p><p>You can implement a set of accesses through the contentprovideroperation class, using <code>ContentResolver.applyBatch()</code> operations.</p></p><p><p>For example, a set of insert operations is performed below:</p></p><pre class="prettyprint"><pre class="prettyprint"><code class="language-java hljs "><span class="hljs-comment">// 创建一组ContentProviderOperation对象,每一个对象代表一次CRUD操作</span>ArrayList<ContentProviderOperation> ops = <span class="hljs-keyword">new</span><span class="hljs-keyword">int</span><span class="hljs-comment">// 通过ContentProviderOperation类中的Builder类的build()方法创建ContentProviderOperation对象</span><span class="hljs-comment">// 没记错的话这应该是建造者模式</span> ops.add(ContentProviderOperation.newInsert(uri) .withValue(<span class="hljs-string">"column1"</span><span class="hljs-string">"value1"</span>) .withValue(<span class="hljs-string">"column2"</span><span class="hljs-string">"value2"</span>) .build()); getContentResolver().applyBatch(authority,ops);</code></pre></pre>Access using intents<p><p>The content provider can be accessed indirectly through Intent. Even without permission, we can implement indirect access through the results returned by Intent.</p></p>Obtaining temporary permission<p><p>Without permission, we can send intent to another licensed program and return a intent object with a URI Permission. These specified URI licenses will persist until the activity that receives the permission is Destroyed. A program that has a perpetual license authorizes a temporary license by setting the flag attribute of the Intent:</p></p> <ul> <ul> <li>Read License:<code>FLAG_GRANT_READ_URI_PERMISSION</code></li> <li>Write permission<code>FLAG_GRANT_WRITE_URI_PERMISSION</code></li> </ul> </ul><p><p>Note that these flags are not read-write provider, but allow access to the URI Itself.</p></p>Display data using the helper app<p><p>If our application is not licensed, we still want to display data for another program through Intent. For example, a calendar program that receives a Action_view type of intent can display a date or an Event. This allows you to display calendar information without having to create your own ui. Programs that send intent do not need to be associated with provider Programs.</p></p><p><p>Provider can define the URI permission in the manifest file <code><provider></code> <code><android:grantUriPermission></code> , as well as the <code><provdier></code> child tags <code><grant-uri-permission></code> .</p></p><p><p>For example, We can retrieve contact data from contacts provider, even without a read_contacts license. Maybe we just need to read a contact's information, so we don't need to ask for a read_contacts license to access all of our contacts, allowing the user to choose which contact our program can Read. You need to complete the following steps:</p></p> <ol> <ol> <li> <p> Sends an action (setaction ()) and Content_item_ with Action_pick by <code> Startactivityforresult () </code> Type of the Contact's MIME type (setType ()) of the Intent, code as follows: </p> <pre class="prettyprint"><code class="language-java hljs">intent Intent = <span class="hljs-keyword">new </span> Intent (); intent.setaction (intent.action_pick); Intent.settype ( ContactsContract.RawContacts.CONTENT_ITEM_TYPE); startactivityforresult (intent,resultcode); </code> </pre> </li> <li> because intent matches the Activity's intent filter for the contact app, the activity will be displayed in the Foreground. </li> <li> in this activity, the user selects a contact, and the activity invokes the <code> Setresult (resultcode,intent) </code> Setting intent and returns to our Application. The intent includes: the URI of the user-selected contact, and the flags of <code> flag_grant_read_uri_permission </code>. These flags grant our program a URI permission to read the URI for the specified contact. finally, the activity calls <code> finish () </code> to Destroy. This process is done with the contact app. </li> <li> Our activity returns to the foreground, and the system calls the <code> Onactivityresult () </code> method, which receives the intent just passed IN. </li> <li> with intent, We can read the contacts in the contacts provider (with <code> intent.getdata () </code> to get the uri, then intercept the id, query by id), Even if we do not set the read license in the manifest File. </li> </ol> </ol>Use a different application<p><p>We can use another licensed application to operate the Provider. For example, if we want to insert events into the calendar, we can start the calendar program with Action_insert intent and have the calendar program insert it.</p></p>MIME type<p><p>MIME (multipurpose Internet Mail EXTENSIONS) is an Internet standard that describes data Types.<br>Content providers can return a standard MIME media type, or a custom MIME type string, or Both.<br>The MIME type format is:</p></p><p><p><code>type/subtype</code></p></p><p><p>For example, well-known MIME types have <code>text/html</code> text types and HTML Subtypes.<br>Custom MIME type strings, also known as "vendor-specific" mime types, have more complex types and subtypes. For multiple lines, the type is usually:</p></p><p><p><code>vnd.android.cursor.dir</code></p></p><p><p>For a single line:</p></p><p><p><code>vnd.androi.cursor.item</code></p></p><p><p>Subtypes are specified by provider, and the providers inside Android has some simple subtypes. For example, when you create a phone for a contact, you can use:</p></p><p><p><code>vnd.android.cursor.item/phone_v2</code></p></p><p><p>here, The subtype is phone_v2.</p></p><p><p>Other provider have a custom subtype that relies on provider permissions (autority) and Paths. For example, the permissions are com.example.train2, including table Line1,line2 and Line3. For the URI of the table Line1:<br><code>content://com.example.trains/Line1</code><br>The corresponding MIME types are:<br><code>vnd.android.cursor.dir/vnd.example.line1</code>or <code>vnd.android.cursor.dir/vnd.com.example.train2.line1</code><br>For Line2, the 5th line Uri:<br><code>content://com.example.trains/Line2/5</code><br>The corresponding MIME types are:<br><code>vnd.android.cursor.item/vnd.example.line2</code>Or<code>vnd.android.cursor.dir/vnd.com.example.train2.line2</code></p></p> <p><p>Decoding Android's ContentProvider (1) crud Operations</p></p></span>
The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion;
products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the
content of the page makes you feel confusing, please write us an email, we will handle the problem
within 5 days after receiving your email.
If you find any instances of plagiarism from the community, please send an email to:
info-contact@alibabacloud.com
and provide relevant evidence. A staff member will contact you within 5 working days.
A Free Trial That Lets You Build Big!
Start building with 50+ products and up to 12 months usage for Elastic Compute Service