Android-content-providers
Android-コンテンツプロバイダー
'_コンテンツプロバイダーコンポーネントは、要求に応じて1つのアプリケーションから他のアプリケーションにデータを提供します。 このような要求は、ContentResolverクラスのメソッドによって処理されます。 コンテンツプロバイダーはさまざまな方法でデータを保存でき、データはデータベース、ファイル、またはネットワーク経由でも保存できます。_
ContentProvider
'_アプリケーション間でデータを共有する必要がある場合があります。 これは、コンテンツプロバイダーが非常に役立つ場所です。_
コンテンツプロバイダーを使用すると、コンテンツを1か所に集中させ、必要に応じてさまざまなアプリケーションにアクセスさせることができます。 コンテンツプロバイダーは、クエリ、コンテンツの編集、およびinsert()、update()、delete()、query()メソッドを使用したコンテンツの追加または削除が可能なデータベースと非常によく似た動作をします。 ほとんどの場合、このデータは SQlite データベースに保存されます。
コンテンツプロバイダーは ContentProvider クラスのサブクラスとして実装され、他のアプリケーションがトランザクションを実行できるようにするAPIの標準セットを実装する必要があります。
public class My Application extends ContentProvider {
}
コンテンツURI
コンテンツプロバイダーを照会するには、次の形式を持つURIの形式でクエリ文字列を指定します-
<prefix>://<authority>/<data_type>/<id>
ここにURIのさまざまな部分の詳細があります-
Sr.No | Part & Description |
---|---|
1 |
prefix これは常にcontent://に設定されます |
2 |
authority これは、contacts _、 browser_などのコンテンツプロバイダーの名前を指定します。 サードパーティのコンテンツプロバイダーの場合、これは_com.finddevguides.statusprovider_などの完全修飾名にすることができます。 |
3 |
data_type これは、この特定のプロバイダーが提供するデータのタイプを示します。 たとえば、_Contacts_コンテンツプロバイダーからすべての連絡先を取得している場合、データパスは_people_になり、URIはthiscontent://contacts/peopleのようになります |
4 |
id これは、要求された特定のレコードを指定します。 たとえば、連絡先コンテンツプロバイダーで連絡先番号5を探している場合、URIは_content://contacts/people/5_のようになります。 |
コンテンツプロバイダーの作成
これには、独自のコンテンツプロバイダーを作成するためのいくつかの簡単な手順が含まれます。
- まず、_ContentProviderbaseclass._を拡張するコンテンツプロバイダークラスを作成する必要があります。
- 次に、コンテンツへのアクセスに使用されるコンテンツプロバイダーURIアドレスを定義する必要があります。
- 次に、コンテンツを保持するために独自のデータベースを作成する必要があります。 通常、AndroidはSQLiteデータベースを使用し、フレームワークは_onCreate()_メソッドをオーバーライドする必要があります。このメソッドはSQLite Open Helperメソッドを使用してプロバイダーのデータベースを作成または開きます。 アプリケーションが起動すると、各コンテンツプロバイダーの_onCreate()_ハンドラーがメインアプリケーションスレッドで呼び出されます。
- 次に、コンテンツプロバイダークエリを実装して、さまざまなデータベース固有の操作を実行する必要があります。
- 最後に、<provider>タグを使用してコンテンツプロバイダーをアクティビティファイルに登録します。
以下は、コンテンツプロバイダーを機能させるためにコンテンツプロバイダークラスでオーバーライドする必要があるメソッドのリストです-
ContentProvider
- * onCreate()*このメソッドは、プロバイダーの起動時に呼び出されます。
- * query()*このメソッドはクライアントからリクエストを受け取ります。 結果はCursorオブジェクトとして返されます。
- insert()このメソッドは、コンテンツプロバイダーに新しいレコードを挿入します。
- * delete()*このメソッドは、コンテンツプロバイダーから既存のレコードを削除します。
- * update()*このメソッドは、コンテンツプロバイダーからの既存のレコードを更新します。
- * getType()*このメソッドは、指定されたURIのデータのMIMEタイプを返します。
例
この例では、独自の_ContentProvider_を作成する方法を説明します。 Hello World Example−の作成中に行った手順と同様に、次の手順に従ってみましょう。
Step | Description |
---|---|
1 | You will use Android StudioIDE to create an Android application and name it as My Application under a package com.example.MyApplication, with blank Activity. |
2 | Modify main activity file MainActivity.java to add two new methods onClickAddName() and onClickRetrieveStudents(). |
3 | Create a new java file called StudentsProvider.java under the package com.example.MyApplication to define your actual provider and associated methods. |
4 | Register your content provider in your AndroidManifest.xml file using <provider…/> tag |
5 | Modify the default content of res/layout/activity_main.xml file to include a small GUI to add students records. |
6 | No need to change string.xml.Android studio take care of string.xml file. |
7 | Run the application to launch Android emulator and verify the result of the changes done in the application. |
以下は、変更されたメインアクティビティファイル src/com.example.MyApplication/MainActivity.java の内容です。 このファイルには、基本的なライフサイクルメソッドのそれぞれを含めることができます。 2つの新しいメソッド_onClickAddName()_および_onClickRetrieveStudents()_を追加して、アプリケーションとのユーザーインタラクションを処理します。
package com.example.MyApplication;
import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.ContentValues;
import android.content.CursorLoader;
import android.database.Cursor;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onClickAddName(View view) {
//Add a new student record
ContentValues values = new ContentValues();
values.put(StudentsProvider.NAME,
((EditText)findViewById(R.id.editText2)).getText().toString());
values.put(StudentsProvider.GRADE,
((EditText)findViewById(R.id.editText3)).getText().toString());
Uri uri = getContentResolver().insert(
StudentsProvider.CONTENT_URI, values);
Toast.makeText(getBaseContext(),
uri.toString(), Toast.LENGTH_LONG).show();
}
public void onClickRetrieveStudents(View view) {
//Retrieve student records
String URL = "content://com.example.MyApplication.StudentsProvider";
Uri students = Uri.parse(URL);
Cursor c = managedQuery(students, null, null, null, "name");
if (c.moveToFirst()) {
do{
Toast.makeText(this,
c.getString(c.getColumnIndex(StudentsProvider._ID)) +
", " + c.getString(c.getColumnIndex( StudentsProvider.NAME)) +
", " + c.getString(c.getColumnIndex( StudentsProvider.GRADE)),
Toast.LENGTH_SHORT).show();
} while (c.moveToNext());
}
}
}
_com.example.MyApplication_パッケージの下に新しいファイルStudentsProvider.javaを作成し、以下が src/com.example.MyApplication/StudentsProvider.java の内容です-
package com.example.MyApplication;
import java.util.HashMap;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
public class StudentsProvider extends ContentProvider {
static final String PROVIDER_NAME = "com.example.MyApplication.StudentsProvider";
static final String URL = "content://" + PROVIDER_NAME + "/students";
static final Uri CONTENT_URI = Uri.parse(URL);
static final String _ID = "_id";
static final String NAME = "name";
static final String GRADE = "grade";
private static HashMap<String, String> STUDENTS_PROJECTION_MAP;
static final int STUDENTS = 1;
static final int STUDENT_ID = 2;
static final UriMatcher uriMatcher;
static{
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(PROVIDER_NAME, "students", STUDENTS);
uriMatcher.addURI(PROVIDER_NAME, "students/#", STUDENT_ID);
}
/**
*Database specific constant declarations
*/
private SQLiteDatabase db;
static final String DATABASE_NAME = "College";
static final String STUDENTS_TABLE_NAME = "students";
static final int DATABASE_VERSION = 1;
static final String CREATE_DB_TABLE =
" CREATE TABLE " + STUDENTS_TABLE_NAME +
" (_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
" name TEXT NOT NULL, " +
" grade TEXT NOT NULL);";
/**
*Helper class that actually creates and manages
* the provider's underlying data repository.
*/
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context){
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_DB_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + STUDENTS_TABLE_NAME);
onCreate(db);
}
}
@Override
public boolean onCreate() {
Context context = getContext();
DatabaseHelper dbHelper = new DatabaseHelper(context);
/**
*Create a write able database which will trigger its
* creation if it doesn't already exist.
*/
db = dbHelper.getWritableDatabase();
return (db == null)? false:true;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
/**
*Add a new student record
*/
long rowID = db.insert( STUDENTS_TABLE_NAME, "", values);
/**
*If record is added successfully
*/
if (rowID > 0) {
Uri _uri = ContentUris.withAppendedId(CONTENT_URI, rowID);
getContext().getContentResolver().notifyChange(_uri, null);
return _uri;
}
throw new SQLException("Failed to add a record into " + uri);
}
@Override
public Cursor query(Uri uri, String[] projection,
String selection,String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(STUDENTS_TABLE_NAME);
switch (uriMatcher.match(uri)) {
case STUDENTS:
qb.setProjectionMap(STUDENTS_PROJECTION_MAP);
break;
case STUDENT_ID:
qb.appendWhere( _ID + "=" + uri.getPathSegments().get(1));
break;
default:
}
if (sortOrder == null || sortOrder == ""){
/**
*By default sort on student names
*/
sortOrder = NAME;
}
Cursor c = qb.query(db, projection, selection,
selectionArgs,null, null, sortOrder);
/**
*register to watch a content URI for changes
*/
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int count = 0;
switch (uriMatcher.match(uri)){
case STUDENTS:
count = db.delete(STUDENTS_TABLE_NAME, selection, selectionArgs);
break;
case STUDENT_ID:
String id = uri.getPathSegments().get(1);
count = db.delete( STUDENTS_TABLE_NAME, _ID + " = " + id +
(!TextUtils.isEmpty(selection) ? "
AND (" + selection + ')' : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public int update(Uri uri, ContentValues values,
String selection, String[] selectionArgs) {
int count = 0;
switch (uriMatcher.match(uri)) {
case STUDENTS:
count = db.update(STUDENTS_TABLE_NAME, values, selection, selectionArgs);
break;
case STUDENT_ID:
count = db.update(STUDENTS_TABLE_NAME, values,
_ID + " = " + uri.getPathSegments().get(1) +
(!TextUtils.isEmpty(selection) ? "
AND (" +selection + ')' : ""), selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri );
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)){
/**
*Get all student records
*/
case STUDENTS:
return "vnd.android.cursor.dir/vnd.example.students";
/**
*Get a particular student
*/
case STUDENT_ID:
return "vnd.android.cursor.item/vnd.example.students";
default:
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
}
}
以下は、_AndroidManifest.xml_ファイルの変更されたコンテンツです。 ここでは、コンテンツプロバイダーを含める<provider …/>タグを追加しました。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.MyApplication">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<provider android:name="StudentsProvider"
android:authorities="com.example.MyApplication.StudentsProvider"/>
</application>
</manifest>
以下は、 res/layout/activity_main.xml ファイルの内容です。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.MyApplication.MainActivity">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Content provider"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:textSize="30dp"/>
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Tutorials point "
android:textColor="#ff87ff09"
android:textSize="30dp"
android:layout_below="@+id/textView1"
android:layout_centerHorizontal="true"/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageButton"
android:src="@drawable/abc"
android:layout_below="@+id/textView2"
android:layout_centerHorizontal="true"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button2"
android:text="Add Name"
android:layout_below="@+id/editText3"
android:layout_alignRight="@+id/textView2"
android:layout_alignEnd="@+id/textView2"
android:layout_alignLeft="@+id/textView2"
android:layout_alignStart="@+id/textView2"
android:onClick="onClickAddName"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/editText"
android:layout_below="@+id/imageButton"
android:layout_alignRight="@+id/imageButton"
android:layout_alignEnd="@+id/imageButton"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/editText2"
android:layout_alignTop="@+id/editText"
android:layout_alignLeft="@+id/textView1"
android:layout_alignStart="@+id/textView1"
android:layout_alignRight="@+id/textView1"
android:layout_alignEnd="@+id/textView1"
android:hint="Name"
android:textColorHint="@android:color/holo_blue_light"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/editText3"
android:layout_below="@+id/editText"
android:layout_alignLeft="@+id/editText2"
android:layout_alignStart="@+id/editText2"
android:layout_alignRight="@+id/editText2"
android:layout_alignEnd="@+id/editText2"
android:hint="Grade"
android:textColorHint="@android:color/holo_blue_bright"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Retrive student"
android:id="@+id/button"
android:layout_below="@+id/button2"
android:layout_alignRight="@+id/editText3"
android:layout_alignEnd="@+id/editText3"
android:layout_alignLeft="@+id/button2"
android:layout_alignStart="@+id/button2"
android:onClick="onClickRetrieveStudents"/>
</RelativeLayout>
*res/values/strings.xml* ファイルの次のコンテンツがあることを確認してください。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">My Application</string>
</resources>;
作成したばかりの修正済み My Application アプリケーションを実行してみましょう。 環境のセットアップ中に AVD を作成したと思います。 Android Studio IDEからアプリを実行するには、プロジェクトのアクティビティファイルの1つを開き、ツールバーの[画像:/android/images/eclipse_run.jpg [Android StudioRunアイコン]の実行]アイコンをクリックします。 Android StudioはAVDにアプリをインストールして起動し、セットアップとアプリケーションで問題がなければ、次のエミュレータウィンドウが表示されます。コンピューターの速度に応じて時間がかかることがありますので、しばらくお待ちください。
学生の Name と Grade を入力し、最後に Add Name ボタンをクリックします。これにより、データベースに学生レコードが追加され、データベースに追加されたレコード番号とともにContentProvider URIを示すメッセージが下部に点滅します。 この操作では、* insert()*メソッドを使用します。 このプロセスを繰り返して、コンテンツプロバイダーのデータベースにさらにいくつかの学生を追加します。
データベースにレコードを追加したら、ContentProviderにそれらのレコードを返してもらうように依頼します。それで、 Retrieve Students ボタンをクリックして、実装ごとにすべてのレコードを取得して表示します。 * query()*メソッドの
*MainActivity.java* ファイルでコールバック関数を提供することにより、更新および削除操作に対するアクティビティを記述し、追加および読み取り操作の場合と同じ方法で更新および削除操作用のボタンを持つようにユーザーインターフェイスを変更できます。
このように、アドレス帳などの既存のコンテンツプロバイダーを使用したり、上記の例で説明したように、読み取り、書き込み、更新、削除などのあらゆる種類のデータベース操作を実行できるデータベース指向アプリケーションの開発にコンテンツプロバイダーの概念を使用できます。