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

来源:互联网 发布:python难找工作 编辑:程序博客网 时间:2024/06/05 23:00
 前天经理交给我一个任务,需求是在一个应用中获取摄像头的数据传递到另外一个应用中使用,生成图片。原理是运用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();
    } 
原创粉丝点击