【问题标题】:java.lang.SecurityException trying to read from Android Contacts URIjava.lang.SecurityException 试图从 Android 联系人 URI 中读取
【发布时间】:2011-03-08 14:07:34
【问题描述】:

我正在尝试从ContactsContract URI 读取联系人姓名、电话号码和电子邮件,当我尝试运行该程序时收到SecurityException。我在AndroidManifest.xml文件中设置了权限:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="edu.smumn.cs394"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8" />
    **<uses-permission android:name="android.pemission.READ_CONTACTS"/>**
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".ReadPhoneNumbers"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>`

以下是应用代码:

 @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.contact_list);       
        ContentResolver resolver = getContentResolver();
        Cursor c = resolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
 //[...] Work through data here`

最后一行出现安全异常 (resolver.query()):

`03-08 07:41:40.812: ERROR/AndroidRuntime(416): FATAL EXCEPTION: main
03-08 07:41:40.812: ERROR/AndroidRuntime(416): java.lang.RuntimeException: Unable to start activity ComponentInfo{edu.smumn.cs394/edu.smumn.cs394.ReadPhoneNumbers}: java.lang.SecurityException: Permission Denial: reading com.android.providers.contacts.ContactsProvider2 uri content://com.android.contacts/contacts from pid=416, uid=10037 requires android.permission.READ_CONTACTS
[...]
03-08 07:41:40.812: ERROR/AndroidRuntime(416): Caused by: java.lang.SecurityException: Permission Denial: reading com.android.providers.contacts.ContactsProvider2 uri content://com.android.contacts/contacts from pid=416, uid=10037 requires android.permission.READ_CONTACTS
[...]
03-08 07:41:40.812: ERROR/AndroidRuntime(416):     at edu.smumn.cs394.ReadPhoneNumbers.onCreate(ReadPhoneNumbers.java:30)

[...]`

我一定错过了什么,但我不知道是什么。

【问题讨论】:

  • 您的 AndroidManifest.xml 文件中有语法错误。在 行中,android.permission 在没有 R 的情况下写错了,应该看起来像“permission”而不是“pemission”。跨度>

标签: android permissions contacts


【解决方案1】:

在运行时请求权限

从 Android 6.0(API 级别 23)开始,用户在应用运行时授予应用权限,而不是在安装应用时。

如果您需要添加的权限未列在正常权限下,则需要处理“运行时权限”。运行时权限是在应用程序运行时根据需要请求的权限。这些权限将向用户显示一个对话框,类似于以下:

添加“运行时权限”的第一步是将其添加到 AndroidManifest:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.codepath.androidpermissionsdemo" >

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

接下来,您需要发起权限请求并处理结果。以下代码显示了如何在 Activity 的上下文中执行此操作,但也可以在 Fragment 中执行此操作。

// MainActivity.java
public class MainActivity extends AppCompatActivity {

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

        // In an actual app, you'd want to request a permission when the user performs an action
        // that requires that permission.
        getPermissionToReadUserContacts();
    }

    // Identifier for the permission request
    private static final int READ_CONTACTS_PERMISSIONS_REQUEST = 1;

    // Called when the user is performing an action which requires the app to read the
    // user's contacts
    public void getPermissionToReadUserContacts() {
        // 1) Use the support library version ContextCompat.checkSelfPermission(...) to avoid
        // checking the build version since Context.checkSelfPermission(...) is only available
        // in Marshmallow
        // 2) Always check for permission (even if permission has already been granted)
        // since the user can revoke permissions at any time through Settings
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)
                != PackageManager.PERMISSION_GRANTED) {

            // The permission is NOT already granted.
            // Check if the user has been asked about this permission already and denied
            // it. If so, we want to give more explanation about why the permission is needed.
            if (shouldShowRequestPermissionRationale(
                    Manifest.permission.READ_CONTACTS)) {
                // Show our own UI to explain to the user why we need to read the contacts
                // before actually requesting the permission and showing the default UI
            }

            // Fire off an async request to actually get the permission
            // This will show the standard permission request dialog UI
            requestPermissions(new String[]{Manifest.permission.READ_CONTACTS},
                    READ_CONTACTS_PERMISSIONS_REQUEST);
        }
    }

    // Callback with the request from calling requestPermissions(...)
    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String permissions[],
                                           @NonNull int[] grantResults) {
        // Make sure it's our original READ_CONTACTS request
        if (requestCode == READ_CONTACTS_PERMISSIONS_REQUEST) {
            if (grantResults.length == 1 &&
                    grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(this, "Read Contacts permission granted", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this, "Read Contacts permission denied", Toast.LENGTH_SHORT).show();
            }
        } else {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }
}

【讨论】:

    【解决方案2】:

    确保将其添加到应用程序标记之外。在 Ubuntu 上使用 Eclipse 为 2.3.3 的目标平台进行开发时,我在日志文件中遇到了权限失败,这表明我在处理类似的事情时需要这条确切的行。直到我将 *uses-permission...READ_CONTACTS* 行移到应用程序标记之外,事情才起作用。

    【讨论】:

    • +1:我在 Windows 7 系统上也是如此(针对 api v10 到 v19)。我已经使用 GUI 添加了权限,并且在 标记中添加了该权限。我用 标签替换了它。
    【解决方案3】:

    你好 Steven,调试日志跟踪告诉你你需要 ... 需要 android.permission.READ_CONTACTS

    所以只需通过编辑 Manifest.xml 来尝试一些东西,比如添加另一个权限,看看它是否没有正确读取。

    并在没有**的情况下检查这一行

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

    【讨论】:

      【解决方案4】:

      使用 api 23,权限 &lt;uses-permission android:name="android.pemission.READ_CONTACTS"/&gt; 不起作用,将模拟器中的 api 级别更改为 api 22(lollipop) 或更低

      【讨论】:

      • 那么有什么选择呢?
      • 降级 api 不应该是一个解决方案!
      • 另一种方法是编写 API 23+ 的显式请求权限,如文档中所示,我还必须将我的 sdk 的 targetVersion 降级到 22 以防止做如此繁琐的工作
      • 虽然我使用的是 API 22,但我遇到了同样的问题。请问有什么解决方案吗??
      【解决方案5】:

      如果设备运行的是 Android 6.0 或更高版本,并且您的应用的目标 SDK 为 23 或更高版本:应用必须在清单中列出权限,并且必须在应用运行时请求它需要的每个危险权限。用户可以授予或拒绝每个权限,即使用户拒绝权限请求,应用程序也可以继续以有限的功能运行。

      示例:

       //thisActivity is the running 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.
                  }
              }
      

      http://developer.android.com/training/permissions/requesting.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-02
        相关资源
        最近更新 更多