我的编程空间,编程开发者的网络收藏夹
学习永远不晚

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

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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

引言:
在做用户的头像时,忽然想到前段时间(可能是很久以前了),支付宝传出偷偷拍摄用户的生活照,真实头像,被喷的很厉害。然而作为Android开发者的我第一反应竟然是握草,他是怎么实现的。在我印象中,iOS对权限的控制是很严格的,偷偷调起摄像头这种行为应该是很困难的。然而Android4.2之前可以说开发者几乎拥有了系统权限,能力之强简直可怕。而现在Android已经到了7.0,虽然大多说用户还是在4.4到6.0的。我想我也来做一个静默拍摄的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());
      /
  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();
    }
  }
  
  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){
    /
  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 仿微信图像拍摄和选择界面功能(代码分享)Android仿微信拍摄短视频Android 调用系统相机拍摄获取照片的两种方法实现实例Android实现相机拍摄、选择、图片裁剪功能Android开发仿扫一扫实现拍摄框内的照片功能Android实现返回拍摄的图片功能实例


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

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

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

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

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

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

这篇文章将为大家详细讲解有关Android静默拍摄app制作方法是什么?,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。所谓静默拍摄就是在用户毫无感知的情况下拍摄。一般的拍照都会有预览区域,拍照声。去掉这些
2023-05-31

android静默安装升级的方法是什么

在Android中,静默安装和升级应用程序的方法是使用命令行工具adb(Android Debug Bridge)。以下是在设备上执行静默安装和升级的步骤:1. 确保你的设备已连接到计算机上,并且已启用USB调试模式。2. 打开命令提示符或
2023-10-18

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录