android ContextProvider

来源:互联网 发布:mac截图后存在哪了 编辑:程序博客网 时间:2024/06/08 20:05

1.content provider简介

在andorid 中要实现不同进程间的数据共享,除了可以使用sharedPreferences,File...这外,最重要的还有content provider.通过Content provider应用程序可以把自己私有的数据暴露给别的应用程序,让别的应用程序可以对自己私有的数据库实现增删改查。

2 如何使用

如果没有现存需要的content provider需要自己写一个类extends ContentProvider

例如: 现有一个Account 管理类,需要提供给其它app 以crud操作的方法 .

步骤:

 1.写一个类继承ContentProvider
2. 清单文件中配置authorities 比如,android:authorities="com.example"
3. 训练内容提供者的匹配器 UriMatcher
4. 根据需求实现内容提供者的增删改查的方法

public class AccountProvider extends ContentProvider{private static final int  ACCOUNT=1;private static final int SINGLE_ACCOUNT=2;private DbHelper helper;private String table="account";private static UriMatcher matcher=new UriMatcher(UriMatcher.NO_MATCH);static{matcher.addURI("com.example","account",ACCOUNT);matcher.addURI("com.example","account/#",SINGLE_ACCOUNT);}@Overridepublic boolean onCreate() {helper=new DbHelper(getContext());return true;}@Overridepublic Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {int code=matcher.match(uri);if(code==ACCOUNT){SQLiteDatabase db = helper.getReadableDatabase();return db.query(table, projection, selection, selectionArgs, null, null,null);}else if(code==SINGLE_ACCOUNT){}return null;}@Overridepublic String getType(Uri uri) {// TODO Auto-generated method stubreturn null;}@Overridepublic Uri insert(Uri uri, ContentValues values) {int code=matcher.match(uri);if(code==ACCOUNT){SQLiteDatabase db = helper.getReadableDatabase();long id= db.insert(table, null, values);db.close();return Uri.parse("content://com.example/account/"+id);} return null;}@Overridepublic int delete(Uri uri, String selection, String[] selectionArgs) {int code = matcher.match(uri);if (code == ACCOUNT) {SQLiteDatabase db = helper.getWritableDatabase();int result = db.delete("account", selection, selectionArgs);db.close();//后面程序,通知这个uri的数据变化了getContext().getContentResolver().notifyChange(uri, null);return result;} else {throw new IllegalArgumentException("无权删除数据。");}}@Overridepublic int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) {int code = matcher.match(uri);if (code == ACCOUNT) {SQLiteDatabase db = helper.getWritableDatabase();int result = db.update("account", values, selection, selectionArgs);db.close();//后面程序,通知这个uri的数据变化了getContext().getContentResolver().notifyChange(uri, null);return result;} else {throw new IllegalArgumentException("无权修改数据。");}}}

在AndroidManifest.xml中配置

 <provider      android:name="com.example.ap.AccountProvider"       android:authorities="com.example"> </provider>
这样就写好了一个ContentProvider.

另外一个app 里使用 getContentResolver 去解析,注意Uri 必须得合法

public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}//查询public void query(View view){//得到内容提供者的解析器ContentResolver resolver = getContentResolver();Uri uri = Uri.parse("content://com.example/account");Cursor cursor = resolver.query(uri, null, null, null, null);while(cursor.moveToNext()){String id = cursor.getString(0);String name = cursor.getString(1);String money = cursor.getString(2);System.out.println(id);System.out.println(name);System.out.println(money);}cursor.close();}/** * 添加一条记录 * @param view */public void add(View view){ContentResolver resolver = getContentResolver();Uri uri = Uri.parse("content://com.example/account");ContentValues values = new ContentValues();values.put("name", "王五");values.put("money", 1000000.23f);Uri result  = resolver.insert(uri, values);Toast.makeText(this, result.toString(), 0).show();}//删除某个记录public void delete(View view){ContentResolver resolver = getContentResolver();Uri uri = Uri.parse("content://com.example/account");int result = resolver.delete(uri, "name=?", new String[]{"王五"});if(result>0){Toast.makeText(this, "删除成功", 0).show();}else{Toast.makeText(this, "删除失败", 0).show();}}//更新一下public void update(View view){ContentResolver resolver = getContentResolver();Uri uri = Uri.parse("content://com.example/account");ContentValues values = new ContentValues();values.put("money", 0.05f);int result = resolver.update(uri, values, "name=?", new String[]{"王五"});if(result>0){Toast.makeText(this, "修改成功", 0).show();}else{Toast.makeText(this, "修改失败", 0).show();}}}


如果有,需在应用的Context 中使用ContentResolver对象作为客户端与provider 进行通讯.ContentResolver resolver = getContentResolver();

Android自己包含了管理音频,视频,图像,个人通讯录,短信等数据的content providers;

例如现存需要备份短信:

就可以直接使用这个uri去获取Uri uri = Uri.parse("content://sms/");
注意需要声明<uses-permission android:name="android.permission.READ_SMS"/> 的权限

/** * 短信的备份 *  * @param view */public void backup(View view) {try {// 利用内容提供者获取短信私有的数据ContentResolver resovler = getContentResolver();Uri uri = Uri.parse("content://sms/");Cursor cursor = resovler.query(uri, new String[] { "address","date", "type", "body" }, null, null, null);XmlSerializer serializer = Xml.newSerializer();File file = new File(Environment.getExternalStorageDirectory(),"backup.xml");FileOutputStream os = new FileOutputStream(file);serializer.setOutput(os, "utf-8");// 写xml文件的头serializer.startDocument("utf-8", true);serializer.startTag(null, "root");while (cursor.moveToNext()) {String address = cursor.getString(0);serializer.startTag(null, "sms");serializer.startTag(null, "address");serializer.text(address);serializer.endTag(null, "address");serializer.startTag(null, "date");String date = cursor.getString(1);serializer.text(date);serializer.endTag(null, "date");serializer.startTag(null, "type");String type = cursor.getString(2);serializer.text(type);serializer.endTag(null, "type");serializer.startTag(null, "body");String body = cursor.getString(3);serializer.text(body);serializer.endTag(null, "body");serializer.endTag(null, "sms");}cursor.close();serializer.endTag(null, "root");serializer.endDocument();os.close();Toast.makeText(this, "备份成功", 0).show();} catch (Exception e) {e.printStackTrace();Toast.makeText(this, "备份失败", 0).show();}}

读取系统的联系人列表:

需要的权限: <uses-permission android:name="android.permission.READ_CONTACTS"/>

public static List<ContactInfo> getAllContactInfos(Context context) {List<ContactInfo> infos = new ArrayList<ContactInfo>();ContentResolver resolver = context.getContentResolver();Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");Uri datauri = Uri.parse("content://com.android.contacts/data");Cursor cursor = resolver.query(uri, new String[] { "contact_id" },null, null, null);while (cursor.moveToNext()) {String id = cursor.getString(0);ContactInfo info = new ContactInfo();info.setId(id);System.out.println("id:" + id);if (id != null) {// 根据id查询data表,把这个联系人的数据获取出来。Cursor dataCursor = resolver.query(datauri, new String[] {"data1", "mimetype" }, "raw_contact_id=?",new String[] { id }, null);while (dataCursor.moveToNext()) {String data1 = dataCursor.getString(0);String mimetype = dataCursor.getString(1);if ("vnd.android.cursor.item/email_v2".equals(mimetype)) {// emailinfo.setEmail(data1);} else if ("vnd.android.cursor.item/im".equals(mimetype)) {// qqinfo.setQq(data1);} else if ("vnd.android.cursor.item/name".equals(mimetype)) {// nameinfo.setName(data1);} else if ("vnd.android.cursor.item/phone_v2".equals(mimetype)) {// nameinfo.setPhone(data1);}}infos.add(info);dataCursor.close();}}cursor.close();return infos;}
使用contentProvider 添加联系人:

ui的xml

<LinearLayout 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"    tools:context=".MainActivity"    android:orientation="vertical" >    <EditText        android:id="@+id/et_phone"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="123456789999"        android:hint="电话号码" />      <EditText        android:id="@+id/et_name"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="haha"        android:hint="姓名" />        <EditText        android:id="@+id/et_email"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="aa@aa.com"        android:hint="邮箱" />          <Button        android:id="@+id/bt_save"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="保存"         android:onClick="save"/></LinearLayout>
<pre name="code" class="java" style="font-size: 14px; line-height: 26px;">MainActivity 里实现添加联系的功能,注意权限

public class MainActivity extends Activity {EditText et_phone;EditText et_name;EditText et_email;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);                et_phone=(EditText) findViewById(R.id.et_phone);        et_name=(EditText) findViewById(R.id.et_name);        et_email=(EditText) findViewById(R.id.et_email);    }    public void save(View v){    String phone=et_phone.getText().toString();    String name=et_name.getText().toString();    String email=et_email.getText().toString();        ContentResolver resolver = this.getContentResolver();    Uri uri_raw_contacts=Uri.parse("content://com.android.contacts/raw_contacts");    Uri uri_data=Uri.parse("content://com.android.contacts/data");        Cursor cursor=resolver.query(uri_raw_contacts, new String[]{"_id"},null,null,"_id desc");    int id=1;    if(cursor.moveToFirst()){    id=cursor.getInt(0)+1;    }         ContentValues val=new ContentValues();    val.put(Contactables.RAW_CONTACT_ID, id);    val.put(Contactables.MIMETYPE,"vnd.android.cursor.item/phone_v2");    val.put("data1",phone);resolver.insert(uri_data,val);    val=new ContentValues();    val.put(Contactables.RAW_CONTACT_ID, id);    val.put(Contactables.MIMETYPE,"vnd.android.cursor.item/name");    val.put("data1",name);resolver.insert(uri_data,val);val=new ContentValues();    val.put(Contactables.RAW_CONTACT_ID, id);    val.put(Contactables.MIMETYPE,"vnd.android.cursor.item/email_v2");    val.put("data1",email);resolver.insert(uri_data,val);    Toast.makeText(this, "添加数据成功", 0).show();    }    }

3.内容观察者
使用ContentObserver定向"监听" ContentProvider 内部事件:

例如,可以为短信的contentProvider 注册一个监听器来监听短信的变化

public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);getContentResolver().registerContentObserver(Uri.parse("content://sms"), true, new MyObserver(new Handler()));}private class MyObserver extends ContentObserver{public MyObserver(Handler handler) {super(handler);}@Overridepublic void onChange(boolean selfChange) {super.onChange(selfChange);System.out.println("短信的数据库变化了。");//查询数据库。....}}}

//如果自定义的ContentProvider需要发送通知.
getContext().getContentResolver().notifyChange(uri, null);

相比广播机制更加隐密.更加安全




0 0
原创粉丝点击