Android基础第十篇-内容提供者

本文详细介绍了Android中的ContentProvider,包括访问私有数据库、内容提供者原理和使用、如何通过ContentResolver访问自定义内容提供者。内容提供者作为Android四大组件之一,用于不同应用间的数据共享,通过定义对外接口,允许其他应用访问特定应用的数据库内容。文章还通过实例演示了如何备份和还原短信,获取和插入联系人信息,并利用ContentObserver监听短信数据库变化。
摘要由CSDN通过智能技术生成

转载请标明出处:
http://blog.csdn.net/gj782128729/article/details/52522999
本文出自:【高境的博客】

1. 访问私有数据库


创建一个项目,在项目中利用SQLiteOpenHelper创建一个名称为account的数据库,并在数据库中创建一张名为info的表。

public class MyOpenHelper extends SQLiteOpenHelper {
   
    public MyOpenHelper(Context context) {
        super(context, "account.db", null, 1);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table info (_id integer primary key autoincrement,name varchar(20),money varchar(20))");
        db.execSQL("insert into info('name','money') values ('张三','2000')");
        db.execSQL("insert into info ('name','money') values ('李四','5000')");   
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
    }
}

在MainActivity中需要调用以下代码才能创建数据库:

private MyOpenHelper myOpenHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    myOpenHelper = new MyOpenHelper(this);
    myOpenHelper.getReadableDatabase();
}

运行程序,我们利用DDMS中的FileExplorer查看我们的数据库文件:
这里写图片描述

从上图可以看到创建了一个account.db的数据库,查看文件权限可以看到,对其他用户没有权限。

SQLiteDatabase有一个静态的方法,可以直接加载某个路径下的数据库文件。我们再创建一个项目工程,在这个工程中用这个静态方法访问account.db。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    SQLiteDatabase db = SQLiteDatabase.openDatabase("/data/data/com.itheima.transation/databases/account.db", null, SQLiteDatabase.OPEN_READWRITE);
    Cursor cursor = db.query("info", null, null, null, null, null, null);
       if (cursor!=null && cursor.getCount()>0){        
            while (cursor.moveToNext()) {
                String name=cursor.getString(cursor.getColumnIndex("name"));
                String money=cursor.getString(cursor.getColumnIndex("money"));
                System.out.println("name"+name + "money"+money);
        }           
    } 
}

运行结果:
这里写图片描述
这里写图片描述

以上结果说明我们使用SQLiteDatabase.openDatabase()方法打开数据库需要有权限才能够访问。我们改变account.db的访问权限,使其他用户也能访问该文件:

这里写图片描述

再次运行程序,访问account.db数据库,这时候就能够访问到数据库中的数据了。查看日志输出如下:

这里写图片描述

这种方式虽然能够访问到其他应用程序的数据库,但是这种方式需要手动改变其他应用程序数据库的访问权限,并且这是一种非常不安全的操作,如果改变应用数据库的访问权限,其他程序很容易修改数据库的内容。那么如何才能访问其他应用程序的数据库呢?Google给我们提供了Android中另一个组件ContentProvider内容提供者来解决这个问题。

2. 内容提供者


ContentProvider(内容提供者)是Android中的四大组件之一,在一般的开发中,可能使用的比较少。

ContentProvider为不同的软件之间数据共享,提供统了一套接口。也就是说,如果我们想让其他的应用使用我们自己程序内的数据,就可以使用ContentProvider定义一组对外开放的接口,从而使得其他的应用可以使用咱们应用的文件、数据库内存储的信息。

当然,自己开发的应用需要给其他应用共享信息的需求可能比较少见,但是在Android系统中,很多系统自带应用,比如联系人信息,图片库,音频库等应用,为了对其他应用暴露数据,所以就使用了ContentProvider机制。所以,学习ContentProvider的基本使用,在遇到获取联系人信息,图片库,音频库等需求的时候,才能更好的开发。

2.1. 内容提供者的原理

内容提供者定义了一组对外开放的接口,使其他应用可以访问自己的应用的数据库内容,下图是外部应用访问系统联系人应用数据库的原理图:
这里写图片描述

从上图可以看出,普通外部应用不可以直接访问私有的数据库,只能通过内容提供者访问私有数据库,内容提供者处于应用内部,在内容提供者中定义了一些访问路径匹配等操作,当外部应用通过路径访问私有数据库时,内容提供者根据路径匹配出具体的操作,将私有数据返回给外部应用。

2.2. 内容提供者的使用

(a)创建一个类继承ContentProvider,实现其中的方法

public class AccountProvider extends ContentProvider {
   
    //当内容提供者创建的时候调用
    @Override
    public boolean onCreate() {
        return true;
    }
    //用于查询数据库数据,返回值是Cursor即结果的数据集
    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
      String[] selectionArgs, String sortOrder) {
    }
    //返回MIME类型的字符串,如果返回null,说明没有数据类型
    @Override
    public String getType(Uri uri) {
        return null;
    }
    //用于向数据库插入记录
    @Override
    public Uri insert(Uri uri, ContentValues values) {  
    }
    //用于删除数据库记录
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
    }
    //用于更新数据库记录
    @Override
    public int update(Uri uri, ContentValues values, String selection,
    String[] selectionArgs) {   
    }
}

(b)清单文件中配置内容提供者

<provider
     android:name="com.itheima.transation.AccountProvider"
     //设置主机名
     android:authorities="com.itheima.account.provider" >
</provider>

(c)定义路径匹配规则

//定义当路径匹配成功后对指定的组件返回的返回码
private static final int QUERYSUCESS = 1;
private static final int ADDSUCESS = 2;
private static final int DELSUCESS = 3;
private static final int UPDATESUCESS = 4;
//创建Uri的匹配对象
static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
    //增加匹配规则,参数1为主机名,参数2为路径,参数3为当路径匹配成功后对指定的组件返回的返回码,必须是正数。该主机名必须和清单文件中配置的主机名一致。
    matcher.addURI("com.itheima.account.provider", "query", QUERYSUCESS);
    matcher.addURI("com.itheima.account.provider", "add", ADDSUCESS); 
    matcher.addURI("com.itheima.account.provider", "delete", DELSUCESS);
    matcher.addURI("com.itheima.account.provider", "update", UPDATESUCESS);
}

注意:主机名必须和清单文件中配置的主机名一致。

Uri的组成规则:协议名://主机名或authority/路径/ID。Uri的组成可以参考下图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值