四大组件之内容提供器(ContentProvider)

1.内容提供器简介

   内容提供器其实就是不同应用程序进行数据交流的一个中间站,工具,我们利用内容提供器就只有两个方面,第一就是将我们本地程序的某些数据暴露出去,第二就是读取其他程序暴露出来的数据。

 

2.运行时权限

2.1简介

     一般我们设置权限直接在androidmamifest.xml文件中去静态设置,但是随着时代的变化,人们越来越追求隐私了,所以危险权限在6.0系统之后只能通过动态去设置,也就是说当你要设置该权限的时候,系统会自动跳转出询问我们是否要开通该权限的对话框,我们进行选择是否开通,以下是危险权限目录,不用死记,其是作为参照表用的,除了以下这些,其他都是普通权限,也就是可以直接静态注册的权限。

注意:

表格中的每个危险权限都属于一个权限组,我们在进行运行时权限处理使用的是权限名,但是用户一旦同意授权了,那么该权限所对应的权限组中所有的其他权限也会同时被授权。

(完整的权限列表:http://developer.android.com/reference/android/Manifest.permission.html)

 

2.2.实现动态申请权限

步骤:

1)判断用户是否已经给我们授权了

2)如果有授权直接调用授权之后的操作,如果没有授权,进行动态授权处理

 

代码:

 

总结:

1)今天判断的语句,第一个参数是context,第二个参数是权限,不等如果返回true的话,进行注册处理

2)动态注册处理使用参数有三个,第一个是context,第二个是权限,第三个是请求码,该返回码用于在onRequestPermissionsResult()中进行对应的授权完成处理逻辑,也就是说这个方法中,是所有权限询问对话框逻辑处理的总集合。

 

2.3 撤销申请

      方案:很简单,当你已经给其授权之后又反悔了,你可以在我们手机设置按钮中的权限设置找到对应程序,进行权限的取消。

 

3.访问其他程序中的数据

3.1 整体框架

 

3.2 ContentResolver的基本用法

a.有啥用?其用来访问内容提供器中共享的数据。

 

b.步骤:

1)通过Context的getContentResolver()方法获取该实例

2)然后根据CRUD的特色化处理代码进行访问

 

c.uri

1)组成:其由协议,authority和path组成,authority一般是包名来命名,而path是表名。

2)实例:

 

d.查询操作

1)将uri解析成uri对象

 

2)使用查询语句,返回cursor

 

3)遍历cursor,获取值

 

e.其余操作

添加:

 

更新:

 

删除:

 

 

 3.3 读取系统联系人

需求分析:

1)进行动态权限注册

2)再写一个读取系统联系人的方法,注意最后的cursor要进行关闭

3)最后动态权限也要在androidManifest.xml中进行申请(这一步指的去验证)

 

代码:

 

 

 

4. 创建自己的内容提供器

4.1作用:通过内容提供器,将数据暴露出去

4.2 实现思路:

 

说明:

总结:可以看到,几乎每一个方法都会带有uri这个参数,这个参数也正是调用ContentResolver的增删该查方法是传递过来的。

注意:

1)

 

 2)

 

 

实例:

在开始之前我们先要创建一个数据库创建类(数据库内容后面会讲~):

DBOpenHelper.java

public class DBOpenHelper extends SQLiteOpenHelper {

    final String CREATE_SQL = "CREATE TABLE test(_id INTEGER PRIMARY KEY AUTOINCREMENT,name)";
    
    public DBOpenHelper(Context context, String name, CursorFactory factory,
            int version) {
        super(context, name, null, 1);
    }

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

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // TODO Auto-generated method stub

    }

}

Step 1:自定义ContentProvider类,实现onCreate(),getType(),根据需求重写对应的增删改查方法:

NameContentProvider.java

public class NameContentProvider extends ContentProvider {

    //初始化一些常量
     private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);        
     private DBOpenHelper dbOpenHelper;
    
    //为了方便直接使用UriMatcher,这里addURI,下面再调用Matcher进行匹配
     
     static{  
         matcher.addURI("com.jay.example.providers.myprovider", "test", 1);
     }  
     
    @Override
    public boolean onCreate() {
        dbOpenHelper = new DBOpenHelper(this.getContext(), "test.db", null, 1);
        return true;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        return null;
    }

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

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        
        switch(matcher.match(uri))
        {
        //把数据库打开放到里面是想证明uri匹配完成
        case 1:
            SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
            long rowId = db.insert("test", null, values);
            if(rowId > 0)
            {
                //在前面已有的Uri后面追加ID
                Uri nameUri = ContentUris.withAppendedId(uri, rowId);
                //通知数据已经发生改变
                getContext().getContentResolver().notifyChange(nameUri, null);
                return nameUri;
            }
        }
        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;
    }

}

Step 2:AndroidManifest.xml中为ContentProvider进行注册:

<!--属性依次为:全限定类名,用于匹配的URI,是否共享数据 -->
<provider android:name="com.jay.example.bean.NameContentProvider"
            android:authorities="com.jay.example.providers.myprovider"
            android:exported="true" />

好的,作为ContentProvider的部分就完成了!


接下来,创建一个新的项目,我们来实现ContentResolver的部分,我们直接通过按钮点击插入一条数据:

MainActivity.java

public class MainActivity extends Activity {

    private Button btninsert;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        btninsert = (Button) findViewById(R.id.btninsert);
        
        //读取contentprovider 数据  
        final ContentResolver resolver = this.getContentResolver();
        
        
        btninsert.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                 ContentValues values = new ContentValues();
                 values.put("name", "测试");
                 Uri uri = Uri.parse("content://com.jay.example.providers.myprovider/test");
                resolver.insert(uri, values);
                Toast.makeText(getApplicationContext(), "数据插入成功", Toast.LENGTH_SHORT).show();
                
            }
        });
       
    }
}

如何使用? 好吧,代码还是蛮简单的,先运行作为ContentProvider的项目,接着再运行ContentResolver的项目, 点击按钮插入一条数据,然后打开file exploer将ContentProvider的db数据库取出,用图形查看工具 查看即可发现插入数据,时间关系,就不演示结果了~


 

5.通过ContentObserver监听ContentProvider的数据变化

使用指南

运行程序后,晾一边,收到短信后,可以在logcat上看到该条信息的内容,可以根据自己的需求 将Activtiy改做Service,而在后台做这种事情~

 

posted @ 2017-09-19 17:47  鹏达君  阅读(1550)  评论(0编辑  收藏  举报