這篇文章將為大家詳細講解有關(guān)Android靜默拍攝app制作方法是什么?,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

創(chuàng)新互聯(lián)建站是一家專注于網(wǎng)站建設(shè)、成都網(wǎng)站制作與策劃設(shè)計,城中網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)建站做網(wǎng)站,專注于網(wǎng)站建設(shè)十載,網(wǎng)設(shè)計領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:城中等地區(qū)。城中做網(wǎng)站價格咨詢:13518219792
所謂靜默拍攝就是在用戶毫無感知的情況下拍攝。
一般的拍照都會有預(yù)覽區(qū)域,拍照聲。去掉這些東西才算是真正意義上的靜默拍攝。
首先,做了一個非常正常的自拍軟件,就一個按鈕。拍完之后存到文件夾的一個位置。然后我試了一下,完全ok并沒有什么難度。然后就是清空surfaceView了。我首先想到的就是setVisiblity為gone,然后就報錯了。很尷尬。下一個方案就是用高度和寬度都是0的方法,然而并沒有什么卵用,更加尷尬。
然后想想沒有有什么好辦法了那就把這個surfaceView蓋住好了,非常完美,隨便搞一搞就蓋住了,然后照片照樣拍。合理。
但是“咔嚓”一聲的拍照聲實在令人尷尬,然后我就想到了靜音,在頁面打開的時候就設(shè)置靜音。看上去這是一個非常穩(wěn)健的方法,然后就發(fā)生了更加尷尬的事情。設(shè)置靜音的時候,手機振動了一下,震一下也就算了,關(guān)鍵是還沒有把拍照的聲音去除。然后我就去查了查了相機音量應(yīng)該是哪個。之后悲催的事情就發(fā)生了:
Google的Android開發(fā)者為了Android用戶的用戶體驗,也為了避免開發(fā)者開發(fā)出靜默拍攝的app從而侵犯了隱私,他們就把快門聲音的播放函數(shù)寫在了拍照的方法里面,還是寫在framework層的。瞬間我就很難過了。作為一個平凡的第三方開發(fā)者,我并沒有那么多權(quán)限去改變framework層的方法。
然后智慧的我決定曲線救國。因為在預(yù)覽的時候,并沒有進行拍照,但實際上我們已經(jīng)拿到了相機帶來的圖片流。這很關(guān)鍵。然后我就把這個圖片流變成了bitmap,然后保存到了本地,接著就把相機關(guān)了。神不知鬼不覺地把自拍拿到了。當(dāng)然其中有一點小問題,比如圖片編碼,圖片旋轉(zhuǎ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());
//**********************
//因為圖片會放生旋轉(zhuǎn),因此要對圖片進行旋轉(zhuǎn)到和手機在一個方向上
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);
}
}基本上呢,這一個代碼就能實現(xiàn)簡單的靜默拍照了。
依舊存在的問題:
圖片質(zhì)量實在有點低。
目前來看這也是沒有辦法的,因為我只能取到surfaceView的幀圖像,而顯示在preview中的幀圖像質(zhì)量又是非常感人的。所以不得不說這真是沒什么辦法。
關(guān)于Android靜默拍攝app制作方法是什么?就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
分享題目:Android靜默拍攝app制作方法是什么?
網(wǎng)頁地址:http://chinadenli.net/article12/gphdgc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站策劃、營銷型網(wǎng)站建設(shè)、動態(tài)網(wǎng)站、面包屑導(dǎo)航、微信小程序、全網(wǎng)營銷推廣
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)