LayoutInflater的自定义视图ClassNotFoundException

问题描述 投票:1回答:1

在我们的其中一个发行版中,我们使用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.** { *; }

而且,为了更加安全,我也将@Keep注释也添加到类的顶部,如下所示:

package com.example.android.views;

import androidx.annotation.Keep;

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

[为确保安全,我构建了一个发行版APK并通过APK分析器进行了检查。现在,该应用程序使用MultiDex(因为它必须包含广告),并且classes.dex文件似乎包含具有正确名称,路径(即包装)和方法的视图。因此,我不明白为什么某些设备无法找到此视图。

可以解决此问题的其他方法?感谢您的任何帮助,谢谢。

编辑:如果有帮助,此视图是一个特殊视图,该视图根据在Android Lollipop上方使用Renderscript发送到的位图来创建投影。 (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'
}

android proguard android-custom-view
1个回答
0
投票

更改您的minsdk和目标sdk,在app.gradle中将其编译为sdk

 compileSdkVersion 29
    minSdkVersion 15
    targetSdkVersion 29
© www.soinside.com 2019 - 2024. All rights reserved.