应用之间的通信Aidl和共享内存块MemoryFile的使用

 前天经理交给我一个任务,需求是在一个应用中获取摄像头的数据传递到另外一个应用中使用,生成图片。原理是运用android进程之间的通信AIDL技术,传递分辨率,图片的格式N21,摄像头传递的每一帧的图片大小都是固定的,计算方式为宽*高*单位像素字节,把每一帧图片放入共享内存,在客户端中读取共享内存数据,那么怎么保证一边写一边读,读完之后在写,写完之后在读,这样一步一步进行呢,用锁机制肯定是不行的,因为这属于不同进程了,经理牛人告诉我,用内存中第一位做标志位,默认为0代表可以写,1代表可以读,这样相互标志位的变化,就保障了流程的运行,最后在拿到摄像头数据之后,怎么把它显示出来呢,直接上代码
YuvImage yuvImage = new YuvImage(readdata, ImageFormat. NV21, 1920, 1080, null);
//YuvImage yuvImage = new YuvImage(mBufferBean.mBuffer, ImageFormat.NV21, 1280, 720, null); // MyLog.d(TAG, "readShareBufferMsg yuvImage:" + yuvImage); if (yuvImage != null) {
     stream = new ByteArrayOutputStream();
     yuvImage.compressToJpeg( new Rect(0, 0, 1920, 1080), 80, stream);
     bmp = BitmapFactory. decodeByteArray(stream.toByteArray(), 0, stream.size());
     stream.close();
}

通过自带的YuvImage类,可以转换成bitmap显示出来。


如何操作MemoryFile呢,上代码
/** * Created by ethanzhang on 2017/5/10. */
import android.os.MemoryFile;
import android.os.ParcelFileDescriptor;

import java.io.FileDescriptor;
import java.io.IOException;
import java.lang.reflect.Method;

/** * 对memoryFile类的扩展 * 1.从memoryFile对象中获取FileDescriptor,ParcelFileDescriptor * 2.根据一个FileDescriptor和文件length实例化memoryFile对象 * Created by wuzr on 2016/7/16. */ public class MemoryFileHelper {
    /**      * 创建共享内存对象      *      * @param name   描述共享内存文件名称      * @param length 用于指定创建多大的共享内存对象      * @return MemoryFile 描述共享内存对象      */     public static MemoryFile createMemoryFile(String name, int length) {
        try {
            return new MemoryFile(name, length);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static MemoryFile openMemoryFile(ParcelFileDescriptor pfd, int length, int mode) {
        if (pfd == null) {
            throw new IllegalArgumentException( "ParcelFileDescriptor 不能为空");
        }
        FileDescriptor fd = pfd.getFileDescriptor();
        return openMemoryFile(fd, length, mode);
    }

    /**      * 打开共享内存,一般是一个地方创建了一块共享内存      * 另一个地方持有描述这块共享内存的文件描述符,调用      * 此方法即可获得一个描述那块共享内存的MemoryFile      * 对象      *      * @param fd     文件描述      * @param length 共享内存的大小      * @param mode   PROT_READ = 0x1只读方式打开,      *               PROT_WRITE = 0x2可写方式打开,      *               PROT_WRITE|PROT_READ可读可写方式打开      * @return MemoryFile      */     public static MemoryFile openMemoryFile(FileDescriptor fd, int length, int mode) {
        MemoryFile memoryFile = null;
        try {
            memoryFile = new MemoryFile( "tem", 1);
            memoryFile.close();
            Class<?> c = MemoryFile. class;
            Method native_mmap = null;
            Method[] ms = c.getDeclaredMethods();
            for ( int i = 0; ms != null && i < ms. length; i++) {
                if (ms[i].getName().equals( "native_mmap")) {
                    native_mmap = ms[i];
                }
            }
            ReflectUtil. setField( "android.os.MemoryFile", memoryFile, "mFD", fd);
            ReflectUtil. setField( "android.os.MemoryFile", memoryFile, "mLength", length);
            long address = ( long) ReflectUtil. invokeMethod( null, native_mmap, fd, length, mode);
            ReflectUtil. setField( "android.os.MemoryFile", memoryFile, "mAddress", address);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return memoryFile;
    }

    /**      * 获取memoryFile的ParcelFileDescriptor      *      * @param memoryFile 描述一块共享内存      * @return ParcelFileDescriptor      */     public static ParcelFileDescriptor getParcelFileDescriptor(MemoryFile memoryFile) {
        if (memoryFile == null) {
            throw new IllegalArgumentException( "memoryFile 不能为空");
        }
        ParcelFileDescriptor pfd;
        FileDescriptor fd = getFileDescriptor(memoryFile);
        pfd = (ParcelFileDescriptor) ReflectUtil. getInstance( "android.os.ParcelFileDescriptor", fd);
        return pfd;
    }

    /**      * 获取memoryFile的FileDescriptor      *      * @param memoryFile 描述一块共享内存      * @return 这块共享内存对应的文件描述符      */     public static FileDescriptor getFileDescriptor(MemoryFile memoryFile) {
        if (memoryFile == null) {
            throw new IllegalArgumentException( "memoryFile 不能为空");
        }
        FileDescriptor fd;
        fd = (FileDescriptor) ReflectUtil. invoke( "android.os.MemoryFile", memoryFile, "getFileDescriptor");
        return fd;
    }




package com.newsmy.stream;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/** * Created by ethanzhang on 2017/5/10. */
/** * 反射工具类 * Created by wuzr on 2016/6/27. */ public class ReflectUtil {

    /**      * 根据类名,参数实例化对象      *      * @param className 类的路径全名      * @param params    构造函数需要的参数      * @return 返回T类型的一个对象      */     public static Object getInstance(String className, Object... params) {
        if (className == null || className.equals( "")) {
            throw new IllegalArgumentException( "className 不能为空");
        }
        try {
            Class<?> c = Class. forName(className);
            if (params != null) {
                int plength = params. length;
                Class[] paramsTypes = new Class[plength];
                for ( int i = 0; i < plength; i++) {
                    paramsTypes[i] = params[i].getClass();
                }
                Constructor constructor = c.getDeclaredConstructor(paramsTypes);
                constructor.setAccessible( true);
                return constructor.newInstance(params);
            }
            Constructor constructor = c.getDeclaredConstructor();
            constructor.setAccessible( true);
            return constructor.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**      * 执行instance的方法      *      * @param className  类的全名      * @param instance   对应的对象,为null时执行类的静态方法      * @param methodName 方法名称      * @param params     参数      */     public static Object invoke(String className, Object instance, String methodName, Object... params) {
        if (className == null || className.equals( "")) {
            throw new IllegalArgumentException( "className 不能为空");
        }
        if (methodName == null || methodName.equals( "")) {
            throw new IllegalArgumentException( "methodName不能为空");
        }
        try {
            Class<?> c = Class. forName(className);
            if (params != null) {
                int plength = params. length;
                Class[] paramsTypes = new Class[plength];
                for ( int i = 0; i < plength; i++) {
                    paramsTypes[i] = params[i].getClass();
                }
                Method method = c.getDeclaredMethod(methodName, paramsTypes);
                method.setAccessible( true);
                return method.invoke(instance, params);
            }
            Method method = c.getDeclaredMethod(methodName);
            method.setAccessible( true);
            return method.invoke(instance);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**      * 执行指定的对方法      *      * @param instance 需要执行该方法的对象,为空时,执行静态方法      * @param m        需要执行的方法对象      * @param params   方法对应的参数      * @return 方法m执行的返回值      */     public static Object invokeMethod(Object instance, Method m, Object... params) {
        if (m == null) {
            throw new IllegalArgumentException( "method 不能为空");
        }
        m.setAccessible( true);
        try {
            return m.invoke(instance, params);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**      * 取得属性值      *      * @param className 类的全名      * @param fieldName 属性名      * @param instance  对应的对象,为null时取静态变量      * @return 属性对应的值      */     public static Object getField(String className, Object instance, String fieldName) {
        if (className == null || className.equals( "")) {
            throw new IllegalArgumentException( "className 不能为空");
        }
        if (fieldName == null || fieldName.equals( "")) {
            throw new IllegalArgumentException( "fieldName 不能为空");
        }
        try {
            Class c = Class. forName(className);
            Field field = c.getDeclaredField(fieldName);
            field.setAccessible( true);
            return field.get(instance);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**      * 设置属性      *      * @param className 类的全名      * @param fieldName 属性名      * @param instance  对应的对象,为null时改变的是静态变量      * @param value          */     public static void setField(String className, Object instance, String fieldName, Object value) {
        if (className == null || className.equals( "")) {
            throw new IllegalArgumentException( "className 不能为空");
        }
        if (fieldName == null || fieldName.equals( "")) {
            throw new IllegalArgumentException( "fieldName 不能为空");
        }
        try {
            Class<?> c = Class. forName(className);
            Field field = c.getDeclaredField(fieldName);
            field.setAccessible( true);
            field.set(instance, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**      * 根据方法名,类名,参数获取方法      *      * @param className  类名,全名称      * @param methodName 方法名      * @param paramsType 参数类型列表      * @return 方法对象      */     public static Method getMethod(String className, String methodName, Class... paramsType) {
        if (className == null || className.equals( "")) {
            throw new IllegalArgumentException( "className 不能为空");
        }
        if (methodName == null || methodName.equals( "")) {
            throw new IllegalArgumentException( "methodName不能为空");
        }
        try {
            Class<?> c = Class. forName(className);
            return c.getDeclaredMethod(methodName, paramsType);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}






怎么写入标志位:


while ( mStartVideo && mMemoryFile != null) {
    //读取第一个字节,为0可以写,为1可以读     byte[] buffer= new byte[1];
    try {
       mMemoryFile.readBytes(buffer,0,0,1);
        if(buffer[0]==0)
        {
            if( YUVQueue.size()>0)
            {
                mMemoryFile.writeBytes( new byte[]{1},0,0,1);
                byte[] input= YUVQueue.poll();
                try {
                    mMemoryFile.writeBytes(input,0,1,input. length);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    } 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值