您的位置:首页 > 移动开发 > Android开发

Android学习笔记七之ContentProvider

2016-06-20 14:28 543 查看

Android学习笔记起之ContentProvider

ContentProvicer简介

Content provider,即是内容提供者或者内容提供商。ContentProvider生命周期

应用安装完成,就会创建完成,手机开机后,第一次被访问时,被创建

只要创建了,只要手机没关机,就会一直存在,类似于在注册表里注册一样

手机关机,才会消失

应用里的数据都可以提供访问.不一定是数据库,在方法里自已定义就可以,但通常是访问数据库

作用

  ContentProvider用于不同进程之间传递数据,这也是官方推荐的方式。

当我们想要在自己的应用中访问别的应用的数据,比如获取手机联系人,手机短信等的时候,就需要用到ContentProvider了

当我们自己的应用,需要把自己的一些数据给其它应用进行操作,我们就可以用到contentprovider了。

简单的说,就是Contentprovider为不同应用之间数据共享提供统一的接口。ContentProvider使用表的形式组织数据,所以提供的方法跟表的操作类似,ContentProvider提供如下的方法:

query:查询数据

insert:插入数据

update:更新数据

delete:删除数据

getType:得到数据类型

onCreate:创建数据时调用的回调函数

使用ContentProvider需要一个uri,例如获取手机联系人的uri:

content://com.android.contacts/data/phones

URI解析如下图所示



使用系统提供的ContentProvider

很多时候我们都是使用系统提供的ContentProvider,使用ContentResolver来读取其他应用的信息,例如读取系统APP,短信,联系人, 手机相册等!例如,我们读取手机联系人

读取手机联系人

package com.example.contentprovider;

import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

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

private void getContacts() {
ContentResolver contentResolver = this.getContentResolver();
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
System.out.println("------>>" + uri);
Cursor cursor = contentResolver.query(uri, null, null, null, null);
while (cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
System.out.println("-----------------------------------");
System.out.println("联系人:" + name);
System.out.println("电话号码:" + number);

}

cursor.close();
}
}


获取手机联系人需要用到系统权限,所以需要在AndroidManifest.xml文件中注册:

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


运行效果截图



这样就可以实现简单的读取手机联系人的效果,下面介绍自定义ContentProvider.

自定义ContentProvider

 自定义ContentProvider的步骤如下:

在想要进行数据分享的APP中,创建一个继承ContentProvider的类

实现对应的方法,按照需要进行重写,方法有onCreate()只执行一次,初始化ContentProvider,insert(),delete(),update(),query(),getType()获取ContentProvider数据的MIME类型

在AndroidManifest.xml文件中注册自定义的ContentProvider,至少需要三个属性,name,用于指定ContentProvider的全限定类名;authorities,用于匹配ContentProvider的uri;exported,用于指定是否共享数据,true,共享,false,不共享。

使用UriMatcher,完成uri的匹配

在另外的应用中调用getContentProvider()方法获取到Resolver对象,再进行对应的操作

下面进行代码实现:

创建一个继承ContentProvider的类

package com.example.contentprovider;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.support.annotation.Nullable;

/**
* Created by Devin on 2016/6/17.
*/
public class MYContentProvicer extends ContentProvider {

private static UriMatcher mUriMatcher;
private static final String AUTHORITIES = "com.example.contentprovider";
private static final int PERSON = 1;

private SQLiteDatabaseOpenHelper mOpenHelper;

/**
* 利用静态代码块初始化UriMatcher
* 在UriMatcher中包含了多个Uri,每个Uri代表一种操作
* 当调用UriMatcher.match(Uri uri)方法时就会返回该uri对应的code;
*/
static {
mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
mUriMatcher.addURI(AUTHORITIES, "test", PERSON);
}

/**
* 初始化方法,只执行一次,完成对ContentProvider的初始化
*
* @return
*/
@Override
public boolean onCreate() {
mOpenHelper = new SQLiteDatabaseOpenHelper(this.getContext());
return true;
}

/**
* 查询方法
*
* @param uri
* @param strings
* @param s
* @param strings1
* @param s1
* @return
*/
@Nullable
@Override
public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {
return null;
}

/**
* 获取ContentProvider的MIME类型
*
* @param uri
* @return
*/
@Nullable
@Override
public String getType(Uri uri) {
return null;
}

/**
* 插入数据方法
*
* @param uri
* @param contentValues
* @return
*/
@Nullable
@Override
public Uri insert(Uri uri, ContentValues contentValues) {

switch (mUriMatcher.match(uri)) {
case PERSON:
SQLiteDatabase mDataBase = mOpenHelper.getReadableDatabase();
long rowId = mDataBase.insert("test", null, contentValues);
if (rowId >= 1) {
//通知数据已经发生改变
getContext().getContentResolver().notifyChange(uri, null);
return ContentUris.withAppendedId(uri, rowId);
}
break;
}
return null;
}

/**
* 删除数据的方法
*
* @param uri
* @param s
* @param strings
* @return
*/
@Override
public int delete(Uri uri, String s, String[] strings) {
return 0;
}

/**
* 更新数据的方法
*
* @param uri
* @param contentValues
* @param s
* @param strings
* @return
*/
@Override
public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
return 0;
}
}


SQliteDatabaseHelper

package com.example.contentprovider;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
* Created by Devin on 2016/6/17.
*/
public class SQLiteDatabaseOpenHelper extends SQLiteOpenHelper {
private static final String DATABASENAME = "test1";//数据库名称
private static final int DATABASEVERSION = 1;//数据库版本
private String sql = "CREATE TABLE test(id INTEGER PRIMARY KEY AUTOINCREMENT,name varchar(20),phone varchar(50),salary Integer(12))";

public SQLiteDatabaseOpenHelper(Context context) {
super(context, DATABASENAME, null, DATABASEVERSION);
}

@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL(sql);
}

/**
* 数据库版本版本发生变化时的方法
*
* @param sqLiteDatabase
* @param i
* @param i1
*/
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

}
}


在AndroidManifest.xml文件中注册

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.contentprovider">

<uses-permission android:name="android.permission.READ_CONTACTS"/><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=".MYContentProvicer"
android:authorities="com.example.contentprovider"
android:exported="true"></provider>

</application>

</manifest>


新建一个project,在应用中调用getContentResolver()方法获取ContentResolver,然后实现对ContentProvider的操作

package com.example.client;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

Button btn_insert;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_insert = (Button) findViewById(R.id.btn_insert);
final ContentResolver resolver = this.getContentResolver();
btn_insert.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ContentValues values = new ContentValues();
values.put("name", "张三");
values.put("phone", "15677822442");
values.put("salary", 8000);
Uri uri = Uri.parse("content://com.example.contentprovider/test");
resolver.insert(uri, values);
Toast.makeText(getApplicationContext(), "恭喜你,数据插入成功", Toast.LENGTH_SHORT).show();
}
});
}
}


最后实现效果如下:



插入数据之后,在File Explorer中将数据表导出,用SQLite Expert Personal 4打开



这样就可以实现一个简单的自定义ContentProvider,将自己应用的数据共享出去,不过这种做法比较少见,因为自己的应用数据很少有向其他应用共享的。

通过注册一个观察者,观察ContentProvider的数据变化

/**
* 自定义一个类,继承ContentObserver,重写onChange方法,观察ContentProvider数据发生变化
*/
private class MYContentObserver extends ContentObserver {

public MYContentObserver(Handler handler) {
super(handler);
}

@Override
public void onChange(boolean selfChange) {
System.out.println("MYContentObserver正在观察ContentProvider数据变化");
long lastTime = 0;
if (System.currentTimeMillis() - lastTime > 2000) {
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://com.example.contentprovider/test");
lastTime = System.currentTimeMillis();
} else {
System.out.println("时间间隔过短,忽略此次更新");
}
}

@Override
public boolean deliverSelfNotifications() {
return true;
}
}


在onCreate方法中注册观察者

Uri uri = Uri.parse("content://com.example.contentprovider/test");
mContentObserver = new MYContentObserver(new Handler());
getApplicationContext().getContentResolver().registerContentObserver(uri, true, mContentObserver);


在onDestroy方法中取消注册观察者

@Override
protected void onDestroy() {
super.onDestroy();
if (mContentObserver != null) {
getApplicationContext().getContentResolver().unregisterContentObserver(mContentObserver);
}
}


至此,ContentProvider的简单学习就完成了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: