web-dev-qa-db-fra.com

Puis-je utiliser assert sur les appareils Android?

Je veux utiliser le mot clé Assert dans mes applications Android pour détruire mon application dans certains cas sur l'émulateur ou sur mon appareil pendant les tests. Est-ce possible?

Il semble que l'émulateur ignore simplement mes assertions.

89
Janusz

Voir le document de contrôle Embedded VM (HTML brut de la arborescence source , ou une copie bien formatée ).

Fondamentalement, Dalvik VM est configuré pour ignorer les vérifications d'assertion par défaut, même si le code d'octet .dex inclut le code pour effectuer la vérification. La vérification des assertions est activée de deux manières:

(1) en définissant la propriété système "debug.assert" via:

adb Shell setprop debug.assert 1

que j'ai vérifié fonctionne comme prévu tant que vous réinstallez votre application après cela, ou

(2) en envoyant l'argument de ligne de commande "--enable-assert" au dalvik VM ce qui n'est peut-être pas quelque chose que les développeurs d'applications sont susceptibles de faire (quelqu'un me corrige si je ' me trompe ici).

Fondamentalement, il existe un indicateur qui peut être défini soit globalement, au niveau du package, soit au niveau de la classe qui permet des assertions à ce niveau respectif. Le drapeau est désactivé par défaut, à la suite de quoi les vérifications d'assertion sont ignorées.

J'ai écrit le code suivant dans mon exemple d'activité:


public class AssertActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    int x = 2 + 3;
    assert x == 4;
  }
}

Pour ce code, le code d'octet dalvik généré est (pour Android 2.3.3):


// Static constructor for the class
000318:                                        |[000318] com.example.asserttest.AssertActivity.:()V
000328: 1c00 0300                              |0000: const-class v0, Lcom/example/asserttest/AssertActivity; // class@0003
00032c: 6e10 0c00 0000                         |0002: invoke-virtual {v0}, Ljava/lang/Class;.desiredAssertionStatus:()Z // method@000c
000332: 0a00                                   |0005: move-result v0
000334: 3900 0600                              |0006: if-nez v0, 000c // +0006
000338: 1210                                   |0008: const/4 v0, #int 1 // #1
00033a: 6a00 0000                              |0009: sput-boolean v0, Lcom/example/asserttest/AssertActivity;.$assertionsDisabled:Z // field@0000
00033e: 0e00                                   |000b: return-void
000340: 1200                                   |000c: const/4 v0, #int 0 // #0
000342: 28fc                                   |000d: goto 0009 // -0004


: :


// onCreate() 00035c: |[00035c] com.example.asserttest.AssertActivity.onCreate:(Landroid/os/Bundle;)V 00036c: 6f20 0100 3200 |0000: invoke-super {v2, v3}, Landroid/app/Activity;.onCreate:(Landroid/os/Bundle;)V // method@0001 000372: 1501 037f |0003: const/high16 v1, #int 2130903040 // #7f03 000376: 6e20 0500 1200 |0005: invoke-virtual {v2, v1}, Lcom/example/asserttest/AssertActivity;.setContentView:(I)V // method@0005 00037c: 1250 |0008: const/4 v0, #int 5 // #5 00037e: 6301 0000 |0009: sget-boolean v1, Lcom/example/asserttest/AssertActivity;.$assertionsDisabled:Z // field@0000 000382: 3901 0b00 |000b: if-nez v1, 0016 // +000b 000386: 1251 |000d: const/4 v1, #int 5 // #5 000388: 3210 0800 |000e: if-eq v0, v1, 0016 // +0008 00038c: 2201 0c00 |0010: new-instance v1, Ljava/lang/AssertionError; // class@000c 000390: 7010 0b00 0100 |0012: invoke-direct {v1}, Ljava/lang/AssertionError;.:()V // method@000b 000396: 2701 |0015: throw v1 000398: 0e00 |0016: return-void


Remarquez comment le constructeur statique appelle la méthode desireAssertionStatus sur l'objet Class et définit la variable à l'échelle de la classe $ assertionsDisabled; notez également que dans onCreate (), tout le code pour lancer Java.lang.AssertionError est compilé, mais son exécution dépend de la valeur de $ assertionsDisabled qui est définie pour l'objet Class dans le constructeur statique.

Il semble que la classe Assert de JUnit soit ce qui est utilisé principalement, il est donc probablement une valeur sûre de l'utiliser. La flexibilité du mot clé assert est la possibilité d'activer des assertions au moment du développement et de les désactiver pour l'envoi de bits et échouent gracieusement.

J'espère que cela t'aides.

145
scorpiodawg

Lorsque les assertions sont activées, le mot clé assert renvoie simplement un AssertionError lorsque l'expression booléenne est false.

Donc, l'OMI, la meilleure alternative, esp. si vous êtes réticent à dépendre de junit, c'est de lancer un AssertionError explicitement comme indiqué ci-dessous:

assert x == 0 : "x = " + x;

Une alternative à la déclaration ci-dessus est:

Utils._assert(x == 0, "x = " + x);

Où la méthode est définie comme:

public static void _assert(boolean condition, String message) {
    if (!condition) {
        throw new AssertionError(message);
    }
}

Oracle Java docs recommend lançant un AssertionError comme alternative acceptable.

Je suppose que vous pouvez configurer Proguard pour éliminer ces appels au code de production.

10
Dheeraj V.S.

Dans "Android en pratique", il est suggéré d'utiliser:

$adb Shell setprop dalvik.vm.enableassertions all

si ces paramètres ne persistent pas sur votre téléphone, vous pouvez créer un fichier /data/local.prop avec des propriétés telles que:

dalvik.vm.enableassertions=all
8
marcinj

Cela me dérangeait, que mes assertions ne fonctionnaient pas, jusqu'à ce que je vérifie le problème sur Google ... J'ai abandonné les assertions simples et j'irai avec les méthodes d'assertion junits.

Pour des raisons de commodité, j'utilise:

import statique junit.framework.Assert. *;

En raison de l'importation statique, je peux écrire plus tard:

assertTrue (...); au lieu de Assert.assertTrue (...);

5
Ready4Android

Si vous êtes préoccupé par l'envoi de code avec les assertions JUnit dans (ou tout autre chemin de classe), vous pouvez utiliser l'option de configuration ProGuard 'assumenosideeffects', qui supprimera un chemin de classe en supposant que sa suppression ne fait rien pour le code .

Par exemple.

-assumenosideeffects junit.framework.Assert {
*;
}

J'ai une bibliothèque de débogage commune dans laquelle je mets toutes mes méthodes de test, puis utilise cette option pour la supprimer de mes applications publiées.

Cela supprime également le problème difficile à repérer des chaînes manipulées qui ne sont jamais utilisées dans le code de version. Par exemple, si vous écrivez une méthode de journal de débogage, et dans cette méthode, vous vérifiez le mode de débogage avant d'enregistrer la chaîne, vous construisez toujours la chaîne, allouez de la mémoire, appelez la méthode, mais choisissez de ne rien faire. Supprimer la classe supprime ensuite complètement les appels, ce qui signifie que tant que votre chaîne est construite à l'intérieur de l'appel de méthode, elle disparaît également.

Assurez-vous cependant qu'il est vraiment sûr de simplement retirer les lignes, car cela se fait sans vérification de la part de ProGuard. La suppression de toute méthode de retour vide sera correcte, mais si vous prenez des valeurs de retour de tout ce que vous supprimez, assurez-vous de ne pas les utiliser pour la logique opérationnelle réelle.

4
Zulaxia

Pour ajouter à la réponse de Zulaxia sur la suppression de Junit - Proguard fait déjà partie de Android SDK/Eclipse et la page suivante vous explique comment l'activer.

http://developer.Android.com/guide/developing/tools/proguard.html

De plus, ce qui précède ne fonctionnera pas avec la dernière configuration de proguard par défaut car il utilise l'indicateur -dontoptimize qui doit être retiré et certaines des optimisations activées.

1
Sean Moore

Utilisez le mot clé standard Java assert, par exemple:

assert a==b;

Pour que cela fonctionne, vous devez ajouter une ligne à /system/build.prop et redémarrer le téléphone:

debug.assert=1

Cela fonctionnerait sur un téléphone rooté. Utilisez un gestionnaire de fichiers capable de modifier build.prop (par exemple X-plore).

Avantages: la plupart (tous?) Android sont livrés avec des assertions désactivées. Même si votre code affirme accidentellement qu'il est faux, l'application n'interrompra pas ou ne plantera pas. Cependant, sur votre appareil de développement, vous obtiendrez exception d'assertion.

0
Pointer Null