前天经理交给我一个任务,需求是在一个应用中获取摄像头的数据传递到另外一个应用中使用,生成图片。原理是运用android进程之间的通信AIDL技术,传递分辨率,图片的格式N21,摄像头传递的每一帧的图片大小都是固定的,计算方式为宽*高*单位像素字节,把每一帧图片放入共享内存,在客户端中读取共享内存数据,那么怎么保证一边写一边读,读完之后在写,写完之后在读,这样一步一步进行呢,用锁机制肯定是不行的,因为这属于不同进程了,经理牛人告诉我,用内存中第一位做标志位,默认为0代表可以写,1代表可以读,这样相互标志位的变化,就保障了流程的运行,最后在拿到摄像头数据之后,怎么把它显示出来呢,直接上代码


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) { 

 
new
 
new
 
bmp = BitmapFactory. 
 decodeByteArray(stream.toByteArray(), 0, stream.size()); 

 

       stream.close(); 

 

  }



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




如何操作MemoryFile呢,上代码


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

              e.printStackTrace(); 

 

          } 

 
return null; 

 

      } 

 
 
 
 
public static MemoryFile openMemoryFile(ParcelFileDescriptor pfd, 
 int length, 
  int
 
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
 
null; 

 
try
 
new MemoryFile( 
 "tem", 1); 

 

              memoryFile.close(); 

 
class; 

 
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]; 

 

                  } 

 

              } 

 
setField( 
 "android.os.MemoryFile", memoryFile, 
 "mFD", fd); 

 
setField( 
 "android.os.MemoryFile", memoryFile, 
 "mLength", length); 

 
long address = ( 
 long) ReflectUtil. 
 invokeMethod( 
 null, native_mmap, fd, length, mode); 

 
setField( 
 "android.os.MemoryFile", memoryFile, 
 "mAddress", address); 

 
catch
 

              e.printStackTrace(); 

 

          } 

 
return
 

      } 

 
 
 
 
/** 
      * 获取memoryFile的ParcelFileDescriptor 
      * 
      * 
 @param 
  memoryFile 
 描述一块共享内存 
      * 
 @return 
  ParcelFileDescriptor 
      */ 
     
 public static
 
if (memoryFile == 
  null) { 

 
throw new IllegalArgumentException( 
 "memoryFile 不能为空"); 

 

          } 

 

          ParcelFileDescriptor pfd; 

 
getFileDescriptor(memoryFile); 

 
getInstance( 
 "android.os.ParcelFileDescriptor", fd); 

 
return
 

      } 

 
 
 
 
/** 
      * 获取memoryFile的FileDescriptor 
      * 
      * 
 @param 
  memoryFile 
 描述一块共享内存 
      * 
 @return 
  这块共享内存对应的文件描述符 
      */ 
     
 public static
 
if (memoryFile == 
  null) { 

 
throw new IllegalArgumentException( 
 "memoryFile 不能为空"); 

 

          } 

 

          FileDescriptor fd; 

 
invoke( 
 "android.os.MemoryFile", memoryFile, 
 "getFileDescriptor"); 

 
return
 

      } 

 
 
 
 
 
 
 
 
 
 
 
 
 
package
 
 
 
 
import
 
import
 
import
 
 
 
 
/** 
 * Created by ethanzhang on 2017/5/10. 
 */
 
/** 
 * 反射工具类 
 * Created by wuzr on 2016/6/27. 
  */ 
 public class
 
 
 
 
/** 
      * 根据类名,参数实例化对象 
      * 
      * 
 @param 
  className 
 类的路径全名 
      * 
 @param 
  params    
 构造函数需要的参数 
      * 
 @return 
  返回T类型的一个对象 
      */ 
     
 public static
 
if (className == 
  null || className.equals( 
 "")) { 

 
throw new IllegalArgumentException( 
 "className 不能为空"); 

 

          } 

 
try
 
forName(className); 

 
if (params != 
  null) { 

 
int plength = params. 
 length; 

 
new
 
for ( 
 int
 

                      paramsTypes[i] = params[i].getClass(); 

 

                  } 

 

                  Constructor constructor = c.getDeclaredConstructor(paramsTypes); 

 
true); 

 
return
 

              } 

 

              Constructor constructor = c.getDeclaredConstructor(); 

 
true); 

 
return
 
catch
 

              e.printStackTrace(); 

 

          } 

 
return null; 

 

      } 

 
 
 
 
/** 
      * 执行instance的方法 
      * 
      * 
 @param 
  className  
 类的全名 
      * 
 @param 
  instance   
 对应的对象,为null时执行类的静态方法 
      * 
 @param 
  methodName 
 方法名称 
      * 
 @param 
  params     
 参数 
      */ 
     
 public static
 
if (className == 
  null || className.equals( 
 "")) { 

 
throw new IllegalArgumentException( 
 "className 不能为空"); 

 

          } 

 
if (methodName == 
  null || methodName.equals( 
 "")) { 

 
throw new IllegalArgumentException( 
 "methodName不能为空"); 

 

          } 

 
try
 
forName(className); 

 
if (params != 
  null) { 

 
int plength = params. 
 length; 

 
new
 
for ( 
 int
 

                      paramsTypes[i] = params[i].getClass(); 

 

                  } 

 

                  Method method = c.getDeclaredMethod(methodName, paramsTypes); 

 
true); 

 
return
 

              } 

 

              Method method = c.getDeclaredMethod(methodName); 

 
true); 

 
return
 
catch
 

              e.printStackTrace(); 

 

          } 

 
return null; 

 

      } 

 
 
 
 
/** 
      * 执行指定的对方法 
      * 
      * 
 @param 
  instance 
 需要执行该方法的对象,为空时,执行静态方法 
      * 
 @param 
  m        
 需要执行的方法对象 
      * 
 @param 
  params   
 方法对应的参数 
      * 
 @return 
  方法m执行的返回值 
      */ 
     
 public static
 
if (m == 
  null) { 

 
throw new IllegalArgumentException( 
 "method 不能为空"); 

 

          } 

 
true); 

 
try
 
return
 
catch
 

              e.printStackTrace(); 

 

          } 

 
return null; 

 

      } 

 
 
 
 
/** 
      * 取得属性值 
      * 
      * 
 @param 
  className 
 类的全名 
      * 
 @param 
  fieldName 
 属性名 
      * 
 @param 
  instance  
 对应的对象,为null时取静态变量 
      * 
 @return 
  属性对应的值 
      */ 
     
 public static
 
if (className == 
  null || className.equals( 
 "")) { 

 
throw new IllegalArgumentException( 
 "className 不能为空"); 

 

          } 

 
if (fieldName == 
  null || fieldName.equals( 
 "")) { 

 
throw new IllegalArgumentException( 
 "fieldName 不能为空"); 

 

          } 

 
try
 
forName(className); 

 

              Field field = c.getDeclaredField(fieldName); 

 
true); 

 
return
 
catch
 

              e.printStackTrace(); 

 

          } 

 
return null; 

 

      } 

 
 
 
 
/** 
      * 设置属性 
      * 
      * 
 @param 
  className 
 类的全名 
      * 
 @param 
  fieldName 
 属性名 
      * 
 @param 
  instance  
 对应的对象,为null时改变的是静态变量 
      * 
 @param 
  value     
 值 
      */ 
     
 public static void
 
if (className == 
  null || className.equals( 
 "")) { 

 
throw new IllegalArgumentException( 
 "className 不能为空"); 

 

          } 

 
if (fieldName == 
  null || fieldName.equals( 
 "")) { 

 
throw new IllegalArgumentException( 
 "fieldName 不能为空"); 

 

          } 

 
try
 
forName(className); 

 

              Field field = c.getDeclaredField(fieldName); 

 
true); 

 

              field.set(instance, value); 

 
catch
 

              e.printStackTrace(); 

 

          } 

 

      } 

 
 
 
 
/** 
      * 根据方法名,类名,参数获取方法 
      * 
      * 
 @param 
  className  
 类名,全名称 
      * 
 @param 
  methodName 
 方法名 
      * 
 @param 
  paramsType 
 参数类型列表 
      * 
 @return 
  方法对象 
      */ 
     
 public static
 
if (className == 
  null || className.equals( 
 "")) { 

 
throw new IllegalArgumentException( 
 "className 不能为空"); 

 

          } 

 
if (methodName == 
  null || methodName.equals( 
 "")) { 

 
throw new IllegalArgumentException( 
 "methodName不能为空"); 

 

          } 

 
try
 
forName(className); 

 
return
 
catch
 

              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
 

                      e.printStackTrace(); 

 

                  } 

 

              } 

 

          } 

 
catch
 

          e.printStackTrace(); 

 

      }