App涉及到硬件设备的操作,比如拍照、录音、定位、SD卡等等,都要在AndroidManifest.xml中声明相关的权限。
可是Android系统为了防止某些App滥用权限,又允许用户在系统设置里面对App禁用某些权限。
但这又带来另一个问题,用户打开App之后,App可能因为权限不足导致无法正常运行,甚至直接崩溃闪退。
有鉴于此,Android从6.0开始引入了运行时权限管理机制,允许App在运行过程中动态检查是否拥有某项权限,一旦发现缺少某种必需的权限,则系统会自动弹出小窗提示用户去开启该权限。
(1)检查App是否开启了指定权限
调用ContextCompat的checkSelfPermission方法。
(2)请求系统弹窗,以便用户选择是否开启权限
调用ActivityCompat的requestPermissions方法,即可命令系统自动弹出权限申请窗口。
(3)判断用户的权限选择结果
重写活动页面的权限请求回调方法onRequestPermissionsResult,在该方法内部处理用户的权限选择结果。
权限:
<!-- 存储卡读写 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Android10新增权限MANAGE_EXTERNAL_STORAGE --> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> <!-- 联系人/通讯录。包括读联系人、写联系人 --> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_CONTACTS" /> <!-- 短信。包括发送短信、接收短信、读短信 --> <uses-permission android:name="android.permission.SEND_SMS" /> <uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.READ_SMS" /> <!-- 通话记录。包括读通话记录、写通话记录 --> <uses-permission android:name="android.permission.READ_CALL_LOG" /> <uses-permission android:name="android.permission.WRITE_CALL_LOG" /> <!-- 安装应用请求,Android8.0需要 --> <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /> <!-- 获取媒体位置(Android10新增权限) --> <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
PermissionUtil
package com.example.myapplication.util; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Build; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; public class PermissionUtil { private final static String TAG = "PermissionUtil"; // 检查某个权限。返回true表示已启用该权限,返回false表示未启用该权限 public static boolean checkPermission(Activity act, String permission, int requestCode) { return checkPermission(act, new String[]{permission}, requestCode); } // 检查多个权限。返回true表示已完全启用权限,返回false表示未完全启用权限 public static boolean checkPermission(Activity act, String[] permissions, int requestCode) { boolean result = true; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { int check = PackageManager.PERMISSION_GRANTED; // 通过权限数组检查是否都开启了这些权限 for (String permission : permissions) { check = ContextCompat.checkSelfPermission(act, permission); if (check != PackageManager.PERMISSION_GRANTED) { break; // 有个权限没有开启,就跳出循环 } } if (check != PackageManager.PERMISSION_GRANTED) { // 未开启该权限,则请求系统弹窗,好让用户选择是否立即开启权限 ActivityCompat.requestPermissions(act, permissions, requestCode); result = false; } } return result;
} // 检查权限结果数组,返回true表示都已经获得授权。返回false表示至少有一个未获得授权 public static boolean checkGrant(int[] grantResults) { boolean result = true; if (grantResults != null) { for (int grant : grantResults) // 遍历权限结果数组中的每条选择结果 { if (grant != PackageManager.PERMISSION_GRANTED) { // 未获得授权 result = false; } } } else { result = false; } return result; } }
权限校验:
package com.example.myapplication; import android.Manifest; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import com.example.myapplication.util.PermissionUtil; public class MainActivity extends AppCompatActivity implements View.OnClickListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.btn_next1).setOnClickListener(this); findViewById(R.id.btn_next2).setOnClickListener(this); } @Override public void onClick(View v) { if (PermissionUtil.checkPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE, R.id.btn_next1 % 65536)) { startActivity(new Intent(this, ContentWriteActivity.class)); } else { Toast.makeText(this, "需要允许存储卡权限噢", Toast.LENGTH_SHORT).show(); } if (v.getId() == R.id.btn_next2) { startActivity(new Intent(this, ContentReadActivity.class)); //创建一个目标确定的意图 } } }
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ScrollView android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingBottom="10dp" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:gravity="center" android:text="7.1 在应用之间共享数据" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/btn_content_write" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="写入共享内容" /> <Button android:id="@+id/btn_content_read" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="读取共享内容" /> </LinearLayout> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:gravity="center" android:text="7.2 获取通讯信息" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/btn_file_write" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="公共空间写入文本文件" /> <Button android:id="@+id/btn_file_read" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="公共空间读取文本文件" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/btn_contact_add" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="添加联系人" /> <Button android:id="@+id/btn_contact_read" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="读取联系人" /> <Button android:id="@+id/btn_monitor_sms" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="流量校准" /> </LinearLayout> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:gravity="center" android:text="7.3 在应用之间共享文件" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/btn_send_mms" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="发送彩信(通过系统相册)" /> <Button android:id="@+id/btn_provider_mms" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="发送彩信(Provider方式)" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/btn_provider_apk" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="安装应用" /> </LinearLayout> </LinearLayout> </ScrollView> </LinearLayout>
package com.example.chapter07; import android.Manifest; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import com.example.chapter07.util.PermissionUtil; public class MainActivity extends AppCompatActivity implements View.OnClickListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.btn_content_write).setOnClickListener(this); findViewById(R.id.btn_content_read).setOnClickListener(this); findViewById(R.id.btn_file_write).setOnClickListener(this); findViewById(R.id.btn_file_read).setOnClickListener(this); findViewById(R.id.btn_contact_add).setOnClickListener(this); findViewById(R.id.btn_contact_read).setOnClickListener(this); findViewById(R.id.btn_monitor_sms).setOnClickListener(this); findViewById(R.id.btn_send_mms).setOnClickListener(this); findViewById(R.id.btn_provider_mms).setOnClickListener(this); findViewById(R.id.btn_provider_apk).setOnClickListener(this); } @Override public void onClick(View v) { if (v.getId() == R.id.btn_content_write) { Intent intent = new Intent(this, ContentWriteActivity.class); startActivity(intent); } else if (v.getId() == R.id.btn_content_read) { Intent intent = new Intent(this, ContentReadActivity.class); startActivity(intent); } else if (v.getId() == R.id.btn_file_write) { if (PermissionUtil.checkPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE, R.id.btn_file_write % 65536)) { startActivity(new Intent(this, FileWriteActivity.class)); } } else if (v.getId() == R.id.btn_file_read) { if (PermissionUtil.checkPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE, R.id.btn_file_read % 65536)) { startActivity(new Intent(this, FileReadActivity.class)); } } else if (v.getId() == R.id.btn_contact_add) { if (PermissionUtil.checkPermission(this, Manifest.permission.WRITE_CONTACTS, R.id.btn_contact_add % 65536)) { startActivity(new Intent(this, ContactAddActivity.class)); } } else if (v.getId() == R.id.btn_contact_read) { if (PermissionUtil.checkPermission(this, Manifest.permission.READ_CONTACTS, R.id.btn_contact_read % 65536)) { startActivity(new Intent(this, ContactReadActivity.class)); } } else if (v.getId() == R.id.btn_monitor_sms) { if (PermissionUtil.checkPermission(this, new String[] {Manifest.permission.SEND_SMS, Manifest.permission.READ_SMS}, R.id.btn_monitor_sms % 65536)) { startActivity(new Intent(this, MonitorSmsActivity.class)); } } else if (v.getId() == R.id.btn_send_mms) { Intent intent = new Intent(this, SendMmsActivity.class); startActivity(intent); } else if (v.getId() == R.id.btn_provider_mms) { if (PermissionUtil.checkPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE, R.id.btn_provider_mms % 65536)) { startActivity(new Intent(this, ProviderMmsActivity.class)); } } else if (v.getId() == R.id.btn_provider_apk) { if (PermissionUtil.checkPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE, R.id.btn_provider_apk % 65536)) { startActivity(new Intent(this, ProviderApkActivity.class)); } } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); // requestCode不能为负数,也不能大于2的16次方即65536 if (requestCode == R.id.btn_file_write % 65536) { if (PermissionUtil.checkGrant(grantResults)) { // 用户选择了同意授权 startActivity(new Intent(this, FileWriteActivity.class)); } else { //ToastUtil.show(this, "需要允许存储卡权限才能写入公共空间噢"); Toast.makeText(this, "需要允许存储卡权限才能写入公共空间噢", Toast.LENGTH_SHORT).show(); } } else if (requestCode == R.id.btn_file_read % 65536) { if (PermissionUtil.checkGrant(grantResults)) { // 用户选择了同意授权 startActivity(new Intent(this, FileReadActivity.class)); } else { Toast.makeText(this, "需要允许存储卡权限才能读取公共空间噢", Toast.LENGTH_SHORT).show(); } } else if (requestCode == R.id.btn_contact_add % 65536) { if (PermissionUtil.checkGrant(grantResults)) { // 用户选择了同意授权 startActivity(new Intent(this, ContactAddActivity.class)); } else { Toast.makeText(this, "需要允许通讯录权限才能读写联系人噢", Toast.LENGTH_SHORT).show(); } } else if (requestCode == R.id.btn_contact_read % 65536) { if (PermissionUtil.checkGrant(grantResults)) { // 用户选择了同意授权 startActivity(new Intent(this, ContactReadActivity.class)); } else { Toast.makeText(this, "需要允许通讯录权限才能读写联系人噢", Toast.LENGTH_SHORT).show(); } } else if (requestCode == R.id.btn_monitor_sms % 65536) { if (PermissionUtil.checkGrant(grantResults)) { // 用户选择了同意授权 startActivity(new Intent(this, MonitorSmsActivity.class)); } else { Toast.makeText(this, "需要允许短信权限才能校准流量噢", Toast.LENGTH_SHORT).show(); } } else if (requestCode == R.id.btn_provider_mms % 65536) { if (PermissionUtil.checkGrant(grantResults)) { // 用户选择了同意授权 startActivity(new Intent(this, ProviderMmsActivity.class)); } else { Toast.makeText(this, "需要允许存储卡权限才能发送彩信噢", Toast.LENGTH_SHORT).show(); } } else if (requestCode == R.id.btn_provider_apk % 65536) { if (PermissionUtil.checkGrant(grantResults)) { // 用户选择了同意授权 startActivity(new Intent(this, ProviderApkActivity.class)); } else { Toast.makeText(this, "需要允许存储卡权限才能安装应用噢", Toast.LENGTH_SHORT).show(); } } } }
标签:btn,复习,class,else,Intent,权限,id,动态 From: https://www.cnblogs.com/xiaobaibailongma/p/16610115.html