Android 学习笔记之ContentProvider实现数据共享....

PS:最近听老师说打算让我参与企业的app制作,让我加快学习的进度...好吧,貌似下周还有考试...貌似实验室这个app也要做...暂时不管了...那就只能加快进度了,感觉略微的有点激动和紧张,总算是可以开始对项目进行着手操作了...学的东西还是很少,还要继续努力啊...搞定Android的网络通信后就可以正式的进入项目开发了...不说废话了...

学习内容:

1.使用ContentProvider存储数据

2.操作联系人的ContentProvider...

3.多媒体信息的ContentProvider...

ContentProvider:

  ContentProvider类是一个实现数据共享的一个类,它将共享的数据进行包装,然后对外暴露接口,外界的应用程序就能通过接口来访问被封装的数据,从而达到数据共享的目的...使用这个类需要了解一些其他的东西...

Uri:

  在使用ContentProvider对数据进行操作的时候,以Uri的形式进行数据交换...Uri包含两个部分,一部分包含着我们要操作的ContentProvider..另一部分包括的是对ContentProvider中哪一个数据进行操作...

Uri uri=Uri.parse("content://com.example.contentprovider/person");//这个Uri表示访问person表中的所有记录...

UriMatcher:

  在使用ContentProvider类操作某一种方法的时候有可能传递多种Uri,必须对这些传递的Uri进行相应的判断才能够决定如何去操作...可以使用switch语句进行判断...

    UriMatcher match =new UriMatcher(No_MATCH);//对象的实例化操作...NO_MATCH表示-1...
    match.addURI("包名","表名",匹配码)..
    match.addURI("content://com.example.contentprovider","person",1);//增加一个URI值
   /* 如果match方法匹配content://content.example.contentprovider/person/5     * 那么返回值就是2...
    */
    mathc.addURI("content://com.example.contentprovider","person/#",2);//#为通配符......

ContentUris:

  由于所有的数据操作都要通过Uri的形式进行传递,那么当执行完增加操作之后,我们往往想要返回我们增加后数据的ID以Uri的形式进行返回,那么就可以使用这个类来完成操作...

数据共享:

  如果想实现数据共享,我们可以自己定义自己的ContentProvider...定义以后重写其内部的方法,不过这种方式一般都是没有任何的必要的..因为Android提供了多种类型的ContentProvider(图片,音频,视频,联系人等)...这些类都是它所提供的,因此我们只需要把数据封装这些类中,然后就可以完成数据的共享...因此一般我们都是将数据写入到系统提供的类中,完成数据的共享....

联系人的ContentProvider...

  一般当我们在打电话或者是发短信的时候会使用到联系人这一数据信息,因此这个联系人内部的数据信息必须要进行共享,才使得其他的应用程序获取联系人信息...因此我们需要把数据写入到ContentProvider中....我们在模拟器中或者是自己的手机中也可以,添加几条联系人...然后我们通过触发按钮的形式来获取我们保存的数据信息...这个还需要配置一下权限,在AndroidManifest.xml文件中加入<user-permission android:name="android.permission.READ_CONTACTS"/>....布局文件一个按钮,一个文本显示控件...很简单....主要还是实现过程...

import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends Activity implements View.OnClickListener {

    private TextView tv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.but).setOnClickListener(this);
        findViewById(R.id.but_1).setOnClickListener(this);
        tv=(TextView) findViewById(R.id.text);
    }

    @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 void onClick(View v) {
        // TODO Auto-generated method stub
        switch(v.getId()){
        case R.id.but:
            StringBuilder st=getContents();//定义一个StringBuilder对象...表示st是一个可变的字符串...这里也可以使用StringBuffered...但是使用StringBuider更快...
            tv.setText(st.toString());
            break;
         }   }
  private StringBuilder getContents(){
        StringBuilder stlog=new StringBuilder();
        ContentResolver cr=this.getContentResolver();//操作ContentProvider首先要利用getContentResolver()获取ContentResolver实例..
        Cursor cursor=cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);//用Cursor来保存结果...
       /* cr.query(uri, projection, selection, selectionArgs, sortOrder)
        * uri参数:表示的是对哪个数据表进行操作..
        * projection参数:表示在表中需要选取的列值..
        * selection参数:表示的是查询的条件...相当于where子句..
        * selectionArgs参数:表示语句中是否有?...
        * sortorder参数:表示查询的结果按照什么形式进行排列...
        * 查询的结果返回给Cursor对象...按行进行排列数据...
        * */
               for(cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()){
        //这里cr按行来保存每一条获取的数据...我们可以对想要的数据进行一一获取..
            int nameIndex=cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);//这句话的意思表示获取联系人的名字...内容在ContactsContract.Contacts中...
            String name=cursor.getString(nameIndex);
            stlog.append("name= "+name+";");
            String contentid=cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));//获取联系人的ID信息...
                 //由于一个人可能有多个手机号码...因此还需要Cursor对多个号码进行保存...ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = "+contenti 这一参数来限制必须是同一个ID下的电话号码..说白了就是限制号码必须是一个人的...
            Cursor phonecursor=cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = "+contentid, null, null);
            while(phonecursor.moveToNext()){
                String strphone=phonecursor.getString(phonecursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                stlog.append("phone="+ strphone+";");
            }
   //            phonecursor.close();  这句话在模拟器上可以使用...我们动态关闭...
    //这个也一样可能有多个email....
            Cursor email=cr.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null, ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = "+contentid, null, null);
            while(email.moveToNext()){
                String stremail=email.getString(email.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
                stlog.append("email="+stremail+";");
            }
            /*
             *  if(Build.VERSION.SDK_INT < 14) {
             *   cursor.close();
             *   }
             *   Android真机超过4.0以后的版本无法使用close()方法来关闭程序...否则会出现崩溃现象... 但是在模拟器上可以运行... 可以使用上面的函数进行判断是否已经超过4.0版本...
             * */
//            email.close();
//            cursor.close();
        }
        return stlog;

    }

}
<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" >

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <Button
        android:id="@+id/but"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:text="获取信息..."/>
    <Button
        android:id="@+id/but_1"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:text="增加信息..."/>

</LinearLayout>

  这里我们只是获取我们保存的数据信息,同时我们可以添加联系人,然后将数据保存在联系人中...插入数据就需要使用到ContentValues这个类,将插入的数据信息保存在其中...最后通过insert方法来完成数据的插入操作...这样就完成了数据的插入操作...

    Uri uri=Uri.parse("content://com.android.contacts/raw_contacts");
            ContentResolver resolver_1=this.getContentResolver();
            ContentValues values=new ContentValues();
            //获取主键值...
            long contactid=ContentUris.parseId(resolver_1.insert(uri, values));
            uri=Uri.parse("content://com.android.contacts/data");
            values.put("raw_contact_id",contactid);
            values.put("mimetype", "vnd.android.cursor.item/name");
            values.put("data2", "aa");
            resolver_1.insert(uri, values);
            values.clear();
            values.put("raw_contact_id", contactid);
            values.put("mimetype", "vnd.andoroid.cursor.item/phone_v2");
            values.put("data2", "2");
            values.put("data1", "1131313");
            resolver_1.insert(uri, values);
            values.clear();
            values.put("raw_contact_id", contactid);
            values.put("mimetype", "vnd.android.cursor.item/email_v2");
            values.put("data2", "2");
            values.put("data1", "[email protected]");
            resolver_1.insert(uri, values);                

多媒体信息的ContentProvider...

  多媒体的ContentProvider和联系人的基本都差不多,基本的模式都差不多,多媒体的ContentProvider也是需要首先获取ContentValues实例..然后才能进行增删改查等操作...查询一般使用query(uri,Prjs,Selections,selectArgs,Order)..方法来查询然后进行保存...查询的URI接收几个系统参数...这几个系统参数表示的是几个URI,这几个URI分别表示的是存储在手机内部或者是外部的图片内容,音频内容,或者是视频内容的URI...通过传递参数,我们就可以获取到手机里的图片,音频,或者是视频...

  通过一个简单的例子来说一下多媒体信息的ContentProvider...然后实现多媒体数据信息的共享...这个例子就是获取手机里的音乐的基本信息...主布局...

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/msg"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        android:text="所有音乐"
        android:textSize="20dp"
        android:gravity="center"/>
    <TableLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <TableRow >
            <TextView
                android:layout_height="wrap_content"
                android:layout_width="150px"
                android:textSize="15px"
                android:text="歌曲名"/>
            <TextView
                android:layout_height="wrap_content"
                android:layout_width="100px"
                android:textSize="15px"
                android:text="歌手"/>
            <TextView
                android:layout_width="50px"
                android:layout_height="wrap_content"
                android:textSize="15px"
                android:text="时间"/>
        </TableRow>
    </TableLayout>
    <ListView
        android:id="@+id/songlist"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

    </ListView>

</LinearLayout>

  这个布局没什么好说的...重点还是如何实现获取音乐的基本信息...这是实现的过程...在这里调用了另一个布局文件...调用另一个布局文件来显示获取到的数据信息...这种方式非常的常用...另一个布局文件...

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    <TableRow >
        <TextView
            android:id="@+id/title"
            android:layout_height="wrap_content"
            android:layout_width="150px"
            android:textSize="15px"/>
        <TextView
            android:id="@+id/name"
            android:layout_height="wrap_content"
            android:layout_width="100px"
            android:textSize="15px"/>
        <TextView
            android:id="@+id/time"
            android:layout_width="50px"
            android:layout_height="wrap_content"
            android:textSize="15px"/>

    </TableRow>

</TableLayout>
package com.example.contentprovidermedia;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.media.MediaPlayer;
import android.os.Bundle;
import android.provider.MediaStore;
import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;

public class MainActivity extends Activity {

    private List<Map<String,String>>list=new ArrayList<Map<String,String>>();
    private SimpleAdapter simpleadapter;
    private ListView listview;
    private String songname;
    private String songtime;
    private String songwriter;
    private int  Alltime;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listview=(ListView) findViewById(R.id.songlist);
        listview.setOnItemClickListener(new OnItemClickListener() {

            private MediaPlayer media;
            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
                /*
                 * 这个实现方法简单的说一下...parent表示的这个整体的列表,这个列表保存在适配器中...
                 * view表示的是列表中被选择的子选项...position表示被点击的定位...id表示的是被点击的行数...
                 * 这里表示的是当列表的某一行没触发时需要进行的操作...我定义的操作是,当点击到列表的某一行的时候
                 * 这个音乐将进行播放操作...
                 * */
                // TODO Auto-generated method stub
                Map<String,String>map=(Map<String, String>) MainActivity.this.simpleadapter.getItem(position);
                String songtitle=map.get("title");
                String songname=map.get("name");
                String songtime=map.get("time");
                String songpath=map.get("path");
                palysong(songpath);
            }
            private void palysong(String songpath) {
                // TODO Auto-generated method stub
                this.media=new MediaPlayer();
                media.reset();
                try {
                    media.setDataSource(songpath);
                } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (SecurityException 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();
                }
                try {
                    media.prepare();
                } catch (IllegalStateException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                media.start();
            }
        });

        ContentResolver resolver=this.getContentResolver();
       /* resolver.query(uri, projection, selection, selectionArgs, sortOrder)
        * uri参数:表示的是对哪个数据表进行操作..
        * projection参数:表示在表中需要选取的列值..
        * selection参数:表示的是查询的条件...相当于where子句..
        * selectionArgs参数:表示语句中是否有?...
        * sortorder参数:表示查询的结果按照什么形式进行排列...
        * 查询的结果返回给Cursor对象...按行进行排列数据...
        * */
        Cursor cursor=resolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,  null, null, null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
        if(cursor==null){
            Toast.makeText(MainActivity.this, "没有找到相应的数据", Toast.LENGTH_SHORT).show();
        }else{
            for(cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToLast()){
                songname=cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE));//获取音乐的名字信息..
                songwriter=cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST));//获取音乐的作者...
                Alltime=cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION));//获取音乐的时长...以毫秒为单位...
                songtime=settime(Alltime);
                Map<String,String>map=new HashMap<String, String>();//用一个Map来保存数据...
                map.put("title", songname);
                map.put("songwriter", songwriter);
                map.put("maptime", songtime);
                list.add(map);//将map存入到List中...
                /*
                 *  这里使用了一个简单的适配器...
                 *  new SimpleAdapter(context,data,resource,from,to);这是适配器的构造方法...
                 *    context  SimpleAdapter关联的View的运行环境
                 *    data    一个Map组成的List。在列表中的每个条目对应列表中的一行,每一个map中应该包含所有在from参数中指定的键
                 *    resource    一个定义列表项的布局文件的资源ID。布局文件将至少应包含那些在to中定义了的ID
                 *    from          一个将被添加到Map映射上的键名
                 *    to     将绑定数据的视图的ID,跟from参数对应,这些应该全是TextView
                 *
                 * */
                this.simpleadapter=new SimpleAdapter(this,list, R.layout.songlist, new String[]{"title","name","time"},new int[]{R.id.title,R.id.name,R.id.time});
                listview.setAdapter(simpleadapter);//设置适配器...
            }
        }
    }

    private String settime(int time){
        time/=1000;
        int minute=time/60;
        int second=time%60;
        minute %=60;
        return String.format("%02d:%02d", minute,second);

    }
    @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;
    }

}

  ContentProvider的东西很多,也很杂,其重要的作用还是实现数据的共享,掌握了如何使用这个类来完成数据共享,那么目的就达到了...主要还是掌握如何去实现应用之间去调用共享的数据...

 

时间: 2024-10-10 09:24:31

Android 学习笔记之ContentProvider实现数据共享....的相关文章

Android学习笔记之ContentProvider

读取其他应用程序共享的数据 以下示例为读取联系人信息 package com.jiahemeikang.helloandroid; import com.jiahemikang.service.EchoService; import com.jiahemikang.service.EchoService.EchoServiceBingder; import com.jikexuyua.broadcastreceiver.MyBC; import android.os.Bundle; import

Android学习笔记-----------内容提供者

Android学习笔记-----------内容提供者 简介 内容提供者主要用于在不同的程序之间实现数据共享的功能;一个程序想要访问其他程序种由内容提供者提供的数据,必须依赖于contentresolver这个类的实例,可以通过getContentResolver()这个方法来获取这个类的实例;这个类提供有query(),insert(),update(),delete()等方法来操作数据这些方法都需要提供个Uri类型的参数,这个Uri对应的就是你需要操作的数据引用.一个uri主要由以以下几个部

udacity android 学习笔记: lesson 4 part b

udacity android 学习笔记: lesson 4 part b 作者:干货店打杂的 /titer1 /Archimedes 出处:https://code.csdn.net/titer1 联系:1307316一九六八 声明:本文採用下面协议进行授权: 自由转载-非商用-非衍生-保持署名|Creative Commons BY-NC-ND 3.0 ,转载请注明作者及出处. tips:https://code.csdn.net/titer1/pat_aha/blob/master/Mar

Android学习笔记(四八):提供自己的Content Provider

在上一次的学习中,采用了原生的内容提供者Contact,Contact有多层映射关系,比较复杂,并非作为小例子的好选择,在本次学习中,我们将学习如何建立Content Provider,并通过Uri进行增删改查.如果应用的数据只需自己使用,并不需要content provider,相反避免这样做,可直接访问数据:但是若希望数据可以被其他应用访问,创建content provider就是常规手段. 再谈Content Provider的Uri 在上一次学习中,我们谈到了Uri的格式.现在已cont

Android学习笔记(四九):通过Content Provider访问数据

在上次笔记中,我们编写了自己的Provider,这次笔记,我们将通过Content Provider的Uri接口对数据进行访问,重写Android学习笔记(四二)中例子.在这里我们不在充分描述相关UI如何编写,可以到笔记(四二)中详细查看,重点讲述如何实现数据的访问. 读取信息 读取信息方式,在笔记(四七)中已经介绍,代码如下 private voidread(){     /* 通过managedQuery读取,第1参数表示URI, 第2参数表示所需读取的信息,第3个参数是限制条件,类似SQL

Android学习笔记二

17. 在ContentProvider中定义的getType()方法是定义URI的内容类型. 18. SQLiteDatabase类中的insert/delete/update/query方法其实也挺好用的,我在EquipmentProvider类中做了实现 19. Android专门有个单元测试项目(Android Test Project),在这个项目中,可以新建一个继承AndroidTestCase类的具体测试类来单元测试某个功能.我新建了一个AndroidTestProject项目,在

【转】Pro Android学习笔记(五):了解Content Provider(上)

Content Provider是抽象数据封装和数据访问机制,例如SQLite是Android设备带有的数据源,可以封装到一个content provider中.要通过content provider进行读写,需要使用URI.推荐阅读Android学习笔记(四七):Content Provider初谈和Android联系人信息.Android学习笔记(四八):提供自己的Content Provider和Android学习笔记(四九):通过Content Provider访问数据.Content

udacity android学习笔记: lesson 3

udacity android学习笔记: lesson 3 作者:干货店打杂的 /titer1 /Archimedes 出处:https://code.csdn.net/titer1 联系:1307316一九六八 声明:本文采用以下协议进行授权: 自由转载-非商用-非衍生-保持署名|Creative Commons BY-NC-ND 3.0 ,转载请注明作者及出处. tips:https://code.csdn.net/titer1/pat_aha/blob/master/Markdown/an

【转】Pro Android学习笔记(七):了解Content Provider(下上)

我们通过一个Content Provider小例子进行详细说明.数据源是一个SQLite数据库,名字为books.db,该数据库只含有一个表格,名字为books.表格中含有name,isbn,author,created_date和modified_date几列.我们通过一个名为BookProvider的内容提供者将数据源运行封装,并对外提供增删改查的接口. 首先:定义Content Provider的结构 创建一个Provider,我们首先需要定义好这个provider的结构.通过consta