【Android学习笔记】 运行时权限及内容提供器的基本使用

运行时权限

在Android6.0版本之后引入,用户可以对应用程序进行选择性授权,即使拒绝了这个权限,依旧可以使用该应用的其他功能。

Android所有的危险权限一共有9组24个权限:

Dangerous Permissions:
  group:android.permission-group.CONTACTS
          permission:android.permission.WRITE_CONTACTS
          permission:android.permission.GET_ACCOUNTS
          permission:android.permission.READ_CONTACTS

   group:android.permission-group.PHONE
          permission:android.permission.READ_CALL_LOG
          permission:android.permission.READ_PHONE_STATE
          permission:android.permission.CALL_PHONE
          permission:android.permission.WRITE_CALL_LOG
          permission:android.permission.USE_SIP
          permission:android.permission.PROCESS_OUTGOING_CALLS
          permission:com.android.voicemail.permission.ADD_VOICEMAIL

    group:android.permission-group.CALENDAR
          permission:android.permission.READ_CALENDAR
          permission:android.permission.WRITE_CALENDAR

    group:android.permission-group.CAMERA
          permission:android.permission.CAMERA

    group:android.permission-group.SENSORS
          permission:android.permission.BODY_SENSORS

    group:android.permission-group.LOCATION
          permission:android.permission.ACCESS_FINE_LOCATION
          permission:android.permission.ACCESS_COARSE_LOCATION

    group:android.permission-group.STORAGE
          permission:android.permission.READ_EXTERNAL_STORAGE
          permission:android.permission.WRITE_EXTERNAL_STORAGE

    group:android.permission-group.MICROPHONE
          permission:android.permission.RECORD_AUDIO

    group:android.permission-group.SMS
          permission:android.permission.READ_SMS
          permission:android.permission.RECEIVE_WAP_PUSH
          permission:android.permission.RECEIVE_MMS
          permission:android.permission.RECEIVE_SMS
          permission:android.permission.SEND_SMS
          permission:android.permission.READ_CELL_BROADCASTS

注意:一旦用户授权了一个权限,该权限所对应的权限组中的所有的其他权限也会同时被授权。

在程序运行时申请权限

先修改AndroidManifest.xml文件如下:

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

申请运行时权限核心代码:

onClick(){ 
    //如果用户未授权拨打电话权限,申请运行时权限     
    if(ContextCompat.checkSelfPermission(MainActivity.this,Manifest.     
    permission.CALL_PHONE)!=PackageManager.PERMISSION_GRANTED){ 
        //参数1:Activity的实例;参数2:String数组,放置需要申请的权限名 
        //参数3:请求码,只要是唯一值就可以了 
        ActivityCompat.requestPermissions(MainActivity.this,new String[] {
        Manifest.permission.CALL_PHONE},1); 
    }else{ 
        call(); 
    } 
} 

call(){ 
    try{ 
        Intent intent = new Intent(Intent.ACTION_CALL); 
        intent.setData(Uri.parse("tel:10086")); 
        startActivity(intent); 
    }catch(Exception e){ 
        ... 
    } 
}

//调用完requestPermission()方法后,无论用户是否授权,最终都会回调到此方法中 
public void onRequestPermissionsResult(int requestCode,String[] permissions, int[] grantResults){
    switch(requestCode){ 
        case 1: 
            if(grantResults.length>0 && grantResults[0]==PackageManager.     
            PERMISSION_GRANTED){
                call(); 
            }else{ 
                Toast.makeText(this,"you denied the permission",Toast.     
                LENGTH_SHORT).show(); 
            } 
            break;
        default:
    } 
}

 

内容提供器

访问其他程序中的数据

如果想要访问内容提供器中共享的数据,一定要借助ContentResolver类。

ContentResolver类提供了与SQLiteDatabase类相似的一系列方法对数据进行CRUD操作。

ContentResolver类不接受表名参数,而是接收一个Uri参数。

这个内容URI由authority和path两部分组成,authority是用于对不同的应用作区分的,一般采用程序包名的方式来进行命名;path则是用于对同一程序中不同的表做区分的,通常都会添加到authority后面。

如:content://com.example.app.provider/table1

得到了内容URI字符串后,还需要将它解析为Uri对象才能作为参数传入:

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

使用上述uri查询table1表中的数据:

//参数1:指定查询某个应用程序下的某一张表;参数2:指定查询的列名; 
//参数3:指定where的约束条件;参数4:为where中的占位符提供具体的值 
//参数5:指定查询结果的排序方式 
Cursor cursor = getContentResolver().query( uri, projection, selection, selectionArgs, sortOrder ); 
if(cursor!=null){ 
    while(cursor.moveToNext()){ 
        String column1 = cursor.getString(cursor.getColumnIndex("column1"));
        int column2 = cursor.getInt(cursor.getColumnIndex("column2"));
    } 
    cursor.close(); 
}

添加数据核心代码:

ContentValues values = new ContentValues(); 
values.put("column1","text"); 
values.put("column2",1); 
getContentResolver().insert(uri,values);

修改数据核心代码:

ContentValues values = new ContentValues(); 
values.put("column1",""); 
getContentResolver().update(uri,values,"column1 = ? and column2 = ?", 
new string[]{"text","1"});

删除数据核心代码:

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

读取系统联系人信息:

步骤1 核心代码实现:

onCreate(){ 
    ListView contactsView = (ListView)findViewById(...); 
    adapter = new ArrayAdapter(...); 
    contactsView.setAdapter(adapter); 
    //如果未授权读取联系人权限,申请授权     
    if(ContextCompat.checkSelfPermission(this,Manifest.permission.READ_     
    CONTACTS)!=PackageManager.PERMISSION_GRANTED){ 
        ActivityCompat.requestPermissions(this,new String[]{Manifest.per     
        mission.READ_CONTACTS},1); 
    }else{ 
        readContacts(); 
    } 
} 

readContacts(){ 
    Cursor cursor = null; 
    try{ 
        //查询联系人数据 
        cursor = getContentResolver().query(ContactsContract.CommonDataKinds. 
        Phone.CONTENT_URI,null,null,null.null); 
        if(cursor!=null){ 
            while(cursor.moveToNext()){ 
                //获取联系人姓名 
                String displayName = cursor.getString(cursor.getColumnIndex 
                (ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); 
                //获取联系人手机号 
                String number = cursor.getString(cursor.getColumnIndex 
                (ContactsContract.CommonDataKinds.Phone.NUMBER));         
                contactsList.add(displayName+"\n"+number); 
            } 
        adapter.notifyDataSetChanged(); 
        } 
    }catch(Exception e){
        ... 
    }finally{ 
        if(cursor!=null){ 
            cursor.close(); 
        } 
    } 
} 

public void onRequestPermissionsResult(int requestCode,String[] permissions, int[] grantResults){ 
    switch(requestCode){ 
        case 1: 
            if(grantResults.length>0 && grantResults[0]==PackageManager. 
            PERMISSION_GRANTED){ 
                readContacts(); 
            }else{ 
                Toast.makeText(this,"you denied the permission",Toast. 
                LENGTH_SHORT).show(); 
            } 
            break; 
        default: 
    } 
}

步骤2 配置读取系统联系人的权限:

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

创建自己的内容提供器

自定义内容提供器核心代码:

class MyProvider extends ContentProvider{ 
    //初始化内容提供器时调用,一般在这完成数据库的创建和升级操作 
    boolean onCreate(){ 
        return false; 
    } 

    //从内容提供器中查询数据 
    Cursor query(Uri uri,String[] projection,String selection,String[] selectionArgs
    ,StringsortOrder){ 
        return null; 
    } 

    //向内容提供器中添加数据,添加完成后,返回一个用于表示这条新记录的URI 
    Uri insert(Uri uri,ContentValues values){ 
        return null; 
    } 

    //更新内容提供器中已有的数据,返回受影响的行数 
    int update(Uri uri,ContentValues values,String selection,String[] selectionArgs){ 
        return 0; 
    } 

    //从内容提供器中删除数据,返回受影响的行数 
    int delete(Uri uri,String selection,String[] selectionArgs){ 
        return 0; 
    } 

    //根据传入的内容URI来返回相应的MIME类型 
    String getType(Uri uri){ 
        return null; 
    } 
}

借助UriMatcher这个类可以轻松匹配内容URI的功能

核心代码实现:

class MyProvider extends ContentProvider{ 
    public static final int TABLE1_DIR = 0; 
    public static final int TABLE1_ITEM = 1; 
    public static final int TABLE1_DIR = 2; 
    public static final int TABLE1_ITEM = 3; 
    private static UriMatcher uriMatcher; 

    static{ 
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 
        //参数1:authority;参数2:path;参数3:自定义代码         
        uriMatcher.addURI("com.example.app.provider","table1",TABLE1_DIR);     
        uriMatcher.addURI("com.example.app.provider","table1/#",TABLE1_ITEM); 
        uriMatcher.addURI("com.example.app.provider","table2",TABLE2_DIR); 
        uriMatcher.addURI("com.example.app.provider","table2/#",TABLE2_ITEM); 
    } 

    Cursor query(Uri uri,String[] projection,String selection,String[] selectionArgs,String sortOrder){ 
        //调用UriMatcher的match()方法时,返回值是某个能够匹配这个Uri对象 
        //所对应的自定义代码 
        switch(uriMatcher.match(uri){ 
            case TABLE1_DIR: 
                //查询table1表中的所有数据 
                break; 
            case TABLE1_ITEM: 
                //查询table1表中的单条数据 
                break; 
            case TABLE2_DIR: 
                //查询table2表中的所有数据 
                break; 
            case TABLE2_ITEM: 
                //查询table2表中的单条数据 
                break; 
            default: 
                break; 
        }
    }
}

getType()是所有内容提供器都必须提供的方法,用于获取Uri对象所对应的MIME类型。

一个内容URI所对应的MIME字符串主要由三部分组成:

1 必须以vnd开头

2 如果内容URI以路径结尾,则后接android.cursir.dir/,如果内容URI以id结尾,则后接android.cursir.item/

3 最后接上vnd.<authority>.<path>

完善MyProvider代码:

String getType(Uri uri){ 
    switch(uriMatcher.match(uri){ 
        case TABLE1_DIR: 
            return "vnd.android.cursor.dir/vnd.com.example.app.provider.table1"; 
        case TABLE1_ITEM: 
            return "vnd.android.cursor.item/vnd.com.example.app.provider.table1"; 
        case TABLE2_DIR: 
            return "vnd.android.cursor.dir/vnd.com.example.app.provider.table2"; 
        case TABLE2_ITEM: 
            return "vnd.android.cursor.item/vnd.com.example.app.provider.table2"; 
        default: 
            break; 
    } 
    return null;
}

参考书籍:《第一行代码》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. Android基本概念 Android 是一个开源的操作系统,主要用于移动设备,如智能手机、平板电脑等。它基于 Linux 内核,提供了丰富的应用程序框架和 API,支持多种开发语言,如 Java、C/C++、Kotlin 等。 Android 应用程序由多个组件组成,包括活动(Activity)、服务(Service)、广播接收(Broadcast Receiver)和内容提供(Content Provider)等。这些组件可以组合在一起,形成复杂的应用程序。 2. Android 应用程序开发 Android 应用程序开发主要使用 Java 编程语言和 Android SDK。开发工具包括 Android Studio、Eclipse 等。 Android 应用程序的结构包括布局文件、资源文件、Java 代码和清单文件等。布局文件用于定义应用程序的用户界面,资源文件包括图像、声音、样式、主题等,Java 代码实现应用程序的逻辑,清单文件描述应用程序的组件和权限等信息。 3. Android 应用程序的调试和测试 Android 应用程序的调试和测试可以使用 Android Studio 提供的调试工具,包括断点调试、日志记录等。还可以使用模拟或真实设备进行测试。 4. Android 应用程序的发布 发布 Android 应用程序需要进行签名和打包操作,签名用于验证应用程序的身份和完整性,打包将应用程序打包成 APK 文件,可以上传到应用商店进行发布。 5. Android 应用程序的优化 Android 应用程序的优化包括优化布局、资源、代码和网络等方面,以提高应用程序的性能和用户体验。其中,布局优化包括使用布局最优化算法、使用自定义视图等;资源优化包括压缩资源、使用向量图形等;代码优化包括使用异步任务、使用缓存等;网络优化包括使用数据压缩、使用本地存储等。 6. Android 开发的挑战 Android 开发面临的挑战包括设备碎片化、安全问题、性能问题等。设备碎片化指的是不同设备的屏幕尺寸、分辨率、操作系统版本等不同,需要对应用程序进行适配;安全问题指的是应用程序需要保证用户数据的安全和隐私;性能问题指的是应用程序需要保证快速响应和流畅运行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值