Android中的Exception总结
在开发中会遇到各种各样的Exception, 现在总结如下:
1.java.lang.NullPointerException
空指针异常,这个最常见,基本上每个开发者都会遇上。这个异常通常会导致程序崩溃,App直接退出。
已经上线发布的版本如果出现这个问题,属于很严重的生产事故,应该引起我们足够的重视。
针对这个问题,对于有可能是null的对象,不要进行任何形式的方法调用。在使用之前一定要进行非空判断。
2.android.database.sqlite.SQLiteException
eg:
11-15 15:23:18.260: E/AndroidRuntime(4990): Caused by: android.database.sqlite.SQLiteException: near “LOCALIZED”: syntax error (code 1): , while compiling: SELECT _id, display_name, contacts_status_updates.status AS contact_status, agg_presence.mode AS contact_presence, photo_id, lookup FROM view_contacts_restricted LEFT OUTER JOIN agg_presence ON (view_contacts_restricted._id = agg_presence.presence_contact_id) LEFT OUTER JOIN status_updates contacts_status_updates ON (status_update_id=contacts_status_updates.status_update_data_id) WHERE ((1)) AND ((((display_name NOTNULL) AND (has_phone_number=1) AND (display_name != ” )))) ORDER BY display_nameCOLLATE LOCALIZED ASC
11-15 15:23:18.260: E/AndroidRuntime(4990): #################################################################
11-15 15:23:18.260: E/AndroidRuntime(4990): Error Code : 1 (SQLITE_ERROR)
11-15 15:23:18.260: E/AndroidRuntime(4990): Caused By : SQL(query) error or missing database.
11-15 15:23:18.260: E/AndroidRuntime(4990): (near “LOCALIZED”: syntax error (code 1): , while compiling: SELECT _id, display_name, contacts_status_updates.status AS contact_status, agg_presence.mode AS contact_presence, photo_id, lookup FROM view_contacts_restricted LEFT OUTER JOIN agg_presence ON (view_contacts_restricted._id = agg_presence.presence_contact_id) LEFT OUTER JOIN status_updates contacts_status_updates ON (status_update_id=contacts_status_updates.status_update_data_id) WHERE ((1)) AND ((((display_name NOTNULL) AND (has_phone_number=1) AND (display_name != ” )))) ORDER BY display_nameCOLLATE LOCALIZED ASC)
11-15 15:23:18.260: E/AndroidRuntime(4990): #################################################################
11-15 15:23:18.260: E/AndroidRuntime(4990): #################################################################
11-15 15:23:18.260: E/AndroidRuntime(4990): Error Code : 1 (SQLITE_ERROR)
11-15 15:23:18.260: E/AndroidRuntime(4990): Caused By : SQL(query) error or missing database.
11-15 15:23:18.260: E/AndroidRuntime(4990): (near “LOCALIZED”: syntax error (code 1): , while compiling: SELECT _id, display_name, contacts_status_updates.status AS contact_status, agg_presence.mode AS contact_presence, photo_id, lookup FROM view_contacts_restricted LEFT OUTER JOIN agg_presence ON (view_contacts_restricted._id = agg_presence.presence_contact_id) LEFT OUTER JOIN status_updates contacts_status_updates ON (status_update_id=contacts_status_updates.status_update_data_id) WHERE ((1)) AND ((((display_name NOTNULL) AND (has_phone_number=1) AND (display_name != ” )))) ORDER BY display_nameCOLLATE LOCALIZED ASC)
11-15 15:23:18.260: E/AndroidRuntime(4990): #################################################################)
11-15 15:23:18.260: E/AndroidRuntime(4990): #################################################################
11-15 15:23:18.260: E/AndroidRuntime(4990): at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:179)
11-15 15:23:18.260: E/AndroidRuntime(4990): at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
11-15 15:23:18.260: E/AndroidRuntime(4990): at android.content.ContentProviderProxy.query(ContentProviderNative.java:421)
11-15 15:23:18.260: E/AndroidRuntime(4990): at android.content.ContentResolver.query(ContentResolver.java:502)
11-15 15:23:18.260: E/AndroidRuntime(4990): at android.content.CursorLoader.loadInBackground(CursorLoader.java:64)
11-15 15:23:18.260: E/AndroidRuntime(4990): at android.content.CursorLoad
这种是在操作数据库的时候出现的异常,出现异常后App直接崩溃退出。
出现这个问题的原因是sql语句有问题,我在拼接sql语句的时候,少了一个空格。
3.android.database.sqlite.SQLiteConstraintException
eg:
10-31 15:12:25.076: E/SQLiteDatabase(15463): android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: passenger.userId, passenger.travellerId (code 1555)
10-31 15:12:25.076: E/SQLiteDatabase(15463): #################################################################
10-31 15:12:25.076: E/SQLiteDatabase(15463): Error Code : 1555 (SQLITE_CONSTRAINT_PRIMARYKEY)
10-31 15:12:25.076: E/SQLiteDatabase(15463): Caused By : Abort due to constraint violation.
10-31 15:12:25.076: E/SQLiteDatabase(15463): (UNIQUE constraint failed: passenger.userId, passenger.travellerId (code 1555))
10-31 15:12:25.076: E/SQLiteDatabase(15463): #################################################################
10-31 15:12:25.076: E/SQLiteDatabase(15463): at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
10-31 15:12:25.076: E/SQLiteDatabase(15463): at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:866)
10-31 15:12:25.076: E/SQLiteDatabase(15463): at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
10-31 15:12:25.076: E/SQLiteDatabase(15463): at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
10-31 15:12:25.076: E/SQLiteDatabase(15463): at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1673)
10-31 15:12:25.076: E/SQLiteDatabase(15463): at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1543)
我在表中把userId设成了主键PRIMARY,插入travellerId的值同userId一样,在表中已存在同样的信息,所以抛出了异常。
另外,如果定义的字段为NOT NULL,而插入时对应的数据为NULL,也会出现这种异常。
4.java.lang.SecurityException
eg:
11-15 10:57:34.704: E/AndroidRuntime(24497): Caused by: java.lang.SecurityException: Permission Denial: opening provider com.android.providers.contacts.ContactsProvider2 from ProcessRecord{a557811 24497:com.example.loadertest/u0a321} (pid=24497, uid=10321) requires android.permission.READ_CONTACTS or android.permission.WRITE_CONTACTS
11-15 10:57:34.704: E/AndroidRuntime(24497): at android.os.Parcel.readException(Parcel.java:1621)
11-15 10:57:34.704: E/AndroidRuntime(24497): at android.os.Parcel.readException(Parcel.java:1574)
11-15 10:57:34.704: E/AndroidRuntime(24497): at android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:4292)
11-15 10:57:34.704: E/AndroidRuntime(24497): at android.app.ActivityThread.acquireProvider(ActivityThread.java:6567)
11-15 10:57:34.704: E/AndroidRuntime(24497): at android.app.ContextImpl
11-15 10:57:34.704: E/AndroidRuntime(24497): at android.content.AsyncTaskLoader
11-15 10:57:34.704: E/AndroidRuntime(24497): at java.util.concurrent.FutureTask.run(FutureTask.java:237)
11-15 10:57:34.704: E/AndroidRuntime(24497): … 3 more
从日志中明显可以看到requires android.permission.READ_CONTACTS or android.permission.WRITE_CONTACTS这一句。
我这里是没有读或者写联系人权限,在AndroidManifest中配置下就好了。在使用拍照、定位等功能,涉及用户隐私敏感信息的时候,注意提前申请权限。
类似这种异常,根据日志就可以解决。
5.android.view.WindowManager$BadTokenException
eg:
11-16 14:56:42.191: E/AndroidRuntime(9507): android.view.WindowManager$BadTokenException: Unable to add window – token android.os.BinderProxy@fefd524 is not valid; is your activity running?
11-16 14:56:42.191: E/AndroidRuntime(9507): at android.view.ViewRootImpl.setView(ViewRootImpl.java:910)
11-16 14:56:42.191: E/AndroidRuntime(9507): at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:337)
11-16 14:56:42.191: E/AndroidRuntime(9507): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:109)
11-16 14:56:42.191: E/AndroidRuntime(9507): at android.app.Dialog.show(Dialog.java:505)
我是在弹出Dialog的时候出现这个异常。根据日志信息,将要弹出的dialog所要依附的View已经不存在导致的。
在初始化Dialog的时候,使用的是getApplicationContext(),它的生命周期是整个应用程序的生命周期,而对于Activity的Context来说,当Activity销毁之后它对应的Context的生命周期就结束了。
Dialog是属于Activity的,创建的时候,需要Activity.this 所获取的Context。当Activity销毁的时候它也必须销毁。
6.java.lang.IllegalStateException
eg:
11-16 11:05:42.401: E/AndroidRuntime(25416): java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child’s parent first.
11-16 11:05:42.401: E/AndroidRuntime(25416): at android.view.ViewGroup.addViewInner(ViewGroup.java:4659)
11-16 11:05:42.401: E/AndroidRuntime(25416): at android.view.ViewGroup.addView(ViewGroup.java:4495)
11-16 11:05:42.401: E/AndroidRuntime(25416): at android.view.ViewGroup.addView(ViewGroup.java:4436)
11-16 11:05:42.401: E/AndroidRuntime(25416): at android.view.ViewGroup.addView(ViewGroup.java:4409)
按照Log信息,是一个子View已经存在一个父View,必须先调用该子视图的父视图的 removeView() 方法。
这种情况通常出现在动态添加视图的情况下,出现这种错误的原因是一个子控件只允许存在一个父控件,而很多时候在动态添加视图的时候,我们不知道该子视图是否已存在父视图,当已存在的时候就会出现这个异常。