Android四大组件之一的ContentProvider

上次说了Activity,这次说一下Android四大组件之一的ContentProvider

1.ContentProvider是什么

ContentProvider是Android四大组件之一 内容提供者

作用:进程之间数据交互&共享,即跨进程通信

Android四大组件之一的ContentProvider

2.uri介绍

1.定义:Uniform Resource Identifier,即统一资源标识符

2.作用:唯一标识Content Provider其中的数据,外界进程通过Uri找到对应的ContentProvider其中的数据,在进行数据操作

uri的定义格式

Android四大组件之一的ContentProvider

3.简单介绍一下系统的获取

//简单的读取收件箱信息

private void getMsgs() {

        Uri parse = Uri.parse("content://sms/");

        ContentResolver contentResolver = getContentResolver();

        Cursor query = contentResolver.query(parse, new String[]{"address", "date", "type", "body"}, null, null, null

        );

        if (query == null) {

            Toast.makeText(this, "我没有邮箱", Toast.LENGTH_SHORT).show();

        } else {

            while (query.moveToNext()) {

                String address = query.getString(0);

                String date = query.getString(1);

                String type = query.getString(2);

                String body = query.getString(3);

                Log.d("MainActivity", "地址:" + address);

                Log.d("MainActivity", "时间:" + date);

                Log.d("MainActivity", "类型:" + type);

                Log.d("MainActivity", "内容:" + body);

                Log.d("MainActivity", "======================");

            }

            query.close();

        }

    }

//别忘了加权限<uses-permission android:name="android.permission.READ_SMS"/>

//简单的往收件箱里插入一条信息

private void insertMsg() {

        ContentResolver resolver = getContentResolver();

        Uri uri = Uri.parse("content://sms/");

        ContentValues conValues = new ContentValues();

        conValues.put("address", "18888888888");

        conValues.put("type", 1);

        conValues.put("date", System.currentTimeMillis());

        conValues.put("body", "你是毕牛逼吗?");

        resolver.insert(uri, conValues);

        Log.e("HeHe", "短信插入完毕~");

    }

//别忘了加权限    <uses-permission android:name="android.permission.WRITE_SMS"/>

//                <uses-permission android:name="android.permission.SEND_SMS"/>

//简单的读取手机联系人

private void getContacts(){

        //①查询raw_contacts表获得联系人的id

        ContentResolver resolver = getContentResolver();

        Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;

        //查询联系人数据

        Cursor cursor = resolver.query(uri, null, null, null, null);

        while(cursor.moveToNext())

        {

            //获取联系人姓名,手机号码

            String cName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));

            String cNum = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

            Log.d("MainActivity", "姓名:" + cName);

            Log.d("MainActivity", "号码:" + cNum.trim());

            Log.d("MainActivity", "======================");

        }

        cursor.close();

    }

//别忘了加 读联系人的权限 <uses-permission android:name="android.permission.READ_CONTACTS"/>

//别忘了读写权限的 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

                 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

//查询指定电话的联系人信息

  private void queryContact(String number){

        Uri uri = Uri.parse("content://com.android.contacts/data/phones/filter/" + number);

        ContentResolver resolver = getContentResolver();

        Cursor cursor = resolver.query(uri, new String[]{"display_name"}, null, null, null);

        if (cursor.moveToFirst()) {

            String name = cursor.getString(0);

            System.out.println(number + "对应的联系人名称:" + name);

        }

        cursor.close();

    }

//添加一个新的联系人

private void AddContact() throws RemoteException, OperationApplicationException {

    //使用事务添加联系人

    Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");

    Uri dataUri =  Uri.parse("content://com.android.contacts/data");

    ContentResolver resolver = getContentResolver();

    ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();

    ContentProviderOperation op1 = ContentProviderOperation.newInsert(uri)

            .withValue("account_name", null)

            .build();

    operations.add(op1);

    //依次是姓名,号码,邮编

    ContentProviderOperation op2 = ContentProviderOperation.newInsert(dataUri)

            .withValueBackReference("raw_contact_id", 0)

            .withValue("mimetype", "vnd.android.cursor.item/name")

            .withValue("data2", "Coder-pig")

            .build();

    operations.add(op2);

    ContentProviderOperation op3 = ContentProviderOperation.newInsert(dataUri)

            .withValueBackReference("raw_contact_id", 0)

            .withValue("mimetype", "vnd.android.cursor.item/phone_v2")

            .withValue("data1", "13798988888")

            .withValue("data2", "2")

            .build();

    operations.add(op3);

    ContentProviderOperation op4 = ContentProviderOperation.newInsert(dataUri)

            .withValueBackReference("raw_contact_id", 0)

            .withValue("mimetype", "vnd.android.cursor.item/email_v2")

            .withValue("data1", "[email protected]")

            .withValue("data2", "2")

            .build();

    operations.add(op4);

    //将上述内容添加到手机联系人中~

    resolver.applyBatch("com.android.contacts", operations);

    Toast.makeText(getApplicationContext(), "添加成功", Toast.LENGTH_SHORT).show();

}

//添加权限

<uses-permission android:name="android.permission.WRITE_CONTACTS"/>

<uses-permission android:name="android.permission.WRITE_PROFILE"/>

4.自定义ContentProvider流程

Android四大组件之一的ContentProvider

public class DBOpenHelper extends SQLiteOpenHelper {

 

    final String CREATE_SQL = "CREATE TABLE test(_id INTEGER PRIMARY KEY AUTOINCREMENT,name)";

   

    public DBOpenHelper(Context context, String name, CursorFactory factory,

            int version) {

        super(context, name, null, 1);

    }

 

   

    @Override

    public void onCreate(SQLiteDatabase db) {

        db.execSQL(CREATE_SQL);

    }

 

    @Override

    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

        // TODO Auto-generated method stub

 

    }

 

}

 

Step 1:自定义ContentProvider类,实现onCreate(),getType(),根据需求重写对应的增删改查方法:

NameContentProvider.java

public class NameContentProvider extends ContentProvider {

 

    //初始化一些常量

     private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);       

     private DBOpenHelper dbOpenHelper;

   

    //为了方便直接使用UriMatcher,这里addURI,下面再调用Matcher进行匹配

    

     static{ 

         matcher.addURI("com.jay.example.providers.myprovider", "test", 1);

     } 

    

    @Override

    public boolean onCreate() {

        dbOpenHelper = new DBOpenHelper(this.getContext(), "test.db", null, 1);

        return true;

    }

 

    @Override

    public Cursor query(Uri uri, String[] projection, String selection,

            String[] selectionArgs, String sortOrder) {

        return null;

    }

 

    @Override

    public String getType(Uri uri) {

        return null;

    }

 

    @Override

    public Uri insert(Uri uri, ContentValues values) {

       

        switch(matcher.match(uri))

        {

        //把数据库打开放到里面是想证明uri匹配完成

        case 1:

            SQLiteDatabase db = dbOpenHelper.getReadableDatabase();

            long rowId = db.insert("test", null, values);

            if(rowId > 0)

            {

                //在前面已有的Uri后面追加ID

                Uri nameUri = ContentUris.withAppendedId(uri, rowId);

                //通知数据已经发生改变

                getContext().getContentResolver().notifyChange(nameUri, null);

                return nameUri;

            }

        }

        return null;

    }

 

    @Override

    public int delete(Uri uri, String selection, String[] selectionArgs) {

        return 0;

    }

 

    @Override

    public int update(Uri uri, ContentValues values, String selection,

            String[] selectionArgs) {

        return 0;

    }

 

}

 

Step 2:AndroidManifest.xml中为ContentProvider进行注册:

 

<!--属性依次为:全限定类名,用于匹配的URI,是否共享数据 -->

<provider android:name="com.jay.example.bean.NameContentProvider"

            android:authorities="com.jay.example.providers.myprovider"

            android:exported="true" />

 

public class MainActivity extends Activity {

 

    private Button btninsert;

   

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

       

        btninsert = (Button) findViewById(R.id.btninsert);

       

        //读取contentprovider 数据 

        final ContentResolver resolver = this.getContentResolver();

       

       

        btninsert.setOnClickListener(new OnClickListener() {

           

            @Override

            public void onClick(View v) {

                 ContentValues values = new ContentValues();

                 values.put("name", "测试");

                 Uri uri = Uri.parse("content://com.jay.example.providers.myprovider/test");

                resolver.insert(uri, values);

                Toast.makeText(getApplicationContext(), "数据插入成功", Toast.LENGTH_SHORT).show();

               

            }

        });

}

    }

通过ContentObserver监听ContentProvider 数据的变化

Android四大组件之一的ContentProvider

5.ContentProvider 、ContentResolver与ContentObserver之间的关系?

ContentProvider :管理数据,提供数据的增删改查操作,数据源可以是数据库、文件、xml、网络等,Content Provider为这些数据提供了统一的接口,可以用来做进程间数据共享(内容提供者,用于对外提供数据)

ContentResolver :ContentResolver可以不同URI操作不同的ContentProvider中的数据,外部进程可以通过ContentResolver与Content Provider进行交互(notifyChange(Uri)发出消息)(内容解析者,用于获取内容提供者提供数据)(ContentResolver.registerContentObserver()监听消息)

ContentObserver:观察ContentProvider中的数据变化,并将变化通知给外界(内容监听器,可以监听数据的改变状态)