首先我们的引入安卓的四大组件之一的Contentprovider,内容提供者,负责数据的搬运。跨程序的通信,主要有提供者和获取者。

例如首先介绍提供方:首先创了contentprider提供方可以把数据库的数据提供出来:首先继承ContentProvider,

有五个方法重写:


public class Myprider extends ContentProvider {
    @Override
    public boolean onCreate() {
        return false;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        return null;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        return null;
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        return null;
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
        return 0;
    }
}


2.第二步在清单里对contentprovider进行注册:


自定义权限,注意这里的第一个参数的意思是

authorities:是一个唯一标示,通过这个东西可以找到contentprider,名字自己取
name:是自己的包名+类名;
第三个参数设置为true:可以保证外部程序访问成功;
permission:这是自己定义的权限。


<provider
    android:authorities="com.wj.class"
    android:name=".db.Myprider"
    android:exported="true"
    android:permission="android.permission.READ_WJ_DB"
    />
注意这里提供者添加了权限,则需要在清单里注册权限:
<permission
    android:description="@string/wj_db"    android:icon="@mipmap/ic_launcher_round"    android:label="@string/app_name"    android:name="READ_WJ_DB"    android:protectionLevel="normal"    />//第一个参数description是权限的描述,如果你失败了这会谈出这句话。注意这里需要@string
<string name="wj_db">wj close the door</string>

//第二个是直接填app名字即可,第三个是权限的名字:包名+刚才的权限名字

READ_WJ_DB,第四个是权限的等级:normol最低默认。这里就注册了权限,你自定义的权限就生效了
3.介绍一下uri
uri代表了要操作的数据,是一个路径。由两部分组成,第一部分是说你代表一个什么样的contentprovider,第二个是说对contentprovider什么样的数据进行操作(音乐,通讯录等等),
下面就是Uri和它的介绍



这里的person代表数据库的意思。

首先我们来看一个提供者如何拿到数据库,对数据库插入一条数据:

刚才重写了ContentProvider这个类,里面的


public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {


首先我们需要在这里进行格式判断,比如用户只需要进行找到student数据库,只插入name值,或者只是id,又或者两个都要添加


//只name的格式

// 首先要判断一个uri 格式//content:// com.wj.class/student/name
//既有name又有id的格式



// 格式//content:// com.wj.class/student/id/name
if(uri.equals("//content:// com.wj.class/student/id/name)"))
{
//接着我们要对进行赋值调用Contentvalues的方法
int id= values.getAsInteger("id");
      String st=values.getAsString("name");
     String sql="insert into student values("+id+","+st+")";
       db.execSQL(sql);     }

return null; }


注意这里必须的对数据库初始化:datebse哪里来的呢



SQLiteDatabase db;
//这里直接把数据库的获取放在Oncreate里边
@Override
public boolean onCreate() {
    db = new Mydbhelper(getContext()).getWritableDatabase();
    return false;
}




这是重写的第二个方法,用来取数据,在这里默认给我一个uri我给你取所有数据。


@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
    //首先你需要传一个uri进行判断是否符合我的要求,如果不是则返回null

   if(uri.equals("content:// com.wj.class/student"))
{
    String sq = "select * from student";
    Cursor cursor = db.rawQuery(sq, null);

    return cursor;
}else
    {
        return null;
    }}




写到这里一个Contentprovider提供者就写好了

 下面要开始写一个获取者,获取数据,获取方。看下面代码:


public class LocalActivity extends AppCompatActivity {
    ArrayList<String> pathName = new ArrayList<String>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_local);
//       File file= Environment.getDataDirectory();
//        String  str=Environment.DIRECTORY_MUSIC;
//       File str1=Environment.getExternalStorageDirectory();
//        Log.e("msg",""+file);
//        Log.e("msg",""+str);
//        Log.e("msg",""+str1);

//        String sql = "insert into student values(1,'zzz')";
//        db.execSQL(sql);

//首先是通过当前activty获取ContentResover来获取当前的获取的对象。
        ContentResolver contentResolver=this.getContentResolver();
//然后填写你要拿的uri
        Uri uri=Uri.parse("content://com.wj.class/student");//出入数据的地址
//查询方法生成一个游标对象,下面就是对游标进行判断索引。
        Cursor cursor=contentResolver.query(uri,null,null,null,null);

        if (cursor.moveToNext()) {
            //代表第几列拿
          int id=cursor.getInt(0);
            //通过列名拿
            int id1=cursor.getInt(cursor.getColumnIndex("id"));
            String name=cursor.getString(1);
            Log.e("msg","id"+id+"id1"+id1+"name"+name);

        }else
            {
                Log.e("msg","游标失败");
            }
    }




}


后面出现报错说明需要添加权限这个,就是刚才自定义的


<uses-permission android:name="android.permission.READ_WJ_DB"/>
同时要特别注意填写的uri,用getpath()获取到的是后面的数据库和资源并非全名称所以应该直接uri.equals()就可以,好了

4.刚才我们拿到是自己的数据库,现在我们要拿手机上的系统音乐数据库:

首先要找到系统的uri是什么:

MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
这个就是系统的uri音乐地址:然后通过Uri类进行生成对象
Uri uri1=MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;下一步调用获取方法,获取方法是这个 ContentResolver contentResolver=this.getContentResolver();//调用这个query()方法,同时要添加提供者要的参数后面的四个null; Cursor cursor=contentResolver.query(uri,null,null,null,null);//改成下面这个信息,具体信息,包括歌曲的各种信息,这是在提供方里面已经定义好了的Cursor cursor=contentResolver.query(uri1,
        new String[]{MediaStore.Audio.Media._ID,    //写入我想要获得的信息(列)
        MediaStore.Audio.Media.TITLE,
        MediaStore.Audio.Media.ALBUM,
        MediaStore.Audio.Media.DISPLAY_NAME,
        MediaStore.Audio.Media.ARTIST,
        MediaStore.Audio.Media.DURATION,
        MediaStore.Audio.Media.SIZE,
        MediaStore.Audio.Media.DATA},null,null,null);//下面通过游标把提供方的东西取出来看下
if(cursor!=null)
{
    while(cursor.moveToNext())
    {
        long id = cursor.getLong(0);
        String title = cursor.getString(1);
        String album = cursor.getString(2);
        String displayName = cursor.getString(3);
        String artist = cursor.getString(4);
        long duration = cursor.getLong(5);
        long size = cursor.getLong(6);
        String url = cursor.getString(7);   //转存数据
        Log.e("msg",""+id+""+title+""+ album+""+displayName+""+artist+""+duration
        +""+size+""+url);
    }
}



这个就是拿到的歌曲信息包括

下面把拿到的歌曲放到自己的集合中在这里需要:

这样首先创了一个类:用集合对象


MusicInfo



public class MusicInfo
{
    private long id;
    private String title;
    private String album;
    private  String displayName;
    private  String artist;
    private long duration;
    private  long size;
    private  String url;


    public MusicInfo() {

    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAlbum() {
        return album;
    }

    public void setAlbum(String album) {
        this.album = album;
    }

    public String getDisplayName() {
        return displayName;
    }

    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

    public String getArtist() {
        return artist;
    }

    public void setArtist(String artist) {
        this.artist = artist;
    }

    public long getDuration() {
        return duration;
    }

    public void setDuration(long duration) {
        this.duration = duration;
    }

    public long getSize() {
        return size;
    }

    public void setSize(long size) {
        this.size = size;
    }
}
MusicInfo musicInfo = new MusicInfo();
ArrayList<MusicInfo>  mMusicInfos = new ArrayList< MusicInfo>();
musicInfo.setTitle(title);
musicInfo.setId(id);
musicInfo.setAlbum(album);
musicInfo.setArtist(artist);
musicInfo.setSize(size);
musicInfo.setDisplayName(displayName);
musicInfo.setDuration(duration);
musicInfo.setUrl(url);  //存到数据单元

mMusicInfos.add(musicInfo);  //添加到List
//下面我们把它迭代出来:看到的结果
for(MusicInfo musicInf : mMusicInfos) {
    Log.e("msg",""+musicInf.getDisplayName());
}