Пользовательское представление ClassNotFoundException от LayoutInflater - PullRequest
1 голос
/ 03 февраля 2020

В одной из наших сборок выпуска мы используем ProGuard , где это помогает запутывать и минимизировать код. Эта проблема не воспроизводится на моем устройстве или эмуляторе, но от некоторых пользователей через Crashlytics мы получаем исключение, которое говорит, что система не может найти класс. Исключение составляют различные устройства и выше Android Lollipop. (API 21)

Трассировка исключений:

Caused by java.lang.ClassNotFoundException: Did not find class "com.example.android.views.CustomImageView" on path: DexPathList[[zip file "/data/app/com.example.android-1/base.apk"],nativeLibraryDirectories=[/data/app/com.example.android-1/lib/arm, /vendor/lib, /system/lib]]
       at dalvik.system.BaseDexClassLoader.findClass + 56(BaseDexClassLoader.java:56)
       at java.lang.ClassLoader.loadClass + 511(ClassLoader.java:511)
       at java.lang.ClassLoader.loadClass + 469(ClassLoader.java:469)
       at android.view.LayoutInflater.createView + 583(LayoutInflater.java:583)
       at android.view.LayoutInflater.createViewFromTag + 764(LayoutInflater.java:764)
       at android.view.LayoutInflater.createViewFromTag + 704(LayoutInflater.java:704)
       at android.view.LayoutInflater.rInflate + 835(LayoutInflater.java:835)
       at android.view.LayoutInflater.rInflateChildren + 798(LayoutInflater.java:798)
       at android.view.LayoutInflater.rInflate + 838(LayoutInflater.java:838)
       at android.view.LayoutInflater.rInflateChildren + 798(LayoutInflater.java:798)
       at android.view.LayoutInflater.rInflate + 838(LayoutInflater.java:838)
       at android.view.LayoutInflater.rInflateChildren + 798(LayoutInflater.java:798)
       at android.view.LayoutInflater.inflate + 515(LayoutInflater.java:515)
       at android.view.LayoutInflater.inflate + 423(LayoutInflater.java:423)
       at com.example.android.fragments.MyFragment.onCreateView + 160(AdPopupFragmentVertical.java:160)
       at androidx.fragment.app.Fragment.performCreateView + 2600(Fragment.java:2600)
       at androidx.fragment.app.FragmentManagerImpl.moveToState + 881(FragmentManagerImpl.java:881)
       at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState + 1238(FragmentManagerImpl.java:1238)
       at androidx.fragment.app.FragmentManagerImpl.moveToState + 1303(FragmentManagerImpl.java:1303)
       at androidx.fragment.app.FragmentManagerImpl.dispatchStateChange + 2659(FragmentManagerImpl.java:2659)
       at androidx.fragment.app.FragmentManagerImpl.dispatchActivityCreated + 2613(FragmentManagerImpl.java:2613)
       at androidx.fragment.app.FragmentController.dispatchActivityCreated + 246(FragmentController.java:246)
       at androidx.fragment.app.FragmentActivity.onStart + 542(FragmentActivity.java:542)
       at androidx.appcompat.app.AppCompatActivity.onStart + 201(AppCompatActivity.java:201)

Связанное правило ProGuard:

-keep class com.example.android.views.** { *; }

И, чтобы go еще безопаснее, Я также добавил аннотацию @Keep в начало класса, например:

package com.example.android.views;

import androidx.annotation.Keep;

@Keep
public class CustomImageView extends AppCompatImageView {
     // rest of the code
}

Чтобы убедиться, что я создал релиз APK и проверил его с помощью APK Analyzer. Теперь приложение использует MultiDex (поскольку оно должно содержать рекламу), а файл classes.dex содержит представление с его правильным именем, путем (я имею в виду пакет) и методами. Итак, я не понимаю, почему некоторые устройства не могут найти это представление.

Что еще можно сделать, чтобы решить эту проблему? Спасибо за любую помощь, спасибо.

Редактировать: Если это помогает, это представление является специальным представлением, которое создает тень в зависимости от растрового изображения, в которое она отправляется с использованием Renderscript выше Android Lollipop. (API 21)

Редактировать 2: Вот мой файл build.gradle уровня приложения. (пропущены ненужные части)

android {
    compileSdkVersion 29
    buildToolsVersion '28.0.3' // this is ignored already
    defaultConfig {
        applicationId "com.example.android"
        minSdkVersion 16
        targetSdkVersion 29
        versionCode 1000
        versionName "1000"
        multiDexEnabled true
        lintOptions {
            checkReleaseBuilds false
        }
        vectorDrawables.useSupportLibrary = true
    }

    dexOptions {
        preDexLibraries = false
        javaMaxHeapSize "4g"
    }

    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
        }
        debug {
            signingConfig signingConfigs.release
        }
    }

    compileOptions {
        sourceCompatibility = '1.8'
        targetCompatibility = '1.8'
    }

    applicationVariants.all { variant ->

        def flavor = variant.mergedFlavor
        def name = flavor.getVersionName()

        if (variant.buildType.isDebuggable())
            name += 'd'
        else
            name += 'r'

        variant.outputs.each { output ->
            output.versionNameOverride = name
        }

        variant.outputs.all {
            def versionName = variant.versionName
            versionName += variant.buildType.isDebuggable() ? 'd' : 'r'
            outputFileName = "example-${versionName}.apk"
        }
    }

    useLibrary 'org.apache.http.legacy'
}

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