xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.windowdemo"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.example.windowdemo.MyService" >
</service>
</application>
</manifest>
====================================================================================
activity
package com.example.windowdemo;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 启动服务,在服务里开启悬浮窗
Intent intent = new Intent(MainActivity.this,MyService.class);
startService(intent);
finish();
}
});
}
}
============================================================================
service
package com.example.windowdemo;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.Service;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.PixelFormat;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.provider.Settings;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
public class MyService extends Service {
public static String TAG = "MyService";
/**
* 自定义窗口
*/
private MyWindow myWindow;
/**
* 窗口管理者
*/
private WindowManager mWindowManager;
/**
* 窗口布局参数
*/
private LayoutParams Params;
private Handler handler = new Handler() {
@SuppressLint("NewApi")
public void handleMessage(Message msg) {
if (isHome()) {
// 如果回到桌面,则显示悬浮窗
if (!myWindow.isAttachedToWindow()) {
mWindowManager.addView(myWindow, Params);
}
} else {
// 如果在非桌面,则去掉悬浮窗
if (myWindow.isAttachedToWindow()) {
myWindow.colseCamera();
mWindowManager.removeView(myWindow);
}
}
super.handleMessage(msg);
};
};
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@SuppressLint("NewApi")
@Override
public void onCreate() {
super.onCreate();
// 定时器类
Timer timer = new Timer();
timer.schedule(task, 1000, 1000); // 1s后执行task,经过1s再次执行
Log.i(TAG, "onCreate");
showWindow();
//对于6.0以上的设备
// if (Build.VERSION.SDK_INT >= 23) {
// //如果支持悬浮窗功能
// if (Settings.canDrawOverlays(getApplicationContext())) {
// showWindow();
// } else {
// //手动去开启悬浮窗
// Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// getApplicationContext().startActivity(intent);
// }
// } else {
// //6.0以下的设备直接开启
// showWindow();
// }
}
private void showWindow() {
Log.i(TAG, "showWindow1");
//创建MyWindow的实例
myWindow = new MyWindow(getApplicationContext());
//窗口管理者
mWindowManager = (WindowManager) getSystemService(Service.WINDOW_SERVICE);
//窗口布局参数
Params = new WindowManager.LayoutParams();
//布局坐标,以屏幕左上角为(0,0)
Params.x = 0;
Params.y = 0;
//布局类型
Params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; // 系统提示类型,重要
//布局flags
Params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; // 不能抢占聚焦点
Params.flags = Params.flags | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
Params.flags = Params.flags | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; // 排版不受限制
Params.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
//布局的gravity
Params.gravity = Gravity.LEFT | Gravity.TOP;
//布局的宽和高
Params.width = 400;
Params.height = 400;
myWindow.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
Params.x = (int) event.getRawX() - myWindow.getWidth() / 2;
Params.y = (int) event.getRawY() - myWindow.getHeight() / 2;
//更新布局位置
mWindowManager.updateViewLayout(myWindow, Params);
break;
}
return false;
}
});
}
//定时发送message给Handler
TimerTask task = new TimerTask() {
@Override
public void run() {
Message message = new Message();
handler.sendMessage(message);
}
};
/**
* @return 获取桌面(Launcher)的包名
*/
private List<String> getHomes() {
List<String> names = new ArrayList<String>();
PackageManager packageManager = this.getPackageManager();
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo info : resolveInfo) {
names.add(info.activityInfo.packageName);
}
return names;
}
/**
* @return 判断当前是否是桌面
*/
public boolean isHome() {
ActivityManager mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> rti = mActivityManager.getRunningTasks(1);
List<String> strs = getHomes();
if (strs != null && strs.size() > 0) {
return strs.contains(rti.get(0).topActivity.getPackageName());
} else {
return false;
}
}
}
=================================================================
view
package com.example.windowdemo;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.app.Service;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.os.Environment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.TextureView;
import android.view.TextureView.SurfaceTextureListener;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;
public class MyWindow extends LinearLayout implements SurfaceTextureListener {
public static String TAG = "MyWindow";
private TextureView textureView;
private SurfaceTexture mSurfaceTexture = null ;
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200;
/**
* 相机类
*/
private Camera myCamera;
private Context context;
private WindowManager mWindowManager;
public MyWindow(Context context) {
super(context);
LayoutInflater.from(context).inflate(R.layout.window, this);
this.context = context;
initView();
}
Button bt_open,bt2_pic,bt_colse;
private void initView() {
textureView = (TextureView) findViewById(R.id.textureView);
bt_open = (Button) findViewById(R.id.bt_open);
bt2_pic = (Button) findViewById(R.id.bt2_pic);
bt_colse = (Button) findViewById(R.id.bt_colse);
textureView.setSurfaceTextureListener(this);
mWindowManager = (WindowManager) context.getSystemService(Service.WINDOW_SERVICE);
bt_open.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
openCamera();
}
});
bt2_pic.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
myCamera.takePicture(null, null, mPicture);
}
});
bt_colse.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
colseCamera();
}
});
}
String cameraId;
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
// if (myCamera == null) {
// // 创建Camera实例
// myCamera = Camera.open(0);
// Log.i(TAG, "myCamera:"+myCamera);
// try {
// // 设置预览在textureView上
// myCamera.setPreviewTexture(surface);
// myCamera.setDisplayOrientation(SetDegree(MyWindow.this));
//
// // 开始预览
// myCamera.startPreview();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
Log.d(TAG,"onSurfaceTextureAvailable-width:"+width+"-height:"+height);
// int cameraFacing =CAMERA_FACING_FRONT;s
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
Camera.getCameraInfo(i, cameraInfo);
// if (cameraInfo.facing == cameraFacing) {
// cameraId = i;
// }
Log.d(TAG,"startCamera -cameraInfo.facing:"+cameraInfo.facing);
}
// // TtsUtils.systemOutPtintln("startCamera -isCameraCanUse-cameraId:"+cameraId);
Log.d(TAG,"startCamera -isCameraCanUse-cameraId:"+cameraId);
// mCamera = Camera.open(cameraId);
mSurfaceTexture = surface ;
myCamera = Camera.open();
Log.d(TAG,"startCamera -isCameraCanUse-myCamera:"+myCamera);
Log.d(TAG,"startCamera -isCameraCanUse-surface:"+surface);
if (myCamera != null) {
try {
myCamera.setPreviewTexture(surface);
myCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, e.getMessage());
}
}
}
private int SetDegree(MyWindow myWindow) {
// 获得手机的方向
int rotation = mWindowManager.getDefaultDisplay().getRotation();
int degree = 0;
// 根据手机的方向计算相机预览画面应该选择的角度
switch (rotation) {
case Surface.ROTATION_0:
degree = 90;
break;
case Surface.ROTATION_90:
degree = 0;
break;
case Surface.ROTATION_180:
degree = 270;
break;
case Surface.ROTATION_270:
degree = 180;
break;
}
return degree;
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
myCamera.stopPreview(); //停止预览
myCamera.release(); // 释放相机资源
myCamera = null;
return false;
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// int displayOrientation = getDisplayOrientation();
// myCamera.setDisplayOrientation(displayOrientation);
// List<Camera.Size> supportedPreviewSizes = myCamera.getParameters().getSupportedPreviewSizes();
// Camera.Size optimalPreviewSize = getOptimalPreviewSize(supportedPreviewSizes, width, height);
// myCamera.getParameters().setPictureSize(optimalPreviewSize.width, optimalPreviewSize.height);
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
public void colseCamera(){
if(myCamera != null ){
myCamera.stopPreview(); //停止预览
myCamera.release(); // 释放相机资源
myCamera = null;
}
}
public void openCamera(){
myCamera = Camera.open();
Log.d(TAG,"startCamera -isCameraCanUse-myCamera:"+myCamera);
Log.d(TAG,"startCamera -isCameraCanUse-surface:"+mSurfaceTexture);
if (myCamera != null) {
try {
myCamera.setPreviewTexture(mSurfaceTexture);
myCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, e.getMessage());
}
}
}
private PictureCallback mPicture = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null) {
Log.d(TAG,
"Error creating media file, check storage permissions: "
+ "e.getMessage()");
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
Log.d(TAG, "File ok getPath: " + pictureFile.getPath());
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
};
/** 为保存图片或视频创建File */
private static File getOutputMediaFile(int type) {
// 安全起见,在使用前应该
// 用Environment.getExternalStorageState()检查SD卡是否已装入
File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"MyCameraApp");
// 如果期望图片在应用程序卸载后还存在、且能被其它应用程序共享,
// 则此保存位置最合适
// 如果不存在的话,则创建存储目录
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("MyCameraApp", "failed to create directory");
return null;
}
Log.d("MyCameraApp", "failed to create directory");
}
// 创建媒体文件名
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
.format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "IMG_" + timeStamp + ".jpg");
} else if (type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "VID_" + timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
}
=====================================================================
main xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}" >
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="开启悬浮窗" />
</RelativeLayout>
view xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
<TextureView
android:id="@+id/textureView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal" >
<Button
android:id="@+id/bt_open"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#00ffff"
android:text="照相机"
android:layout_weight="1"
android:textSize="30sp" />
<Button
android:id="@+id/bt2_pic"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#00ffff"
android:layout_weight="1"
android:text="拍照"
android:textSize="30sp" />
<Button
android:id="@+id/bt_colse"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#00ffff"
android:layout_weight="1"
android:text="关闭"
android:textSize="30sp" />
</LinearLayout>
</LinearLayout>
======================================
探讨在打开摄像头预览时这两个方法的作用
关于:setPreviewCallbackWithBuffer()
Installs a callback to be invoked for every preview frame, using buffers supplied with addCallbackBuffer(byte[]), in addition to displaying them on the screen.
在摄像头开启时增加一个回调函数,在每一帧出现时调用.通过addCallbackBuffer(byte[])使用一个缓存容器来显示这些数据.
其实就是通过内存复用来提高预览的效率,但是如果没有调用这个方法addCallbackBuffer(byte[]),帧回调函数就不会被调用,也就是说在每一次回调函数调用后都必须调用addCallbackBuffer(byte[]).(所以可以直接在onPreviewFrame中调用addCallbackBuffer(byte[]),即camera.addCallbackBuffer(data);),复用这个原来的内存地址即可.
使用步骤:
1 在打开摄像头预览前先分配一个buffer地址
camera.setPreviewCallbackWithBuffer(h264Encoder);
camera.addCallbackBuffer(mPreviewSize.width* mPreviewSize.height*3 / 2);
camera.startPreview();
1
2
3
2 然后只用在onPreviewFrame中调用addCallbackBuffer(data)即可了,就可以一直复用原来开辟的那个内存空间了,视频数据data永远都只会保持在一个地址中,只是其中的内容在不断的变化
=======================
package com.example.windowdemo;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.app.Service;
import android.content.Context;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.PreviewCallback;
import android.os.Environment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.TextureView;
import android.view.TextureView.SurfaceTextureListener;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;
public class MyWindow extends LinearLayout implements SurfaceTextureListener{//PreviewCallback
public static String TAG = "MyWindow";
private TextureView textureView;
private SurfaceTexture mSurfaceTexture = null ;
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200;
/**
* 相机类
*/
private Camera myCamera;
private Context context;
private WindowManager mWindowManager;
public MyWindow(Context context) {
super(context);
LayoutInflater.from(context).inflate(R.layout.window, this);
this.context = context;
initView();
}
Button bt_open,bt2_pic,bt_colse;
private void initView() {
textureView = (TextureView) findViewById(R.id.textureView);
bt_open = (Button) findViewById(R.id.bt_open);
bt2_pic = (Button) findViewById(R.id.bt2_pic);
bt_colse = (Button) findViewById(R.id.bt_colse);
textureView.setSurfaceTextureListener(this);
mWindowManager = (WindowManager) context.getSystemService(Service.WINDOW_SERVICE);
bt_open.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
openCamera();
}
});
bt2_pic.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
myCamera.takePicture(null, null, mPicture);
}
});
bt_colse.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
colseCamera();
}
});
}
String cameraId;
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
// if (myCamera == null) {
// // 创建Camera实例
// myCamera = Camera.open(0);
// Log.i(TAG, "myCamera:"+myCamera);
// try {
// // 设置预览在textureView上
// myCamera.setPreviewTexture(surface);
// myCamera.setDisplayOrientation(SetDegree(MyWindow.this));
//
// // 开始预览
// myCamera.startPreview();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
Log.d(TAG,"onSurfaceTextureAvailable-width:"+width+"-height:"+height);
// int cameraFacing =CAMERA_FACING_FRONT;s
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
Camera.getCameraInfo(i, cameraInfo);
// if (cameraInfo.facing == cameraFacing) {
// cameraId = i;
// }
Log.d(TAG,"startCamera -cameraInfo.facing:"+cameraInfo.facing);
}
// // TtsUtils.systemOutPtintln("startCamera -isCameraCanUse-cameraId:"+cameraId);
Log.d(TAG,"startCamera -isCameraCanUse-cameraId:"+cameraId);
// mCamera = Camera.open(cameraId);
mSurfaceTexture = surface ;
myCamera = Camera.open();
Log.d(TAG,"startCamera -isCameraCanUse-myCamera:"+myCamera);
Log.d(TAG,"startCamera -isCameraCanUse-surface:"+surface);
if (myCamera != null) {
try {
//Callback buffer was too small! Expected 460800 bytes, but got 217200 bytes!
myCamera.addCallbackBuffer(new byte[((800 * 480) * 3) / 2] );
// myCamera.addCallbackBuffer(new byte[((800 * 480) * ImageFormat.getBitsPerPixel(ImageFormat.NV21)) / 8]);
myCamera.setPreviewCallbackWithBuffer(myPreviewCallback);
myCamera.setPreviewTexture(surface);
myCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, e.getMessage());
}
}
}
private int SetDegree(MyWindow myWindow) {
// 获得手机的方向
int rotation = mWindowManager.getDefaultDisplay().getRotation();
int degree = 0;
// 根据手机的方向计算相机预览画面应该选择的角度
switch (rotation) {
case Surface.ROTATION_0:
degree = 90;
break;
case Surface.ROTATION_90:
degree = 0;
break;
case Surface.ROTATION_180:
degree = 270;
break;
case Surface.ROTATION_270:
degree = 180;
break;
}
return degree;
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
myCamera.stopPreview(); //停止预览
myCamera.release(); // 释放相机资源
myCamera = null;
return false;
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// int displayOrientation = getDisplayOrientation();
// myCamera.setDisplayOrientation(displayOrientation);
// List<Camera.Size> supportedPreviewSizes = myCamera.getParameters().getSupportedPreviewSizes();
// Camera.Size optimalPreviewSize = getOptimalPreviewSize(supportedPreviewSizes, width, height);
// myCamera.getParameters().setPictureSize(optimalPreviewSize.width, optimalPreviewSize.height);
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
public void colseCamera(){
if(myCamera != null ){
myCamera.stopPreview(); //停止预览
myCamera.release(); // 释放相机资源
myCamera = null;
}
}
public void openCamera(){
myCamera = Camera.open();
Log.d(TAG,"startCamera -isCameraCanUse-myCamera:"+myCamera);
Log.d(TAG,"startCamera -isCameraCanUse-surface:"+mSurfaceTexture);
if (myCamera != null) {
try {
myCamera.setPreviewTexture(mSurfaceTexture);
myCamera.startPreview();
myCamera.setPreviewCallbackWithBuffer(myPreviewCallback);
} catch (Exception e) {
Log.d(TAG, e.getMessage());
}
}
}
private PictureCallback mPicture = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null) {
Log.d(TAG,
"Error creating media file, check storage permissions: "
+ "e.getMessage()");
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
Log.d(TAG, "File ok getPath: " + pictureFile.getPath());
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
};
/** 为保存图片或视频创建File */
private static File getOutputMediaFile(int type) {
// 安全起见,在使用前应该
// 用Environment.getExternalStorageState()检查SD卡是否已装入
File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"MyCameraApp");
// 如果期望图片在应用程序卸载后还存在、且能被其它应用程序共享,
// 则此保存位置最合适
// 如果不存在的话,则创建存储目录
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("MyCameraApp", "failed to create directory");
return null;
}
Log.d("MyCameraApp", "failed to create directory");
}
// 创建媒体文件名
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
.format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "IMG_" + timeStamp + ".jpg");
} else if (type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "VID_" + timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
private PreviewCallback myPreviewCallback = new PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
// TODO Auto-generated method stub
Log.e(TAG, "onPreviewFrame2");
if (data == null ) {
camera.addCallbackBuffer(data);
return;
}else{
camera.addCallbackBuffer(data);
}
}
};
}
====缓冲(w*h)*3/2