Android:跨进程传递bitmap图片

1. 问题描述:

       项目中有个需求是这样的,在A进程中处理了很多比较大的bitmap 对象,在某一点击事件要启动 并 将某个bitmap传递给 B进程(推流进程)作为推流引擎的背景图,这个bitmap 有可能比较大,因为要尽量保证清晰度,所以必然会涉及到跨进程传输大型bitmap 的问题。

2.方案

a.文件传输:保存到sdcard或是数据库(提供provider)。这这样会涉及到文件读写,文件超大时,效率就会比较低;

b.intent直接传输:intent只能传一定大小的数据,太大就会抛出异常。限制大小后,图片压缩,清晰度就达不到要求。

          i) intent.putExtra("big_bitmap", ((BitmapDrawable) bigDrawable).getBitmap()); 如下:

           

          图片太大,报错如下:

           

android.os.TransactionTooLargeException官方文档

 

         从上面可以看出:

          1,此异常发生在Binder IPC 调用的过程;

          2,客户端发送数据太大,或是返回数据太大, 都会发生该异常;

         3,binder的buffer缓冲区大小当前为1M,当前进程的所有调用共享;

        4,如果数据太大可以将数据分次传输。避免异常出现;

c. 通过binder。bundle.putBinder()可以完美解决上面的问题;

       首先向intent的bundle中放一个binder对象,启动组件后,读出intent的bundle中的binder对象,调用他的getBitmap()方法就可以获取到了;

下面是具体实现:

服务端:

1,定义 IRemoteBitMapInterface.aidl 文件

        

        

2,将binder放入intent;

      

  这样服务端就完成了。

客户端:

   1,将同样的aidl文件复制到客户端:

        

   2, 取出intent中的binder:

     

总结:

上面用到的还是binder机制:

aidl在编译器编译后会给我们生成基于binder机制的java文件,如下:

package com.xxxxx.launcher;
public interface IRemoteBitMapInterface extends android.os.IInterface {
    public static abstract class Stub extends android.os.Binder implements com.xxxxx.launcher.IRemoteBitMapInterface {
        private static final java.lang.String DESCRIPTOR = "com.xxxxx.launcher.IRemoteBitMapInterface";
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }
        public static com.xxxxx.launcher.IRemoteBitMapInterface asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.xxxxx.launcher.IRemoteBitMapInterface))) {
                return ((com.xxxxx.launcher.IRemoteBitMapInterface) iin);
            }
            return new com.xxxxx.launcher.IRemoteBitMapInterface.Stub.Proxy(obj);
        }
        @Override
        public android.os.IBinder asBinder() {
            return this;
        }
        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_getBitmap: {
                    data.enforceInterface(DESCRIPTOR);
                    android.graphics.Bitmap _result = this.getBitmap();
                    reply.writeNoException();
                    if ((_result != null)) {
                        reply.writeInt(1);
                        _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                    } else {
                        reply.writeInt(0);
                    }
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.xxxxx.launcher.IRemoteBitMapInterface {
            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }

            @Override
            public android.os.IBinder asBinder() {
                return mRemote;
            }

            public java.lang.String getInterfaceDescriptor() {
                return DESCRIPTOR;
            }

            @Override
            public android.graphics.Bitmap getBitmap() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                android.graphics.Bitmap _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_getBitmap, _data, _reply, 0);
                    _reply.readException();
                    if ((0 != _reply.readInt())) {
                        _result = android.graphics.Bitmap.CREATOR.createFromParcel(_reply);
                    } else {
                        _result = null;
                    }
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }

        static final int TRANSACTION_getBitmap = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    }

    public android.graphics.Bitmap getBitmap() throws android.os.RemoteException;
}

想继续深入了解,可以看下binder的机制。这里就不介绍了。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值