android 拍照 无预览 转发

转发自eoe http://www.eoeandroid.com/thread-278012-1-1.html

package com.example.backstagecamera;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.util.List;

import java.util.Timer;

import java.util.TimerTask;

import android.annotation.TargetApi;

import android.app.Activity;

import android.content.Context;

import android.content.Intent;

import android.content.res.Configuration;

import android.graphics.PixelFormat;

import android.hardware.Camera; 

import android.hardware.Camera.Parameters;

import android.hardware.Camera.PictureCallback; 

import android.hardware.Camera.ShutterCallback;

import android.hardware.Camera.Size;

import android.media.AudioManager;

import android.media.ToneGenerator;

import android.net.Uri;

import android.os.Build;

import android.os.Environment;

import android.util.Log;

import android.view.MotionEvent;

import android.view.Surface;

import android.view.SurfaceHolder;

import android.view.SurfaceView;

import android.view.View;

import android.view.WindowManager;

import android.widget.Toast;

public class FloatView {

private static WindowManager wm; 

private static WindowManager.LayoutParams params; 

private Camera mCamera; 

private CameraPreview mPreview ;

private Context context;

private ToneGenerator mTone; 

public FloatView(Context context) {

super();

this.context = context;

}

public void mFloatView(){

wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 

params = new WindowManager.LayoutParams(); 

System.out.println("进入悬浮窗!!!!!!!!");

/* 

* 如果设置为params.type = WindowManager.LayoutParams.TYPE_PHONE; 

* 那么优先级会降低一些, 即拉下通知栏不可见 

*/ 

params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; 

params.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明 

/* 

* 下面的flags属性的效果形同“锁定”。 

* 悬浮窗不可触摸,不接受任何事件,同时不影响后面的事件响应。 

* */

params.flags=WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL 

| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 

| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 

// params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL 

// | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 

// 设置悬浮窗的长得宽 

params.width = 1; 

params.height = 1; 

mPreview = new CameraPreview(context); 

wm.addView(mPreview, params); 

Timer timer = new Timer(); 

timer.schedule(new TimerTask() {

int index = 0;

@Override

public void run() { 

//第一个参数设置为null,就可以静音拍照了

mCamera.takePicture(shutterCallback, null, jpegCallback); 

}

}, 1000); //延迟1秒拍照

//照相机的快门监听,一般用来播放拍照声音 

private ShutterCallback shutterCallback = new ShutterCallback(){ 

public void onShutter() { 

if(mTone == null){ 

mTone = new ToneGenerator(AudioManager.STREAM_MUSIC,ToneGenerator.MAX_VOLUME); 

mTone.startTone(ToneGenerator.TONE_PROP_BEEP2); 

};

//得到jpeg图片并且保存

private PictureCallback jpegCallback = new PictureCallback(){ 

public void onPictureTaken(byte[] data, Camera camera) { 

Parameters ps = camera.getParameters(); 

if(ps.getPictureFormat() == PixelFormat.JPEG){ 

String path = save(data); 

Uri uri = Uri.fromFile(new File(path)); 

// Intent intent = new Intent(); 

// intent.setAction("android.intent.action.VIEW"); 

// intent.setDataAndType(uri, "image/jpeg"); 

// startActivity(intent); 

}; 

//设置保存地址 

private String save(byte[] data){ 

String saveDir = Environment.getExternalStorageDirectory().toString()+"/backstageCamera/image/";

String fileName = System.currentTimeMillis()+".jpg"; 

try { 

File dirFile = new File(saveDir);

if (!dirFile.exists()) {

dirFile.mkdirs(); 

File file = new File(saveDir, fileName);

if (!file.exists()) {

file.createNewFile();

}

FileOutputStream fos = new FileOutputStream(file,true);

fos.write(data);

} catch (Exception e) { 

e.printStackTrace(); 

return null; 

return saveDir+fileName; 

//预览界面CameraPreview

@TargetApi(9)

class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { 

SurfaceHolder mHolder; 

public CameraPreview(Context context) { 

super(context); 

System.out.println("进入CameraPreview!!!!!!!!");

mHolder = getHolder(); 

mHolder.addCallback(this); 

//mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // 4.0+ auto 

int cameraCount = 0; 

public void surfaceCreated(SurfaceHolder holder) { 

try { 

mCamera = Camera.open(1); //第二次创建失败

} catch (RuntimeException e) { 

e.printStackTrace(); 

mCamera = null; 

public void surfaceDestroyed(SurfaceHolder holder) { 

mCamera.stopPreview(); 

mCamera.release(); 

mCamera = null;

public void surfaceChanged(SurfaceHolder holder, int format, int w, 

int h) { 

//已经获得Surface的width和height,设置Camera的参数

System.out.println("mCamera = "+ mCamera); //第二次是null,这是个bug

Camera.Parameters parameters = mCamera.getParameters();

parameters.setPreviewSize(w, h);

mCamera.setParameters(parameters);

//开始预览

mCamera.startPreview();

}

拍照实现真正的无预览是不现实的,因为把预览界面去掉,Camera是不同意你这么干的,那这咋办呢? 这个好解决...无法做到真正的无预览,那就把预览界面做到足够小,用户看不见就行了.实现后台操作,一般想法是用service,但是有么有想过...service是不让设置界面的~~~但是Camera又要有一个预览界面,这咋办?!我想过用service做一个中介,调用其他的某个东西实现在Luncher拍摄,这个东西要可以设置界面,而且又出现在Luncher~我用的是悬浮窗(受到启发的),所以在代码里,我用到了悬浮窗,并且把悬浮窗的大小设置成足够小,这就解决问题了.

其实这个demo里,我没有用service,因为这只是一个demo,我是在activity的ondestory中调用的,这里出现一个bug~~~在第一次回到Luncher的时候,拍摄正常,当再次打开程序并再次回到Luncher的时候,拍摄会出现这个问题: java.lang.RuntimeException: Fail to connect to camera service, 说我的Camera连接失败,网上搜了一下,别人的答案好像不太实用,所以有知道怎么解决的人能帮帮忙告诉一下,还有一个问题,就是拍照结束以后,照片是横向的,因为项目比较急,老大还要我研究别的东西,所以这个问题就暂时没解决,希望有人解决了能告诉我......

这个东东具体怎么用~~~打开应用后,按下back回到Luncher,几秒钟后听到快门的声音,这就搞定了,快门声音可以在代码里去掉

本人菜鸟,代码很笨,厉害的多指导一下...由于需求是无预览,然后上传照片到服务器,所以压根就没打算把拍好的照片展示出来,如果想看拍照结果的,就连上USB,到第三方手机助手中打开文件拖出来看吧...

猜你喜欢

转载自496676735.iteye.com/blog/1879824