Android12-内容提供者

1.内容提供者

将私有的数据库暴露给其他应用使用。

2.直接暴露数据库

 public void query(View v){
     //数据库目录
     String path = "/data/data/com.my.androidpro33/databases/my.db";
     //通过openDatabase打开数据库,出入数据库路径,游标工厂,打开数据库的模式
     SQLiteDatabase readableDatabase = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READWRITE);

     Cursor rawQuery = readableDatabase.rawQuery("select name,phone from info", null);
     while(rawQuery.moveToNext()){
         String name = rawQuery.getString(rawQuery.getColumnIndex("name"));
         System.out.println(name);
     }
     rawQuery.close();
 }

3.通过内容提供者访问暴露的数据库

/*
 * 数据库
 */
public class MySQLiteOpenHelper extends SQLiteOpenHelper {

	public MySQLiteOpenHelper(Context context) {
		super(context, "my.db", null, 1);
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL("create table info(_id integer primary key autoincrement,name varchar(20),phone varchar(20))");

		db.execSQL("alter table info add age integer");
		
		db.execSQL("insert into info(name,phone) values('张','13777771');");
		db.execSQL("insert into info(name,phone) values('李','13777772');");
		db.execSQL("insert into info(name,phone) values('王','13777773');");
		db.execSQL("insert into info(name,phone) values('赵','13777774');");
		db.execSQL("insert into info(name,phone) values('田','13777775');");
		db.execSQL("insert into info(name,phone) values('bob','13777776');");
	}

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

	}

}

/*
 * 内容提供者,可以让外界访问
 */
public class MyContentProvider extends ContentProvider {

	private static final int QUERY_SUCCESS = 0;
	private MySQLiteOpenHelper sqLiteOpenHelper;
	//创建UriMatcher,在UriMatcher中添加其中应用访问需要遵循匹配规则,当匹配失败返回NO_MATCH
	private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);

	static {
		//往UriMatcher中添加匹配规则,进行内容提供者的匹配
		//第一个参数是内容提供者的authorities,用来匹配内容提供者
		//第二个是要访问的路径或者方法,加入query证明这个内容提供者,可以访问query方法
		//第三个是匹配成功后返回的状态
		URI_MATCHER.addURI("com.my.provider", "query", QUERY_SUCCESS );
	}
	
	/*
	 * (non-Javadoc)
	 * @see android.content.ContentProvider#onCreate()
	 * 当内容提供者被创建了就会调用这个方法
	 * 在这个方法中可以创建MySQLiteOpenHelper对象
	 * 但是不建议调用getReadableDatabase来获取数据库对象
	 * 在insert、query、update、delete中可以调用getReadableDatabase来进行操作
	 */
	@Override
	public boolean onCreate() {
		sqLiteOpenHelper = new MySQLiteOpenHelper(getContext());
		return false;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		//通过match进行匹配,用来判断是否可以访问这个方法
		int result = URI_MATCHER.match(uri);
		if(result == QUERY_SUCCESS){
			SQLiteDatabase database = sqLiteOpenHelper.getReadableDatabase();
			//第一个参数表名,第二个参数要查询的列名,传入null,查询所有的列
			//第三个参数,查询的参数,where后面的参数,第四个参数,查询的参数的值
			//第五个参数分组语句,第六个参数having语句,第七个参数排序语句
			Cursor cursor = database.query("info", null, selection, selectionArgs, null, null, sortOrder);
			System.out.println(cursor == null);
			return cursor;
		}else {
			throw new IllegalArgumentException("内容提供者匹配失败");
		}
		
	}

	@Override
	public String getType(Uri uri) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		SQLiteDatabase database = sqLiteOpenHelper.getReadableDatabase();
		//返回最新插入行的id
		long id = database.insert("my.db", null, values);
		return Uri.parse(String.valueOf(id));
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		SQLiteDatabase database = sqLiteOpenHelper.getReadableDatabase();
		int number = database.delete("my.db", selection, selectionArgs);
		return number;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		SQLiteDatabase database = sqLiteOpenHelper.getReadableDatabase();
		int number = database.update("my.db", values, selection, selectionArgs);
		return number;
	}

}

/*
 * 通过内容提供访问数据库
 */
public void query1(View v){
    //创建要匹配的内容提供者的uri
    Uri uri = Uri.parse("content://com.my.provider/query");
    ContentResolver contentResolver = getContentResolver();
    Cursor rawQuery = contentResolver.query(uri, null, null, null, null);
    while(rawQuery.moveToNext()){
        String name = rawQuery.getString(rawQuery.getColumnIndex("name"));
        System.out.println(name);
    }
    rawQuery.close();
}
<!-- 在清单文件中注册内容提供者,必须声明authorities,给定权限
        exported表示是否暴露给其他应用 -->
<provider android:name="com.my.androidpro35.MyContentProvider" 
          android:authorities="com.my.provider" android:exported="true"></provider>

4.内容提供者访问短信数据库

public class MainActivity extends Activity {
	
	private List<Sms> list = new ArrayList<Sms>();

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


     /*
     * 查询短信,短信的数据库com.android.providers.telephoney,短信数据在databases目录下
     * mmssms.db,其中sms和短信的收发有关
     */
    public void query(View v){
    	ContentResolver resolver = getContentResolver();
    	//匹配短信的内容提供者,传入null,匹配所有的操作
    	Uri uri = Uri.parse("content://sms");
    	String[] projection = {"address","date","body"};
    	Cursor cursor = resolver.query(uri, projection, null, null, null);
    	while(cursor.moveToNext()){
    		
    		
    		String address = cursor.getString(0);
    		String date = cursor.getString(1);
    		String body = cursor.getString(2);
    		
    		Sms sms = new Sms();
    		sms.address = address;
    		sms.date = date;
    		sms.body = body;
    		list.add(sms);
    	}
    }
    
    /*
     * 备份短信
     */
    public void backups(View v){
    	XmlSerializer xml = Xml.newSerializer();
    	try {
			xml.setOutput(openFileOutput("sms.xml", MODE_PRIVATE), "utf-8");
			
			xml.startDocument("utf-8", null);
			
			xml.startTag(null, "smsList");
			
			for(Sms sms : list){
				xml.startTag(null, "sms");
				
				xml.startTag(null, "address");
				xml.text(sms.address);
				xml.endTag(null, "address");
				
				xml.startTag(null, "date");
				xml.text(sms.date);
				xml.endTag(null, "date");
				
				xml.startTag(null, "body");
				xml.text(sms.body);
				xml.endTag(null, "body");
				
				xml.endTag(null, "sms");
			}
			
			xml.endTag(null, "smsList");
			xml.endDocument();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
    }
    
     /*
     * 插入短信
     */
    public void insert(View v){
    	ContentResolver resolver = getContentResolver();
    	Uri url = Uri.parse("content://sms");
    	ContentValues values = new ContentValues();
    	values.put("address", "95555");
    	values.put("date", System.currentTimeMillis());
    	values.put("body", "恭喜-----------");
    	resolver.insert(url, values);
    }
}
<!-- 读写短信需要的权限 -->
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />

5.内容提供者访问联系人数据库

public class MainActivity extends Activity {
	
	private List<Contact> list = new ArrayList<Contact>();

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


    /*
     * 查询联系人
     * 联系人要操作的数据库 com.android.providers.contacts/databases/contact2.db
     * 与联系人操作相关的表
     * data 存储数据
     * row_contacts 保存联系人,多少个联系人,保存多少数据
     * mimetypes 保存data数据的类型 如姓名(7)、地址(8)、邮箱(1)、电话号码(5)用不同的数字表示
     * 索引要进行查询,先操作raw_contacts表,查询contact_id,就可以知道有多少联系人
     * contact_id和data中的raw_contact_id对应,就可以查出一个联系人的具体数据
     * 通过mimetype_id,查出这个是什么数据,mimetype_id和mimetypes的_id对应
     * 
     * 联系人操作所在目录providers\ContactsProvider\src\com\android\providers\contacts\ContactsProvider2.java
     */
    public void query(View v){
    	ContentResolver resolver = getContentResolver();
    	
    	//raw_contacts表匹配的uri
    	Uri raw_contacts_uri = Uri.parse("content://com.android.contacts/raw_contacts");
    	//data表匹配的uri
    	Uri data_uri = Uri.parse("content://com.android.contacts/data");
    	
    	//先查询raw_contacts表的contact_id数据
    	Cursor cursor1 = resolver.query(raw_contacts_uri, new String[]{"contact_id"}, null, null, null);
    	Contact contact = null;
    	while(cursor1.moveToNext()){
    		String contact_id = cursor1.getString(0);
    		//通过contact_id和data中的raw_contact_id对应,就可以查出一个联系人数据
    		//data1具体的值,如姓名或者邮箱具体的值;mimetype值的类型,如是姓名还是邮箱
    		//12-09 13:25:48.735: I/System.out(12050): vnd.android.cursor.item/phone_v2
    		//vnd.android.cursor.item/phone_v2 表示电话
    		//vnd.android.cursor.item/email_v2-邮箱
    		//vnd.android.cursor.item/name-姓名
    		//vnd.android.cursor.item/postal-address_v2-地址
    		//联系人的数据库使用视图技术(视图使得在打开表示存在mimetype_id列,看起来直观)
    		//data中并没有mimetype_id列,而是mimetype列,直接保存数据的类型
    		String[] projection = {"data1","mimetype"};
			String selection = "raw_contact_id = ?";
			String[] selectionArgs = {contact_id};
			Cursor cursor2 = resolver.query(data_uri, projection , selection, selectionArgs, null);
			
			contact = new Contact();
			while(cursor2.moveToNext()){
				String data1 = cursor2.getString(0);
				String mimetype = cursor2.getString(1);
				
				if("vnd.android.cursor.item/phone_v2".equals(mimetype)){
					contact.phone = data1;
				}else if("vnd.android.cursor.item/email_v2".equals(mimetype)){
					contact.email = data1;
				}else if("vnd.android.cursor.item/name".equals(mimetype)){
					contact.name = data1;
				}else if("vnd.android.cursor.item/postal-address_v2".equals(mimetype)){
					contact.address = data1;
				}
			}
			
			list.add(contact);
    	}
    	
    	for(Contact con : list){
    		System.out.println(con);
    	}
    }
}
<!-- 读写联系人的权限 -->
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />

6.保存联系人数据

public class MainActivity extends Activity {

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

	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        et_name = (EditText) findViewById(R.id.et_name);
        et_address = (EditText) findViewById(R.id.et_address);
        et_phone = (EditText) findViewById(R.id.et_phone);
        et_email = (EditText) findViewById(R.id.et_email);
    }

	/*
	 * 保存联系人数据
	 */
    public void save(View v){
    	System.out.println("1");
    	//获取内容提供者的解析器
    	ContentResolver resolver = getContentResolver();
    	//添加要操作的内容提供者和数据库表匹配的Uri
    	//raw_contacts表匹配的uri
    	Uri raw_contacts_uri = Uri.parse("content://com.android.contacts/raw_contacts");
    	//data表匹配的uri
    	Uri data_uri = Uri.parse("content://com.android.contacts/data");
    	//先查询raw_contacts总共的数据
    	String[] projection = {"contact_id"};
		Cursor cursor1 = resolver.query(raw_contacts_uri, projection , null, null, null);
		int count = cursor1.getCount() + 1;
		System.out.println(count + "count");
		
		//向raw_contacts插入数据
		ContentValues values = new ContentValues();
		values.put("contact_id", count);
		resolver.insert(raw_contacts_uri, values);
		
		//向data表插入数据
		//vnd.android.cursor.item/phone_v2 表示电话
		//vnd.android.cursor.item/email_v2-邮箱
		//vnd.android.cursor.item/name-姓名
		//vnd.android.cursor.item/postal-address_v2-地址
		String name = et_name.getText().toString().trim();
		ContentValues nameValues = new ContentValues();
		nameValues.put("data1", name);
		nameValues.put("mimetype", "vnd.android.cursor.item/name");
		nameValues.put("raw_contact_id", count);
		resolver.insert(data_uri, nameValues);
		
		String address = et_address.getText().toString().trim();
		ContentValues addressValues = new ContentValues();
		addressValues.put("data1", address);
		addressValues.put("mimetype", "vnd.android.cursor.item/postal-address_v2");
		addressValues.put("raw_contact_id", count);
		resolver.insert(data_uri, addressValues);
		
		String phone = et_phone.getText().toString().trim();
		ContentValues phoneValues = new ContentValues();
		phoneValues.put("data1", phone);
		phoneValues.put("mimetype", "vnd.android.cursor.item/phone_v2");
		phoneValues.put("raw_contact_id", count);
		resolver.insert(data_uri, phoneValues);
		
		String email = et_email.getText().toString().trim();
		ContentValues emailValues = new ContentValues();
		emailValues.put("data1", email);
		emailValues.put("mimetype", "vnd.android.cursor.item/email_v2");
		emailValues.put("raw_contact_id", count);
		resolver.insert(data_uri, emailValues);
		
		Toast.makeText(getApplicationContext(), "OK", Toast.LENGTH_SHORT).show();
    }
}
<!-- 读写联系人的权限 -->
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />

7.内容观察者

/*
* 通过内容提供者访问数据库,修改数据
*/
public void insert(View v){
    ContentResolver resolver = getContentResolver();
    Uri uri = Uri.parse("content://com.my.provider/insert");
    ContentValues values = new ContentValues();
    values.put("name", "wang");
    values.put("phone", "10101010");
    resolver.insert(uri, values);
}

/*
* (non-Javadoc)
* @see android.content.ContentProvider#insert(android.net.Uri, android.content.ContentValues)
* 内容提供者修改数据库,并且向注册了这个uri的内容观察者发送通知
*/
@Override
public Uri insert(Uri uri, ContentValues values) {
    int result = URI_MATCHER.match(uri);
    if(result == INSERT_SUCCESS){
        SQLiteDatabase database = sqLiteOpenHelper.getReadableDatabase();
        //返回最新插入行的id
        //通过内容解析者获取内容观察者
        //第一个参数uri,通过uri来判断调用那个内容观察者
        //第二个参数传入具体的内容观察者,如果是null,则注册了这个uri的所有内容观察者都可以收到
        getContext().getContentResolver().notifyChange(uri, null);
        long id = database.insert("info", null, values);
        return Uri.parse(String.valueOf(id));
    }else {
        throw new IllegalArgumentException("匹配失败");
    }

}

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        Uri uri = Uri.parse("content://com.my.provider/insert");
        //如果是true,则进行前面的部分匹配,如果是false则会通过uri进行完全匹配
        boolean notifyForDescendents = true;
        MyContentObserver observer = new MyContentObserver(new Handler());
        //注册内容观察者
		getContentResolver().registerContentObserver(uri, notifyForDescendents , observer);
    }
    
    private class MyContentObserver extends ContentObserver {

		public MyContentObserver(Handler handler) {
			super(handler);
		}
		
		/*
		 * (non-Javadoc)
		 * @see android.database.ContentObserver#onChange(boolean, android.net.Uri)
		 * 当内容观察者收到数据库改变的通知是,会调用这个方法
		 */
		@Override
		public void onChange(boolean selfChange, Uri uri) {
			System.out.println(uri);
		}
    	
    }
}

8.内容提供者、内容解析者、内容观察者

1:ContentProvider,内容提供者,可以将自己的数据库暴露出来,使得别来访问。
2:ContentResolver,内容解析者,可以访问别人的数据库。
3:ContentObserver,内容观察者,当数据库数据被修改时,可以回调方法,收到通知。

9.四大组件

1:Activity。声明周期,onCreate当Activity创建了就会被调用,一般用来进行界面、数据的初始化,可以为获取组件、注册广播接受者、开启服务。onStart执行完成界面可见不可操作。Onresume执行完成之后界面可见,可以操作,可以刷新界面。onPause执行完成界面可见不可操作。onStop执行完成界面不可见、不可操作,可以停止刷新界面的操作。onDestory,销魂当前的Activity,可以关闭数据库、注销广播接受者、关闭bind开启服务。
2:Service,没有界面的Activity。主要使得应用在后台运行,可以将长期运行的操作放在Service中。用于解决Activity退出之后,还有任务要完成,使得Activity不能回收,从而造成Activity泄露。有两种开启的方式,startService和bindService。startService的声明周期方法,onCreate、onStartCommand(执行一次startService进行一次调用)、onDestory。bindService的声明周期方法,onCreate、onBind。aidl是rpc的通信方式。
3:BroadcastReceiver。通过Intent进行通信。主要用来发布一些系统通知或者自定义的通知。
4:ContentProvider。提供自己数据库的数据供他人访问。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值