1page.title=コンテンツ プロバイダの基本 2@jd:body 3<div id="qv-wrapper"> 4<div id="qv"> 5<!-- In this document --> 6<h2>本書の内容</h2> 7<ol> 8 <li> 9 <a href="#Basics">概要</a> 10 <ol> 11 <li> 12 <a href="#ClientProvider">プロバイダにアクセスする</a> 13 </li> 14 <li> 15 <a href="#ContentURIs">コンテンツ URI</a> 16 </li> 17 </ol> 18 </li> 19 <li> 20 <a href="#SimpleQuery">プロバイダからデータを取得する</a> 21 <ol> 22 <li> 23 <a href="#RequestPermissions">読み取りアクセス パーミッションを要求する</a> 24 </li> 25 <li> 26 <a href="#Query">クエリを作成する</a> 27 </li> 28 <li> 29 <a href="#DisplayResults">クエリ結果を表示する</a> 30 </li> 31 <li> 32 <a href="#GettingResults">クエリ結果を取得する</a> 33 </li> 34 </ol> 35 </li> 36 <li> 37 <a href="#Permissions">コンテンツ プロバイダ パーミッション</a> 38 </li> 39 <li> 40 <a href="#Modifications">データを挿入、更新、削除する</a> 41 <ol> 42 <li> 43 <a href="#Inserting">データを挿入する</a> 44 </li> 45 <li> 46 <a href="#Updating">データを更新する</a> 47 </li> 48 <li> 49 <a href="#Deleting">データを削除する</a> 50 </li> 51 </ol> 52 </li> 53 <li> 54 <a href="#DataTypes">プロバイダ データタイプ</a> 55 </li> 56 <li> 57 <a href="#AltForms">プロバイダ アクセスの別の形式</a> 58 <ol> 59 <li> 60 <a href="#Batch">バッチアクセス</a> 61 </li> 62 <li> 63 <a href="#Intents">インテント経由のデータアクセス</a> 64 </li> 65 </ol> 66 </li> 67 <li> 68 <a href="#ContractClasses">コントラクト クラス</a> 69 </li> 70 <li> 71 <a href="#MIMETypeReference">MIME タイプ リファレンス</a> 72 </li> 73</ol> 74 75 <!-- Key Classes --> 76<h2>キークラス</h2> 77 <ol> 78 <li> 79 {@link android.content.ContentProvider} 80 </li> 81 <li> 82 {@link android.content.ContentResolver} 83 </li> 84 <li> 85 {@link android.database.Cursor} 86 </li> 87 <li> 88 {@link android.net.Uri} 89 </li> 90 </ol> 91 92 <!-- Related Samples --> 93<h2>関連サンプル</h2> 94 <ol> 95 <li> 96 <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/List2.html"> 97 Cursor (People)</a> 98 </li> 99 <li> 100 <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/List7.html"> 101 Cursor (Phones)</a> 102 </li> 103 </ol> 104 105 <!-- See also --> 106<h2>関連ドキュメント</h2> 107 <ol> 108 <li> 109 <a href="{@docRoot}guide/topics/providers/content-provider-creating.html"> 110 コンテンツ プロバイダの作成</a> 111 </li> 112 <li> 113 <a href="{@docRoot}guide/topics/providers/calendar-provider.html"> 114 カレンダー プロバイダ</a> 115 </li> 116 </ol> 117</div> 118</div> 119 120 <!-- Intro paragraphs --> 121<p> 122 コンテンツ プロバイダは、データの中央リポジトリへのアクセスを管理します。プロバイダは Android アプリケーションの一部であり、通常、データを処理するための独自の UI を備えています。 123 124ただし、コンテンツ プロバイダは主に他のアプリケーションでの使用を意図したものです。アプリケーションはプロバイダ クライアント オブジェクトを使用してプロバイダにアクセスします。 125さらに、プロバイダとプロバイダ クライアントにはデータを扱うための一貫性のある標準のインターフェースが備わっており、プロセス間の通信や安全なデータ アクセスを処理します。 126 127 128</p> 129<p> 130 このトピックでは、次の項目に関する基本的な内容を説明します。 131</p> 132 <ul> 133 <li>コンテンツ プロバイダの仕組み。</li> 134 <li>コンテンツ プロバイダからのデータの取得に使用する API。</li> 135 <li>コンテンツ プロバイダへのデータの挿入、データの更新や削除に使用する API。</li> 136 <li>プロバイダでの作業に役立つその他の API 機能。</li> 137 </ul> 138 139 <!-- Basics --> 140<h2 id="Basics">概要</h2> 141<p> 142 外部アプリケーションでは、コンテンツ プロバイダのデータは、リレーショナル データベースで使用する表と同様に、1 つ以上の表として表示されます。 143行はプロバイダが収集するデータの何らかのタイプのインスタンスを表しており、行内のそれぞれの列はインスタンスに対して収集した個々のデータを表しています。 144 145 146</p> 147<p> 148 たとえば、Android プラットフォームに組み込まれているプロバイダの 1 つに単語リストがありますが、ここにはユーザーが保存しておく標準以外の単語のスペリングが格納されます 149表 1 は、このプロバイダの表にデータがどのように格納されているのかを表しています。 150 151</p> 152<p class="table-caption"> 153 <strong>表 1:</strong> サンプルの単語リスト表。 154</p> 155<table id="table1" style="width: 50%;"> 156 <tr> 157 <th style="width:20%" align="center" scope="col">word</th> 158 <th style="width:20%" align="center" scope="col">app id</th> 159 <th style="width:20%" align="center" scope="col">frequency</th> 160 <th style="width:20%" align="center" scope="col">locale</th> 161 <th style="width:20%" align="center" scope="col">_ID</th> 162 </tr> 163 <tr> 164 <td align="center" scope="row">mapreduce</td> 165 <td align="center">user1</td> 166 <td align="center">100</td> 167 <td align="center">en_US</td> 168 <td align="center">1</td> 169 </tr> 170 <tr> 171 <td align="center" scope="row">precompiler</td> 172 <td align="center">user14</td> 173 <td align="center">200</td> 174 <td align="center">fr_FR</td> 175 <td align="center">2</td> 176 </tr> 177 <tr> 178 <td align="center" scope="row">applet</td> 179 <td align="center">user2</td> 180 <td align="center">225</td> 181 <td align="center">fr_CA</td> 182 <td align="center">3</td> 183 </tr> 184 <tr> 185 <td align="center" scope="row">const</td> 186 <td align="center">user1</td> 187 <td align="center">255</td> 188 <td align="center">pt_BR</td> 189 <td align="center">4</td> 190 </tr> 191 <tr> 192 <td align="center" scope="row">int</td> 193 <td align="center">user5</td> 194 <td align="center">100</td> 195 <td align="center">en_UK</td> 196 <td align="center">5</td> 197 </tr> 198</table> 199<p> 200 表 1 の各行は、標準の辞書には含まれていない単語のインスタンスを表しています。 201各列は、該当する単語のデータの一部(その単語が最初に見つかったロケールなど)を表しています。 202列の見出しは、プロバイダに格納される列の名前です。 203行のロケールを調べるには、<code>locale</code> 列を参照します。このプロバイダの場合、<code>_ID</code> 列が「プライマリキー」の列の役割を果たし、プロバイダはこの列を自動的に保持します。 204 205 206</p> 207<p class="note"> 208 <strong>注:</strong> プロバイダはプライマリキーを持つ必要がなく、プライマリキーがある場合は <code>_ID</code> をプライマリキーの列名として使用する必要はありません。 209ただし、プロバイダのデータを {@link android.widget.ListView} にバインドする場合は、いずれかの列の名前を <code>_ID</code> とする必要があります。 210 211この要件についての詳細は、<a href="#DisplayResults">クエリ結果を表示する</a>セクションをご覧ください。 212 213</p> 214<h3 id="ClientProvider">プロバイダにアクセスする</h3> 215<p> 216 アプリケーションは、{@link android.content.ContentResolver} クライアント オブジェクトを使用して、コンテンツ プロバイダのデータにアクセスします。 217このオブジェクトには、プロバイダ オブジェクトの同名のメソッドを呼び出すメソッドが備わっています。これは、{@link android.content.ContentProvider} の具体的なサブクラスのインスタンスのいずれかになります。 218 219{@link android.content.ContentResolver} メソッドには、永続ストレージの基本的な「CRUD」(作成、取得、更新、削除)機能が備わっています。 220 221 222</p> 223<p> 224 クライアント アプリケーションのプロセスにおける {@link android.content.ContentResolver} オブジェクトと、プロバイダを所有するアプリケーションの {@link android.content.ContentProvider} オブジェクトが、プロセス間の通信を自動的に処理します。さらに、{@link android.content.ContentProvider} は、データのリポジトリと、外部に表形式で表示されるデータの間の抽象化レイヤーとして機能します。 225 226 227 228 229</p> 230<p class="note"> 231 <strong>注:</strong> 通常、アプリケーションがプロバイダにアクセスする場合、そのマニフェスト ファイルで特定のパーミッションを要求する必要があります。 232詳細は、<a href="#Permissions">コンテンツ プロバイダ パーミッション</a>セクションをご覧ください。 233 234</p> 235<p> 236 たとえば、単語リスト プロバイダから単語とそのロケールの一覧を取得するには、{@link android.content.ContentResolver#query ContentResolver.query()} を呼び出します。 237 238 {@link android.content.ContentResolver#query query()} メソッドによって、単語リスト プロバイダが定義する{@link android.content.ContentProvider#query ContentProvider.query()} メソッドが呼び出されます。 239 240コードの次の行は、{@link android.content.ContentResolver#query ContentResolver.query()} 呼び出しを表しています。 241 242<p> 243<pre> 244// Queries the user dictionary and returns results 245mCursor = getContentResolver().query( 246 UserDictionary.Words.CONTENT_URI, // The content URI of the words table 247 mProjection, // The columns to return for each row 248 mSelectionClause // Selection criteria 249 mSelectionArgs, // Selection criteria 250 mSortOrder); // The sort order for the returned rows 251</pre> 252<p> 253 表 2 は、query(Uri,projection,selection,selectionArgs,sortOrder)} の引数が SQL SELECT 文にどのように一致しているかを示しています。 254 255 256</p> 257<p class="table-caption"> 258 <strong>表 2:</strong> SQL クエリと比較した Query()。 259</p> 260<table id="table2" style="width: 75%;"> 261 <tr> 262 <th style="width:25%" align="center" scope="col">query() 引数</th> 263 <th style="width:25%" align="center" scope="col">SELECT キーワード / パラメータ</th> 264 <th style="width:50%" align="center" scope="col">注</th> 265 </tr> 266 <tr> 267 <td align="center"><code>Uri</code></td> 268 <td align="center"><code>FROM <em>table_name</em></code></td> 269 <td><code>Uri</code> は、<em>table_name</em> という名前のプロバイダの表にマッピングされます。</td> 270 </tr> 271 <tr> 272 <td align="center"><code>projection</code></td> 273 <td align="center"><code><em>col,col,col,...</em></code></td> 274 <td> 275 <code>projection</code> は、取得するそれぞれの行に含まれる列の配列です。 276 277 </td> 278 </tr> 279 <tr> 280 <td align="center"><code>selection</code></td> 281 <td align="center"><code>WHERE <em>col</em> = <em>value</em></code></td> 282 <td><code>selection</code> は、行を選択する際の基準を指定します。</td> 283 </tr> 284 <tr> 285 <td align="center"><code>selectionArgs</code></td> 286 <td align="center"> 287 (正確に一致するものはありません。選択句では、<code>?</code> プレースホルダーが選択引数に置き換わります) 288 289 </td> 290 </tr> 291 <tr> 292 <td align="center"><code>sortOrder</code></td> 293 <td align="center"><code>ORDER BY <em>col,col,...</em></code></td> 294 <td> 295 <code>sortOrder</code> は、返される {@link android.database.Cursor} 内で行が表示される順番を指定します。 296 297 </td> 298 </tr> 299</table> 300<h3 id="ContentURIs">コンテンツ URI</h3> 301<p> 302 <strong>コンテンツ URI</strong> は、プロバイダのデータを特定する URI です。コンテンツ URI には、プロバイダ全体の識別名(<strong>認証局</strong>)と表をポイントする名前(<strong>パス</strong>)が含まれます。 303 304プロバイダの表にアクセスするためのクライアント メソッドを呼び出す場合、その引数の 1 つがコンテンツ URI になります。 305 306 307</p> 308<p> 309 コードの前半の行では、定数 {@link android.provider.UserDictionary.Words#CONTENT_URI} に、単語リストの「words」表のコンテンツ URI が入ります。 310 311{@link android.content.ContentResolver} オブジェクトは URI の認証局をパースし、認証局を既知のプロバイダのシステム表と比較して、プロバイダを「解決」します。 312 313その後、{@link android.content.ContentResolver} は、クエリ引数を正しいプロバイダに送信できます。 314 315 316</p> 317<p> 318 {@link android.content.ContentProvider} は、アクセスする表を選択するのに、コンテンツ URI のパス部分を使用します。 319通常、プロバイダは公開する各表の<strong>パス</strong>を持ちます。 320</p> 321<p> 322 コードの前半の行では、「words」表の完全な URI は次のようになります。 323</p> 324<pre> 325content://user_dictionary/words 326</pre> 327<p> 328 ここで、<code>user_dictionary</code> 文字列はプロバイダの認証局になり、<code>words</code> 文字列は表のパスになります。 329文字列 <code>content://</code>(<strong>スキーム</strong>)は常に存在し、これがコンテンツ URI であることを示します。 330 331 332</p> 333<p> 334 多くのプログラムでは、URI の末尾に ID 値を付加することで、表内の 1 つの行にアクセスできます。たとえば、<code>_ID</code> が <code>4</code> の行を単語リストから取得するには、次のコンテンツ URI を使用します。 335 336 337</p> 338<pre> 339Uri singleUri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI,4); 340</pre> 341<p> 342 通常は、一連の行を取得してからいずれかの行を更新、削除するような場合に ID 値を使用します。 343 344</p> 345<p class="note"> 346 <strong>注:</strong> {@link android.net.Uri} クラスと {@link android.net.Uri.Builder} クラスには、正しい形式の URI オブジェクトを文字列から作成するための、便利なメソッドが用意されています。 347{@link android.content.ContentUris} には、URI に ID 値を付加するための便利なメソッドが用意されています。前述のスニペットは {@link android.content.ContentUris#withAppendedId 348 withAppendedId()} を使用して、UserDictionary コンテンツ URI に ID を付加しています。 349 350 351</p> 352 353 354 <!-- Retrieving Data from the Provider --> 355<h2 id="SimpleQuery">プロバイダからデータを取得する</h2> 356<p> 357 このセクションでは、単語リスト プロバイダの例を使い、プロバイダからデータを取得する方法を説明します。 358 359</p> 360<p class="note"> 361 わかりやすくするために、このセクションのコード スニペットは「UI スレッド」の {@link android.content.ContentResolver#query ContentResolver.query()} を呼び出しています。 362ただし、実際のコードでは、個別のスレッドで非同期にクエリを実行する必要があります。 363この操作は、{@link android.content.CursorLoader} クラスを使用して行うこともできます。このクラスについての詳細は、「<a href="{@docRoot}guide/components/loaders.html">ローダ</a>」に関するガイドをご覧ください。 364 365 366さらに、コードの行はスニペットのみであり、完全なアプリケーションにはなっていません。 367 368</p> 369<p> 370 プロバイダからデータを取得するには、次の基本的な手順に従います。 371</p> 372<ol> 373 <li> 374 プロバイダの読み取りアクセスを要求します。 375 </li> 376 <li> 377 プロバイダにクエリを送信するコードを定義します。 378 </li> 379</ol> 380<h3 id="RequestPermissions">読み取りアクセス パーミッションを要求する</h3> 381<p> 382 プロバイダからデータを取得するには、アプリケーションからプロバイダの読み取りアクセスを要求します。 383実行時にはこのパーミッションを要求できません。その代わりに、<code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html"><uses-permission></a></code> 要素とプロバイダで定義した正確なパーミッション名を使用して、このパーミッションを必要としていることをマニフェストで指定する必要があります。 384 385 386 387この要素をマニフェストで指定すると、実際に、このパーミッションをアプリケーションに「要求」することになります。 388ユーザーがアプリケーションをインストールすると、この要求が暗黙的に付与されることになります。 389 390</p> 391<p> 392 使用する読み取りアクセス パーミッションの正確な名前と、プロバイダが使用するその他のアクセス パーミッションの名前については、プロバイダのドキュメントをご覧ください。 393 394 395</p> 396<p> 397 プロバイダにアクセスする際のパーミッションのロールの詳細は、<a href="#Permissions">コンテンツ プロバイダ パーミッション</a>セクションをご覧ください。 398 399</p> 400<p> 401 単語リスト プロバイダはパーミッション <code>android.permission.READ_USER_DICTIONARY</code> をマニフェスト ファイルで定義するため、プロバイダからの読み取りを行うアプリケーションはこのパーミッションを要求する必要があります。 402 403 404</p> 405<!-- Constructing the query --> 406<h3 id="Query">クエリを作成する</h3> 407<p> 408 プロバイダからのデータの取得の次の手順では、クエリを作成します。最初のスニペットで、単語リスト プロバイダにアクセスするための変数をいくつか定義します。 409 410</p> 411<pre class="prettyprint"> 412 413// A "projection" defines the columns that will be returned for each row 414String[] mProjection = 415{ 416 UserDictionary.Words._ID, // Contract class constant for the _ID column name 417 UserDictionary.Words.WORD, // Contract class constant for the word column name 418 UserDictionary.Words.LOCALE // Contract class constant for the locale column name 419}; 420 421// Defines a string to contain the selection clause 422String mSelectionClause = null; 423 424// Initializes an array to contain selection arguments 425String[] mSelectionArgs = {""}; 426 427</pre> 428<p> 429 次のスニペットでは、単語リスト プロバイダの例を使って、{@link android.content.ContentResolver#query ContentResolver.query()} を使用する方法を示しています。 430 431プロバイダ クライアント クエリは SQL クエリに似たものであり、戻り値となる一連の列、一連の選択基準、並べ替えの順番を含みます。 432 433</p> 434<p> 435 クエリの戻り値となる一連の列は、<strong>投影</strong>(変数 <code>mProjection</code>)と呼ばれます。 436 437</p> 438<p> 439 取得する行を指定する式は、選択句と選択引数に分割されます。 440選択句は論理式やブール式、列名、値(変数 <code>mSelectionClause</code>)の組み合わせになります。 441値の代わりに置き換え可能パラメータ <code>?</code> を指定すると、クエリ メソッドによって、選択引数の配列(変数 <code>mSelectionArgs</code>)から値が取得されます。 442 443 444</p> 445<p> 446 次のスニペットでは、ユーザーが単語を入力しない場合、選択句が <code>null</code> に設定され、クエリによってプロバイダのすべての単語が返されます。 447ユーザーが単語を入力すると、選択句が <code>UserDictionary.Words.WORD + " = ?"</code> に設定され、選択引数の配列の最初の要素が、ユーザーが入力した単語に設定されます。 448 449 450</p> 451<pre class="prettyprint"> 452/* 453 * This defines a one-element String array to contain the selection argument. 454 */ 455String[] mSelectionArgs = {""}; 456 457// Gets a word from the UI 458mSearchString = mSearchWord.getText().toString(); 459 460// Remember to insert code here to check for invalid or malicious input. 461 462// If the word is the empty string, gets everything 463if (TextUtils.isEmpty(mSearchString)) { 464 // Setting the selection clause to null will return all words 465 mSelectionClause = null; 466 mSelectionArgs[0] = ""; 467 468} else { 469 // Constructs a selection clause that matches the word that the user entered. 470 mSelectionClause = UserDictionary.Words.WORD + " = ?"; 471 472 // Moves the user's input string to the selection arguments. 473 mSelectionArgs[0] = mSearchString; 474 475} 476 477// Does a query against the table and returns a Cursor object 478mCursor = getContentResolver().query( 479 UserDictionary.Words.CONTENT_URI, // The content URI of the words table 480 mProjection, // The columns to return for each row 481 mSelectionClause // Either null, or the word the user entered 482 mSelectionArgs, // Either empty, or the string the user entered 483 mSortOrder); // The sort order for the returned rows 484 485// Some providers return null if an error occurs, others throw an exception 486if (null == mCursor) { 487 /* 488 * Insert code here to handle the error. Be sure not to use the cursor! You may want to 489 * call android.util.Log.e() to log this error. 490 * 491 */ 492// If the Cursor is empty, the provider found no matches 493} else if (mCursor.getCount() < 1) { 494 495 /* 496 * Insert code here to notify the user that the search was unsuccessful. This isn't necessarily 497 * an error. You may want to offer the user the option to insert a new row, or re-type the 498 * search term. 499 */ 500 501} else { 502 // Insert code here to do something with the results 503 504} 505</pre> 506<p> 507 このクエリは、 SQL 文に似ています。 508</p> 509<pre> 510SELECT _ID, word, locale FROM words WHERE word = <userinput> ORDER BY word ASC; 511</pre> 512<p> 513 この SQL 文では、コントラクト クラスの定数ではなく、実際の列の名前が使用されます。 514</p> 515<h4 id="Injection">悪意のある入力から保護する</h4> 516<p> 517 コンテンツ プロバイダが管理するデータが SQL データベース内にある場合、外部の信頼されていないデータを未処理の SQL 文に含めると SQL インジェクションが発生することがあります。 518 519</p> 520<p> 521 次のような選択句を考えてみます。 522</p> 523<pre> 524// Constructs a selection clause by concatenating the user's input to the column name 525String mSelectionClause = "var = " + mUserInput; 526</pre> 527<p> 528 このようにすれば、ユーザーが悪意のある SQL を SQL 文に連結できるようになります。 529 たとえば、ユーザーが <code>mUserInput</code> に「nothing; DROP TABLE *;」と入力すると、選択句は <code>var = nothing; DROP TABLE *;</code> となります。 530選択句は SQL 文として処理されるため、この場合、基本的な SQLite データベースのすべての表が消去されることがあります(プロバイダに <a href="http://en.wikipedia.org/wiki/SQL_injection">SQL インジェクション</a>の試みの検出が設定されていない場合)。 531 532 533 534</p> 535<p> 536 この問題を回避するには、<code>?</code> を置き換え可能パラメータとして使う選択句と、選択引数の個別の配列を使用します。 537そうすることで、ユーザー入力は、SQL 文の一部として解釈されずに、クエリに直接バインドされます。 538 539 SQL として扱われないため、ユーザー入力によって悪意のある SQL が挿入されることはありません。ユーザー入力を含める際に連結を使用しないで、次の選択句を使用します。 540 541</p> 542<pre> 543// Constructs a selection clause with a replaceable parameter 544String mSelectionClause = "var = ?"; 545</pre> 546<p> 547 選択引数の配列を次のように設定します。 548</p> 549<pre> 550// Defines an array to contain the selection arguments 551String[] selectionArgs = {""}; 552</pre> 553<p> 554 選択引数の配列に次のように値を格納します。 555</p> 556<pre> 557// Sets the selection argument to the user's input 558selectionArgs[0] = mUserInput; 559</pre> 560<p> 561 プロバイダが SQL データベースに基づいたものではない場合でも、選択内容を指定する場合は、<code>?</code> を置き換え可能パラメータとして使う選択句と、選択引数の配列を使用することをお勧めします。 562 563 564</p> 565<!-- Displaying the results --> 566<h3 id="DisplayResults">クエリ結果を表示する</h3> 567<p> 568 {@link android.content.ContentResolver#query ContentResolver.query()} クライアント メソッドは、常に {@link android.database.Cursor} を返します。これには、クエリの選択基準に一致する、行へのクエリの投影によって指定される列が含まれます。 569 570{@link android.database.Cursor} オブジェクトは、含まれる行と列へのランダム読み取りアクセスを提供します。 571 572{@link android.database.Cursor} メソッドを使用すると、結果の行の繰り返し、各列のデータタイプの識別、列からのデータの取得、結果のその他のプロパティの確認といった操作が可能となります。 573 574一部の {@link android.database.Cursor} を実装すると、プロバイダのデータが変更された場合にオブジェクトが自動的に送信されたり、{@link android.database.Cursor} が変更された場合にオブザーバ オブジェクトのメソッドがトリガーされたり、その両方が実行されたりします。 575 576 577</p> 578<p class="note"> 579 <strong>注:</strong> クエリを作成するオブジェクトの特性に基づいて、プロバイダによって列へのアクセスが制限されることがあります。 580たとえば、連絡先プロバイダにより同期アダプタは一部の列へのアクセスが制限されるため、その場合はアクティビティやサービスを返しません。 581 582</p> 583<p> 584 選択基準に一致する行がない場合は、{@link android.database.Cursor#getCount Cursor.getCount()} が 0(空のカーソル)の {@link android.database.Cursor} オブジェクトを返します。 585 586 587</p> 588<p> 589 内部エラーが発生した場合、クエリの結果はプロバイダによって異なります。<code>null</code> が返されることもあれば、{@link java.lang.Exception} がスローされることもあります。 590 591</p> 592<p> 593 {@link android.database.Cursor} は行の「一覧」であることから、{@link android.database.Cursor} のコンテンツを表示する場合は、{@link android.widget.SimpleCursorAdapter} 経由で {@link android.widget.ListView} にリンクすることをお勧めします。 594 595 596</p> 597<p> 598 次のスニペットは前のスニペットのコードの続きです。クエリによって取得する {@link android.database.Cursor} を含む {@link android.widget.SimpleCursorAdapter} オブジェクトを作成し、このオブジェクトを {@link android.widget.ListView} のアダプタに設定します。 599 600 601 602</p> 603<pre class="prettyprint"> 604// Defines a list of columns to retrieve from the Cursor and load into an output row 605String[] mWordListColumns = 606{ 607 UserDictionary.Words.WORD, // Contract class constant containing the word column name 608 UserDictionary.Words.LOCALE // Contract class constant containing the locale column name 609}; 610 611// Defines a list of View IDs that will receive the Cursor columns for each row 612int[] mWordListItems = { R.id.dictWord, R.id.locale}; 613 614// Creates a new SimpleCursorAdapter 615mCursorAdapter = new SimpleCursorAdapter( 616 getApplicationContext(), // The application's Context object 617 R.layout.wordlistrow, // A layout in XML for one row in the ListView 618 mCursor, // The result from the query 619 mWordListColumns, // A string array of column names in the cursor 620 mWordListItems, // An integer array of view IDs in the row layout 621 0); // Flags (usually none are needed) 622 623// Sets the adapter for the ListView 624mWordList.setAdapter(mCursorAdapter); 625</pre> 626<p class="note"> 627 <strong>注:</strong> {@link android.database.Cursor} によって {@link android.widget.ListView} を戻すには、カーソルに <code>_ID</code> という名前の列を含める必要があります。 628 629 そのため、{@link android.widget.ListView} には表示されまませんが、前述のクエリは「words」表に <code>_ID</code> 列を取得します。 630 631 また、このような制限があることから、大部分のプロバイダがそれぞれの表に <code>_ID</code> 列を持ちます。 632 633</p> 634 635 <!-- Getting data from query results --> 636<h3 id="GettingResults">クエリ結果を取得する</h3> 637<p> 638 クエリ結果を単に表示するだけでなく、他のタスクに使用することもできます。たとえば、単語リストからスペリングを取得して、それを他のプロバイダで検索するといった操作も可能です。 639 640そのためには、次のように {@link android.database.Cursor} の行に操作を繰り返します。 641</p> 642<pre class="prettyprint"> 643 644// Determine the column index of the column named "word" 645int index = mCursor.getColumnIndex(UserDictionary.Words.WORD); 646 647/* 648 * Only executes if the cursor is valid. The User Dictionary Provider returns null if 649 * an internal error occurs. Other providers may throw an Exception instead of returning null. 650 */ 651 652if (mCursor != null) { 653 /* 654 * Moves to the next row in the cursor. Before the first movement in the cursor, the 655 * "row pointer" is -1, and if you try to retrieve data at that position you will get an 656 * exception. 657 */ 658 while (mCursor.moveToNext()) { 659 660 // Gets the value from the column. 661 newWord = mCursor.getString(index); 662 663 // Insert code here to process the retrieved word. 664 665 ... 666 667 // end of while loop 668 } 669} else { 670 671 // Insert code here to report an error if the cursor is null or the provider threw an exception. 672} 673</pre> 674<p> 675 {@link android.database.Cursor} の実装には「取得」メソッドがいくつか備わっており、オブジェクトからさまざまなタイプのデータを取得できます。 676たとえば、前述のスニペットは {@link android.database.Cursor#getString getString()} を使用しています。 677さらに、列のデータタイプを示す値を返す {@link android.database.Cursor#getType getType()} メソッドも使用しています。 678 679 680</p> 681 682 683 <!-- Requesting permissions --> 684<h2 id="Permissions">コンテンツ プロバイダ パーミッション</h2> 685<p> 686 プロバイダのアプリケーションでは、他のアプリケーションがプロバイダのデータにアクセスするのに必要なパーミッションを指定できます。 687これらのパーミッションを設定しておけば、ユーザーはアプリケーションがアクセスしようとしているデータの種類を把握できます。 688他のアプリケーションは、プロバイダの要件に基づき、そのプロバイダにアクセスするのに必要なパーミッションを要求します。 689エンドユーザーがアプリケーションをインストールする際には、要求されたパーミッションを確認できます。 690 691</p> 692<p> 693 プロバイダのアプリケーションでパーミッションを指定していない場合は、他のアプリケーションはプロバイダのデータにアクセスできません。 694ただし、指定したパーミッションに関係なく、プロバイダのアプリケーションのコンポーネントには完全な読み取り権限と書き込み権限を常に付与する必要があります。 695 696</p> 697<p> 698 前述のとおり、単語リスト プロバイダには、データを取得するための <code>android.permission.READ_USER_DICTIONARY</code> パーミッションが必要です。 699 700 プロバイダには、データの挿入、更新、削除に対してそれぞれ個別の <code>android.permission.WRITE_USER_DICTIONARY</code> パーミッションがあります。 701 702</p> 703<p> 704 プロバイダにアクセスするのに必要なパーミッションを取得するには、アプリケーションのマニフェスト ファイルの <code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html"><uses-permission></a></code> 要素を使用してパーミッションを要求する必要があります。 705 706Android Package Manager でアプリケーションをインストールする場合は、ユーザーがアプリケーションが要求するすべてのパーミッションを承認する必要があります。 707ユーザーがすべてのパーミッションを承認すると、Package Manager がインストールを続行します。ユーザーが承認しない場合は、Package Manager がインストールを中止します。 708 709 710</p> 711<p> 712 次の <code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html"><uses-permission></a></code> 要素は、単語リスト プロバイダへの読み取りアクセスを要求します。 713 714 715</p> 716<pre> 717 <uses-permission android:name="android.permission.READ_USER_DICTIONARY"> 718</pre> 719<p> 720 プロバイダ アクセスへのパーミッションの影響については、<a href="{@docRoot}guide/topics/security/security.html">セキュリティとパーミッション</a>に関するガイドをご覧ください。 721 722</p> 723 724 725<!-- Inserting, Updating, and Deleting Data --> 726<h2 id="Modifications">データを挿入、更新、削除する</h2> 727<p> 728 データを収集するには、プロバイダからデータを取得するのと同様に、プロバイダ クライアントとプロバイダの {@link android.content.ContentProvider} 間で操作を行います。 729 730 対応する {@link android.content.ContentProvider} のメソッドに渡した引数を使用して、{@link android.content.ContentResolver} のメソッドを呼び出します。 731プロバイダとプロバイダ クライアントが、セキュリティとプロセス間の通信を自動的に処理します。 732 733</p> 734<h3 id="Inserting">データを挿入する</h3> 735<p> 736 プロバイダにデータを挿入するには、{@link android.content.ContentResolver#insert ContentResolver.insert()} メソッドを呼び出します。 737 738このメソッドはプロバイダに新しい行を挿入し、その行のコンテンツ URI を返します。 739 このスニペットは、単語リスト プロバイダに新しい単語を挿入する方法を示しています。 740</p> 741<pre class="prettyprint"> 742// Defines a new Uri object that receives the result of the insertion 743Uri mNewUri; 744 745... 746 747// Defines an object to contain the new values to insert 748ContentValues mNewValues = new ContentValues(); 749 750/* 751 * Sets the values of each column and inserts the word. The arguments to the "put" 752 * method are "column name" and "value" 753 */ 754mNewValues.put(UserDictionary.Words.APP_ID, "example.user"); 755mNewValues.put(UserDictionary.Words.LOCALE, "en_US"); 756mNewValues.put(UserDictionary.Words.WORD, "insert"); 757mNewValues.put(UserDictionary.Words.FREQUENCY, "100"); 758 759mNewUri = getContentResolver().insert( 760 UserDictionary.Word.CONTENT_URI, // the user dictionary content URI 761 mNewValues // the values to insert 762); 763</pre> 764<p> 765 新しい行のデータは 1 つの {@link android.content.ContentValues} オブジェクトに入ります。これは 1 行カーソルの形式に似ています。 766このオブジェクト内の列は同じデータタイプを持つ必要はなく、値をまったく指定しない場合は、{@link android.content.ContentValues#putNull ContentValues.putNull()} を使用して列を <code>null</code> に設定できます。 767 768 769</p> 770<p> 771 この列は自動的に保持されるため、スニペットは <code>_ID</code> 列を追加しません。 772プロバイダは、追加するそれぞれの行に、<code>_ID</code> の一意の値を割り当てます。 773通常、プロバイダはこの値を表のプライマリキーとして使用します。 774</p> 775<p> 776 <code>newUri</code> で返されるコンテンツ URI は、新たに追加された行を特定するものであり、次の形式となります。 777 778</p> 779<pre> 780content://user_dictionary/words/<id_value> 781</pre> 782<p> 783 <code><id_value></code> は、新しい行の <code>_ID</code> のコンテンツです。 784 ほとんどのプロバイダではコンテンツ URI のこの形式を自動的に検出し、特定の行で要求された操作を実行します。 785 786</p> 787<p> 788 返された {@link android.net.Uri} から <code>_ID</code> の値を取得するには、{@link android.content.ContentUris#parseId ContentUris.parseId()} を呼び出します。 789 790</p> 791<h3 id="Updating">データを更新する</h3> 792<p> 793 行を更新するには、挿入操作と同じように、値を更新した {@link android.content.ContentValues} オブジェクトと、クエリ操作のときと同じように選択基準を使用します。 794 795 使用するクライアント メソッドは {@link android.content.ContentResolver#update ContentResolver.update()} です。 796更新する列の {@link android.content.ContentValues} オブジェクトに値を追加する操作のみが必要になります。 797列のコンテンツを消去する場合は、値を <code>null</code> に設定します。 798 799</p> 800<p> 801 次のスニペットは、ロケール言語が「en」となっているすべての行のロケールを <code>null</code> に変更します。 802戻り値は、更新された行の数となります。 803</p> 804<pre> 805// Defines an object to contain the updated values 806ContentValues mUpdateValues = new ContentValues(); 807 808// Defines selection criteria for the rows you want to update 809String mSelectionClause = UserDictionary.Words.LOCALE + "LIKE ?"; 810String[] mSelectionArgs = {"en_%"}; 811 812// Defines a variable to contain the number of updated rows 813int mRowsUpdated = 0; 814 815... 816 817/* 818 * Sets the updated value and updates the selected words. 819 */ 820mUpdateValues.putNull(UserDictionary.Words.LOCALE); 821 822mRowsUpdated = getContentResolver().update( 823 UserDictionary.Words.CONTENT_URI, // the user dictionary content URI 824 mUpdateValues // the columns to update 825 mSelectionClause // the column to select on 826 mSelectionArgs // the value to compare to 827); 828</pre> 829<p> 830 また、{@link android.content.ContentResolver#update ContentResolver.update()} を呼び出すときには、ユーザー入力をサニタイズする必要があります。 831詳細は、<a href="#Injection">悪意のある入力から保護する</a>セクションをご覧ください。 832 833</p> 834<h3 id="Deleting">データを削除する</h3> 835<p> 836 行の削除は行データの取得と似た操作になります。削除する行の選択基準を指定することで、クライアント メソッドが削除した行の数を返します。 837 838 次のスニペットは appid が「user」となっている行を削除します。メソッドによって削除された行の数が返されます。 839 840</p> 841<pre> 842 843// Defines selection criteria for the rows you want to delete 844String mSelectionClause = UserDictionary.Words.APP_ID + " LIKE ?"; 845String[] mSelectionArgs = {"user"}; 846 847// Defines a variable to contain the number of rows deleted 848int mRowsDeleted = 0; 849 850... 851 852// Deletes the words that match the selection criteria 853mRowsDeleted = getContentResolver().delete( 854 UserDictionary.Words.CONTENT_URI, // the user dictionary content URI 855 mSelectionClause // the column to select on 856 mSelectionArgs // the value to compare to 857); 858</pre> 859<p> 860 また、{@link android.content.ContentResolver#delete ContentResolver.delete()} を呼び出すときには、ユーザー入力をサニタイズする必要があります。 861詳細は、<a href="#Injection">悪意のある入力から保護する</a>セクションをご覧ください。 862 863</p> 864<!-- Provider Data Types --> 865<h2 id="DataTypes">プロバイダ データタイプ</h2> 866<p> 867 コンテンツ プロバイダではさまざまなデータタイプを利用できます。単語リスト プロバイダで提供できるのはテキストのみですが、次のような形式を提供できます。 868 869</p> 870 <ul> 871 <li> 872 整数 873 </li> 874 <li> 875 long 整数(long) 876 </li> 877 <li> 878 浮動小数点 879 </li> 880 <li> 881 long 浮動小数点(double) 882 </li> 883 </ul> 884<p> 885 それ以外にも、プロバイダでは 64KB バイト配列として実装されるバイナリ ラージ オブジェクト(BLOB)もよく使用されます。 886利用可能なデータタイプについては、{@link android.database.Cursor} クラスの「get」メソッドをご覧ください。 887 888</p> 889<p> 890 プロバイダの各列のデータタイプは、通常、そのドキュメントに一覧が記載されています。 891 単語リスト プロバイダのデータタイプは、コントラクト クラス {@link android.provider.UserDictionary.Words} のリファレンスに一覧が記載されています(コントラクト クラスの詳細は、<a href="#ContractClasses">コントラクト クラス</a>セクションをご覧ください)。 892 893 894 さらに、{@link android.database.Cursor#getType 895 Cursor.getType()} を呼び出すことで、データタイプを判断することもできます。 896</p> 897<p> 898 プロバイダは、プロバイダによって定義される各コンテンツ URI の MIME データタイプも保持します。MIME タイプ情報を使用すると、プロバイダが提供するデータをアプリケーションが処理できるかを判断したり、MIME タイプに基づいて処理のタイプを選択したりできます。 899 900通常は、複雑なデータ構造やファイルを持つプロバイダで作業をする際に MIME タイプが必要になります。 901 902たとえば、連絡先プロバイダの {@link android.provider.ContactsContract.Data} 表は MIME タイプを使用して、それぞれの行に格納される連絡先データのタイプをラベル付けします。 903 904コンテンツ URI に対応する MIME タイプを取得するには、{@link android.content.ContentResolver#getType ContentResolver.getType()} を呼び出します。 905 906</p> 907<p> 908 「<a href="#MIMETypeReference">MIME タイプ リファレンス</a>」セクションでは、標準とカスタムの両方の MIME タイプについて説明しています。 909 910</p> 911 912 913<!-- Alternative Forms of Provider Access --> 914<h2 id="AltForms">プロバイダ アクセスの別の形式</h2> 915<p> 916 アプリケーションの開発では、次に示すプロバイダ アクセスの別の 3 つの形式が重要になります。 917</p> 918<ul> 919 <li> 920 <a href="#Batch">バッチアクセス</a>: {@link android.content.ContentProviderOperation} クラスのメソッドを使用したアクセス呼び出しのバッチを作成し、{@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()} に適用できます。 921 922 923 </li> 924 <li> 925 非同期クエリ: クエリは個別のスレッドで実行する必要があります。この操作は、{@link android.content.CursorLoader} オブジェクトを使用して行うこともできます。 926「<a href="{@docRoot}guide/components/loaders.html">ローダ</a>」のガイドには、この操作の例が記載されています。 927 928 929 </li> 930 <li> 931 <a href="#Intents">インテント経由のデータアクセス</a>: インテントをプロバイダに直接送信できませんが、プロバイダのアプリケーションにはインテントを送信できます。通常、プロバイダのデータの修正に最適な機能を備えたアプリケーションになります。 932 933 934 </li> 935</ul> 936<p> 937 バッチアクセスとインテント経由の修正については、次のセクションで説明しています。 938</p> 939<h3 id="Batch">バッチアクセス</h3> 940<p> 941 多数の行を挿入する場合や、同じメソッド呼び出しで複数の表に行を挿入する場合は、プロバイダへのバッチアクセスを使用すると便利です。また、一般的には、境界をまたいでプロセス全体にトランザクションとして一連の操作を実行する場合にもバッチアクセスが便利です。 942 943 944</p> 945<p> 946 「バッチモード」でプロバイダにアクセスするには、{@link android.content.ContentProviderOperation} オブジェクトの配列を作成してから、{@link android.content.ContentResolver#applyBatch ContentResolver.applyBatch()} を使用してそれらのオブジェクトをコンテンツ プロバイダに送信します。 947 948 949このメソッドには、特定のコンテンツ URI ではなく、コンテンツ プロバイダの<em>認証局</em>を渡します。そうすることで、配列内のそれぞれの {@link android.content.ContentProviderOperation} オブジェクトを別々の表に対して機能するようになります。 950 951 952{@link android.content.ContentResolver#applyBatch 953 ContentResolver.applyBatch()} への呼び出しでは、結果の配列が返されます。 954</p> 955<p> 956 {@link android.provider.ContactsContract.RawContacts} コントラクト クラスの説明には、バッチ挿入を示したコード スニペットが記載されています。 957<a href="{@docRoot}resources/samples/ContactManager/index.html">Contact Manager</a> のサンプル アプリケーションでは、<code>ContactAdder.java</code> ソースファイルでのバッチアクセスの例が紹介されています。 958 959 960 961</p> 962<div class="sidebox-wrapper"> 963<div class="sidebox"> 964<h2>ヘルパーアプリでデータを表示する</h2> 965<p> 966 アプリケーションにアクセス パーミッションが<em>付与されている</em>場合でも、インテントを使用して別のアプリケーションにデータを表示できます。 967たとえば、カレンダー アプリケーションは {@link android.content.Intent#ACTION_VIEW} インテントにアクセスしますが、このインテントは特定の日付やイベントを表示するものです。 968 969 これにより、独自の UI を作成しなくても、カレンダー情報を表示できます。この機能の詳細は、「<a href="{@docRoot}guide/topics/providers/calendar-provider.html">カレンダー プロバイダ</a>」のガイドをご覧ください。 970 971 972</p> 973<p> 974 インテントの送信先アプリケーションは、必ずしもプロバイダに関連付けられたアプリケーションである必要はありません。 975たとえば、連絡先プロバイダから連絡先を取得してから、連絡先の画像のコンテンツ URI を含む {@link android.content.Intent#ACTION_VIEW} インテントを画像ビューワに送信するといった操作が可能です。 976 977 978</p> 979</div> 980</div> 981<h3 id="Intents">インテント経由のデータアクセス</h3> 982<p> 983 インテントを使用すれば、コンテンツ プロバイダに間接的にアクセスできます。アプリケーションにアクセス パーミッションがない場合でも、パーミッションを持つアプリケーションから結果のインテントを取得したり、パーミッションを持つアプリケーションをアクティベートしてそのアプリケーションをユーザーに使用させたりすることで、ユーザーがプロバイダのデータにアクセスできるようになります。 984 985 986 987</p> 988<h4>一時的なパーミッションによりアクセスを取得する</h4> 989<p> 990 適切なアクセス パーミッションがない場合でも、パーミッションを持つアプリケーションにインテントを送信し、「URI」パーミッションを含む結果のインテントを受け取ることで、コンテンツ プロバイダのデータにアクセスできます。 991 992 993 これらのパーミッションは特定のコンテンツ URI のパーミッションであり、パーミッションを受け取ったアクティビティが終了するまで効力を持ちます。 994永続的なパーミッションを持つアプリケーションは、次のように結果のインテントにフラグを設定し、一時的なパーミッションを付与します。 995 996</p> 997<ul> 998 <li> 999 <strong>読み取りパーミッション:</strong> {@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION} 1000 1001 </li> 1002 <li> 1003 <strong>書き込みパーミッション:</strong> {@link android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION} 1004 1005 </li> 1006</ul> 1007<p class="note"> 1008 <strong>注:</strong> これらのフラグは、認証局がコンテンツ URI に含まれるプロバイダへの全般的な読み取りと書き込みアクセスを付与するものではありません。アクセスは URI 自身に限定されます。 1009 1010</p> 1011<p> 1012 プロバイダは、<code><a href="{@docRoot}guide/topics/manifest/provider-element.html"><provider></a></code> 要素の <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn">android:grantUriPermission</a></code> 属性や、<code><a href="{@docRoot}guide/topics/manifest/provider-element.html"><provider></a></code> 要素の <code><a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html"><grant-uri-permission></a></code> 子要素を使用して、コンテンツ URI の URI パーミッションを自身のマニフェストで定義します。 1013 1014 1015 1016 1017 1018 1019 1020URI パーミッションのメカニズムについての詳細は、URI パーミッション セクションの<a href="{@docRoot}guide/topics/security/security.html">セキュリティとパーミッション</a>に関するガイドをご覧ください。 1021 1022 1023</p> 1024<p> 1025 たとえば、{@link android.Manifest.permission#READ_CONTACTS} パーミッションを持たない場合でも、連絡先プロバイダの連絡先のデータを取得できます。 1026連絡先の誕生日にグリーティング カードをオンラインで送信するアプリケーションなどにこのメカニズムを利用できます。 1027ユーザーのすべての連絡先やそのすべての情報へのアクセス件を付与する {@link android.Manifest.permission#READ_CONTACTS} を要求する代わりに、アプリケーションで使用する連絡先をユーザーが制御できるように設定することもできます。 1028 1029 1030そのためには、次の手順を使用します。 1031</p> 1032<ol> 1033 <li> 1034 アプリケーションが、メソッド {@link android.app.Activity#startActivityForResult 1035 startActivityForResult()} を使用して、アクション {@link android.content.Intent#ACTION_PICK} と「連絡先」MIME タイプ {@link android.provider.ContactsContract.RawContacts#CONTENT_ITEM_TYPE} を含むインテントを送信します。 1036 1037 1038 1039 </li> 1040 <li> 1041 このインテントは連絡帳アプリの「selection」アクティビティのインテント フィルタに一致するため、アクティビティがフォアグラウンドに移動します。 1042 1043 </li> 1044 <li> 1045 selection アクティビティでは、更新する連絡先をユーザーが選択します。 1046この操作が行われると、selection が {@link android.app.Activity#setResult setResult(resultcode, intent)} を呼び出し、アプリケーションに戻すインテントを設定します。 1047 1048インテントには、ユーザーが選択した連絡先のコンテンツ URI と、「エクストラ」フラグ {@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION} が含まれます。 1049 1050これらのフラグがあることで、コンテンツ URI がポイントする連絡先のデータを読み取るための URI パーミッションがアプリに付与されます。その後、selection アクティビティによって、アプリケーションに制御を返すための {@link android.app.Activity#finish()} が呼び出されます。 1051 1052 1053 1054 </li> 1055 <li> 1056 アクティビティがフォアグラウンドに戻り、システムがアクティビティの {@link android.app.Activity#onActivityResult onActivityResult()} メソッドを呼び出します。 1057 1058このメソッドは、連絡帳アプリの selection アクティビティによって作成された結果のインテントを受け取ります。 1059 1060 </li> 1061 <li> 1062 結果のインテントのコンテンツ URI を使用すれば、マニフェストで永続的なアクセス パーミッションをプロバイダに要求していなくても、連絡先プロバイダから連絡先のデータを読み取ることができます。 1063 1064その後、連絡先の誕生日情報やメールアドレスを取得し、グリーティング カードをオンラインで送信できます。 1065 1066 </li> 1067</ol> 1068<h4>別のアプリケーションを使用する</h4> 1069<p> 1070 パーミッションを持つアプリケーションをアクティベートし、そのアプリケーションをユーザーが使用すれば、アクセス パーミッションを持たないデータをユーザーが修正できるようになります。 1071 1072</p> 1073<p> 1074 たとえば、アプリケーションの挿入 UI をアクティベートできる {@link android.content.Intent#ACTION_INSERT} インテントをカレンダー アプリケーションが受け入れるとします。このインテントに「エクストラ」データを渡すことで、アプリケーションがそのデータを使用して、事前に入力された UI を作成します。繰り返し発生するイベントは複雑な構文を持つため、カレンダー プロバイダにイベントを挿入する場合は、{@link android.content.Intent#ACTION_INSERT} でカレンダー アプリをアクティベートしてから、ユーザーにイベントを挿入してもらうことをお勧めします。 1075 1076 1077 1078 1079 1080</p> 1081<!-- Contract Classes --> 1082<h2 id="ContractClasses">コントラクト クラス</h2> 1083<p> 1084 コントラクト クラスは、アプリケーションがコンテンツ URI、列名、インテント アクション、コンテンツのその他の機能で作業する際に役立つ定数を定義します。 1085プロバイダでコントラクト クラスが自動的に含まれることはありません。プロバイダのデベロッパーはコントラクト クラスを定義して、その他のデベロッパーが使用できるようにする必要があります。 1086 1087Android プラットフォームに含まれる多くのプロバイダは、パッケージ {@link android.provider} 内に対応するコントラクト クラスを持ちます。 1088 1089</p> 1090<p> 1091 たとえば、単語リスト プロバイダは、コンテンツ URI と列名の定数を含む、コントラクト クラス {@link android.provider.UserDictionary} を持つとします。 1092「words」表のコンテンツ URI は、定数 {@link android.provider.UserDictionary.Words#CONTENT_URI UserDictionary.Words.CONTENT_URI} で定義されます。 1093 1094 1095 さらに、{@link android.provider.UserDictionary.Words} クラスは、このガイドのサンプルのスニペットで使用される、列名の定数を持ちます。 1096たとえば、クエリの投影は次のように定義できます。 1097 1098</p> 1099<pre> 1100String[] mProjection = 1101{ 1102 UserDictionary.Words._ID, 1103 UserDictionary.Words.WORD, 1104 UserDictionary.Words.LOCALE 1105}; 1106</pre> 1107<p> 1108 もう一方のコントラクト クラスは、連絡先プロバイダのクラス {@link android.provider.ContactsContract} です。 1109 このクラスのリファレンスには、サンプルのコード スニペットが記載されています。サブクラスの 1 つである {@link android.provider.ContactsContract.Intents.Insert} は、インテントとインテント データの定数を含むコントラクト クラスです。 1110 1111 1112</p> 1113 1114 1115<!-- MIME Type Reference --> 1116<h2 id="MIMETypeReference">MIME タイプ リファレンス</h2> 1117<p> 1118 コンテンツ プロバイダは、標準の MIME メディア タイプかカスタムの MIME タイプ文字列、またはその両方を返すことができます。 1119</p> 1120<p> 1121 MIME タイプは次の形式となります 1122</p> 1123<pre> 1124<em>type</em>/<em>subtype</em> 1125</pre> 1126<p> 1127 たとえば、よく利用される MIME タイプ <code>text/html</code> は、<code>text</code> タイプと <code>html</code> サブタイプを持ちます。 1128プロバイダから URI に対してこのタイプが返される場合、その URI を使用するクエリは HTML タグを含むテキストを返すことになります。 1129 1130</p> 1131<p> 1132 「ベンダー固有の」MIME タイプとも呼ばれるカスタムの MIME タイプ文字列には、より複雑な <em>type</em> と <em>subtype</em> の値が含まれます。 1133複数行の場合、<em>type</em> 値は常に 1134</p> 1135<pre> 1136vnd.android.cursor.<strong>dir</strong> 1137</pre> 1138<p> 1139 となり、1 つの行の場合は 1140</p> 1141<pre> 1142vnd.android.cursor.<strong>item</strong> 1143</pre> 1144<p> 1145 となります。 1146</p> 1147<p> 1148 <em>subtype</em> はプロバイダ固有の値になります。通常、Android 組み込みプロバイダは単純な subtype を使用します。 1149たとえば、連絡先アプリケーションが電話番号の行を作成すると、行には次のように MIME タイプが設定されます。 1150 1151</p> 1152<pre> 1153vnd.android.cursor.item/phone_v2 1154</pre> 1155<p> 1156 subtype の値は単純に <code>phone_v2</code> となっていることがわかります。 1157</p> 1158<p> 1159 他のプロバイダ デベロッパーは、プロバイダの認証局と表明に基づいて独自のパターンの subtype を作成できます。 1160たとえば、列車の時刻表を含むプロバイダについて考えてみます。 1161 プロバイダの認証局は <code>com.example.trains</code> であり、表 Line1、Line2、Line3 を持ちます。 1162表 Line1 のコンテンツ URI 1163</p> 1164<p> 1165<pre> 1166content://com.example.trains/Line1 1167</pre> 1168<p> 1169 に対しては、プロバイダは次の MIME タイプを返します 1170</p> 1171<pre> 1172vnd.android.cursor.<strong>dir</strong>/vnd.example.line1 1173</pre> 1174<p> 1175 表 Line2 の行 5 のコンテンツ URI 1176</p> 1177<pre> 1178content://com.example.trains/Line2/5 1179</pre> 1180<p> 1181 に対しては、プロバイダは次の MIME タイプを返します 1182</p> 1183<pre> 1184vnd.android.cursor.<strong>item</strong>/vnd.example.line2 1185</pre> 1186<p> 1187 ほとんどのコンテンツ プロバイダが、使用する MIME タイプに対してコントラクト クラス定数を定義します。たとえば、連絡先プロバイダのコントラクト クラス {@link android.provider.ContactsContract.RawContacts} は、1 つの未加工連絡先行の MIME タイプに、定数 {@link android.provider.ContactsContract.RawContacts#CONTENT_ITEM_TYPE} を定義します。 1188 1189 1190 1191 1192</p> 1193<p> 1194 1 つの行のコンテンツ URI については、<a href="#ContentURIs">コンテンツ URI</a> セクションをご覧ください。 1195 1196</p> 1197