Android 使用ContentProvider在应用间共享数据
1294055889
8年前
<h3><strong>Android 使用ContentProvider在应用间共享数据</strong></h3> <p style="text-align:center"><img src="https://simg.open-open.com/show/bdd90b305c19b0ed89b28e92ebf51fc0.jpg"></p> <p>在开发的过程中,有时会有需求要实现应用程序之间实现数据共享,在 Android 系统中提供了一个内容提供者 ContentProvider</p> <p>可以实现这个功能,需要继承这个类,并实现相关的接口,其他的应用就可以通过uri来访问相关的数据,在 Android 中最常见的</p> <p>内容提供者就是 MediaProvider ,所有的应用都可以通过uri来访问系统中的媒体数据,我们也可以实现这样的功能,首先就是要</p> <p>确定你的应用是否要向外提供数据</p> <h3><strong>设计数据存储</strong></h3> <p>我们这里是通过数据库最为媒介来提供数据,需要设计具体的数据库的数据结构,通过系统提供的 SQLiteOpenHelper 类来创建数据库</p> <p>核心的代码:</p> <p>简单的数据结构,根据自己的需求设计数据库的数据结构</p> <pre> <code class="language-java">public final class Settings implements BaseColumns{ private Settings(){} public static final String TABLE_NAME = "settings"; //数据库中标的名称 public static final String COLUMN_NAME_TITLE = "name"; //表中的列名 public static final String COLUMN_NAME_VALUE = "value"; //表中的列名 }</code></pre> <p>继承 SQLiteOpenHelper 来创建数据库</p> <pre> <code class="language-java">private static class DatabaseHelper extends SQLiteOpenHelper{ public DatabaseHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS settings"); onCreate(db); } @Override public void onCreate(SQLiteDatabase db) { String sql = " CREATE TABLE "+Settings.TABLE_NAME +" (" + Settings._ID +" INTEGER PRIMARY KEY," + Settings.COLUMN_NAME_TITLE +" TEXT," + Settings.COLUMN_NAME_VALUE +" TEXT" + ");"; db.execSQL(sql); } }</code></pre> <h3><strong>内容提供者</strong></h3> <p>ContentProvider 需重载的接口如下:</p> <ul> <li>public Uri insert(Uri uri, ContentValues values)</li> <li>public int delete(Uri uri, String selection, String[] selectionArgs)</li> <li>public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)</li> <li>public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)</li> <li> <p>public String getType(Uri uri)</p> <p>URI的设计</p> <p>[content://][com.example.demo.gank.provider][/settings][/1]</p> <p>|-----A-----|---------------B---------------|-----C----|--D-|</p> </li> <li> <p>A:是Scheme,固定为 content://</p> </li> <li>B: 是Authority,用来识别特定的 Content Provider ,一般使用应用的报名来命名</li> <li>C:是资源的路径</li> <li> <p>D: 资源的ID</p> <p>为了传入的uri执行不同的操作,可以通过Android中的 UriMatcher 实体类,将uri映射不同的内容</p> </li> </ul> <h3><strong>设置权限</strong></h3> <p>可以为provider设置权限</p> <pre> <code class="language-java"><?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.demo.gank"> 。。。。 <permission android:name="com.example.demo.gank.provider.READ_PROVIDER" android:protectionLevel="normal"></permission> <permission android:name="com.example.demo.gank.provider.WRITE_PROVIDER" android:protectionLevel="normal"></permission> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <provider android:authorities="com.example.demo.gank.provider" android:name="com.example.demo.gank.provider.SettingsProvider" android:readPermission="com.example.demo.gank.provider.READ_PROVIDER" android:writePermission="com.example.demo.gank.provider.WRITE_PROVIDER" android:exported="true"> </provider> </application> </manifest></code></pre> <p>运行工程,这个工程应用是A,A应用安装之后,这个应用就是一个内容提供者</p> <p>再建一个工程B,在B中访问数据,这个是工程B中访问数据库的代码</p> <pre> <code class="language-java">Uri uri = Uri.parse("content://com.example.demo.gank.provider/settings"); //和A中提供的uri保持一致 Cursor c = getContentResolver().query(uri,new String[]{"name","value"}," name =? ", //是在A中定义的数据库的字段 new String[]{"settings"},null); if(c != null && c.moveToFirst()){ String value = c.getString(c.getColumnIndex("value")); log.e(TAG,"=================query value: "+value); }</code></pre> <p>在B中的 AndroidManifest.xml' 中加入相关的权限</p> <pre> <code class="language-java"><uses-permission android:name="com.example.demo.gank.provider.READ_PROVIDER"/> <uses-permission android:name="com.example.demo.gank.provider.WRITE_PROVIDER"/></code></pre> <p>运行结果就是得到A中数据库的内容</p> <h3><strong>代码</strong></h3> <p>Settings.java</p> <pre> <code class="language-java">public static final String SCHEME = "content://"; private static final String PATH_SETTINGS = "/settings"; private static final String PATH_SETTINGS_ID = "/settings/"; public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.com.example.demo.gank.settings"; public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.com.example.demo.gank.settings";</code></pre> <p>SettingsProvider.java</p> <pre> <code class="language-java">public class SettingsProvider extends ContentProvider{ private static final String DB_NAME = "settings.db"; private static final int DB_VERSION = 1; private static final int SETTINGS = 1; private static final int SETTINGS_ID = 2; //.... static { sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); sUriMatcher.addURI(Settings.AUTHORITY,"settings",SETTINGS); sUriMatcher.addURI(Settings.AUTHORITY,"settings/#",SETTINGS_ID); sProjectionMap = new HashMap<>(); sProjectionMap.put(Settings.COLUMN_NAME_TITLE,Settings.COLUMN_NAME_TITLE); sProjectionMap.put(Settings.COLUMN_NAME_VALUE,Settings.COLUMN_NAME_VALUE); sProjectionMap.put(Settings._ID,Settings._ID); } @Nullable @Override public Uri insert(Uri uri, ContentValues values) { return null; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { return 0; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { return 0; } @Nullable @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { return null; } @Nullable @Override public String getType(Uri uri) { return null; } @Override public boolean onCreate() { mOPenHelper = new DatabaseHelper(getContext()); return true; } private static class DatabaseHelper extends SQLiteOpenHelper{ //具体的代码请参看源码 //。。。。 } }</code></pre> <p> </p> <p>来自:http://www.jianshu.com/p/f69c7e0a4ba5</p> <p> </p>