使用ContentProvider进行应用程序间的数据交互

什么是ContentProvider:

ContentProvider用来管理数据的访问规则。它允许你的应用程序向外界暴露需要被访问的数据。

是Android的四大组件之一。

ContentProviders支持四种基本的操作,即我们平时所见到的CRUD操作(增删改查)。Android系统

本身已经提供了一些内容提供者,它们允许我们查询联系人,媒体库,和短息消息等。

基于Content Uri的查询:

没有Uri,ContentProvider 类基本无法工作,就像我们上网没有网址。当我们要上网,就要在地址栏输入网址。

因此,要了解ContentProvider,我们必须先了解 Content Uri

下面是Uri的基本格式:

content://authority/optionalPath/optionalId

content://是内容提供者的标准前缀,而且它必须是content://。authority由我们自己定义,它必须具有唯一性,

因此我们一般使用应用程序包名命名authority。optionalPath和optionalId是可选的。

下面我们来看一下WordPress的文章地址格式:

http://www.whathecode.com/archives/221

http:// 是http协议的标准写法,它是规定的,没有为什么。

www.whathecode.com可以理解为authority,因为域名是唯一的,它可以分辨我们要访问哪一个网站。

arichives可以理解为文章的分类。

最后的221就是文章的id,假如我们要查看第一遍文章,只要将221改成1就可以。

这样理解Uri是不是简单了很多。

建立自己的ContentProvider

建立ContentProvider只需几部:

1. 设计数据库的储存方式,因为ContentProvider提供的是数据,没有数据,ContentProvider就没有了用处。

2. 定义自己的类,继承ContentProvider类,并实现基本的方法。

3. 设计authority字符串。(要被人访问你的网站,你就需要一个网址,当然ip地址也可以)

4. 在AndroidManifest中注册Provider

我们先来研究一下代码:

作为示例下面的代码只实现了query方法,而且只添加了一个Uri,

一般应用程序都不只一个Uri

package com.whathecode.provider;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.util.Log;
import android.widget.Toast;

public class MemberProvider extends ContentProvider
{

	private static final UriMatcher sMatcher;
	private static final String MEMBER_NAME = "name";
	private static final int QUERY_BY_NAME = 0;
	private static final String DB_NAME = "member.db";
	private static final String TAG = "MemberProvider";

	static
	{
		sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		/**
		 * 添加需要匹配的Uri, 当这个Uri被匹配的时候返回第三个参数。
		 * 得到这个参数之后就可以在query,insert,update,delete
		 * 方法中做出相应的动作。
		 */
		sMatcher.addURI(Member.AUTHORITY, MEMBER_NAME, QUERY_BY_NAME);
	}

	private static class DataBaseHelper extends SQLiteOpenHelper
	{

		public DataBaseHelper(Context context, String name,
				CursorFactory factory, int version)
		{
			super(context, name, factory, version);
		}

		@Override
		public void onCreate(SQLiteDatabase db)
		{
			//建立数据库表结构
			db.execSQL("create table member(_id integer primary key," +
					"name varchar(20)," +
					"work varchar(20)," +
					"age integer)");
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
		{
			// TODO Auto-generated method stub

		}

	}

	private DataBaseHelper mHelper;

	@Override
	public boolean onCreate()
	{
		mHelper = new DataBaseHelper(getContext(), DB_NAME, null, 2);
		return true;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder)
	{

		 /**
		  * 前面我们在静态代码块中已添加了Uri库
		  * 当每个Uri作为参数传进来的时候我们都先进行匹配
		  *
		  */
		switch (sMatcher.match(uri))
		{
		case QUERY_BY_NAME:
			//第一次执行时生成数据库member.db
			SQLiteDatabase readableDatabase = mHelper.getReadableDatabase();
			/**
			 * 当query方法执行的时候向外发送广播
			 */
			Intent intent = new Intent();
			intent.setAction("com.contentprovider.execquery");
			intent.putExtra("MemberProvider", "query方法执行了");
			getContext().sendBroadcast(intent);
			break;

		default:
			/**
			 * 当Uri匹配失败的时候说明Uri参数错误,无法继续进行操作,
			 * 因此程序抛出一个错误
			 */
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
		return null;
	}

	@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 delete(Uri uri, String selection, String[] selectionArgs)
	{
		// TODO Auto-generated method stub
		return 0;
	}

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

}

这样,一个虽简单但可行的内容提供者就创建好了,现在我们只需在AndroidManifest文件中注册它。

<provider android:name="com.whathecode.provider.MemberProvider"
      android:authorities="com.whathecode.contentproviderdemo.member">
</provider>

接下来,运行这个程序,将我们刚才定义的ContentProvider部署到模拟器。

然后,我们建立另外一个程序测试这个内容提供者是否真的工作正常。

下面是另外一个程序的代码:

我们需要另外一个类进行访问ContentProvider提供的数据。

这个类就是ContentResolver,它提供了和ContentProvider一样的CRUD方法。

方便我们查询数据。

package com.whathecode.contentprovidertest;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity
{

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

		//创建一个广播接受者用于接收MemberProvider发出的广播
		receiver = new BroadcastReceiver()
		{

			@Override
			public void onReceive(Context context, Intent intent)
			{
				/**
				 * 当广播被接收到的时候Toast提示用户接收到的信息
				 */
				Toast.makeText(getBaseContext(),
						"收到的信息" + intent.getStringExtra("MemberProvider"),
						Toast.LENGTH_SHORT).show();
			}
		};
	}

	@Override
	protected void onResume()
	{
		super.onResume();
		//注册广播接受者
		registerReceiver(receiver, new IntentFilter("com.contentprovider.execquery"));
	}

	public void onClick(View view)
	{
		/**
		 * 获取ContentResolver实例访问ContentProvider
		 */
		ContentResolver resolver = getContentResolver();
		Uri uri = Uri
				.parse("content://com.whathecode.contentproviderdemo.member/name");
		resolver.query(uri, null, null, null, null);
	}

	@Override
	protected void onPause()
	{
		super.onPause();
		//取消注册广播接受者
		unregisterReceiver(receiver);
	}
}

运行效果:

如果Toast运行证明MemberProvider中的query方法被成功执行

时间: 2024-10-08 02:25:30

使用ContentProvider进行应用程序间的数据交互的相关文章

linux 共享内存shm_open实现进程间大数据交互

linux 共享内存shm_open实现进程间大数据交互 read.c #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <sys/mman.h> #include <string.h> #include <errno.h> #include <unistd.h> /* int

iOS应用程序间共享数据(转)

我们知道iOS由于沙盒的存在,应用程序不能越过自己的区域去访问别的存储空间的内容,不过可能有许多场景我们需要在应用程序之间共享数据,比如多个应用共用用户名密码进行登录等.虽然我们不能直接通过文件系统来分享数据,不过还是有些方法可以实现,为了方便说明,这里同时创建了两个工程Example1和Example2,实现这两个app之间的信息共享,Example1负责写数据,Example2负责读数据,具体的demo代码可以到这里获取 UIPasteboard 剪贴板是应用程序之间传递数据的简单方式,建议

iOS应用程序间共享数据

我们知道iOS由于沙盒的存在,应用程序不能越过自己的区域去访问别的存储空间的内容,不过可能有许多场景我们需要在应用程序之间共享数据,比如多个应用共用用户名密码进行登录等.虽然我们不能直接通过文件系统来分享数据,不过还是有些方法可以实现,为了方便说明,这里同时创建了两个工程send和receive,实现这两个app之间的信息共享,send负责写数据,receive负责读数据,具体的demo代码可以到这里获取 UIPasteboard 剪贴板是应用程序之间传递数据的简单方式,建议不要使用全局的粘贴板

Linux下的C程序,通过最简单的管道(‘|‘)实现两个程序间的数据传递

本文中使用的管道,是Linux中把前一个程序的输出放到后一个程序的输入的'|'符号,并不是自己实现的管道 代码1:程序a.c输出"HelloWorld",并由b.c通过管道接住输出 a.c代码 #include <stdio.h> void main() {     printf("Hello World! :-P\n"); } b.c代码 #include <stdio.h> void main() {     char input[100

View与Control间的数据交互

1.ViewBag.Name ="Name1" 2.ViewData["VD"] = "view data"; 3.TempData["TD"] = "temp data"; 4.Model ViewBag和ViewData只在当前的Action中有效,生命周期和 View 相同: TempData可以通过转向继续使用,因为它的值保存在Session中.但TempData只能经过一次传递,之后会被系统自动清

iOS应用间共享数据

准备工作 新建两个应用,分别为ProjectA和ProjectB.  然后从A贡献数据到B 然后设置ProjectB的Url Schemes 在ProjectA 添加跳转Url: NSURL *url = [NSURL URLWithString:@"projectb:hehe"]; [[UIApplication sharedApplication] openURL:url]; 1 2 那么projectb:hehe 冒号后面的参数就是我们可以传过去的数据 APP状态 B并没有启动,

IOS应用程序间相互跳转 与 传值

阅读本文之前建议参考:<Communicating with Other App程序间通信[翻译]> 在IOS中,实现在app1中打开app2,方法如下: 1,在app2中注册一个URL Schemes 注册的方法很简单,在XXX-info.plist文件中新增一个URL types数组元素,取一个名字,比如"tekuba_net".或者在工程的-TARGETS-Info,中找到URL Types添加一个URL Schemes,名为"tekuba_net"

Hybrid小程序混合开发之路 - 数据交互

HTML+CSS是历史悠久.超高自由度.控制精准.表现能力极强.编码简单.学习门槛超低.真跨平台的一种UI界面开发方式. 本文介绍的是微信小程序和H5混合开发的一种数据交互方式. 很多应用在原生界面中混杂着HTML界面 记得xp时代的QQ,有些界面偶尔会弹出熟悉的js错误对话框,还能右键弹出熟悉的IE6的右键菜单,伪装的挺好,差点没认出来,现在的QQ就不知道了. 美团.淘宝这些拥有几乎无限界面的手机App,顶部进度条一亮,这是一个H5 没谁了! Electron!好嗨哟~ 数据交互 使用了HTM

java不同对象之间的数据交互(通用)

??java中万物皆对象.不论你是线程,还是异步任务,还是...都可以用以下的三种通用方法来进行对象间数据的交互.当然android相比java有自己独特的数据交互方式,这些会在后面的文章中讲到,本篇文章意在对java通用的对象间的数据交互进行总结. 一.通过构造函数传递 ??构造函数很大程度上是方便参数的传递,以达到在新建对象的时候,同时对这个对象的一些属性进行初始化.我们经常需要根据自己的需要,重载类的构造方法.我们可以在对象初建的时候把它需要的数据传递给它,以实现不同对象之间数据的交互.