android content provider(内容提供者) 学习总结
2016-09-08 09:19
337 查看
**
当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,而使用ContentProvider共享数据的好处是统一了数据访问方式。
简单直白的说就是把一个应用的数据暴露给其他应用使用,不过实际开发中一般不会把自己应用的数据暴露出来,所以往往是使用该类访问系统的短信 联系人等应用数据
**
短信备份和向短信应用的数据库中插入短信
配置文件如下
布局文件layout(使用了fragment)
具体的实现类 copy()方法和insert()实现了相应的类
读取联系人和插入联系人
*这里要注意联系人的数据库是比较特殊的,标识用户的主键是存放在contacts表中,联系人的信息是以列的形式存放在data表中data1列中,区分各个信息是使用mimetype列的值
*小细节
还有就是联系人的id在两张表里的名称也是一样,在contacts表中叫做contact_id,在data表中是raw_contact_id。一定要注意***。*
代码如下
实现类 contactsResolver
联系人的javaBean对象
布局文件
配置文件
content provider 是什么?干什么?
**当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,而使用ContentProvider共享数据的好处是统一了数据访问方式。
简单直白的说就是把一个应用的数据暴露给其他应用使用,不过实际开发中一般不会把自己应用的数据暴露出来,所以往往是使用该类访问系统的短信 联系人等应用数据
**
小实验
**短信备份和向短信应用的数据库中插入短信
配置文件如下
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.alleged.smsoperate" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" /> <uses-permission android:name="android.permission.READ_SMS" /> <uses-permission android:name="android.permission.WRITE_SMS"/> <!-- 在SDCard中创建与删除文件权限 --> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <!-- 往SDCard写入数据权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".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> </application> </manifest>
布局文件layout(使用了fragment)
<!-- A DrawerLayout is intended to be used as the top-level content view using match_parent for both width and height to consume the full space available. --> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.alleged.smsoperate.MainActivity" > <!-- As the main content view, the view below consumes the entire space available using match_parent in both dimensions. --> <FrameLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" /> <!-- android:layout_gravity="start" tells DrawerLayout to treat this as a sliding drawer on the left side for left-to-right languages and on the right side for right-to-left languages. If you're not building against API 17 or higher, use android:layout_gravity="left" instead. --> <!-- The drawer is given a fixed width in dp and extends the full height of the container. --> <fragment android:id="@+id/navigation_drawer" android:name="com.alleged.smsoperate.NavigationDrawerFragment" android:layout_width="@dimen/navigation_drawer_width" android:layout_height="match_parent" android:layout_gravity="start" tools:layout="@layout/fragment_navigation_drawer" /> </android.support.v4.widget.DrawerLayout> <RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android: 4000 paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.alleged.smsoperate.MainActivity$PlaceholderFragment" > <TextView android:id="@+id/section_label" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:id="@+id/insertSms" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/section_label" android:layout_centerHorizontal="true" android:layout_marginTop="49dp" android:text="插入短信" android:onClick="insert" /> <Button android:id="@+id/copySms" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/insertSms" android:layout_below="@+id/insertSms" android:layout_marginTop="111dp" android:text="短信备份" android:onClick="copy" /> </RelativeLayout> <ListView 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:background="#cccc" android:choiceMode="singleChoice" android:divider="@android:color/transparent" android:dividerHeight="0dp" tools:context="com.alleged.smsoperate.NavigationDrawerFragment" />
具体的实现类 copy()方法和insert()实现了相应的类
package com.alleged.smsoperate; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import org.xmlpull.v1.XmlSerializer; import android.app.Activity; import android.support.v7.app.ActionBarActivity; import android.util.Xml; import android.support.v7.app.ActionBar; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.view.Gravity; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.support.v4.widget.DrawerLayout; import android.widget.ArrayAdapter; import android.widget.TextView; public class MainActivity extends ActionBarActivity implements NavigationDrawerFragment.NavigationDrawerCallbacks { /** * Fragment managing the behaviors, interactions and presentation of the * navigation drawer. */ private NavigationDrawerFragment mNavigationDrawerFragment; /** * Used to store the last screen title. For use in * {@link #restoreActionBar()}. */ private CharSequence mTitle; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mNavigationDrawerFragment = (NavigationDrawerFragment) getSupportFragmentManager() .findFragmentById(R.id.navigation_drawer); mTitle = getTitle(); // Set up the drawer. mNavigationDrawerFragment.setUp(R.id.navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout)); } //点击后向系统短信应用插入一条短信 public void insert(View v){ /* 实现逻辑 * 实现内容解析者 * 创建出来ContentValues对象承载内容*/ //具体实现 Uri uri = Uri.parse("content://sms/"); ContentValues newSms = new ContentValues(); //这里的key代表你要插入数据库表的列名 values代表要插入的值 newSms.put("address", "13054569999"); newSms.put("body", "晚上小树林见"); newSms.put("date", System.currentTimeMillis()); //通过内容解析者调用系统的短信的插入方法 getContentResolver().insert(uri, newSms); System.out.println("插入成功"); } /*短信备份 * 实现逻辑 * 通过ContentResolver对象(内容解析器)调用查询方法 * 把查询到的结果保存到xml文件中 * */ public void copy(View v){ try { //1 判断保存短信的xml文件是否存在,不存在就创建 File file = new File(Environment.getExternalStorageDirectory().getPath(),"smsbackup.xml"); if(!file.exists()){ try { file.createNewFile(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //获取文件的输出流 FileOutputStream fos = new FileOutputStream(file); //获取XmlSerializer类对象帮助操作文件 XmlSerializer xmlserializer = Xml.newSerializer(); //设置序列化参数 xmlserializer.setOutput(fos, "utf-8"); //设置文档的开头 xmlserializer.startDocument("utf-8", true); //写xml的根节点 第一个参数是命名空间 是节点名 xmlserializer.startTag(null, "smss"); //构建url Uri uri = Uri.parse("content://sms/"); //第一个参数代表从那里查 2 代表查询的列 3 代表查询的条件 4代表查询的参数 5 排序方式 Cursor reslut = getContentResolver().query(uri, new String[]{"address","date","body"}, null, null, null); while(reslut.moveToNext()){ xmlserializer.startTag(null, "sms"); String address = reslut.getColumnName(0); String date = reslut.getColumnName(1); String body = reslut.getColumnName(2); xmlserializer.startTag(null, "address"); xmlserializer.text(address); xmlserializer.endTag(null, "address"); xmlserializer.startTag(null, "date"); xmlserializer.text(date); xmlserializer.endTag(null, "date"); xmlserializer.startTag(null, "body"); xmlserializer.text(body); xmlserializer.endTag(null, "body"); xmlserializer.endTag(null, "sms"); } xmlserializer.endTag(null, "smss"); xmlserializer.endDocument(); fos.close(); System.out.println("备份完成"); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } // } @Override public void onNavigationDrawerItemSelected(int position) { // update the main content by replacing fragments FragmentManager fragmentManager = getSupportFragmentManager(); fragmentManager.beginTransaction().replace(R.id.container, PlaceholderFragment.newInstance(position + 1)) .commit(); } public void onSectionAttached(int number) { switch (number) { case 1: mTitle = getString(R.string.title_section1); break; case 2: mTitle = getString(R.string.title_section2); break; case 3: mTitle = getString(R.string.title_section3); break; } } public void restoreActionBar() { ActionBar actionBar = getSupportActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); actionBar.setDisplayShowTitleEnabled(true); actionBar.setTitle(mTitle); } @Override public boolean onCreateOptionsMenu(Menu menu) { if (!mNavigationDrawerFragment.isDrawerOpen()) { // Only show items in the action bar relevant to this screen // if the drawer is not showing. Otherwise, let the drawer // decide what to show in the action bar. getMenuInflater().inflate(R 11d2a .menu.main, menu); restoreActionBar(); return true; } return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } /** * A placeholder fragment containing a simple view. */ public static class PlaceholderFragment extends Fragment { /** * The fragment argument representing the section number for this * fragment. */ private static final String ARG_SECTION_NUMBER = "section_number"; /** * Returns a new instance of this fragment for the given section number. */ public static PlaceholderFragment newInstance(int sectionNumber) { PlaceholderFragment fragment = new PlaceholderFragment(); Bundle args = new Bundle(); args.putInt(ARG_SECTION_NUMBER, sectionNumber); fragment.setArguments(args); return fragment; } public PlaceholderFragment() { } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_main, container, false); return rootView; } @Override public void onAttach(Activity activity) { super.onAttach(activity); ((MainActivity) activity).onSectionAttached(getArguments().getInt(ARG_SECTION_NUMBER)); } } }
读取联系人和插入联系人
*这里要注意联系人的数据库是比较特殊的,标识用户的主键是存放在contacts表中,联系人的信息是以列的形式存放在data表中data1列中,区分各个信息是使用mimetype列的值
*小细节
还有就是联系人的id在两张表里的名称也是一样,在contacts表中叫做contact_id,在data表中是raw_contact_id。一定要注意***。*
代码如下
package com.alleged.contacts; import android.support.v7.app.ActionBarActivity; import java.util.List; import com.alleged.ContentResolver.contactsResolver; import com.alleged.javaBean.contacts; import android.content.Context; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends ActionBarActivity { private Context context; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); context = this; /* * 业务逻辑 创建出来一个类,提供两个方法,查看联系人返回一个集合 插入一个联系人,返回boolean */ } //插入联系人 从控件上取得值传入到contactsResolver 的insert方法中实现添加 public void insertContacts(View v) { EditText name = (EditText) findViewById(R.id.contactsName); EditText phone = (EditText) findViewById(R.id.contactsPhone); EditText email = (EditText) findViewById(R.id.contactsEmail); String contactsname = name.getText().toString().trim(); String contactsphone = phone.getText().toString().trim(); String contactsemail = email.getText().toString().trim(); if (contactsemail != null && contactsname != null && contactsphone != null) { contactsResolver re = new contactsResolver(context); boolean success = re.insert(contactsname, contactsphone, contactsemail); if (success) { Toast.makeText(context, "添加成功", 0).show(); } else { Toast.makeText(context, "添加失败", 0).show(); } }else{ Toast.makeText(context, "添加内容为空", 0).show(); } } public void lookContacts(View v) { List<contacts> list = new contactsResolver(context).look(); if (!list.isEmpty()) { for (contacts item : list) { System.out.println(item.getName() + "\t" + item.getPhone() + "\t" + item.getEmail()); } } else { System.out.println("联系人为空"); } } @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; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
实现类 contactsResolver
package com.alleged.ContentResolver; import java.util.ArrayList; import java.util.List; import com.alleged.javaBean.contacts; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.net.Uri; public class contactsResolver { private Context context; public contactsResolver(Context context) { this.context = context; } public boolean insert(String name,String phone,String email){ //把传过来的数据插入到数据库中 /*业务逻辑 * [1]先往row_contacts表插入数据 contact_id [2]在往data表里面插入数据 data1 */ Uri uri = Uri.parse("content://com.android.contacts/raw_contacts"); Uri dauri = Uri.parse("content://com.android.contacts/data"); //插入contact_id前先查询有多少条数据,contact_id就是数据量加一 ContentResolver contentResolver = context.getContentResolver(); Cursor couser = contentResolver.query(uri, null, null, null, null); int id = couser.getCount()+1; ContentValues values = new ContentValues(); //插入联系人的id values.put("contact_id",id); //先向row_contacts表添加上联系人 contentResolver.insert(uri, values); //把name phone email添加到data ContentValues content = new ContentValues(); content.put("data1", name); //☆ ☆ ☆ ☆ ☆ 插入的数据要告诉数据库 属于第几条联系人 和 数据类型 content.put("raw_contact_id", id); content.put("mimetype", "vnd.android.cursor.item/name"); context.getContentResolver().insert(dauri, content); ContentValues phoneValues = new ContentValues(); phoneValues.put("data1", phone); phoneValues.put("mimetype", "vnd.android.cursor.item/phone_v2"); phoneValues.put("raw_contact_id", id); contentResolver.insert(dauri, phoneValues); ContentValues emailValues = new ContentValues(); emailValues.put("data1", email); emailValues.put("mimetype", "vnd.android.cursor.item/email_v2"); emailValues.put("raw_contact_id", id); contentResolver.insert(dauri, emailValues); return true; } public List<contacts> look() { if(context!=null){ // 1 查询row_contacts表的 contact_id列 获取到共有多少个联系人对象 ContentResolver contacts = context.getContentResolver(); // 第一个参数 要查看的数据库的某张表 第二个 查询的列 第三个 查询的条件 第四个 查询的方式 第五个 排序方式 Uri uri = Uri.parse("content://com.android.contacts/raw_contacts"); List<contacts> list = new ArrayList<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()) { // 取得当前的联系人id String contact_id = cursor.getString(0); if(contact_id!=null){ contacts Contact = new contacts(); // 如果联系人id 不为空 查询data表 取得数据 Cursor datacursor = contacts.query(datauri, new String[] { "data1", "mimetype" }, "contact_id=?", new String[] { contact_id }, null); while (datacursor.moveToNext()) { String data1 = datacursor.getString(0); String mimetype = datacursor.getString(1); 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); } } list.add(Contact); } } return list; }else{ System.out.println("context is null!!"); return null; } } }
联系人的javaBean对象
package com.alleged.javaBean; public class contacts { private String name; private String phone; private String email; 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; } }
布局文件
<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:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context="com.alleged.contacts.MainActivity" > <EditText android:id="@+id/contactsName" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入联系人姓名" /> <EditText android:id="@+id/contactsPhone" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入电话号码" /> <EditText android:id="@+id/contactsEmail" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入联系人邮箱" /> <Button android:id="@+id/insertContacts" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:onClick="insertContacts" android:text="添加联系人" /> <Button android:id="@+id/lookContacts" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:onClick="lookContacts" android:text="查看联系人"/> </LinearLayout>
配置文件
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.alleged.contacts" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" /> <!-- 读写联系人权限 --> <uses-permission android:name="android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS" /> <uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="android.permission.WRITE_CONTACTS"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".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> </application> </manifest>
相关文章推荐
- 第九天 Android学习总结(内容提供者)
- android开发学习(四)——内容提供者
- Androidx学习笔记(81)--- 内容提供者(ContentProvider)
- 【android学习】四大组件-Content Provider(内容提供者)
- Android 内容提供者、解释者和观察者学习笔记
- Android Studio 学习Demo内容及一些bug处理技巧 -----个人技术文档,两次冲刺总结
- Android学习九 ContentProvider内容提供者相关
- Android学习之内容提供者ContentProvider
- android 学习随笔二十一(内容提供者 )
- 创建一个内容提供者Creating a Content Provider——翻译总结自developer.android.com
- Android四大组件之内容提供者Content Provider总结
- Android Content Provider内容提供者的学习笔记
- Android(java)学习笔记246:ContentProvider使用之学习ContentProvider(内容提供者)的目的
- Android基础总结.doc(第三节、 ListView和内容提供者)
- android基础学习12——内容提供者ContentProvider的使用
- Android内容提供者ContentProvider总结
- Android学习总结(九)———— 内容提供器(ContentProvider)
- Android个人每天总结.doc(day04四大组件之:内容提供者ContentProvider)
- Androidx学习笔记(82)--- 内容提供者(ContentProvider)-自定义内容提供者
- Android之内容提供者ContentProvider的总结