Android学习---通过内容提供者(ContentProvider)操作另外一个应用私有数据库的内容

一.什么是ContentProvider?

ContentProvider直译过来就是内容提供者,主要作用就是A应用提供接口给B应用调用数据,和之前介绍的sharedPreference和直接开放文件访问类似,都是共享应用程序数据,不同的是之前的两种文件格式可能完全不同,如可能为xml,txt,sql等等,这里ContentProvider返回的数据格式是统一的,因此应用的更为广泛一点.

二.实例

这里使用的是A应用通过ContentProvider共享数据给B应用.这里A应用用的是前文中的android_db里的person表.B应用是新建的android_content_provider程序.

1.新创建android_content_provider应用程序

2.访问android_db共享的数据

创建好了应用程序以后,

/android_content_provider/src/com/example/android_content_provider/ContentProvider.java

package com.example.android_content_provider;

import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;

public class ContentProvider extends Activity {

    private static String tag = "ContentProvider.class";

    /**
     * Called when the activity is first created.
     */

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //内容解析者
        ContentResolver contentResolver = getContentResolver();
        Uri uri = Uri.parse("content://com.amos.android_db.provider.PersonProvider/persons");
        Cursor cursor = contentResolver.query(uri, null, null, null, null);
        while(cursor.moveToNext()){
            String name = cursor.getString(cursor.getColumnIndex("name"));
            int age = cursor.getInt(cursor.getColumnIndex("age"));
            System.out.println("name:"+name+" age:"+age);
            Log.d(tag,"用户名:"+name+" 年龄:"+age);
        }
    }
}

3.android_db开放共享数据接口

1)开放一个uri

/android_db/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.amos.android_db"
          android:versionCode="1"
          android:versionName="1.0">
    <instrumentation android:name="android.test.InstrumentationTestRunner"
                     android:targetPackage="com.amos.android_db"></instrumentation>
    <uses-sdk android:minSdkVersion="7"/>
    <application android:label="@string/app_name">
        <uses-library android:name="android.test.runner"/>
        <activity android:name="MyActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!--给内容提供者提供定义一个uri,一般建议使用包名+类名,以供其它程序调用 -->
        <provider android:authorities="com.amos.android_db.provider.PersonProvider" android:name=".provider.PersonProvider">

        </provider>
    </application>
</manifest> 

2).定义路径匹配(继承ContentProvider类)

/android_db/src/com/amos/android_db/provider/PersonProvider.java
package com.amos.android_db.provider;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.util.Log;
import com.amos.android_db.MyDBHelper;
import com.amos.android_db.dao.Person;
import com.amos.android_db.dao.PersonDao;

import java.util.List;

/**
 * Created by amosli on 14-6-17.
 */
public class PersonProvider extends ContentProvider {

    //创建一个路径识别器
    //常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码,也就是说如果找不到匹配的类型,返回-1
    private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    private static final int ALL_PERSON = 1;
    private static final int PERSON = 2;
    private static final int OTHER = 3;

    private static String tag="PersonProvider.class";

    static{
        //1.指定一个路径的匹配规则
        //如果路径满足content://com.amos.android_db.provider.PersonProvider/persons,返回值就是(ALL_PERSON)=1
        uriMatcher.addURI("com.amos.android_db.provider.PersonProvider","persons",ALL_PERSON);

        //2.如果路径满足content://com.amos.android_db.provider.PersonProvider/person/3,返回值就是(PERSON)=2
        //#号为通配符
        uriMatcher.addURI("com.amos.android_db.provider.PersonProvider","person/#",PERSON);
        //3.如果路径满足content://com.amos.android_db.provider.PersonProvider/other,返回值就是(OTHER)=3
        uriMatcher.addURI("com.amos.android_db.provider.PersonProvider","other",OTHER);

    }

    /**
     * 一般是对象第一次被创建时调用的方法
     *
     * @return
     */
    @Override
    public boolean onCreate() {

        return false;
    }

    /**
     * 让别人去调用返回结果
     *
     * @param uri
     * @param projection    选择的列
     * @param selection     查询条件
     * @param selectionArgs 查询条件的value
     * @param sortOrder     排序
     * @return
     */
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        int result = uriMatcher.match(uri);
        switch(result){
            //如果路径满足content://com.amos.android_db.provider.PersonProvider/persons,返回值就是(ALL_PERSON)=1
            case ALL_PERSON:
                PersonDao dao = new PersonDao(this.getContext());
                return dao.findAllByCursor();

            //2.如果路径满足content://com.amos.android_db.provider.PersonProvider/person/3,返回值就是(PERSON)=2
            case PERSON:
                long id = ContentUris.parseId(uri);
                SQLiteDatabase database = new MyDBHelper(this.getContext()).getReadableDatabase();
                if(database.isOpen()){
                    database.execSQL("select * person where personid = "+id);
                    return database.query("person", null, "personid", new String[]{id + ""}, null, null, null);
                    //不要关闭数据库,否则就没有数据了.
                }
            case OTHER:
                Log.d(tag,"我是其他匹配规则!");
                break;
            default:
                throw new RuntimeException("出错了!!");

        }

        return null;
    }

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

    @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;
    }
}

4.效果图

首先,将android_db部署到avd上,其次,运行android_content_provider项目,最后,查看log输出.

5.出现的问题

1).报空指针错误

.....

at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.example.android_content_provider.ContentProvider.onCreate(ContentProvider.java:21)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
.....

这种问题很有可能是路径名称不对,注意提供的接口名称保持一致;并且保证获取数据的接口是正常的,即android_db里获取person表的内容是正常的.

2).intelij中的logcat中看不到log

注意选择Android--->选择要查看Log的进程--->点击上面的双向箭头进行切换日志展示信息.

 6.扩展

1),查询,增加,删除,修改的接口全部实现

上面已经实现了查询的接口,这里将实现另外三个接口:

        //4.插入数据,如果路径满足content://com.amos.android_db.provider.PersonProvider/insert,返回值就是(INSERT)=4
        uriMatcher.addURI("com.amos.android_db.provider.PersonProvider", "insert", INSERT);
        //5.删除数据,如果路径满足content://com.amos.android_db.provider.PersonProvider/delete,返回值就是(DELETE)=5
        uriMatcher.addURI("com.amos.android_db.provider.PersonProvider", "delete", DELETE);
        //6.更新数据,如果路径满足content://com.amos.android_db.provider.PersonProvider/update,返回值就是(UPDATE)=6
        uriMatcher.addURI("com.amos.android_db.provider.PersonProvider", "update", UPDATE);

对应的实现:

 @Override
    public Uri insert(Uri uri, ContentValues values) {

        //content://com.amos.android_db.provider.PersonProvider/insert
        int result = uriMatcher.match(uri);
        switch (result) {
            case INSERT:
                SQLiteDatabase database = myDBHelper.getWritableDatabase();
                if (database.isOpen()) {
                    database.insert("person", null, values);
                }
                return uri;

            default:
                throw new RuntimeException("无法识别该URI,出错了!!");
        }

    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        //删除操作
        //content://com.amos.android_db.provider.PersonProvider/delete
        int result = uriMatcher.match(uri);
        switch (result) {
            case DELETE:
                SQLiteDatabase database = myDBHelper.getWritableDatabase();
                return database.delete("person", selection, selectionArgs);

            default:
                throw new RuntimeException("无法识别该URI,出错了!!");
        }

    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
       //更新操作
        //content://com.amos.android_db.provider.PersonProvider/update
        int result = uriMatcher.match(uri);
        switch (result) {
            case UPDATE:
                SQLiteDatabase database = myDBHelper.getWritableDatabase();
                return database.update("person", values, selection, selectionArgs);

            default:
                throw new RuntimeException("无法识别该URI,出错了!!");
        }

    }

//返回值的类型

   @Override
    public String getType(Uri uri) {
        int result = uriMatcher.match(uri);
        switch (result){
            case ALL_PERSON:
                return "List<Person>";
            case PERSON:
                return "Person";
            default:return null;
        }
    }

2)测试 

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.ContentProviderTest"
          android:versionCode="1"
          android:versionName="1.0">
    <uses-sdk android:minSdkVersion="7"/>
    <instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="com.example.ContentProviderTest"/>

    <application android:label="@string/app_name">
        <uses-library android:name="android.test.runner"/>
        <activity android:name="MyActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest> 

加入加粗的两行,配置好测试的环境.

/ContentProviderTest/src/com/example/ContentProviderTest/test/TestCase.java

package com.example.ContentProviderTest.test;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.net.Uri;
import android.test.AndroidTestCase;

/**
 * Created by amosli on 14-6-19.
 */
public class TestCase extends AndroidTestCase {

    public void testInsert(){
            ContentResolver contentResolver = getContext().getContentResolver();
            Uri uri = Uri.parse("content://com.amos.android_db.provider.PersonProvider/insert");
            ContentValues values = new ContentValues();
            values.put("name", "bill");
            values.put("age", 18);
            contentResolver.insert(uri, values);
    }
    public void testDelete(){
        ContentResolver contentResolver = getContext().getContentResolver();
        Uri uri = Uri.parse("content://com.amos.android_db.provider.PersonProvider/delete");
        contentResolver.delete(uri,"name=?",new String[]{"amos96"});
    }
    public void testUpdate(){
        ContentResolver contentResolver = getContext().getContentResolver();
        Uri uri = Uri.parse("content://com.amos.android_db.provider.PersonProvider/update");
        ContentValues contentValues = new ContentValues();
        contentValues.put("name","jack");
        contentValues.put("age",30);
        contentResolver.update(uri,contentValues,"name=?",new String[]{"amos97"});
    }

}

3)效果图:

插入数据(insert方法),bill

删除数据(delete方法),amos96

更新数据(update方法 ),amos97

本文源码:

https://github.com/amosli/android_basic/tree/android_db

https://github.com/amosli/android_basic/tree/content_provoider

https://github.com/amosli/android_basic/tree/android_contentProviderTest

Android学习---通过内容提供者(ContentProvider)操作另外一个应用私有数据库的内容

时间: 2024-10-12 17:21:41

Android学习---通过内容提供者(ContentProvider)操作另外一个应用私有数据库的内容的相关文章

[Android Pro] 监听内容提供者ContentProvider的数据变化

转载自:http://blog.csdn.net/woshixuye/article/details/8281385 一.提出需求 有A,B,C三个应用,B中的数据需要被共享,所以B中定义了内容提供者ContentProvider:A应用修改了B应用的数据,插入了一条数据.有这样一个需求,此时C应用需要得到数据被修改的通知并处理相应操作. 二.示例代码 A应用 /** * 对内容提供者进行操作 * * @author XY * */ public class MainActivity exten

[Android Pro] 内容提供者ContentProvider的基本使用

一.ContentProvider简介 当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据.ContentProvider为存储和获取数据提供了统一的接口.虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,如采用文件方式对外共享数据,需要进行文件操作读写数据:采用sharedpreferences共享数据,需要使用sharedpreferences API读写数据.而使用ContentProvider共享数据的

Android四大组件之内容提供者--ContentProvider

Android四大组件之内容提供者--ContentProvider 1,什么是ContentProvider ContentProvider将应用中的数据对其它应用进行共享, 提供增删改查的方法 ContentProvider统一了数据的访问方式,不必针对不同数据类型采取不同的访问策略 ContentProvider将数据封装,只暴露出我们希望提供给其它程序的数据 ContentProvider中可以注册观察者, 监听数据的变化 2,怎么创建 2.1定义类继承ContentProvider,

【Android基础】内容提供者ContentProvider的使用详解

1.什么是ContentProvider 首先,ContentProvider(内容提供者)是android中的四大组件之一,但是在一般的开发中,可能使用的比较少. ContentProvider为不同的软件之间数据共享,提供统一的接口.也就是说,如果我们想让其他的应用使用我们自己程序内的数据,就可以使用ContentProvider定义一个对外开放的接口,从而使得其他的应用可以使用咱们应用的文件.数据库内存储的信息.当然,自己开发的应用需要给其他应用共享信息的需求可能比较少见,但是在Andro

Android开发之内容提供者ContentProvider

2 内容提供者ContentProvider 一.ContentProvider简介 当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据.虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,如:采用文件方式对外共享数据,需要进行文件操作读写数据:采用sharedpreferences共享数据,需要使用sharedpreferences API读写数据.而使用ContentProvider共享数据的好处是统一了数据

Android中内容提供者ContentProvider实现数据库增删改查

1.我们首先new一个我们自己的类集成ContentProvider,并实现方法如下 package com.wzw.sqllitedemo.providers; import com.wzw.sqllitedemo.db.PersonSQLiteOpenHelper; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues;

内容提供者ContentProvider

首先在需要提供内容提供者的应用中添加内容提供者的代码 package com.example.sqllite; import com.example.sqllite.servise.DBOpenHelp; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.UriMatcher

Android学习路线(五)开启另一个Activity

在完成了 上一篇课程后,你已经有了一个应用.这个应用展示了一个包含一个文本框和一个按钮的activity(一个单独的界面).在这次的课程中,你将会通过在MainActivity中添加一些代码,来让当给你点击Send按钮时能够跳转到另一个activity中. 响应Send按钮 为了响应按钮的点击事件,打开fragment_main.xml 布局文件,然后在 <Button> 元素中加入android:onClick属性: <Button     android:layout_width=&

Android之内容提供者ContentProvider的总结

本文包含以下知识点: ContentProvider Uri 的介绍 ContentResolver: 监听ContentProvider的数据改变 一:ContentProvider部分 ContentProvider的作用: Content providers store and retrieve data and make it accessible to all applications. They're the only way to share data across applica