1. 程式人生 > >關於Android6.0許可權適配的問題

關於Android6.0許可權適配的問題

1.適配的背景

由於Android系統的碎片化嚴重,適配成了不可或缺的重要步驟;最近在專案中負責Android6.0的各種危險許可權的適配,今天藉此機會,向大家分享一下適配的原理。

2.藍芽許可權的適配

    有人會問為什麼把藍芽許可權單獨拿出來說,我只能回答,藍芽許可權有些特別,開啟藍芽搜尋的時候,模糊定位也就開啟了,而重要的是,模糊定位是一種危險的許可權,在Android6.0中最好做做必要的適配工作;下面我將採取Android官方的方式進行藍芽適配。

2.1 Android 6.0之前,使用藍芽功能只需要在Manifest檔案中新增如下許可權:

<uses-permission android
:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
2.2 Android6.0及以上版本,使用藍芽掃描,需要新增模糊定位的許可權:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
並且該許可權在使用時,需要動態的去申請。
2.3適配程式碼:
public class MainActivity extends 
AppCompatActivity { private static final int MY_PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION = 100; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.bluetooth).setOnClickListener
(new View.OnClickListener() { @Override public void onClick(View view) { checkBluetoothPermission(); } }); } /* 校驗藍芽許可權 */ private void checkBluetoothPermission() { if (Build.VERSION.SDK_INT >= 23) { //校驗是否已具有模糊定位許可權 if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, MY_PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION); } else { //具有許可權 connectBluetooth(); } } else { //系統不高於6.0直接執行 connectBluetooth(); } } /** * 對返回的值進行處理,相當於StartActivityForResult * @param requestCode * @param permissions * @param grantResults */ @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); doNext(requestCode, grantResults); } private void doNext(int requestCode, int[] grantResults) { if (requestCode == MY_PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { //同意權限,做跳轉邏輯 connectBluetooth(); } else { // 許可權拒絕,提示使用者開啟許可權 denyPermission(); } } } private void denyPermission() { Toast.makeText(MainActivity.this,"藍芽許可權已經拒絕!",Toast.LENGTH_SHORT).show(); } private void connectBluetooth() { Toast.makeText(MainActivity.this,"連線藍芽成功!",Toast.LENGTH_SHORT).show(); } }
效果圖:

3.其他許可權的適配

3.1 除了藍芽許可權,還有相機,讀寫,定位等危險許可權在Android6.0要進行適配。這裡我引用了一個第三方適配框架AndPermission
compile 'com.yanzhenjie:permission:1.0.2'
3.2 適配步驟: ①在Activity中進行適配
public class PermissionActivity extends AppCompatActivity implements View.OnClickListener{
    @Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.permission_activity);

        findViewById(R.id.test_calendar).setOnClickListener(this);
        findViewById(R.id.test_contacts_sms).setOnClickListener(this);
    }

    /**
     * 寫日曆
*/
private void requestCalendarPermission(){
        AndPermission.with(this)
                     .requestCode(100)
                     .permission(Manifest.permission.WRITE_CALENDAR)
                     .send();
    }
    @PermissionYes(100)
   private void getCalendarYes(){
        Toast.makeText(this,"獲取日曆成功",Toast.LENGTH_SHORT).show();
    }

    @PermissionNo(100)
    private void getCalendarNo(){
        Toast.makeText(this,"獲取日曆失敗",Toast.LENGTH_SHORT).show();
    }

    /**
     * 聯絡人,簡訊
*/
private void requestContactsAndSMS(){
        AndPermission.with(this)
                     .requestCode(101)
                     .permission(Manifest.permission.WRITE_CONTACTS,Manifest.permission.READ_SMS)
                     .send();

    }
    @PermissionYes(101)
    private void getContactsAndSMSYes(){
        Toast.makeText(this,"獲取聯絡人,簡訊成功",Toast.LENGTH_SHORT).show();
    }
    @PermissionNo(101)
    private void getContactAndSMSNo(){
        Toast.makeText(this,"獲取聯絡人,簡訊失敗",Toast.LENGTH_SHORT).show();

    }

    @Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
       // super.onRequestPermissionsResult(requestCode, permissions, grantResults);
AndPermission.onRequestPermissionsResult(this,requestCode,permissions,grantResults);
    }

    @Override
public void onClick(View view) {
     switch (view.getId()){
         case R.id.test_calendar:
requestCalendarPermission();
             break;

         case R.id.test_contacts_sms:
requestContactsAndSMS();
             break;
     }
    }
}
②在Fragment中進行適配
public class PermissionFragment extends AppCompatActivity {
    @Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fragment_layout);
        getSupportFragmentManager().beginTransaction().add(R.id.fragmentLayout,new FragmentPermission(),"permissionFragment").commit();
    }

    @Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}
然後在Fragment進行適配
public class FragmentPermission extends Fragment implements View.OnClickListener {
    @Nullable
    @Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.permission_fragment,container,false);
    }

    @Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        view.findViewById(R.id.test_phone_state).setOnClickListener(this);
        view.findViewById(R.id.test_sensor).setOnClickListener(this);
    }

    @Override
public void onClick(View view) {
        switch (view.getId()){
            case R.id.test_phone_state:
requestPhoneState();
                break;
            case R.id.test_sensor:
requestSensor();
                break;
        }

    }

    /**
     * 感測器
*/
private void requestSensor() {
        AndPermission.with(this)
                .requestCode(104)
                .permission(Manifest.permission.BODY_SENSORS)
                .send();
    }
    @PermissionYes(104)
    private void getSensorYes(){
        Toast.makeText(getContext(),"獲取感測器成功",Toast.LENGTH_SHORT).show();
    }
    @PermissionNo(104)
    private void getSensorNo(){
        Toast.makeText(getContext(),"獲取感測器失敗",Toast.LENGTH_SHORT).show();
    }




    /**
     * 手機狀態
*/
private void requestPhoneState() {
        AndPermission.with(this)
                     .requestCode(103)
                     .permission(Manifest.permission.READ_PHONE_STATE)
                     .send();
    }
    @PermissionYes(103)
    private void getPhoneStateYes(){
        Toast.makeText(getContext(),"獲取手機狀態成功",Toast.LENGTH_SHORT).show();
    }
    @PermissionNo(103)
    private void getPhoneStateNo(){
        Toast.makeText(getContext(),"獲取手機狀態失敗",Toast.LENGTH_SHORT).show();
    }

    @Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        //super.onRequestPermissionsResult(requestCode, permissions, grantResults);
AndPermission.onRequestPermissionsResult(this,requestCode,permissions,grantResults);
    }
}
③通過Listener 回撥成功或失敗事件(推薦)
public class ListenerActivity extends AppCompatActivity implements View.OnClickListener{
    @Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.listener_layout);
        findViewById(R.id.btn_request_location).setOnClickListener(this);
    }

    /**
     * 申請SD卡許可權
*/
private void requestLocationPermission() {
        AndPermission.with(this)
                .requestCode(100)
                .permission(Manifest.permission.ACCESS_FINE_LOCATION)
                .rationale(rationaleListener)
                .send();
    }

    private RationaleListener rationaleListener = new RationaleListener() {
        @Override
public void showRequestPermissionRationale(int requestCode,final Rationale rationale) {
            new AlertDialog.Builder(ListenerActivity.this)
                    .setTitle("友好提醒")
                    .setMessage("您已拒絕過定位許可權,沒有定位許可權無法為您推薦附近妹子,請把定位許可權賜給我吧!")
                    .setPositiveButton("好,給你", new DialogInterface.OnClickListener() {
                        @Override
public void onClick(DialogInterface dialog, int which) {
                            dialog.cancel();
                            rationale.resume();
                        }
                    })
                    .setNegativeButton("我拒絕", new DialogInterface.OnClickListener() {
                        @Override
public void onClick(DialogInterface dialog, int which) {
                            dialog.cancel();
                            rationale.cancel();
                        }
                    }).show();
        }
    };

    @PermissionYes(100)
    private void getLocationYes() {
        Toast.makeText(this, "獲取定位許可權成功", Toast.LENGTH_SHORT).show();
    }

    @PermissionNo(100)
    private void getLocationNo() {
        Toast.makeText(this, "獲取定位許可權失敗", Toast.LENGTH_SHORT).show();
    }

    @Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        // 這個Activity中沒有Fragment,這句話可以註釋。
// super.onRequestPermissionsResult(requestCode, permissions, grantResults);
AndPermission.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
    }

    @Override
public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_request_location: {
                requestLocationPermission();
                break;
            }
        }
    }
}
好了,適配就說這麼多了,有木有很簡單啊!我是張星,歡迎您的關注,後期更精彩!原始碼地址:http://download.csdn.net/detail/zhangxing52077/9706043