Android 침묵 촬영 Android 침묵 촬영 앱 만 드 는 법 이란 무엇 인가
사용자 의 프로필 사진 을 만 들 때 갑자기 얼마 전(아마 오래전 일 것 이다)이 생각 났 다.알 리 페 이 는 몰래 사용자 의 생활 사진 을 찍 었 다 는 소문 이 나 서 실제 프로필 사진 이 심하게 뿌 려 졌 다.하지만 안 드 로 이 드 개발 자로 서 의 나의 첫 반응 은 풀 을 잡 는 것 이 었 다.그 가 어떻게 이 루어 졌 는 지.내 기억 에 iOS 는 권한 에 대한 통제 가 엄격 하 다.몰래 카 메 라 를 조정 하 는 것 은 어 려 울 것 이다.그러나 Android 4.2 이전에 개발 자 들 은 시스템 권한 을 거의 가지 고 있 었 고 능력 이 강해 서 정말 무 서 웠 다 고 할 수 있다.현재 안 드 로 이 드 는 7.0 에 이 르 렀 다.대부분 사용 자 는 4.4 에서 6.0 이 라 고 하지만.나 도 조용히 촬영 하 는 앱 을 만 들 고 싶다.
본문:
침묵 촬영 이란 사용자 가 감지 하지 못 한 상태 에서 촬영 하 는 것 이다.
보통 사진 은 미리 보기 구역,사진 소리 가 난다.이런 것들 을 없 애 야 진정한 의미 의 침묵 촬영 이 라 고 할 수 있다.
우선,매우 정상 적 인 셀 카 프로그램 을 만 들 었 는데 버튼 만 있 었 다.촬영 이 끝 난 후에 폴 더 의 한 위치 에 저장 합 니 다.그리고 해 봤 는데 전혀 ok 어렵 지 않 았 어 요.그리고 surfaceView 를 비 웠 습 니 다.내 가 먼저 생각 한 것 은 set Visibility 를 gone 이 라 고 생각 한 후에 잘못 보고 한 것 이다.어색해.다음 방안 은 높이 와 너 비 를 0 으로 하 는 방법 이지 만 알 이 별로 쓰 이지 않 아 더 어색 하 다.
그리고 방법 이 없 을 거 라 고 생각 했 어 요.그럼 이 surfaceView 를 덮 으 세 요.아주 완벽 해 요.대충 해 보고 덮 으 세 요.그리고 사진 은 그대로 찍 으 세 요.합리적이다.
그러나'찰 칵'하 는 소리와 함께 찍 는 소리 가 정말 어색 했다.그리고 나 서 나 는 음소 거 가 생각 나 페이지 가 열 릴 때 음소 거 를 설정 했다.매우 온건 한 방법 으로 보 였 고 더 난처 한 일이 벌 어 졌 다.음소 거 를 설정 할 때 휴대 전화 가 진동 을 일 으 켜 흔 들 리 면 그만 이지 만 관건 은 아직 사진 찍 는 소 리 를 제거 하지 않 았 다 는 것 이다.그래서 카메라 볼 륨 이 어떤 건 지 알 아 봤 어 요.그 러 자 슬 픈 일이 벌 어 졌 다.
구 글 의 안 드 로 이 드 개발 자 들 은 안 드 로 이 드 사용자 체험 을 위해 개발 자가 몰래 촬영 한 앱 을 개발 해 프라이버시 를 침해 하지 않도록 셔터 소리의 재생 함 수 를 사진 찍 는 방법 에 썼 는 지,프레임 워 크 층 에 썼 는 지 확인 했다.순간 나 는 괴 로 웠 다.평범한 제3자 개발 자로 서 저 는 프레임 워 크 층 을 바 꿀 수 있 는 권한 이 많 지 않 습 니 다.
그리고 지혜 로 운 나 는 곡선 을 그 려 나 라 를 구하 기로 했다.미리 보기 때 는 사진 을 찍 지 않 았 지만 실제로 카메라 가 가 져 온 그림 흐름 을 받 았 기 때문이다.이것 은 매우 중요 하 다.그리고 나 서 나 는 이 그림 을 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 에 표 시 된 프레임 이미지 의 질 은 매우 감동 적 이기 때문이다.그래서 어 쩔 수 없 이 어 쩔 수 없 었 어 요.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.