Android四大组件之一——内容提供器(一)

 

目录

运行时权限

 权限动态申请


       在学习内容提供器值之前,我们需要先掌握另外一个非常重要的知识——Android运行时权限,因为内容提供器实例会使用到运行时权限的功能。当然不光是内容提供器,以后我们的开发过程中,也会经常用到运行时权限,因此我们必须牢牢掌握。

运行时权限

        1、Android的权限机制详解
        (1)、普通权限:指的是那些不会直接威胁到用户的安全和隐私的权限,对这部分权限的申请,系统会自动帮我们进行授权,而不需要用户再去手动操作了。
        (2)、危险权限:则表示那些可能会触及用户或者设备安全性造成影响的权限,如获取设备联系人信息,定位设备地理位置等,对这部分权限申请,必须要由用户手动点击授权才可以,否则程序就无法使用相应的功能。

        下表列出了Android中所有危险的权限,一共是9组24个权限。

 权限动态申请

        新建一个RequestContacts项目,用于读取联系人。

        1. 首先在联系人中随意添加几个姓名及其电话

        2. 在activity_main.xml文件中新建一个ListView用于显示读取到的联系人

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
 
    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/list_contacts"
        />
 
</LinearLayout>

        3. 在MainActivity.java中加入如下代码:

        实现显示联系人的逻辑:

public class MainActivity extends AppCompatActivity {
 
    private ArrayAdapter<String> adapter;
    private ListView contactView;
    private List<String> contactList = new ArrayList<>();
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.activity_main);
        contactView = findViewById(R.id.list_contacts);
        adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, contactList);
        contactView.setAdapter(adapter);
    }
}

        实现动态申请权限的逻辑:

        检查是否有相应的权限需要调用 ContextCompat.checkSelfPermission() 方法,该方法接收两个参数,第一个是Context,第二是具体的权限名。根据应用是否具有相应权限,此方法会返回 PERMISSION_GRANTED 或 PERMISSION_DENIED 。

        requestPermissions() 则用于申请权限。
        ActivityCompat.requestPermissions() 和Activity.requestPermissions()的参数略有区别。ActivityCompat.requestPermissions()接收三个参数,第一个是Activity的实例;第二个是要申请的所有权限,以数组方式传入;第三个是requestCode申请码,需要是从0开始的唯一整数值。

public class MainActivity extends AppCompatActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        ...
        // request app runtime permission
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)
                == PackageManager.PERMISSION_GRANTED) {
            readContacts();
        } else {
            requestPermissions(new String[]{ Manifest.permission.READ_CONTACTS }, 1);
        }
    }
}

        调用了完requestPermissions()之后,系统会弹出一个权限申请的对话框,用户可以选择或者拒绝权限申请,无论结果如何,都会回调onRequestPermissionsResult()方法,重写该方法,用于处理用户的不同选择。

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        if (grantResults == null || grantResults.length == 0) {return;}
        switch (requestCode) {
            case 1:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    readContacts();
                } else {
                    Log.d(PKG + TAG, "onRequestPermissionsResult: You Denied the Permission");
                    Toast.makeText(this, "You Denied the Permission", Toast.LENGTH_SHORT).show();
                }
                break;
            default:
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

         然后处理读取联系人的逻辑。代码如下:

    private void readContacts() {
        Cursor cursor = null;
        try {
            cursor = getContentResolver().query(ContactsContract.CommonDataKinds.
                    Phone.CONTENT_URI, null, null, null, null);
            if (null != cursor) {
                while (cursor.moveToNext()) {
                    String name = cursor.getString(cursor.getColumnIndexOrThrow(
                            ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                    String phoneNumber = cursor.getString(cursor.getColumnIndexOrThrow(
                            ContactsContract.CommonDataKinds.Phone.NUMBER));
                    contactList.add(name + ": " + phoneNumber);
                }
                adapter.notifyDataSetChanged();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != cursor) {cursor.close();};
        }
    }

        最后,别忘了即使是动态申请权限也需要在AndroidManifest.xml文件中加入相关权限声明。

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

         接下来我们学习同时申请几个权限的简单方法:

public void askPermission(){//申请权限
        try {
            List<String> permissionList = new ArrayList<>();
            if (ContextCompat.checkSelfPermission(SuixinWeatherActivity.this, Manifest.permission.ACCESS_FINE_LOCATION)
                    != PackageManager.PERMISSION_GRANTED){
                permissionList.add(Manifest.permission.ACCESS_FINE_LOCATION);
            }
            if (ContextCompat.checkSelfPermission(SuixinWeatherActivity.this,Manifest.permission.READ_PHONE_STATE )
                    != PackageManager.PERMISSION_GRANTED){
                permissionList.add(Manifest.permission.READ_PHONE_STATE);
            }
            if (ContextCompat.checkSelfPermission(SuixinWeatherActivity.this,Manifest.permission.WRITE_EXTERNAL_STORAGE )
                    != PackageManager.PERMISSION_GRANTED){
                permissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
            }
            if (!permissionList.isEmpty()){
                String[] permissions = permissionList.toArray(new String[permissionList.size()]);
                ActivityCompat.requestPermissions(SuixinWeatherActivity.this,permissions,1);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0) {
                    for(int result : grantResults){
                        if (result != PackageManager.PERMISSION_GRANTED) {
                            Toast.makeText(this, "必须所有权限都同意才能使用本应用!", Toast.LENGTH_SHORT).show();
                            finish();
                            return;
                        }
                    }
                }else {
                    Toast.makeText(this, "发生未知错误!", Toast.LENGTH_SHORT).show();
                    finish();
                }
        }
    }

        同时在AndroidMenifest.xml文件中添加如下权限

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  1. askPermission() 方法首先创建一个空的权限列表 permissionList,用于存储需要请求的权限。

  2. 使用 ContextCompat.checkSelfPermission() 方法检查应用程序是否已经被授予了特定权限。如果权限未被授予,则将该权限添加到 permissionList 中。

  3. 如果 permissionList 不为空,将其转换为字符串数组 permissions,然后使用 ActivityCompat.requestPermissions() 方法请求权限。该方法会显示权限请求对话框,让用户决定是否授予权限。请求码参数为 1,可用于在 onRequestPermissionsResult() 方法中进行识别。

  4. onRequestPermissionsResult() 方法是权限请求的回调方法,当用户对权限请求作出响应时会被调用。

  5. 在 onRequestPermissionsResult() 方法中,首先检查请求码 requestCode 是否与之前请求的一致。

  6. 如果 grantResults 数组的长度大于 0,表示用户已经做出了权限请求的响应。然后遍历 grantResults 数组,检查每个权限的授权结果。

  7. 如果有任何一个权限未被授予(PackageManager.PERMISSION_GRANTED),则显示一个提示消息,并且关闭当前的活动。

  8. 如果 grantResults 数组的长度为 0,表示发生了未知错误,显示一个错误提示消息,并且关闭当前的活动。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值