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.
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.
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.
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
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 (...);
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.
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.
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.