关于如何使用内容提供器Content Provider的简介

本文深入探讨了Android应用中使用内容提供器的必要性、创建过程及实际应用,包括数据保存系统建立、ContentProvider类扩展、ContentURI理解与使用示例,旨在为开发者提供全面指南。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、什么情况下需要使用内容提供器?

内容提供器用来存放和获取数据并使这些数据可以被所有的应用程序访问。它们是应用程序之间共享数据的唯一方法,不存在所有Android软件包都能访问的公共储存区域。

Android为常见数据类型(音频,视频,图像,个人联系人信息,等等)装载了很多内容提供器,在android.provider包里列举了一些。可以查询这些提供器包含了什么数据(尽管,对某些提供器,必须获取合适的权限来读取数据)。

如果开发者想公开应用程序自己的数据,有两个选择:创建自己的内容提供器(一个ContentProvider子类) 或者 给已有的提供器添加数据(前提是存在一个控制同样类型数据的内容提供器且你拥有写的权限)。


二、如何创建内容提供器?

要创建一个内容提供器,你必须:

1)建立一个保存数据的系统。大多数内容提供器使用Android的文件储存方法或SQLite数据库来存放它们的数据,但是你可以用任何你想要的方式来存放数据。Android提供SQLiteOpenHelper类来帮助你创建一个数据库以及SQLiteDatabase类来管理它。

2)扩展ContentProvider类来提供数据访问接口。

3)在清单manifest文件中为你的应用程序声明这个内容提供器(AndroidManifest.xml)。


三、content URI的重要内容

 

A.     标准前缀表明这个数据被一个内容提供器所控制。它不会被修改。

B.     URI的权限部分;它标识这个内容提供器。对于第三方应用程序,这应该是一个全称类名(小写)以确保唯一性。权限在<provider>元素的权限属性中进行声明:

<provider name=".TransportationProvider"

         authorities="com.example.transportationprovider"

          . . .  >

C.      用来判断请求数据类型的路径。这可以是0或多个段长。如果内容提供器只暴露了一种数据类型(比如,只有火车),这个分段可以没有。如果提供器暴露若干类型,包括子类型,那它可以是多个分段长-例如,提供"land/bus","land/train", "sea/ship", "sea/submarine"4个可能的值。

D.     被请求的特定记录的ID,如果有的话。这是被请求记录的_ID数值。如果这个请求不局限于单个记录,这个分段和尾部的斜线会被忽略:

content://com.example.transportationprovider/trains


四、例子

第一步:创建数据保存系统

/**
 * 数据库操作帮助类 安装版本:SDSQLiteOpenHelper 
 * 模拟测试版本 :SQLiteOpenHelper
 * 
 * @author Jessica
 * @date 2013-5-18
 */
public class DatabaseHelper extends SQLiteOpenHelper {
	private static final int DATABASE_VERSION = 2;
	private static final String DATABASE_NAME = "info.db";

	private static final String TABLE_CREATE = "CREATE TABLE info "
			+ "(_id INTEGER PRIMARY KEY, zc_code1 TEXT,zc_code2 TEXT, zc_nums TEXT);";

	public DatabaseHelper(Context context) {	
		super(context, DATABASE_NAME, null, DATABASE_VERSION);
		Log.v("DatabaseHelper","----create database end---------");
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		Log.v("DatabaseHelper","----create table begin --------");
		db.execSQL(TABLE_CREATE);	
		Log.v("DatabaseHelper","----create table end --------");
		
		Log.v("DatabaseHelper","----init data begin --------");
		db.execSQL("insert into info values(1,'BX','CD','10A');");
		db.execSQL("insert into info values(2,'BX','CD','10B');");
		Log.v("DatabaseHelper","----init data end --------");
		
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		if (newVersion != oldVersion) {
			db.execSQL("DROP TABLE IF EXISTS info");
			onCreate(db);
		}
		Log.v("DatabaseHelper","----update database end --------");
	}
}

第二步:扩展ContentProvider类,提供数据访问接口

public class InfoProvider extends ContentProvider {
	
	private static final String INFO_TABLE_NAME = "info";
	
	private static final int INFOS = 1; 
	
	private DatabaseHelper mOpenHelper;
	
	private static final UriMatcher sUriMatcher;

	/*
	 * 创建数据库
	 * 
	 * @see android.content.ContentProvider#onCreate()
	 */
	@Override
	public boolean onCreate() {
		mOpenHelper = new DatabaseHelper(getContext());
		return true;
	}
	
	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
		switch (sUriMatcher.match(uri)) {
		case INFOS:
			qb.setTables(INFO_TABLE_NAME);
			break;		
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		// Get the database and run the query
		SQLiteDatabase db = mOpenHelper.getReadableDatabase();
		if (sortOrder != null) {
			Cursor c = qb.query(db, projection, selection, selectionArgs, sortOrder, null, null);
			return c;
		}
		Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, null);

		return c;
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		// TODO Auto-generated method stub
		return 0;
	}

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

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		// TODO Auto-generated method stub
		return null;
	}	

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		// TODO Auto-generated method stub
		return 0;
	}
	
	static {
		sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		sUriMatcher.addURI(Info.AUTHORITY, "info", INFOS);
	}
}

第三步:使用数据访问接口

public class MainActivity extends Activity {
	private Intent intent;

	public static final String[] infoProjection = new String[] { Infos._ID, Infos.CODE1, Infos.CODE2,
			Infos.NUMS };
	EditText txtCode1 = null;
	EditText txtCode2 = null;
	EditText txtNums = null;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		txtCode1 = (EditText) this.findViewById(R.id.txt_code1);
		txtCode2 = (EditText) this.findViewById(R.id.txt_code2);
		txtNums = (EditText) this.findViewById(R.id.txt_nums);
		intent = getIntent();
		// 初始化数据
		this.initData();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	private void initData() {
		intent.setData(Infos.CONTENT_URI);
		Cursor c = managedQuery(getIntent().getData(), infoProjection, null, null, null);
		
		if (c.getCount() != 0) {
			c.moveToFirst();				
			while (!c.isLast()) {
				 txtCode1.setText(c.getString(c.getColumnIndex(Infos.CODE1)));
				 txtCode2.setText(c.getString(c.getColumnIndex(Infos.CODE2)));
				 txtNums.setText(c.getString(c.getColumnIndex(Infos.NUMS)));
				 c.moveToNext();
			}
		} 
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值