标签:
android之利用surfaceView实现自定义水印相机
知识点
1、自定义相机+预览相机
2、截屏拍照加水印
3、关于不使用intent来传输图片
俗话说,有图有真相。很多人都是喜欢直接看图,不像我,比较喜欢文字多点,经常看看散文什么的陶冶一下情操。
好了,说到这里,就引出我们今天要做的这个功能,那就是水印相机。水印相机说白了,就是在拍照的图片上面加上自己想要的各种信息,包括文字,图片或者其它你想要的信息。
在这里,我自己定义了一个类WaterCameraActivity,是自定义的相机的,然后还有一个类ViewPhoto,是用来查看你拍照后的图片的,有使用图片和取消/重新拍照功能。
3、关于不使用intent来传输图片
因为intent最大的传输数据为1m,一张图片随便都有3,4m,再加之读取到内存中,就可能变成2倍3倍大了,很容易造成oom。所以我们还是利用本地储存来进行,只要传输一个路径就OK了,这样做的问题就是,老是要读取本地图片,性能不是很好呢。关于这个,如果各位有好的建议可以提出来一起探讨。
下面我们直接上代码,毕竟还是代码说事比较清楚,代码里面都注释好了,各位可以认真去看。
WaterCameraActivity的布局:布局很简单,就是一个SurfaceView+需要加入的水印信息,如下图
布局
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <!--这是用来预览相机的空间,大家可以去好好了解一下,这里我就不详细讲了--> <SurfaceView android:id="@+id/sfv_camera" android:layout_width="match_parent" android:layout_height="match_parent" /> <!--想要的信息放在surfaceview之上就OK了,下面是我想要加入的信息--> <RelativeLayout android:id="@+id/rl_setting" android:layout_width="match_parent" android:layout_height="60dp" android:background="@null" android:gravity="center_vertical"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginLeft="5dp" android:orientation="vertical"> <TextView android:id="@+id/tv_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:shadowColor="#000" android:shadowDx="3" android:shadowDy="3" android:shadowRadius="2" android:text="08:27" android:textColor="#fff" android:textSize="25sp" /> <TextView android:id="@+id/tv_date" android:layout_width="wrap_content" android:layout_height="wrap_content" android:shadowColor="#000" android:shadowDx="3" android:shadowDy="3" android:shadowRadius="2" android:text="2016/07/24" android:textColor="#fff" android:textSize="15sp" /> </LinearLayout> <ImageButton android:id="@+id/imgvBtn_switchFlash" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_marginRight="20dp" android:background="@null" android:paddingLeft="10dp" android:paddingRight="10dp" /> <ImageButton android:id="@+id/imgvBtn_switchCamera" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_marginRight="20dp" android:background="@null" android:paddingLeft="10dp" android:paddingRight="10dp" android:visibility="gone" /> </RelativeLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginBottom="75dp" android:layout_marginRight="3dp" android:gravity="right" android:orientation="vertical"> <TextView android:id="@+id/tv_operation" style="@style/textView_water" android:drawableLeft="@drawable/operation" android:text="点击操作" /> <TextView android:id="@+id/tv_username" style="@style/textView_water" android:drawableLeft="@drawable/user_icon" android:text="钓鱼的小木匠" /> <TextView android:id="@+id/tv_address" style="@style/textView_water" android:drawableLeft="@drawable/address" android:text="广东省惠州市惠城区鹅岭南路6号TCL工业大厦" /> </LinearLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="75dp" android:layout_alignParentBottom="true" android:layout_gravity="center_vertical"> <!--android:background="@drawable/take_photo_selector" 定义一个根据点击状态改变的xml文件--> <ImageButton android:id="@+id/btn_takePic" android:layout_width="64dp" android:layout_height="64dp" android:layout_centerInParent="true" android:background="@drawable/take_photo_selector" /> <Button android:id="@+id/imgvBtn_back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="20dp" android:background="@null" android:text="取 消" android:textColor="#0f0" android:textSize="20sp" /> </RelativeLayout> </RelativeLayout> </RelativeLayout>
WaterCameraActivity类
/** * 启动自定义水印相机 * * Created by tanksu on 16/6/28. */ public class WaterCameraActivity extends BaseActivity implements SurfaceHolder.Callback { private Context mContext; private SurfaceView mSurfaceView; private ImageButton imgvBtn_takePic, imgvBtn_switchFlash, imgvBtn_switchCamera; private Button btn_back; private TextView tv_time, tv_username, tv_address, tv_date, tv_operation; private SurfaceHolder mSurfaceHolder; private Camera mCamera; private String curDate = "", curTime = "", curAddress = "", userName = "", userOperation = ""; private final int REQUEST_CODE = 1001; private Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); private int mCameraId; private long currentTimeMillis = 0; private Intent waterIntent; /** * 这是点击surfaceview聚焦所调用的方法 */ private Camera.AutoFocusCallback autoFocusCallback = new Camera.AutoFocusCallback(){ @Override public void onAutoFocus(boolean success, Camera camera) { //success = true,聚焦成功,否则聚焦失败 //在这里我们可以在点击相机后是否聚焦成功,然后做我们的一些操作,这里我就省略了,大家自行根据需要添加 } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.watercamera_layout); initViews(); initData(); initListener(); } /** * 初始化控件 */ private void initViews() { mSurfaceView = (SurfaceView) findViewById(R.id.sfv_camera); imgvBtn_takePic = (ImageButton) findViewById(R.id.btn_takePic); tv_time = (TextView) findViewById(R.id.tv_time); tv_username = (TextView) findViewById(R.id.tv_username); tv_address = (TextView) findViewById(R.id.tv_address); tv_date = (TextView) findViewById(R.id.tv_date); tv_operation = (TextView) findViewById(R.id.tv_operation); imgvBtn_switchFlash = (ImageButton) findViewById(R.id.imgvBtn_switchFlash); imgvBtn_switchFlash.setImageResource(R.drawable.camera_setting_flash_off_normal); imgvBtn_switchCamera = (ImageButton) findViewById(R.id.imgvBtn_switchCamera); imgvBtn_switchCamera.setImageResource(R.drawable.changing_camera_normal); btn_back = (Button) findViewById(R.id.imgvBtn_back); mContext = this; } /** * 初始化数据 */ private void initData() { mSurfaceView.setFocusable(true); mSurfaceHolder = mSurfaceView.getHolder(); mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); mSurfaceHolder.setKeepScreenOn(true); mSurfaceHolder.setFormat(PixelFormat.TRANSPARENT); mSurfaceHolder.addCallback(this); SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd"); //获取当前时间,作为图片的命名,再转换为常用时间格式 currentTimeMillis = System.currentTimeMillis(); curDate = formatter.format(currentTimeMillis); tv_date.setText(curDate); SimpleDateFormat format = new SimpleDateFormat("HH:mm", Locale.getDefault()); //获取24小时制的时间 curTime = format.format(currentTimeMillis); tv_time.setText(curTime); Intent intent = getIntent(); //我写的这个类,是要用startActivityForResult来启动的,传入的参数可以根据自己需求来定,我这里传过来的信息有 //地址CUR_ADDRESS,用户名USER_NAME,用户操作USER_OPERATION,然后把信息设置到空间里面去,同时还要保存intent。 //而时间和日期,则是在本类中自己获取,同样设置入控件里面去 if (intent != null) { waterIntent = intent; curAddress = intent.getStringExtra(StaticParam.CUR_ADDRESS); userName = intent.getStringExtra(StaticParam.USER_NAME); userOperation = intent.getStringExtra(StaticParam.USER_OPERATION); tv_operation.setText(userOperation); tv_address.setText(curAddress); tv_username.setText(userName); }else { toast("intent equals null,please try again!"); } mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK; } /** * 初始化监听器 */ private void initListener() { //这个方法是点击拍照的方法 imgvBtn_takePic.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mCamera.takePicture(null, null, new PicCallBacKImpl(WaterCameraActivity.this)); } }); //设置闪光灯的模式,有禁止,自动和打开闪光灯三种模式 imgvBtn_switchFlash.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { CameraUtil.setFlashMode(mCamera, imgvBtn_switchFlash); } }); //这个是切换前后摄像头的操作,因为时间关系没有做 imgvBtn_switchCamera.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } }); //取消按钮,finish本页面 btn_back.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { WaterCameraActivity.this.finish(); } }); mSurfaceView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { mCamera.autoFocus(autoFocusCallback); //设置相机为自动对焦模式,就不用认为去点击了 return false; } }); } /** * 我们在此周期方法里面打开摄像头 */ @Override protected void onStart() { if (this.checkCameraHardware(this) && (mCamera == null)) { openCamera();//打开后置摄像头 } super.onStart(); } /** * 拍照回调类 */ class PicCallBacKImpl implements Camera.PictureCallback { private Activity mActivity; public PicCallBacKImpl(Activity activity) { this.mActivity = activity; } @Override public void onPictureTaken(byte[] data, Camera camera) { Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); bitmap = ImageUtil.matrixImageView(bitmap, 90); String path = ImageUtil.saveBitmap(null, String.valueOf(currentTimeMillis), bitmap); if (path != null && path.length() > 0) { waterIntent.setClass(mActivity, ViewPhoto.class); waterIntent.putExtra(StaticParam.PIC_PATH, path); waterIntent.putExtra(StaticParam.CUR_DATE, curDate); waterIntent.putExtra(StaticParam.CUR_TIME, curTime); waterIntent.putExtra(StaticParam.CUR_TIME_MILLIS, currentTimeMillis); mActivity.startActivityForResult(waterIntent, REQUEST_CODE); } else { toast("can't save the picture"); camera.stopPreview(); camera.release(); camera = null; } } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if(RESULT_OK == resultCode){ switch (requestCode){ case REQUEST_CODE: //处理返回结果 setResult(RESULT_OK, data); //将结果直接给设置为,启动水印相机的返回结果 break; default: break; } WaterCameraActivity.this.finish();//结束本页面,就会将结果返回到调用本页的那个activity了 } super.onActivityResult(requestCode, resultCode, data); } @Override public void surfaceCreated(SurfaceHolder holder) { try { mCamera = Camera.open(mCameraId); Camera.getCameraInfo(mCameraId, cameraInfo); } catch (Exception e) { e.printStackTrace(); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { startPreview(mCamera, mSurfaceHolder); } @Override public void surfaceDestroyed(SurfaceHolder holder) { if (mCamera != null) { mCamera.stopPreview(); mCamera.release(); mCamera = null; } } /** * 检查设备是否有摄像头 * * @param context context * @return boolean */ private boolean checkCameraHardware(Context context) { if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) { return true; } return false; } /** * 打开后置摄像头 */ private void openCamera() { Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); Camera.getCameraInfo(mCameraId, cameraInfo); this.cameraInfo = cameraInfo; if (mCameraId == Camera.CameraInfo.CAMERA_FACING_BACK) { //后置摄像头 CAMERA_FACING_FRONT mCamera = Camera.open(); mCamera.startPreview();//开始预览相机 } } /** * 开始预览相机 * * @param camera camera * @param surfaceHolder surfaceHolder */ private void startPreview(Camera camera, SurfaceHolder surfaceHolder) { camera.setDisplayOrientation(CameraUtil.getPreviewDegree(WaterCameraActivity.this)); try { camera.setPreviewDisplay(surfaceHolder); } catch (IOException e) { e.printStackTrace(); } finally { } camera.startPreview();//调用此方法,然后真正的预览相机 } /** * 停止相机预览 */ private void stopPreview() { if (mCamera != null) { mCamera.release(); mCamera.release(); mCamera = null; } } @Override protected void onDestroy() { if (mCamera != null) { mCamera.stopPreview(); mCamera.release(); mCamera = null; } super.onDestroy(); } }
ViewPhoto类的布局,布局入下图所示
<span style="font-size:12px;"><?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <RelativeLayout android:id="@+id/rl_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="0dp" android:padding="0dp"> <ImageView android:id="@+id/imgv_photo" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#000000" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="12dp" android:layout_marginTop="65dp" android:orientation="vertical"> <TextView android:id="@+id/tv_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:shadowColor="#000" android:shadowDx="3" android:shadowDy="3" android:shadowRadius="2" android:text="08:27" android:textColor="#fff" android:textSize="25sp" /> <TextView android:id="@+id/tv_date" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/tv_time" android:shadowColor="#000" android:shadowDx="3" android:shadowDy="3" android:shadowRadius="2" android:text="2016/07/24" android:textColor="#fff" android:textSize="15sp" /> </RelativeLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginBottom="70dp" android:layout_marginRight="1dp" android:gravity="right" android:orientation="vertical"> <TextView android:id="@+id/tv_operation" style="@style/textView_water" android:drawableLeft="@drawable/operation" android:text="点击操作" /> <TextView android:id="@+id/tv_userName" style="@style/textView_water" android:drawableLeft="@drawable/user_icon" android:text="钓鱼的小木匠" /> <TextView android:id="@+id/tv_address" style="@style/textView_water" android:drawableLeft="@drawable/address" android:text="广东省惠州市惠城区鹅岭南路6号TCL工业大厦" /> </LinearLayout> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginBottom="10dp" android:background="#000" android:gravity="center_vertical"> <TextView android:id="@+id/tv_cancel" style="@style/textView_common" android:layout_marginLeft="20dp" android:text="重 拍" /> <TextView android:id="@+id/tv_ok" style="@style/textView_common" android:layout_alignParentRight="true" android:layout_marginRight="20dp" android:text="使用图片" /> <CheckBox android:id="@+id/cb_savePic" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:checked="true" android:text="保存" android:textColor="#4fe19f" /> </RelativeLayout> </RelativeLayout> </span>
ViewPhoto类代码
<span style="font-size:12px;">/** * 查看拍照的类 * <p/> * Created by tanksu on 16/6/29. */ public class ViewPhoto extends BaseActivity { private ImageView imgv_photo; private TextView tv_cancel, tv_ok; private int width, height; private RelativeLayout rl_layout; private String picPath = "", curDate = "", curTime = "", curAddress = "", userName = "", userOperation = ""; private TextView tv_time, tv_date, tv_userName, tv_address, tv_operation; private CheckBox cb_savePic; private long currentTimeMillis; private String signal; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE);//去掉标题栏 setContentView(R.layout.viewphoto_layout); initViews(); initData(); initListener(); } /** * 初始化控件 */ private void initViews() { imgv_photo = (ImageView) findViewById(R.id.imgv_photo); tv_cancel = (TextView) findViewById(R.id.tv_cancel); tv_ok = (TextView) findViewById(R.id.tv_ok); rl_layout = (RelativeLayout) findViewById(R.id.rl_layout); tv_time = (TextView) findViewById(R.id.tv_time); tv_date = (TextView) findViewById(R.id.tv_date); tv_userName = (TextView) findViewById(R.id.tv_userName); tv_address = (TextView) findViewById(R.id.tv_address); cb_savePic = (CheckBox) findViewById(R.id.cb_savePic); tv_operation = (TextView) findViewById(R.id.tv_operation); } /** * 初始化数据 */ private void initData() { WindowManager windowManager = getWindowManager(); Display display = windowManager.getDefaultDisplay(); width = display.getWidth(); height = display.getHeight(); Intent intent = getIntent(); if (intent != null) { //这里的目标是,将所有传过来的的信息都去取出来,设置到每个相应的空间里面去 //有人会问我为什么要这样做,其实我在拍照的时候,还没有真正的拿到一张具有水印的照片 //我这里采用的是截屏的方式,所以呢,就要重新吧信息展现出来 //其实还有很多的方法可以做水印相机,例如用位图来“画”信息等,但是有简单的方法,为什么不用呢,非要去弄一些很复杂的方法?! picPath = intent.getStringExtra(StaticParam.PIC_PATH); curDate = intent.getStringExtra(StaticParam.CUR_DATE); curTime = intent.getStringExtra(StaticParam.CUR_TIME); userName = intent.getStringExtra(StaticParam.USER_NAME); curAddress = intent.getStringExtra(StaticParam.CUR_ADDRESS); userOperation = intent.getStringExtra(StaticParam.USER_OPERATION); signal = intent.getStringExtra(StaticParam.TS_HUB_OP_SIGNAL); currentTimeMillis = intent.getLongExtra(StaticParam.CUR_TIME_MILLIS, System.currentTimeMillis()); tv_time.setText(curTime); tv_date.setText(curDate); tv_userName.setText(userName); tv_address.setText(curAddress); tv_operation.setText(userOperation); BitmapFactory.Options options = new BitmapFactory.Options(); options.outWidth = width; options.outHeight = height; Bitmap bitmap = ImageUtil.getPressedBitmap(picPath, width, height);//方法在下面,根据路径,获取第一步拍照存本地的图片 /** * * * 根据图片路径,得到压缩过的位图 * * @param path * @param width * @param height * @return returnBitmap public static Bitmap getPressedBitmap(String path, int width, int height) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; Bitmap bitmap = BitmapFactory.decodeFile(path, options); options.inSampleSize = getBitmapSampleSize(options, width, height);//getBitmapSampleSize(options, width, height) options.inJustDecodeBounds = false; Bitmap returnBitmap = BitmapFactory.decodeFile(path, options); return returnBitmap; } * 根据要去的宽高,压缩图片 * * @param options options * @param reqWidth reqWidth * @param reqHeight reqHeight * @return inSimpleSize public static int getBitmapSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { int imgWidth = options.outWidth; int imgHeight = options.outHeight; int inSimpleSize = 1; if (imgWidth > imgHeight || imgWidth < imgHeight) { final int heightRatio = imgWidth / reqWidth; final int widthRatio = imgHeight / reqHeight; inSimpleSize = widthRatio < heightRatio ? widthRatio : heightRatio; } return inSimpleSize; } */ imgv_photo.setImageBitmap(bitmap); } else { toast("intent equals null,please try again!"); } } /** * 初始化监听器 */ private void initListener() { //点击使用图片按钮,就可以在启动水印相机的onactivityresult回调里面,获取到图片的路径,然后获取图片即可使用了 tv_ok.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final Bitmap bitmap = getScreenPhoto(rl_layout); ImageUtil.saveBitmap(picPath, String.valueOf(currentTimeMillis), bitmap);//根据路径保存图片 /** * 根据路径和名字保存图片 * * @param path path * @param imgName imgName * @param bitmap bitmap * @return createPath public static String saveBitmap(String path, String imgName, Bitmap bitmap) { String savePath = null; if (path == null) { //if path is null File fileSDCardDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM); String imgPath = fileSDCardDir.getAbsolutePath() + "/s/waterCamera/"; File fileDir = new File(imgPath); if (!fileDir.exists()) { fileDir.mkdirs(); } String photoName = imgName + ".JPG"; imgPath = imgPath + photoName; File fileIphoto = new File(imgPath); if (!fileIphoto.exists()) { try { fileIphoto.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } savePath = fileIphoto.getPath(); saveBitmap(bitmap, fileIphoto); return savePath; } else { //if path isn't null, override the photo File oldFile = new File(path); if (oldFile.exists()) { oldFile.delete(); } File newFile = new File(path); if (!newFile.exists()) { try { newFile.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } saveBitmap(bitmap, newFile); savePath = newFile.getPath(); return savePath; } } */ Intent intent = new Intent(ViewPhoto.this, TsDrActivity.class); intent.putExtra(StaticParam.PIC_PATH, picPath);//这里最主要的,就是将储存在本地的图片的路径作为结果返回 intent.putExtra(StaticParam.IS_SAVE_PIC, cb_savePic.isChecked());//这里就是是否用户要保存这张图片的选项 intent.putExtra(StaticParam.TS_HUB_OP_SIGNAL, signal); setResult(RESULT_OK, intent); //如果是OK,就设置为OK结果 ViewPhoto.this.finish(); } }); tv_cancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { ImageUtil.deleteImageFromSDCard(picPath);//重新拍照,就将本地的图片给删除掉,然后重新拍照 } }).start(); ViewPhoto.this.finish(); } }); } /** * 截屏,这里就是截屏的地方了,我这里是截屏RelativeLayout, * 只要你将需要的信息放到这个RelativeLayout里面去就可以截取下来了 * * @param waterPhoto waterPhoto * @return Bitmap */ public Bitmap getScreenPhoto(RelativeLayout waterPhoto) { View view = waterPhoto; view.setDrawingCacheEnabled(true); view.buildDrawingCache(); Bitmap bitmap = view.getDrawingCache(); int width = view.getWidth(); int height = view.getHeight(); Bitmap bitmap1 = Bitmap.createBitmap(bitmap, 0, 0, width, height); view.destroyDrawingCache(); bitmap = null; return bitmap1; } </span>
<span style="font-size:12px;">//例如:启动水印相机的代码 Intent intent = new Intent(TsHubActivity.this, WaterCameraActivity.class); intent.putExtra(StaticParam.CUR_ADDRESS, curAddress); intent.putExtra(StaticParam.USER_NAME, stationName); Button btn_recv = (Button) findViewById(R.id.batchRecv); intent.putExtra(StaticParam.USER_OPERATION, btn_recv.getText().toString()); startActivityForResult(intent, JustOneOrder); </span>回调
<span style="font-size:12px;">//拍照回调方法 @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { //以下是需要拍照的图片参数 final String imgPath = data.getStringExtra(StaticParam.PIC_PATH);//图片路径 Bitmap bitmap = BitmapFactory.decodeFile(imgPath);//获取到图片了 }</span>
上面这两个类,直接复制来就可以用了,可以根据你的需求进行修改,不难,很简单。关于前后摄像头切换的,因为时间紧任务重,就没有时间去做了。
如有任何问题,请及时与我联系,谢谢。
android之利用surfaceView实现自定义水印相机
标签:
原文地址:http://blog.csdn.net/qq_16628781/article/details/52012426