温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Android静默拍摄app制作方法是什么?

发布时间:2020-06-23 15:10:21 来源:亿速云 阅读:119 作者:清晨 栏目:移动开发

这篇文章将为大家详细讲解有关Android静默拍摄app制作方法是什么?,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。


所谓静默拍摄就是在用户毫无感知的情况下拍摄。

一般的拍照都会有预览区域,拍照声。去掉这些东西才算是真正意义上的静默拍摄。
首先,做了一个非常正常的自拍软件,就一个按钮。拍完之后存到文件夹的一个位置。然后我试了一下,完全ok并没有什么难度。然后就是清空surfaceView了。我首先想到的就是setVisiblity为gone,然后就报错了。很尴尬。下一个方案就是用高度和宽度都是0的方法,然而并没有什么卵用,更加尴尬。

然后想想没有有什么好办法了那就把这个surfaceView盖住好了,非常完美,随便搞一搞就盖住了,然后照片照样拍。合理。

但是“咔嚓”一声的拍照声实在令人尴尬,然后我就想到了静音,在页面打开的时候就设置静音。看上去这是一个非常稳健的方法,然后就发生了更加尴尬的事情。设置静音的时候,手机振动了一下,震一下也就算了,关键是还没有把拍照的声音去除。然后我就去查了查了相机音量应该是哪个。之后悲催的事情就发生了:

Google的Android开发者为了Android用户的用户体验,也为了避免开发者开发出静默拍摄的app从而侵犯了隐私,他们就把快门声音的播放函数写在了拍照的方法里面,还是写在framework层的。瞬间我就很难过了。作为一个平凡的第三方开发者,我并没有那么多权限去改变framework层的方法。

然后智慧的我决定曲线救国。因为在预览的时候,并没有进行拍照,但实际上我们已经拿到了相机带来的图片流。这很关键。然后我就把这个图片流变成了bitmap,然后保存到了本地,接着就把相机关了。神不知鬼不觉地把自拍拿到了。当然其中有一点小问题,比如图片编码,图片旋转,本地存储,获取帧图像都是各种各样的问题。但这些都是可以解决的。思路依旧是我上面提到的思路,各种表现方式可以由大家自己搞。

public class MainActivity extends AppCompatActivity {
 static final String TAG = "CAMERA ACTIVITY";

 //Camera object
 Camera mCamera;
 //Preview surface
 SurfaceView surfaceView;
 //Preview surface handle for callback
 SurfaceHolder surfaceHolder;
 //Camera button
 Button btnCapture;
 //Note if preview windows is on.
 boolean previewing;

 int mCurrentCamIndex = 0;
 private AudioManager manager;
 private int volumn;
 private boolean canTake=false;
 private ImageView imageView;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  btnCapture = (Button) findViewById(R.id.btn_capture);
  imageView =(ImageView)findViewById(R.id.iv);
  btnCapture.setOnClickListener(new Button.OnClickListener() {
   public void onClick(View arg0) {
    canTake=true;
   }
  });

  surfaceView = (SurfaceView) findViewById(R.id.surfaceView1);
  surfaceHolder = surfaceView.getHolder();
  surfaceHolder.addCallback(new SurfaceViewCallback());
  //surfaceHolder.addCallback(this);
  surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

 }

 public void getSurfacePic(byte[] data, Camera camera,String name){
  Camera.Size size = camera.getParameters().getPreviewSize();
  YuvImage image = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);
  if(image!=null){
   ByteArrayOutputStream stream = new ByteArrayOutputStream();
   image.compressToJpeg(new Rect(0, 0, size.width, size.height), 80, stream);

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

   //**********************
   //因为图片会放生旋转,因此要对图片进行旋转到和手机在一个方向上
   rotateMyBitmap(bmp,name);
   //**********************************


  }
 }

 /** 保存方法 */
 public void saveBitmap(Bitmap bm,String name) {
  Log.e(TAG, "保存图片");
  File f = new File("/sdcard/namecard/", name);
  if (f.exists()) {
   f.delete();
  }
  try {
   FileOutputStream out = new FileOutputStream(f);
   bm.compress(Bitmap.CompressFormat.PNG, 90, out);
   out.flush();
   out.close();
   Log.e(TAG, "已经保存");
  } catch (FileNotFoundException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }

 }

 /**
  * 保存图片到指定文件夹
  *
  * @param bmp
  * @return
  */
 private boolean saveBitmapTofile(byte[] bmp) {
  String fileName = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
    .toString()
    + File.separator
    + "PicTest_" + System.currentTimeMillis() + ".jpg";
  File file = new File(fileName);
  if (!file.getParentFile().exists()) {
   file.getParentFile().mkdir();
  }

  try {
   BufferedOutputStream bos = new BufferedOutputStream(
     new FileOutputStream(file));
   bos.write(bmp);
   bos.flush();
   bos.close();
   scanFileToPhotoAlbum(file.getAbsolutePath());
   Toast.makeText(MainActivity.this, "[Test] Photo take and store in" + file.toString(),Toast.LENGTH_LONG).show();
  } catch (Exception e) {
   Toast.makeText(MainActivity.this, "Picture Failed" + e.toString(),
     Toast.LENGTH_LONG).show();
  }
  return true;
 }

 public void saveMyBitmap(Bitmap mBitmap,String bitName) {
  String fileName = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
    .toString()
    + File.separator
    + "PicTest_" + System.currentTimeMillis() + ".jpg";
  File file = new File(fileName);
  if (!file.getParentFile().exists()) {
   file.getParentFile().mkdir();
  }
  FileOutputStream fOut = null;
  try {
   fOut = new FileOutputStream(file);
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  }

  try {
   if (null != fOut) {
    mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
    fOut.flush();
    fOut.close();
   }
  } catch (Exception e) {
   e.printStackTrace();
  }

 }

 public void rotateMyBitmap(Bitmap bmp,String name){
  //*****旋转一下
  Matrix matrix = new Matrix();
  matrix.postRotate(270);

  Bitmap bitmap = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.RGB_565);

  Bitmap nbmp2 = Bitmap.createBitmap(bmp, 0,0, bmp.getWidth(), bmp.getHeight(), matrix, true);

  saveMyBitmap(compressImage(nbmp2),"cool");

  //*******显示一下
  imageView.setImageBitmap(nbmp2);

 };
 /**
  * 压缩图片
  *
  * @param image
  * @return
  */
 public static Bitmap compressImage(Bitmap image) {
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  // 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
  image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
  // 把压缩后的数据baos存放到ByteArrayInputStream中
  ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
  // 把ByteArrayInputStream数据生成图片
  Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);
  return bitmap;
 }



 Camera.ShutterCallback shutterCallback = new Camera.ShutterCallback() {
  @Override
  public void onShutter() {
  }
 };

 Camera.PictureCallback rawPictureCallback = new Camera.PictureCallback() {
  @Override
  public void onPictureTaken(byte[] arg0, Camera arg1) {

  }
 };

 Camera.PictureCallback jpegPictureCallback = new Camera.PictureCallback() {
  @Override
  public void onPictureTaken(byte[] arg0, Camera arg1) {

   String fileName = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
     .toString()
     + File.separator
     + "PicTest_" + System.currentTimeMillis() + ".jpg";
   File file = new File(fileName);
   if (!file.getParentFile().exists()) {
    file.getParentFile().mkdir();
   }

   try {
    BufferedOutputStream bos = new BufferedOutputStream(
      new FileOutputStream(file));
    bos.write(arg0);
    bos.flush();
    bos.close();
    scanFileToPhotoAlbum(file.getAbsolutePath());
    Toast.makeText(MainActivity.this, "[Test] Photo take and store in" + file.toString(),Toast.LENGTH_LONG).show();
   } catch (Exception e) {
    Toast.makeText(MainActivity.this, "Picture Failed" + e.toString(),
      Toast.LENGTH_LONG).show();
   }
  };
 };

 public void setVolumnSilence(){
  manager = (AudioManager) this
    .getSystemService(Context.AUDIO_SERVICE);
  manager.setStreamMute(AudioManager.STREAM_SYSTEM, false);
  volumn = manager.getStreamVolume(AudioManager.STREAM_SYSTEM);
  if (volumn != 0) {
   // 如果需要静音并且当前未静音(muteMode的设置可以放在Preference中)
   manager.setStreamVolume(AudioManager.STREAM_SYSTEM, 0,
     AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
  }
 }

 public void scanFileToPhotoAlbum(String path) {

  MediaScannerConnection.scanFile(MainActivity.this,
    new String[] { path }, null,
    new MediaScannerConnection.OnScanCompletedListener() {

     public void onScanCompleted(String path, Uri uri) {
      Log.i("TAG", "Finished scanning " + path);
     }
    });
 }

 public void cameraRefresh(String picPath) {
  Toast.makeText(this,picPath,Toast.LENGTH_SHORT).show();
 }

 private final class SurfaceViewCallback implements android.view.SurfaceHolder.Callback {
  public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3)
  {
   if (previewing) {
    mCamera.stopPreview();
    previewing = false;
   }

   try {
    mCamera.setPreviewDisplay(arg0);
    mCamera.startPreview();
    previewing = true;
    setCameraDisplayOrientation(MainActivity.this, mCurrentCamIndex, mCamera);
   } catch (Exception e) {}
  }
  public void surfaceCreated(SurfaceHolder holder) {
//    mCamera = Camera.open();
   //change to front camera
   mCamera = openFrontFacingCameraGingerbread();
   // get Camera parameters
   Camera.Parameters params = mCamera.getParameters();

   List<String> focusModes = params.getSupportedFocusModes();
   if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
    // Autofocus mode is supported
   }
   mCamera.setPreviewCallback(new Camera.PreviewCallback() {
    @Override
    public void onPreviewFrame(byte[] bytes, Camera camera) {
     Log.e("stuart","onPreviewFrame "+canTake);
     if(canTake) {
      getSurfacePic(bytes, camera, "hahahaah");
      canTake=false;
     }
    }
   });
  }

  public void surfaceDestroyed(SurfaceHolder holder) {
   mCamera.stopPreview();
   mCamera.release();
   mCamera = null;
   previewing = false;
  }


 }

 private Camera openFrontFacingCameraGingerbread() {
  int cameraCount = 0;
  Camera cam = null;
  Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
  cameraCount = Camera.getNumberOfCameras();

  for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
   Camera.getCameraInfo(camIdx, cameraInfo);
   if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
    try {
     cam = Camera.open(camIdx);
     mCurrentCamIndex = camIdx;
    } catch (RuntimeException e) {
     Log.e(TAG, "Camera failed to open: " + e.getLocalizedMessage());
    }
   }
  }

  return cam;
 }

 private static void setCameraDisplayOrientation(Activity activity, int cameraId, Camera camera)
 {
  Camera.CameraInfo info = new Camera.CameraInfo();
  Camera.getCameraInfo(cameraId, info);
  int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();

  //degrees the angle that the picture will be rotated clockwise. Valid values are 0, 90, 180, and 270.
  //The starting position is 0 (landscape).
  int degrees = 0;
  switch (rotation)
  {
   case Surface.ROTATION_0: degrees = 0; break;
   case Surface.ROTATION_90: degrees = 90; break;
   case Surface.ROTATION_180: degrees = 180; break;
   case Surface.ROTATION_270: degrees = 270; break;
  }
  int result;
  if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
  {
   result = (info.orientation + degrees) % 360;
   result = (360 - result) % 360; // compensate the mirror
  }
  else
  {
   // back-facing
   result = (info.orientation - degrees + 360) % 360;
  }
  camera.setDisplayOrientation(result);
 }
}

基本上呢,这一个代码就能实现简单的静默拍照了。

依旧存在的问题:

图片质量实在有点低。

目前来看这也是没有办法的,因为我只能取到surfaceView的帧图像,而显示在preview中的帧图像质量又是非常感人的。所以不得不说这真是没什么办法。

关于Android静默拍摄app制作方法是什么?就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI