Android ContentProvider 简介
当在系统中部署一个又一个Android应用之后,系统里将会包含多个Android应用,有时候就需要在小同的应用之问芡亭数据,比如现在有一个短信接收应用,用户想把接收到的陌生短信的发信人添加到联系人管理应用中,就需要在小同应用之问共宁数据。对于这种需要在小同应用之问共亨数据的需求,当然可以让一个应用程序直接去操作另个应用程序所记录的数据,比如操作它所记录的SharedPreferences、文件或数据库等,这种方式显得太杂乱了:不同的应用程序记录数据的方式差别很大,这种力式不利于应用程序之问进行数据交换。
为了在应用程序之问交换数据,Android提供了ContentProvider,ContentProvider是不同应用程序之间进行数据交换的标准API,当一个应用程序需要把自己的数据暴露给其他程序使用时,该应用科序就可以通过提供ContentProvider来实现;其他应用程序就可通过ContentResolver来操作ContentProvider暴露的数据。
ContentProvider也是Android应刖的四大组件之一,与Activity、Service、BroadcastReceiver相似,它们都需要存AndroidManifest.xml文件中进行配置。
一旦某个应用程序通过ContentProvider暴露了自己的数据操作接口,那么不管该应用程序是否启动,其他应用程序都可通过该接口来操作该应用程序的内部数据,包括增加数据、删除数据、修改数据、查询数据等。
MyContentProvider
MyUser.java
package com.supermario.mycontentprovider; import android.net.Uri;
import android.provider.BaseColumns; public class MyUser {
public static final String AUTHORITY = "com.supermario.MyContentProvider"; // BaseColumn类中已经包含了_id字段
public static final class User implements BaseColumns {
// 定义Uri
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);
// 定义数据表列
public static final String USER_NAME = "USER_NAME";
}
}
MyContentProvider.java
package com.supermario.mycontentprovider; import android.content.ContentProvider;
import android.content.ContentUris;
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.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri; /**
* MyContentProvider继承ContentProvider类,实现其insert,update,delete,getType,
* onCreate等方法
*/
public class MyContentProvider extends ContentProvider {
// 定义一个SQLiteDatabase变量
private SQLiteDatabase sqlDB;
// 定义一个DatabaseHelper变量
private DatabaseHelper dbHelper;
// 数据库名
private static final String DATABASE_NAME = "Users.db";
// 数据库版本
private static final int DATABASE_VERSION = 1;
// 表名
private static final String TABLE_NAME = "User"; /**
* 定义一个内部类
*
* 这个内部类继承SQLiteOpenHelper类,重写其方法
*/
public static class DatabaseHelper extends SQLiteOpenHelper {
// 构造方法
public DatabaseHelper(Context context) {
// 父类构造方法
super(context, DATABASE_NAME, null, DATABASE_VERSION);
} // 当第一次创建数据库的时候调用该方法,可以为数据库增加一些表,和初始化一些数据
@Override
public void onCreate(SQLiteDatabase db) {
// 在数据库里生成一张表
db.execSQL("Create table "
+ TABLE_NAME
+ "( _id INTEGER PRIMARY KEY AUTOINCREMENT, USER_NAME TEXT);");
} // 当更新数据库版本的时候,调用该方法。可以删除,修改表的一些信息
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
} // 这是一个回调函数,当生成所在类的对象时,这个方法被调用,创建一个数据库
@Override
public boolean onCreate() {
dbHelper = new DatabaseHelper(getContext());
return (dbHelper == null) ? false : true;
} // 查询
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
SQLiteDatabase db = dbHelper.getReadableDatabase();
qb.setTables(TABLE_NAME);
Cursor c = qb.query(db, projection, selection, null, null, null,sortOrder);
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
} // 取得类型
@Override
public String getType(Uri uri) {
return null;
} // 插入数据
@Override
public Uri insert(Uri uri, ContentValues contentvalues) {
sqlDB = dbHelper.getWritableDatabase();
long rowId = sqlDB.insert(TABLE_NAME, "", contentvalues);
if (rowId > 0) {
Uri rowUri = ContentUris.appendId(MyUser.User.CONTENT_URI.buildUpon(), rowId).build();
getContext().getContentResolver().notifyChange(rowUri, null);
return rowUri;
}
throw new SQLException("Failed to insert row into" + uri);
} // 删除数据
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
} // 更新数据
@Override
public int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) {
return 0;
}
}
MyContentActivity.java
package com.supermario.mycontentprovider; import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.widget.Toast; public class MyContentActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 插入两条记录
insertRecord("Test");
insertRecord("Guo");
// 显示记录
displayRecords();
} // 插入记录
private void insertRecord(String userName) {
ContentValues values = new ContentValues();
values.put(MyUser.User.USER_NAME, userName);
getContentResolver().insert(MyUser.User.CONTENT_URI, values);
} private void displayRecords() {
// 构建一个字符串数组用于存放用户的记录
String columns[] = new String[] { MyUser.User._ID,MyUser.User.USER_NAME };
// 设定ContentProvider的Uri
Uri myUri = MyUser.User.CONTENT_URI;
Cursor cur = managedQuery(myUri, columns, null, null, null);
if (cur.moveToFirst()) {
String id = null;
String userName = null;
do {
id = cur.getString(cur.getColumnIndex(MyUser.User._ID));
userName = cur.getString(cur.getColumnIndex(MyUser.User.USER_NAME));
// 显示数据表中的数据
Toast.makeText(this, id + " " + userName, Toast.LENGTH_LONG).show();
} while (cur.moveToNext());
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.supermario.mycontentprovider"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="10" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<!-- 声明ContentProvider -->
<provider android:name="MyContentProvider"
android:authorities="com.supermario.MyContentProvider"></provider>
<activity
android:name=".MyContentActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
界面:
MyContentClient
MyConrentClientActivity.java
package com.supermario.mycontentclient;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MyContentClientActivity extends Activity {
public static final String AUTHORITY = "com.supermario.MyContentProvider";
private Button insertButton = null;
// 访问ContentProvider的Uri
Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView show=(TextView)findViewById(R.id.show);
StringBuffer sb=new StringBuffer("");
// 得到ContentProvider对于表的所有数据,以游标格式保存
Cursor c = managedQuery(CONTENT_URI,
new String[] { "_id", "USER_NAME" }, null, null, null);
// 循环打印ContentProvider的数据
if (c.moveToFirst()) {
String _id = null;
String user_name = null;
do {
// 得到_id列,USER_NAME列
_id = c.getString(c.getColumnIndex("_id"));
user_name = c.getString(c.getColumnIndex("USER_NAME")); sb.append("_id = " + _id + ", user_name = " + user_name+"\n");
} while (c.moveToNext());
}
show.setText(sb);
// 根据Id得到控件对象
insertButton = (Button) findViewById(R.id.insert);
// 给按钮绑定事件监听器
insertButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 得到EditText输入的数据
String username = ((EditText) findViewById(R.id.userName))
.getText().toString();
// 生成一个ContentResolver对象
ContentResolver cr = getContentResolver();
// 生成一个ContentValues对象
ContentValues values = new ContentValues();
// 将EditText输入的值,保存到ContentValues对象中
values.put("USER_NAME", username);
// 插入数据
cr.insert(CONTENT_URI, values);
}
});
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<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:id="@+id/show"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<!-- 文本编辑框 ,用于输入信息-->
<EditText
android:id="@+id/userName"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<!-- 输入按钮 -->
<Button
android:id="@+id/insert"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</LinearLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.supermario.mycontentclient"
android:versionCode="1"
android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" /> <application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".MyContentClientActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application> </manifest>
界面:
Android ContentProvider 简介的更多相关文章
- "浅谈Android"第一篇:Android系统简介
近来,看了一本书,名字叫做<第一行代码>,是CSDN一名博主写的,一本Android入门级的书,比较适合新手.看了书之后,有感而发,想来进行Android开发已经有一年多了,但欠缺系统化的 ...
- Android Framework 简介
Android Framework 简介 简介 之前的研究太偏向应用层功能实现了,很多原理不了解没有详记,结果被很多公司技术人员鄙视了,为了减少自己的短板,重新复习了一遍C++.java.Androi ...
- Android基础 : Android ContentProvider
Android 应用程序通过ContentProvider实现方式统一的数据共享功能. 外界的程序通过ContentResolver接口可以访问ContentProvider提供的数据,在Activi ...
- Android Studio 简介及导入 jar 包和第三方开源库方[转]
原文:http://blog.sina.com.cn/s/blog_693301190102v6au.html Android Studio 简介 几天前的晚上突然又想使用 Android Studi ...
- 【译】Android系统简介—— Activity
续上一篇,继续介绍Android系统.上一篇: [译]Android系统简介 本文主要介绍构建Android应用的一些主要概念: Activity Activity是应用程序中一个单独的有UI的页面( ...
- 被遗忘的Android mipmaps简介
被遗忘的 Android mipmaps 简介 [导读]已经发布的 Android Studio1.1 版本是一个 bug 修复版本.在这个版本中,当你创建工程时一项改变将会吸引你的眼球.工程创建登陆 ...
- Android系统简介(中):系统架构
Android的系统架构栈分为4层,从上往下分别是Applications.Application framework.Libraries & Android Runtime.Linux ...
- Android系统简介(上):历史渊源
上个月,看到微信的一系列文章,讲到Linux的鼻祖-李纳斯的传记<Just for Fun>, 其人神乎其能, 其人生过程非常有趣,值得每个程序员细细品味. 而实际上,对我而已,虽然做软件 ...
- Android ART简介
一. Android ART简介 Android DEX/ODEX/OAT文件
随机推荐
- js~fancybox为我们提供的iframe功能
对于fancybox我们已经耳熟能详了,一般用来到表单的弹框,提示弹框等,而今天,我们将分页列表也使用fancybox来实现一下,这东西听起来简单,但做起来还真不是那么回事,有事细节需要我们注意的,首 ...
- SQL Server不区分大小写的问题
SQL Server不区分大小写的问题 默认情况下,SQL Server不区分大小写,如果数据表TEST的TNAME列中有数据“abcd”和“Abcd”, 如果使用查询语句:select * fr ...
- Android Scroller类的详细分析
尊重原创作者,转载请注明出处: http://blog.csdn.net/gemmem/article/details/7321910 Scroller这个类理解起来有一定的困难,刚开始接触Scrol ...
- Android抓包工具Fiddler抓取数据
1.手机端设置 2.Fiddler设置监听 Tools/Fiddler options 是否允许监听到https(Fiddler默认只抓取http格式的),首次点击会弹出是否信任fiddler证书和安 ...
- Mono For Android离线激活
我们之前创建过Mono For Android的开发环境,但是使用一段时间后就说明证书过期,那如何破解呢? 但我说的这个也就只能使用免费的证书. 首先下载免费的证书,monoandroid.licx, ...
- [转] Linux下查看文件和文件夹大小
当磁盘大小超过标准时会有报警提示,这时如果掌握df和du命令是非常明智的选择. df可以查看一级文件夹大小.使用比例.档案系统及其挂入点,但对文件却无能为力. du可以查看文件及文件夹的大小. ...
- Android开发艺术探索》读书笔记 (5) 第5章 理解RemoteViews
第5章 理解RemoteViews 5.1 RemoteViews的应用 (1)RemoteViews表示的是一个view结构,它可以在其他进程中显示.由于它在其他进程中显示,为了能够更新它的界面,R ...
- 每天一条Linux命令(OS X系统上操作)
Linux菜鸟必学的60个命令 安装和登录命令:login.shutdown.halt.reboot.install.mount.umount.chsh.exit.last: 文件处理命令:file ...
- BeanFactory学习
关于BeanFactory,一个相对易懂的博客,关于深入的理解,后续继续学习 http://www.cnblogs.com/liuling/archive/2013/04/14/BeanFactory ...
- DNX概述
1. 什么是.NET执行环境 ? .NET Execution Environment(DNX) 是一个SDK 和运行时环境,它包含所有的你需要创建和运行.net应用程序的组件.它提供一个主机进程,C ...