Android API 30+添加/编辑联系人所需XML queries配置问题
问题描述
我用Kotlin编写了向Android联系人列表添加联系人的代码,但intent.resolveActivity(getPackageManager)返回null。了解到Android API 30及以上版本需要在AndroidManifest.xml中添加<queries>语句,但不清楚添加/编辑联系人时该配置什么内容。我不想使用QUERY_ALL_PACKAGES权限,因为提交到Google Play时会触发权限审核。以下是我的Manifest和Activity代码,请求指导正确的queries配置。
我的Android Manifest
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <uses-sdk tools:overrideLibrary=" androidx.camera.camera2, androidx.camera.core, androidx.camera.view, androidx.camera.lifecycle" /> <uses-feature android:name="android.hardware.camera" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_CONTACTS" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <queries> <!-- Browser --> <intent> <action android:name="android.intent.action.VIEW" /> <data android:scheme="http" /> </intent> <!-- Camera --> <intent> <action android:name="android.media.action.IMAGE_CAPTURE" /> </intent> <!-- Gallery --> <intent> <action android:name="android.intent.action.GET_CONTENT" /> </intent> </queries> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".AddToContacts" android:exported="true"> <meta-data android:name="android.app.lib_name" android:value="" /> </activity> <activity android:name=".MainActivity" android:exported="true"> <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" /> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
我的Activity代码
import android.content.Intent import android.content.pm.PackageManager import android.graphics.Bitmap import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.provider.ContactsContract import android.view.View import android.widget.Button import android.widget.TextView import android.widget.Toast import androidx.camera.core.impl.utils.ContextUtil.getApplicationContext import androidx.core.content.ContextCompat.startActivity class AddToContacts : AppCompatActivity() { private lateinit var textViewName: TextView private lateinit var textViewPhoneNumber: TextView private lateinit var textViewEmailAddress: TextView private lateinit var textViewEmailAddress2: TextView private lateinit var buttonSaveToContacts: Button private lateinit var strQRCodeResult: String override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_add_to_contacts) textViewName = findViewById(R.id.textViewName) textViewPhoneNumber = findViewById(R.id.textViewPhoneNumber) textViewEmailAddress = findViewById(R.id.textViewEmailAddress) textViewEmailAddress2 = findViewById(R.id.textViewEmailAddress2) buttonSaveToContacts = findViewById(R.id.SaveToContacts) strQRCodeResult= intent.getStringExtra("mystring").toString() buttonSaveToContacts.setOnClickListener(object: View.OnClickListener { override fun onClick(v: View) { if (textViewName.text.toString().isNotEmpty()&&textViewPhoneNumber.text.toString().isNotEmpty()&& textViewEmailAddress.text.toString().isNotEmpty()&& textViewEmailAddress2.text.toString().isNotEmpty()){ val intent = Intent(Intent.ACTION_INSERT) intent.setType(ContactsContract.RawContacts.CONTENT_TYPE) intent.putExtra(ContactsContract.Intents.Insert.NAME,textViewName.text.toString()) intent.putExtra(ContactsContract.Intents.Insert.PHONE,textViewPhoneNumber.text.toString()) intent.putExtra(ContactsContract.Intents.Insert.EMAIL,textViewEmailAddress.text.toString()) if (intent.resolveActivity(getPackageManager())!=null) { startActivity(intent) } else { Toast.makeText(getApplicationContext(),"there is no app to support this action", Toast.LENGTH_SHORT).show() } } else { Toast.makeText(getApplicationContext(),"please fill in all fields",Toast.LENGTH_SHORT).show() } } }) ParseData(strQRCodeResult) } private fun ParseData(strQRCodeResult: String) { textViewName.text="yyy xxx" textViewPhoneNumber.text="2125551212" textViewEmailAddress.text="bob@hotmail.com" textViewEmailAddress2.text="bob@hotmail.com" } }
解决方案
你需要在<queries>标签中添加匹配联系人插入Intent的规则,让系统允许你的应用查询到处理ACTION_INSERT且类型为ContactsContract.RawContacts.CONTENT_TYPE的应用。
修改后的<queries>部分如下:
<queries> <!-- Browser --> <intent> <action android:name="android.intent.action.VIEW" /> <data android:scheme="http" /> </intent> <!-- Camera --> <intent> <action android:name="android.media.action.IMAGE_CAPTURE" /> </intent> <!-- Gallery --> <intent> <action android:name="android.intent.action.GET_CONTENT" /> </intent> <!-- 新增:匹配联系人插入Intent --> <intent> <action android:name="android.intent.action.INSERT" /> <data android:mimeType="vnd.android.cursor.dir/raw_contact" /> </intent> </queries>
说明
ContactsContract.RawContacts.CONTENT_TYPE对应的MIME类型就是vnd.android.cursor.dir/raw_contact,直接在<data>标签中指定这个MIME类型,就能精准匹配处理联系人插入的系统或第三方应用。- 这个配置不需要
QUERY_ALL_PACKAGES权限,完全符合Google Play的政策要求,不会触发额外审核。
验证
修改Manifest后,重新编译运行应用,点击保存联系人按钮时,intent.resolveActivity(getPackageManager())就能正确返回处理该Intent的应用组件,不会再返回null,联系人添加流程可以正常触发。
内容的提问来源于stack exchange,提问作者user6090578
相关产品推荐
相关产品推荐

