Приложение иногда вылетает с ресурсом $ NotFoundException после переключения на дистрибутив Android-приложений. - PullRequest
0 голосов
/ 23 сентября 2018

Приложение имеет более 20000 активных пользователей в месяц.Он был доступен в Google Play в течение нескольких месяцев.После того, как я недавно переключился с дистрибутива с .apk на дистрибутив с .aab, я начал получать случайные сбои на crashlytics и магазине Google Play.Другие существенные изменения не были внесены в сборку, которая привела к сбоям.

Сбой происходит на самом первом экране приложения при надувании макета XML.Рассматриваемый макет xml представляет собой простой экран-заставку, который содержит только одно представление изображения и одно представление текста.Imageview - это android.widget.ImageView, а не версия для сравнения, и оно отображает PNG-изображение, а не векторное изображение.Изображение присутствует во всех доступных для рисования папках: drawable, drawable-mdpi, ..., drawable-xxxhdpi.

Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.company/com.company.ui.splash.SplashActivity}: android.view.InflateException: Binary XML file line #14: Binary XML file line #14: Error inflating class ImageView
          at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
          at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
          at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
          at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
          at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
          at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
          at android.os.Handler.dispatchMessage(Handler.java:106)
          at android.os.Looper.loop(Looper.java:193)
          at android.app.ActivityThread.main(ActivityThread.java:6669)
          at java.lang.reflect.Method.invoke(Method.java)
          at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:495)
          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

   Caused by android.view.InflateException: Binary XML file line #14: Binary XML file line #14: Error inflating class ImageView


   Caused by android.view.InflateException: Binary XML file line #14: Error inflating class ImageView


   Caused by android.content.res.Resources$NotFoundException: Drawable (missing name) with resource ID #0x7f0800b2


   Caused by android.content.res.Resources$NotFoundException: Unable to find resource ID #0x7f0800b2
          at android.content.res.ResourcesImpl.getResourceName(ResourcesImpl.java:255)
          at android.content.res.ResourcesImpl.loadDrawableForCookie(ResourcesImpl.java:785)
          at android.content.res.ResourcesImpl.loadDrawable(ResourcesImpl.java:631)
          at android.content.res.Resources.loadDrawable(Resources.java:897)
          at android.content.res.TypedArray.getDrawableForDensity(TypedArray.java:955)
          at android.content.res.TypedArray.getDrawable(TypedArray.java:930)
          at android.widget.ImageView.<init>(ImageView.java:189)
          at android.widget.ImageView.<init>(ImageView.java:172)
          at android.support.v7.widget.AppCompatImageView.<init>(AppCompatImageView.java:71)
          at android.support.v7.widget.AppCompatImageView.<init>(AppCompatImageView.java:67)
          at android.support.v7.app.AppCompatViewInflater.createImageView(AppCompatViewInflater.java:181)
          at android.support.v7.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:105)
          at android.support.v7.app.AppCompatDelegateImplV9.createView(AppCompatDelegateImplV9.java:1035)
          at android.support.v7.app.AppCompatDelegateImplV9.onCreateView(AppCompatDelegateImplV9.java:1092)
          at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:772)
          at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
          at android.view.LayoutInflater.rInflate(LayoutInflater.java:863)
          at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824)
          at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
          at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
          at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
          at android.support.v7.app.AppCompatDelegateImplV9.setContentView(AppCompatDelegateImplV9.java:287)
          at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:139)
          at com.company.ui.splash.SplashActivity.onCreate(SplashActivity.java:58)
          at android.app.Activity.performCreate(Activity.java:7136)
          at android.app.Activity.performCreate(Activity.java:7127)
          at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
          at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
          at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
          at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
          at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
          at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
          at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
          at android.os.Handler.dispatchMessage(Handler.java:106)
          at android.os.Looper.loop(Looper.java:193)
          at android.app.ActivityThread.main(ActivityThread.java:6669)
          at java.lang.reflect.Method.invoke(Method.java)
          at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:495)
          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Часть XML-файла, которая вызывает сбой:

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_above="@id/center"
    android:layout_centerHorizontal="true"
    android:src="@drawable/logo" />

Сбой происходит на всех версиях Android, от 4.1.2 до 9.0.

В сторонус других устройств я также получал сбои от Google Pixel и Nexus 5X, оба без рута.Мне довелось владеть обоими устройствами.Я пытался установить на них свое приложение из Google Play и из сервисов боковой загрузки, таких как pureapk, но я не смог воспроизвести сбой.

Вопрос похож на Пакет приложений Android представляет ресурсНе обнаружен сбой в приложении Android , но в этом вопросе автору удалось решить свои проблемы с помощью векторного рисованного компата.Это не мой случай.

Похоже, что вся папка ресурсов отсутствует в apk, хотя проверить это предположение сложно.Я не могу воспроизвести проблему, поэтому мне придется перераспределить приложение и подождать пару дней, чтобы увидеть, как изменился сбой, и я бы не стал проводить тестирование на живых пользователях.

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

Итак, подведем итог:
1. Сбой начал появляться сразу после переключения на распространение пакета приложений для Android наgoogle play
2. Приложение аварийно завершает свою работу при первой попытке восстановить нарисованный ресурс - простое изображение в формате png
3. Сбой не зависит от версии Android;это происходит как на рутованных, так и на некорневых устройствах
4. Если пользователь получает эту ошибку, он, вероятно, застрял навсегда

Что является причиной этого сбоя?Есть ли обходной путь?

==========

Обновление: После прочтения ответа ниже я пришел к выводу, что единственный обходной путь - этообнаружите установку с боковой загрузкой, а затем откройте активность без каких-либо доступных ресурсов или стилей со ссылками на Google Play и официальный сайт с файлом старой школы apk.Затем пользователь может повторно загрузить приложение из другого источника.

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

private fun isValidInstallation(): Boolean {
    var resourcesPresent: Boolean
    try {
        // Any drawable id will suffice
        val logo = ResourcesCompat.getDrawable(resources, R.drawable.logo_white, null)
        resourcesPresent = logo != null
    } catch (e: Exception) {
        resourcesPresent = false
    }

    if (!resourcesPresent) {
        Timber.e("No drawable resources detected inside app")
    }

    var nativeLibrariesPresent: Boolean
    try {
        val nativeLibraryDir = File(applicationInfo.nativeLibraryDir)
        val primaryNativeLibraries = nativeLibraryDir.list()
        nativeLibrariesPresent = primaryNativeLibraries.isNotEmpty()
    } catch (e: Exception) {
        nativeLibrariesPresent = false
    }

    if (!nativeLibrariesPresent) {
        Timber.e("No native libraries detected inside app")
    }

    return resourcesPresent && nativeLibrariesPresent
}

Вы захотите начать альтернативную деятельность, прежде чем делать что-либо внутри своей основной деятельности:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    if (!isValidInstallation()) {
        val intent = Intent(this, InvalidInstallationActivity::class.java)
        startActivity(intent)
        finish()
        return
    }

    setContentView(R.layout.activity_main)
    ...

InvalidInstallationActivity может использовать макет xml и может использовать строковые ресурсы, если вы не используетеНе делите ваш AAB по языку (language { enableSplit = false }), но он не может использовать никакие ресурсы для рисования.

1 Ответ

0 голосов
/ 24 сентября 2018

Это почти наверняка пользователи, разделяющие приложение, либо через программы обмена P2P, либо загружающие APK в Интернет, чем другие пользователи, загружающие и устанавливающие из Интернета.

Люди, привыкшие иметь дело с комплектом приложений, отличных от Androidприложения просто переносят и делятся основными APK.Но в вашем приложении есть множество «разделенных APK» для таких вещей, как ресурсы, именно так происходит экономия размера.Вы можете прочитать все об этом процессе на странице помощи .Если пользователь устанавливает основной APK без установки правильных разделенных APK, то при первой попытке приложения загрузить ресурс произойдет сбой «Ресурсы не найдены».

Если вы хотите поддержать пользователей, загружающих ваше приложениеи только основной APK, вы можете попытаться обнаружить эту ситуацию и показать пользователю сообщение (без использования каких-либо ресурсов) с надписью «Пожалуйста, установите из Google Play».Или же вы можете просто решить, что не собираетесь поддерживать пользователей, которые делятся APK-файлами таким образом.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...