ContentProvider:
ContentProvider(内容提供者)是android中的四大组件之一,但是在一般的开发中,可能使用的比较少。
ContentProvider为不同的软件之间数据共享,提供统一的接口。也就是说,如果我们想让其他的应用使用我们自己程序
内的数据,就可以使用ContentProvider定义一个对外开放的接口,从而使得其他的应用可以使用咱们应用的文件、
数据库内存储的信息。当然,自己开发的应用需要给其他应用共享信息的需求可能比较少见,但是在Android系统中,
很多系统自带应用,比如联系人信息,图片库,音频库等应用,为了对其他应用暴露数据,所以就使用了ContentProvider
机制。所以还是要学习ContentProvider的基本使用,在遇到获取联系人信息,图片库,音频库等需求的时候,
才能更好的实现功能。
跟其他组件一样,需要一个类来继承ContentProvider,并且一般会实现如下几个方法:相当于操作系统的数据库
onCreate() 当我们的provider初始化时被调用,我们应该在这个方法里面完成部分初始化操作
query() 查询方法,用于给调用者返回数据 insert() 插入操作,用于让外部应用插入数据到内容提供者中
update() 更新操作,用于更新内容提供者的数据
delete() 用于删除数据
举几个常用的例子,一般用于与系统的数据操作,一般其他的软件不会让自己的内容暴露给别人的。所以与系统自带应用数据交互,不需要再清单文件配置,只需要注意使用权限。
但是是操作一个私有的数据库,一定要在清单文件中配置,压i加上action标识
短信的备份:
package com.example.smsbackup;
import java.io.File;
import java.io.FileOutputStream;
import org.xmlpull.v1.XmlSerializer;
import android.app.Activity;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Xml;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void click(View V) {
try {
// 1,获取xmlSerializer
XmlSerializer serializer = Xml.newSerializer();
// 2,设置序列化器参数
File file = new File(Environment.getExternalStorageDirectory().getPath(), "smsbackup.xml");
FileOutputStream fos = new FileOutputStream(file);
serializer.setOutput(fos, "utf-8");
// 3,写xml文档的开头
serializer.startDocument("utf-8", true);
// 4,写xml开始的根节点
serializer.startTag(null, "smss");
// 5,构造uri
Uri uri = Uri.parse("content://sms/");
// 6,y由于短信的数据库已经通过内容提供者暴露出来了,所以直接通过内容解析者查询
Cursor cursor = getContentResolver().query(uri, new String[] { "address", "date", "body" }, null, null,
null);
while (cursor.moveToNext()) {
String address = cursor.getString(0);
String date = cursor.getString(1);
String body = cursor.getString(2);
//7,写sms节点
serializer.startTag(null, "sms");
//8,写address节点
serializer.startTag(null, "address");
serializer.text(address);
serializer.endTag(null, "address");
//9,写date节点
serializer.startTag(null, "date");
serializer.text(date);
serializer.endTag(null, "date");
//10,写body节点
serializer.startTag(null, "body");
serializer.text(body);
serializer.endTag(null, "body");
//11,写sms结尾节点
serializer.endTag(null, "sms");
// System.out.println("address: " + address + "-----date: " + date + "------body: " + body);
Toast.makeText(getApplicationContext(), address + "---" + date + "---" + body, 0).show();
}
//12,写xml结尾根节点
serializer.endTag(null, "smss");
serializer.endDocument();
//13,关闭流
fos.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
将短信的内容备份到xml文件中。
还需要添加使用权限:读取、写入短信和存储权限:
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.WRITE_SMS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
关键一点 统一资源标识符Uri uri = Uri.parse("content://sms/"); sms一定的知道是怎么来的 是通过查看系统短信的源码 smsProvider 得知
例2、查询联系人:
查询工具类:查询逻辑
package com.itheima.querycontacts;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
//查询联系人的工具类
public class QueryContactsUtils {
public static List<Contact> queryContacts(Context context){
//[0]创建一个集合
List<Contact> contactLists = new ArrayList<Contact>();
//[1]先查询row_contacts表 的contact_id列 我们就知道一共有几条联系人
Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
Uri dataUri = Uri.parse("content://com.android.contacts/data");
Cursor cursor = context.getContentResolver().query(uri,new String[]{"contact_id"} , null, null, null);
while(cursor.moveToNext()){
String contact_id = cursor.getString(0);
if (contact_id!=null) {
//创建javabean对象
Contact contact = new Contact();
contact.setId(contact_id);
System.out.println("contact_id:"+contact_id);
//[2]根据contact_id去查询data表 查询data1列和mimetype_id
//☆ ☆ ☆ ☆ 当我们在查询data表的时候 其实查询的是view_data的视图
Cursor dataCursor = context.getContentResolver().query(dataUri, new String[]{"data1","mimetype"}, "raw_contact_id=?", new String[]{contact_id}, null);
while(dataCursor.moveToNext()){
String data1 = dataCursor.getString(0);
String mimetype = dataCursor.getString(1);
//[3]根据mimetype 区分data1列的数据类型
if ("vnd.android.cursor.item/name".equals(mimetype)) {
contact.setName(data1);
}else if ("vnd.android.cursor.item/phone_v2".equals(mimetype)) {
contact.setPhone(data1);
}else if ("vnd.android.cursor.item/email_v2".equals(mimetype)) {
contact.setEmail(data1);
}
}
//把javabean对象加入到集合中
contactLists.add(contact);
}
}
return contactLists;
}
}
MainActivity:打印出联系人信息
package com.itheima.querycontacts;
import java.util.List;
import android.os.Bundle;
import android.app.Activity;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<Contact> queryContacts = QueryContactsUtils.queryContacts(getApplicationContext());
for (Contact contact : queryContacts) {
System.out.println("contat:"+contact);
}
}
}
Contact:定义JavaBean
package com.itheima.querycontacts;
public class Contact {
private String id;
private String name;
private String phone;
private String email;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "Contact [id=" + id + ", name=" + name + ", phone=" + phone
+ ", email=" + email + "]";
}
}
记得加权限:
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
[1]data表 data1列里面存的是所有联系人的信息 raw_contact_id 列是用来区分一共有几条联系人信息 mimetype_id 列
是用来区分数据类型
[2]row_contacts表 中contact_id就是data表的 raw_contact_id
查询联系人的步骤
[1]先查询row_contacts表 的contact_id列 我们就知道一共有几条联系人
[2]我根据contact_id去查询data表 查询data1列和mimetype
[3]view_data 是由data表和mimetype表的组合
要根据上面minetype来分辨联系人的各项数据如最常用的:1:email 5:电话号码 7 :名字 8:通讯地址等等
例子:插入联系人:
package com.itheima.insertcontactdb;
import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
private EditText et_name;
private EditText et_phone;
private EditText et_email;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//[1]找到我们关心的控件
et_name = (EditText) findViewById(R.id.et_name);
et_phone = (EditText) findViewById(R.id.et_phone);
et_email = (EditText) findViewById(R.id.et_email);
}
//点击按钮 插入一条联系人信息
public void click(View v) {
Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
Uri dataUri = Uri.parse("content://com.android.contacts/data");
//[2]获取name phone email Textutils
String name = et_name.getText().toString().trim();
String phone = et_phone.getText().toString().trim();
String email = et_email.getText().toString().trim();
//[2.1]在插入联系人id的时候 先查询一下 row_contact 一共有几条数据 加+1就是联系人的id
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
int count = cursor.getCount();
int contact_id = count +1;
//[3] 先往row_contact表 插入联系人的id (contact_id)
ContentValues values = new ContentValues();
values.put("contact_id", contact_id);
getContentResolver().insert(uri,values);
//[4]在把name phone email 插入到data表
ContentValues nameValues = new ContentValues();
nameValues.put("data1", name);
//☆ ☆ ☆ ☆ ☆ 插入的数据要告诉数据库 属于第几条联系人 和 数据类型
nameValues.put("raw_contact_id", contact_id);
nameValues.put("mimetype", "vnd.android.cursor.item/name");
getContentResolver().insert(dataUri, nameValues);
Toast.makeText(getApplicationContext(), name+"插入", 1).show();
//[5]把phone号码 插入到data表
ContentValues phoneValues = new ContentValues();
phoneValues.put("data1", phone);
phoneValues.put("mimetype", "vnd.android.cursor.item/phone_v2");
phoneValues.put("raw_contact_id", contact_id);
getContentResolver().insert(dataUri, phoneValues);
//[5]把phone号码 插入到data表
ContentValues emailValues = new ContentValues();
emailValues.put("data1", email);
emailValues.put("mimetype", "vnd.android.cursor.item/email_v2");
emailValues.put("raw_contact_id", contact_id);
getContentResolver().insert(dataUri, emailValues);
}
}
记得加权限:
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
读取通话记录
package com.example.testquery;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.database.Cursor;
import android.provider.CallLog;
public class QueryContactsUtils {
public static List<Data> queryContacts(Context context) {
List<Data> contactLists = new ArrayList<Data>();
Cursor cursor = context.getContentResolver().query(CallLog.Calls.CONTENT_URI, null, null, null, CallLog.Calls.DATE + " desc");
while(cursor.moveToNext()){
Data data=new Data();
data.name=cursor.getString(cursor.getColumnIndex(CallLog.Calls.CACHED_NAME));
if(data.name==null){
data.name="陌生人";
}
data.number=cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER));
data.type=cursor.getInt(cursor.getColumnIndex(CallLog.Calls.TYPE));
switch (data.type) {
case 1:
data.strType="来电记录";
break;
case 2:
data.strType="拨打记录";
break;
case 3:
data.strType="未接记录";
break;
}
data.lDate=cursor.getLong(cursor.getColumnIndex(CallLog.Calls.DATE));
data.duration =cursor.getLong(cursor.getColumnIndex(CallLog.Calls.DURATION));
data._new=cursor.getInt(cursor.getColumnIndex(CallLog.Calls.NEW));
contactLists.add(data);
}
return contactLists;
}
}
javabean类:
package com.example.testquery;
public class Data {
public String name;
public String number;
public String strType;
public int type;
public long lDate;
public long duration;//通话时间
public int _new;
@Override
public String toString() {
return "姓名:" + name + ",电话:" + number + ", " + strType + ", 通话时长"
+ duration+"秒";
}
}
权限:
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
对于私人的数据库数据共享,对URI的介绍和路径匹配器
Uri类简介
Uri代表了要操作的数据,Uri主要包含了两部分信息
①需要操作的ContentProvider
②对ContentProvider中的什么数据进行操作
组成部分
①scheme:ContentProvider的scheme已经由Android所规定为content://
②主机名(Authority):用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。建议为公司域名,保持唯一性
③路径(path):可以用来表示我们要操作的数据,路径的构建应根据业务而定:
要操作person表中id为10的记录
content://cn.xyCompany.providers.personProvider/person/10
要操作person表中id为10的记录的name字段
content://cn.xyCompany.providers.personProvider/person/10/name
要操作person表中的所有记录
content://cn.xyCompany.providers.personProvider/person
要操作的数据不一定来自数据库,也可以是文件等他存储方式,如要操作xml文件中user节点下的name节点
content://cn.xyCompany.providers.personProvider/person/10/name
把一个字符串转换成Uri,可以使用Uri类中的parse()方法
Uri uri = Uri.parse("content://cn.xyCompany.providers.personProvider/person")
UriMatcher、ContentUris和ContentResolver简介
Uri代表了要操作的数据,所以经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher 和ContentUris。掌握它们的使用会便于我们的开发工作。
UriMatcher
用于匹配Uri
①把需要匹配Uri路径全部给注册上
// 常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码(-1)。
UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
// 若match()方法匹配content://cn.xyCompany.providers.personProvider/person路径则返回匹配码为1
uriMatcher.addURI("content://cn.xyCompany.providers.personProvider","person", 1);
// 若match()方法匹配content://cn.xyCompany.providers.personProvider/person/10路径则返回匹配码为2
uriMatcher.addURI("content://cn.xyCompany.providers.personProvider","person/#", 1);
②注册完需要匹配的Uri后,就可以使用uriMatcher.match(uri)方法对输入的Uri进行匹配
ContentUris
ContentUris是对URI的操作类,其中的withAppendedId(uri, id)用于为路径加上ID部分,parseId(uri)方法用于从路径中获取ID部分方法很实用。
Uri insertUri = Uri.parse("content://cn.xyCompany.providers.personProvider/person" + id);等价于
Uri insertUri = ContentUris.withAppendedId(uri, id);
ContentResolver
当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成。要获取ContentResolver 对象,可以使用Activity提供的getContentResolver()方法。 ContentResolver使用insert、delete、update、query方法来操作数据。
例子:先创建一个私人的数据库:
定义一个类继承与ContentValues
package com.itheima.db;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
public class AccountProvider extends ContentProvider {
//[1]定一个一个uri路径匹配器
private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
private static final int QUERYSUCESS = 0; //ctrl+shift+X 变大写 小写加y
private static final int INSERTSUCESS = 1;
private static final int UPDATESUCESS = 2;
private static final int DELETESUCESS = 3;
private MyOpenHelper myOpenHelper;
//[2]创建一个静态代码块 在这个里面添加 uri
static{
/**
* http://www.baidu.com
* authority 注意: 和清单文件里面定义的一样 com.itheima.provider/query
*
*/
sURIMatcher.addURI("com.itheima.provider", "query", QUERYSUCESS);
sURIMatcher.addURI("com.itheima.provider", "insert", INSERTSUCESS);
sURIMatcher.addURI("com.itheima.provider", "update", UPDATESUCESS);
sURIMatcher.addURI("com.itheima.provider", "delete", DELETESUCESS);
}
//当内容提供者初始化 会执行此方法
@Override
public boolean onCreate() {
//[3]初始化 myopenHelpler 对象 就可以获取到sqlitedatabases对象 我们就可以操作数据库
myOpenHelper = new MyOpenHelper(getContext());
return false;
}
//这个方法对外暴露的
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
int code = sURIMatcher.match(uri);
if (code ==QUERYSUCESS ) {
//说明路径匹配成功
SQLiteDatabase db = myOpenHelper.getReadableDatabase();
//调用query方法
Cursor cursor = db.query("info", projection, selection, selectionArgs, null, null, sortOrder);
//发送一条消息 说明说明数据库被操作了
getContext().getContentResolver().notifyChange(uri, null);
// db.close();
//小细节 ☆ 这个cursor不能关
return cursor;
}else{
//说明路径不匹配
// return null;
throw new IllegalArgumentException("哥们 :uri路径不匹配 请检测路径");
}
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
int code = sURIMatcher.match(uri);
if (code == INSERTSUCESS) {
//说明路径匹配成功
SQLiteDatabase db = myOpenHelper.getReadableDatabase();
long insert = db.insert("info", null, values);
Uri uri2 = Uri.parse("com.hahaheheheihei/"+insert);
if (insert>0) {
//发送一条消息 说明说明数据库被操作了
getContext().getContentResolver().notifyChange(uri, null);
}
db.close();//关闭数据库
return uri2;
}else {
throw new IllegalArgumentException("姐们 :uri路径不匹配 请检测路径");
}
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int code = sURIMatcher.match(uri);
if (code == DELETESUCESS) {
//匹配成功
SQLiteDatabase db = myOpenHelper.getReadableDatabase();
//代表影响的行数
int delete = db.delete("info", selection, selectionArgs);
if (delete>0) {
//发送一条消息 说明说明数据库被操作了
getContext().getContentResolver().notifyChange(uri, null);
}
return delete;
}
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int code = sURIMatcher.match(uri);
if (code == UPDATESUCESS) {
//路径匹配成功
SQLiteDatabase db = myOpenHelper.getWritableDatabase();
//代表影响的行数
int update = db.update("info", values, selection, selectionArgs);
if(update>0){
//发送一条消息 说明说明数据库被操作了
getContext().getContentResolver().notifyChange(uri, null);
}
return update;
}else{
throw new IllegalArgumentException("大爷:uri路径不匹配 请检测路径");
}
}
}
创建数据库的帮助类,并实现其二个方法
package com.itheima.db;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
public class MyOpenHelper extends SQLiteOpenHelper {
public MyOpenHelper(Context context) {
/**
* name 数据库的名字
* factory 游标工厂
* version 版本
*/
super(context, "Account.db", null, 1);
}
/**
* Called when the database is created for the first time
* 当数据库第一次 创建的时候调用 那么这个方法特别适合做 表结构的初始化
*
*/
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table info(_id integer primary key autoincrement,name varchar(20),money varchar(20))");
db.execSQL("insert into info(name,money) values(?,?)", new String[]{"张三","5000"});
db.execSQL("insert into info(name,money) values(?,?)", new String[]{"李四","3000"});
}
@Override
//版本改变的时候调用
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
MainActivity:取出数据
package com.itheima.db;
import android.os.Bundle;
import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.view.Menu;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyOpenHelper helper = new MyOpenHelper(getApplicationContext());
SQLiteDatabase db = helper.getWritableDatabase();
//需求把张三和李四的数据取出来
Cursor cursor = db.query("info", null, null, null, null, null, null);
if (cursor!=null&&cursor.getCount()>0) {
while(cursor.moveToNext()){
String name = cursor.getString(1);
String money = cursor.getString(2);
System.out.println("name:"+name+"-----"+money);
}
cursor.close();
}
}
@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;
}
}
清单文件配置内容提供者
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.itheima.db"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.itheima.db.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 配置内容提供者 -->
<provider
android:name="com.itheima.db.AccountProvider"
android:authorities="com.itheima.provider" >
</provider>
</application>
</manifest>
上面就完成了一个私人的数据库创建
创建一个应用来读取上面的私人数据库
MainActivity:
package com.itheima.readdb;
import android.net.Uri;
import android.os.Bundle;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//点击按钮 往数据库里面插入一条数据
public void click1(View v){
//因为第一个应用里面的私有的数据库 已经通过内容提供者暴露出来了 所以通过内容解析者去获取数据
Uri uri = Uri.parse("content://com.itheima.provider/insert");
ContentValues values = new ContentValues(); //实际是map
//key: 代表列名 value 对应的值
values.put("name", "zhaoliu");
values.put("money", 1000);
//插入一条数据
Uri uri2 = getContentResolver().insert(uri, values);
System.out.println("uri2:"+uri2);
}
//点击按钮删除 赵六删掉
public void click2(View v){
//[1]获取内容的解析者
Uri uri = Uri.parse("content://com.itheima.provider/delete");
//[2]代表影响的函数
int delete = getContentResolver().delete(uri, "name=?", new String[]{"zhaoliu"});
Toast.makeText(getApplicationContext(), "删除了"+delete+"行", 1).show();
}
//给赵六多点钱 1000元
public void click3(View v){
//[1] 创建uri
Uri uri = Uri.parse("content://com.itheima.provider/update");
//[2]获取内容的解析者
ContentValues values = new ContentValues();
values.put("money", "10000000");
int update = getContentResolver().update(uri, values, "name=?",new String[]{"zhaoliu"});
Toast.makeText(getApplicationContext(), "更新了"+update+"行", 1).show();
}
//点击按钮 查询第一个应用里面数据库的信息
public void click4(View v){
// 第二种 查询方式 因为第一个应用里面的私有的数据库 已经通过内容提供者暴露出来了 所以通过内容解析者去获取数据
Uri uri = Uri.parse("content://com.itheima.provider/query");
//获取内容解析者获取数据
Cursor cursor = getContentResolver().query(uri, new String[]{"name","money"}, null, null, null);
if (cursor!=null) {
while(cursor.moveToNext()){
String name = cursor.getString(0);
String money = cursor.getString(1);
System.out.println("第二个应用:"+name+"---"+money);
}
}
}
}
注意程序中uri的设定的资源表示符,在第一数据库应用中清单文件中配置了。
总结:要求掌握对系统应用的数据交互。