安卓基础总结 内容提供者

1.使用内容提供者读写短信信息

(1)将短信内容读出并写入XML文件

API


    ContentResolver contentResolver = getContentResolver();
    //getContentResolver();是上下文中携带的方法,用于处理内容提供者提供的访问方式。
寻找哪个内容提供者需要用通过uri,uri路径分文 "主机名"+"具体要操作的数据"   其中"主机名"在提供数据库程序的清单文件中定义,"具体要操作的数据"在这个程序的源码中(一般文件名有provide字样),
我们可以通过查找"UriMatcher"函数搜索相关的信息。

读取短信例程

提供权限   读写短信  操作SD卡:
    <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"/>


    public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

    public void click(View v)
    {
        ContentResolver contentResolver = getContentResolver();

        //通过查找TelephonyProvider程序的清单文件和源码可知,主机名为"sms" 后面为空则对应SMS_ALL
        Uri uri = Uri.parse("content://sms/");

        //使用ContentResolver提供的查询方法,查找短信相关信息
        Cursor cursor = contentResolver.query(uri, new String[]{"address", "body"}, null, null, null);

        //将cursor指向的内容封装到xml文件中
        OutputStream os;
        try {
            os = new FileOutputStream(Environment.getExternalStorageDirectory().getPath()+"/msmInfo.xml");

            XmlSerializer serializer = Xml.newSerializer();

            serializer.setOutput(os, "utf-8"); 
            serializer.startDocument("utf-8", true);

            serializer.startTag(null, "info");

            while(cursor.moveToNext())
            {
                serializer.startTag(null, "sms");

                serializer.startTag(null, "address");
                String address = cursor.getString(0);
                serializer.text(address);
                serializer.endTag(null, "address");

                serializer.startTag(null, "body");
                String body = cursor.getString(1);
                serializer.text(body);
                serializer.endTag(null, "body");

                serializer.endTag(null, "sms");
            }

            serializer.endTag(null, "info");
            serializer.endDocument();

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    }

(2)将自定义信息写入短信程序下的数据库中

写入短信例程

    public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void click(View v)
    {
        ContentResolver contentResolver = getContentResolver();

        Uri uri = Uri.parse("content://sms/");

        //写入列名及其对应的值
        ContentValues values = new ContentValues();
        values.put("address", "110");
        values.put("body", "hello chenchen");

        contentResolver.insert(uri, values);
    }
    }

2.使用内容提供者读写联系人信息

背景知识

1.data表中存储联系人的所有信息
2.通过mimetype                    来区分信息对应的类型
3.通过raw_contact_id(即联系人的id)来区分不同信息对应的联系人

1.读取联系人信息模板 例程

    public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void click(View v)
    {
        ContentResolver contentResolver = getContentResolver();

        //用于处理raw_contacts表格的uri
        Uri uri_raw = Uri.parse("content://com.android.contacts/raw_contacts");

        //用于处理data表格的uri
        Uri uri_data = Uri.parse("content://com.android.contacts/data");

        //查出raw_contacts表格中所有id号,也就是用户id
        Cursor cursor = contentResolver.query(uri_raw, new String[]{"contact_id"}, null, null, null);

        while(cursor.moveToNext())
        {
            //获得一个contact_id号
            String contact_id = cursor.getString(0);

            System.out.println("  contact_id:"+contact_id);

            //查找data1表中所有contact_id为当前id的内容       ************注意此处为"mimetype"而不是直接写表中的"mimetype_id",此处是一个视图
            Cursor cursor_data1 = contentResolver.query(uri_data, new String[]{"mimetype", "data1"}, "raw_contact_id=?", new String[]{contact_id}, null);

            while(cursor_data1.moveToNext())
            {
                //查出当前行的mime类型,从而确定当前data1列的数据的类型
                String mimetype = cursor_data1.getString(0);
                System.out.println("*************mimetype*"+mimetype+"*****************");
                String data = cursor_data1.getString(1);
                System.out.println("*************data1*"+data+"*****************");

                if("vnd.android.cursor.item/name".equals(mimetype)){
                    System.out.println("******name:"+data+"********");
                }else if("vnd.android.cursor.item/phone_v2".equals(mimetype)){
                    System.out.println("******phone:"+data+"********");
                }else if("vnd.android.cursor.item/email_v2".equals(mimetype)){
                    System.out.println("******email:"+data+"********");
                }
            }
        }
    }
    }

将上述代码封装成一个工具类,用于获取联系人信息

public class ReadContactUtils {

    /**
     * 获取本机通讯录信息,返回通讯录中每个条目的List
     * @param context   传入上下文,用于获取ContentResolver内容解析者
     * @return
     */
    public static List<Contact> getContacts(Context context)
    {
        List<Contact> list = new ArrayList<Contact>(); 
        Contact contact=null;

        ContentResolver contentResolver = context.getContentResolver();

        Uri uri_raw = Uri.parse("content://com.android.contacts/raw_contacts");
        Uri uri_data1 = Uri.parse("content://com.android.contacts/data");

        Cursor cursor = contentResolver.query(uri_raw, new String[]{"contact_id"}, null, null, null);//由于要返回所有的条目,所以不需要写后面的参数

        while(cursor.moveToNext())
        {
            //从raw_contact_id表中获取contact_id
            String contact_id = cursor.getString(0);            
            //System.out.println("*******"+contact_id+"********");
            if(contact_id != null)
            {
                contact = new Contact();

                //使用contact_id查出data表中对应的所有对应项  ,这些对应项就是一个联系人的所有信息
                Cursor cursor_data1 = contentResolver.query(uri_data1, new String[]{"mimetype", "data1"}, "raw_contact_id=?" ,new String[]{contact_id}, null);
                while(cursor_data1.moveToNext())
                {
                    //获取表的数据的类型
                    String mimetype = cursor_data1.getString(0);
                    String data1 = cursor_data1.getString(1);

                    //System.out.println("****mimetype*"+mimetype+"******data1*"+data1+"****");
                    //根据不同类型找到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);
                    }

                }
            }
            list.add(contact);
        }
        return list;
    }
    }

2.写入联系人信息 例程

注意应当先在raw_contact_id表中加入新的contact_id,然后再添加data2中的各项信息。否则data2中不能插入信息。

    public void click(View v)
    {
        String name = et_name.getText().toString().trim();
        String email = et_email.getText().toString().trim();
        String phone = et_phone.getText().toString().trim();

        ContentResolver contentResolver = getContentResolver();

        Uri uri_raw = Uri.parse("content://com.android.contacts/raw_contacts");
        Uri uri_data1 = Uri.parse("content://com.android.contacts/data");

        //看看raw_contact_id中的contact_id到第几条了
        Cursor cursor = contentResolver.query(uri_raw, null, null, null, null);
        int count = cursor.getCount();
        int id = count+1;

        //在raw_contact_id表中加入新信息的contact_id
        ContentValues idValues = new ContentValues();
        idValues.put("contact_id", id);
        contentResolver.insert(uri_raw, idValues);

        //分别加入信息中的每个行
        ContentValues contentValues = new ContentValues();

        contentValues.put("raw_contact_id", id);
        contentValues.put("mimetype", "vnd.android.cursor.item/name");
        contentValues.put("data1", name);
        contentResolver.insert(uri_data1, contentValues);

        contentValues.put("raw_contact_id", id);
        contentValues.put("mimetype", "vnd.android.cursor.item/phone_v2");
        contentValues.put("data1", phone);
        contentResolver.insert(uri_data1, contentValues);

        contentValues.put("raw_contact_id", id);
        contentValues.put("mimetype", "vnd.android.cursor.item/email_v2");
        contentValues.put("data1", email);
        contentResolver.insert(uri_data1, contentValues);
    }

3.内容观察者ContentObserver

public class MainActivity extends Activity {

    private Uri uri;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        uri = Uri.parse("content://sms");

        //第二个参数的解释  为true可以是不精确的路径   为false必须是精确路径
        //notifyForDescendents If true changes to URIs beginning with uri will also cause 
        //notifications to be sent. If false only changes to the exact URI specified by uri 
        //will cause notifications to be sent. If true, than any URI values at or below the 
        //specified URI will also trigger a match.

        getContentResolver().registerContentObserver(uri, true, new MyObeserver(new Handler()));
    }

    class MyObeserver extends ContentObserver
    {

        public MyObeserver(Handler handler) {
            super(handler);

        }

        //发现监视路径下的数据库发生变化就会调用此方法         
        @Override
        public void onChange(boolean selfChange) {

            //把短信的address 和  body内容取出来
            Cursor cursor = getContentResolver().query(uri, new String[]{"address","body"}, null, null, "date desc");
            cursor.moveToFirst();
            String address = cursor.getString(0);
            String body = cursor.getString(1);

            System.out.println("body:"+body+"address:"+address);

            super.onChange(selfChange);
        }
    }
    }

4.内容提供者的原理简析

前几个条目主要说了我们如何获取其他数据的数据库信息,使用的是内容解析者提供的方法来对其他程序的数据库进行操作。

下面我们看一下数据库提供方程序是如何工作的。

1.同四大组件中其他的三个一样,也是继承一个类(ContentProvider),并为这个类在清单文件中配置一下。我们需要实现其中的增删改查方法。

public class MyContentProvider extends ContentProvider {

    @Override
    public boolean onCreate() {
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
    }

    @Override
    public String getType(Uri uri) {

        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {

    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {

    }
    }

    清单文件   name : 内容提供者的路径
              authorities : 内容提供者的主机名 

     <provider android:name="com.example.readprivatedata.MyContentProvider"
            android:authorities="com.example.myprovider">
    </provider>


2.有了增删改查的方法,但是我们去操作哪站表,或者哪张表中的哪些数据呢?者就需要我们配置另外一个参数,用于找到对应的数据。我们使用**UriMatcher**类进行操作。

    private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);

    //参数分别为   主机名   要操作的数据的标识   该标识对应的数字
    matcher.addURI("com.example.myprovider", "info", INFO); 


    当我们进行增删改查操作时,从完整uri,通过match方法获取code码,每个code码对应操作不同的数据

    int code = matcher.match(uri);获取当前uri对应的code码  

例程

内容提供者

    public class MyContentProvider extends ContentProvider {

    //用于匹配调用哪个函数
    private static final int INFO = 1;

    private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
    private MyOpenHelper helper;

    static{ 
        //可以为matcher添加多个uri,用于操作不同的数据
        matcher.addURI("com.example.myprovider", "info", INFO);
    }

    @Override
    public boolean onCreate() {
        //创建这个Provider时创建数据库,后面有这个类的源码   其中包含一张名为"info"的表格
        helper = new MyOpenHelper(getContext());
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {

        //获取code码
        int code = matcher.match(uri);

        System.out.println("query******code:"+code+"*******");

        //当code码和我们为某个数据预定义的code一样时,就进行对应的操作
        if(code == INFO)
        {
            System.out.println("*******query********");

            SQLiteDatabase db = helper.getReadableDatabase();
            Cursor cursor = db.query("info", projection, selection, selectionArgs, null, null, sortOrder);
            return cursor;
        }else {

            throw new IllegalArgumentException("query路径不匹配 请检查");
        }

    }

    @Override
    public String getType(Uri uri) {

        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {

        int code = matcher.match(uri);

        System.out.println("insert******code:"+code+"*******");
        if(code == INFO)
        {
            System.out.println("*******insert********");

            //匹配成功 
            SQLiteDatabase db = helper.getReadableDatabase();
            //代表插入到了多少行 
            long insert = db.insert("info", null, values);
            return Uri.parse("com.itheima.account.provider"+insert); 
        }else {

            throw new IllegalArgumentException("insert路径不匹配 请检查");
        }

    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {

        int code = matcher.match(uri);

        System.out.println("delete******code:"+code+"*******");
        if(code == INFO)
        {
            System.out.println("*******delete********");

            SQLiteDatabase db = helper.getReadableDatabase();
            int delete = db.delete("info", selection, selectionArgs);
            //删除了多少行

            return delete;
        }else {
            throw new IllegalArgumentException("3路径不匹配 请检查");

        }
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {

        int code = matcher.match(uri);

        System.out.println(" update******code:"+code+"*******");
        if(code == INFO)
        {
            System.out.println("*******update********");

            SQLiteDatabase db = helper.getReadableDatabase();
            int update = db.update("info", values, selection, selectionArgs);
            //删除了多少行

            return update;
        }else {
            throw new IllegalArgumentException("4路径不匹配 请检查");

        }
    }
    }


    创建数据库的类

    public class MyOpenHelper extends SQLiteOpenHelper {

    public MyOpenHelper(Context context) {
        super(context, "account.db", null, 1);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {       
        db.execSQL("create table info (_id integer primary key autoincrement,name varchar(20),money varchar(20))");
        //初始化2条数据
        db.execSQL("insert into info ('name','money') values ('张三','2000')");
        db.execSQL("insert into info ('name','money') values ('李四','5000')");           
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

        System.out.println("onUpgrade");        
    }
    }

内容解析者

    public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void click_insert(View v)
    {
        ContentValues contentValues = new ContentValues();
        contentValues.put("name", "haha");
        contentValues.put("money", 10000);

        //注意,uri决定了要操作的表,内容提供者在调用insert方法时,根据uri对应的code只找到相应的分支,这个分支对应的操作是操作info指定的数据
        getContentResolver().insert(Uri.parse("content://com.example.myprovider/info"), contentValues);
    }

    public void click_delete(View v)
    {
        getContentResolver().delete(Uri.parse("content://com.example.myprovider/info"), "name=?", new String[]{"haha"});
    }

    public void click_update(View v)
    {

    }

    public void click_find(View v)
    {

    }
    }
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是Android入门知识点的总结: 1. Android基础知识: - Android是一个基于Linux的开源操作系统,主要用于移动设备。 - Android应用程序使用Java编程语言开发。 - Android应用程序由多个组件组成,包括活动(Activity)、服务(Service)、广播接收器(Broadcast Receiver)和内容提供者(Content Provider)。 2. Android应用程序的生命周期: - 活动(Activity)是Android应用程序的用户界面的基本构建块。活动有不同的生命周期状态,如创建、启动、暂停、恢复和销毁。 - 活动的生命周期由回调方法控制,如onCreate()、onStart()、onResume()、onPause()、onStop()和onDestroy()。 3. Android布局: - Android应用程序使用XML文件定义用户界面布局。 - 常用的布局类型包括线性布局(LinearLayout)、相对布局(RelativeLayout)、帧布局(FrameLayout)和约束布局(ConstraintLayout)。 4. Android资源管理: - Android应用程序使用资源文件来存储图像、字符串、颜色等非代码资源。 - 资源文件存储在res目录下,可以通过资源ID在代码中访问。 5. Android意图(Intent): - 意图用于在不同组件之间传递数据和执行操作。 - 显式意图(Explicit Intent)用于启动特定的组件,如活动。 - 隐式意图(Implicit Intent)用于执行系统级操作,如拨打电话、发送短信等。 6. Android存储: - Android应用程序可以使用内部存储和外部存储来保存数据。 - 内部存储用于保存应用程序私有数据,如数据库文件。 - 外部存储用于保存公共数据,如图片、音频和视频文件。 7. Android网络通信: - Android应用程序可以使用HTTP协议进行网络通信。 - 可以使用Android提供的HttpClient类或者使用第三方库,如OkHttp、Volley等。 8. Android数据库: - Android应用程序可以使用SQLite数据库进行数据存储。 - SQLite是一种轻量级的关系型数据库,适用于移动设备。 9. Android权限管理: - Android应用程序需要在清单文件中声明所需的权限。 - 权限用于保护用户的隐私和设备的安全。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值