En utilisant Android new Android Bundle d'applications j'ai trouvé une ressource introuvable. Crashes dans 2 de mes applications Google Play Store: -
Voici la pile de tissu pour l'une des applications: -
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)
dépendances 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:2.6.8@aar') {
transitive = true;
}
implementation 'petrov.kristiyan:colorpicker-library:1.1.8'}
Une dernière chose qu’il ne se passe que sur Android 4 système d’exploitation pas sur les nouvelles versions de Android .Que ai-je constaté que l’autre application avait le même problème de Ressource non trouvée qui n'existait pas avant d'utiliser Android bundle d'application. Existe-t-il un problème de bibliothèque ou de code ou est-ce dû à la version bêta de Android app bundle ?
J'ai également trouvé la ressource extractible en raison de laquelle il se bloque: -
Je pense que cette question est également liée à ceci: - Erreur lors de l’ajout de la classe Android.support.design.widget.NavigationView après l’ajout de SwitchCompat dans Android App Bundle
C’est presque certainement que les utilisateurs partagent (déchargent latéralement) l’application, via des programmes de partage P2P, ou téléchargent le fichier APK sur le Web, puis que d’autres utilisateurs téléchargent et installent à partir du Web.
Les gens habitués à traiter avec Android App _ Bundles app ne font que transférer et partager l'APK principal. Mais votre appli d'Application Bundle a beaucoup de "APK fractionnés" pour des choses comme les ressources, voilà comment l'économie de taille se produit. Vous pouvez tout lire sur ce processus sur la page d'aide . Si un utilisateur installe l'APK principal sans installer les APK bien fractionnés, un blocage "Ressources non trouvées" se produira la première fois que l'application tente de charger une ressource.
Si vous souhaitez aider les utilisateurs à ne pas charger votre application et le fichier APK principal, vous pouvez essayer de détecter cette situation et d’afficher un message à l’utilisateur (sans utiliser de ressources) indiquant "Veuillez installer à partir de Google Play". Vous pouvez également décider de ne pas aider les utilisateurs partageant les fichiers APK de cette manière.
Je pense qu'à long terme, les sites Web et les programmes de partage P2P seront de mieux en mieux pour partager correctement ces APK, de sorte que je ne passerais pas trop de temps à m'en inquiéter.
Si cela se produit beaucoup plus fréquemment sur les versions inférieures Android, cela n'est probablement pas dû à un bogue des versions inférieures Android. C’est probablement parce que, dans les pays où les utilisateurs partagent généralement des applications P2P (par exemple, en Inde), les utilisateurs ont également beaucoup plus de chances d’être sur des téléphones dotés d’une version antérieure.
Le problème est probablement que votre application a été rechargée de manière horizontale, c'est-à-dire qu'elle n'a pas été installée via le Play Store, et des fichiers APK incompatibles ont été installés manuellement sur ces appareils.
C’est un peu tard, mais Google a introduit une nouvelle API pour Sideloading crash prevention
, qui vous permet de détecter une installation incomplète des applications créées à l'aide d'un Android App Bundle.
Par exemple, considérons une application qui utilise Android Bundles d’applications pour optimiser la taille de téléchargement d’application à l’aide de fichiers APK divisés. Lorsqu'un utilisateur télécharge l’application depuis le Google Play Store, il s’assure que le périphérique télécharge et installe le ensemble complet de fichiers APK scindés requis pour exécuter cette application sur ce périphérique particulier. Lorsque vous ignorez le chargement secondaire de Google Play, la plate-forme ne dispose pas de suffisamment de données pour valider l'installation de l'application et le bon fonctionnement de celle-ci n'est pas garanti.
Commencez par inclure la bibliothèque Play Core 1.6.0 ou supérieure dans votre projet.
Incluez les éléments suivants dans le fichier build.gradle de votre projet d’application:
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'
}
}
Vous pouvez utiliser l'une de ces 3 méthodes ci-dessous
1) Enregistrer les chèques via le manifeste
<?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) Appliquer des contrôles dans une classe d'application personnalisée
public class MyCustomApplication extends Application {
@Override
public void onCreate() {
if (MissingSplitsManagerFactory.create(this).disableAppIfMissingRequiredSplits()) {
// Skip app initialization.
return;
}
super.onCreate();
...
}
}
3) Appliquer des contrôles aux fournisseurs de contenu
public class ExampleProvider extends ContentProvider {
@Override
public boolean onCreate() {
if (MissingSplitsManagerFactory.create(getContext()).isMissingRequiredSplits()) {
// Skip provider initialization.
return false;
}
super.onCreate();
...
}
}
En savoir plus: https://developer.Android.com/reference/com/google/Android/play/core/release-notes?hl=en-419#1-6-
La réponse acceptée est absolument correcte - racine du problème est un téléchargement latéral du fichier APK.
Néanmoins, beaucoup de gens cherchent encore une solution de contournement, demandant comment gérer correctement ce cas.
Dans mon application, j'ai fait ce qui suit:
Créez une image 1x1 nommée pixel.png
Et mettez-la dans tous les dossiers suivants: drawable-mdpi
, drawable-hdpi
, drawable-xhdpi
, drawable-xxhdpi
, drawable-xxxhdpi
.
Créez simple Activity
qui affiche un message statique, par exemple.
Cette copie de l'application est corrompue et ne peut pas être lancée.
S'il vous plaît, installez la version originale de Google Play
Ensuite, appelez simplement getDrawable(R.drawable.pixel)
à partir de Activity.onCreate()
intégré dans la clause try/catch
.
Si l'exception est interceptée, finissez simplement le Activity
actuel et commencez-en un autre à partir de l'étape 2.
Terminé!
Cette solution fonctionne bien. À présent, des données de Firebase Analytics me le confirment.
Parmi les 46 000 nouveaux utilisateurs (événement first_open
), 266 utilisateurs ont eu cette erreur (qui a été interceptée) et 221 utilisateurs ont cliqué sur le bouton menant à Google Play.
Voici mon code source (également disponible sur 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;
}
}
Comme cela ne se produit que sur les appareils Android 4 après la migration vers Android App Bundle, j'ai découvert un moyen de le faire après avoir ajouté: -
public class App extends Application {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); }
Et dans build.gradle: -
Android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
comme expliqué dans ce post: - tilisation de Android vecteur Drawables sur le crash de Lollipop
En ce qui concerne la deuxième question: - erreur de ressource introuvable) res/drawable/abc_switch_thumb_material.xml après l'ajout de SwitchCompat dans Android App Bundle
Comme cela se produit sur toutes les versions Android. J'ai installé Sideload dans Apk et capable de reproduire la même erreur dans logcat. Cela ne peut donc être résolu qu'en supprimant le SwitchCompat de mon projet. Je sais que c'est un correctif temporaire et Google devrait sûrement faire quelque chose à ce sujet afin d'éviter au moins un crash. après avoir sideloading l'apk, peut-être que la redirection vers Play Store serait la meilleure option. Mais le crash de l'application après la migration vers Android App Bundle affecte définitivement la stabilité de l'application, car de nombreux utilisateurs le font régulièrement.
Vous pouvez vérifier le partage d'utilisateurs (chargement latéral ) de l'application depuis console de lecture Connexion à la console de lecture sélectionnez votre application sur laquelle vous publiez un ensemble d'applications. au lieu d'apk.
Sélectionnez Android Vital -> ANR et crash et cliquez sur l'onglet Crashes.
sélectionnez installer depuis le jeu
Grâce au lien ci-dessus, j’ai appris que les icônes utilisées dans l’application devaient figurer dans le dossier de ressources pouvant être dessiné, tandis que les icônes de lancement devaient figurer dans le dossier de ressources mipmap. J'ai transféré mes icônes et cela a fonctionné pour moi.