前言:
内容提供者是安卓应用程序的主要基石之一,其目的是为应用程序提供内容。它们封装数据,然后通过一个ContentResolver接口
将封装的数据提供给应用程序;如果你想要在多个应用中去共享数据,那么只需要一个内容提供者就可以了;例如:联系人的数据
是被多个应用所共享的,所以这个数据必须存储在一个内容提供者中;如果你不想在多个应用中去共享这个数据,那么你可以
通过SQLite数据库来实现;
当通过一个ContentResolver来发送一个请求时,系统会检查这个给定的URI的权限,然后将这个URI传递给这个内容提供者,只要内容
提供者想要的话,内容提供者是可以解析剩余的URI的;UriMatcher有助于去解析URI;
以下是一些需要被实现的方法:
onCreate():当初始化一个provider的时候,这个方法就会被调用;
query(Uri, String[], String, String[], String):这个是用来返回数据给调用者;
insert(Uri, ContentValues):这个是用来插入数据到内容提供者中;
update(Uri, ContentValues, String, String[]):更新内容提供者中的数据;
delete(Uri, String, String[]):删除内容提供者中的数据;
getType(Uri):在内容提供者中返回一个MIME类型的数据;
Note:
数据访问的方法(insert(Uri, ContentValues)和update(Uri, ContentValues, String, String[])),同一时刻,也许会被多个线程所调用,
所以在使用时应该注意一下其线程安全的问题;其他的方法(比如:onCreate())则只会被应用的主线程调用,所以在这里必须去避免
一些耗时的操作;
本示例的演示的是:
在自定义的内容提供者这个应用的MainActivity中写入一个文件,与此同时,并这个应用中提供一个内容提供者,
供其他应用程序通过这个内容提供者去访问这个应用的文件
在访问内容提供者的应用中,通过获取ContentResolver对象来向自定义内容提供者应用的文件写入数据;以此来达到
学习内容提供者的目的;
代码示例如下:
自定义内容提供者
MainActivity.java
package com.example.administrator.testascontentprovider; import android.os.Bundle; import android.os.Environment; import android.support.v7.app.AppCompatActivity; import android.util.Log; import java.io.File; import java.io.IOException; /*** * 在本示例中,我们先让这个应用生成一个文件,然后 * 通过外部应用借助本应用的ContentProvider来实现 * 对本应用文件的写入操作; * ***/ public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ /*** * 1> * new File()的时候,若文件不存在,其并不会去闯进一个文件, * 此时需要调用file.create()来创建这个文件; * 2> * getFilesDir()是在本应用的目录下去创建文件,如这个示例所示, * 其所创建的文件的路径如下: * /data/data/com.example.administrator.testascontentprovider/files/Content.txt * * 3> * 在操作SD卡时,记得其相应权限的添加 * **/ File file = new File(getFilesDir(),"Content.txt"); if(file.exists()){ Log.e("file","exist"); }else { try { file.createNewFile(); if(file.exists()){ Log.e("file",file.getAbsolutePath()); }else { Log.e("file","create failed"); } } catch (IOException e) { e.printStackTrace(); } } } } }
MyContentProvider.java
package com.example.administrator.testascontentprovider; import android.content.ContentProvider; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.util.Log; import java.io.File; import java.io.FileOutputStream; /*** * 在本示例中,这个ContentProvider的作用是: * 充当一个媒介的作用,因为外面的应用没法访问 * 本应用内部的文件,所以在本应用中增加这个 * ContentProvider是为了能够让外界通过 * ContentProvider来访问本应用中的某些 * 想要暴漏的数据文件; * * 在本示例中,我们仅仅测试文件的插入操作; * 若对于其他操作,也想实现,可自己单独去 * 重写相应的方法; * **/ public class MyContentProvider extends ContentProvider { public MyContentProvider() { } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // Implement this to handle requests to delete one or more rows. throw new UnsupportedOperationException("Not yet implemented"); } @Override public String getType(Uri uri) { // TODO: Implement this to handle requests for the MIME type of the data // at the given URI. throw new UnsupportedOperationException("Not yet implemented"); } /**** * 在本示例中,我们仅实现对文件内容的写入操作; * * uri:是我们本应用的ContentProvider的地址, * 也就是我们在AndroidManifest.xml中声明的 * android:authorities="testContentProvider" * * values:是外部应用传入的数据 * **/ @Override public Uri insert(Uri uri, ContentValues values) { /*** * 将values写入本应用的文件中; * ***/ String string = (String) values.get("test"); Log.e("string",string); File file = new File(getContext().getFilesDir(),"Content.txt"); try { FileOutputStream fileOutputStream = new FileOutputStream(file); fileOutputStream.write(string.getBytes()); } catch (Exception e) { Log.e("write",""); e.printStackTrace(); } return uri; } @Override public boolean onCreate() { // TODO: Implement this to initialize your content provider on startup. return false; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // TODO: Implement this to handle query requests from clients. throw new UnsupportedOperationException("Not yet implemented"); } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { // TODO: Implement this to handle requests to update one or more rows. throw new UnsupportedOperationException("Not yet implemented"); } }
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.administrator.testascontentprovider"> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <provider android:name=".MyContentProvider" android:authorities="testContentProvider" android:enabled="true" android:exported="true"></provider> </application> </manifest>
访问内容提供者
MainActivity.java
package com.example.administrator.testaccesscontentprovider; import android.content.ContentResolver; import android.content.ContentValues; import android.net.Uri; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; /** * 本应用的目的是:向有ContentProvider的应用TestAsContentProvider * 写入数据 * **/ public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } /*** * 向ContentProvider写入数据 * ***/ public void insert(View view){ ContentResolver contentResolver = getContentResolver(); ContentValues contentValues = new ContentValues(); contentValues.put("test","hello world"); /*** * 记得加上URI的前缀:content:// * **/ contentResolver.insert(Uri.parse("content://testContentProvider"),contentValues); } }
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?> <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:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.administrator.testaccesscontentprovider.MainActivity"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="insert" android:onClick="insert" /> </RelativeLayout>
运行结果如下:
总结:
内容提供者的作用是让应用去暴漏部分数据,以供其他应用去操作;
内容提供者存在于想要暴漏数据的应用中,目的是为其他应用通过内容提供者去访问这个数据;
源码:
1>
2>