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

什么是Android静默拍摄 Android静默拍摄app制作方法,第1张

概述引言:在做用户的头像时,忽然想到前段时间(可能是很久以前了),支付宝传出偷偷拍摄用户的生活照,真实头像,被喷的很厉害。然而作为Android开发者的我第一反应竟然是握草,他是怎么实现的。在我印象中,iOS对权限

引言:
在做用户的头像时,忽然想到前段时间(可能是很久以前了),支付宝传出偷偷拍摄用户的生活照,真实头像,被喷的很厉害。然而作为AndroID开发者的我第一反应竟然是握草,他是怎么实现的。在我印象中,iOS对权限的控制是很严格的,偷偷调起摄像头这种行为应该是很困难的。然而AndroID4.2之前可以说开发者几乎拥有了系统权限,能力之强简直可怕。而现在AndroID已经到了7.0,虽然大多说用户还是在4.4到6.0的。我想我也来做一个静默拍摄的app。

@H_301_4@正文:

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

一般的拍照都会有预览区域,拍照声。去掉这些东西才算是真正意义上的静默拍摄。
首先,做了一个非常正常的自拍软件,就一个按钮。拍完之后存到文件夹的一个位置。然后我试了一下,完全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,size.height),80,stream);      Bitmap bmp = BitmapFactory.decodeByteArray(stream.toByteArray(),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,bmp.getWIDth(),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,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,Toast.LENGTH_LONG).show();      } catch (Exception e) {        Toast.makeText(MainActivity.this,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,AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);    }  }  public voID scanfiletophotoAlbum(String path) {    MediaScannerConnection.scanfile(MainActivity.this,new String[] { path },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,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);  }}

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

@H_301_4@依旧存在的问题:

图片质量实在有点低。

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

总结

以上是内存溢出为你收集整理的什么是Android静默拍摄 Android静默拍摄app制作方法全部内容,希望文章能够帮你解决什么是Android静默拍摄 Android静默拍摄app制作方法所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1146564.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存