Android App Bundle представляет ресурс Не найдена авария в приложении для Android

Используя Android-приложение Android Android, я обнаружил, что ресурс не найден. Сбой в двух моих приложениях в Google Play Store:

Вот стек из ткани для одного из приложений: -

Unable to start activity ComponentInfo{/com.Lastyear.MainActivity}: android.content.res.Resources$NotFoundException: File res/drawable/abc_item_background_holo_dark.xml from drawable resource ID #0x7f08002c
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2377)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2429)
       at android.app.ActivityThread.access$800(ActivityThread.java:151)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1342)
       at android.os.Handler.dispatchMessage(Handler.java:110)
       at android.os.Looper.loop(Looper.java:193)
       at android.app.ActivityThread.main(ActivityThread.java:5363)
       at java.lang.reflect.Method.invokeNative(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:515)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:828)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:644)
       at dalvik.system.NativeStart.main(NativeStart.java)

build.gradle Зависимости: -

 dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.12'
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:customtabs:27.1.1'
implementation 'com.android.support:cardview-v7:27.1.1'
implementation 'com.squareup.picasso:picasso:2.5.2'

implementation 'com.android.support:palette-v7:27.1.1'
implementation 'com.afollestad.material-dialogs:core:0.9.6.0'
implementation 'com.jakewharton:butterknife:8.8.1'
implementation 'com.github.bumptech.glide:glide:3.7.0'
implementation 'com.android.support:design:27.1.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
implementation 'com.github.hotchemi:android-rate:1.0.1'
implementation 'com.hannesdorfmann.smoothprogressbar:library:1.0.0'
implementation 'com.android.support:palette-v7:27.1.1'
implementation 'com.google.android.gms:play-services-ads:15.0.1'
implementation 'com.muddzdev:styleabletoast:1.0.9'
implementation 'com.github.GrenderG:Toasty:1.2.5'
implementation 'com.hannesdorfmann.smoothprogressbar:library:1.0.0'

implementation 'com.wang.avi:library:2.1.3'
implementation 'com.github.medyo:fancybuttons:1.8.4'
implementation 'com.irozon.sneaker:sneaker:1.0.1'
implementation 'com.sdsmdg.tastytoast:tastytoast:0.1.1'
implementation 'de.hdodenhof:circleimageview:2.2.0'
implementation 'com.github.barteksc:android-pdf-viewer:2.8.2'


implementation 'com.getkeepsafe.taptargetview:taptargetview:1.11.0'


implementation('com.crashlytics.sdk.android:crashlytics:[email protected]') {
    transitive = true;
}


implementation 'petrov.kristiyan:colorpicker-library:1.1.8'}

Еще одна вещь, которая происходит только в операционной системе Android 4, не в новых версиях Android. Что я обнаружил, что у другого приложения есть та же проблема Resource Not Found, которая не существовала до использования пакета приложений для Android. Есть ли какая-то проблема в библиотеке или коде, или из-за бета-версии пакета приложений для Android?

enter image description here

Я также нашел ресурс, который можно извлечь из-за которого он сбой: - enter image description here

Я думаю, что этот вопрос также связан с этим: - Ошибка раздувания класса android.support.design.widget.NavigationView после добавления SwitchCompat в приложение для Android-приложений

Ответы

Ответ 1

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

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

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

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

Если вы видите, что это происходит гораздо чаще в более низких версиях Android, это, вероятно, не из-за ошибки в более низких версиях Android. Наоборот, это возможно потому, что в странах, где пользователи обычно используют P2P-приложения (например, в Индии), пользователи также гораздо чаще используют телефоны более старых версий.

Ответ 2

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

Ответ 3

Поскольку это происходит только на устройствах Android 4 после перехода на Android App Bundle, я узнал об этом после добавления: -

public class App extends Application {

static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); }

И в build.gradle: -

android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

как объясняется в этом сообщении: - Использование андроидального вектора Drawables при аварийном завершении Lollipop

Что касается второго вопроса: - Ошибка ресурса не найдена res/drawable/abc_switch_thumb_material.xml после добавления SwitchCompat в приложение Android Bundle

Поскольку это происходит на всех версиях Android. Я загрузил Apk и смог воспроизвести ту же ошибку в logcat. Поэтому это можно устранить, удалив SwitchCompat из моего проекта, я знаю, что это временное исправление, и Google обязательно должен что-то сделать, чтобы, по крайней мере, аварии не произошло после загрузки apk, возможно, перенаправление на игру в магазине будет лучшим вариантом. Но сбой приложения после перехода на Android App Bundle определенно влияет на стабильность приложения, поскольку многие пользователи делают это на регулярной основе.

Ответ 4

Принятый ответ является абсолютно правильным - корень этой проблемы - боковая загрузка APK файла.

Тем не менее, многие люди все еще ищут обходной путь, спрашивая, как правильно справиться с этим делом.

В моем приложении я сделал следующее:

  1. Создайте изображение 1x1 с именем pixel.png и поместите его во все следующие папки: drawable-mdpi drawable-hdpi, drawable-xhdpi drawable-xxhdpi, drawable-xxhdpi, drawable-xxhdpi, drawable-xxxhdpi.

  2. Создать простую Activity, которая показывает статическое сообщение, например,

    Эта копия приложения повреждена и не может быть запущена.

    Пожалуйста, установите оригинальную версию из Google Play

  3. Затем просто вызовите getDrawable(R.drawable.pixel) из Activity.onCreate() заключенного в предложение try/catch.

  4. Если исключение поймали, только закончить текущую Activity и начать еще один из шага # 2.

Готово!

Screenshot

Это решение работает хорошо, теперь у меня даже есть данные из Firebase Analytics, подтверждающие это.

Из 46 тысяч новых пользователей (событие first_open) 266 пользователей получили эту ошибку (которая была обнаружена) и 221 пользователь нажал кнопку, которая ведет в Google Play.

Вот мой исходный код (также доступен на GitHub):

DrawablesValidator.java

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Space;
import android.widget.TextView;
import android.widget.Toast;

public class DrawablesValidator extends Activity {
    public static void ensureDrawablesValid(@NonNull Activity activity) {
        try {
            // IMPORTANT create 1x1 image named pixel.png and put it to all folders
            //           drawable-mdpi
            //           drawable-hdpi
            //           drawable-xhdpi
            //           drawable-xxhdpi
            //           drawable-xxxhdpi
            activity.getDrawable(R.drawable.pixel);
        } catch (Resources.NotFoundException ex) {
            // NOTE optionally, report exception to Crashlytics or just an event to Analytics

            activity.finish();
            activity.startActivity(new Intent(activity, DrawablesValidator.class));
        }
    }

    // NOTE don't care about translations of text messages here, don't put them to strings.xml
    //      we assume, that if user is smart enough to get APK from outside and install it,
    //      then user will definitely understand few messages in English :)
    @SuppressLint("SetTextI18n")
    @Override
    protected void onCreate(Bundle state) {
        super.onCreate(state);

        int dp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics());
        int dp8 = dp * 8;
        int dp16 = dp * 16;
        int dp80 = dp * 80;

        LinearLayout root = new LinearLayout(this);
        root.setOrientation(LinearLayout.VERTICAL);
        root.setGravity(Gravity.CENTER_HORIZONTAL);
        root.setPadding(dp80, dp16, dp80, dp16);

        Space spaceTop = new Space(this);

        TextView title = new TextView(this);
        title.setPadding(0, dp8, 0, dp8);
        title.setTextSize(20);
        title.setText("Re-install app");

        TextView message = new TextView(this);
        message.setPadding(0, dp8, 0, dp8);
        message.setTextSize(16);
        message.setText("This copy of app is corrupted and can't be launched." +
                "\n\n" +
                "Please, install original version from Google Play");

        Button button = new Button(this);
        button.setPadding(dp16, dp8, dp16, dp8);
        button.setText("Continue");
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + getPackageName())));
                } catch (Exception ex) {
                    Toast.makeText(getApplicationContext(), "Can't open Google Play", Toast.LENGTH_SHORT).show();
                }
            }
        });

        Space spaceBottom = new Space(this);

        int wc = ViewGroup.LayoutParams.WRAP_CONTENT;
        int mp = ViewGroup.LayoutParams.MATCH_PARENT;

        root.addView(spaceTop, lp(0, 0, 1, -1));
        root.addView(title, lp(wc, wc, 0, -1));
        root.addView(message, lp(mp, wc, 0, -1));
        root.addView(button, lp(wc, wc, 0, Gravity.END));
        root.addView(spaceBottom, lp(mp, wc, 1, -1));

        setContentView(root);
    }

    private LinearLayout.LayoutParams lp(int width, int height, int weight, int gravity) {
        LinearLayout.LayoutParams result = new LinearLayout.LayoutParams(width, height);
        result.weight = weight;
        result.gravity = gravity;
        return result;
    }
}

Ответ 5

https://ourcodeworld.com/articles/read/331/android-error-no-resource-found-that-matches-the-given-name-at-icon-with-value-drawable-icon

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

Ответ 6

Вы можете проверить пользователей, разделяющих (загружающих) приложение из игровой консоли. Войдите в игровую консоль и выберите свое приложение, в котором вы публикуете пакет приложений вместо apk.

Выберите Android Vital → ANRs & crash и нажмите на вкладку crashes.

выберите установить из игры

enter image description here

Ответ 7

Это немного поздно, но Google представила новый API для Sideloading crash prevention, который позволяет обнаруживать неполную установку приложений, созданных с помощью пакета приложений для Android.

Например, рассмотрим приложение, которое использует комплекты Android-приложений для оптимизации размера загрузки приложения с помощью разделенных APK. Когда пользователь загружает приложение из магазина Google Play, оно гарантирует, что устройство загрузит и установит полный набор разделенных APK, необходимых для запуска этого приложения на этом конкретном устройстве. Когда вы обходите Google Play, чтобы загрузить приложение, платформа не имеет достаточно данных для проверки установки приложения, и надлежащая функциональность приложения не гарантируется.

Прежде всего, включите библиотеку Play Core 1.6.0 или выше в ваш проект.

Включите в файл build.gradle проектов вашего приложения следующее:

buildscript {
    dependencies {
        ...
        // Use bundletool 0.9.0 or higher when building with the
        // Android Gradle plugin.
        classpath 'com.android.tools.build:bundletool:0.9.0'
    }
}

Вы можете использовать 1 из этих 3 методов ниже

1) Зарегистрируйте чеки через манифест

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapplication" >
    <application
        ...
        android:name="com.google.android.play.core.missingsplits.MissingSplitsDetectingApplication" >
    </application>
    ...
</manifest>

2) Применить проверки в пользовательском классе приложения

public class MyCustomApplication extends Application {
    @Override
    public void onCreate() {

        if (MissingSplitsManagerFactory.create(this).disableAppIfMissingRequiredSplits()) {
            // Skip app initialization.
            return;
        }

        super.onCreate();
        ...
    }
}

3) Применить проверки к контент-провайдерам

public class ExampleProvider extends ContentProvider {
    @Override
    public boolean onCreate() {

        if (MissingSplitsManagerFactory.create(getContext()).isMissingRequiredSplits()) {
            // Skip provider initialization.
            return false;
        }

        super.onCreate();
        ...
    }
}

Подробнее: https://developer.android.com/reference/com/google/android/play/core/release-notes?hl=ru-419#1-6-0