欢迎莅临 SUN WU GANG 的园子!!!

世上无难事,只畏有心人。有心之人,即立志之坚午也,志坚则不畏事之不成。

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  470 随笔 :: 0 文章 :: 22 评论 :: 30万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

ContentProvider

ContentProvider用于实现数据共享.

ContentProvider是不同应用程序之间进行数据交换的标准API,其以某种Uri的形式对外提供数据,允许其他应用程序访问或修改数据;

其他应用程序使用ContentResolver根据Uri去访问操作指定数据。

注意:ContentProvider为android四大组件之一,需要在AndroidMainfest.xml中做配置处理。

如果把ContentProvider当做一个网站,那么完成的开发一个ContentProvider的操作步骤如下:

1.定义自己的ContentProvider类,该类需要继承android提供的ContentProvider基类;

2.向android系统注册这个“网站”,也就是在AndroidMainfest.xml文件中注册这个ContentProvider——就像注册Activity一样。注册ContentProvider需要为其绑定一个URL.

注意:

向android系统中注册ContentProvider只要在<application.../>元素中添加子元素即可,如下所示:

当我们向android系统注册了ContentProvider之后,其他应用程序就可通过Uri来访问DictProvider所暴露的数据了。

那么DictPovider到底如何暴露其提供的数据?

==》

由于应用程序对数据的操作无非就是CRUD,因此DictProvider除了需要继承ContentProvider之外,还需要提供如下几个方法:

public boolean onCreate()

该方法在ContentProvider创建后被调用,当其他应用程序第一次访问ContentProvider时,该ContentProvider会被创建出来,

并立即回调该onCreate()

public Uri insert(Uri uri,ContentValues values) 根据Uri插入values对应的数据
public int delete(Uri uri,String selection,String[] selecttionArgs) 根据Uri删除select条件所匹配的所有记录
publc int update(Uri uri,ContentValues values,String selection,Sting[] selecttionArgs) 根据Uri修改select条件所匹配的所有记录
public Cursor query(Uri uri,Sting[] projection,String selection,Sting[] selectionArgs,String sortOrder) 根据Uri查询select条件所匹配的所有记录,其中projection就是一个列名列表,表明只选择出指定的列的数据列
public String getType(Uri uri) 该方法用于返回当前Uri所代表的数据的MIME类型。如果该Uri对应数据可能包括多条记录,那么MIME类型字符串应该以vnd.android.cursor.dir/开头;如果该Uri对应的数据只包含一条记录,那么返回MIME类型字符串应该以vnd.android.cursor.item/开头

 

 

 

 

 

 

 

 

 

 

 

Uri简介

网页URL,如:https://www.baidu.com/s?tn=baidutop...

1.http://——URL协议部分,只要通过HTTP协议来访问网站,该部分为固定信息;

2.www.baidu.com——网站域名部分,只要通过http协议来访问网站,该部分总是固定信息;

3.s?tn=baidutop...——网站资源部分, 当访问者需要访问不同资源时,这个部分是动态改变的。

 

Android Uri因此类似,如下:

content://org.crazyit.providers.dictprovider/words

其也可分为三个部分:

1.content://,这个不是android规定的,是固定的;

2.org.crazyit.providers.dictprovider,这个部分就是ContentProvider的authority.系统就是由这个部分来找到操作那个ContentProvider.只要访问指定的ContentProvider,这个部分就是固定的;

3.words,资源部分或者说是数据部分,当访问者需要访问不同资源时,这个部分是动态改变的。

注意:

需要指出的是,Android的Uri所能表达的功能更丰富,还可以支持如下Uri:

content://org.crazyit.providers.dictprovider/words/2——此时需要访问的资源为words/2,其意味着访问words数据中ID为2的记录的word字段。

content://org.crazyit.providers.dictprovider/words——访问全部数据;

 

大部分使用ContentProvider所操作的数据都来自于数据库,但有时候这些数据也可以来自于文件、XML或网络等其他存储方式,此时支持的Uri也可改为如下形式:

content://org.crazyit.providers.dictprovider/word/detail/——代表操作word节点下的detail节点;

 

为了将一个字符串转换成Uri,Android提供的Uri工具类提供了parse()静态方法,转换方式如下:

Uri uri = Uri.parse("content://org.crazyit.providers.dictprovider/words/2");

 

使用ContentResolver操作数据

ContentProvider相当于一个“网站”,它的作用是暴露可供操作的数据;

其他程序则通过ContentResolver来操作ContentProvider所暴露的数据;ContentResolver相当于HttpClient.

Content提供了如下方法来获取ContentResolver对象:getContentResolver().

获取ContentResolver对象成功后,可通过如下方法操作数据:

insert(Uri uri,ContentValues values) 向Uri对应的ContentProvider中插入values对应的数据
delete(Uri uri,String where,Sting[] selectionArgs) 删除uri对应的ContentProvider中where提交匹配的数据
update(Uri uri,ContentValues values,String where,String[] selectionArgs) 更新uri对应的ContentProvider中where提交匹配的数据
query(Uri uri,Sting[] projection,String selection,String[] selectionArgs,String sortOrder) 查询Uri对应的ContentProvider中where提交匹配的数据

 

 

 

 

 

 

 注意:一般来说,ContentProvider是单实例模式的,当多个应用程序通过ContentResolver来操作ContentProvider提供的数据时,ContentResolver

调用的数据操作将会委托给同一个ContentProvider处理。

 

操作系统的ContentProvider

使用ContentProvider操作数据的操作步骤:

1.调用Activity的ContentResolver()获取ContentResolver对象

2.根据需要调用ContentResolver的insert()、delete()、update()、query方法操作数据即可

注意:操作系统提供的ContentResolver,需要了解其对应的ContentProvider对应的Uri.

 

使用ContentProvider管理联系人

Android系统提供了Contacts应用程序来管理联系人,而且Android系统还为联系人管理提供了ContentProvider,这就运行其他应用程序以ContentResolver来管理联系人数据。

Android系统对联系人管理ContentProvider的几个Uri如下:

ContactsContact.Contacts.CONTENT_URI 管理联系人的Uri
ContactsContact.CommonDataKinds.Phone.CONTENT_URI 管理联系人的电话的Uri
ContactsContact.CommonDataKinds.Email.CONTENT_URI 管理联系人的邮箱的Uri

 

 

 

 

实例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
布局文件main.xml==>
<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=".MainActivity" >
 
    <Button
        android:id="@+id/btnQuery"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="查询" />
 
</LinearLayout>
 
result.xml==>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
 
    <ExpandableListView
        android:id="@+id/list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="#ffffff"
        android:cacheColorHint="#00000000"
        android:listSelector="#00000000" >
    </ExpandableListView>
 
</LinearLayout>
 
AndroidMainfest.xml==>
 <uses-permission android:name="android.permission.READ_CONTACTS" />
 <uses-permission android:name="android.permission.WRITE_CONTACTS" />
 
代码实现==》
package com.example.myprovidercontent1;
 
import java.util.ArrayList;
 
import android.os.Bundle;
import android.provider.ContactsContract;
import android.app.Activity;
import android.app.AlertDialog;
import android.database.Cursor;
import android.database.DataSetObserver;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.AbsListView;
import android.widget.AbsListView.LayoutParams;
import android.widget.Button;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.TextView;
 
public class MainActivity extends Activity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        Button btnQuery = (Button) this.findViewById(R.id.btnQuery);
        btnQuery.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                query(v);
            }
        });
    }
 
    private void query(View v)
    {
        // 定义两个List封装系统联系人信息、指定联系人的电话号码、Email等...
        final ArrayList<String> names = new ArrayList<String>();
        final ArrayList<ArrayList<String>> details = new ArrayList<ArrayList<String>>();
        // 使用ContentResolver查找联系人数据
        Cursor cursor = this.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
                null, null, null, null);
        // 遍历查询结果,获取系统中所有联系人
        while (cursor.moveToNext())
        {
            // 联系人Id、名称
            String contactId = cursor.getString(cursor
                    .getColumnIndex(ContactsContract.Contacts._ID));
            String name = cursor.getString(cursor
                    .getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
            names.add(name);
            Log.i("swg", "name:" + name);
            // 联系人电话号码
            Cursor phones = this.getContentResolver()
                    .query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
                            ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + contactId,
                            null, null);
            final ArrayList<String> detail = new ArrayList<String>();
            // 遍历查询结果,获取该联系人的多个 电话号码
            while (phones.moveToNext())
            {
                String phoneNum = phones.getString(phones
                        .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                Log.i("swg", "电话号码:" + phoneNum);
                detail.add("电话号码:" + phoneNum);
            }
            phones.close();
 
            // 使用ContentResolver查询联系人Email
            Cursor emails = this.getContentResolver()
                    .query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null,
                            ContactsContract.CommonDataKinds.Email.CONTACT_ID + "=" + contactId,
                            null, null);
            // 遍历查询结果,获取该联系人的多个Email地址
            while (emails.moveToNext())
            {
                String emailAdd = emails.getString(emails
                        .getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
 
                Log.i("swg", "邮件地址:" + emailAdd);
                detail.add("邮件地址:" + emailAdd);
            }
            emails.close();
 
            details.add(detail);
        }
        cursor.close();
 
        // 加载result.xml界面布局文件
        View resultDialog = this.getLayoutInflater().inflate(R.layout.result, null);
        ExpandableListView list = (ExpandableListView) resultDialog.findViewById(R.id.list);
        // 创建一个ExpandableListAdapter对象
        ExpandableListAdapter adapter = new ExpandableListAdapter()
        {
            @Override
            public void unregisterDataSetObserver(DataSetObserver observer)
            {
            }
 
            @Override
            public void registerDataSetObserver(DataSetObserver observer)
            {
            }
 
            @Override
            public void onGroupExpanded(int groupPosition)
            {
            }
 
            @Override
            public void onGroupCollapsed(int groupPosition)
            {
            }
 
            @Override
            public boolean isEmpty()
            {
                return false;
            }
 
            @Override
            public boolean isChildSelectable(int groupPosition, int childPosition)
            {
                return true;
            }
 
            @Override
            public boolean hasStableIds()
            {
                return true;
            }
 
            // 该方法决定每个组选项的外观
            @Override
            public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
                    ViewGroup parent)
            {
                TextView tv = getTextView();
                tv.setText(getGroup(groupPosition).toString());
                return tv;
            }
 
            @Override
            public long getGroupId(int groupPosition)
            {
                return groupPosition;
            }
 
            @Override
            public int getGroupCount()
            {
                // details
                return names.size();
            }
 
            @Override
            public Object getGroup(int groupPosition)
            {
                // details
                return names.get(groupPosition);
            }
 
            @Override
            public long getCombinedGroupId(long groupId)
            {
                return 0;
            }
 
            @Override
            public long getCombinedChildId(long groupId, long childId)
            {
                return 0;
            }
 
            @Override
            public int getChildrenCount(int groupPosition)
            {
                return details.get(groupPosition).size();
            }
 
            private TextView getTextView()
            {
                AbsListView.LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
                        64);
                TextView tv = new TextView(MainActivity.this);
                tv.setLayoutParams(lp);
                tv.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.LEFT);
                tv.setPadding(36, 0, 0, 0);
                tv.setTextSize(20);
                return tv;
            }
 
            // 该方法决定每个子项的外观
            @Override
            public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
                    View convertView, ViewGroup parent)
            {
                TextView tv = getTextView();
                tv.setText(getChild(groupPosition, childPosition).toString());
                return tv;
            }
 
            @Override
            public long getChildId(int groupPosition, int childPosition)
            {
                return childPosition;
            }
 
            @Override
            public Object getChild(int groupPosition, int childPosition)
            {
                return details.get(groupPosition).get(childPosition);
            }
 
            @Override
            public boolean areAllItemsEnabled()
            {
                return false;
            }
        };
        // 为ExpandableListView设置Adapter
        list.setAdapter(adapter);
        // 使用对话框来显示查询结果
        new AlertDialog.Builder(MainActivity.this).setView(resultDialog)
                .setPositiveButton("确定", null).show();
    }
}

 实例二、添加联系人

 

posted on   sunwugang  阅读(333)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示