Android _ privacy acquisition of devices, ignoring 6.0 permission management
1. Preface
(1). Because some custom systems such as MIUI also have permission management and do not have relevant APIs, it is impossible to determine whether users are allowed to obtain privacy such as contacts. After Android 6.0, new permission management allows you to determine the running status of users through official APIs;
(2). If targetSdkVersion is set to 23 or later, We need to request these required permissions at runtime. This is very important because many developers have updated targetSdkVersion and found that their app crashed frantically because they did not implement the Code for executing the runtime permission request. When you have published an app with a targeting API of 23 or later to Google Play, this is even more a problem. You cannot immediately replace the targeting API of that apk with an earlier version.
2. Permission Analysis
From Android6.0, permissions are classified into common permissions and permission permissions. Permission is categorized into groups. After a permission is authorized, all permissions in the group can be used.
(1) General Permissions
You only need to apply for it in xml. The usage is the same as that before 6.0. When an application is installed, the application is licensed by default.
(2) Permission
Run $ adb shell pm list permissions-d-g.
Permission Group |
Permissions |
android.permission-group.CALENDAR |
android.permission.READ_CALENDAR
android.permission.WRITE_CALENDAR
|
android.permission-group.CAMERA |
android.permission.CAMERA
|
android.permission-group.CONTACTS |
android.permission.READ_CONTACTS
android.permission.WRITE_CONTACTS
android.permission.GET_ACCOUNTS
|
android.permission-group.LOCATION |
android.permission.ACCESS_FINE_LOCATION
android.permission.ACCESS_COARSE_LOCATION
|
android.permission-group.MICROPHONE |
android.permission.RECORD_AUDIO
|
android.permission-group.PHONE |
android.permission.READ_PHONE_STATE
android.permission.CALL_PHONE
android.permission.READ_CALL_LOG
android.permission.WRITE_CALL_LOG
com.android.voicemail.permission.ADD_VOICEMAIL
android.permission.USE_SIP
android.permission.PROCESS_OUTGOING_CALLS
|
android.permission-group.SENSORS |
android.permission.BODY_SENSORS
|
android.permission-group.SMS |
android.permission.SEND_SMS
android.permission.RECEIVE_SMS
android.permission.READ_SMS
android.permission.RECEIVE_WAP_PUSH
android.permission.RECEIVE_MMS
android.permission.READ_CELL_BROADCASTS
|
android.permission-group.STORAGE |
android.permission.READ_EXTERNAL_STORAGE
android.permission.WRITE_EXTERNAL_STORAGE
|
Any permission in the same group is authorized, and other permissions are automatically authorized. For example, once WRITE_CONTACTS is authorized, the app also has READ_CONTACTS and GET_ACCOUNTS.
The methods used to check and request permissions in the source code are Activity checkSelfPermission and requestPermissions. These methods are introduced in api23.
3. Related Methods
(1). ContextCompat. checkSelfPermission ()
Check whether the application has this permission. The authorized return value is PERMISSION_GRANTED. Otherwise, PERMISSION_DENIED is returned.
(2). ActivityCompat. requestPermissions ()
The request authorization dialog box is displayed. This method is called in versions earlier than M. OnRequestPermissionsResultCallback is called directly with the correct PERMISSION_GRANTED or PERMISSION_DENIED.
(3). AppCompatActivity. onRequestPermissionsResult ()
This method is similar to the OnActivityResult () callback method of the Activity. It mainly receives the return value of the request authorization.
// Determine if (Build. VERSION. SDK_INT> = 23) {// reduce whether permission int checkCallPhonePermission = ContextCompat. checkSelfPermission (getApplicationContext (), permission); if (checkCallPhonePermission! = PackageManager. PERMISSION_GRANTED) {// The receiving permission ActivityCompat. requestPermissions (BaseActivity. this, new String [] {permission}, id); return ;}
@ Overridepublic void onRequestPermissionsResult (int requestCode, @ NonNull String [] permissions, @ NonNull int [] grantResults) {super. onRequestPermissionsResult (requestCode, permissions, grantResults); if (grantResults [0] = PackageManager. PERMISSION_GRANTED) {// TODO: Authorized} else {// TODO: User reject }}
4. Encapsulation
Public class BaseActivity extends AppCompatActivity {private Map
AllowablePermissionRunnables = new HashMap <> (); private Map
DisallowablePermissionRunnables = new HashMap <> (); @ Override protected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState );} /*** request permission ** @ param id: the unique identifier of the authorization id. * @ param permission request permission * @ param allowableRunnable: after agreeing to the authorized operation * @ param disallowableRunnable */protected void requestPermission (int id, string permission, Runnable allowableRunnable, Runnable disallowab LeRunnable) {if (allowableRunnable = null) {throw new partition ("allowableRunnable = null");} response. put (id, allowableRunnable); if (disallowableRunnable! = Null) {disallowablePermissionRunnables. put (id, disallowableRunnable);} // determine if (Build. VERSION. SDK_INT> = 23) {// reduce whether you have the int checkCallPhonePermission = ContextCompat. checkSelfPermission (getApplicationContext (), permission); if (checkCallPhonePermission! = PackageManager. PERMISSION_GRANTED) {// dialog box that appears to receive the permission ActivityCompat. requestPermissions (BaseActivity. this, new String [] {permission}, id); return;} else {allowableRunnable. run () ;}} else {allowableRunnable. run () ;}@ Override public void onRequestPermissionsResult (int requestCode, @ NonNull String [] permissions, @ NonNull int [] grantResults) {super. onRequestPermissionsResult (requestCode, permissions, grantResults); if (grantResults [0] = PackageManager. PERMISSION_GRANTED) {Runnable allowRun = allowablePermissionRunnables. get (requestCode); allowRun. run ();} else {Runnable disallowRun = disallowablePermissionRunnables. get (requestCode); disallowRun. run ();}}}
Public class MainActivity extends BaseActivity implements View. onClickListener {private Button btCallPhone; private Button btContact; @ Override protected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_main); btCallPhone = (Button) findViewById (R. id. call_phone); btContact = (Button) findViewById (R. id. contact); btCallPhone. setOnClickListener (this); btContact. setOnClickListener (this) ;}@ Override public void onClick (View v) {if (v = btCallPhone) {// call requestPermission (1, Manifest. permission. CALL_PHONE, new Runnable () {@ Override public void run () {callPhone () ;}, new Runnable () {@ Override public void run () {callPhoneDenied () ;}}) ;}else if (v = btContact) {// read the contact information requestPermission (2, Manifest. permission. WRITE_CONTACTS, new Runnable () {@ Override public void run () {readContact () ;}, new Runnable () {@ Override public void run () {readContactDenied () ;}} private void callPhone () {Toast. makeText (MainActivity. this, "CALL_PHONE OK", Toast. LENGTH_SHORT ). show ();} private void callPhoneDenied () {Toast. makeText (MainActivity. this, "CALL_PHONE Denied", Toast. LENGTH_SHORT ). show ();} private void readContact () {ContentResolver cr = getContentResolver (); String str [] = {ContactsContract. commonDataKinds. phone. CONTACT_ID, ContactsContract. commonDataKinds. phone. DISPLAY_NAME, ContactsContract. commonDataKinds. phone. NUMBER, ContactsContract. commonDataKinds. phone. PHOTO_ID}; Cursor cur = cr. query (ContactsContract. commonDataKinds. phone. CONTENT_URI, str, null); int count = cur. getCount (); cur. close (); Toast. makeText (MainActivity. this, String. format ("% s found", count), Toast. LENGTH_SHORT ). show ();} private void readContactDenied () {Toast. makeText (MainActivity. this, "Contact Denied", Toast. LENGTH_SHORT ). show ();}}