国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 系統(tǒng) > Android > 正文

什么是Android靜默拍攝 Android靜默拍攝app制作方法

2019-10-23 18:33:55
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

引言:
在做用戶(hù)的頭像時(shí),忽然想到前段時(shí)間(可能是很久以前了),支付寶傳出偷偷拍攝用戶(hù)的生活照,真實(shí)頭像,被噴的很厲害。然而作為Android開(kāi)發(fā)者的我第一反應(yīng)竟然是握草,他是怎么實(shí)現(xiàn)的。在我印象中,iOS對(duì)權(quán)限的控制是很?chē)?yán)格的,偷偷調(diào)起攝像頭這種行為應(yīng)該是很困難的。然而Android4.2之前可以說(shuō)開(kāi)發(fā)者幾乎擁有了系統(tǒng)權(quán)限,能力之強(qiáng)簡(jiǎn)直可怕。而現(xiàn)在Android已經(jīng)到了7.0,雖然大多說(shuō)用戶(hù)還是在4.4到6.0的。我想我也來(lái)做一個(gè)靜默拍攝的app。

正文:

所謂靜默拍攝就是在用戶(hù)毫無(wú)感知的情況下拍攝。

一般的拍照都會(huì)有預(yù)覽區(qū)域,拍照聲。去掉這些東西才算是真正意義上的靜默拍攝。
首先,做了一個(gè)非常正常的自拍軟件,就一個(gè)按鈕。拍完之后存到文件夾的一個(gè)位置。然后我試了一下,完全ok并沒(méi)有什么難度。然后就是清空surfaceView了。我首先想到的就是setVisiblity為gone,然后就報(bào)錯(cuò)了。很尷尬。下一個(gè)方案就是用高度和寬度都是0的方法,然而并沒(méi)有什么卵用,更加尷尬。

然后想想沒(méi)有有什么好辦法了那就把這個(gè)surfaceView蓋住好了,非常完美,隨便搞一搞就蓋住了,然后照片照樣拍。合理。

但是“咔嚓”一聲的拍照聲實(shí)在令人尷尬,然后我就想到了靜音,在頁(yè)面打開(kāi)的時(shí)候就設(shè)置靜音。看上去這是一個(gè)非常穩(wěn)健的方法,然后就發(fā)生了更加尷尬的事情。設(shè)置靜音的時(shí)候,手機(jī)振動(dòng)了一下,震一下也就算了,關(guān)鍵是還沒(méi)有把拍照的聲音去除。然后我就去查了查了相機(jī)音量應(yīng)該是哪個(gè)。之后悲催的事情就發(fā)生了:

Google的Android開(kāi)發(fā)者為了Android用戶(hù)的用戶(hù)體驗(yàn),也為了避免開(kāi)發(fā)者開(kāi)發(fā)出靜默拍攝的app從而侵犯了隱私,他們就把快門(mén)聲音的播放函數(shù)寫(xiě)在了拍照的方法里面,還是寫(xiě)在framework層的。瞬間我就很難過(guò)了。作為一個(gè)平凡的第三方開(kāi)發(fā)者,我并沒(méi)有那么多權(quán)限去改變framework層的方法。

然后智慧的我決定曲線(xiàn)救國(guó)。因?yàn)樵陬A(yù)覽的時(shí)候,并沒(méi)有進(jìn)行拍照,但實(shí)際上我們已經(jīng)拿到了相機(jī)帶來(lái)的圖片流。這很關(guān)鍵。然后我就把這個(gè)圖片流變成了bitmap,然后保存到了本地,接著就把相機(jī)關(guān)了。神不知鬼不覺(jué)地把自拍拿到了。當(dāng)然其中有一點(diǎn)小問(wèn)題,比如圖片編碼,圖片旋轉(zhuǎn),本地存儲(chǔ),獲取幀圖像都是各種各樣的問(wèn)題。但這些都是可以解決的。思路依舊是我上面提到的思路,各種表現(xiàn)方式可以由大家自己搞。

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());      //**********************      //因?yàn)閳D片會(huì)放生旋轉(zhuǎn),因此要對(duì)圖片進(jìn)行旋轉(zhuǎn)到和手機(jī)在一個(gè)方向上      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, "已經(jīng)保存");    } 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){    //*****旋轉(zhuǎn)一下    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();    // 質(zhì)量壓縮方法,這里100表示不壓縮,把壓縮后的數(shù)據(jù)存放到baos中    image.compress(Bitmap.CompressFormat.JPEG, 100, baos);    // 把壓縮后的數(shù)據(jù)baos存放到ByteArrayInputStream中    ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());    // 把ByteArrayInputStream數(shù)據(jù)生成圖片    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) {      // 如果需要靜音并且當(dāng)前未靜音(muteMode的設(shè)置可以放在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);  }}

基本上呢,這一個(gè)代碼就能實(shí)現(xiàn)簡(jiǎn)單的靜默拍照了。

依舊存在的問(wèn)題:

圖片質(zhì)量實(shí)在有點(diǎn)低。

目前來(lái)看這也是沒(méi)有辦法的,因?yàn)槲抑荒苋〉絪urfaceView的幀圖像,而顯示在preview中的幀圖像質(zhì)量又是非常感人的。所以不得不說(shuō)這真是沒(méi)什么辦法。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持VEVB武林網(wǎng)。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到Android開(kāi)發(fā)頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 通海县| 望江县| 滁州市| 佛冈县| 剑阁县| 肥西县| 梨树县| 宁夏| 遂平县| 滁州市| 正蓝旗| 连南| 高淳县| 明水县| 乐业县| 睢宁县| 察雅县| 黄梅县| 沂水县| 开鲁县| 铁力市| 界首市| 龙门县| 静安区| 绍兴市| 蒙山县| 弥渡县| 山东省| 长沙县| 渑池县| 玛沁县| 离岛区| 弥勒县| 丹凤县| 宜阳县| 察雅县| 陵水| 阿尔山市| 鹤壁市| 嘉定区| 常州市|