Marshmallow 中对联系人列表的访问是否发生了变化?

Does access to Contact List has changed in Marshmallow?

希望这不是一个愚蠢的问题,但我的应用程序一直运行到两天前,但在那之后我得到了 OTA 更新以将其升级到 Marshmallow。然后在那之后,不仅我无法获得我的联系人列表,甚至用于显示联系人列表的默认设备应用程序也不显示任何联系人。我从 Play 商店下载了几个联系人管理应用程序,即使它们不显示任何内容。我什至不能 send/recieve 短信 :) 我想知道 wtf 正在发生。

好的,让我删掉 b.s 并分享我所做的。 我根据 Marshmallow 需要的新动态权限请求更改了代码。我启动应用程序并授予对联系人的访问权限,但没有任何显示:(

这是我的代码,抱歉我知道很长但很简单:

public class MainActivity extends AppCompatActivity
{
    private static final String TAG = MainActivity.class.getSimpleName();
    private static final int MY_PERMISSIONS_REQUEST_READ_CONTACTS = 10;

    private SwipeRefreshLayout mRefreshLayout;
    private RecyclerView mRecyclerView;
    private ContactsAdapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        Log.d(TAG, "********************************");
        Log.d(TAG, "*** Contacts Remover Started ***");
        Log.d(TAG, "********************************");

        setContentView(R.layout.activity_main);

        mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        mRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.refreshScreen);
        mRefreshLayout.setOnRefreshListener(this::refreshLayout);
        mRefreshLayout.setColorSchemeResources(android.R.color.holo_blue_bright,
                android.R.color.holo_green_light,
                android.R.color.holo_orange_light,
                android.R.color.holo_red_light);

        // use this setting to improve performance if you know that changes
        // in content do not change the layout size of the RecyclerView
        mRecyclerView.setHasFixedSize(true);

        // use a linear layout manager
        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mLayoutManager);

        // create adapter
        mAdapter = new ContactsAdapter();
        mRecyclerView.setAdapter(mAdapter);

        // Check required permissions
        checkContactPermission();
    }

    private void checkContactPermission()
    {
        Log.d(TAG, "Yu");
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED ||
            ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_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,
                        Manifest.permission.WRITE_CONTACTS}, MY_PERMISSIONS_REQUEST_READ_CONTACTS);
            }
        }
        else
        {
            Log.d(TAG, "Perms granted");
            // Get Contacts and display it
            refreshLayout();
        }
    }

    @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)
                {
                    // Get Contacts and display it
                    refreshLayout();
                }
                else
                {
                    this.finish();
                }
                return;
            }

            // other 'case' lines to check for other
            // permissions this app might request
        }
    }

    private List<Contact> getContactList()
    {
        Log.d(TAG, "2");
        List<Contact> contactList = new ArrayList<>(100);

        ContentResolver cr = getContentResolver();
        Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
        Log.d(TAG, "3");
        if (cur != null && cur.getCount() > 0)
        {
            int i = 0;
            Log.d(TAG, "4");
            while (cur.moveToNext())
            {
                i++;
                Log.d(TAG, "-> " + i);

                Contact contact = new Contact();
                contact.setId(cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID)));
                contact.setName(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)));
                contact.setImageAddress(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.PHOTO_THUMBNAIL_URI)));

                contactList.add(contact);
            }

            cur.close();
            Log.d(TAG, "5");
        }

        Log.d(TAG, String.format("Number of %s contacts found", contactList.size()));
        return contactList;
    }

    private Observable<Contact> getApps()
    {
        Log.d(TAG, "1");
        return Observable.create(subscriber -> {
            List<Contact> contactList = getContactList();
            Log.d(TAG, "6");

            if (subscriber.isUnsubscribed())
            {
                return;
            }

            Log.d(TAG, "7");

            for (Contact contact : contactList)
            {
                subscriber.onNext(contact);
            }

            Log.d(TAG, "8");

            if (!subscriber.isUnsubscribed())
            {
                subscriber.onCompleted();
            }

            Log.d(TAG, "9");
        });
    }

    private void refreshLayout()
    {
        Log.d(TAG, "0");
        if (mRefreshLayout.isRefreshing())
        {
            return;
        }

        mRefreshLayout.setRefreshing(true);

        getApps().toSortedList()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<List<Contact>>()
                {
                    @Override
                    public void onCompleted()
                    {
                        Log.d(TAG, "10");
                        Toast.makeText(MainActivity.this, "List updated!", Toast.LENGTH_LONG).show();
                        mRefreshLayout.setRefreshing(false);
                    }

                    @Override
                    public void onError(Throwable e)
                    {
                        Log.d(TAG, "ERROR!!!");
                        Toast.makeText(MainActivity.this, "Shit! Something went wrong :(", Toast.LENGTH_LONG).show();
                        mRefreshLayout.setRefreshing(false);
                    }

                    @Override
                    public void onNext(List<Contact> contactList)
                    {
                        Log.d(TAG, "*");
                        mAdapter.setContactList(contactList);
                        mAdapter.notifyDataSetChanged();
                    }
                });
    }
}

最后我的日志是:

10-15 01:05:46.239 1514-1514/? D/MainActivity: ********************************
10-15 01:05:46.239 1514-1514/? D/MainActivity: *** Contacts Remover Started ***
10-15 01:05:46.239 1514-1514/? D/MainActivity: ********************************
10-15 01:05:46.285 1514-1514/? D/MainActivity: Yu
10-15 01:05:46.287 1514-1514/? D/MainActivity: Perms granted
10-15 01:05:46.287 1514-1514/? D/MainActivity: 0
10-15 01:05:46.288 1514-1514/? D/MainActivity: 1
10-15 01:05:46.306 1514-14799/? D/MainActivity: 2

这一行发生了一些事情,Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);。没有错误,没有崩溃,没有报告!什么都没有:(

当 phone 上的默认联系人应用程序也没有显示任何联系人时,您似乎在浪费时间调整代码。

看起来好像 OTA 更新已经完成了某种部分出厂重置,或者可能只是删除了之前提供您的设备联系人的帐户。先解决这个问题,所以默认的应用会显示一些联系人,我怀疑你的应用也会开始显示联系人。