我想在我的Android应用程序中使用Assert关键字在某些情况下在模拟器或测试期间的设备上销毁我的应用程序.这可能吗?
似乎模拟器只是忽略了我的断言.
sco*_*awg 145
请参阅嵌入式VM控制文档(源树中的原始HTML 或格式良好的副本).
基本上,即使.dex字节代码包含执行检查的代码,Dalvik VM也会默认设置为忽略断言检查.检查断言是以两种方式之一打开的:
(1)通过以下方式设置系统属性"debug.assert":
adb shell setprop debug.assert 1
Run Code Online (Sandbox Code Playgroud)
只要您在执行此操作后重新安装应用程序,我验证的工作符合预期,或者
(2)通过向dalvik VM发送命令行参数"--enable-assert",这可能不是app开发人员可能做的事情(如果我在这里错了,有人会纠正我).
基本上,存在既可以全局设置,在封装级,或者在类级使断言在该各自电平的标志.该标志默认是关闭的,因此跳过断言检查.
我在我的示例Activity中编写了以下代码:
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;
}
}
对于此代码,生成的dalvik字节代码是(对于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
注意静态构造函数如何在Class对象上调用方法desiredAssertionStatus并设置类范围的变量$ assertionsDisabled; 另请注意,在onCreate()中,所有抛出java.lang.AssertionError的代码都是编译进来的,但是它的执行取决于为静态构造函数中的Class对象设置的$ assertionsDisabled的值.
似乎JUnit的Assert类是主要使用的类,所以使用它可能是一个安全的选择.assert关键字的灵活性是能够在开发时打开断言并将其关闭以用于传送位,而是优雅地失败.
希望这可以帮助.
Dhe*_*.S. 10
启用断言时,assert关键字只会AssertionError在布尔表达式时抛出false.
所以IMO,最好的选择,尤其是 如果你反对依赖junit,那就是AssertionError明确抛出如下所示:
assert x == 0 : "x = " + x;
Run Code Online (Sandbox Code Playgroud)
上述陈述的替代方案是:
Utils._assert(x == 0, "x = " + x);
Run Code Online (Sandbox Code Playgroud)
方法定义为:
public static void _assert(boolean condition, String message) {
if (!condition) {
throw new AssertionError(message);
}
}
Run Code Online (Sandbox Code Playgroud)
Oracle java文档建议将其AssertionError作为可接受的替代方案.
我想你可以配置Proguard去掉这些生产代码的调用.
在"Android in Practice"中,建议使用:
$adb shell setprop dalvik.vm.enableassertions all
Run Code Online (Sandbox Code Playgroud)
如果您的手机上没有保留此设置,则可以使用以下属性创建/data/local.prop文件:
dalvik.vm.enableassertions=all
Run Code Online (Sandbox Code Playgroud)
这让我感到害怕,我的断言没有用,直到我在google上检查了这个问题...我放弃了简单的断言,并将使用junits断言方法.
为方便起见,我使用的是:
import static junit.framework.Assert.*;
由于静态导入我可以稍后写:
assertTrue(...); 而不是Assert.assertTrue(...);
JRL*_*JRL -7
API 提供JUnit Assert。
你可以做
import static junit.framework.Assert.*;
Run Code Online (Sandbox Code Playgroud)
现在您可以使用junit框架中提供的所有函数,如assertTrue、assertEquals、assertNull。
注意不要通过eclipse导入Junit4框架,那将是org.junit包。您必须使用 junit.framework 包才能使其在 Android 设备或模拟器上运行。