【问题标题】:Android Nougat Run time permissionAndroid Nougat 运行时权限
【发布时间】:2017-03-20 08:56:39
【问题描述】:

我是 Android 新手,运行时权限有问题。 我的应用程序读取电话的所有联系人并在列表中提取。问题是读取我手机联系人的权限。就目前而言,当我第一次打开我的应用程序时,应用程序崩溃了,然后..请求读取联系人的权限。 当我再次打开它时,第二次我的应用程序有任何问题。 所以问题是在崩溃之前请求许可...... 我的 MainActivity 是:

public class MainActivity extends AppCompatActivity {
    public static final int REQUEST_CODE_ASK_PERMISSIONS = 123;
    ReadContacts values = new ReadContacts();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // Readcontacts val = new Readcontacts();
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Get ListView object from xml

/*
        int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.READ_CONTACTS);
        if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.READ_CONTACTS},
                    REQUEST_CODE_ASK_PERMISSIONS);   }*/
        final ListView listView = (ListView) findViewById(R.id.list);
        final int frth = listView.getHeight();
        ToggleButton toggle = (ToggleButton) findViewById(R.id.toggleButton9);
        toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    for (int i = 0; i < listView.getChildCount(); i++) {
                        double max = 2 * 90;
                        Resources r = getResources();
                        float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 72, r.getDisplayMetrics());
                        listView.getChildAt(i).setMinimumHeight((int) px);
                    }

                    // The toggle is enabled
                } else {
                    // The toggle is disabled
                    for (int i = 0; i < listView.getChildCount(); i++) {
                        listView.getChildAt(i).setMinimumHeight(frth);
                    }
                }
            }
        });
        String[] values = new String[1000000];
        int temp =0 ;
        final int PERMISSIONS_REQUEST_READ_CONTACTS = 100;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, PERMISSIONS_REQUEST_READ_CONTACTS);
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, 225);

            //After this point you wait for callback in onRequestPermissionsResult(int, String[], int[]) overriden method
        } else {

            Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
            while (phones.moveToNext()) {
                String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                values[temp] = name;
                temp += 1;

            }
            phones.close();}
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.row, R.id.text, values);
            listView.setAdapter(adapter);
            // Assign adapter to ListView
            listView.setAdapter(adapter);

            // ListView Item Click Listener
            listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

                @Override
                public void onItemClick(AdapterView<?> parent, View view,
                                        int position, long id) {

                    // ListView Clicked item index
                    int itemPosition = position;

                    // ListView Clicked item value
                    String itemValue = (String) listView.getItemAtPosition(position);

                    // Show Alert
                    Toast.makeText(getApplicationContext(),
                            itemValue, Toast.LENGTH_LONG)
                            .show();

                }

            });

        }


}

当然我已经用 add 改变了我的清单

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

有什么想法???

编辑: 我的新 MainACtivity,但我的问题仍然存在...有什么想法吗?

public class MainActivity extends AppCompatActivity {
    public static final int REQUEST_CODE_ASK_PERMISSIONS = 123;
    ReadContacts values = new ReadContacts();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // Readcontacts val = new Readcontacts();
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Get ListView object from xml
        // Here, thisActivity is the current activity
        int permissionCheck = ContextCompat.checkSelfPermission(this,
                Manifest.permission.READ_CONTACTS);
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.READ_CONTACTS)
                != PackageManager.PERMISSION_GRANTED) {

            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.READ_CONTACTS)) {

                // Show an explanation 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(this,
                        new String[]{Manifest.permission.READ_CONTACTS},
                        REQUEST_CODE_ASK_PERMISSIONS);

                // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
                // app-defined int constant. The callback method gets the
                // result of the request.
            }
        }

/*

        int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.READ_CONTACTS);
        if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.READ_CONTACTS},
                    REQUEST_CODE_ASK_PERMISSIONS);   }*/
        final ListView listView = (ListView) findViewById(R.id.list);
        final int frth = listView.getHeight();
        ToggleButton toggle = (ToggleButton) findViewById(R.id.toggleButton9);
        toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    for (int i = 0; i < listView.getChildCount(); i++) {
                        double max = 2 * 90;
                        Resources r = getResources();
                        float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 72, r.getDisplayMetrics());
                        listView.getChildAt(i).setMinimumHeight((int) px);
                    }

                    // The toggle is enabled
                } else {
                    // The toggle is disabled
                    for (int i = 0; i < listView.getChildCount(); i++) {
                        listView.getChildAt(i).setMinimumHeight(frth);
                    }
                }
            }
        });
        String[] values = new String[1000000];
        int temp =0 ;
        //final int PERMISSIONS_REQUEST_READ_CONTACTS = 100;
      //  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
        //    requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, PERMISSIONS_REQUEST_READ_CONTACTS);
          //  ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, 225);

            //After this point you wait for callback in onRequestPermissionsResult(int, String[], int[]) overriden method
        //} else {

            Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
            while (phones.moveToNext()) {
                String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                values[temp] = name;
                temp += 1;

            }
            phones.close();//}
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.row, R.id.text, values);
            listView.setAdapter(adapter);
            // Assign adapter to ListView
            listView.setAdapter(adapter);

            // ListView Item Click Listener
            listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

                @Override
                public void onItemClick(AdapterView<?> parent, View view,
                                        int position, long id) {

                    // ListView Clicked item index
                    int itemPosition = position;

                    // ListView Clicked item value
                    String itemValue = (String) listView.getItemAtPosition(position);

                    // Show Alert
                    Toast.makeText(getApplicationContext(),
                            itemValue, Toast.LENGTH_LONG)
                            .show();

                }

            });

        }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case REQUEST_CODE_ASK_PERMISSIONS: {
                // 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
        }
    }
}

错误是

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.serepasf.myapp4/com.example.serepasf.myapp4.MainActivity}: java.lang.SecurityException: Permission Denial: opening provider com.android.providers.contacts.ContactsProvider2 from ProcessRecord{c638436 27660:com.example.serepasf.myapp4/u0a756} (pid=27660, uid=10756) requires android.permission.READ_CONTACTS or android.permission.WRITE_CONTACTS

【问题讨论】:

  • 崩溃发生在哪一行?有什么例外?发布错误日志。
  • 发布崩溃日志。另外我没有看到回调方法onRequestPermissionsResult(int, String[], int[])的实现
  • 你的权限在哪里onRequestPermissionsResult
  • 我没有实现回调方法 onRequestPermissionsResult(int, String[], int[]) ,我必须在哪里以及具体添加什么?

标签: android permissions android-7.0-nougat


【解决方案1】:

从 Android 6.0(API 级别 23)开始,用户需要在应用运行时授予权限。

第 1 步 您需要通过实现此代码来检查是否在 MAnifest 中声明了权限:

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

第 2 步 您可以向用户解释您为什么请求这些权限。然后最后显示 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 explanation 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.
    }
}

第 3 步 现在将出现一个对话框,用户可以在其中授予应用程序权限。用户的响应被传递到以下方法:onRequestPermissionsResult() 在这里您可以处理用户拒绝权限的情况,并显示一个对话框,如果您不授予此权限,您可能无法执行该操作。使用下面的代码:

@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
    }
}

您也可以查看官方文档:https://developer.android.com/training/permissions/requesting.html

我尝试过的示例代码:

package com.karan.permissions;

import android.Manifest;
import android.content.ContentResolver;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Build;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.support.v7.app.AppCompatActivity;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;


/**
 * @author karan
 * @date 20/3/17
 */

public class MainActivity extends AppCompatActivity {

    // Request code for READ_CONTACTS. It can be any number > 0.
    private static final int PERMISSIONS_REQUEST_READ_CONTACTS = 100;
    // The ListView
    private ListView name_list;

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

        // Find the list view
        this.name_list = (ListView) findViewById(R.id.name_list);

        // Read and show the contacts
        showContacts();
    }

    /**
     * Show the contacts in the ListView.
     */
    private void showContacts() {
        // Check the SDK version and whether the permission is already granted or not.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, PERMISSIONS_REQUEST_READ_CONTACTS);
            //After this point you wait for callback in onRequestPermissionsResult(int, String[], int[]) overriden method
        } else {
            // Android version is lesser than 6.0 or the permission is already granted.
            List<String> contacts = getContactNames();
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, contacts);
            name_list.setAdapter(adapter);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions,
                                           int[] grantResults) {
        if (requestCode == PERMISSIONS_REQUEST_READ_CONTACTS) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permission is granted
                showContacts();
            } else {
                Toast.makeText(this, "Until you grant the permission, we canot display the names", Toast.LENGTH_SHORT).show();
            }
        }
    }

    /**
     * Read the name of all the contacts.
     *
     * @return a list of names.
     */
    private List<String> getContactNames() {
        List<String> contacts = new ArrayList<>();
        // Get the ContentResolver
        ContentResolver cr = getContentResolver();
        // Get the Cursor of all the contacts
        Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);

        // Move the cursor to first. Also check whether the cursor is empty or not.
        if (cursor.moveToFirst()) {
            // Iterate through the cursor
            do {
                // Get the contacts name
                String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
                contacts.add(name);
            } while (cursor.moveToNext());
        }
        // Close the curosor
        cursor.close();

        return contacts;
    }
}

【讨论】:

  • 谢谢,所有这些我都会在我的 MainActivity 开始添加?
  • @FilipposSer 是的,您可以这样做。如果解决方案适合您,请接受答案。
  • 正如我所说,我重读了我的 mainactivity,如您在上面看到的结果相同...知道吗?
  • @FilipposSer 新代码有什么问题?你得到权限对话框了吗?如果授予权限,您是否以覆盖的方法收到有关状态的响应。
  • 错误是java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.serepasf.myapp4/com.example.serepasf.myapp4.MainActivity}: java.lang.SecurityException: Permission Denial: opening provider com.android.providers.contacts.ContactsProvider2 from ProcessRecord{c638436 27660:com.example.serepasf.myapp4/u0a756} (pid=27660, uid=10756) requires android.permission.READ_CONTACTS or android.permission.WRITE_CONTACTS
猜你喜欢
  • 1970-01-01
  • 2021-10-05
  • 2016-03-25
  • 2017-10-17
  • 1970-01-01
  • 1970-01-01
  • 2022-08-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多