Android 6.0動(dòng)態(tài)權(quán)限介紹與處理

從 Android 6.0(API 級(jí)別 23)開(kāi)始砍艾,用戶開(kāi)始在應(yīng)用運(yùn)行時(shí)向其授予權(quán)限悯衬,而不是在應(yīng)用安裝時(shí)授予码耐。 Android 6.0系統(tǒng)6.0以前追迟,所有的權(quán)限,訪問(wèn)網(wǎng)絡(luò)的權(quán)限骚腥,讀取SD卡的權(quán)限敦间,訪問(wèn)通訊錄,撥打電話的權(quán)限都在安裝的時(shí)候系統(tǒng)授予了要安裝的應(yīng)用。在系統(tǒng)運(yùn)行的時(shí)候不需要對(duì)權(quán)限做任何的處理廓块。用戶在安裝的時(shí)候一般都不知道這些權(quán)限用在了什么地方厢绝,這樣做很不安全。一個(gè)應(yīng)用很容易在一個(gè)Service中讀取用戶所有的通訊錄信息發(fā)送到服務(wù)器上带猴。Android 6.0后的動(dòng)態(tài)權(quán)限讓我們的系統(tǒng)更加安全昔汉,犧牲了用戶的方便性,得到的是安全拴清。下圖是Android 6.0系統(tǒng)對(duì)撥打電話和管理電話權(quán)限組的詢問(wèn)靶病。

image.png

Android 6.0把權(quán)限分為兩種:Normal Permissions(正常權(quán)限)和Dangerous Permissions(危險(xiǎn)權(quán)限)。其中危險(xiǎn)權(quán)限又進(jìn)行了分類口予。把所有的危險(xiǎn)權(quán)限分成了幾個(gè)組娄周。正常權(quán)限不會(huì)給用戶的隱私帶來(lái)不安全,不需要?jiǎng)討B(tài)申請(qǐng)苹威,在應(yīng)用安裝的時(shí)候就已經(jīng)被授予了昆咽。危險(xiǎn)權(quán)限需要?jiǎng)討B(tài)處理,只有用戶批準(zhǔn)了這些權(quán)限牙甫,應(yīng)用才能被授予這些權(quán)限掷酗。

所有的普通權(quán)限:

  • ACCESS_LOCATION_EXTRA_COMMANDS
  • ACCESS_NETWORK_STATE
  • ACCESS_NOTIFICATION_POLICY
  • ACCESS_WIFI_STATE
  • BLUETOOTH
  • BLUETOOTH_ADMIN
  • BROADCAST_STICKY
  • CHANGE_NETWORK_STATE
  • CHANGE_WIFI_MULTICAST_STATE
  • CHANGE_WIFI_STATE
  • DISABLE_KEYGUARD
  • EXPAND_STATUS_BAR
  • GET_PACKAGE_SIZE
  • INSTALL_SHORTCUT
  • INTERNET
  • KILL_BACKGROUND_PROCESSES
  • MODIFY_AUDIO_SETTINGS
  • NFC
  • READ_SYNC_SETTINGS
  • READ_SYNC_STATS
  • RECEIVE_BOOT_COMPLETED
  • REORDER_TASKS
  • REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
  • REQUEST_INSTALL_PACKAGES
  • SET_ALARM
  • SET_TIME_ZONE
  • SET_WALLPAPER
  • SET_WALLPAPER_HINTS
  • TRANSMIT_IR
  • UNINSTALL_SHORTCUT
  • USE_FINGERPRINT
  • VIBRATE
  • WAKE_LOCK
  • WRITE_SYNC_SETTINGS

所有的危險(xiǎn)權(quán)限:

image.png

二、Android 6.0+危險(xiǎn)權(quán)限的動(dòng)態(tài)處理

在開(kāi)發(fā)應(yīng)用的時(shí)候不管是正常權(quán)限還是危險(xiǎn)權(quán)限都必須在應(yīng)用的Manifest.xml文件中聲明窟哺。如果設(shè)備運(yùn)行的是Android 5.1或更低的系統(tǒng)泻轰,或者應(yīng)用的目標(biāo)SDK小于23,那么在Manifest.xml文件中列出的危險(xiǎn)權(quán)限在安裝的時(shí)候用戶必須接受且轨,要不應(yīng)用沒(méi)法安裝浮声。如果設(shè)備運(yùn)行的是Android 6.0或更高的系統(tǒng),或者應(yīng)用的目標(biāo)SDK大于等于23旋奢,那么在Manifest.xml文件中列出的危險(xiǎn)權(quán)限泳挥,會(huì)在應(yīng)用運(yùn)行的時(shí)候被用戶授予或拒絕。開(kāi)發(fā)者需要在代碼中對(duì)危險(xiǎn)權(quán)限進(jìn)行處理至朗。

public class MainActivity extends AppCompatActivity {

    final public static int REQUEST_CODE_ASK_CALL_PHONE = 123;
    private String mMobile;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.button).setOnClickListener(new                                                   

        View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onCallWrapper("12345678912");
            }
        });

    }
    public void onCallWrapper(String mobile) {
        this.mMobile = mobile;
        //檢測(cè)權(quán)限
        int checkCallPhonePermisssion = ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE);
        if (checkCallPhonePermisssion != PackageManager.PERMISSION_GRANTED || !checkOpsPermission(this,Manifest.permission.CALL_PHONE)) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,          Manifest.permission.CALL_PHONE)) {
                Toast.makeText(this, "shouldShowRequestPermissionRationale", Toast.LENGTH_SHORT).show();
                new AlertDialog.Builder(this)
                        .setTitle("提示")
                        .setMessage("應(yīng)用需要開(kāi)啟拍照的權(quán)限屉符,是否繼續(xù)?")
                        .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                ActivityCompat.requestPermissions(MainActivity.this, new           String[]{Manifest.permission.CALL_PHONE}, REQUEST_CODE_ASK_CALL_PHONE);
                            }
                        })
                        .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {

                            }
                        }).show();
            } else {
                //請(qǐng)求權(quán)限
                ActivityCompat.requestPermissions(this, new String[]             {Manifest.permission.CALL_PHONE}, REQUEST_CODE_ASK_CALL_PHONE);
            }

        } else {
            callDirectly(mobile);
        }
    }

  //權(quán)限檢測(cè)
    private static boolean checkOpsPermission(Context context, String permission) {
        //6.0 api 23
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            try {
                AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
                String opsName = null;
                opsName = AppOpsManager.permissionToOp(permission);
                if (opsName == null) {
                    return true;
                }
                int opsMode = appOpsManager.checkOpNoThrow(opsName, Process.myUid(), context.getPackageName());
                return opsMode == AppOpsManager.MODE_ALLOWED;
            } catch (Exception ex) {
                return true;
            }
        }
        return true;
    }

    //請(qǐng)求權(quán)限返回的結(jié)果
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,        
@NonNull int[] grantResults) {

        switch (requestCode) {
            case REQUEST_CODE_ASK_CALL_PHONE:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // Permission Granted 授予權(quán)限
                    callDirectly(mMobile);
                } else {
                    // Permission Denied 權(quán)限被拒絕
                    Toast.makeText(MainActivity.this, "Permission Denied", 
                  Toast.LENGTH_SHORT).show();
                }

                break;
            default:
                break;
        }

        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    private void callDirectly(String mobile) {
        Intent intent = new Intent();
        intent.setAction("android.intent.action.CALL");
        intent.setData(Uri.parse("tel:" + mobile));
        this.startActivity(intent);
    }
}

上面這個(gè)簡(jiǎn)單的例子是通過(guò)點(diǎn)擊一個(gè)按鈕撥打電話锹引。在6.0系統(tǒng)之前矗钟,我們只需要直接調(diào)用方法callDirectly()方法就可以了。增加了系統(tǒng)的安全性嫌变,但是多了很多代碼上的處理吨艇。ContextCompat和
ActivityCompat分別是Context和Activity的兼容類,在上的代碼中我們就不用去判斷當(dāng)前系統(tǒng)的API是多好了腾啥,在API23之前也能用上面代碼中的方法东涡。ContextCompat.checkSelfPermission()方法是用來(lái)判斷冯吓,當(dāng)前應(yīng)用是否擁有某個(gè)權(quán)限。如果擁有我們可以直接調(diào)用callDirectly()方法撥打電話软啼。如果當(dāng)前應(yīng)用沒(méi)有撥打電話的權(quán)限桑谍,會(huì)調(diào)ActivityCompat.shouldShowRequestPermissionRationale()方法,注意當(dāng)前系統(tǒng)還沒(méi)有彈出讓用戶去選擇是允許還是拒絕祸挪,這個(gè)時(shí)候shouldShowRequestPermissionRationale()方法返回false锣披。所以接下來(lái)會(huì)執(zhí)ActivityCompat.requestPermissions()方法會(huì)向系統(tǒng)去請(qǐng)求,系統(tǒng)會(huì)彈出一個(gè)對(duì)話框讓用戶去選擇贿条。onRequestPermissionsResult()方法用來(lái)處理用戶的選擇雹仿。這個(gè)方法可以監(jiān)聽(tīng)用戶選擇的是允許還是拒絕。當(dāng)用戶選擇了允許整以,那么直接調(diào)用callDirectly()方法撥打電話胧辽。當(dāng)用戶選擇了拒絕,上面的代碼只是提示一個(gè)Toast公黑。

當(dāng)用戶選擇了拒絕邑商,那么在下次點(diǎn)擊按鈕撥打電話的時(shí)候ActivityCompat.shouldShowRequestPermissionRationale()方法會(huì)返回true,在上面的代碼中我們會(huì)彈出一個(gè)對(duì)話框給用戶,給用戶一個(gè)提示凡蚜。當(dāng)用戶選擇確定人断,會(huì)向系統(tǒng)請(qǐng)求權(quán)限。當(dāng)用戶選擇取消朝蜘,關(guān)閉對(duì)話框什么也不做恶迈。當(dāng)我們選擇了不在提示并且選擇了拒絕的時(shí)候ActivityCompat.shouldShowRequestPermissionRationale()方法返回false。

三谱醇、用Easy Permissions開(kāi)源庫(kù)處理權(quán)限

1.配置

在app層的build.gradle中

dependencies {
    // EasyPermissions
    compile 'pub.devrel:easypermissions:1.2.0'
}

github : https://github.com/googlesamples/easypermissions

2.舉例

EasyPermissions是谷歌封裝的一個(gè)運(yùn)行時(shí)權(quán)限申請(qǐng)的庫(kù)暇仲,簡(jiǎn)化了操作的過(guò)程

1、builde gradle中依賴
2副渴、清單文件中聲明權(quán)限
3奈附、重寫onRequestPermissionsResult()方法,把執(zhí)行操作給easyPermissions來(lái)
4煮剧、通過(guò)hasPermissions檢查權(quán)限桅狠,或者原生的也行,然后去申請(qǐng)權(quán)限
5轿秧、實(shí)現(xiàn)EasyPermissions.PermissionCallbacks接口,重寫兩個(gè)方法咨堤,成功或失敗
6菇篡、在成功或者失敗方法中編寫要具體做的事。
public class SecondActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks {

    private static final int RC_CAMERA_PERM = 123;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                cameraTask();
            }
        });
    }

//RC_CAMERA_PERM 標(biāo)識(shí)請(qǐng)求碼, (可選)@AfterPermissionGranted()注解 .這里的方法名可以自己取一喘,
//主要是權(quán)限都申請(qǐng)完驱还,就調(diào)用這個(gè)方法嗜暴,執(zhí)行里面的操作。其實(shí)就相當(dāng)于在onPermissionsGranted()調(diào)用這個(gè)方法而已: 
    @AfterPermissionGranted(RC_CAMERA_PERM)
    public void cameraTask() {
        //通過(guò)hasPermissions檢查權(quán)限
        if (EasyPermissions.hasPermissions(this, Manifest.permission.CAMERA)) {
            // 該應(yīng)用已經(jīng)有打電話的權(quán)限
            Toast.makeText(this, "TODO: Camera things", Toast.LENGTH_LONG).show();
        } else {
          //請(qǐng)求權(quán)限
            EasyPermissions.requestPermissions(this, "需要獲取系統(tǒng)的拍照的權(quán)限议蟆!", RC_CAMERA_PERM, Manifest.permission.CAMERA);
        }
    }

//重新以下三個(gè)方法  1,把執(zhí)行結(jié)果的操作給EasyPermissions
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
    }

  //請(qǐng)求成功執(zhí)行相應(yīng)的操作
    @Override
    public void onPermissionsGranted(int requestCode, List<String> perms) {
        Toast.makeText(this, "onPermissionsGranted", Toast.LENGTH_SHORT).show();
    }

//申請(qǐng)失敗時(shí)調(diào)用
    @Override
    public void onPermissionsDenied(int requestCode, List<String> perms) {
        Toast.makeText(this, "onPermissionsDenied", Toast.LENGTH_SHORT).show();
        //不一定執(zhí)行,有些手機(jī)會(huì)執(zhí)行系統(tǒng)的彈框
        new AppSettingsDialog.Builder(this)
                .setTitle("權(quán)限申請(qǐng)")
                .setPositiveButton("確認(rèn)")
                .setNegativeButton("取消")
                .setRationale("當(dāng)前App需要申請(qǐng)camera權(quán)限,需要打開(kāi)設(shè)置頁(yè)面么?")
                .setRequestCode(RC_CAMERA_PERM)
                .build()
                .show();
    }
}

也可以通過(guò)原生來(lái)檢查權(quán)限,比如有多個(gè)權(quán)限,可以抽取一個(gè)工具類

public final class CheckPermissionUtils {
    private CheckPermissionUtils() {
    }

    //需要申請(qǐng)的權(quán)限
    private static String[] permissions = new String[]{
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.CAMERA
    };

    //檢測(cè)權(quán)限
    public static String[] checkPermission(Context context){
        List<String> data = new ArrayList<>();//存儲(chǔ)未申請(qǐng)的權(quán)限
        for (String permission : permissions) {
            int checkSelfPermission = ContextCompat.checkSelfPermission(context, permission);
            if(checkSelfPermission == PackageManager.PERMISSION_DENIED){//未申請(qǐng)
                data.add(permission);
            }
        }
        return data.toArray(new String[data.size()]);
    }
}

以下是在activity中調(diào)用該工具類

//初始化權(quán)限
private void initPermission() {
        //檢查權(quán)限
        String[] permissions = CheckPermissionUtils.checkPermission(this);
        if (permissions.length == 0) {
            //權(quán)限都申請(qǐng)了
           
        } else {
            //申請(qǐng)權(quán)限 ,參數(shù)2:權(quán)限數(shù)組,參數(shù)3:請(qǐng)求碼code
            ActivityCompat.requestPermissions(this, permissions, 100);
          //把執(zhí)行結(jié)果的操作給EasyPermissions的onRequestPermissionsResult
        }
    }

這個(gè)例子是點(diǎn)擊一個(gè)按鈕闷沥,處理拍照的事情,所以我們需要獲取相機(jī)的權(quán)限咐容。首先我們要復(fù)寫Activity或者Fragment的onRequestPermissionsResult()方法舆逃。SecondActivity實(shí)現(xiàn)了EasyPermissions.PermissionCallbacks這個(gè)接口復(fù)寫了onPermissionsGranted()和onPermissionsDenied()這兩個(gè)接口。當(dāng)用戶選擇了允許那么調(diào)用onPermissionsGranted()方法戳粒,當(dāng)用戶選擇了拒絕那么調(diào)用onPermissionsDenied()方法路狮。AppSettingsDialog是一個(gè)詢問(wèn)用戶是否跳轉(zhuǎn)到運(yùn)行應(yīng)用的設(shè)置界面去開(kāi)啟權(quán)限的對(duì)話框。

四蔚约、用Permissions Dispatcher開(kāi)源庫(kù)處理權(quán)限

1.配置

在app層的build.gradle中

dependencies {
    // Permissions Dispatcher
    compile 'com.github.hotchemi:permissionsdispatcher:3.0.1'
    annotationProcessor 'com.github.hotchemi:permissionsdispatcher-processor:3.0.1'
}

這種配置需要有個(gè)條件:Android Gradle Plugin >= 2.2

2.舉例

這個(gè)庫(kù)用到了5個(gè)注解:

注解 是否必須 描述
@RuntimePermissions 注冊(cè)在Acttivity或者Fragment上
@NeedsPermission 再需要權(quán)限的方法上注冊(cè)
@OnShowRationale 被注解的方法可以提示為什么需要這個(gè)權(quán)限
@OnPermissionDenied 如果用戶拒絕了權(quán)限申請(qǐng)那么調(diào)用該方法
@OnNeverAskAgain 如果用戶選擇了不再詢問(wèn)奄妨,調(diào)用該方法

這個(gè)庫(kù)用到了Annotion Processor,需要用到一個(gè)應(yīng)用編譯期間產(chǎn)生的類苹祟,這個(gè)類的命名是:類名+PermissionsDispatcher砸抛。


image.png
//注冊(cè)在Acttivity或者Fragment上
@RuntimePermissions
public class ThirdActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_third);

        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ThirdActivityPermissionsDispatcher.showContactsWithCheck(ThirdActivity.this);
            }
        });
    }

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

//處理當(dāng)用戶允許該權(quán)限時(shí)需要處理的方法
    @NeedsPermission({Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS})
    public void showContacts() {
        Toast.makeText(this, "讀取通訊錄", Toast.LENGTH_SHORT).show();
    }

//如果用戶拒絕了權(quán)限申請(qǐng)那么調(diào)用該方法
    @OnPermissionDenied({Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS})
    public void onContactsDenied() {
        Toast.makeText(this, "onContactsDenied", Toast.LENGTH_SHORT).show();

    }

//如果用戶選擇了不再詢問(wèn),調(diào)用該方法
    @OnNeverAskAgain({Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS})
    public void onContactsNeverAskAgain() {
        Toast.makeText(this, "onContactsNeverAskAgain", Toast.LENGTH_SHORT).show();
    }

//// 提示用戶權(quán)限使用的對(duì)話框
    @OnShowRationale({Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS})
    public void showRationaleContacts(final PermissionRequest request) {
//        Toast.makeText(this, "showRationaleContacts", Toast.LENGTH_SHORT).show();

        new AlertDialog.Builder(this)
                .setPositiveButton("繼續(xù)", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(@NonNull DialogInterface dialog, int which) {
                        request.proceed();
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(@NonNull DialogInterface dialog, int which) {
                        request.cancel();
                    }
                })
                .setCancelable(false)
                .setMessage("需要通訊錄權(quán)限")
                .show();
    }

}

其實(shí)這個(gè)dispather就是對(duì)動(dòng)態(tài)權(quán)限處理的那些操作進(jìn)行了封裝树枫,通過(guò)查看生成的MainActivityPermissionsDispatcher文件就可以驗(yàn)證這一點(diǎn)直焙。這里的權(quán)限說(shuō)的是危險(xiǎn)權(quán)限,普通權(quán)限只用在Manifest中聲明就可以了团赏。

五箕般、一句代碼搞定權(quán)限請(qǐng)求,XXPermissions

image.png

github : https://github.com/getActivity/XXPermissions

集成步驟

dependencies {
    implementation 'com.hjq:xxpermissions:3.2'
}

使用

XXPermissions.with(this)
        //.constantRequest() //可設(shè)置被拒絕后繼續(xù)申請(qǐng)舔清,直到用戶授權(quán)或者永久拒絕
        //.permission(Permission.REQUEST_INSTALL_PACKAGES, Permission.SYSTEM_ALERT_WINDOW) //支持請(qǐng)求安裝權(quán)限和懸浮窗權(quán)限
        .permission(Permission.Group.STORAGE) //支持多個(gè)權(quán)限組進(jìn)行請(qǐng)求丝里,不指定則默以清單文件中的危險(xiǎn)權(quán)限進(jìn)行請(qǐng)求
        .request(new OnPermission() {

          
                    @Override
                    public void hasPermission(List<String> granted, boolean isAll) {
                        if (isAll) {
                            Toast.makeText(MainActivity.this, "獲取權(quán)限成功", Toast.LENGTH_SHORT).show();
                        }else {
                            Toast.makeText(MainActivity.this, "獲取權(quán)限成功,部分權(quán)限未正常授予", Toast.LENGTH_SHORT).show();
                        }
                    }

                    @Override
                    public void noPermission(List<String> denied, boolean quick) {
                        if(quick) {
                            Toast.makeText(MainActivity.this, "被永久拒絕授權(quán)体谒,請(qǐng)手動(dòng)授予權(quán)限", Toast.LENGTH_SHORT).show();
                            //如果是被永久拒絕就跳轉(zhuǎn)到應(yīng)用權(quán)限系統(tǒng)設(shè)置頁(yè)面
                            XXPermissions.gotoPermissionSettings(MainActivity.this);
                        }else {
                            Toast.makeText(MainActivity.this, "獲取權(quán)限失敗", Toast.LENGTH_SHORT).show();
                        }
                    }
        });

參考文獻(xiàn):

https://github.com/googlesamples/easypermissions

https://github.com/hotchemi/PermissionsDispatcher
http://hotchemi.github.io/PermissionsDispatcher/

https://inthecheesefactory.com/blog/things-you-need-to-know-about-android-m-permission-developer-edition/en

https://developer.android.com/guide/topics/security/permissions.html#normal-dangerous
系統(tǒng)所需要的權(quán)限
https://developer.android.com/reference/android/Manifest.permission.html
普通權(quán)限
https://developer.android.com/guide/topics/permissions/normal-permissions.html
危險(xiǎn)權(quán)限
https://developer.android.com/guide/topics/security/permissions.html#perm-groups
在運(yùn)行時(shí)請(qǐng)求權(quán)限
https://developer.android.com/training/permissions/requesting.html

解讀Android官方開(kāi)發(fā)指導(dǎo) - 運(yùn)行時(shí)權(quán)限
http://www.reibang.com/p/0beb6243d650

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末杯聚,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子抒痒,更是在濱河造成了極大的恐慌幌绍,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件故响,死亡現(xiàn)場(chǎng)離奇詭異傀广,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)彩届,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門伪冰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人樟蠕,你說(shuō)我怎么就攤上這事贮聂】扛蹋” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵吓懈,是天一觀的道長(zhǎng)歼冰。 經(jīng)常有香客問(wèn)我,道長(zhǎng)耻警,這世上最難降的妖魔是什么隔嫡? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮榕栏,結(jié)果婚禮上畔勤,老公的妹妹穿的比我還像新娘。我一直安慰自己扒磁,他們只是感情好庆揪,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著妨托,像睡著了一般浩习。 火紅的嫁衣襯著肌膚如雪敢辩。 梳的紋絲不亂的頭發(fā)上秦忿,一...
    開(kāi)封第一講書(shū)人閱讀 52,255評(píng)論 1 308
  • 那天捻激,我揣著相機(jī)與錄音,去河邊找鬼敦腔。 笑死均澳,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的符衔。 我是一名探鬼主播找前,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼判族!你這毒婦竟也來(lái)了躺盛?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤形帮,失蹤者是張志新(化名)和其女友劉穎槽惫,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體辩撑,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡界斜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了合冀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锄蹂。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖水慨,靈堂內(nèi)的尸體忽然破棺而出得糜,到底是詐尸還是另有隱情,我是刑警寧澤晰洒,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布朝抖,位于F島的核電站,受9級(jí)特大地震影響谍珊,放射性物質(zhì)發(fā)生泄漏治宣。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一砌滞、第九天 我趴在偏房一處隱蔽的房頂上張望侮邀。 院中可真熱鬧,春花似錦贝润、人聲如沸绊茧。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)华畏。三九已至,卻和暖如春尊蚁,著一層夾襖步出監(jiān)牢的瞬間亡笑,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工横朋, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留仑乌,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓琴锭,卻偏偏與公主長(zhǎng)得像晰甚,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子祠够,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,283評(píng)論 25 707
  • 目前搭載android6.0以上版本系統(tǒng)手機(jī)占有量將近三分之一压汪,具體如下圖所示: 所以有必要將升級(jí)app的targ...
    flywfk閱讀 3,088評(píng)論 0 4
  • 1. Android 6.0 在運(yùn)行時(shí)請(qǐng)求權(quán)限介紹 從 Android 6.0(API 級(jí)別 23)開(kāi)始,用戶開(kāi)始...
    conio閱讀 4,238評(píng)論 0 6
  • 許久沒(méi)有吃我喜歡的串串啦古瓤!甚是想念止剖! 工具:普通彩色鉛筆,網(wǎng)格本落君,黑水筆穿香。 簡(jiǎn)單易學(xué)畫(huà)起來(lái)啦! 只需要一個(gè)小小本绎速,...
    影子倒了閱讀 642評(píng)論 3 6
  • 女人最重要的是什么呢皮获,姣好的面容,豐滿性感的身材纹冤,還是鍍金的好學(xué)歷洒宝? 學(xué)生時(shí)代羨慕那些貌美好身材的姑娘购公,長(zhǎng)的漂亮?xí)?..
    星光漫漫閱讀 252評(píng)論 0 0