Android知识梳理之ContentProvider内容提供者的使用

时间:2021-05-13 09:18:53

        在实际的开发中我们可能会遇到这样的情况:将自己app的数据文件提供给别的app.类似系统自带的联系人,短信箱.但是我们知道Android系统中每一个进程都是独立的,而且他们的数据都是属于私有数据,别的进程是无法获取到的.当然我们可以通过将文件或者是数据库存到sd卡或者手机内存里面来实现文件的共享.But,如果采用文件操作模式对外共享数据,数据的访问方式会因数据存储的方式而不同,导致数据的访问方式无法统一,如:采用xml文件对外共享数据,需要进行xml解析才能读取数据;采用sharedpreferences共享数据,需要使用sharedpreferences API读取数据。为了解决这样的问题.Android提供了contentprovider来实现不同应用之间文件的共享.作为Android中的四大组件之一的内容提供者(content provider)可能是被用的最少的组件,但是它却简化了应用间数据的共享方式.说了一大堆如果你没怎么看明白也不要紧.下面看看实现的效果.

     转载请注明出处: http://blog.csdn.net/unreliable_narrator?viewmode=contents

                 Android知识梳理之ContentProvider内容提供者的使用

    老规矩:我们先来看看实现的效果.在app1中写好内容提供者,在app2中对共享的数据进行操作.Android知识梳理之ContentProvider内容提供者的使用

      首先我们先来了解一些概念:
               Uri:  

          URI是个什么东西?在ContentProvider中有什么用处?URI中的几个方法。

        概念:URI(Uniform Resource )翻译过来就是统一资源定位符,URI在ContentProvider中代表了要操做的数据。

    在Android系统中通常的URI格式为:content://com.dapengdb/person/10

    在万维网访问时通常用的URI格式为:http://www.XXXX.com/aa/bb

    • content://                              schema,这个是Android中已经定义好的一个标准。有些类似于http://,都是代表的协议。ContentProvider(内容提供者)的scheme已经由Android所规定为:content://
    • content://com.dapengdb/person/10     authority(主机名),用于唯一标识这个ContentProvider,外部调用者通过这个authority来找到它。相当于www.XXXX.com,代表的是我们ContentProvider所在的”域名”,这个”域名”在我们Android中一定要是唯一的,否则系统就不知道去找哪一个对应的provider了.所以一般情况下,建议采用完整的包名加类名来标识这个ContentProvider的authority。
    • /person/10                                路径,用来标识我们要操作的数据。/person/10表示的意思是——找到person中id为10的记录。其实这个相当于/aa/bb。
        接着来看看实现的步骤:

           1.首先创建一个数据库打开的帮助类(如果对数据库不了解详看:http://blog.csdn.net/unreliable_narrator/article/details/51179634).

public class DBOpenHelper extends SQLiteOpenHelper {
    public DBOpenHelper(Context context) {
        super(context, "person.db", null, 1);
    }
    
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table person (_id integer primary key autoincrement,name varchar(20),phone varchar(2))");
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }
}

          2.既然是四大组件自然是需要在清单文件中进行配置,设置主机名,如果想跨进程共享数据就需要设置android:exported="true".

<provider
            android:name=".PersonCP"
            android:authorities="com.dapeng.personcp"
            android:exported="true"/>

         3.创建一个类继承content paovider并且实现里面的增删改查的方法.

public class PersonCP extends ContentProvider {
    // 常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
    private static UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    private static final int PERSON = 1;
    private DBOpenHelper mDBOpenHelper;
    //使用静态代码块让程序一运行就加载
    static {
        // 如果match()方法匹配content://com.dapeng.personcp/person路径,返回匹配码为PERSON
        uriMatcher.addURI("com.dapeng.personcp", "person", PERSON);
    }
    /*
    * 内容提供者被创建时调用的方法.ContentProvider在其它应用第一次访问它时才会被创建
    * */
    @Override
    public boolean onCreate() {
        mDBOpenHelper = new DBOpenHelper(getContext());
        return true;
    }
    /*
    *插入数据
    * */
    @Nullable
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        SQLiteDatabase writableDatabase = mDBOpenHelper.getWritableDatabase();
        int match = uriMatcher.match(uri);
        if (match == PERSON) {
            long person = writableDatabase.insert("person", null, values);
            writableDatabase.close();
            return Uri.parse("" + person);
        } else {
            writableDatabase.close();
            return null;
        }
    }
    /*
    删除数据
    * */
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        SQLiteDatabase writableDatabase = mDBOpenHelper.getWritableDatabase();
        if (uriMatcher.match(uri) == PERSON) {
            int persion = writableDatabase.delete("person", selection, selectionArgs);
            writableDatabase.close();
            return persion;
        } else {
            writableDatabase.close();
            return 0;
        }
    }
    /*
    查询数据
    * */
    @Nullable
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        SQLiteDatabase writableDatabase = mDBOpenHelper.getWritableDatabase();
        if (uriMatcher.match(uri) == PERSON) {
            return writableDatabase.query("person", projection, selection, selectionArgs, null, null, sortOrder);
        } else {
            return null;
        }
    }
    /*
       修改数据
       * */
    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        SQLiteDatabase writableDatabase = mDBOpenHelper.getWritableDatabase();
        if (uriMatcher.match(uri) == PERSON) {
            int person = writableDatabase.update("person", values, selection, selectionArgs);
            writableDatabase.close();
            return person;
        } else {
            writableDatabase.close();
            return 0;
        }
    }
    @Nullable
    @Override
    public String getType(Uri uri) {
        return null;
    }
}

  4.创建一个新的app,得到contentresolver根据Uri去进行匹配.就可以对共享的数据进行操作了.

public class MainActivity extends AppCompatActivity {
    private TextView tv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView) findViewById(R.id.tv);
    }
    /**
     * 添加数据
     *
     * @param view
     */
    public void add(View view) {
        ContentResolver contentResolver = this.getContentResolver();
        Uri insertUri = Uri.parse("content://com.dapeng.personcp/person");
        ContentValues values = new ContentValues();
        values.put("name", "狗蛋");
        values.put("phone", "1234567");
        contentResolver.insert(insertUri, values);
        Toast.makeText(MainActivity.this, "数据删除成功", Toast.LENGTH_SHORT).show();
    }
    /**
     * 删除
     *
     * @param view
     */
    public void delete(View view) {
        ContentResolver resolver = getContentResolver();
        Uri uri = Uri.parse("content://com.dapeng.personcp/person/");
        int delete = resolver.delete(uri, "name=?", new String[]{"狗蛋"});
        if (delete != -1) {
            Toast.makeText(MainActivity.this, "数据删除成功", Toast.LENGTH_SHORT).show();
        }
    }
    /**
     * 修改
     *
     * @param view
     */
    public void update(View view) {
        ContentResolver resolver = getContentResolver();
        Uri uri = Uri.parse("content://com.dapeng.personcp/person/");
        ContentValues contentValues = new ContentValues();
        contentValues.put("name", "金三胖");
        contentValues.put("phone", "7654321");
        int update = resolver.update(uri, contentValues, "name=?", new String[]{"狗蛋"});
        if (update > 0) {
            Toast.makeText(this, "修改成功", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this, "修改失败", Toast.LENGTH_SHORT).show();
        }
    }
    /**
     * 查询
     *
     * @param view
     */
    public void query(View view) {
        tv.setText("");
        ContentResolver resolver = getContentResolver();
        Uri uri = Uri.parse("content://com.dapeng.personcp/person");
        Cursor cursor = resolver.query(uri, null, null, null, null);
        StringBuilder sb = new StringBuilder();
        while (cursor.moveToNext()) {
            String id = cursor.getString(0);
            String name = cursor.getString(1);
            String money = cursor.getString(2);
            sb.append(id);
            sb.append(name);
            sb.append(money);
            sb.append("\n");
        }
        tv.setText(sb.toString());
        cursor.close();
    }
}

That's all.enjory it!