梅明子 2016-08-26 03:13 采纳率: 100%
浏览 2265
已采纳

Android 序列化Intent对象到本地异常问题

        // 序列化PendingIntent对象,以时间作为文件名
        String fileName = String.valueOf(ent.date);
        PendingIntent intent = noti.contentIntent;

        L.e("recordNotification", "保存文件名:" + fileName);
        L.e("recordNotification", "PendingIntent:" + intent);
        ParcelableFileUtil.writeParcelable(mContext, fileName, intent);

        L.e("recordNotification", "保存通知并刷新界面");
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                NotificationWrapper.getInstance().addNotificationList(ent);
                NotificationWrapper.getInstance().refreshNotification();
            }
        };
        handler.post(runnable);

        // cancelNotification(packageName, sbn.getTag(), sbn.getId());

我这是从通知栏里获取到一个通知的Intent,然后我想把它序列化保存到本地,在方法writeParcelable中出现报错。但搞不懂不知为什么出错。

writeParcelable方法如下,执行到byte[] data = parcel.marshall();返回二进制字节这里就出下面那个错了。

     /**
     * 存储单个Parcelable对象
     * 
     * @param context
     * @param fileName
     * @param object
     * @return boolean
     */
    public static boolean writeParcelable(Context context, String fileName,
            Parcelable object) {
        if (fileName == null || object == null) {
            return false;
        }
        boolean success = false;
        FileOutputStream outPutStream = null;
        try {
            outPutStream = context.openFileOutput(fileName,
                    Context.MODE_PRIVATE);
            Parcel parcel = Parcel.obtain();
            parcel.writeParcelable(object,
                    Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
            byte[] data = parcel.marshall();
            outPutStream.write(data);
            success = true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            success = false;
        } catch (IOException e) {
            e.printStackTrace();
            success = false;
        } finally {
            if (outPutStream != null) {
                try {
                    outPutStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return success;
    }

错误日志截图:
图片说明

错误日志代码:

     08-26 03:07:38.023: E/onNotificationPosted(11563): packageName:com.example.notifications
    08-26 03:07:38.043: E/recordNotification(11563): 系统通知View
    08-26 03:07:38.113: E/Util(11563): saveBitmap:/storage/emulated/0/CleanMaster/notification_cache/IMG_20160826030738
    08-26 03:07:38.113: E/recordNotification(11563): 保存文件名:1472180858021
    08-26 03:07:38.113: E/recordNotification(11563): PendingIntent:PendingIntent{4238f680: android.os.BinderProxy@42355f30}
    08-26 03:07:38.113: W/NotificationListenerService[NotificationListener](11563): Error running onNotificationPosted
    08-26 03:07:38.113: W/NotificationListenerService[NotificationListener](11563): java.lang.RuntimeException: Tried to marshall a Parcel that contained Binder objects.
    08-26 03:07:38.113: W/NotificationListenerService[NotificationListener](11563):     at android.os.Parcel.nativeMarshall(Native Method)
    08-26 03:07:38.113: W/NotificationListenerService[NotificationListener](11563):     at android.os.Parcel.marshall(Parcel.java:420)
    08-26 03:07:38.113: W/NotificationListenerService[NotificationListener](11563):     at com.qiulong.notificationintercepttest.util.ParcelableFileUtil.writeParcelable(ParcelableFileUtil.java:36)
    08-26 03:07:38.113: W/NotificationListenerService[NotificationListener](11563):     at com.qiulong.notificationintercepttest.service.NotificationListener.getNotificationInfo(NotificationListener.java:125)
    08-26 03:07:38.113: W/NotificationListenerService[NotificationListener](11563):     at com.qiulong.notificationintercepttest.service.NotificationListener.onNotificationPosted(NotificationListener.java:58)
    08-26 03:07:38.113: W/NotificationListenerService[NotificationListener](11563):     at android.service.notification.NotificationListenerService$INotificationListenerWrapper.onNotificationPosted(NotificationListenerService.java:168)
    08-26 03:07:38.113: W/NotificationListenerService[NotificationListener](11563):     at android.service.notification.INotificationListener$Stub.onTransact(INotificationListener.java:56)
    08-26 03:07:38.113: W/NotificationListenerService[NotificationListener](11563):     at android.os.Binder.execTransact(Binder.java:404)
    08-26 03:07:38.113: W/NotificationListenerService[NotificationListener](11563):     at dalvik.system.NativeStart.run(Native Method)
  • 写回答

3条回答 默认 最新

  • FFZ2009 2016-08-26 08:34
    关注

    这个异常是说,parcel中含有Ibinder对象,因此Parcel中的数据不能被简单的序列化成字节流。
    这是由Parcel的设计和实现决定的。
    总的来说就是:使用Parcel.mashall把对象保存到本地文件是不允许的。
    Parcel的文档有这样的提示

    Parcel is not a general-purpose serialization mechanism. This class (and the corresponding Parcelable API for placing arbitrary objects into a Parcel) is designed as a high-performance IPC transport. As such, it is not appropriate to place any Parcel data in to persistent storage: changes in the underlying implementation of any of the data in the Parcel can render older data unreadable.

    大意是Parcel不是一般用途的序列化机制。这个类(和对应的Parcelable API )设计目的是作为一个高性能的IPC 数据传递机制。因此,不适合把任意的Parcel数据存到永久存储(比如本地文件)中:Parcel中的任何一种这样的数据的底层实现的改变会使老的数据不可读。

    另外Parcel.mashall的方法注释中提到

    The data you retrieve here** must no**t be placed in any kind of persistent storage (on local disk, across a network, etc). For that, you should use standard serialization or another kind of general serialization mechanism. The Parcel marshalled representation is highly optimized for local IPC, and as such does not attempt to maintain compatibility with data created in different versions of the platform.

    大意是从Parcel.mashall中得到的数据**不应该**被保存到任何一种永久存储中(例如,本地磁盘,跨网络)。 如果你想永久存储的话,需要用标准的的Serialization。Parcel 的marshall为本地IPC做了极大的优化,因此没有去维护数据的兼容性。

    要解决你碰到的异常就只能使用更为普通的序列化机制了。
    这里提供一个大概的思路就是用Java的 Serialization.
    当然Intent没有实现Serializable接口,这就得自己设计一个类,姑且叫SerializedIntent,实现Serializable接口,将你需要保存的属性作为成员放到SerializedIntent中,将SerializedIntent对象保存为本地文件。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 在若依框架下实现人脸识别
  • ¥15 网络科学导论,网络控制
  • ¥100 安卓tv程序连接SQLSERVER2008问题
  • ¥15 利用Sentinel-2和Landsat8做一个水库的长时序NDVI的对比,为什么Snetinel-2计算的结果最小值特别小,而Lansat8就很平均
  • ¥15 metadata提取的PDF元数据,如何转换为一个Excel
  • ¥15 关于arduino编程toCharArray()函数的使用
  • ¥100 vc++混合CEF采用CLR方式编译报错
  • ¥15 coze 的插件输入飞书多维表格 app_token 后一直显示错误,如何解决?
  • ¥15 vite+vue3+plyr播放本地public文件夹下视频无法加载
  • ¥15 c#逐行读取txt文本,但是每一行里面数据之间空格数量不同