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>