3.6 应用程序崩溃排错
Ulysses Levy
3.6.1 问题
应用崩溃,而原因不确定(参见图3-14)。
3.6.2 解决方案
从查看日志开始。
3.6.3 讨论
遇到应用程序崩溃时,我们可以使用adb logcat命令或者Eclipse LogCat窗口查看AVD的日志。例3-3说明了如何用adb logcat查看堆栈跟踪,找到故障的位置。
例3-3:“权限拒绝”问题的堆栈跟踪
E/DatabaseUtils( 53): Writing exception to parcel
E/DatabaseUtils( 53): java.lang.SecurityException: Permission Denial: writing
com.android.providers.settings.SettingsProvider uri content://settings/system
from pid=430, uid=10030 requires android.permission.WRITE_SETTINGS
E/DatabaseUtils( 53): at android.content.ContentProvider$Transport.
enforceWritePermission(ContentProvider.java:294)
E/DatabaseUtils( 53): at android.content.ContentProvider$Transport.
insert(ContentProvider.java:149)
E/DatabaseUtils( 53): at android.content.ContentProviderNative.
onTransact(ContentProviderNative.java:140)
E/DatabaseUtils( 53): at android.os.Binder.execTransact(Binder.java:287)
E/DatabaseUtils( 53): at com.android.server.SystemServer.init1(Native Method)
E/DatabaseUtils( 53): at com.android.server.SystemServer.main(SystemServer.java:497)
E/DatabaseUtils( 53): at java.lang.reflect.Method.invokeNative(Native Method)
E/DatabaseUtils( 53): at java.lang.reflect.Method.invoke(Method.java:521)
E/DatabaseUtils( 53): at com.android.internal.os.
ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
E/DatabaseUtils( 53): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
E/DatabaseUtils( 53): at dalvik.system.NativeStart.main(Native Method)
D/AndroidRuntime( 430): Shutting down VM
W/dalvikvm( 430): threadid=3: thread exiting with uncaught exception (group=0x4001b188)
...
在例3-3中,我们遇到了权限问题。这一特殊实例的解决方案是在AndroidManifest.xml文件中添加WRITE_SETTINGS权限。
<manifest ... >
<application ... />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
</manifest>
另一种相当常见的错误是空指针异常(NPE)。
例3-4显示了LogCat输出。
例3-4:LogCat输出
I/ActivityManager( 53): Displayed activity com.android.launcher/.Launcher:
28640 ms (total 28640 ms)
I/ActivityManager( 53): Starting activity: Intent { act=android.intent.action.MAIN
cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.aschyiel.disp/.Disp }
I/ActivityManager( 53): Start proc com.aschyiel.disp for
activity com.aschyiel.disp/.Disp: pid=214 uid=10030 gids={1015}
I/ARMAssembler( 53): generated scanline__00000177:03515104_00000001_00000000 [ 73 ipp]
(95 ins) at [0x47c588:0x47c704] in 2087627 ns
I/ARMAssembler( 53): generated scanline__00000077:03545404_00000004_00000000 [ 47 ipp]
(67 ins) at [0x47c708:0x47c814] in 1834173 ns
I/ARMAssembler( 53): generated scanline__00000077:03010104_00000004_00000000 [ 22 ipp]
(41 ins) at [0x47c818:0x47c8bc] in 653016 ns
D/AndroidRuntime( 214): Shutting down VM
W/dalvikvm( 214): threadid=3: thread exiting with uncaught exception (group=0x4001b188)
E/AndroidRuntime( 214): Uncaught handler: thread main exiting due to uncaught exception
E/AndroidRuntime( 214): java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.aschyiel.disp/com.aschyiel.disp.Disp}:java.lang.NullPointerException
E/AndroidRuntime( 214): at android.app.ActivityThread.performLaunchActivity(
ActivityThread.java:2496)
E/AndroidRuntime( 214): at android.app.ActivityThread.handleLaunchActivity(
ActivityThread.java:2512)
E/AndroidRuntime( 214): at android.app.ActivityThread.access$2200(
ActivityThread.java:119)
E/AndroidRuntime( 214): at android.app.ActivityThread$H.handleMessage(
ActivityThread.java:1863)
E/AndroidRuntime( 214): at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime( 214): at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime( 214): at android.app.ActivityThread.main(ActivityThread.java:4363)
E/AndroidRuntime( 214): at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 214): at java.lang.reflect.Method.invoke(Method.java:521)
E/AndroidRuntime( 214): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(
ZygoteInit.java:860)
E/AndroidRuntime( 214): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
E/AndroidRuntime( 214): at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime( 214): Caused by: java.lang.NullPointerException
E/AndroidRuntime( 214): at com.aschyiel.disp.Disp.onCreate(Disp.java:66)
E/AndroidRuntime( 214): at android.app.Instrumentation.callActivityOnCreate(
Instrumentation.java:1047)
E/AndroidRuntime( 214): at android.app.ActivityThread.performLaunchActivity(
ActivityThread.java:2459)
E/AndroidRuntime( 214): ... 11 more
发生错误的示例代码如下:
import ...
public class Disp extends Activity
{
private TextView foo;
@Override
public void onCreate( Bundle savedInstanceState )
{
...
foo.setText("bar");
}
}
上述代码失败原因是忘记使用findViewById()。
下面是修复后的代码:
import ...
public class Disp extends Activity
{
private TextView foo;
@Override
public void onCreate( Bundle savedInstanceState )
{
...
foo = (TextView) findViewById( R.id.id_foo );
foo.setText("bar");
}
}
这段代码应该会去除错误。
3.6.4 参阅
“Google I/O 2009-Debugging Arts of the Ninja Masters”(Google I/O 2009-忍者大师的调试艺术)