首页 > 解决方案 > Android:选择正确的设置来准备 ActivityResultLauncher 以选择联系人

问题描述

经过 4 小时的尝试和阅读文档后,我无法解决在使用 ActivityResultLauncher 代替我的工作但已弃用的选择联系人和 contentResolver 以使用数据的解决方案时获取 Uri 数据的问题。

复制的代码至少使我能够使用启动的意图成功选择联系人,但应用 [...data.setData((Uri) uriData)...] 会导致 getContentResolver 出现 NULL 指针异常。

我尝试使用 ActivityResultContracts.GetContent() 将 ActivityResultLauncher 声明为 String 和 Uri,但是当我认为我接近时,我找不到正确的参数来启动 ContactContracts.... PickContact 因为它没有 MIME,但使用意图,我无法得到 Uri 结果。猜猜这就是为什么他们只在开发者网站上记录简单的解决方案,例如选择图像 MIME。

Public class InvoiceFragment extends Fragment implements InvoiceListAdapter.OnInvoiceItemListener{
private InvoiceListAdapter iAdapter;
private SubTotalListAdapter sAdapter;
private Locale locale = new Locale("en", "UK");
private NumberFormat currencyFormatter = NumberFormat.getCurrencyInstance(locale);
Float invoiceTotal;
RecyclerView.LayoutManager invLayoutManager;
DatabaseHelper myDb;
final Uri uriData = null;
//ArrayList<InvoiceItem> invoiceItemList = new ArrayList<>();
ActivityResultLauncher<Intent> mStartForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
        new ActivityResultCallback<ActivityResult>() {


            @Override
            public void onActivityResult(ActivityResult result) {
                Intent data = result.getData();
                data.setData((Uri) uriData);

                Cursor c =  getContext().getContentResolver().query(uriData, null, null, null, null);
                if(c.moveToFirst()){
                    String name = c.getString(c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
                    Log.d(TAG, "onActivityResult: " + name);
                    c.close();

                }
            }




        });

然后启动它!

       view.findViewById(R.id.btGetContact).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (checkPermissions(getActivity(), READ_CONTACTS)) {
                Intent contactsIntent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
                //contactsIntent.setData((Uri) uriData);

                mStartForResult.launch(contactsIntent);
            }


        }
    });

结果是

    java.lang.RuntimeException: Unable to resume activity {wytonmcs.com.accounts/wytonmcs.com.accounts.InvoiceActivity}: java.lang.NullPointerException: uri
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3581)
    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3621)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1638)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6494)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
 Caused by: java.lang.NullPointerException: uri
    at com.android.internal.util.Preconditions.checkNotNull(Preconditions.java:128)
    at android.content.ContentResolver.query(ContentResolver.java:737)
    at android.content.ContentResolver.query(ContentResolver.java:704)
    at android.content.ContentResolver.query(ContentResolver.java:662)
    at wytonmcs.com.accounts.InvoiceFragment$1.onActivityResult(InvoiceFragment.java:70)
    at wytonmcs.com.accounts.InvoiceFragment$1.onActivityResult(InvoiceFragment.java:62)
    at androidx.activity.result.ActivityResultRegistry$1.onStateChanged(ActivityResultRegistry.java:145)
    at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:354)
    at androidx.lifecycle.LifecycleRegistry.forwardPass(LifecycleRegistry.java:265)
    at androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.java:307)
    at androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.java:148)
    at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.java:134)
    at androidx.fragment.app.Fragment.performStart(Fragment.java:3013)
    at androidx.fragment.app.FragmentStateManager.start(FragmentStateManager.java:586)
    at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:300)
    at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:112)
    at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1636)
    at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3112)
    at androidx.fragment.app.FragmentManager.dispatchStart(FragmentManager.java:3063)
    at androidx.fragment.app.FragmentController.dispatchStart(FragmentController.java:262)
    at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:482)
    at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:178)
    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1334)
    at android.app.Activity.performStart(Activity.java:7029)
    at android.app.Activity.performRestart(Activity.java:7104)
    at android.app.Activity.performResume(Activity.java:7109)
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3556)
    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3621) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1638) 
    at android.os.Handler.dispatchMessage(Handler.java:106) 
    at android.os.Looper.loop(Looper.java:164) 
    at android.app.ActivityThread.main(ActivityThread.java:6494)

标签: javaandroiduri

解决方案


在您的 OnClick 调用中,使用 null 启动, mStartForResult.launch(null);

你可以使用ActivityResultContracts.PickContact()

ActivityResultLauncher<String> mStartForResult = registerForActivityResult(new ActivityResultContracts.PickContact(),
    new ActivityResultCallback<Uri>() {
        @Override
        public void onActivityResult(Uri uri) {
            Cursor c =  getContext().getContentResolver().query(uri, null, null, null, null);
                if(c.moveToFirst()){
                    String name = c.getString(c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
                    Log.d(TAG, "onActivityResult: " + name);
                    c.close();
                }
        }
});

youtube 视频中有一些示例,名为:ActivityResultContracts Android


推荐阅读