Недопустимый идентификатор ресурса с startIntentSenderForResult с SDK 25.

Мое приложение для Android запускает интерфейс покупки в приложении из фрагмента, например:

Bundle responseBundle = this.billingService.getBuyIntent(3, getPackageName(), id, "inapp", StringUtils.randomString(32));
PendingIntent pendingIntent = responseBundle.getParcelable("BUY_INTENT");
fragment.getActivity().startIntentSenderForResult(pendingIntent.getIntentSender(), R.id.buyUpgradeResponse, new Intent(), Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0));

Это работало нормально, пока я не увеличил свой targetSdkVersion с 23 до 25, чтобы добавить некоторые функции Android 7. Теперь строка startIntentSenderForResult выдает это исключение:

java.lang.IllegalArgumentException: можно использовать только младшие 16 бит для requestCode

Это означает, что код запроса (второй аргумент этого метода) имеет ограничение в 65 535. Но R.id.buyUpgradeResponse, который генерируется случайным образом из файла ids.xml, имеет значение около 20 000 000. Есть ли способ ограничить диапазон, который Android использует для случайно сгенерированных идентификаторов ресурсов?

Другой ответ SO говорит, что эта ошибка возникает только при использовании android.support.v4.app.FragmentActivity. Все мои действия используют базовое действие, которое расширяет AppCompatActivity, которое расширяет android.support.v7.app.AppCompatActivity, которое расширяет android.support.v4.app.FragmentActivity. Таким образом, другим подходом было бы устранение моей зависимости от класса support.v4. Но я боюсь вносить глобальные изменения, которые могут иметь непредвиденные последствия в любой части моего приложения. (Мой minSdkVersion равен 15, если это имеет значение.)

Я также мог бы просто заменить R.id.buyUpgradeResponse жестко запрограммированным идентификатором, но я боюсь, что в приложении есть и другие места, в которых возникает та же проблема, и это не решит все случаи проблемы.

Обновить

Я только что подтвердил, что изменение моих настроек сборки вызвало проблему. Проблема не возникала с моими предыдущими настройками:

compileSdkVersion 23
buildToolsVersion '25.0.2'
minSdkVersion 15
targetSdkVersion 23
compile "com.android.support:appcompat-v7:23.0.0"

Проблема началась, когда я обновил эти настройки:

compileSdkVersion 25
buildToolsVersion '25.0.2'
minSdkVersion 15
targetSdkVersion 25
compile "com.android.support:appcompat-v7:25.3.1"

Обновление 2

Я снова столкнулся с этим при реализации Storage Access Framework. . startActivityForResult сгенерировал исключение недействительного идентификатора, поскольку случайно сгенерированный идентификатор составлял 20 миллионов с чем-то. Другие функции в моем приложении, такие как открытие фрагмента во всплывающем окне, используют эти идентификаторы без жалоб, но намерения SAF не будут. В итоге я жестко запрограммировал больше идентификаторов для намерений SAF. Я думаю, что лучшим решением было бы ограничить диапазон случайно сгенерированных идентификаторов диапазоном, который поддерживают все фреймворки, но я не вижу способа сделать это.


comment
Фрагменты/действия фреймворка имеют такое же требование к своему requestCode, поэтому отказ от использования библиотек поддержки вам не поможет. Почему вы использовали идентификаторы вместо нескольких определяемых вами констант?   -  person ianhanniballake    schedule 31.05.2017
comment
Почему вы использовали идентификаторы? У меня есть десятки предупреждений и всплывающих окон, которые принимают аргумент идентификатора, поэтому я просто добавлял элементы в файл ids.xml для всех из них.   -  person arlomedia    schedule 31.05.2017
comment
Похоже, что Fragment.startActivityForResult() и DialogFragment.setTargetFragment() по-прежнему отлично работают с автоматически сгенерированными идентификаторами, поэтому, возможно, мне просто нужно жестко закодировать идентификатор для Activity. startIntentSenderForResult(), который я сейчас использую только в одном месте.   -  person arlomedia    schedule 31.05.2017


Ответы (1)


Я обнаружил, что проблема не возникает, если я запускаю действие из фрагмента, а не из действия фрагмента. Итак, это вызывает проблему:

fragment.getActivity().startIntentSenderForResult(pendingIntent.getIntentSender(), R.id.buyUpgradeResponse, new Intent(), Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0));

Но это нормально:

fragment.startIntentSenderForResult(pendingIntent.getIntentSender(), R.id.buyUpgradeResponse, new Intent(), Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0));

Возможно, в этом есть логика, но я не знаю, какая.

person arlomedia    schedule 06.11.2018