转载请注明出处: http://blog.csdn.net/a992036795/article/details/51610936
一、简介:
ContentProvider 在android中的作用是对外共享数据,也就是说可以通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过ContentProvider对应用中的数据进行增、删、该、查。使用ContentProvider的好处是,统一了数据的访问方式。
ContentProvider的体层实现实际是Binder。
二、使用:
一般ContentProvider的实现都是对SqliteOpenHelp的进一步包装,通过Uri映射来判断选择需要操作数据库中的那个表,并且进行增、删、改、查处理。
我们先来看以一下ContentProvider的定义:
**
* Content providers are one of the primary building blocks of Android applications, providing
* content to applications. They encapsulate data and provide it to applications through the single
* {@link ContentResolver} interface. A content provider is only required if you need to share
* data between multiple applications. For example, the contacts data is used by multiple
* applications and must be stored in a content provider. If you don‘t need to share data amongst
* multiple applications you can use a database directly via
* {@link android.database.sqlite.SQLiteDatabase}.
*
* <p>When a request is made via
* a {@link ContentResolver} the system inspects the authority of the given URI and passes the
* request to the content provider registered with the authority. The content provider can interpret
* the rest of the URI however it wants. The {@link UriMatcher} class is helpful for parsing
* URIs.</p>
*
* <p>The primary methods that need to be implemented are:
* <ul>
* <li>{@link #onCreate} which is called to initialize the provider</li>
* <li>{@link #query} which returns data to the caller</li>
* <li>{@link #insert} which inserts new data into the content provider</li>
* <li>{@link #update} which updates existing data in the content provider</li>
* <li>{@link #delete} which deletes data from the content provider</li>
* <li>{@link #getType} which returns the MIME type of data in the content provider</li>
* </ul></p>
*
* <p class="caution">Data access methods (such as {@link #insert} and
* {@link #update}) may be called from many threads at once, and must be thread-safe.
* Other methods (such as {@link #onCreate}) are only called from the application
* main thread, and must avoid performing lengthy operations. See the method
* descriptions for their expected thread behavior.</p>
*
* <p>Requests to {@link ContentResolver} are automatically forwarded to the appropriate
* ContentProvider instance, so subclasses don‘t have to worry about the details of
* cross-process calls.</p>
*
* <div class="special reference">
* <h3>Developer Guides</h3>
* <p>For more information about using content providers, read the
* <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
* developer guide.</p>
*/
public abstract class ContentProvider implements ComponentCallbacks2 {
private static final String TAG = "ContentProvider";
通过注释我们大概可以了解到:
我们自定义一个ContentProvider,需要实现它的onCreate、query、insert、update、delete、getType方法。
因为它底层实现是Binder、其实对源码进行分析的话、可以看到如果是夸进程调用的话,OnCreate将发生在主线程、而其他方法将发生在Binder线程池中。
这一点,我们可以通过在方法打印进程名会得到证实。
06-08 01:46:21.903 3016-3016/com.blueberry.process1 I/SimpleContentProvider: onCreate: current thread: main
06-08 01:46:21.920 3016-3032/com.blueberry.process1 I/SimpleContentProvider: insert: current thread: Binder_2
06-08 01:46:22.968 3016-3032/com.blueberry.process1 I/SimpleContentProvider: query: current thread: Binder_2
这是我写的一个例子的测试结果。下面我们将自己写一个ContentProvider。
首先我们先定义个SQLiteOpenHelp,来创建1个数据库,其中存在2张表。
下面给出类的定义:
/**
* Created by blueberry on 2016/6/7.
*/
public class UserInfoDbHelper extends SQLiteOpenHelper {
private static final String TAG = "UserInfoDbHelper";
private static final String DB_NAME = "userinfo.db"; /*数据库名*/
private static final int DB_VERSION = 1;/*版本号*/
public static final String TABLE_USER_INFO = "userinfo";/*用户信息表*/
public static final String TABLE_COMPANY = "company";/*公司表*/
public static final String TEL_COLUMN = "tel_num";/*电话号码*/
public static final String DESC_COLUMN = "desc";/*描述*/
public static final String COMP_ID_COLUMN = "comp_id";/*公司id*/
public static final String ID_COLUMN = "id";/*公司的id*/
public static final String BUSINESS_COLUMN = "business";/*公司的业务*/
public static final String ADDR_COLUMN = "addr";/*公司位置*/
// 表 userinfo
// | 字段名 | 类型 |意义 |
// | Tel_num | TEXT |电话号码 |
// | Desc | TEXT |描述 |
// | comp_id | INTEGER | 公司id |
//
// 表 company
// |字段名 |类型 |意义 |
// |Id |INTEGER |公司的id |
// |Business | TEXT |公司的业务 |
// | Addr | TEXT | 公司位置 |
private static final String POSTCODE_TABLE_SQL ="CREATE TABLE IF NOT EXISTS "+TABLE_USER_INFO +" ("
+TEL_COLUMN+" TEXT ,"
+COMP_ID_COLUMN+" INTEGER ,"
+DESC_COLUMN+" TEXT"
+")" ;
private static final String COMPANY_TABLE_SQL ="CREATE TABLE IF NOT EXISTS "+TABLE_COMPANY+" ("
+ID_COLUMN +" INTEGER PRIMEARY KEY ,"
+BUSINESS_COLUMN+" TEXT ,"
+ADDR_COLUMN+" TEXT" +")" ;
public UserInfoDbHelper(Context context) {
super(context, DB_NAME , null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(POSTCODE_TABLE_SQL);
db.execSQL(COMPANY_TABLE_SQL);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
可以看到创建了2张表,一张为userinfo 一张为 company。字段名已在注释列出。
下面继续给出自定一ContentProvider的定义:
/**
* Created by blueberry on 2016/6/7.
*/
public class SimpleContentProvider extends ContentProvider {
private static final String TAG = "SimpleContentProvider";
public static final String AUTHORITY = "com.blueberry.test08.provider";
/*该ContentProvider返回的数据类型定义,数据集合*/
private static final String CONTENT_TYPE ="vnd.android.cursor.dir/vnd."+AUTHORITY;
/*单项数据*/
private static final String CONTNET_TYPE_ITEM ="vnd.android.cursor.item/vnd."+AUTHORITY ;
public static final Uri USERINFO_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
+ UserInfoDbHelper.TABLE_USER_INFO);
public static final Uri COMPANY_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
+ UserInfoDbHelper.TABLE_COMPANY);
public static final int USERINFO_CODE = 0;
public static final int USERINFO_ITEM_CODE = 1;
public static final int COMPANY_CODE = 2;
public static final int COMPANY_ITEM_CODE = 3;
private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
/**
* 这里使用2种通配符 "*"表示匹配任意长度的任意字符,"#"表示匹配任意长度的数字
* 因此,content://com.blueberry.test08.provider/company 表示查询company表中的所有数据
* 而 conent://com.blueberry.test08.provider/company/# 表示根据一个数字id 查询一条信息
*/
sUriMatcher.addURI(AUTHORITY, "userinfo", USERINFO_CODE);
sUriMatcher.addURI(AUTHORITY, "userinfo/*", USERINFO_ITEM_CODE);
sUriMatcher.addURI(AUTHORITY, "company", COMPANY_CODE);
sUriMatcher.addURI(AUTHORITY, "company/#", COMPANY_ITEM_CODE);
}
private SQLiteDatabase mDatabase;
/**
* 夸进程时发生在主线程
*
* @return
*/
@Override
public boolean onCreate() {
Log.i(TAG, "onCreate: current thread: " + Thread.currentThread().getName());
/*返回一个可读写的数据库*/
mDatabase = new UserInfoDbHelper(getContext()).getWritableDatabase();
return true;
}
/**
* 夸进程时发生在工作线程
*
* @param uri
* @param projection
* @param selection
* @param selectionArgs
* @param sortOrder
* @return
*/
@Nullable
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
Log.i(TAG, "query: current thread: " + Thread.currentThread().getName());
Cursor cursor = null;
switch (sUriMatcher.match(uri)) {
case USERINFO_CODE:
cursor = mDatabase.query(UserInfoDbHelper.TABLE_USER_INFO, projection, selection, selectionArgs, null, null, sortOrder);
break;
case USERINFO_ITEM_CODE:
String tel = uri.getPathSegments().get(1);
cursor = mDatabase.query(UserInfoDbHelper.TABLE_USER_INFO, projection, "tel_num = ?", new String[]{tel}, null, null, sortOrder);
break;
case COMPANY_CODE:
cursor = mDatabase.query(UserInfoDbHelper.TABLE_COMPANY, projection, selection, selectionArgs, null, null, sortOrder);
break;
case COMPANY_ITEM_CODE:
String cid = uri.getPathSegments().get(1);
cursor = mDatabase.query(UserInfoDbHelper.TABLE_COMPANY, projection, "id = ?", new String[]{cid}, null, null, sortOrder);
break;
}
return cursor;
}
/**
* 夸进程时发生在工作线程
*
* @param uri
* @param values
* @return
*/
@Nullable
@Override
public Uri insert(Uri uri, ContentValues values) {
Log.i(TAG, "insert: current thread: " + Thread.currentThread().getName());
long newId = 0;
Uri newUri = null;
switch (sUriMatcher.match(uri)) {
case USERINFO_CODE:
newId = mDatabase.insert(UserInfoDbHelper.TABLE_USER_INFO, null, values);
newUri = Uri.parse("content://" + AUTHORITY + "/" + UserInfoDbHelper.TABLE_USER_INFO + "/" + newId);
break;
case COMPANY_CODE:
newId = mDatabase.insert(UserInfoDbHelper.TABLE_COMPANY, null, values);
newUri = Uri.parse("content://" + AUTHORITY + "/" + UserInfoDbHelper.TABLE_COMPANY + "/" + newId);
break;
}
if (newId > 0) return newUri;
throw new IllegalArgumentException("Failed to insert row info" + uri);
}
/**
* 夸进程时发生在工作线程
*
* @param uri
* @return
*/
@Nullable
@Override
public String getType(Uri uri) {
Log.i(TAG, "getType: current thread: " + Thread.currentThread().getName());
switch (sUriMatcher.match(uri)){
case USERINFO_CODE:
case COMPANY_CODE:
return CONTENT_TYPE;
case USERINFO_ITEM_CODE:
case COMPANY_ITEM_CODE:
return CONTNET_TYPE_ITEM;
default:
throw new RuntimeException("错误的 uri");
}
}
@Nullable
@Override
public Bundle call(String method, String arg, Bundle extras) {
return super.call(method, arg, extras);
}
/**
* 夸进程时发生在工作线程
*
* @param uri
* @param selection
* @param selectionArgs
* @return
*/
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
Log.i(TAG, "delete: current thread: " + Thread.currentThread().getName());
return 0;
}
/**
* 夸进程时发生在工作线程
*
* @param uri
* @param values
* @param selection
* @param selectionArgs
* @return
*/
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
Log.i(TAG, "update: current thread: " + Thread.currentThread().getName());
return 0;
}
}
我这里只是测试,所以只实现了query和inser方法。这里主要用了一个 UriMatcher类。
这里对上面的程序简要分析一下:
我们先来简要看一下Uri,Uri代表了要操作的数据表的绝对路径,Uri主要包含两部分信息,一是需要操作的ContentProvider,二是对ContentProvider中的哪个表进行操作。一个Uri的组成为:
ContentProvider的Schema已经由Android固定设置为content://, Authority用于唯一标示这个ContentProvider,外部调用者可以根据这个标示来找到它,这里的path就是要查询的数据表,最后的id是可选字段,例如,我们操作特定的数据项时就会指定一个查询条件,如果所有联系人的uri为 content://contacts/people,某个联系人的Uri:content://contacts/people/5,这个5 就是联系人的id,也就对应了查询的关键字。
这里我们的Authority为 com.blueberry.test08.provider。
接下来我们看以UriMatcher
我们来看一下这个类的定义:
/**
Utility class to aid in matching URIs in content providers.
<p>To use this class, build up a tree of <code>UriMatcher</code> objects.
For example:
<pre>
private static final int PEOPLE = 1;
private static final int PEOPLE_ID = 2;
private static final int PEOPLE_PHONES = 3;
private static final int PEOPLE_PHONES_ID = 4;
private static final int PEOPLE_CONTACTMETHODS = 7;
private static final int PEOPLE_CONTACTMETHODS_ID = 8;
private static final int DELETED_PEOPLE = 20;
private static final int PHONES = 9;
private static final int PHONES_ID = 10;
private static final int PHONES_FILTER = 14;
private static final int CONTACTMETHODS = 18;
private static final int CONTACTMETHODS_ID = 19;
private static final int CALLS = 11;
private static final int CALLS_ID = 12;
private static final int CALLS_FILTER = 15;
private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static
{
sURIMatcher.addURI("contacts", "people", PEOPLE);
sURIMatcher.addURI("contacts", "people/#", PEOPLE_ID);
sURIMatcher.addURI("contacts", "people/#/phones", PEOPLE_PHONES);
sURIMatcher.addURI("contacts", "people/#/phones/#", PEOPLE_PHONES_ID);
sURIMatcher.addURI("contacts", "people/#/contact_methods", PEOPLE_CONTACTMETHODS);
sURIMatcher.addURI("contacts", "people/#/contact_methods/#", PEOPLE_CONTACTMETHODS_ID);
sURIMatcher.addURI("contacts", "deleted_people", DELETED_PEOPLE);
sURIMatcher.addURI("contacts", "phones", PHONES);
sURIMatcher.addURI("contacts", "phones/filter/*", PHONES_FILTER);
sURIMatcher.addURI("contacts", "phones/#", PHONES_ID);
sURIMatcher.addURI("contacts", "contact_methods", CONTACTMETHODS);
sURIMatcher.addURI("contacts", "contact_methods/#", CONTACTMETHODS_ID);
sURIMatcher.addURI("call_log", "calls", CALLS);
sURIMatcher.addURI("call_log", "calls/filter/*", CALLS_FILTER);
sURIMatcher.addURI("call_log", "calls/#", CALLS_ID);
}
</pre>
<p>Starting from API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, paths can start
with a leading slash. For example:
<pre>
sURIMatcher.addURI("contacts", "/people", PEOPLE);
</pre>
<p>Then when you need to match against a URI, call {@link #match}, providing
the URL that you have been given. You can use the result to build a query,
return a type, insert or delete a row, or whatever you need, without duplicating
all of the if-else logic that you would otherwise need. For example:
<pre>
public String getType(Uri url)
{
int match = sURIMatcher.match(url);
switch (match)
{
case PEOPLE:
return "vnd.android.cursor.dir/person";
case PEOPLE_ID:
return "vnd.android.cursor.item/person";
... snip ...
return "vnd.android.cursor.dir/snail-mail";
case PEOPLE_ADDRESS_ID:
return "vnd.android.cursor.item/snail-mail";
default:
return null;
}
}
</pre>
instead of:
<pre>
public String getType(Uri url)
{
List<String> pathSegments = url.getPathSegments();
if (pathSegments.size() >= 2) {
if ("people".equals(pathSegments.get(1))) {
if (pathSegments.size() == 2) {
return "vnd.android.cursor.dir/person";
} else if (pathSegments.size() == 3) {
return "vnd.android.cursor.item/person";
... snip ...
return "vnd.android.cursor.dir/snail-mail";
} else if (pathSegments.size() == 3) {
return "vnd.android.cursor.item/snail-mail";
}
}
}
return null;
}
</pre>
*/
public class UriMatcher
{
可以看到,注释中已经把他的用法说的查不到了。
UriMather 会根据uri来匹配出对应的 code来使得我们判断该查询那张表,
这里我们定义了四个 code. 分别对用与 用户信息查询、单个用户信息查询、公司查询、单个公司查询。
public static final int USERINFO_CODE = 0;
public static final int USERINFO_ITEM_CODE = 1;
public static final int COMPANY_CODE = 2;
public static final int COMPANY_ITEM_CODE = 3;
我们通过如下方法将 对应信息添加进去:
static {
/**
* 这里使用2种通配符 "*"表示匹配任意长度的任意字符,"#"表示匹配任意长度的数字
* 因此,content://com.blueberry.test08.provider/company 表示查询company表中的所有数据
* 而 conent://com.blueberry.test08.provider/company/# 表示根据一个数字id 查询一条信息
*/
sUriMatcher.addURI(AUTHORITY, "userinfo", USERINFO_CODE);
sUriMatcher.addURI(AUTHORITY, "userinfo/*", USERINFO_ITEM_CODE);
sUriMatcher.addURI(AUTHORITY, "company", COMPANY_CODE);
sUriMatcher.addURI(AUTHORITY, "company/#", COMPANY_ITEM_CODE);
}
我们接着来看一下getType方法,根据UriMather推荐的方法,如果查询的是数据集合, 我们返回的类型应该是 vnd.android.cursor.dir/….. 如果是查询单个数据我们返回的类型应该是 vnd.android.cursor.item/….
/*该ContentProvider返回的数据类型定义,数据集合*/
private static final String CONTENT_TYPE ="vnd.android.cursor.dir/vnd."+AUTHORITY;
/*单项数据*/
private static final String CONTNET_TYPE_ITEM ="vnd.android.cursor.item/vnd."+AUTHORITY ;
/**
* 夸进程时发生在工作线程
*
* @param uri
* @return
*/
@Nullable
@Override
public String getType(Uri uri) {
Log.i(TAG, "getType: current thread: " + Thread.currentThread().getName());
switch (sUriMatcher.match(uri)){
case USERINFO_CODE:
case COMPANY_CODE:
return CONTENT_TYPE;
case USERINFO_ITEM_CODE:
case COMPANY_ITEM_CODE:
return CONTNET_TYPE_ITEM;
default:
throw new RuntimeException("错误的 uri");
}
}
接着来看 他的query 和 insert方法:
/**
* 夸进程时发生在工作线程
*
* @param uri
* @param projection
* @param selection
* @param selectionArgs
* @param sortOrder
* @return
*/
@Nullable
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
Log.i(TAG, "query: current thread: " + Thread.currentThread().getName());
Cursor cursor = null;
switch (sUriMatcher.match(uri)) {
case USERINFO_CODE:
cursor = mDatabase.query(UserInfoDbHelper.TABLE_USER_INFO, projection, selection, selectionArgs, null, null, sortOrder);
break;
case USERINFO_ITEM_CODE:
String tel = uri.getPathSegments().get(1);
cursor = mDatabase.query(UserInfoDbHelper.TABLE_USER_INFO, projection, "tel_num = ?", new String[]{tel}, null, null, sortOrder);
break;
case COMPANY_CODE:
cursor = mDatabase.query(UserInfoDbHelper.TABLE_COMPANY, projection, selection, selectionArgs, null, null, sortOrder);
break;
case COMPANY_ITEM_CODE:
String cid = uri.getPathSegments().get(1);
cursor = mDatabase.query(UserInfoDbHelper.TABLE_COMPANY, projection, "id = ?", new String[]{cid}, null, null, sortOrder);
break;
}
return cursor;
}
/**
* 夸进程时发生在工作线程
*
* @param uri
* @param values
* @return
*/
@Nullable
@Override
public Uri insert(Uri uri, ContentValues values) {
Log.i(TAG, "insert: current thread: " + Thread.currentThread().getName());
long newId = 0;
Uri newUri = null;
switch (sUriMatcher.match(uri)) {
case USERINFO_CODE:
newId = mDatabase.insert(UserInfoDbHelper.TABLE_USER_INFO, null, values);
newUri = Uri.parse("content://" + AUTHORITY + "/" + UserInfoDbHelper.TABLE_USER_INFO + "/" + newId);
break;
case COMPANY_CODE:
newId = mDatabase.insert(UserInfoDbHelper.TABLE_COMPANY, null, values);
newUri = Uri.parse("content://" + AUTHORITY + "/" + UserInfoDbHelper.TABLE_COMPANY + "/" + newId);
break;
}
if (newId > 0) return newUri;
throw new IllegalArgumentException("Failed to insert row info" + uri);
}
可以看到,利用UriMatcher得到要怎样查询,然后代用了 database的方法。
最后说一个方法:
@Nullable
@Override
public Bundle call(String method, String arg, Bundle extras) {
return super.call(method, arg, extras);
}
可以利用这个方法,扩展出一些查询方式。
最后我们来看以下在清单文件中的注册:
<provider
android:authorities="com.blueberry.test08.provider"
android:name=".SimpleContentProvider"
android:permission="com.blueberry.permission.provider"
android:process="com.blueberry.process1"
android:multiprocess="false"
>
</provider>
这里主要的字段为 authorities ,他是ContentProvider的唯一标识。
permission,它分为 读权限,和写权限 对应为 android:readpermission 和
android:writepermission 。 multiprocess如果设置为true标识每个调用进程都拥有一个示例,负责只有所有进程只有一个示例。process字段使得它运行在一个名为com.blueberry.process1的进程中。
最后我们来看一下调用程序:
public class MainActivity extends AppCompatActivity {
private EditText etUserDesc,etUserPhoneNumber,etUserCompanyId;
private EditText etCompanyId,etCompanyBussiness,etCompanyAddress ;
private Button btnSubmitUserInfo,btnSubmitCompany;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etUserDesc = (EditText) findViewById(R.id.et_user_desc);
etUserPhoneNumber = (EditText) findViewById(R.id.et_user_phone_number);
etUserCompanyId = (EditText) findViewById(R.id.et_user_company_id);
etCompanyId = (EditText) findViewById(R.id.et_company_id);
etCompanyBussiness = (EditText) findViewById(R.id.et_company_bussiness);
etCompanyAddress = (EditText) findViewById(R.id.et_company_address);
btnSubmitUserInfo = (Button) findViewById(R.id.btn_save_userinfo);
btnSubmitCompany = (Button) findViewById(R.id.btn_save_company);
btnSubmitUserInfo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//存数用户信息数据
saveUserInfoRecord();
btnSubmitUserInfo.postDelayed(new Runnable() {
@Override
public void run() {
queryUserInfo();
}
},1000);
}
});
btnSubmitCompany.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
saveCompanyInfo();
btnSubmitCompany.postDelayed(new Runnable() {
@Override
public void run() {
queryCompanyInfo();
}
},1000) ;
}
});
}
/**
* 通过电话号码查询相关信息
*/
private void queryUserInfo() {
Uri queryUri = Uri.parse("content://com.blueberry.test08.provider/userinfo/123456") ;
Cursor cursor = getContentResolver().query(queryUri,
new String[]{UserInfoDbHelper.DESC_COLUMN,UserInfoDbHelper.COMP_ID_COLUMN,UserInfoDbHelper.TEL_COLUMN}
,null,null,null);
if(cursor.moveToFirst()){
Toast.makeText(this,
" 描述信息"+cursor.getString(0)
+" 公司id"+cursor.getString(1)
+" 电话来自"+cursor.getString(2),Toast.LENGTH_SHORT).show();
}
cursor.close();
}
/**
* 存储用户信息到ContentProvider
*/
private void saveUserInfoRecord() {
ContentValues newRecord = new ContentValues();
newRecord.put(UserInfoDbHelper.DESC_COLUMN,etUserDesc.getText().toString());
newRecord.put(UserInfoDbHelper.COMP_ID_COLUMN,etUserCompanyId.getText().toString());
newRecord.put(UserInfoDbHelper.TEL_COLUMN,etUserPhoneNumber.getText().toString());
getContentResolver().insert(SimpleContentProvider.USERINFO_CONTENT_URI,newRecord) ;
}
private void saveCompanyInfo() {
ContentValues newRecord = new ContentValues();
newRecord.put(UserInfoDbHelper.ID_COLUMN,etCompanyId.getText().toString());
newRecord.put(UserInfoDbHelper.BUSINESS_COLUMN,etCompanyBussiness.getText().toString());
newRecord.put(UserInfoDbHelper.ADDR_COLUMN,etCompanyAddress.getText().toString());
getContentResolver().insert(SimpleContentProvider.COMPANY_CONTENT_URI,newRecord);
}
private void queryCompanyInfo(){
Cursor cursor = getContentResolver().query(SimpleContentProvider.COMPANY_CONTENT_URI,
new String[]{UserInfoDbHelper.ID_COLUMN,UserInfoDbHelper.BUSINESS_COLUMN,UserInfoDbHelper.ADDR_COLUMN}
,null,null,null);
StringBuffer sb = new StringBuffer();
while (cursor.moveToNext()){
sb.append("id: "+cursor.getString(0)+" business: "+cursor.getString(1)+" address: "+cursor.getString(2));
sb.append("\n");
}
Toast.makeText(this,sb.toString(),Toast.LENGTH_LONG).show();
}
}
布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.blueberry.test08.MainActivity">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/et_user_desc"
android:hint="请输入用户描述信息"
android:contentDescription="用户描述信息"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/et_user_phone_number"
android:hint="输入用户电话号码"
android:contentDescription="用户电话号码"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/et_user_company_id"
android:hint="用户公司id"
android:contentDescription="用户公司id"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/btn_save_userinfo"
android:text="存储用户信息"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/et_company_id"
android:hint="公司id"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/et_company_bussiness"
android:hint="请输入公司业务"
android:contentDescription="公司业务"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/et_company_address"
android:hint="请输入公司地址"
android:contentDescription="请输入公司地址"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/btn_save_company"
android:text="保存公司信息"
/>
</LinearLayout>