Android开发_6:内容提供器

此博客为学习Android开发的笔记型博客,若有不妥或补充之处希望各位大神给予指正

Android权限

Android权限机制

Android权限分为普通权限和危险权限
对于普通权限,一般系统会自动帮我们授权,但对于危险权限需要用户手动授权。
下面是Android中所有的危险权限:在这里插入图片描述其他表中没有列出的权限就全都是普通权限。
Android中系统完整的权限列表:http://developer.android.com/reference/android/Manifest.permission.html

在程序运行时申请权限

在这里我们模拟点击按钮后,呼叫10086。(由于我们使用的是虚拟机所以不会真的呼出去的,不会给他人造成不便,这点请放心)

1.在配置文件中声明权限:

    <uses-permission android:name="android.permission.CALL_PHONE"/>

2.给button添加事件:
首先我们检测权限是否已被授权:

button.setOnClickListener(new View.OnClickListener() {
            @Override
	public void onClick(View v) {
          if (ContextCompat.checkSelfPermission(FirstActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
          	ActivityCompat.requestPermissions(FirstActivity.this, new String[]{Manifest.permission.CALL_PHONE}, 1);
          } else {
            call();
          }
    }
});

使用ContextCompat.checkSelfPermission()方法,传入两个参数:Context 和所需要的权限。

Manifest.permission.CALL_PHONE为拨号权限的常量。
同理,PackageManager.PERMISSION_GRANTED也是常量,是已授权的常量。

这里当没有授权时,调用ActivityCompat.requestPermissions()方法申请权限,传入三个参数:Context,申请权限列表(String[ ]),请求码(唯一即可)。

3.授权和回调onRequestPermissionsResult 方法

然后系统会弹出一个申请权限的对话框,无论是否授权,都会回调onRequestPermissionsResult 方法,里面有三个参数:请求码,权限列表(String[ ]),权限的处理结果(int[ ])

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
                                            //请求码                 权限列表                          权限的处理结果
   switch (requestCode){
       case 1:
           if(grantResults[0]==PackageManager.PERMISSION_GRANTED){
              call();
           }else{
              Toast.makeText(FirstActivity.this,"You denied the permission",Toast.LENGTH_SHORT).show();
           }
           break;
        default:

   }
}

4.执行呼号操作

    void call() {
        try {
            Intent intent = new Intent(Intent.ACTION_CALL);
            intent.setData(Uri.parse("tel:10086"));
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
                return;
            }
            startActivity(intent);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

访问其他程序中的数据

内容提供器:主要用于在不同程序之间实现数据共享功能。它提供了一套机制,允许一个程序访问另一个程序的数据。内容提供器可以选择只对哪一部分的数据进行共享,保证了数据的安全性。

要想访问内容提供器中的数据,就要借助ContentResolver类,可以通过context类中的getContentResolver()方法获得该类实例。
ContentResolver提供了一系列方法对数据进行操作:
insert(): 添加
update():更新
delete():删除
query():查找
没错,类似于SQLite的操作。只不过这里传的不是表名,而是uri。

uri:authority+path
authority:用于区分不同的应用程序。一般为了避免冲突采用程序包名来命名。
path:用于区分同一应用程序中的不同表

首先我们学习使用现有的内容提供器。

1.将uri字符串解析为uri对象:

Uri uri=Uri.parse("contect://com.example.app.provider/table1");

2.查询

Cursor cursor=getContentResolver().query(
uri,
projection,
selection,
selectionArgs,
sortOrder()
);

在这里插入图片描述3.取出数据:

if(cursor != null){
	while(cursor.moveToNext()){
		String data=cursor.getString(cursor.getColumnIndex("column1"));
	}
	cursor.close();
}

4.添加:

ContentValues values=new ContentValues();
values.put("column1","tom");
getContentResolver().insert(uri,values);

5.修改:

//将 符合条件的 column1一列的值清空
ContentValues values=new ContentValues();
values.put("column1","");
getContentResolver().update(uri,values,"column1 = ? and column2 = ?",new String[]{"tom","1"});

6.删除:

getContentResolver().delete(uri,"column2 = ?" new String[]{"1"});

创建内容提供器

新建一个类继承ContentProvider类,创建自己的内容提供器。
需要重写6个抽象方法:
onCreate():
初始化内容提供器时调用,通常在这里完成数据库的创建和升级。

query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder):
返回Cursor

insert(Uri uri, ContentValues values):
返回一个用于表示这条新记录的URI(Uri)

update(Uri uri, ContentValues values, String selection,String[] selectionArgs):
返回受影响的行数(int)

delete(Uri uri, String selection, String[] selectionArgs):
返回被删除的行数(int)

getType(Uri uri):
返回MIMI(String)
MIMI格式:
uri以路径结尾:
“vnd”+“android.cursor.dir/”+“vnd.< authority >.< path >”
uri 以id结尾:
“vnd"+“android.cursor.item/”+“vnd.< authority >.< path >”

实战:

1.使用UriMatcher类匹配Uri

public class MyContentProvider extends ContentProvider {

    public static final int BOOK_DIR=0;
    public static final int BOOK_ITEM=1;
    public static final String AUTHORITY="com.example.databasetest.provider";
    private static UriMatcher matcher;
    private static MyDatabaseHelper databaseHelper;

    static {
        matcher=new UriMatcher(UriMatcher.NO_MATCH);
        matcher.addURI(AUTHORITY,"book",BOOK_DIR);
        matcher.addURI(AUTHORITY,"book/#",BOOK_ITEM);

    }

2.重写insert方法:

    public Uri insert(Uri uri, ContentValues values) {
        // TODO: Implement this to handle requests to insert a new row.
//        throw new UnsupportedOperationException("Not yet implemented");
        Uri uriReturn=null;
        SQLiteDatabase db = databaseHelper.getReadableDatabase();
        switch (matcher.match(uri)){
            case BOOK_DIR:
            case BOOK_ITEM:
                long newBookId= db.insert("Book",null,values);
                uriReturn=Uri.parse("content://"+AUTHORITY+"/book/"+newBookId);
                break;
            default:
                break;
        }
        return uriReturn;
    }

3.重写delete方法:

    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // Implement this to handle requests to delete one or more rows.
//        throw new UnsupportedOperationException("Not yet implemented");
        int rows=0;
        SQLiteDatabase db=databaseHelper.getReadableDatabase();
        switch (matcher.match(uri)){
            case BOOK_DIR:
                rows=db.delete("Book",selection,selectionArgs);
                break;
            case BOOK_ITEM:
                String bookId=uri.getPathSegments().get(1);
                rows=db.delete("Book","id = ?",new String[]{bookId});
                break;
            default:
                break;
        }
        return rows;

    }

4.重写query方法:

    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
        // TODO: Implement this to handle query requests from clients.
        Cursor cursor=null;
        SQLiteDatabase db = databaseHelper.getReadableDatabase();
        switch (matcher.match(uri)){
            case BOOK_DIR:
                cursor=db.query("Book",projection,selection,selectionArgs,null,null,sortOrder);
                break;
            case BOOK_ITEM:
                String bookId= uri.getPathSegments().get(1);
                cursor=db.query("Book",projection,"id = ?",new String[]{bookId},null,null,sortOrder);
                break;
            default:
                break;

        }
        return cursor;

    }

5.重写update方法:

    public int update(Uri uri, ContentValues values, String selection,
                      String[] selectionArgs) {
        // TODO: Implement this to handle requests to update one or more rows.
//        throw new UnsupportedOperationException("Not yet implemented");
        int rows=0;
        SQLiteDatabase db=databaseHelper.getReadableDatabase();
        switch (matcher.match(uri)){
            case BOOK_DIR:
                rows=db.update("Book",values,selection,selectionArgs);
                break;
            case BOOK_ITEM:
                String bookId= uri.getPathSegments().get(1);
                rows=db.update("Book",values,"id = ?",new String[]{bookId});
                break;
            default:
                break;
        }
        return rows;
    }

6.重写getType方法:

    public String getType(Uri uri) {
        // TODO: Implement this to handle requests for the MIME type of the data
        // at the given URI.
//        throw new UnsupportedOperationException("Not yet implemented");
        switch (matcher.match(uri)){
            case BOOK_DIR:
                return "vnd.android.cursor.dir/vnd.com.example.databasetest.provider.book";
            case BOOK_ITEM:
                return "vnd.android.cursor.item/vnd.com.example.databasetest.provider.book";
            default:
                break;
        }
        return null;
    }

7.在secondActivity的listView中展现出来,即调用query方法:
oncreate():

        ListView listView=(ListView) findViewById(R.id.second_listview);
        adapter=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,contactsList);
        listView.setAdapter(adapter);
        initialList();

initialList():

    void initialList(){
        Uri uri=Uri.parse("content://com.example.databasetest.provider/book");
        ContentResolver contentResolver=getContentResolver();
        Cursor cursor=null;
        try {
            cursor=contentResolver.query(uri,null,null,null,null);
            if(cursor!=null){
                while (cursor.moveToNext()){
                    String id =cursor.getString(cursor.getColumnIndex("id"));
                    String name=cursor.getString(cursor.getColumnIndex("name"));
                    contactsList.add(id+"\n"+name);
                }
                adapter.notifyDataSetChanged();
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(cursor!=null) {
                cursor.close();
            }
        }

    }

结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值