内容提供器
内容提供器是用来读取和存储数据,使用它可以将我们自己的数据共享给别人,同时可以读取到别人的数据在别人容许的情况下。他是唯一个可以在不同的应用程序间共享数据的方式,没有公共的存储区域,所有的android应用程序都可以访问。
android系统自带一些内容提供器为常用的数据类型,如音乐,视频,图片,联系人资料等,你可以通过android.provider包查看这些东东,你可以通过这些内容提供器查询他们包含的数据(但是你必须要得到其他用户程序的许可)。
如果你想让你的数据可以让别人共享,你必须做两个操作,1.你需要建立你自己的contentProvider(一个系统提供的contentProvider的子类)存储数据,2.你通过别人提供的provider去存储自己的数据(这个provider必须很你需要操作的数据类型一样,且你拥有这个provider写的权利)。
contentprovider基础
一个contentprovider怎样存储数据,完全有他的开发者控制,但是所有的contentprovider必须实现相同的接口,用来查询内容和返回结果,比如添加数据,修改,和删除。
用户可以通过系统提供的一个接口getContentResolver回去contentResolver对象(在activity中调用这个对象),当你得到这个对象后,
一般在activity中使用的方法为
ContentResolver c = getContentResolver();这个时候你就可以和提供contentprovider的应用进行交互了,
当我们发起一个查询事件时,系统识别contentProvider通过在查询中提供的uri,然后确定这个contentprovider启动并且在运行,android系统在启动的时候就初始化所有的contentprovider对象(自己提供的contentprovider需要在manifest文件中声明,具体做法一会讲)
对一些公共的应用你永远不需要自己去实现(开源软件的好处,省力,省钱,支持开源,但同时也降低了我们程序员的水准),实际上你根本不需要直接和一个contentprovider打交道(除非是自己的),android系统为没个contentprovider提供了一个实例(单例模式),但是它可以和多个contentresolver打交道(线程安全的),线程安全是由contentresolver和contentprovider完成的,我们使用者不比为此担忧。
数据模式
contentprovider是按照表的方式公开自己的数据。每一个行是一条记录,每一列是一个具体的值,这里就不举例了,如果连表都不知道的话,建议你还是别存从事软件开发了,免得降低程序员的水准,呵呵,题外话
在android的中,每一行数据都必须包含一列,列名为"_id",他是表的主键。主键的概念和作用参考数据库方面的书
每一个查询都返回一个Cursor对象,做过oracle pl/sql编程的可定知道他的意思。cursor对象可以让我们从一行移另一行,一列移动到另一列,可以很方便的读数据。他还提供读取特定类型的数据的方法,如getString,getInteger等方法,前提是你必须知道每个字段所代表的类型。(一会将详细介绍查询结果和cursor对象)
Uri
uri的作用是准确的定位我们需要的contentprovider提供的数据,否则就会乱套(不安全的,得带),每一个contentprovider都提供一个公开的uri ,他可以准确的标识一个数据集,一个contentprovider控制多个数据集,通过uri可以准确的标识他们,中的每一个数据集。所有的uri必须以content://开头,content:是作为识别contentprovider的标识。
如果你自己定义了一个contentprovider,那么你也需要为他建立一个uri,简化他人调用的工作and make future updates cleaner(请大侠解释),android定义content_uri 常量给所有的和平台交互的provider(Android defines CONTENT_URI constants for all the providers that come with the platform)。例如,查询联系的联系人和联系的图片的uri为:
android.provider.Contacts.Phones.COntent_URI 和android.provider.Contacts.Photos.CONTENT_URI.
uri 对所有和contentprovider交互的用户。每个contentresolver的方法的第一个参数就是uri,他定义了将要和哪个contentprovider的contentresolver进行对话,以及将要对哪个表进行操作。
查询一个contentprovider
你需要分三步去查询一个contentprovidr
1.contentprovidr定义的uri
2.你需要返回的表的列名
3.这些数据的类型(本人有点疑问)
如果你要查询某条特定的数据,你还需要制定ID
生成查询
你可以通过ContentResolver对象的query方法或者Activity.managedQuery方法,这个方法的参数都一样,都返回一个cursor对象,但是managedQuery方法可以让activity管理cursor对象的生命周期,他可以做好多事情,比如,当activity pauses以后,会自动关闭cursor对象。当activity restart的时候,它可以自动去重新查询。你也可以调用activit的startmanagingCursor(Cursor c)方法去管理这个对象。
query方法和managedQuery方法的第一个参数为provider的uri,关于uri上面已经介绍过了,
android系统提供了一些辅助方法,比如,COntentUris.withAppendedId()和Uri.withAppendedPath()方法,他们可以很方便的为uri添加一个id,两个方法都是静态的,都返回一个uri对象,下面是android 帮助文档中提供的例子
import android.provider.Contacts.People;
import android.content.ContentUris;
import android.net.Uri;
import android.database.Cursor;
// Use the ContentUris method to produce the base URI for the contact with _ID == 23.
//Uri myPerson = ContentUris.withAppendedId(People.CONTENT_URI, 23);
// Alternatively, use the Uri method to produce the base URI.
// It takes a string rather than an integer.
Uri myPerson = Uri.withAppendedPath(People.CONTENT_URI, "23");
// Then query for this specific record:
Cursor cur = managedQuery(myPerson, null, null, null, null);
query()和managedQuery()方法的参数代表的意思如下:
参数1:uri。参数2:需要返回的列名,比如_id,number,nember_key等,如果为空,则返回所有列。参数3:相当于sql语句的where条件,比如 “_id” = 12,"_id" = ? 。如果为null的时候,则返回所有列,前提是你的uri是返回全部的uri。参数4:如果参选3中包含形如"_id" = ?的条件,那么此项不能为空。否则此项为空,目的是提供查询速度,让sql语句软解析。参数5:是排序,比如要按照id排序,则为“id desc ”,不需要加order by。详细请查看android api android.content.contentResolver
查询返回的数据
每个查询都会返回o个或者多条记录。不会返回null,而且每行都会包含_id这列,
读取返回的数据
从cursor中读数据的时候,一定要知道数据的类型,但是你也可以通过getString方法,读取到所有数据,但是返回的对象都是string类型的,在你实际应用中,你还是要转换成真正的类型,所以还是第一次就使用对象的get方法把,你可以使用index或者列名去读数据。好像没有提供直接使用列名读数据的方法,不知道为什么,待解(难道是我没注意到)。
如下:
if (cur.moveToFirst()) {
String name;
String phoneNumber;
int nameColumn = cur.getColumnIndex(People.NAME);
int phoneColumn = cur.getColumnIndex(People.NUMBER);
String imagePath;
do {
// Get the field values
name = cur.getString(nameColumn);
phoneNumber = cur.getString(phoneColumn);
// Do something with the values.
...
} while (cur.moveToNext());
}
如果一个查询返回的是二进制数据,如image或者音乐。那么数据可以直接存在表中,也可以通过一个uri链接到相应内容。使用uri可以获取数据。一般情况下,小数据,如20-50k或者更小的,直接存在数据库,可以通过getBlod()方法到到btye数据。如果table存在的uri,那么你不需要直接打开或者读取这个文件,(不过要有这个权限)。你应该调用ContentResolver.onpenInputStream()获取inputStream对象,然后可以读。
修改数据
1.add
2.updata
3.batch update
3.delete
一. 添加数据
添加数据的第一步,你需要创建一个key-value对象在ContentValues(相当于map,内部实现还是以map实现的,android封装了java的map对象)。数据设置好后,调用contentResolver的insert方法就可以插入了
insert方法返回的不是我们想象的id类型,而是一个uri对象,代表新插入记录的uri。你可以使用他查询刚才添加的记录。如下:
ContentValues values = new ContentValues();
// Add Abraham Lincoln to contacts and make him a favorite.
values.put(People.NAME, "Abraham Lincoln");
// 1 = the new contact is added to favorites
// 0 = the new contact is not added to favorites
values.put(People.STARRED, 1);
Uri uri = getContentResolver().insert(People.CONTENT_URI, values);
二. 修改,删除就不说了,基本上差不多,update和delete方法。
创建一个contentprovider
1.创建一个contentProvider子类
2.定义uri
3.使用创建的类。打开一个SQLiteDatabase对象。openRendHelper和openWirterHelper方法。
4.在manifest文件中声明这个类,一定要声明,<provider android:name="com.example.autos.AutoInfoProvider"
android:authorities="com.example.autos.autoinfoprovider"
. . . />
</provider>
实现类里,需要实现的方法有 query,insert update getType oncreate
格式为 content://xxx.xxx.xxx全部数据,某一条数据 content://xxx.xxx.xxx/id
<provider android:name="com.example.autos.AutoInfoProvider"
android:authorities="com.example.autos.autoinfoprovider"
. . . />
</provider>
import java.util.Calendar;
import java.util.Date;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DiaryDbAdapter {
public static final String KEY_TITLE = "title";
public static final String KEY_BODY = "body";
public static final String KEY_ROWID = "_id";
public static final String KEY_CREATED = "created";
private static final String TAG = "DiaryDbAdapter";
private DatabaseHelper mDbHelper;
private SQLiteDatabase mDb;
private static final String DATABASE_CREATE = "create table diary (_id integer primary key autoincrement, "
+ "title text not null, body text not null, created text not null);";
private static final String DATABASE_NAME = "database";
private static final String DATABASE_TABLE = "diary";
private static final int DATABASE_VERSION = 1;
private final Context mCtx;
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DATABASE_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS diary");
onCreate(db);
}
}
public DiaryDbAdapter(Context ctx) {
this.mCtx = ctx;
}
public DiaryDbAdapter open() throws SQLException {
mDbHelper = new DatabaseHelper(mCtx);
mDb = mDbHelper.getWritableDatabase();
return this;
}
public void closeclose() {
mDbHelper.close();
}
public long createDiary(String title, String body) {
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_TITLE, title);
initialValues.put(KEY_BODY, body);
Calendar calendar = Calendar.getInstance();
String created = calendar.get(Calendar.YEAR) + "年"
+ calendar.get(Calendar.MONTH) + "月"
+ calendar.get(Calendar.DAY_OF_MONTH) + "日"
+ calendar.get(Calendar.HOUR_OF_DAY) + "时"
+ calendar.get(Calendar.MINUTE) + "分";
initialValues.put(KEY_CREATED, created);
return mDb.insert(DATABASE_TABLE, null, initialValues);
}
public boolean deleteDiary(long rowId) {
return mDb.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
}
public Cursor getAllNotes() {
return mDb.query(DATABASE_TABLE, new String[] { KEY_ROWID, KEY_TITLE,
KEY_BODY, KEY_CREATED }, null, null, null, null, null);
}
public Cursor getDiary(long rowId) throws SQLException {
Cursor mCursor =
mDb.query(true, DATABASE_TABLE, new String[] { KEY_ROWID, KEY_TITLE,
KEY_BODY, KEY_CREATED }, KEY_ROWID + "=" + rowId, null, null,
null, null, null);
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}
public boolean updateDiary(long rowId, String title, String body) {
ContentValues args = new ContentValues();
args.put(KEY_TITLE, title);
args.put(KEY_BODY, body);
Calendar calendar = Calendar.getInstance();
String created = calendar.get(Calendar.YEAR) + "年"
+ calendar.get(Calendar.MONTH) + "月"
+ calendar.get(Calendar.DAY_OF_MONTH) + "日"
+ calendar.get(Calendar.HOUR_OF_DAY) + "时"
+ calendar.get(Calendar.MINUTE) + "分";
args.put(KEY_CREATED, created);
return mDb.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
}
}
分享到:
相关推荐
总的来说,这份教程深入浅出地介绍了Android开发的基本概念,包括环境配置、Activity生命周期、Intent、SQLite数据库操作和Content Provider的使用,是初学者入门Android开发的宝贵资源。通过实践这些基础知识,...
在实际项目中,Laravel API Doc Provider不仅可以帮助开发者快速生成和更新API文档,还可以用于自动化测试和客户端SDK的生成。它提高了团队协作的效率,确保了API文档与代码的一致性,减少了因为文档不准确带来的...
- **基础知识**:理解Android的基本组件,如活动(Activity)、服务(Service)、广播接收者(Broadcast Receiver)和内容提供者(Content Provider),是开发Android应用的基础。这些组件共同构成了Android应用的...
在Android应用开发中,你需要理解四大组件:Activity(活动)、Service(服务)、Broadcast Receiver(广播接收器)和Content Provider(内容提供者)。Activity是用户界面的入口,Service在后台运行,不与用户交互...
组件测试是Android测试框架的一大亮点,它提供了一系列针对Activity、Content Provider、Service等组件的测试用例类。例如,开发者可以创建特定的测试用例来验证Activity的行为,模拟用户交互,或检查Content ...
10. **内容提供者(Content Provider)**:Content Provider作为数据交换的桥梁,使应用能以标准化方式暴露或访问其他应用的数据,无论数据存储在SQLite数据库、文件系统还是网络上。 11. **广播接收器(Broadcast ...
Content Provider是Android中数据共享的机制,允许不同应用之间访问和交换数据。 8. **Broadcast Receiver** 广播接收器是监听系统或应用广播事件的组件,例如系统启动或网络连接变化,从而做出相应反应。 9. **...
开发者使用Android SDK工具将代码、数据和资源文件编译成一个Android包,即以`.apk`为扩展名的归档文件。每一个`.apk`文件被视为一个独立的应用程序,是Android设备用于安装应用的文件。一旦安装在设备上,每个...
其中,Activity 负责用户界面,Broadcast Intent Receiver 负责接收广播,Service 负责后台服务,Content Provider 负责数据共享。 Android 应用程序开发 Android 应用程序开发需要使用 Android SDK 和开发工具...
- `android.content`:包含内容解析和发布相关的类,如Intent和ContentResolver。 - `android.database`:提供了与数据库交互的接口。 - `android.graphics`:底层图形库,支持2D绘图和基本形状。 - `android....
5. **Content Providers**:为了实现记事的存储,开发者需要利用Android的`Content Provider`机制。`Content Provider`是Android中数据共享的标准接口,它可以将数据存储在SQLite数据库中,并允许其他应用通过URI...
【Android English Doc API】是针对Android开发者的重要参考资料,它包含了Android SDK中的纯英文API文档,以HTML格式呈现。这些文档详细地介绍了Android平台的各种类、接口、方法和属性,为开发者提供了全面的开发...
本章讲解如何创建和使用Content Provider,以及如何使用ContentResolver进行数据查询和操作。 第10章 FRAGMENT Fragment是用于支持多屏和动态UI设计的组件。本章将介绍如何在Activity中添加、移除和管理Fragment,...
Android 应用程序的组件包括四种类型:活动(Activity)、服务(Service)、广播接收器(Broadcast Receiver)和内容提供者(Content Provider)。活动是应用程序的主要组件之一,负责呈现视觉用户界面,例如展示...
在后续的学习中,你将接触到Android的组件模型,包括Activity、Service、Broadcast Receiver和Content Provider。理解这些组件如何协同工作是构建应用程序的关键。你还将学习XML布局文件的编写,以及如何使用Android...
1. Android系统架构:了解Android系统的架构和组件,包括Activity、Service、Broadcast Receiver、Content Provider等。 2. Java语言基础:掌握Java语言的基础知识,包括变量、数据类型、运算符、控制结构、函数等。...
第十一章,通过一个完整的“找一个朋友”应用案例,展示了如何创建 SQLite 数据库、自定义 Content Provider、多个活动(Activity)以及地图视图。这个案例涵盖了从数据存储到用户界面再到地图集成的全面开发过程。 ...
Activity 负责用户界面交互,Service 负责后台处理,Broadcast Receiver 负责处理系统广播,Content Provider 负责数据存储和共享。 知识点 3: Eclipse 开发环境 Eclipse 是一个集成了多种开发工具的集成开发...
Android APP 的架构主要包括四个组件:Activity、Service、Broadcast Receiver 和 Content Provider。 知识点三:软件需求性分析 软件需求性分析是软件开发的重要步骤,本文档中对基于 Android 系统的手机地图 ...
Android 应用程序组件包括 Activity、Service、Broadcast Receiver、Content Provider 等,各个组件都有其特定的功能和应用场景。例如,Activity 是 Android 应用程序的主要组件,负责处理用户交互和显示用户界面。...