在B程序中访问A程序的ConentProvider

设计两个程序,一个A程序,一个B程序,在A程序中创建ContentProvider暴露我们想要暴露的数据,然后再在程序中创建ContentResolver对A程序暴露的数据进行访问;

在创建的过程尤其值得注意的是:如果想要在B程序中访问A程序暴露的数据,必须在A程序的注册文件中的相应ContentProvider加上android:exported="true"属性;

如果你忘记加上这个属性,那么在B程序中试图访问A的暴露数据,那么就会出现以下错误:



  这样写的A,B程序有个问题是,如果A程序没有运行过,或者说被强行关闭后,B程序就不能获取到A程序的数据,容易造成空指针,如果想处理这个问题

可以把ContentProvider代码写在后台运行(不能接触强行关闭的)


先创建A程序,A程序结构如下:



先给出布局文件代码:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    
<TextView 
    android:text="我是内容提供 "
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"/>
</LinearLayout>

然后是创建SQLiteOpenHelperd 的myDBSQLite类;主要负责上下文传递和相应创建数据库.代码如下:


package com.example.dao;

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

public class myDBSQLite extends SQLiteOpenHelper {//第一个程序的SQLiteOpenHelper
//构造函数,提供上下文
	public myDBSQLite(Context context)
			 {
		super(context, "persons.db", null, 3);//创建persons数据库
		// TODO 自动生成的构造函数存根
	}
//创建表格
	@Override
	public void onCreate(SQLiteDatabase arg0) {
		// TODO 自动生成的方法存根
		arg0.execSQL("create table persons(id Integer primary key autoincrement,name nvchar(20),nameText nvchar(20))");
		
	}
//版本更新时候调用
	@Override
	public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
		// TODO 自动生成的方法存根
		
	}

}
   再给出ContentProvider  来暴露A程序的数据。代码如下:

package com.example.myoperationcontentprovider;

import com.example.dao.myDBSQLite;

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;

public class myContentProvider extends ContentProvider {
	private static UriMatcher matcher =new UriMatcher(UriMatcher.NO_MATCH);//获取uri匹配器
	private static final int INSERT=1;//添加数据成功匹配Uri路径成功时候返回值
	private static final int UPDATE=2;//更新数据成功后匹配uri路径成功时候的返回值
	private static final int DELETE=3;//删除数据成功后匹配uri成功时候返回值
	private static final int QUERY=4;//查询到数据匹配uri成功时候的返回值
	private static final int QUERYONE=5;//查询到一行数据匹配uri成功时候的返回值
	
	private myDBSQLite helper;
	
	static {
		matcher.addURI("cn.itcast.myContent", "insert", INSERT); //增加数据插入匹配规程
		matcher.addURI("cn.itcast.myContent", "update", UPDATE);//更新数据
		matcher.addURI("cn.itcast.myContent", "delete", DELETE);//删除数据
		matcher.addURI("cn.itcast.myContent", "query/#", QUERYONE);//查询特定数据
		matcher.addURI("cn.itcast.myContent", "query", QUERY);//查询一系列数据
	}

	@Override
	public int delete(Uri arg0, String arg1, String[] arg2) {//删除数据
		if(matcher.match(arg0)==DELETE){//匹配删除成功
			SQLiteDatabase db=helper.getWritableDatabase();
			db.delete("persons", arg1, arg2);
		}else{
			throw new IllegalArgumentException("路径匹配失败,不能执行删除操作 ");//异常必须是IllegalArgumentException,若是Exception则需要在try中书写
			
		}
		// TODO 自动生成的方法存根
		return 0;
	}

	@Override
	public String getType(Uri arg0) {
		if(matcher.match(arg0)==QUERY){
			return "vnd.android.cursor.dir/persons";//表示返回一个集合
			
		}
		else if(matcher.match(arg0)==QUERYONE){
		// TODO 自动生成的方法存根
		return "vnd.android.cursor.item/persons";//返回一个数据
		}
		return null;
	}
	
	@Override
	public Uri insert(Uri arg0, ContentValues arg1) {
		if(matcher.match(arg0)==INSERT){
			SQLiteDatabase db=helper.getWritableDatabase();
			db.insert("persons", null, arg1);
		}
		else{
			throw new IllegalArgumentException("路径匹配失败,不鞥执行插入操作");
		}
		// TODO 自动生成的方法存根
		return null;
	}

	@Override
	public boolean onCreate() {
		helper=new myDBSQLite(getContext());
		// TODO 自动生成的方法存根
		return false;
	}

	@Override
	public Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3,
			String arg4) {
		if(matcher.match(arg0)==QUERYONE){//如果匹配查询一个数据
			SQLiteDatabase db=helper.getReadableDatabase();
			long id=ContentUris.parseId(arg0);//获取当前uri、中数据的id
			 Cursor cursor=db.query("persons", arg1, "id=?", new String []{""+id}, null, null, arg4);
			return cursor;//返回一个游标数据,如果没有该返回,在contentresolverz中将查询不到数据
			
		}
		else if(matcher.match(arg0)==QUERY){//如果匹配到一个查询集合数据
			SQLiteDatabase db=helper.getReadableDatabase();
			Cursor cursor=db.query("persons", arg1, arg2, arg3, null, null, arg4);
			return cursor;//返回一个游标数据,如果没有该返回,在contentresolverz中将查询不到数据
		}
		else {
			throw new IllegalArgumentException("路径不匹配,不能执行查询");
		}
		// TODO 自动生成的方法存根
		
	}

	@Override
	public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) {
		if(matcher.match(arg0)==UPDATE){
			SQLiteDatabase db=helper.getWritableDatabase();
			db.update("persons", arg1, arg2, arg3);
		}else{
			throw new IllegalArgumentException("路径匹配失败,不能更新操作");
		}
		// TODO 自动生成的方法存根
		return 0;
	}

}

然后是操作对象的实体类,代码如下:

package com.example.javabean;

public class Person {
	//保存相关数据操作的类
	private long id;
	private String name;
	private String nameText;
	public Person(int id,String name,String nameText){
		this.id=id;
		this.name=name;
		this.nameText=nameText;
	}
	public Person(String name,String nameText){
		
		this.name=name;
		this.nameText=nameText;
	}
	public Person(){
		
	}

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getNameText() {
		return nameText;
	}

	public void setNameText(String nameText) {
		this.nameText = nameText;
	}
}

然后是实体代码的实现类,主要是对实体操作的数据库具体实现:代码如下:

package com.example.dao;

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

import com.example.javabean.Person;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.widget.ListView;

public class PersonDao {
	private myDBSQLite helper;
	public PersonDao(Context context){
		helper=new myDBSQLite(context);
		//实例化SQLiteOpenHelper的对象
	}
	//书写插入方法
	public long insert(Person person){
		SQLiteDatabase db=helper.getWritableDatabase();//获得一个可以写入数据库对象,不需要权限说明
		ContentValues contentValues=new ContentValues();
		contentValues.put("name", person.getName());
		contentValues.put("nameText", person.getNameText());
		long ids=db.insert("persons", null, contentValues);
		db.close();
		return ids;//返回受到影响的行数
	}
	public List<Person> query(){//查询一系列数据
		List<Person> list=new ArrayList<Person>();
		SQLiteDatabase db=helper.getReadableDatabase();//得到一个可以只读的数据库对象
		String sql="";
		Cursor cursor=db.query("persons", null, null, null, null, null, null);
		//查询persons表格中所有数据 
		while(cursor.moveToNext()){
			//得到数据库中想要的值
			int id=cursor.getInt(cursor.getColumnIndex("id"));//得到游标中的取得数据库标识为id的数据
			String name=cursor.getString(cursor.getColumnIndex("name"));
			String nameText=cursor.getString(cursor.getColumnIndex("nameText"));
			//判断数据是不是空,如果是空表示没有查到数据
			if((id+"")!=""&&(name!="")&&(nameText!="")){
				list.add(new Person(id, name, nameText));
				
			}
			
		}
		cursor.close();//关闭游标,关闭数据库,否则容易造成内存浪费,可能造成内存不足
		db.close();
		return list;//返回查询到的数据,用集合
	}

}

最后在主界面中对数据库插入数据:代码如下:


package com.example.myoperationcontentprovider;

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

import com.example.dao.PersonDao;
import com.example.javabean.Person;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.Toast;

public class MainActivity extends Activity {
	private List<Person> list;
	private PersonDao personDao;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        list=new ArrayList<Person>();
        personDao=new PersonDao(this);
        //插入数据(如果数据库里面没有数据就查询的话容易造成空指针异常)
        for(int i=0;i<3;i++){
        	personDao.insert(new Person("我"+i,"没事没事"+i));
        }
        //判断数据是否为空
        list=personDao.query();
        for(int i=0;i<list.size();i++){
        	if(list.get(i).equals("")){
        		Toast.makeText(this, "数据插入失败", Toast.LENGTH_SHORT).show();
        	}
        	else{
        		Toast.makeText(this, "数据插入"+list.get(i).getId()+"成功", Toast.LENGTH_SHORT).show();
        	}
        }
        
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    
}

  A程序主要0的注册文件如下:

 <provider
            android:exported="true"
           android:name="com.example.myoperationcontentprovider.myContentProvider"
            android:authorities="cn.itcast.myContent"/>


A程序结束,运行结果如下:






B程序开始:B的代码结构如下:


B的主界面布局为:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <ListView
        android:id="@+id/listview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        
        
        />

</LinearLayout>


ListView具体布局如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >
"

    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="这是name" />

    <TextView
        android:layout_marginLeft="30dp"
        android:id="@+id/nameText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="这是nameText" />

</LinearLayout>

实体类和上面所讲一样就不再赘述:

主界面实现代码如下:完成适配器数据配对和获取A程序的暴露数据


package com.example.myopearationcontentresolver;

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

import com.example.javabean.Person;

import android.R.integer;
import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;


public class MainActivity extends Activity {

	private myAdapter adapter;
	List<Person> list;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ListView listView=(ListView)findViewById(R.id.listview);
        getPersonInfos();
        adapter=new myAdapter();
        //测试查询数据是否成功
        for(int i=0;i<list.size();i++){
        	Toast.makeText(this, list.get(i).getName(), Toast.LENGTH_SHORT).show();
        }
        //绑定适配器
        listView.setAdapter(adapter);
        
    }

    private void getPersonInfos(){
    	list=new ArrayList<Person>();
    	ContentResolver resolver=getContentResolver();
    	//注意,如果想要在B程序中访问A程序的contentProvider就需要在A程序的Contentprovider注册加入
    	//android:exported="true"属性,否则会报安全错误
    	//content不能丢
    	String path="content://cn.itcast.myContent/query";
    	Uri uri=Uri.parse(path);
    	Cursor cursor=resolver.query(uri, null, null, null, null);
    	if(cursor==null){
    		Toast.makeText(this, "contentR失败", 1).show();
    	}
    	else{//cursor数据 不为空
    	while(cursor.moveToNext()){
    		int id=cursor.getInt(cursor.getColumnIndex("id"));
    		String name=cursor.getString(cursor.getColumnIndex("name"));
    		String nameText=cursor.getString(cursor.getColumnIndex("nameText"));
    		list.add(new Person(id,name,nameText));
    	}
    	}
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
  private class myAdapter extends BaseAdapter {
//简单baseAdapter运用
	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return list.size();
	}

	@Override
	public Object getItem(int position) {
		// TODO Auto-generated method stub
		return list.get(position);
	}

	@Override
	public long getItemId(int position) {
		// TODO Auto-generated method stub
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		// TODO Auto-generated method stub
		View view=View.inflate(MainActivity.this, R.layout.listview, null);
		Person person=list.get(position);
		TextView nameTextView=(TextView)view.findViewById(R.id.name);
		TextView nameTextTextView=(TextView)view.findViewById(R.id.nameText);
		nameTextView.setText("姓名为:"+person.getName());
		nameTextTextView.setText("信息为:"+person.getNameText());
		return view;
	}
	  
  }
}


多次运行后结果如下:



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值