Android 6.0 (Marshmallow) 拒绝权限并且不向用户显示权限请求对话框

Android 6.0 (Marshmallow) Denying permissions and no Permission Request Dialog is shown to user

阅读 Android 文档后,我决定尝试一下 "read sms messages from my device."

但是,在 Manifest 中设置权限后,在代码隐藏 (java) 中编写代码请求权限,并在 RequestPermission() 上设置断点后,我发现我的应用程序崩溃了,因为"Permission denied."

当我声明了文档告诉我声明的所有内容时,为什么我的权限被拒绝 并且 也实现了你得到 OS 来询问的东西用户授予或拒绝权限(这甚至没有发生 - 它没有向我显示授予或拒绝权限的对话框 - 我的应用程序甚至在它出现之前就崩溃了!)

我怎样才能弄清楚发生了什么?我如何向用户请求[具体] READ_SMS 权限?

请注意,在 的时间里,我一直在用头撞桌子,所以这里的代码是我拥有的最新代码,但是大约有20(完成)重写。因此,如果缺少某些内容,它可能已经存在但因为不起作用而被删除,或者被删除以进行故障排除以查看哪些有效哪些无效。

清单:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.me.app">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.READ_SMS" />
        <uses-permission android:name="android.permission.RECEIVE_SMS" />
        <uses-feature
            android:name="android.hardware.telephony"
            android:required="true">
        </uses-feature>
        <grant-uri-permission android:path="content://sms/"
            android:pathPattern=".*"
            android:pathPrefix="\"/>
        <activity
            android:name=".Main"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Main.java (onCreate(...)):

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Testing Snackbar", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.setDrawerListener(toggle);
    toggle.syncState();

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);

    RequestPermission(this);
}

Main.java(权限方式):

private static final int MY_PERMISSIONS_REQUEST_READ_SMS = 226;

protected void RequestPermission(Activity activity)
{
    if(ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED)
    {
        if(ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.READ_SMS)) {
            return;
        }
        else
        {
            ActivityCompat.requestPermissions(activity, new String[] { Manifest.permission.READ_SMS
            }, MY_PERMISSIONS_REQUEST_READ_SMS);
        }
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
{
    switch(requestCode)
    {
        case MY_PERMISSIONS_REQUEST_READ_SMS:
        {
            if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
            {
                MessageAdapter messageAdapter = new MessageAdapter(GetMessages());
                RecyclerView recList = (RecyclerView) findViewById(R.id.messagesList);
                recList.setAdapter(messageAdapter);

                // CardView List
                LinearLayoutManager llm = new LinearLayoutManager(this.getApplicationContext());
                llm.setOrientation(LinearLayoutManager.VERTICAL);
                recList.setLayoutManager(llm);
            }
            else
            {
                return;
            }

            return;
        }
    }
}

您应该修复的一个地方是:

if(ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.READ_SMS)) {
            return;
        }

这里你只是返回,而你实际上应该显示 rationalle 为什么你需要此权限然后请求它。通常的方法是使用 Snackbar 或对话框,或者直接调用 ActivityCompat.requestPermissions( - 至少出于测试目的。

[编辑]

  Snackbar.make(activity, R.string.rationaleStringId, Snackbar.LENGTH_INDEFINITE)
          .setAction(android.R.string.ok, new View.OnClickListener() {
            @Override
            @TargetApi(Build.VERSION_CODES.M)
            public void onClick(View v) {
                 ActivityCompat.requestPermissions(activity, new String[] {Manifest.permission.READ_SMS}, MY_PERMISSIONS_REQUEST_READ_SMS);
            }
          }).show();

您的 <uses-permission> 元素位于错误的位置,<uses-feature> 元素也是如此。这些在 <application> 元素之外,作为根 <manifest> 元素的直接子元素。

另外,删除 <grant-uri-permission> 元素。它不仅不在正确的位置,而且您 没有 正确的位置,因为它只能作为 <provider> 元素的子元素。