【问题标题】:Pick contact directly from contact picker intent直接从联系人选择器意图中选择联系人
【发布时间】:2017-05-10 16:37:09
【问题描述】:

您好,我想从我们的默认通讯录意图中选择一个联系人。 我尝试了几种方法来做到这一点。请在下面找到代码。所有这些代码的问题在于,它们打开一个中间文档屏幕,其中用户必须选择联系人的选项很少,然后它会打开通讯录。

private void openContactIntent() {
     Intent intent = new Intent(Intent.ACTION_GET_CONTENT, ContactsContract.Contacts.CONTENT_URI);
     intent.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
     startActivityForResult(intent, REQ_CONTACT_DIRECTORY);
}

我也试过了

Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
startActivityForResult(intent, PICK_CONTACT);

Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType(ContactsContract.Contacts.CONTENT_TYPE);
startActivityForResult(intent, PICK_CONTACT); 

我看到的中间屏幕是

【问题讨论】:

  • Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI); startActivityForResult(intent, PICK_CONTACT); 它对我有用!
  • 它与任何操作系统有关吗?我在 Android N 上运行代码。对我来说它不起作用。我没有添加任何权限。
  • 我也在运行 Android N!
  • 还有权限?

标签: android android-intent android-contacts android-implicit-intent contactpicker


【解决方案1】:

StarActivityForResult 已弃用。所以我们可以在 Kotlin 中使用下面的模型。

在清单中:

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

请同时实现运行时权限。我的代码中还没有完成。

用于处理结果的以下行:

    private val openContacts = registerForActivityResult(ActivityResultContracts.PickContact()) {

    val contactData: Uri = it
    val phone: Cursor? = contentResolver.query(contactData!!, null, null, null, null)
    if (phone!!.moveToFirst()) {
        val contactName: String = phone.getString(phone.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME))

        // To get number - runtime permission is mandatory.
        val id: String = phone.getString(phone.getColumnIndex(ContactsContract.Contacts._ID))
        if (phone.getString(phone.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)).toInt() > 0) {
            val phones = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + id, null, null)
            while (phones!!.moveToNext()) {
                val phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))
                Log.d("## Number", phoneNumber)
            }
            phones!!.close()
        }

        Log.d("## Contact Name", contactName)
    }

}

打开联系人:

button.setOnClickListener {
        openContacts.launch(null)
    }

【讨论】:

    【解决方案2】:

    对于 Android 11+,需要在 AndroidManifest 中添加以下代码

    ......
    </application>
        <queries>
            <intent>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="vnd.android.cursor.dir/contact" />
            </intent>
        </queries>
    </manifest>
    

    【讨论】:

      【解决方案3】:

      这是一个很好的实现(在 Kotlin 中),我将在此处添加它以帮助从光标获取联系信息。 您还需要授予权限并请求运行时权限

      &lt;uses-permission android:name="android.permission.READ_CONTACTS" /&gt;

          @SuppressLint("Recycle")
          private fun getContactDataFrom(
              contentResolver: ContentResolver,
              contactUri: Uri
          ): ContactModel? {
              val projection = arrayOf(
                  ContactsContract.Contacts._ID,
                  ContactsContract.Contacts.DISPLAY_NAME,
                  ContactsContract.Contacts.HAS_PHONE_NUMBER
              )
      
              try {
                  val cursor = contentResolver.query(contactUri, projection, null, null, null) ?: return null
                  if (!cursor.moveToFirst()) {
                      return null
                  }
      
                  val id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID))
                  val name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME))
                  val hasNumber = (cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)))
                  cursor.close()
      
                  val email = getEmail(contentResolver, id)
      
                  val phoneNumber = if (hasNumber > 0) {
                      getPhoneNumber(contentResolver, id)
                  } else {
                      ""
                  }
                  return ContactModel(name, phoneNumber, email)
              } catch (e: Exception) {
                  Log.e("Contacts", "Could not get contact info.", e)
                  return null
              }
          }
      
          @SuppressLint("Recycle")
          private fun getPhoneNumber(contentResolver: ContentResolver, id: String?): String {
              var phoneNumber = ""
      
              val cursor = contentResolver.query(
                  ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                  null,
                  ContactsContract.Contacts._ID + " = ?",
                  arrayOf(id),
                  null
              ) ?: return phoneNumber
      
              if (cursor.moveToFirst()) {
                  phoneNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DATA))
              }
      
              cursor.close()
              return phoneNumber
          }
      
          @SuppressLint("Recycle")
          private fun getEmail(contentResolver: ContentResolver, id: String?): String {
              var email = ""
      
              val cursor = contentResolver.query(
                  ContactsContract.CommonDataKinds.Email.CONTENT_URI,
                  null,
                  ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?",
                  arrayOf(id),
                  null
              ) ?: return email
      
              if (cursor.moveToFirst()) {
                  email = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA))
              }
      
              cursor.close()
              return email
          }
      

      触发器:

          val intent = Intent(this, PickLabelActivity::class.java)               
          startActivityForResult(intent, PickLabelActivity.REQ_CODE_PICK_LABEL)
      

      onActivityResult 中的用法应该是这样的:

      override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
              super.onActivityResult(requestCode, resultCode, data)
      
               if (resultCode == RESULT_OK && requestCode == ConstantsHandler.INTENT_CODE_PICK_CONTACT) {
                  val contactUri = data?.data ?: return
                  val contactModel = getContactDataFrom(contentResolver, contactUri)
      
                  inputName.setText(contactModel?.name)
                  inputPhone.setText(contactModel?.phone)
                  inputEmail.setText(contactModel?.email)
              }
          }
      

      而那个 ContactModel 只是一个简单的数据类。

      data class ContactModel(
          var name: String? = null,
          var phone: String? = null,
          var email: String? = null
      ) : Serializable
      

      【讨论】:

        【解决方案4】:

        试试下面的代码来选择联系人:

        Intent contactPickerIntent = new Intent(Intent.ACTION_PICK,
                            ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
                    startActivityForResult(contactPickerIntent, RESULT_PICK_CONTACT);
        

        您可以在onActivityResult中获取所需的信息,如下所示:

        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            if (resultCode == RESULT_OK) {
                switch (requestCode) {
                    case RESULT_PICK_CONTACT:
                          Cursor cursor = null;
            try {
                String phoneNo = null;
                String name = null;
        
                Uri uri = data.getData();
                cursor = getContentResolver().query(uri, null, null, null, null);
                cursor.moveToFirst();
                int  phoneIndex =cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
                int  nameIndex =cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
                phoneNo = cursor.getString(phoneIndex);
                name = cursor.getString(nameIndex);
        
               Log.e("Name and Contact number is",name+","+phoneNo);
        
            } catch (Exception e) {
                e.printStackTrace();
            }
                        break;
                }
            } else {
                Log.e("Failed", "Not able to pick contact");
            }
        }
        

        【讨论】:

        • 哦..!!太棒了..!!
        • 这实际上还是在某些设备上打开了文件管理器,最好也加上intent.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE);
        • RESULT_PICK_CONTACT 是什么。是字符串还是其他变量?
        【解决方案5】:

        这是一种从 Kotlin 中的联系人中选择姓名、电话号码的方法

        private fun pickEmergencyFromContacts() {
            val i = Intent(Intent.ACTION_PICK)
            i.type = ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE
            startActivityForResult(i, SELECT_PHONE_NUMBER)
        }
        
        override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
            super.onActivityResult(requestCode, resultCode, data)
            if (requestCode == SELECT_PHONE_NUMBER && resultCode == Activity.RESULT_OK) {
                val contactUri = data?.data ?: return
                val projection = arrayOf(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
                        ContactsContract.CommonDataKinds.Phone.NUMBER)
                val cursor = requireContext().contentResolver.query(contactUri, projection,
                        null, null, null)
        
                if (cursor != null && cursor.moveToFirst()) {
                    val nameIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)
                    val numberIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)
                    val name = cursor.getString(nameIndex)
                    val number = cursor.getString(numberIndex)
        
                    // do something with name and phone
                }
                cursor?.close()
            }
        }
        
        companion object {
        
            private const val SELECT_PHONE_NUMBER = 111    
            ...
        }
        

        希望对你有帮助

        【讨论】:

        • 这只会给1个联系人,有没有办法一次选择多个联系人?
        【解决方案6】:
         private static final int RESULT_PICK_CONTACT1= 1;
         public void pickContact1 (View v)
              {
                Intent contactPickerIntent = new Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
                startActivityForResult(contactPickerIntent, RESULT_PICK_CONTACT1);
              }
         @Override
            protected void onActivityResult ( int requestCode, int resultCode, Intent data){
                if (resultCode == RESULT_OK) {
                    switch (requestCode) {
                        case RESULT_PICK_CONTACT1:
                            contactPicked1(data);
                            break;
                    }
                } else {
                    Log.e("SetupActivity", "Failed to pick contact");
                }
            }
        
         private void contactPicked1 (Intent data){
                Cursor cursor = null;
                try {
                    String phoneNo = null;
                    String name = null;
                    Uri uri = data.getData();
                    cursor = getContentResolver().query(uri, null, null, null, null);
                    cursor.moveToFirst();
                    int phoneIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
                    int nameIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
                    name = cursor.getString(nameIndex);
                    phoneNo = cursor.getString(phoneIndex);
                    ed11.setText(name);
                    ed12.setText(phoneNo);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        

        这肯定行得通。

        【讨论】:

          【解决方案7】:

          我也遇到了同样的问题。最后,我使用下面的代码摆脱了中间选择器屏幕,

          Intent i=new Intent(Intent.ACTION_PICK);
          i.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE);
          startActivityForResult(i, SELECT_PHONE_NUMBER);
          

          onActivityResult获取电话号码如下

          if (requestCode == SELECT_PHONE_NUMBER && resultCode == RESULT_OK) {
            // Get the URI and query the content provider for the phone number
            Uri contactUri = data.getData();
            String[] projection = new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER};
            Cursor cursor = getContext().getContentResolver().query(contactUri, projection,
                null, null, null);
          
            // If the cursor returned is valid, get the phone number
            if (cursor != null && cursor.moveToFirst()) {
              int numberIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
              String number = cursor.getString(numberIndex);
              // Do something with the phone number
              ... 
            } 
          
            cursor.close();
          }
          

          【讨论】:

          • 这对我来说效果很好,除了 getContext 需要替换为对活动的引用(this),否则我会遇到没有仪器注册的问题。
          • 运行良好,但由于某种原因结果代码是随机的,可能是 Android 11 问题
          • 对于 Android 11+,AndroidManifest 文件中的更改,如 stackoverflow.com/a/67600033/1889825
          【解决方案8】:

          这对我有用:

          Intent it= new Intent(Intent.ACTION_PICK, 
               ContactsContract.Contacts.CONTENT_URI); 
          startActivityForResult(it, requestCode);
          

          【讨论】:

            猜你喜欢
            • 2019-07-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-02-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多