コンテンツプロバイダContentProviderとコンテンツ解析者ContentResolver


概要
ContentProviderのandroidでの役割は、データを対外的に共有することです.つまり、ContentProviderを通じてアプリケーションのデータを他のアプリケーションに共有してアクセスすることができます.他のアプリケーションはContentProviderを通じてアプリケーションのデータを削除して調べることができます.データ共有については,以前にファイルの操作モードを学習したが,ファイルの操作モードがContextであることを知っていた.MODE_WORLD_READADBLEまたはContext.MODE_WORLD_WRITEABLEも同様にデータを対外的に共有することができる.では、ここではなぜContentProviderを使ってデータを対外共有するのでしょうか.このように、ファイル操作モードを採用してデータを対外共有すると、データのアクセス方式はデータ記憶の方式によって異なり、データのアクセス方式が統一できない.例えば、xmlファイルを採用してデータを対外共有するには、xml解析を行ってからデータを読み取る必要がある.sharedpreferencesを使用してデータを共有するには、sharedpreferences APIを使用してデータを読み込む必要があります.ContentProviderを使用してデータを対外的に共有するメリットは、データへのアクセス方法を統一することです.
ContentProviderの原理は、一定のルールに従って自分のインタフェースを他のアプリケーションに暴露して自分のアプリケーションのデータにアクセスすることです(実際には、インタフェースを追加削除して暴露し、他のアプリケーションに自分のデータにアクセスさせることです).
ContentResolverは、一定のルールに従ってコンテンツプロバイダのデータにアクセスします(実際には、コンテンツプロバイダがカスタマイズしたインタフェースを呼び出してデータを操作します).
ContentProvider対外共有データ:
ステップ
1.クラス継承ContentProviderを定義する
2.照合ルールの定義ホスト名+path code urimatcher content://
3.静的コードブロックによるマッチングルールの追加
4.インベントリファイル構成コンテンツプロバイダにauthoritiesを追加することを忘れないでください.
説明:
ContentProviderを継承するには、次の方法を書き換える必要があります.
public class PersonContentProvider extends ContentProvider{
  public boolean onCreate()
  public Uri insert(Uri uri, ContentValues values)
  public int delete(Uri uri, String selection, String[] selectionArgs)
  public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
  public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
  public String getType(Uri uri)}
4つ目はAndroidManifestですxmlはこのContentProviderを使用して構成され、他のアプリケーションがContentProviderを見つけることができるようにContentProvider
authorities(ホスト名/ドメイン名)を使用して一意の識別を行い、ContentProviderをWebサイトと見なすことができます(考えてみれば、Webサイトもデータ提供者です).authoritiesは彼のドメイン名です.
ContentProviderクラスの主なメソッドの役割:
public boolean onCreate()
この方法はContentProviderが作成されると呼び出され、Androidが起動すると、ContentProviderが他のアプリケーションで初めてアクセスしたときに作成されます.
public Uri insert(Uri uri, ContentValues values)
この方法は、外部アプリケーションがContentProviderにデータを追加するために使用されます.
public int delete(Uri uri, String selection, String[] selectionArgs)
この方法は、外部アプリケーションがContentProviderからデータを削除するために使用されます.
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
この方法は、外部アプリケーションがContentProviderのデータを更新するために使用されます.
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
この方法は、外部アプリケーションがContentProviderからデータを取得するために使用されます.
public String getType(Uri uri)
この方法は、現在のUrlで表されるデータのMIMEタイプを返すために使用される.操作データが集合型に属する場合、MIME型文字列はvndであるべきである.android.cursor.dir/先頭、
たとえば、すべてのpersonレコードを取得するUriはcontent://cn.itcast.provider.personprovider/personでは、返されるMIMEタイプ文字列は「vnd.android.cursor.dir/person」です.操作するデータが非集合型データに属する場合、MIME型文字列はvndであるべきである.android.cursor.item/先頭、例えばidが10のpersonレコードが得られ、Uriはcontent://cn.itcast.provider.personprovider/person/10では、返されるMIMEタイプ文字列は「vnd.android.cursor.item/person」です.
Uri紹介
Uriは操作するデータを表し、Uriは主に2つの部分の情報を含んでいる:1』操作が必要なContentProvider、2』はContentProviderの中のどんなデータに対して操作を行い、1つのUriは以下のいくつかの部分から構成されている:
ContentProvider(コンテンツプロバイダ)のschemeはすでにAndroidによって規定されており、schemeは:content://
ホスト名(またはAuthority)は、このContentProviderを一意に識別するために使用され、外部呼び出し者はこの識別に基づいて見つけることができます.
パス(path)は、ビジネスに応じて構築されるデータを表すために使用できます.次のようにします.
personテーブルのidが10のレコードを操作するには、/person/10というパスを構築します.
personテーブルのidが10のレコードのnameフィールドを操作するには、person/10/name
personテーブルのすべてのレコードを操作するには、/personというパスを構築します.
xxxテーブルのレコードを操作するには、/xxxを構築します.
もちろん、操作するデータは必ずしもデータベースから来るものではなく、ファイル、xml、またはネットワークなどの他の記憶方式であってもよい.以下のようにする.
xmlファイルのpersonノードの下にあるnameノードを操作するには、/person/nameというパスを構築します.
文字列をUriに変換する場合は、Uriクラスのparse()メソッドを使用して、次のようにします.
Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person")
UriMatcherクラスの使用説明
Uriは操作するデータを表すため,Uriを解析し,Uriからデータを取得することがしばしば必要である.Androidシステムは、Uriを操作するための2つのツールクラスを提供しています.それぞれUriMatcherとContentUrisです.
それらの使用を把握すると、私たちの開発作業に便利になります.UriMatcherクラスはUriをマッチングするために使用されます.まず、最初のステップでは、Uriパスをすべて登録する必要があります.以下のようにします.
//定数UriMatcher.NO_MATCHは、任意のパスに一致しない戻りコードUriMatcher sMatcher=new UriMatcher(UriMatcher.NO_MATCH);match()メソッドが一致する場合content://cn.itcast.provider.personprovider/personパス、戻り一致コードは1 sMatcherである.addURI(“cn.itcast.provider.personprovider”, “person”, 1);//マッチングuriを追加し、マッチングするとマッチングコード//match()メソッドがマッチングする場合content://cn.itcast.provider.personprovider/person/230パス、戻り一致コードは2 sMatcherである.addURI(“cn.itcast.provider.personprovider”, “person/#”, 2);//#ワイルドカード番号switch(sMatcher.match(Uri.parse)content://cn.itcast.provider.personprovider/person/10"){case 1 break;case 2 break;default://不整合break;}一致するUriを登録したら、sMatcherを使用できます.match(uri)メソッドは入力したUriをマッチングし,マッチングするとマッチングコードを返し,マッチングコードはaddURI()メソッドを呼び出して入力した3番目のパラメータであり,
仮定照合content://cn.itcast.provider.personprovider/personパス、返される一致コードは1です.
コードの例
package com.itheima.transaction;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;

public class AccountProvider extends ContentProvider {

	private static final int QUEYSUCESS = 0;  // ctrl + shift + X(   )        + y  
	private static final int INSERTSUCESS = 1;
	
	private static final int UPDATESUCESS  = 2;
	
	private static final int DELSUCESS  = 3;
	
	//1                      code:                         -1
	 static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);

	private MyOpenHelper helper;
	
	//2         
	 
	 static{
		 //         
		 /**
		  * authority                       
		  * path            com.itheima.contentprovider/query
		  * code     
		  */
		 matcher.addURI("com.itheima.contentprovider", "query", QUEYSUCESS);
		 //        
		 matcher.addURI("com.itheima.contentprovider", "insert", INSERTSUCESS);
		 //        
		 matcher.addURI("com.itheima.contentprovider", "update", UPDATESUCESS);
		 //        
		 matcher.addURI("com.itheima.contentprovider", "delete", DELSUCESS);
		 
		 
	 }
	 
	
	@Override
	public boolean onCreate() {
		helper = new MyOpenHelper(getContext());
		
		
		
		return false;
	}

	//Uri                tel:            
	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		//     uri                
		int match = matcher.match(uri);
		if (match == QUEYSUCESS ) {
			//       
			SQLiteDatabase db = helper.getReadableDatabase();  //        
			Cursor cursor = db.query("info", projection, selection, selectionArgs, null, null, sortOrder);
			
			//              cursor    db 
			
			//              
			getContext().getContentResolver().notifyChange(uri, null);
			
			return cursor;
			
		}else{
			//     
			throw new IllegalArgumentException("      ");
			
		}
		
		
	}

	@Override
	public String getType(Uri uri) {
		return null;
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		
		int match = matcher.match(uri);
		if (match == INSERTSUCESS) {
			//      
			SQLiteDatabase db = helper.getReadableDatabase();
			long insert = db.insert("info", null, values);
			
			//                                              
			
			if (insert>0) {

				//                
				getContext().getContentResolver().notifyChange(uri, null);
			}
			
			
			
			
			Uri uri2 = Uri.parse("com.itheima.contentprovider/"+insert);
			return uri2;
		}else{
			//     
			throw new IllegalArgumentException("      ");
			
		}
				
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		int match = matcher.match(uri);
		if (match == DELSUCESS) {
			//    
			SQLiteDatabase db = helper.getReadableDatabase();
			int delete = db.delete("info", selection, selectionArgs);
			
			if (delete>0) {
				//              
				getContext().getContentResolver().notifyChange(uri, null);
				
			}
			
			
			return delete;
			
		}else {
			
			//     
			throw new IllegalArgumentException("      ");
			
		}
		
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		
		int match = matcher.match(uri);
		if (match == UPDATESUCESS) {
			//     
			SQLiteDatabase db = helper.getReadableDatabase();
			int update = db.update("info", values, selection, selectionArgs);
			
			if (update>0) {
				//              
				getContext().getContentResolver().notifyChange(uri, null);
			}
			
			return update;
		}else {
			//     
			throw new IllegalArgumentException("      ");
		}
		
	}

}

ContentResolver ContentResolver ContentResolverを使用してContentProviderが提供するインタフェースを呼び出し、データを操作する
外部アプリケーションがContentProviderのデータを追加、削除、変更、クエリーする必要がある場合は、ContentResolverクラスを使用してContentResolverオブジェクトを取得し、
Activityが提供するgetContentResolver()メソッドを使用できます.ContentResolverクラスには、ContentProviderクラスと同じ署名の4つのメソッドが用意されています.このメソッドは、ContentProviderにデータを追加するためのpublic Uri insert(Uriuri,ContentValue values)です.public int delete(Uriuri,String selection,String[]selectionArgs)ContentProviderからデータを削除する方法です.public int update(Uriuri,ContentValue,String selection,String[]selectionArgs)ContentProviderのデータを更新する方法です.public Cursor query(Uriuri,String[]projection,String selection,String[]selectionArgs,String sortOrder)ContentProviderからデータを取得する方法.これらの方法の最初のパラメータはUriであり、操作するContentProviderとその中のどのデータを操作するかを表し、与えられたものはUriであると仮定する.parse(“content://cn.itcast.providers.personprovider/person/10)を選択すると、ホスト名はcnとなります.itcast.providers.personproviderのContentProviderが操作し,操作したデータはpersonテーブル中のidが10のレコードである.
  ContentResolver ContentProvider        、  、       :
	ContentResolver resolver =  getContentResolver();
	Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person");
	//      
	ContentValues values = new ContentValues();
	values.put("name", "itcast");
	values.put("age", 25);
	resolver.insert(uri, values);		
	//  person      
	Cursor cursor = resolver.query(uri, null, null, null, "personid desc");
	while(cursor.moveToNext()){
		Log.i("ContentTest", "personid="+ cursor.getInt(0)+ ",name="+ cursor.getString(1));
	}
	// id 1    name       liming
	ContentValues updateValues = new ContentValues();
	updateValues.put("name", "liming");
	resolver.update(updateIdUri, updateValues, null, null);

ContentProviderでのデータの変更の傍受
ContentProviderのアクセス者がContentProviderのデータが変化したことを知る必要がある場合は、ContentProviderのデータが変化したときに呼び出すことができます.
getContentResolver().notifyChange(uri,null)は、このURIに登録されている訪問者に通知し、例は以下の通りである.
public class PersonContentProvider extends ContentProvider {
	public Uri insert(Uri uri, ContentValues values) {
		db.insert("person", "personid", values);
		getContext().getContentResolver().notifyChange(uri, null);
	}
	}

ContentProviderのアクセス者がデータ変更通知を取得する必要がある場合は、ContentObserverを使用してデータ(データはuri記述)をリスニングする必要があり、データ変更通知を監視する場合、
ContentObserverのonChange()メソッドが呼び出されます.
	getContentResolver().registerContentObserver(Uri.parse("content://cn.itcast.providers.personprovider/person"),
        		true,//true         Uri                ,    uri        uri          
                                           new PersonObserver(new Handler()));
	public class PersonObserver extends ContentObserver{
	public PersonObserver(Handler handler) {
		super(handler);
	}
	public void onChange(boolean selfChange) {
	    //             
	}
	}

インスタンスコード
コンテンツ解析者によるメッセージのバックアップ
package com.itheima.backupsms;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import org.xmlpull.v1.XmlSerializer;

import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.FileObserver;
import android.app.Activity;
import android.database.Cursor;
import android.util.Xml;
import android.view.Menu;
import android.view.View;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}

	/**
	 *         
	 * 
	 * @param v
	 */
	public void backup(View v) {

		try {
			// 1    xml     
			XmlSerializer serializer = Xml.newSerializer();
			// 2   xml        
			File file = new File(Environment.getExternalStorageDirectory()
					.getPath(), "smsbackup.xml");
			FileOutputStream fos = new FileOutputStream(file);
			serializer.setOutput(fos, "utf-8");

			// 3     xml  
			serializer.startDocument("utf-8", true);

			//     xml     smss
			serializer.startTag(null, "smss");
			// 1                                                  
			Uri uri = Uri.parse("content://sms");

			Cursor cursor = getContentResolver().query(uri,
					new String[] { "address", "date", "body" }, null, null,
					null);
			while (cursor.moveToNext()) {
				//  sms   
				serializer.startTag(null, "sms");
				String address = cursor.getString(0);
				String date = cursor.getString(1);
				String body = cursor.getString(2);

				//    address    
				serializer.startTag(null, "address");
				serializer.text(address);
				serializer.endTag(null, "address");
				
				//    date    
				serializer.startTag(null, "date");
				serializer.text(date);
				serializer.endTag(null, "date");
				
				
				//    body    
				serializer.startTag(null, "body");
				serializer.text(body);
				serializer.endTag(null, "body");
				
				serializer.endTag(null, "sms");
			}

			//     address date body

			serializer.endTag(null, "smss");

			//     
			serializer.endDocument();

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}

コンテンツ解析者によるメッセージの挿入
//1           
		Uri uri = Uri.parse("content://sms");
		ContentValues values = new ContentValues();
		values.put("address", "110");
		values.put("date", System.currentTimeMillis());
		values.put("body", "             ");
		getContentResolver().insert(uri, values);

コンテンツ解析者による連絡先データの取得
1.まずraw_を検索しますcontactsテーブル取得contact_id  
2.去data表根据contact_id mimetype data 1のデータを取得する
3.そしてmimetype_によるidはデータ型を区別する
package com.itheima.getcontactinfo.utils;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;

import com.itheima.getcontactinfo.domain.ContactInfo;

public class ContactUtils {

	public static List getContactInfos(Context context) {

		List contactLists = new ArrayList();
		// 1        raw_contacts      contact_id 
		// (1)      ?        path
		Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
		Uri datauri = Uri.parse("content://com.android.contacts/data");

		ContentResolver resolver = context.getContentResolver();
		Cursor cursor = resolver.query(uri, new String[] { "contact_id" },
				null, null, null);
		while (cursor.moveToNext()) {
			//    contact_id   
			String contact_id = cursor.getString(0);
			System.out.println("contact_id--" + contact_id);

			//                contact_id     
			if (contact_id != null) {

				ContactInfo info = new ContactInfo();
				info.setId(contact_id);

				// 2 data     contact_id     mimetyple_id  data1  

				Cursor dataCursor = resolver.query(datauri, new String[] {
						"mimetype", "data1" }, "raw_contact_id=?",
						new String[] { contact_id }, null);
				while (dataCursor.moveToNext()) {
					String mimetype = dataCursor.getString(0); //    mimeytype
					String data1 = dataCursor.getString(1);

					// 3      mimetype          
					if ("vnd.android.cursor.item/email_v2".equals(mimetype)) {
						info.setEmail(data1);

					} else if ("vnd.android.cursor.item/name".equals(mimetype)) {

						info.setName(data1);

					} else if ("vnd.android.cursor.item/phone_v2"
							.equals(mimetype)) {
						System.out.println("data---    -" + data1);
						info.setPhone(data1);
					}

				}
				dataCursor.close();
				contactLists.add(info); //  info       

			}

		}
		cursor.close();

		return contactLists;

	}

}
package com.itheima.getcontactinfo.domain;

public class ContactInfo {

	private String id;
	private String name;
	private String phone;
	private String email;
	
	
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPhone() {
		return phone;
	}
	public void setPhone(String phone) {
		this.phone = phone;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	@Override
	public String toString() {
		return "ContactInfo [id=" + id + ", name=" + name + ", phone=" + phone
				+ ", email=" + email + "]";
	}

	
	
	
	
}

コンテンツ解析者による連絡先の挿入
1.先にraw_へcontactsデータの挿入
2.dataテーブルへのデータ挿入mimetype contact_によるidデータを挿入する
package com.itheima.insert.contact;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;

public class MainActivity extends Activity {

	private EditText et_name;
	private EditText et_phone;
	private EditText et_email;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		//1         
		
		et_name = (EditText) findViewById(R.id.et_name);
		et_phone = (EditText) findViewById(R.id.et_phone);
		et_email = (EditText) findViewById(R.id.et_email);
		
		
		
		
	}
	
	/**
	 *         
	 * @param v
	 */
	public void click(View v){
		
		//1       edittext   
		String name = et_name.getText().toString().trim();
		String phone = et_phone.getText().toString().trim();
		String email = et_email.getText().toString().trim();
		
		//2   raw_contacts                  
		Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
		Uri datauri = Uri.parse("content://com.android.contacts/data");
		
		ContentValues values = new ContentValues();
		//                   raw_contacts            
		Cursor cursor = getContentResolver().query(uri, null, null, null, null);
		int count = cursor.getCount();  //          
	    int contact_id =  count + 1;  
		
		values.put("contact_id", contact_id);
		getContentResolver().insert(uri, values);
		
		// 3  data       
		
		ContentValues nameValues = new ContentValues();
		nameValues.put("data1", name);
		nameValues.put("mimetype", "vnd.android.cursor.item/name");
		nameValues.put("raw_contact_id", contact_id);
		getContentResolver().insert(datauri, nameValues);

		ContentValues phoneValues = new ContentValues();
		phoneValues.put("data1", phone);
		phoneValues.put("mimetype", "vnd.android.cursor.item/phone_v2");
		phoneValues.put("raw_contact_id", contact_id);
		getContentResolver().insert(datauri, phoneValues);
		
		ContentValues emailValues = new ContentValues();
		emailValues.put("data1", email);
		emailValues.put("mimetype", "vnd.android.cursor.item/email_v2");
		emailValues.put("raw_contact_id", contact_id);
		getContentResolver().insert(datauri, emailValues);
		
		
		
		
		
	}

	
}

リスニングとコンテンツ解析者によるメールのリスニング
package com.itheima.smslistener;

import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.database.ContentObserver;
import android.database.Cursor;
import android.view.Menu;

public class MainActivity extends Activity {

	private Uri	uri;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		
		//1          
	   	uri = Uri.parse("content://sms");
		getContentResolver().registerContentObserver(uri, true, new MyObserver(new Handler()));
		
	}

	
	
	private  class MyObserver  extends ContentObserver{

		public MyObserver(Handler handler) {
			super(handler);
		}
		@Override
		public void onChange(boolean selfChange) {
			
			//                             
			
			Cursor cursor = getContentResolver().query(uri, new String[]{"address","body","date"}, null, null, null);
			while(cursor.moveToNext()){
				
				String address = cursor.getString(0);
				String body = cursor.getString(1);
				String date = cursor.getString(2);
				
				System.out.println("address---"+address+"--body:"+body);
				
			}
			
			super.onChange(selfChange);
		}
		
		
	}
	
}