从 Android 6.0(API 级别 23)开始,用户开始在应用运行时向其授予权限,而不是在应用安装时授予。此方法可以简化应用安装过程,因为用户在安装或更新应用时不需要授予权限。它还让用户可以对应用的功能进行更多控制;例如,用户可以选择为相机应用提供相机访问权限,而不提供设备位置的访问权限。用户可以随时进入应用的“Settings”屏幕调用权限。
系统权限分为两类:正常权限 和 危险权限:
正常权限不会直接给用户隐私权带来风险。如果您的应用在其清单中列出了正常权限,系统将自动授予该权限。
危险权限会授予应用访问用户机密数据的权限。如果您的应用在其清单中列出了正常权限,系统将自动授予该权限。如果您列出了危险权限,则用户必须明确批准您的应用使用这些权限。
以下为9组危险权限
权限组 | 权限 |
---|---|
CALENDAR |
|
CAMERA |
|
CONTACTS |
|
LOCATION |
|
MICROPHONE |
|
PHONE |
|
SENSORS |
|
SMS |
|
STORAGE |
|
在Android6.0之前,我们只需要通过下面的代码将这些权限写在Mainfest.xml文件即可。
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.xxx" />
而在Android6.0以上的系统版本中,如果只是在Mainfest.xml文件里面申请是会被默认拒绝该权限的。比如你没有申请拨打电话的权限,进行拨号操作,这个时候是会报异常的。
下面我们来看一下Android6.0运行时权限的申请,话不多说,直接上代码看注释。
package com.example.permissionsapply;
import android.Manifest;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
public class Main2Activity extends AppCompatActivity {
public static final int request_Permissions_Request_Code = 88;
private static final String TAG = "Main2Activity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
findViewById(R.id.btn2_call_phone).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
applyPermission();
}
});
}
/**
* 申请权限
*/
private void applyPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
/**
* @see #requestPermissions(String[], int)
* 第一个参数是需要申请的权限,需要请求几个权限就在数组里面添加几个
* 第二个参数是请求回调的标示码,通过onRequestPermissionsResult(int requestCode, @NonNull
* String[] permissions, @NonNull int[] grantResults)的requestCode参数返回
*/
requestPermissions(new String[]{Manifest.permission.CALL_PHONE,Manifest.permission.ACCESS_FINE_LOCATION},request_Permissions_Request_Code);
}
}
/**
* 当申请权限的时候回调该方法。(给用户弹出对话框提示用户是否通过权限,当用户点击拒绝或同意的时候就回调该方法。
* 如果用户已经 同意/拒绝 该权限则不会弹出对话框,这个时候会直接回调该方法。)
* @param requestCode 通过 requestPermissions(String[], int)方法请求权限的时候传入的requestCode
* @param permissions 请求的权限
* @param grantResults 请求的权限所对应的返回结果,同意=0 拒绝=-1 参考{@link android.content.pm.PackageManager#PERMISSION_GRANTED}
* 和 {@link android.content.pm.PackageManager#PERMISSION_DENIED}.
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
Log.i(TAG,"requestCode = " +requestCode);
for (int i = 0; i < permissions.length; i++) {
Log.i(TAG,"权限:" + permissions[i] + " ,grantResults = " +grantResults[i]);
}
}
}
当然,在Mainfest.xml里面还是需要加上下面的代码,否则是无法弹出权限申请对话框的,会直接回调onRequestPermissionsResult(…)方法,并返回拒绝的状态。
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
上面的方法就可以完成对权限的申请,如果我们的权限已经被同意,那么我们就没有必要每次都去申请了。所以在申请权限之前,我们做一下判断。
public class Main2Activity extends AppCompatActivity {
public static final int request_Permissions_Request_Code = 88;
private static final String TAG = "Main2Activity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
findViewById(R.id.btn2_call_phone).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//通过该方法检测某个权限是否被用户同意
if (ActivityCompat.checkSelfPermission(Main2Activity.this, Manifest.permission.CALL_PHONE)
!= PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(Main2Activity.this,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
applyPermission();
return ;
}
}
});
}
/**
* 申请权限
*/
private void applyPermission() {
......
}
经常看到群里有同学问怎么我返回的一直是0呢。事情是这样样子的,你肯定用的是6.0以下的系统,而且已经在mainfest文件里面已经申请权限了。如果你用的是6.0以上的系统,那你就是点击允许该权限了。
如果嫌上面Activity里面的代码写的多,没有关系,我们可以通过几行代码就可以完成上述操作。只是需要进行封装(网上找的封装,时间长了忘记作者了,所以在这里就没写作者)。
package com.example.permissionsapply;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.example.permissionsapply.permissions.PermissionResultAdapter;
import com.example.permissionsapply.permissions.PermissionUtil;
public class MainActivity extends AppCompatActivity {
private final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_call_phone).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
applyCallPhonePermission();
}
});
}
/**
* 申请拨打电话的权限
*/
private void applyCallPhonePermission() {
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
//申请拨打电话的权限
PermissionUtil.getInstance().request(this, new String[]{Manifest.permission.CALL_PHONE}, new PermissionResultAdapter() {
@Override
public void onPermissionGranted() {
callPhone("10086");
Log.d(TAG,"权限通过");
}
});
} else {
callPhone("10086");
}
}
/**
* 拨打电话
*/
private void callPhone(String phone) {
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "请打开拨打电话权限", Toast.LENGTH_SHORT).show();
return;
}
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + phone));
MainActivity.this.startActivity(intent);
}
}
是不是变的简单多了,封装的代码比较多,我就不再这里贴出来了。需要的朋友可以在下面的地址下载
Git地址: https://code.csdn.net/chengliang0315/permissionsapply.git
资源包 : http://download.csdn.net/detail/chengliang0315/9751451