Android Exception异常汇集【不定时更新】

2014-12-16 10:06

1.

android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity  context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
at android.app.ContextImpl.startActivity(ContextImpl.java:1161)
at android.app.ContextImpl.startActivity(ContextImpl.java:1148)

原因是:
  Context中有一个startActivity方法,Activity继承自Context,重载了startActivity方法。如果使用 Activity的startActivity方法,不会有任何限制,而如果使用Context的startActivity方法的话,就需要开启一个新的task,遇到上面那个异常的,都是因为使用了Context的startActivity方法。解决办法是,加一个flag。intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 


2.

FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS: 
如果调出的Activtivity只是一个功能片段,并没有实际的意义,也没有必要出现在长按Home键调出最近使用过的程序类表中,那么使用FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 
Intent intent = new Intent(this, TestActivity.class); 
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 
startActivity(intent); 

==========================================================================================

==========================================================================================

2015年01月12号

3.Android4.4.X版本,开启或关闭飞行模式时,报出异常:

E/AndroidRuntime( 2775): FATAL EXCEPTION: main
E/AndroidRuntime( 2775): Process: com.android.deskclock, PID: 2775
E/AndroidRuntime( 2775): java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.intent.action.AIRPLANE_MODE from pid=2775, uid=10057
E/AndroidRuntime( 2775):  at android.os.Parcel.readException(Parcel.java:1472)
E/AndroidRuntime( 2775):  at android.os.Parcel.readException(Parcel.java:1426)
E/AndroidRuntime( 2775):  at android.app.ActivityManagerProxy.broadcastIntent(ActivityManagerNative.java:2491)
E/AndroidRuntime( 2775):  at android.app.ContextImpl.sendBroadcast(ContextImpl.java:1243)
E/AndroidRuntime( 2775):  at android.content.ContextWrapper.sendBroadcast(ContextWrapper.java:365)
E/AndroidRuntime( 2775):  at com.android.deskclock.alarmclock.Alarms.closeAirplaneMode(Alarms.java:1863)
E/AndroidRuntime( 2775):  at com.android.deskclock.alarmclock.LockAlarmFullActivity$ControlAlarm.dismiss(LockAlarmFullActivity.java:955)
E/AndroidRuntime( 2775):  at com.android.deskclock.alarmclock.LockAlarmFullActivity$4.onTouch(LockAlarmFullActivity.java:617)
E/AndroidRuntime( 2775):  at android.view.View.dispatchTouchEvent(View.java:7780)
E/AndroidRuntime( 2775):  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2316)

虽然已经在AndroidManifest.xml声明了权限,但是依旧会报出异常。后查需要在AndroidManifest.xml 添加 android:sharedUserId="android.uid.system"

如果上面方法仍不奏效,那么可以使该apk的签名和平台保持一致。即使用源码平台默认签名对该apk进行重新签名,并push到 systen/app下面。那么操作Setttings表时就具有了系统权限。

==========================================================================================

==========================================================================================


2015年01月15日:

4.

Android平台继承SQLiteOpenHelper实现的CRUD操作,默认情况不允许数据库降级,否则显示会抛出异常:
throw new SQLiteException("Can't downgrade database from version " +oldVersion + " to " + newVersion);  

01-14 20:29:22.290: E/AndroidRuntime(2722): FATAL EXCEPTION: AsyncHandler
01-14 20:29:22.290: E/AndroidRuntime(2722): Process: com.android.deskclock, PID: 2722
01-14 20:29:22.290: E/AndroidRuntime(2722): android.database.sqlite.SQLiteException: Can't downgrade database from version 10 to 7
01-14 20:29:22.290: E/AndroidRuntime(2722): at android.database.sqlite.SQLiteOpenHelper.onDowngrade(SQLiteOpenHelper.java:361)
01-14 20:29:22.290: E/AndroidRuntime(2722): at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:255)


    /**
     * Called when the database needs to be downgraded. This is strictly similar to
     * {@link #onUpgrade} method, but is called whenever current version is newer than requested one.
     * However, this method is not abstract, so it is not mandatory for a customer to
     * implement it. If not overridden, default implementation will reject downgrade and
     * throws SQLiteException
     *
     * <p>
     * This method executes within a transaction.  If an exception is thrown, all changes
     * will automatically be rolled back.
     * </p>
     *
     * @param db The database.
     * @param oldVersion The old database version.
     * @param newVersion The new database version.
     */
    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        throw new SQLiteException("Can't downgrade database from version " +
                oldVersion + " to " + newVersion);
    }


当然可以复写父类方法允许数据库降级,前提是对数据库版本号毫不关心。因此通常不会去复写该方法,因为:
You should care about this "Database Version thing" if ever your database schema is ever going to change  

==========================================================================================

==========================================================================================


2015年01月26日:

5. WindowManager$BadTokenException: Unable to add window…is not valid; is your activity running?

01-26 11:20:07.365 11836 11836 E AndroidRuntime: Process: com.mediatek.schpwronoff, PID: 11836
01-26 11:20:07.365 11836 11836 E AndroidRuntime: android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@41f06b68 is not valid; is your activity running?
01-26 11:20:07.365 11836 11836 E AndroidRuntime: at android.view.ViewRootImpl.setView(ViewRootImpl.java:637)
01-26 11:20:07.365 11836 11836 E AndroidRuntime: at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:261)
01-26 11:20:07.365 11836 11836 E AndroidRuntime: at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
01-26 11:20:07.365 11836 11836 E AndroidRuntime: at android.app.Dialog.show(Dialog.java:329)
01-26 11:20:07.365 11836 11836 E AndroidRuntime: at android.app.Activity.showDialog(Activity.java:3182)
01-26 11:20:07.365 11836 11836 E AndroidRuntime: at android.app.Activity.showDialog(Activity.java:3132)
01-26 11:20:07.365 11836 11836 E AndroidRuntime: at com.mediatek.schpwronoff.ShutdownActivity$1.onTick(ShutdownActivity.java:93)
01-26 11:20:07.365 11836 11836 E AndroidRuntime: at android.os.CountDownTimer$1.handleMessage(CountDownTimer.java:124)
01-26 11:20:07.365 11836 11836 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:110)
01-26 11:20:07.365 11836 11836 E AndroidRuntime: at android.os.Looper.loop(Looper.java:193)
01-26 11:20:07.365 11836 11836 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:5332)
01-26 11:20:07.365 11836 11836 E AndroidRuntime: at java.lang.reflect.Method.invokeNative(Native Method)
01-26 11:20:07.365 11836 11836 E AndroidRuntime: at java.lang.reflect.Method.invoke(Method.java:515)
01-26 11:20:07.365 11836 11836 E AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:831)
01-26 11:20:07.365 11836 11836 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:647)
01-26 11:20:07.365 11836 11836 E AndroidRuntime: at dalvik.system.NativeStart.main(Native Method)

======================================================

FATAL EXCEPTION: main
 android.view.WindowManager$BadTokenException: Unable to add window -- token android.app.LocalActivityManager$LocalActivityRecord@4051c0e0 is not valid; is your activity running?
 at android.view.ViewRoot.setView(ViewRoot.java:558)
 at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
 at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
 at android.view.Window$LocalWindowManager.addView(Window.java:433)
 at android.app.Dialog.show(Dialog.java:265)
 at net.reecam.CameraSearch$3.onClick(CameraSearch.java:103)
 at android.view.View.performClick(View.java:2532)
 at android.view.View$PerformClick.run(View.java:9308)
 at android.os.Handler.handleCallback(Handler.java:587)
 at android.os.Handler.dispatchMessage(Handler.java:92)
 at android.os.Looper.loop(Looper.java:150)
 at android.app.ActivityThread.main(ActivityThread.java:4293)
 at java.lang.reflect.Method.invokeNative(Native Method)
 at java.lang.reflect.Method.invoke(Method.java:507)
 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
 at dalvik.system.NativeStart.main(Native Method)

问题原因:
看报错关键词提示: Unable to add window 、LocalActivityManager、is your activity running,再结合应用程序中用到了AcitivityGroup来管理子Activity这个环境,而报错的前提就是在子Activity上弹出ProgressDialog进度条会话框,提示如上报错提示。就是说不能在子Activity上添加此窗口,LocalActivityManager$LocalActivityRecord@4051c0e0 is not valid就是说当前Activity管理器中此4051c0e0代表的Acitivity是无效的,也就是网上资料所说找不到它依附的Acitivity。

解决办法:
将new DialogToast(this);
改为:
new DialogToast(getParent());
就OK了。


是由于有activity时依附于另一个activity的,当被依附的activity产生错误的时候,该activity没有了靠山而产生错误(或者是调用了一个已经被finish()的activity)。一般在创建alertdialog.builder是很容易见到。

对于这个错误还没有根本的解决办法,唯一的办法就是改变该activity依附于另一activity的事实,将其放入另一activity。


Android利用ActivityGroup加载子Activity,子Activity调用对话框,弹出:

ERROR/AndroidRuntime(10104): Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token android.app.LocalActivityManager$LocalActivityRecord@45a58ee0 is not valid; is your activity running?

 

原因分析:

因为new对话框的时候,参数content 指定成了this,即指向当前子Activity的content。但子Activity是动态创建的,不能保证一直存在。其父Activity的content是稳定存在的,所以有下面的解决办法。

 

解决办法: 

将content替换为getParent()即可。 

==========================================================================================

==========================================================================================


2015年01月27

6.android.os.BadParcelableException: ClassNotFoundException when unmarshalling:解决办法

例如在用AlarmManager的时候

 

复制代码
复制代码
 1 AlarmManager alarmMgr = (AlarmManager) mContext
 2                 .getSystemService(Context.ALARM_SERVICE);
 3         Intent intent = new Intent(ALARM_ALERT);
 4        // intent.setExtrasClassLoader(DBTask.class.getClassLoader());
 5         Bundle mBundle=new Bundle(); 
 6         mBundle.putParcelable(AlarmMeReceiver.DB_TASK_KEY,task); 
 7         intent.putExtras(mBundle); 
 8         int id=Integer.valueOf(task.id);
 9         PendingIntent pendIntent = PendingIntent.getBroadcast(
10                 mContext.getApplicationContext(), id, intent,
11                 PendingIntent.FLAG_UPDATE_CURRENT);
12         long triggerAtTime = task.time;
13         alarmMgr.set(AlarmManager.RTC_WAKEUP , triggerAtTime, pendIntent);
复制代码
复制代码

 通过第6行 intent传提一个Parcelable对象 (Parcelable里面没有问题)

android.os.BadParcelableException: ClassNotFoundException when unmarshalling错误可以加上

intent.setExtrasClassLoader(DBTask.class.getClassLoader());

 

原因是android.platform.frameworks.base/core/java/android/content/Intent.java

复制代码
复制代码
5052             try {
5053                 Bundle newb = new Bundle(other.mExtras);
5054                 newb.putAll(mExtras);
5055                 mExtras = newb;
5056             } catch (RuntimeException e) {
5057                 // Modifying the extras can cause us to unparcel the contents
5058                 // of the bundle, and if we do this in the system process that
5059                 // may fail.  We really should handle this (i.e., the Bundle
5060                 // impl shouldn't be on top of a plain map), but for now just
5061                 // ignore it and keep the original contents. :(
5062                 Log.w("Intent", "Failure filling in extras", e);
5063             }
复制代码
复制代码

 

 

 android 中自定义的对象序列化的问题有两个选择一个是Parcelable,另外一个是Serializable。

一 序列化原因:

1.永久性保存对象,保存对象的字节序列到本地文件中;
2.通过序列化对象在网络中传递对象;
3.通过序列化在进程间传递对象。 

二 至于选取哪种可参考下面的原则:

1.在使用内存的时候,Parcelable 类比Serializable性能高,所以推荐使用Parcelable类。
2.Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。
3.Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点, 也不提倡用,但在这种情况下,还是建议你用Serializable 。


==============================================================================================================

android.os.BadParcelableException: ClassNotFoundException when unmarshalling

本文主要分析android.os.BadParcelableException: ClassNotFoundException when unmarshalling这个异常的原因及解决方法,解释了android的class loader.

 

一、现象:
应用打开,home键到后台,过一段时间打开,偶现fc,log如下:

程序中的写法是

报错的语句即为config = in.readParcelable(null);

 

二、原因分析:
根据android文档介绍:
readParcelable (ClassLoader loader)
loader A ClassLoader from which to instantiate the Parcelable object, or null for the default class loader.
即loader为空时系统会采取默认的class loader。

 

Android有两种不同的classloaders:framework classloader和apk classloader,其中framework classloader知道怎么加载android classes,apk classloader知道怎么加载you code,apk classloader继承自framework classloader,所以也知道怎么加载android classes。

 

在应用刚启动时,默认class loader是apk classloader,但在系统内存不足应用被系统回收会再次启动,这个默认class loader会变为framework classloader了,所以对于自己的类会报ClassNotFoundException。

 

三、解决方法:
将config = in.readParcelable(null);改为config = in.readParcelable(Config.class.getClassLoader());
Config.class.getClassLoader()即为apk classloader, 其中Config.class可以改为你程序中自己写的任意类,因为他们同样指向apk loader
嘿嘿,试着改为config = in.readParcelable(Activity.class.getClassLoader());你会发现依然ClassNotFoundException因为Activity.class.getClassLoader()指向的是framework classloader

 

四、如何测试重现这个问题,方便测试呢:
重现这个问题即使的应用被系统回收,把设置->开发者选项->不保留活动开关打开,打开测试程序按home键,再打开测试程序就会执行到这句。

如果你是在onSaveInstanceState中保存
savedInstanceState.putParcelable(key, value),则需要设置Bundle的class loader,如下:
savedInstanceState.setClassLoader(getClass().getClassLoader());

 

PS:
(1)、readParcelableArray(ClassLoader loader), readParcelable, readArray,readArrayList, readBundle, readHashMap, readParcelable, readSparseArray, readValue, readList, readMap也有可能报上面的异常

 

相关博客:

关于Parcelable以及Parcelable和Serializable的区别的区别,可参考以前写的:http://www.cnblogs.com/trinea/archive/2012/11/09/2763213.html
参考:http://stackoverflow.com/questions/13997550/unmarshalling-errors-in-android-app-with-custom-parcelable-classes
http://developer.android.com/reference/android/os/Parcel.html#readParcelable(java.lang.ClassLoader



=========================================================================================

关于这个“Activity之间对象传递的两种方法(Serializable,Parcelable)”我是通过别人的博客里学习到的,引用自:http://blog.csdn.net/Android_Tutor/archive/2010/07/16/5740845.aspx

    本来是要直接附上Demo的,可惜这里面没找到加入本地文件的地方。大家需要的还是到作者那去看看吧。

 

首先,我这里主要说下Parcelable 的用法。

1、定义对象类,类实现Parcelable接口。且要实现Parcelable接口的几个必要方法。如我的Question类中的相关方法的实现:

private Question(Parcel in){
  question_title = ParcelUtils.readStringFromParcel(in);

  created_time = ParcelUtils.readStringFromParcel(in);
  question_id = in.readInt();

  creator_name = ParcelUtils.readStringFromParcel(in);
  answer_list = new Group<Answer>();
  int answerSize = in.readInt();
  for (int i = 0; i < answerSize; i++) {
     Answer answer = in.readParcelable(Answer.class.getClassLoader());     
     answer_list.add(answer);
   }

}

public static final Question.Creator<Question> CREATOR = new Parcelable.Creator<Question>() {
        public Question createFromParcel(Parcel in) {
            return new Question(in);
        }

        @Override
        public Question[] newArray(int size) {
            return new Question[size];
        }
};
 
@Override
public void writeToParcel(Parcel out, int flags) {

  ParcelUtils.writeStringToParcel(out, question_title);

  ParcelUtils.writeStringToParcel(out, created_time);
  out.writeInt(question_id);  

  ParcelUtils.writeStringToParcel(out, creator_name);  
  if (answer_list != null) {
            out.writeInt(answer_list.size());
            for (int i = 0; i < answer_list.size(); i++) {
                out.writeParcelable(answer_list.get(i), flags);
            }
  } else {
            out.writeInt(0);
  }
}

注意:

方法private Question(Parcel in){}和方法public void writeToParcel(Parcel out, int flags) {}中变量顺序是一致的,是一一对应的。其中,

       Question(Parcel in)是变量的存储;

       writeToParcel(Parcel out, int flags) 是变量的读取。

 

2、程序中的应用:

1)存储

     Intent intent = new Intent(Question1.this,Question2.class);
     Bundle bundle = new Bundle();
     bundle.putParcelable("question_objs", question);
     intent.putExtras(bundle);
     startActivity(intent);

2)提取
     Intent intent = getIntent();

     Question que = intent.getParcelableExtra("question_objs");

3)接下来就可以使用question对象了。

 

其次,在使用Parcelable的过程中,曾报异常:

Caused By:android.os.BadParcelableException: ClassNotFoundException when unmarshalling:

     at android.os.Parcel.readParcelable(Parcel.java )

该异常是由于,我在对象类得定义中,成员变量的读取和存储没有一一对应,导致成员变量赋值错误,从而导致上述异常,所以,在上述对象类的定义说明中加了“注意:



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值