android 四大组件之ContentProvider1.

本文通过一个实例介绍了Android中ContentProvider的基本用法,包括如何创建和配置一个ContentProvider服务端及客户端,实现跨应用的数据共享。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.从学习android到至今已经有一年的时间了,四大组件中用到了三个唯独contentprovider没有被用到过,而且对这个也不是很理解,但是学习《android开发艺术探究》之后在第二章的IPC机制中,提到一种方法就是contentprovider。通过contentprovider可以实现数据共享。

2.contentprovider暴露数据的接口,这样其他的程序可以通过Uri来访问这个contentprovider的数据。我们知道每个app运行的时候都占用一个进程,contentprovider可以实现进程间的通讯。这个demo分为俩部分,一个是提供contentprovider的应用的app,我们称为service,另外一个应用程序我们称为client,也就是说这次我们要写俩个应用程序。


3.Service端。第一步首先要继承contentprovider,代码如下:

package com.example.lenovo.contentprovidertest;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.support.annotation.Nullable;

/**
 * Created by lenovo on 21/6/2016.
 */
public class MyContentProvider extends ContentProvider {

    SQLiteDatabase writedb;
    SQLiteDatabase readb;
    Database d;
    final static String uri="content://com.example.lenovo.contentprovidertest.MyContentProvider1";
    final  static UriMatcher matcher=new UriMatcher(UriMatcher.NO_MATCH);
    static {
        matcher.addURI(uri,"Login",1);
    }
    @Override
    public boolean onCreate() {
         d=new Database(getContext(),"Login",null,1);

        return false;
    }

    @Nullable
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {

        readb=d.getReadableDatabase();
        Cursor cursor= readb.rawQuery("select * from user ",null);
        return cursor;
    }

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

    @Nullable
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        writedb=d.getWritableDatabase();
        writedb.insert("user",null,values);
        return uri;
    }

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

下面有几个需要注意的地方:

oncreate(),方法运行在主线程中,因此在这个方法中我们不能做耗时操作。

UriMatcher类的作用:就是将authorities 和具体访问的资源绑定起来,并且设置一个code,当匹配成功就会返回这个code。

例如:www.baidu.sa.html     www.baidu就相当于我们这的authorities  sa.html 相当具体的资源。关于contentprovider的uri不懂的可以找找资料看看。这里不细说

当你继承Contentprovider的时候,会要求重写一些方法,那些方法都需要我们自己来实现,在我贴的代码中,我是通过Sqliteopenhelper来管理一个数据库的。具体代码如下:

package com.example.lenovo.contentprovidertest;

import android.content.Context;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
 * Created by lenovo on 21/6/2016.
 */
class Database extends SQLiteOpenHelper{

    public  String table="create table if not exists user(_id integer primary key autoincrement,name varchar(20),password varchar(20))";
    public Database(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    public Database(Context context, String name, SQLiteDatabase.CursorFactory factory, int version, DatabaseErrorHandler errorHandler) {
        super(context, name, factory, version, errorHandler);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(table);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

写好了这个Sqlieopenhelper之后,我们就可以在contentprovider类中,在相应的方法中,调用数据库相应的操作。例如在contentprovider方法里面有insert方法 那么,在哪个方法内部我们需要调用数据库执行insert的sql语句。详细代码请看上面的内容。

之后MainActivity的运行界面如下:


将username和password,输入内容之后,通过调用contentprovider的insert方法保存起来。通过上面代码可知,在insert方法中,我其实也是调用表的数据库的insert操作。


写完后最后一步就是在Manifest.xml里面配置provider的信息。代码如下:

<provider
            android:authorities="com.example.lenovo.contentprovidertest.MyContentProvider1"
            android:name=".MyContentProvider"
            android:exported="true"
            />
注意:exported 这个属性要设置为true。true表示可以在不同的进程中调用,false表示不可以。默认情况为false。

之后安装这个程序   输入 内容然后保存起来,每当保存成功后  会有一个Toast弹出来。



4.再建立一个客户端来调用service里面的contentprovider。MainActivity的代码如下:

package com.example.lenovo.clientcontentprivider;

import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    final static String uri="content://com.example.lenovo.contentprovidertest.MyContentProvider1/Login";
    ContentResolver contentResolver;
    Button but;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        but= (Button) findViewById(R.id.query);
        but.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                contentResolver=getContentResolver();
                Cursor cursor=contentResolver.query(Uri.parse(uri), null, null, null, null);

                while (cursor.moveToNext())
                {
                    String s=cursor.getString(cursor.getColumnIndex("name"));
                   String s1= cursor.getString(cursor.getColumnIndex("password"));
                    Toast.makeText(MainActivity.this,s, Toast.LENGTH_SHORT).show();
                }
                cursor.close();
            }
        });
    }
}

通过contentResolver.query方法来查询 Service应用保存的那些username,和password的数据。


总结:contentprovider这个类,主要是把一些需要跨进程调用的数据,保存到数据库中,其他应用程序通过一个uri来访问那个数据库,进而查询到数据。

这篇文章主要针对一些对contentprovider了解点的人,但是又不是很明白。最开始我也不是很懂contentprovider的使用,看视频也不懂,觉得超级麻烦。但是现在看看觉得也不是那么麻烦,掌握了逻辑,熟悉了过程,代码只是其次。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值