Исключение происходит для некоторых пользователей с помощью электронной почты

Я пытаюсь разрешить моим пользователям выбирать контакт из числа контактов, у которых есть адреса электронной почты. Это код, который выполняется при нажатии соответствующей кнопки:

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

Это работает отлично на моем собственном телефоне, но после выпуска моего приложения я вижу следующее исключение для некоторых из моих пользователей:

0       android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.PICK dat=content://com.android.contacts/data/emails }
1   at  android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1638)
2   at  android.app.Instrumentation.execStartActivity(Instrumentation.java:1510)
3   at  android.app.Activity.startActivityForResult(Activity.java:3244)
4   at  com.fitrocket.android.InviteMethodSelectionAct.onClick(InviteMethodSelectionAct.java:59)
5   at  android.view.View.performClick(View.java:3549)
6   at  android.view.View$PerformClick.run(View.java:14400)
7   at  android.os.Handler.handleCallback(Handler.java:605)
8   at  android.os.Handler.dispatchMessage(Handler.java:92)
9   at  android.os.Looper.loop(Looper.java:154)
10  at  android.app.ActivityThread.main(ActivityThread.java:4945)
11  at  java.lang.reflect.Method.invokeNative(Native Method)
12  at  java.lang.reflect.Method.invoke(Method.java:511)
13  at  com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
14  at  com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
15  at  dalvik.system.NativeStart.main(Native Method)

Я не смог воспроизвести это сам, поэтому мне интересно, может ли кто-нибудь сказать мне, в чем проблема?

Ответ 1

Не то решение, которое вы ищете, но то же самое, что и для меня, при использовании намерения ACTION_PICK для выбора приложения. Обычно то, что будет происходить, - это то, что эта деятельность займет много времени, чтобы начать без какой-либо (очевидной) причины, а иногда просто сбой с исключением "Без активности". То, что я закончил, - это создание моей собственной активности, в которой перечислены доступные приложения. В вашем случае вы, вероятно, можете сделать то же самое для контактов, используя курсор, чтобы запросить все контакты по электронной почте и показать диалог/действие, чтобы разрешить выбор пользователя. Звучит как ужасное обходное решение, но может быть самым быстрым в реализации... (см. Пример кода здесь)

Еще один способ: связаться с этими пользователями и посмотреть, есть ли у них пользовательское приложение для контактов, которое может не поддерживать тип содержимого ContactsContract.CommonDataKinds.Email.CONTENT_URI.

Ответ 2

Проблема, насколько я вижу, заключается в том, что вы предполагаете, что каждый пользователь имеет установленное приложение, которое может реагировать на комбинацию действий и данных, которую вы хотите выполнить. Хотя предположение, вероятно, будет справедливым в вашем случае, некоторые пользователи, возможно, решили использовать свою систему и могли установить приложение для управления своими контактами, которые не могут реагировать на действие, которое вы запускаете. Независимо от причины, вы всегда должны проверять наличие приложения для ответа на ваш Intent.

public static boolean isIntentAvailable(Context context, String action)
{
    final PackageManager packageManager = context.getPackageManager();
    final Intent intent = new Intent(action);
    List<ResolveInfo> list =
            packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
    return list.size() > 0;
}

Этот код вернет true, если доступно хотя бы одно приложение, которое вы указали как параметр action. См. Intents и Intent Filters для официальной документации по проблеме, описанной выше.

Теперь все хорошо и прекрасно, но что он решит? Во-первых, ваше приложение не будет аварийно завершено. Затем вам нужно оправиться от того факта, что вы не можете действовать так, как вы считали. Обычно, отображая сообщение пользователю и предлагая установить приложение, которое, как вам известно, обеспечивает функциональность, работает довольно хорошо. Кроме того, я хотел бы отметить эту зависимость в вашей документации, чтобы всем пользователям было ясно, что им нужно.

Обновить. Дополнительные источники для просмотра:

Я считаю, что последнее содержит точное объяснение того, почему ваше приложение выходит из строя. Я цитирую:

"Caution: If you invoke an intent and there is no app available on the device that can handle the intent, your app will crash."

В этом разделе также содержится дополнительная информация о том, как решить эту проблему.