精华内容
参与话题
问答
  • Android权限

    千次阅读 2016-04-26 17:07:36
    Android权限
    • 系统权限
    • 在运行时请求权限

    系统权限

      Android是一个权限分离的操作系统,每个应用使用不同的系统身份运行(Linux用户ID和群组ID)。系统的不同部分也被分隔进不同的身份域。Linux以此来实现不同应用与其他应用和系统的独立。
      更细粒度的安全特征由“权限”机制提供,该机制在一个进程能够执行的特定操作上强制施加了限制,并且每一个URI权限能够授予对特定数据的临时访问。

    安全框架

      Android安全框架的一个中心设计点是,默认情况下,没有应用具有执行任何不利地影响其他应用,操作系统或用户的操作的权限。这些操作包括,读写用户私有数据,读写其他应用程序文件,执行网络访问,保持设备唤醒等等。
      因为每一个Android程序运行在进程沙盒里,所以应用间必须严格地分享资源和数据。它们能够通过声明它们需要的权限来增加基础沙盒没有提供的能力。应用声明并请求它们需要的权限,Android系统提示用户以获得用户赞同。
      应用程序沙盒不依赖用来构建应用的技术。实际上,Dalvik VM不是一个安全的边界,任何应用都能运行本地代码。所有类型的应用-Java,native,hybrid-是使用相同的方式被沙盒封装,他们有相同的安全等级。

    应用签名

      所有的apk必须使用证书签名,该证书的私有密钥由开发者持有。该证书标识了应用的作者。该证书不需要被一个证书颁发机构签名。并且对于Android应用使用自签名证书,是非常被允许和支持的。在Android中证书的作用是用来区分应用的作者。

    用户IDs和文件访问

      在安装时,Android会给每一个安装包一个不同的Linux用户ID。这个身份在该应用在设备上的期间是恒定不变的。在不同的设备上,相同的安装包可有有不同的UID。
      安全限制发生在进程级别。由于不同应用需要运行作为不同的Linux用户,所以两个不同安装包的代码通常不能运行在相同的进程。但你可以在AndroidManifest.xml的manifest标签中使用sharedUserId属性来让不同的包分配相同的用户ID。通过这样做,两个包是被作为相同的应用,有相同的用户ID和文件权限。注意为了确保安全,仅两个使用相同签名,且请求相同sharedUserId的应用会被分配相同的用户ID。
      一个应用存储的任何数据都会被分配应用的用户ID,并且正常情况下不能被其他的包访问。当使用getSharedPreferences(String, int)openFileOutput(String, int)openOrCreateDatabase(String, int, SQLiteDatabase.CursorFactory)等方法创建新文件时,你能够使用MODE_WORLD_READABLEMODE_WORLD_WRITEABLE标签来允许其他应用读写该文件。当设置这些标签时,该文件仍然被你的应用所拥有,但它的全局读写权限已经被适当地设置,所以其它应用可以看见它。

    使用权限

      默认情况下,一个基本的Android应用没有被分配任何权限,这意味着它不能做任何不利地影响用户体验和数据的操作。为了使用设备上受保护的特征,你必须在AndroidManifest.xml中使用一个或多个<uses-permission>标签。
    例如,一个应用需要接收SMS信息,则这样定义:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.android.app.myapp" >
        <uses-permission android:name="android.permission.RECEIVE_SMS" />
        ...
    </manifest>

      如果你的应用声明了“正常权限”(不会对用户隐私或设备造成影响的操作权限),系统会自动授予这些权限。如果你的应用声明了“危险权限”(会对用户隐私或设备造成影响的操作权限),系统会询问用户严格地授予这些权限。请求权限的表现形式具体依赖于设备系统版本和应用的目标系统版本:

    • 如果你的设备运行在Android6.0(API级别23)以上,并且你的应用的targetSdkVersion是23或更高,则该应用在运行时向用户请求权限。用户可以在任何时候取消这个权限,所以应用需要在每次运行时检测是否已有该权限。
    • 如果你的设备运行在Android5.1(API级别22)一下,会你的应用的targetSdkVersion是22或更低,则系统在安装应用时,询问用户授予该权限。如果你在更新的版本中增加了一个新权限,则系统在升级应用时,询问用户授予该权限。一旦用户安装了该应用,唯一的取消该权限的方式就是卸载应用。

    通常一个权限失败会导致抛出一个SecurityException。然而,这不是绝对的。例如,sendBroadcast(Intent)方法在数据被传递到每一个接收器时检查权限,当方法调用返回后,如果权限失败,不会收到异常。在几乎所有情况下,一个权限失败会打印一条log。
      Android系统提供的所有权限可以在Manifest.permission中找到。应用也可以定义自己的权限。
      通常特定的权限被施加在你的应用的有数的几个位置上:

    • 调入系统时,防止应用执行特定功能。
    • 当启动一个Activity时,防止应用创建其他应用的Activity。
    • 发送或接受广播时,来控制谁能接收你的广播或谁能发送广播给你。
    • 当在Content Provider上访问和操作时。
    • 绑定或启动服务时。

    自动权限调整

      随着时间的推移,新的限制会被增加到平台,为了使用这些APIs,你的应用必须请求它以前不需要的权限。如果已发布的应用访问了这些API会怎么呢?Android会让其自由的访问,并在新平台版本上将请求的新权限授予应用,以防止已发布的应用挂掉。Android通过targetSdkVersion属性提供的值来判断是否需要请求新权限。如果这个值低于新权限被增加的版本,则Android默认授予该权限。
      例如,WRITE_EXTERNAL_STORAGE权限是在API级别4增加的用来限制访问共享存储空间的权限。如果你的targetSdkVersion设置的值小于等于3,则该权限在新Android版本上默认被增加到你的应用。
      注意:被自动增加到App的权限,会被列在Google Play权限列表中,尽管你的应用不需要请求他们。
      为了避免这些并移除你不需要的默认权限,一直尽可能高的更新你的targetSdkVersion。你可以在Build.VERSION_CODES文档中找到某个权限是在哪个版本中新增的。

    “正常”和“危险”权限

      系统权限被分为几个不同的保护级别。两个最重要的保护级别是正常”和“危险”权限:

    • “正常权限”覆盖了你的应用需要访问的数据或资源是应用沙盒外的所有区域,在这些区域对用户隐私或其他应用程序的操作所造成的风险是非常小的。例如,设置时间地区的权限是一个 “正常”权限。如果应用声明了它需要一个“正常”权限,则系统自动授予应用该权限。
    • “危险权限”覆盖了所有你的应用想要的数据或资源包含用户的隐私信息,或可能潜在地影响用户存储的数据或其他应用的操作的区域。例如,读取用户的联系人的权限就是一个危险的权限。如果应用声明了它想要一个“危险”权限,则用户必须严格授予该权限给应用。

    当前所有的“正常权限”

    PROTECTION_NORMAL类权限
    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

    权限组

      所有“危险权限”属于权限组。如果设备正运行在Android6.0(API级别23)之上,并且该应用的targetSdkVersion是23或更高,则当应用请求一个“危险权限”时,下面的系统行为出现。

    • 如果应用请求了一个“危险权限”,且应用当前没有该权限所在权限组的权限,则系统展示一个对话框去向用户描述该应用想要访问的权限组。这个对话框不能描述该权限组中的具体权限。例如,如果应用仅请求了READ_CONTACTS权限,则系统对话框仅会展示该应用需要访问设备的联系人。如果用户授予了该权限,则系统仅会授予该应用请求的权限,同一权限组中的其他权限还需要再去请求。
    • 如果应用请求了一个“危险权限”,并且该应用已经有了该权限组中的另一个“危险权限”,则系统会立刻授予该权限,而不会与用户有任何的交互。例如,如果应用已经请求并授予了READ_CONTACTS权限,则当它再请求WRITE_CONTACTS权限时,系统会立刻授予该权限。

    注意:任何权限都属于一个权限组,包括“正常权限”和用户自定义的权限。只是“危险权限”的权限组会影响用户体验,所以我们特殊对待。

    所有“危险权限”和权限组

    权限组 权限
    CALENDAR READ_CALENDAR
    WRITE_CALENDAR
    CAMERA CAMERA
    CONTACTS READ_CONTACTS
    WRITE_CONTACTS
    GET_ACCOUNTS
    LOCATION ACCESS_FINE_LOCATION
    ACCESS_COARSE_LOCATION
    MICROPHONE RECORD_AUDIO
    PHONE READ_PHONE_STATE
    CALL_PHONE
    READ_CALL_LOG
    WRITE_CALL_LOG
    ADD_VOICEMAIL
    USE_SIP
    PROCESS_OUTGOING_CALLS
    SENSORS BODY_SENSORS
    SMS SEND_SMS
    RECEIVE_SMS
    READ_SMS
    RECEIVE_WAP_PUSH
    RECEIVE_MMS
    STORAGE READ_EXTERNAL_STORAGE
    WRITE_EXTERNAL_STORAGE

    定义和施行权限

      为了施行自己的权限,你首先需要在AndroidManifest.xml中使用<permission>标签定义权限。
      例如,应用想要控制谁能启动一个Activity,则可以像下面这样定义权限:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.me.app.myapp" >
        <permission android:name="com.me.app.myapp.permission.DEADLY_ACTIVITY"
            android:label="@string/permlab_deadlyActivity"
            android:description="@string/permdesc_deadlyActivity"
            android:permissionGroup="android.permission-group.COST_MONEY"
            android:protectionLevel="dangerous" />
        ...
        <uses-permission android:name="com.me.app.myapp.permission.DEADLY_ACTIVITY" />
        . . .
        <application . . .>
            <activity android:name=".FreneticActivity"
                      android:permission="com.me.app.myapp.permission.DEADLY_ACTIVITY"
                      . . . >
                . . .
            </activity>
        </application>
    </manifest>
    • protectionLevel:指定了该权限的安全级别,它告诉系统当应用请求该权限时怎样通知用户,或谁被允许持有该权限。
    • permissionGroup:其仅帮助系统向用户显示权限。通常你设置其为一个标准系统权限组(android.Manifest.permission_group中列举)或自定义的权限组。
    • label:被用来展示给用户当展示一个权限列表时,要尽量简短
    • description:具体描述一个权限

    可以在手机“设置”->“应用程序”中选择具体的应用来查看其需要的相关权限,也可以使用adb shell pm list permissions命令查看权限:

    $ adb shell pm list permissions -s
    All Permissions:
    
    Network communication: view Wi-Fi state, create Bluetooth connections, full
    Internet access, view network state
    
    Your location: access extra location provider commands, fine (GPS) location,
    mock location sources for testing, coarse (network-based) location
    
    Services that cost you money: send SMS messages, directly call phone numbers
    ...

    在运行时请求权限

      从Android6.0(API级别23)开始,用户在应用运行时授予权限。这种方式简化了应用的安装过程,因为用户不再需要在安装或升级应用时授予权限。这也给了用户在使用应用过程中的更多控制。例如,一个用户能够选择给一个相机应用访问相机的权限而不给获取设备位置的权限。用户能够随时在应用设置界面取消授予的权限。

    检测权限

      如果你的应用需要一个“危险权限”,则在每次执行请求这个权限的操作时,你必须检测你是否已经被授予该权限。因为用户可以随时取消授权。
    使用ContextCompat.checkSelfPermission()方法来检测你是否被授予一个权限。例如,下面的代码段展示了怎样检测一个Activity是否已被授予写日历的权限:

    // Assume thisActivity is the current activity
    int permissionCheck = ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.WRITE_CALENDAR);

      如果应用具有该权限,则该方法返回PackageManager.PERMISSION_GRANTED,则该应用可以执行该操作。如果该应用不具有该权限,则该方法返回PERMISSION_DENIED,则应用不得不严格地向用户请求该权限。

    请求权限

      如果你的应用需要一个“危险权限”,它必须询问用户授予该权限。Android提供了几种用来请求权限的方法。调用这些方法调起一个标准的对话框,它不能被订制。

    解释为什么应用需要这个权限

      有些情况下,你可能想帮用户理解为什么你的应用需要一个权限。例如,如果启动一个拍照应用,则用户不会惊讶于应用请求使用相机的权限,但用户不能理解应用为什么想要访问用户的位置和联系人。在你请求一个权限之前,你应该考虑向用户做出一个解释。注意不要让解释影响了用户。如果你提供了太多的解释,用户可能会产生厌烦,卸载了你的应用。
      一种你能够使用的方法是,仅当用户已经拒绝了权限请求时提供解释。如果用户持续尝试使用一个请求权限的功能,但却保持拒绝权限请求,则这可能表明用户不理解为什么应用需要该权限来提供这个功能。像这种情况,可能给出一个解释是个好的实践。
      为了帮助找出用户可能需要一个解释的情况,Android提供了一个实用的方法shouldShowRequestPermissionRationale()。如果应用之前请求过这个权限并且用户拒绝了该请求,则该方法返回true。
      注意:如果用户在过去拒绝了这个权限请求并在该权限的请求对话框中选择了“不再询问”选项,则该方法返回false。如果设备策略禁止该应用有该权限则该方法也返回false。

    请求你需要的权限

      如果你的应用还没有它需要的权限,则该应用必须调用requestPermissions()方法来请求该权限。该方法需要传递你的应用需要的权限和标识该次权限请求的一个整形请求码。该方法的作用是异步的,当用户响应该对话框后,系统调用回调方法返回授权结果,结果中会包含请求权限时传入的相同请求码。
      下面的代码检测应用是否具有读用户联系人的权限并在需要时请求该权限:

    // Here, thisActivity is the current activity
    if (ContextCompat.checkSelfPermission(thisActivity,
                    Manifest.permission.READ_CONTACTS)
            != PackageManager.PERMISSION_GRANTED) {
    
        // Should we show an explanation?
        if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
                Manifest.permission.READ_CONTACTS)) {
    
            // Show an expanation to the user *asynchronously* -- don't block
            // this thread waiting for the user's response! After the user
            // sees the explanation, try again to request the permission.
    
        } else {
    
            // No explanation needed, we can request the permission.
    
            ActivityCompat.requestPermissions(thisActivity,
                    new String[]{Manifest.permission.READ_CONTACTS},
                    MY_PERMISSIONS_REQUEST_READ_CONTACTS);
    
            // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
            // app-defined int constant. The callback method gets the
            // result of the request.
        }
    }

    处理权限请求响应

      当你的应用请求权限时,系统呈现一个对话框给用户。当用户响应时,系统触发onRequestPermissionsResult()方法,给出响应结果。下面给出了请求READ_CONTACTS权限时的响应回调方法:

    Override
    public void onRequestPermissionsResult(int requestCode,
            String permissions[], int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
    
                    // permission was granted, yay! Do the
                    // contacts-related task you need to do.
    
                } else {
    
                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.
                }
                return;
            }
    
            // other 'case' lines to check for other
            // permissions this app might request
        }
    }

      注意:你的应用仍需要严格地请求每一个它需要的权限,尽管用户已经授予了相同权限组的其他权限。因为权限组的分组可能会在将来的某个Android版本更改。你的代码不应该依赖该权限是不是在相同权限组的假设。
      当系统询问用户授予权限时,用户有一个操作选项用来告诉系统需要再次询问授予该权限。在这种情况下,每次使用requestPermissions()方法请求权限,系统都会立即拒绝请求,而不再弹出授权对话框。

    运行时权限示例程序

    使用Android原生API请求权限

      Android API中处理运行时权限的方法checkSelfPermission()shouldShowRequestPermissionRationale()requestPermissions()等都是在Android6.0版本增加的方法,所以要使用这些方法必须要至少API级别为23,为了调用方法的兼容性可以通过如下检查运行版本的方式处理:

    if (Build.VERSION.SDK_INT >= 23) {
        // Marshmallow+
    } else {
        // Pre-Marshmallow
    }

      这种方法虽然可以解决兼容性问题,但太过复杂,幸运的是,v4兼容库已经提供了相应的兼容方法。

    • ContextCompat.checkSelfPermission()
      被授权函数返回PERMISSION_GRANTED,否则返回PERMISSION_DENIED,在所有版本都是如此。
    • ActivityCompat.requestPermissions()
      这个方法在M之前版本调用,OnRequestPermissionsResult回调方法直接被调用,带着正确的PERMISSION_GRANTED或者PERMISSION_DENIED
    • ActivityCompat.shouldShowRequestPermissionRationale()
      在M之前版本调用,永远返回false。

    后两种方法,在Fragment中也有相应方法,使用v13兼容包的FragmentCompat.requestPermissions()FragmentCompat.shouldShowRequestPermissionRationale()方法。

    一次请求一个权限

      以拍照功能为例,我们示例请求拍照权限。
    在AndroidManifest.xml中声明权限

    <uses-permission android:name="android.permission.CAMERA" />

    在SingleNormalActivity.java中动态请求权限

    /**
     * 单个权限请求处理
     * Created by sunxiaodong on 16/4/26.
     */
    public class SingleNormalActivity extends AppCompatActivity implements View.OnClickListener {
    
        private static final int CAMERA_REQUEST_CODE = 1;
        private static final int PERMISSION_REQUEST_CODE = 2;
    
        private Button mGoCamera;
        private ImageView mPhotoImageView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.camera_activity);
            initView();
        }
    
        private void initView() {
            mGoCamera = (Button) findViewById(R.id.go_camera);
            mGoCamera.setOnClickListener(this);
            mPhotoImageView = (ImageView) findViewById(R.id.photo_imageview);
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.go_camera:
                    getCameraPermission();
                    break;
            }
        }
    
        private void getCameraPermission() {
            int hasCameraPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
            if (hasCameraPermission != PackageManager.PERMISSION_GRANTED) {
                if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
                    showRationaleDialog(getResources().getString(R.string.permission_camera_rationale),
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    ActivityCompat.requestPermissions(SingleNormalActivity.this,
                                            new String[]{Manifest.permission.CAMERA},
                                            PERMISSION_REQUEST_CODE);
                                }
                            });
                    return;
                }
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.CAMERA},
                        PERMISSION_REQUEST_CODE);
                return;
            }
            camera();
        }
    
        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            switch (requestCode) {
                case PERMISSION_REQUEST_CODE:
                    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                        camera();
                    } else {
                        Toast.makeText(this, getResources().getString(R.string.permission_camera_denied), Toast.LENGTH_SHORT).show();
                    }
                    break;
                default:
                    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            }
        }
    
        private void camera() {
            Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            startActivityForResult(openCameraIntent, CAMERA_REQUEST_CODE);
        }
    
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == RESULT_OK) {
                switch (requestCode) {
                    case CAMERA_REQUEST_CODE:
                        Bitmap bm = (Bitmap) data.getExtras().get("data");
                        mPhotoImageView.setImageBitmap(bm);
                        break;
                    default:
                        break;
                }
            }
        }
    
        private void showRationaleDialog(String message, DialogInterface.OnClickListener okListener) {
            new AlertDialog.Builder(this)
                    .setMessage(message)
                    .setPositiveButton("OK", okListener)
                    .setNegativeButton("Cancel", null)
                    .create()
                    .show();
        }
    
    }

    下面给出授权过程的一个执行路径
      首次点击拍照按钮,弹出自定义授权解释对话框:
    这里写图片描述

      点击授权解释对话框的“允许”选项,弹出系统的授权请求对话框:
    这里写图片描述

      点击授权请求对话框的“拒绝”选项后,再次点击拍照按钮,弹出有“不再询问”选项的授权请求对话框:
    这里写图片描述

      选择“不再询问”选项,点击授权请求对话框的“拒绝”选项后,再次点击拍照按钮,弹出自定义授权解释对话框:
    这里写图片描述

      点击授权解释对话框的“允许”选项,不再有任何反应。

      分析程序中可知,在运行时权限下,如果想要使用拍照功能,就必须在使用相机功能前,主动请求相机权限,程序中,我们首先调用ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)方法获取应用是否已经被授予相机权限,如果已被授予该权限,则可直接使用相机功能,否则通过调用ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)来判断用户是否拒绝过该权限的授予或是否用户已经选择了“不再询问”选项予以拒绝授予该权限,如果用户已经选择了“不再询问”选项予以拒绝授予该权限,则系统不再弹出权限请求提示框,所以我们自己弹出需要相机权限的解释,如果仅是简单地被拒绝了授予权限,则再次调用ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, PERMISSION_REQUEST_CODE);方法请求权限。请求权限后,用户响应授权提示的结果,通过onRequestPermissionsResult()回调方法返回,接下来根据用户授权情况,做出相应处理。

    一次请求多个权限

      接下来,在请求拍照功能的同时,一起请求联系人权限。
    在AndroidManifest.xml中声明权限

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />

    在MultiNormalActivity.java中动态请求权限

    /**
     * 常规的一次请求多个权限处理方式
     * Created by sunxiaodong on 16/4/26.
     */
    public class MultiNormalActivity extends AppCompatActivity implements View.OnClickListener {
    
        private static final int CAMERA_REQUEST_CODE = 1;
        private static final int PERMISSION_REQUEST_CODE = 2;
    
        private Button mGoCamera;
        private ImageView mPhotoImageView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.camera_activity);
            initView();
        }
    
        private void initView() {
            mGoCamera = (Button) findViewById(R.id.go_camera);
            mGoCamera.setOnClickListener(this);
            mPhotoImageView = (ImageView) findViewById(R.id.photo_imageview);
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.go_camera:
                    getCameraAndContactsPermission();
                    break;
            }
        }
    
        private boolean addPermission(List<String> permissionsList, String permission) {
            if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
                permissionsList.add(permission);
                if (!ActivityCompat.shouldShowRequestPermissionRationale(this, permission))
                    return false;
            }
            return true;
        }
    
        private void getCameraAndContactsPermission() {
            List<String> permissionsNeeded = new ArrayList<String>();
            final List<String> permissionsList = new ArrayList<String>();
            if (!addPermission(permissionsList, Manifest.permission.CAMERA)) {
                permissionsNeeded.add("相机");
            }
            if (!addPermission(permissionsList, Manifest.permission.READ_CONTACTS)) {
                permissionsNeeded.add("读联系人");
            }
            if (!addPermission(permissionsList, Manifest.permission.WRITE_CONTACTS)) {
                permissionsNeeded.add("写联系人");
            }
            if (permissionsList.size() > 0) {
                if (permissionsNeeded.size() > 0) {
                    String message = getResources().getString(R.string.permission_rationale, permissionsNeeded.get(0));
                    for (int i = 1; i < permissionsNeeded.size(); i++)
                        message = message + ", " + permissionsNeeded.get(i);
                    showRationaleDialog(message,
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    ActivityCompat.requestPermissions(MultiNormalActivity.this, permissionsList.toArray(new String[permissionsList.size()]),
                                            PERMISSION_REQUEST_CODE);
                                }
                            });
                    return;
                }
                ActivityCompat.requestPermissions(this, permissionsList.toArray(new String[permissionsList.size()]),
                        PERMISSION_REQUEST_CODE);
                return;
            }
            camera();
        }
    
        @Override
        public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
            switch (requestCode) {
                case PERMISSION_REQUEST_CODE: {
                    Map<String, Integer> perms = new HashMap<String, Integer>();
                    perms.put(Manifest.permission.CAMERA, PackageManager.PERMISSION_GRANTED);
                    perms.put(Manifest.permission.READ_CONTACTS, PackageManager.PERMISSION_GRANTED);
                    perms.put(Manifest.permission.WRITE_CONTACTS, PackageManager.PERMISSION_GRANTED);
                    for (int i = 0; i < permissions.length; i++)
                        perms.put(permissions[i], grantResults[i]);
                    if (perms.get(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
                            && perms.get(Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED
                            && perms.get(Manifest.permission.WRITE_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
                        camera();
                    } else {
                        Toast.makeText(this, getResources().getString(R.string.permission_denied), Toast.LENGTH_SHORT).show();
                    }
                }
                break;
                default:
                    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            }
        }
    
        private void camera() {
            Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            startActivityForResult(openCameraIntent, CAMERA_REQUEST_CODE);
        }
    
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == RESULT_OK) {
                switch (requestCode) {
                    case CAMERA_REQUEST_CODE:
                        Bitmap bm = (Bitmap) data.getExtras().get("data");
                        mPhotoImageView.setImageBitmap(bm);
                        break;
                    default:
                        break;
                }
            }
        }
    
        private void showRationaleDialog(String message, DialogInterface.OnClickListener okListener) {
            new AlertDialog.Builder(this)
                    .setMessage(message)
                    .setPositiveButton("OK", okListener)
                    .setNegativeButton("Cancel", null)
                    .create()
                    .show();
        }
    
    }

      从程序中可知,一次请求多个权限的过程同一次请求一个权限的过程,所以不再对其进行分析,读者可下载示例源码自行查看结果。

    使用PermissionDispatcher库请求权限

      使用Android原生API请求权限有些复杂,所以出现了很多第三方库来简化过程,PermissionDispatcher是其中一个比较好用的库,接下来对使用其进行权限请求进行介绍。
    继续以拍照为例。

    一次请求一个权限

    在AndroidManifest.xml中声明权限

    <uses-permission android:name="android.permission.CAMERA" />

    在SinglePermissionDispatcherActivity.java中动态请求权限

    /**
     * 使用PermissionDispatcher处理一次单个权限请求
     * Created by sunxiaodong on 16/4/26.
     */
    @RuntimePermissions
    public class SinglePermissionDispatcherActivity extends AppCompatActivity implements View.OnClickListener {
    
        private static final int CAMERA_REQUEST_CODE = 1;
    
        private Button mGoCamera;
        private ImageView mPhotoImageView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.camera_activity);
            initView();
        }
    
        private void initView() {
            mGoCamera = (Button) findViewById(R.id.go_camera);
            mGoCamera.setOnClickListener(this);
            mPhotoImageView = (ImageView) findViewById(R.id.photo_imageview);
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.go_camera:
                    SinglePermissionDispatcherActivityPermissionsDispatcher.cameraWithCheck(this);
                    break;
            }
        }
    
        @NeedsPermission(Manifest.permission.CAMERA)
        public void camera() {
            Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            startActivityForResult(openCameraIntent, CAMERA_REQUEST_CODE);
        }
    
        @OnShowRationale(Manifest.permission.CAMERA)
        void showRationaleForCamera(PermissionRequest request) {
            showRationaleDialog(R.string.permission_camera_rationale, request);
        }
    
        @OnPermissionDenied(Manifest.permission.CAMERA)
        void onCameraDenied() {
            Toast.makeText(this, R.string.permission_camera_denied, Toast.LENGTH_SHORT).show();
        }
    
        @OnNeverAskAgain(Manifest.permission.CAMERA)
        void onCameraNeverAskAgain() {
            Toast.makeText(this, R.string.permission_camera_never_askagain, Toast.LENGTH_SHORT).show();
        }
    
        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            SinglePermissionDispatcherActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
        }
    
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == RESULT_OK) {
                switch (requestCode) {
                    case CAMERA_REQUEST_CODE:
                        Bitmap bm = (Bitmap) data.getExtras().get("data");
                        mPhotoImageView.setImageBitmap(bm);
                        break;
                    default:
                        break;
                }
            }
        }
    
        private void showRationaleDialog(@StringRes int messageResId, final PermissionRequest request) {
            new AlertDialog.Builder(this)
                    .setPositiveButton(R.string.button_allow, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(@NonNull DialogInterface dialog, int which) {
                            request.proceed();
                        }
                    })
                    .setNegativeButton(R.string.button_deny, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(@NonNull DialogInterface dialog, int which) {
                            request.cancel();
                        }
                    })
                    .setCancelable(false)
                    .setMessage(messageResId)
                    .show();
        }
    
    }

    下面给出授权过程的一个执行路径
      首次点击拍照按钮,弹出系统的授权请求对话框:
    这里写图片描述

      点击授权请求对话框的“拒绝”选项后,再次点击拍照按钮,弹出自定义授权解释对话框:
    这里写图片描述

      点击自定义授权解释对话框的“允许”选项后,弹出有“不再询问”选项的授权请求对话框:
    这里写图片描述

      选择“不再询问”选项,点击授权请求对话框的“拒绝”选项后,再次点击拍照按钮,弹出授权不再询问的Toast提示:
    这里写图片描述

    一次请求多个权限

    在AndroidManifest.xml中声明权限

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />

    在MultiPermissionDispatcherActivity.java中动态请求权限

    /**
     * 使用PermissionDispatcher处理一次多个权限请求
     * Created by sunxiaodong on 16/4/26.
     */
    @RuntimePermissions
    public class MultiPermissionDispatcherActivity extends AppCompatActivity implements View.OnClickListener {
    
        private static final int CAMERA_REQUEST_CODE = 1;
    
        private Button mGoCamera;
        private ImageView mPhotoImageView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.camera_activity);
            initView();
        }
    
        private void initView() {
            mGoCamera = (Button) findViewById(R.id.go_camera);
            mGoCamera.setOnClickListener(this);
            mPhotoImageView = (ImageView) findViewById(R.id.photo_imageview);
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.go_camera:
                    MultiPermissionDispatcherActivityPermissionsDispatcher.cameraWithCheck(this);
                    break;
            }
        }
    
        @NeedsPermission({Manifest.permission.CAMERA, Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS})
        public void camera() {
            Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            startActivityForResult(openCameraIntent, CAMERA_REQUEST_CODE);
        }
    
        @OnShowRationale({Manifest.permission.CAMERA, Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS})
        void showRationaleForCamera(PermissionRequest request) {
            showRationaleDialog(R.string.permission_camera_contacts_rationale, request);
        }
    
        @OnPermissionDenied({Manifest.permission.CAMERA, Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS})
        void onCameraDenied() {
            Toast.makeText(this, R.string.permission_denied, Toast.LENGTH_SHORT).show();
        }
    
        @OnNeverAskAgain({Manifest.permission.CAMERA, Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS})
        void onCameraNeverAskAgain() {
            Toast.makeText(this, R.string.permission_never_askagain, Toast.LENGTH_SHORT).show();
        }
    
        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            MultiPermissionDispatcherActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
        }
    
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == RESULT_OK) {
                switch (requestCode) {
                    case CAMERA_REQUEST_CODE:
                        Bitmap bm = (Bitmap) data.getExtras().get("data");
                        mPhotoImageView.setImageBitmap(bm);
                        break;
                    default:
                        break;
                }
            }
        }
    
        private void showRationaleDialog(@StringRes int messageResId, final PermissionRequest request) {
            new AlertDialog.Builder(this)
                    .setPositiveButton(R.string.button_allow, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(@NonNull DialogInterface dialog, int which) {
                            request.proceed();
                        }
                    })
                    .setNegativeButton(R.string.button_deny, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(@NonNull DialogInterface dialog, int which) {
                            request.cancel();
                        }
                    })
                    .setCancelable(false)
                    .setMessage(messageResId)
                    .show();
        }
    
    }

      从程序中可知,使用PermissionDispatcher一次请求多个权限的过程同一次请求一个权限的过程,所以不再对其进行分析,读者可下载示例源码自行查看结果。

    源码地址

    展开全文
  • android权限

    万次阅读 2013-06-21 12:48:53
    常用权限: 读写存储卡 装载和卸载文件系统 android.permission.WRITE_EXTERNAL_STORAGE android.permission.READ_EXTERNAL_STORAGE android.permission.MOUNT_UNMOUNT_FILESYSTEMS 网络...

    常用权限:

    读写存储卡

    装载和卸载文件系统
    android.permission.WRITE_EXTERNAL_STORAGE
    android.permission.READ_EXTERNAL_STORAGE
    android.permission.MOUNT_UNMOUNT_FILESYSTEMS
    网络连接
    android.permission.INTERNET
    android.permission.ACCESS_NETWORK_STATE
    android.permission.ACCESS_WIFI_STATE
    android.permission.CHANGE_WIFI_STATE
    开机启动
    android.permission.RECEIVE_BOOT_COMPLETED
    精准的GPS位置
    基于网络的粗略的位置
    获取模拟定位信息(调试)
    android.permission.ACCESS_FINE_LOCATION
    android.permission.ACCESS_COARSE_LOCATION
    android.permission.ACCESS_MOCK_LOCATION
    短信
    android.permission.BROADCAST_SMS
    android.permission.READ_SMS
    android.permission.SEND_SMS
    android.permission.RECEIVE_SMS
    android.permission.WRITE_SMS
    拨打电话
    允许程序拨打电话 (任何电话)
    android.permission.CALL_PHONE
    android.permission.CALL_PRIVILEGED
    读取联系人
    读取通话记录
    android.permission.READ_CONTACTS
    android.permission.WRITE_CONTACTS
    android.permission.READ_CALL_LOG
    android.permission.WRITE_CALL_LOG
    安装/卸载快捷方式
    com.android.launcher.permission.INSTALL_SHORTCUT
    com.android.launcher.permission.UNINSTALL_SHORTCUT
    录音
    修改声音设置
    android.permission.RECORD_AUDIO
    android.permission.MODIFY_AUDIO_SETTINGS
    振动
    android.permission.VIBRATE
    默认
    android.permission.BAIDU_LOCATION_SERVICE
    读写手机状态和身份
    android.permission.READ_PHONE_STATE
    装载和卸载文件系统
    android.permission.MOUNT_UNMOUNT_FILESYSTEMS
    查阅敏感日志数据
    android.permission.READ_LOGS
    发送持久广播
    android.permission.BROADCAST_STICKY
    修改全局系统设置
    android.permission.WRITE_SETTINGS
    唤醒
    android.permission.WAKE_LOCK
    关闭程序
    android.permission.RESTART_PACKAGES
    android.permission.KILL_BACKGROUND_PROCESSES
    android浏览器插件开发
    android.webkit.permission.PLUGIN
    禁用键盘锁
    android.permission.DISABLE_KEYGUARD
    写入浏览器的收藏夹和历史记录

    com.android.browser.permission.WRITE_HISTORY_BOOKMARKS
    com.android.browser.permission.READ_HISTORY_BOOKMARKS
    调用Camera
    android.permission.CAMERA

    android.permission.WRITE_APN_SETTINGS

    android.permission.GET_TASKS
       


    自定义权限:

    http://berdy.iteye.com/blog/1782854

    http://blog.csdn.net/myhu730/article/details/6816880


    权限:http://blog.csdn.net/dianyueneo/article/details/7224756

    访问登记属性 android.permission.ACCESS_CHECKIN_PROPERTIES,读取或写入登记check-in数据库属性表的权限
    获取错略位置 android.permission.ACCESS_COARSE_LOCATION,通过WiFi或移动基站的方式获取用户错略的经纬度信息,定位精度大概误差在30~1500米
    获取精确位置 android.permission.ACCESS_FINE_LOCATION,通过GPS芯片接收卫星的定位信息,定位精度达10米以内
    访问定位额外命令 android.permission.ACCESS_LOCATION_EXTRA_COMMANDS,允许程序访问额外的定位提供者指令
    获取模拟定位信息 android.permission.ACCESS_MOCK_LOCATION,获取模拟定位信息,一般用于帮助开发者调试应用
    获取网络状态 android.permission.ACCESS_NETWORK_STATE,获取网络信息状态,如当前的网络连接是否有效
    访问Surface Flinger android.permission.ACCESS_SURFACE_FLINGER,Android平台上底层的图形显示支持,一般用于游戏或照相机预览界面和底层模式的屏幕截图
    获取WiFi状态 android.permission.ACCESS_WIFI_STATE,获取当前WiFi接入的状态以及WLAN热点的信息
    账户管理 android.permission.ACCOUNT_MANAGER,获取账户验证信息,主要为GMail账户信息,只有系统级进程才能访问的权限
    验证账户 android.permission.AUTHENTICATE_ACCOUNTS,允许一个程序通过账户验证方式访问账户管理ACCOUNT_MANAGER相关信息
    电量统计 android.permission.BATTERY_STATS,获取电池电量统计信息
    绑定小插件 android.permission.BIND_APPWIDGET,允许一个程序告诉appWidget服务需要访问小插件的数据库,只有非常少的应用才用到此权限
    绑定设备管理 android.permission.BIND_DEVICE_ADMIN,请求系统管理员接收者receiver,只有系统才能使用
    绑定输入法 android.permission.BIND_INPUT_METHOD ,请求InputMethodService服务,只有系统才能使用
    绑定RemoteView android.permission.BIND_REMOTEVIEWS,必须通过RemoteViewsService服务来请求,只有系统才能用
    绑定壁纸 android.permission.BIND_WALLPAPER,必须通过WallpaperService服务来请求,只有系统才能用
    使用蓝牙 android.permission.BLUETOOTH,允许程序连接配对过的蓝牙设备
    蓝牙管理 android.permission.BLUETOOTH_ADMIN,允许程序进行发现和配对新的蓝牙设备
    变成砖头 android.permission.BRICK,能够禁用手机,非常危险,顾名思义就是让手机变成砖头
    应用删除时广播 android.permission.BROADCAST_PACKAGE_REMOVED,当一个应用在删除时触发一个广播
    收到短信时广播 android.permission.BROADCAST_SMS,当收到短信时触发一个广播
    连续广播 android.permission.BROADCAST_STICKY,允许一个程序收到广播后快速收到下一个广播
    WAP PUSH广播 android.permission.BROADCAST_WAP_PUSH,WAP PUSH服务收到后触发一个广播
    拨打电话 android.permission.CALL_PHONE,允许程序从非系统拨号器里输入电话号码
    通话权限 android.permission.CALL_PRIVILEGED,允许程序拨打电话,替换系统的拨号器界面
    拍照权限 android.permission.CAMERA,允许访问摄像头进行拍照
    改变组件状态 android.permission.CHANGE_COMPONENT_ENABLED_STATE,改变组件是否启用状态
    改变配置 android.permission.CHANGE_CONFIGURATION,允许当前应用改变配置,如定位
    改变网络状态 android.permission.CHANGE_NETWORK_STATE,改变网络状态如是否能联网
    改变WiFi多播状态 android.permission.CHANGE_WIFI_MULTICAST_STATE,改变WiFi多播状态
    改变WiFi状态 android.permission.CHANGE_WIFI_STATE,改变WiFi状态
    清除应用缓存 android.permission.CLEAR_APP_CACHE,清除应用缓存
    清除用户数据 android.permission.CLEAR_APP_USER_DATA,清除应用的用户数据
    底层访问权限 android.permission.CWJ_GROUP,允许CWJ账户组访问底层信息
    手机优化大师扩展权限 android.permission.CELL_PHONE_MASTER_EX,手机优化大师扩展权限
    控制定位更新 android.permission.CONTROL_LOCATION_UPDATES,允许获得移动网络定位信息改变
    删除缓存文件 android.permission.DELETE_CACHE_FILES,允许应用删除缓存文件
    删除应用 android.permission.DELETE_PACKAGES,允许程序删除应用
    电源管理 android.permission.DEVICE_POWER,允许访问底层电源管理
    应用诊断 android.permission.DIAGNOSTIC,允许程序到RW到诊断资源
    禁用键盘锁 android.permission.DISABLE_KEYGUARD,允许程序禁用键盘锁
    转存系统信息 android.permission.DUMP,允许程序获取系统dump信息从系统服务
    状态栏控制 android.permission.EXPAND_STATUS_BAR,允许程序扩展或收缩状态栏
    工厂测试模式 android.permission.FACTORY_TEST,允许程序运行工厂测试模式
    使用闪光灯 android.permission.FLASHLIGHT,允许访问闪光灯
    强制后退 android.permission.FORCE_BACK,允许程序强制使用back后退按键,无论Activity是否在顶层
    访问账户Gmail列表 android.permission.GET_ACCOUNTS,访问GMail账户列表
    获取应用大小 android.permission.GET_PACKAGE_SIZE,获取应用的文件大小
    获取任务信息 android.permission.GET_TASKS,允许程序获取当前或最近运行的应用
    允许全局搜索 android.permission.GLOBAL_SEARCH,允许程序使用全局搜索功能
    硬件测试 android.permission.HARDWARE_TEST,访问硬件辅助设备,用于硬件测试
    注射事件 android.permission.INJECT_EVENTS,允许访问本程序的底层事件,获取按键、轨迹球的事件流
    安装定位提供 android.permission.INSTALL_LOCATION_PROVIDER,安装定位提供
    安装应用程序 android.permission.INSTALL_PACKAGES,允许程序安装应用
    内部系统窗口 android.permission.INTERNAL_SYSTEM_WINDOW,允许程序打开内部窗口,不对第三方应用程序开放此权限
    访问网络 android.permission.INTERNET,访问网络连接,可能产生GPRS流量
    结束后台进程 android.permission.KILL_BACKGROUND_PROCESSES,允许程序调用killBackgroundProcesses(String).方法结束后台进程
    管理账户 android.permission.MANAGE_ACCOUNTS,允许程序管理AccountManager中的账户列表
    管理程序引用 android.permission.MANAGE_APP_TOKENS,管理创建、摧毁、Z轴顺序,仅用于系统
    高级权限 android.permission.MTWEAK_USER,允许mTweak用户访问高级系统权限
    社区权限 android.permission.MTWEAK_FORUM,允许使用mTweak社区权限
    软格式化 android.permission.MASTER_CLEAR,允许程序执行软格式化,删除系统配置信息
    修改声音设置 android.permission.MODIFY_AUDIO_SETTINGS,修改声音设置信息
    修改电话状态 android.permission.MODIFY_PHONE_STATE,修改电话状态,如飞行模式,但不包含替换系统拨号器界面
    格式化文件系统 android.permission.MOUNT_FORMAT_FILESYSTEMS,格式化可移动文件系统,比如格式化清空SD卡
    挂载文件系统 android.permission.MOUNT_UNMOUNT_FILESYSTEMS,挂载、反挂载外部文件系统
    允许NFC通讯 android.permission.NFC,允许程序执行NFC近距离通讯操作,用于移动支持
    永久Activity android.permission.PERSISTENT_ACTIVITY,创建一个永久的Activity,该功能标记为将来将被移除
    处理拨出电话 android.permission.PROCESS_OUTGOING_CALLS,允许程序监视,修改或放弃播出电话
    读取日程提醒 android.permission.READ_CALENDAR,允许程序读取用户的日程信息
    读取联系人 android.permission.READ_CONTACTS,允许应用访问联系人通讯录信息
    屏幕截图 android.permission.READ_FRAME_BUFFER,读取帧缓存用于屏幕截图
    读取收藏夹和历史记录 com.android.browser.permission.READ_HISTORY_BOOKMARKS,读取浏览器收藏夹和历史记录
    读取输入状态 android.permission.READ_INPUT_STATE,读取当前键的输入状态,仅用于系统
    读取系统日志 android.permission.READ_LOGS,读取系统底层日志
    读取电话状态 android.permission.READ_PHONE_STATE,访问电话状态
    读取短信内容 android.permission.READ_SMS,读取短信内容
    读取同步设置 android.permission.READ_SYNC_SETTINGS,读取同步设置,读取Google在线同步设置
    读取同步状态 android.permission.READ_SYNC_STATS,读取同步状态,获得Google在线同步状态
    重启设备 android.permission.REBOOT,允许程序重新启动设备
    开机自动允许 android.permission.RECEIVE_BOOT_COMPLETED,允许程序开机自动运行
    接收彩信 android.permission.RECEIVE_MMS,接收彩信
    接收短信 android.permission.RECEIVE_SMS,接收短信
    接收Wap Push android.permission.RECEIVE_WAP_PUSH,接收WAP PUSH信息
    录音 android.permission.RECORD_AUDIO,录制声音通过手机或耳机的麦克
    排序系统任务 android.permission.REORDER_TASKS,重新排序系统Z轴运行中的任务
    结束系统任务 android.permission.RESTART_PACKAGES,结束任务通过restartPackage(String)方法,该方式将在外来放弃
    发送短信 android.permission.SEND_SMS,发送短信
    设置Activity观察其 android.permission.SET_ACTIVITY_WATCHER,设置Activity观察器一般用于monkey测试
    设置闹铃提醒 com.android.alarm.permission.SET_ALARM,设置闹铃提醒
    设置总是退出 android.permission.SET_ALWAYS_FINISH,设置程序在后台是否总是退出
    设置动画缩放 android.permission.SET_ANIMATION_SCALE,设置全局动画缩放
    设置调试程序 android.permission.SET_DEBUG_APP,设置调试程序,一般用于开发
    设置屏幕方向 android.permission.SET_ORIENTATION,设置屏幕方向为横屏或标准方式显示,不用于普通应用
    设置应用参数 android.permission.SET_PREFERRED_APPLICATIONS,设置应用的参数,已不再工作具体查看addPackageToPreferred(String) 介绍
    设置进程限制 android.permission.SET_PROCESS_LIMIT,允许程序设置最大的进程数量的限制
    设置系统时间 android.permission.SET_TIME,设置系统时间
    设置系统时区 android.permission.SET_TIME_ZONE,设置系统时区
    设置桌面壁纸 android.permission.SET_WALLPAPER,设置桌面壁纸
    设置壁纸建议 android.permission.SET_WALLPAPER_HINTS,设置壁纸建议
    发送永久进程信号 android.permission.SIGNAL_PERSISTENT_PROCESSES,发送一个永久的进程信号
    状态栏控制 android.permission.STATUS_BAR,允许程序打开、关闭、禁用状态栏
    访问订阅内容 android.permission.SUBSCRIBED_FEEDS_READ,访问订阅信息的数据库
    写入订阅内容 android.permission.SUBSCRIBED_FEEDS_WRITE,写入或修改订阅内容的数据库
    显示系统窗口 android.permission.SYSTEM_ALERT_WINDOW,显示系统窗口
    更新设备状态 android.permission.UPDATE_DEVICE_STATS,更新设备状态
    使用证书 android.permission.USE_CREDENTIALS,允许程序请求验证从AccountManager
    使用SIP视频 android.permission.USE_SIP,允许程序使用SIP视频服务
    使用振动 android.permission.VIBRATE,允许振动
    唤醒锁定 android.permission.WAKE_LOCK,允许程序在手机屏幕关闭后后台进程仍然运行
    写入GPRS接入点设置 android.permission.WRITE_APN_SETTINGS,写入网络GPRS接入点设置
    写入日程提醒 android.permission.WRITE_CALENDAR,写入日程,但不可读取
    写入联系人 android.permission.WRITE_CONTACTS,写入联系人,但不可读取
    写入外部存储 android.permission.WRITE_EXTERNAL_STORAGE,允许程序写入外部存储,如SD卡上写文件
    写入Google地图数据 android.permission.WRITE_GSERVICES,允许程序写入Google Map服务数据
    写入收藏夹和历史记录 com.android.browser.permission.WRITE_HISTORY_BOOKMARKS,写入浏览器历史记录或收藏夹,但不可读取
    读写系统敏感设置 android.permission.WRITE_SECURE_SETTINGS,允许程序读写系统安全敏感的设置项
    读写系统设置 android.permission.WRITE_SETTINGS,允许读写系统设置项
    编写短信 android.permission.WRITE_SMS,允许编写短信
    写入在线同步设置 android.permission.WRITE_SYNC_SETTINGS,写入Google在线同步设置
             
    展开全文
  • Android 权限

    千次阅读 2011-12-14 08:16:47
    介绍一下android的各种权限。 代码如下: <manifestxmlns:android="http://schemas.android.com/apk/res/android" package="net.sunniwell.launcher" android:versionCode="1"android:versionName="1.0.1"> ...

    介绍一下android的各种权限。

    代码如下:

    <manifestxmlns:android="http://schemas.android.com/apk/res/android"
          package="net.sunniwell.launcher"
          android:versionCode="1"android:versionName="1.0.1">


     

    关于自定义权限,这是很好的例子,其他apk程序要想使用Launcher的功能必须添加这些权限,而这些权限都是在这里声明的。


    这个是安装快捷方式的权限定义:

    <permission
            android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
            android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
            android:protectionLevel="normal"
            android:label="@string/permlab_install_shortcut"
            android:description="@string/permdesc_install_shortcut"/>




    这个是卸载快捷方式的权限定义:

    <permission
            android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"
            android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
            android:protectionLevel="normal"
            android:label="@string/permlab_uninstall_shortcut"
            android:description="@string/permdesc_uninstall_shortcut"/>



    这个是读取launcher.db内容的权限定义:

    <permission
            android:name="net.sunniwell.launcher.permission.READ_SETTINGS"
            android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
            android:protectionLevel="normal"
            android:label="@string/permlab_read_settings"
            android:description="@string/permdesc_read_settings"/>



    这个是修改和删除launcher.db内容的权限定义:

    <permission
            android:name="net.sunniwell.launcher.permission.WRITE_SETTINGS"
            android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
            android:protectionLevel="normal"
            android:label="@string/permlab_write_settings"
            android:description="@string/permdesc_write_settings"/>
     


    这些是Launcher的权限声明,通过这些就能看出launcher的大概功能了:

     

    打电话权限:


    <uses-permissionandroid:name="android.permission.CALL_PHONE"/>


    使用状态栏权限:


    <uses-permissionandroid:name="android.permission.EXPAND_STATUS_BAR"/>


    获取当前或最近运行的任务的信息的权限:


    <uses-permissionandroid:name="android.permission.GET_TASKS"/>


    读取通信录权限:


    <uses-permissionandroid:name="android.permission.READ_CONTACTS"/>


    设置壁纸权限:

    <uses-permissionandroid:name="android.permission.SET_WALLPAPER"/>


    允许程序设置壁纸hits的权限:

    <uses-permissionandroid:name="android.permission.SET_WALLPAPER_HINTS"/>


    使用震动功能权限:

    <uses-permissionandroid:name="android.permission.VIBRATE"/>


    修改删除launcher.db内容权限:

    <uses-permissionandroid:name="android.permission.WRITE_SETTINGS"/>


    绑定widget权限:

    <uses-permissionandroid:name="android.permission.BIND_APPWIDGET"/>


    读取launcher.db内容权限:

    <uses-permissionandroid:name="net.sunniwell.launcher.permission.READ_SETTINGS"/>


    修改删除launcher.db内容权限:

    <uses-permissionandroid:name="net.sunniwell.launcher.permission.WRITE_SETTINGS"/>


    读写外部存储设备权限:

    <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>


    <application
            android:name="LauncherApplication"
          activity应该运行的进程的名字:
    android:process="android.process.acore"
            android:label="@string/application_name"
            android:icon="@drawable/swicon">
    
    <activity
                android:name="Launcher"
               是否
    android:launchMode="singleTask"
                android:clearTaskOnLaunch="true"
                这个activity是否在被杀死或者重启后能恢复原来的状态:
    android:stateNotNeeded="true"
                android:theme="@style/Theme"
                android:screenOrientation="landscape"
                android:windowSoftInputMode="stateUnspecified|adjustPan">
    
    <intent-filter>
    
    <actionandroid:name="android.intent.action.MAIN"/>
    
    <categoryandroid:name="android.intent.category.LAUNCHER"/>
    


    桌面应用的标记:

    <categoryandroid:name="android.intent.category.HOME"/>
    
    <categoryandroid:name="android.intent.category.DEFAULT"/>



    自动化测试工具Monkey的标记,待研究…

    <categoryandroid:name="android.intent.category.MONKEY"/>
    
    </intent-filter>
    
    </activity>


    
    

    选择壁纸的activity:

    <activity

                android:name="WallpaperChooser"

                android:label="@string/pick_wallpaper"

                android:icon="@drawable/ic_launcher_gallery">


    设置壁纸的intent-filter:


    <intent-filter>
    
    <actionandroid:name="android.intent.action.SET_WALLPAPER"/>
    
    <categoryandroid:name="android.intent.category.DEFAULT"/>
    
    </intent-filter>


    搜索的activity:

    </activity>
    
    <!-- Enable system-default search mode for any activity in Home -->
    
    <meta-data
                android:name="android.app.default_searchable"
                android:value="*"/>
     


     

    安装快捷方式的广播接收器:


    <!-- Intent received used to install shortcuts from other applications-->
    
    
    <receiver
                android:name=".InstallShortcutReceiver"
                android:permission="com.android.launcher.permission.INSTALL_SHORTCUT">
    
    <intent-filter>
    
    <actionandroid:name="com.android.launcher.action.INSTALL_SHORTCUT"/>
    
    </intent-filter>
    
    </receiver>
     
    
    <!-- Intent received used to uninstall shortcuts from other applications-->


    卸载快捷方式的广播接收器:


    <receiver
                android:name=".UninstallShortcutReceiver"
                android:permission="com.android.launcher.permission.UNINSTALL_SHORTCUT">
    
    <intent-filter>
    
    <actionandroid:name="com.android.launcher.action.UNINSTALL_SHORTCUT"/>
    
    </intent-filter>
    
    </receiver>


    声明ContentProvider,用于对launcher.db操作:

    <!-- The settings provider contains Home's data, like the workspacefavorites -->
    
    <provider
                android:name="SWLauncherProvider"
                android:authorities="net.sunniwell.launcher.settings"
                android:writePermission="net.sunniwell.launcher.permission.WRITE_SETTINGS"
                android:readPermission="net.sunniwell.launcher.permission.READ_SETTINGS"/>
     
    
    </application>
    
    <uses-sdkandroid:minSdkVersion="4"/>
     
    </manifest>


    说明:
    1.
    <manifest标签头部还应声明:
    android:sharedUserId="android.uid.shared",作用是获得系统权限,但是这样的程序属性只能在build整个系统时放进去(就是系统软件)才起作用,手动安装是没有权限的。

    展开全文
  • android 权限

    千次阅读 2010-12-26 21:08:00
    ACCESS_COARSE_LOCATION 是有关错略的位置信息获取,比如说MyLocation API调用获取的Cellid等定位信息必需添加android.permission.ACCESS_COARSE_LOCATION这个声明 <br />ACCESS_FINE_LOCATION、...

    ACCESS_COARSE_LOCATION

    是有关错略的位置信息获取,比如说MyLocation API调用获取的Cellid等定位信息必需添加android.permission.ACCESS_COARSE_LOCATION这个声明


    ACCESS_FINE_LOCATION
    ACCESS_LOCATION_EXTRA_COMMANDS ACCESS_MOCK_LOCATION

    是有关GPS定位获取的信息使用GPS LocationProvider类的相关定位信息必需声明android.permission.ACCESS_FINE_LOCATION android.permission.ACCESS_LOCATION_EXTRA_COMMANDS android.permission.ACCESS_MOCK_LOCATION 

    ACCESS_NETWORK_STATE

    是获取网络状态的权限控制,如果获取当前GSM网络相关信息必需在 androidmanifest.xml中声明android.permission.ACCESS_NETWORK_STATE这句。 

    ACCESS_SURFACE_FLINGER

    是使用SurfaceFlinger底层API的令牌,必需声明 android.permission.ACCESS_SURFACE_FLINGER 

    ACCESS_WIFI_STATE

    权限可以获取使用Wi-FiWLAN无线网络,加入 android.permission.ACCESS_WIFI_STATE这句 

    ADD_SYSTEM_SERVICE

    是系统服务数据库的管理权限,比如添加一个系统服务必需声明 android.permission.ADD_SYSTEM_SERVICE 


    BATTERY_STATS

    是获取Android平台上电池设备的权限令牌,必需声明 android.permission.BATTERY_STATS才可以获得电池信息 


    BLUETOOTH

    蓝牙信息类,获取相关的蓝牙信息必声明android.permission.BLUETOOTH


    BLUETOOTH_ADMIN

    是蓝牙管理权限包含了身份安全认证,必需添加 android.permission.BLUETOOTH_ADMIN

    BRICK    "android.permission.BRICK"  ???

    BROADCAST_PACKAGE_REMOVED

    是广播包移除类权限,可以移除指定的系统消息,必需声明 android.permission.BROADCAST_PACKAGE_REMOVED这句


    BROADCAST_STICKY    "android.permission.BROADCAST_STICKY" 


    CALL_PHONE

    是允许Android手机拨打电话时使用的权限    "android.permission.CALL_PHONE" 


    CALL_PRIVILEGED    "android.permission.CALL_PRIVILEGED" 


    CAMERA

    是摄像头权限控制,可以管理照相功能的启用    "android.permission.CAMERA" 


    CHANGE_COMPONENT_ENABLED_STATE    "android.permission.CHANGE_COMPONENT_ENABLED_STATE" 


    CHANGE_CONFIGURATION

    是控制Android系统设置等敏感信息的权限,修改时必需有 android.permission.CHANGE_CONFIGURATION声明。 


    CHANGE_NETWORK_STATE    "android.permission.CHANGE_NETWORK_STATE" 


    CHANGE_WIFI_STATE

    是改变WLAN状态的开关,如果打开或关闭Wi-Fi必需加入 android.permission.CHANGE_WIFI_STATE的声明。 


    CLEAR_APP_CACHE

    清除程序缓存也是需要权限的,不要忘了包含 android.permission.CLEAR_APP_CACHE这句


    CLEAR_APP_USER_DATA    "android.permission.CLEAR_APP_USER_DATA" 


    DELETE_CACHE_FILES    "android.permission.DELETE_CACHE_FILES" 


    DELETE_PACKAGES    "android.permission.DELETE_PACKAGES" 


    DEVICE_POWER    "android.permission.DEVICE_POWER" 


    DISABLE_KEYGUARD    "android.permission.DISABLE_KEYGUARD" 


    DUMP    "android.permission.DUMP" 


    EXPAND_STATUS_BAR    "android.permission.EXPAND_STATUS_BAR" 


    FACTORY_TEST    "android.permission.FACTORY_TEST" 
    FLASHLIGHT    "android.permission.FLASHLIGHT" 
    FORCE_BACK    "android.permission.FORCE_BACK" 
    FOTA_UPDATE    "android.permission.FOTA_UPDATE" 
    GET_ACCOUNTS    "android.permission.GET_ACCOUNTS" 
    GET_PACKAGE_SIZE    "android.permission.GET_PACKAGE_SIZE" 
    GET_TASKS    "android.permission.GET_TASKS" 
    HARDWARE_TEST    "android.permission.HARDWARE_TEST" 
    INJECT_EVENTS    "android.permission.INJECT_EVENTS" 
    INSTALL_PACKAGES    "android.permission.INSTALL_PACKAGES" 
    INTERNAL_SYSTEM_WINDOW    "android.permission.INTERNAL_SYSTEM_WINDOW" 
    INTERNET    "android.permission.INTERNET" 
    MANAGE_APP_TOKENS    "android.permission.MANAGE_APP_TOKENS" 
    MASTER_CLEAR    "android.permission.MASTER_CLEAR" 
    MODIFY_AUDIO_SETTINGS    "android.permission.MODIFY_AUDIO_SETTINGS" 
    MODIFY_PHONE_STATE    "android.permission.MODIFY_PHONE_STATE" 
    MOUNT_UNMOUNT_FILESYSTEMS    "android.permission.MOUNT_UNMOUNT_FILESYSTEMS" 
    PERSISTENT_ACTIVITY    "android.permission.PERSISTENT_ACTIVITY" 
    PROCESS_OUTGOING_CALLS    "android.permission.PROCESS_OUTGOING_CALLS" 
    READ_CALENDAR    "android.permission.READ_CALENDAR" 
    READ_CONTACTS    "android.permission.READ_CONTACTS" 
    READ_FRAME_BUFFER    "android.permission.READ_FRAME_BUFFER" 
    READ_INPUT_STATE    "android.permission.READ_INPUT_STATE" 
    READ_LOGS    "android.permission.READ_LOGS" 
    READ_OWNER_DATA    "android.permission.READ_OWNER_DATA" 
    READ_PHONE_STATE    "android.permission.READ_PHONE_STATE" 
    READ_SMS    "android.permission.READ_SMS" 
    READ_SYNC_SETTINGS    "android.permission.READ_SYNC_SETTINGS" 
    READ_SYNC_STATS    "android.permission.READ_SYNC_STATS" 


    RECEIVE_BOOT_COMPLETED

    一般用于自启动程序的声明,当Android系统启动时会发送这个广播,所以自启动程序必需 声明android.permission.RECEIVE_BOOT_COMPLETED才可以正常运行

    RECEIVE_MMS    "android.permission.RECEIVE_MMS" 
    RECEIVE_SMS    "android.permission.RECEIVE_SMS" 
    RECEIVE_WAP_PUSH    "android.permission.RECEIVE_WAP_PUSH" 
    RECORD_AUDIO    "android.permission.RECORD_AUDIO" 
    REORDER_TASKS    "android.permission.REORDER_TASKS" 
    RESTART_PACKAGES    "android.permission.RESTART_PACKAGES" 
    SEND_SMS    "android.permission.SEND_SMS" 
    SET_ACTIVITY_WATCHER    "android.permission.SET_ACTIVITY_WATCHER" 
    SET_ALWAYS_FINISH    "android.permission.SET_ALWAYS_FINISH" 
    SET_ANIMATION_SCALE    "android.permission.SET_ANIMATION_SCALE" 
    SET_DEBUG_APP    "android.permission.SET_DEBUG_APP" 
    SET_ORIENTATION    "android.permission.SET_ORIENTATION" 
    SET_PREFERRED_APPLICATIONS    "android.permission.SET_PREFERRED_APPLICATIONS" 
    SET_PROCESS_FOREGROUND    "android.permission.SET_PROCESS_FOREGROUND" 
    SET_PROCESS_LIMIT    "android.permission.SET_PROCESS_LIMIT" 
    SET_TIME_ZONE    "android.permission.SET_TIME_ZONE" 
    SET_WALLPAPER    "android.permission.SET_WALLPAPER" 
    SET_WALLPAPER_HINTS    "android.permission.SET_WALLPAPER_HINTS" 
    SIGNAL_PERSISTENT_PROCESSES    "android.permission.SIGNAL_PERSISTENT_PROCESSES" 
    STATUS_BAR    "android.permission.STATUS_BAR" 
    SYSTEM_ALERT_WINDOW    "android.permission.SYSTEM_ALERT_WINDOW" 
    VIBRATE    "android.permission.VIBRATE" 
    WAKE_LOCK    "android.permission.WAKE_LOCK" 
    WRITE_CALENDAR    "android.permission.WRITE_CALENDAR" 
    WRITE_CONTACTS    "android.permission.WRITE_CONTACTS" 
    WRITE_OWNER_DATA    "android.permission.WRITE_OWNER_DATA" 
    WRITE_SETTINGS    "android.permission.WRITE_SETTINGS" 
    WRITE_SMS    "android.permission.WRITE_SMS" 
    WRITE_SYNC_SETTINGS    "android.permission.WRITE_SYNC_SETTINGS" 

    展开全文
  • Android权限管理

    千次阅读 2019-07-17 12:39:52
    Android权限管理(PermissionsDispatcher框架使用)简述一、Android权限二、6.0以上权限管理 简述 由于对于安全考虑,Android对于权限的管理更加的严谨,以6.0位界分为两种处理方式:6.0以下系统还是保持旧的处理...
  • Unity Android 权限

    万次阅读 2017-06-22 14:22:13
    unity android 权限
  • 本文显示Android的权限大全和动态使用Android权限方法
  • Xamarin Android权限请求

    千次阅读 2017-09-12 14:19:45
    Xamarin Android权限请求
  • Android 权限清单大全

    千次阅读 2014-08-01 10:40:21
    Android权限设置 概述 权限 说明 访问登记属性 android.permission.ACCESS_CHECKIN_PROPERTIES  读取或写入登记check-in数据库属性表的权限 获取错略位置 android.permission.ACCESS_COARSE_...
  • android 权限整理

    千次阅读 2014-03-18 17:21:18
    Android 权限 名称 权限描述 模块 分类 备注 危险等级 拨打电话 android.permission.CALL_PHONE,允许程序从非系统拨号器里输入电话号码 恶意程序可借此在您的话费单上产生意外通话费。 请注意,...
  • Android权限管理之自定义权限

    千次阅读 2014-03-02 14:21:44
    在Android 系统中,权限管理可以避免其他应用在不具备某项权限的时候进行某些危险性操作。 Android权限的配置位置在AndroidManifest.xml中,相关配置元素有、、、 普通的
  • Android 权限的一些细节

    万次阅读 多人点赞 2016-11-15 01:26:41
    Android 权限的一些细节0x01 哪些app属于system app?为了区分privilege app和system app,这里先说明system app是什么,避免之后的讨论概念混乱。
  • Android权限适配全攻略

    千次阅读 2017-10-09 14:49:43
    Android权限适配全攻略概述在Android6.0(API 23)之前Android的权限机制太过于简单粗暴:App安装时会提示用户APP所需权限,用户同意安装后就会永久授权应用所需全部权限。其中大部分用户并不知道为什么APP需要这些...
  • Android权限机制

    千次阅读 2011-08-18 16:00:41
    Android系统是运行在Linux内核上的,Android与Linux分别有自己的一套...作为这段时间对android权限学习的总结,也希望能对大家有所帮助,不正确之处请指出。 首先分清两个概念: 要区分apk运行时的拥有的权限与在文
  • Android权限之动态权限

    千次阅读 2019-05-05 14:57:08
    安卓系统的权限管理机制从API 23 (也就是Android 6.0 又叫做 Android M,)之后发生了比较大的改变,在一些比较危险的权限上要求必须申请动态权限,即使你在AndroidMainfest.xml文件中申请也没有任何用,或者你可以将...
  • Android权限(Permissions)处理

    千次阅读 2018-07-02 15:11:23
    Android权限主要用于限制应用程序内部某些具有限制性的功能使用,以及应用程序之间的组件访问。但是呢Android6.0之后,Google对权限做了一些优化,将一些权限的申请放在了应用运行的时候去申请(动态获取权限),所以...
  • cordova 插件 开发添加 android 权限

    千次阅读 2016-11-28 22:28:33
    cordova 插件 开发添加 android 权限
  • Android权限  权限是一种限制,用于限制对部分代码或设备上数据的访问。施加限制是为了保护可能被误用以致破坏或损害用户体验的关键数据和代码。每种权限均由一个唯一的标签标识。标签通常指示受限制的操作。  ...
  • Android权限操作之uses-permission详解

    千次阅读 2019-06-04 20:17:25
    本文实例讲述了Android权限操作之uses-permission。分享给大家供大家参考,具体如下: 我们在安装Android软件的时候,系统会提示该软件所需要的权限,相对于其他系统,android的权限非常多。我们在开发软件的时候,...
  • 一、Android 权限的完整列表, 请访问以下URL http://developer.android.com/reference/android/Manifest.permission.html 权限具有名称、标签、图标、权限组、描述和保护级别,以下表格定义了这些属性: ...
  • Android 权限设置大全

    千次阅读 2012-03-05 14:49:19
    android权限大全 访问登记属性 android.permission.ACCESS_CHECKIN_PROPERTIES ,读取或写入登记check-in数据库属性表的权限 获取错略位置 android.permission.ACCESS_COARSE_LOCATION,通过WiFi或移动基站...
  • Android权限申请

    千次阅读 2019-07-02 15:10:44
    一、定义一个BaseActivity public class BaseActivity extends AppCompatActivity { private PermissionListener ... * @param permissions 待申请的权限集合 * @param listener 申请结果监听事件 */ protected v...
  • android 权限录音权限检测

    万次阅读 2016-04-22 10:53:55
    最近在项目中要用到语音通话功能,后来测试发现通话过程中有听不到对方声音的情况,经过检测 其中有部分原因是因为有些手机在app安装后会被手机直接禁止录音权限,发现问题后去解决的过程发现,系统自己提供的检查...
  • Android权限列表permission介绍

    千次阅读 2010-08-04 11:19:00
    Android权限分的很细,但命名比较人性化,Android permission比Symbian Capabilities有了不少改进,下面就来看看权限许可都有哪些定义吧,发现还是比较繁多的,如果发现你的程序某个地方调试错误很可能是 ...
  • Android权限配置

    千次阅读 2016-07-18 11:52:43
    权限 名称 描述 android.permission.ACCESS_CHECKIN_PROPERTIES 访问登记属性 读取或写入登记check-in数据库属性表的权限 android.permission.ACCESS_COARSE_LOCATION ...
  • Android 权限控制代码分析

    万次阅读 多人点赞 2012-04-16 11:02:07
    Android 权限控制代码分析 前在文章介绍过android系统管理层次:http://blog.csdn.net/andyhuabing/article/details/7030212 ,这里就核心代码分析一下 android系统充分利用了linux的用户权限管理方法,...
  • android权限级别我分为普通权限、设备管理器权限、deviceowner权限、root权限。 普通权限需要在AndroidManifest.xml文件中注册才能获取,在api23及以上还需要动态申请。此类介绍实在太多,我不详细解释了。直接上...
  • Android 权限汇总大全

    千次阅读 2019-07-09 11:17:07
    android.permission.ACCESS_CHECKIN_PROPERTIES 访问登记属性 读取或写入登记check-in数据库属性表的权限 android.permission.ACCESS_COARSE_LOCATION 获取错略位置 通过WiFi或移动基站的方式获取用户错略的经纬度...

空空如也

1 2 3 4 5 ... 20
收藏数 45,570
精华内容 18,228
关键字:

android权限