【Android基础】-调用前置摄像头实现的‘手机镜子’

前言:

镜子是每个爱美的人必备的物品,但是并不是什么时候都带在身边;手机也是每个人必备的物品,而且随身携带,甚至连上厕所都不愿放下;那么是不是可以想办法让手机具有镜子的功能呢?今天我们就来通过调用摄像头实现一款手机镜子,去掉手机照相机界面上多余的设置部分,带给大家一个干干净净的原生的镜子。


主要代码如下:

package com.tailyou.mirror;

import java.io.IOException;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.PowerManager;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.LinearLayout;
import android.widget.Toast;

import com.umeng.analytics.MobclickAgent;
import com.umeng.update.UmengUpdateAgent;

public class MainActivity extends Activity {
    private Context mContext;
    private Camera mCamera;
    private PowerManager.WakeLock mWakeLock;
    private Bitmap bmp;
    private SurfaceView mSurfaceView;
    private LinearLayout llBottom, llCamera, llSave, llShare;
    private SurfaceHolder holder;
    private Handler handler = new Handler();
    private Runnable runnable = new Runnable() {

        @Override
        public void run() {
            llBottom.setVisibility(View.GONE);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = this;
        initWakeLock();
        initSurfaceView();
        initBottomLayout();
        //友盟自动更新
        UmengUpdateAgent.update(this);
    }

    private void initBottomLayout() {
        llBottom = (LinearLayout) findViewById(R.id.ll_bottom);
        llCamera = (LinearLayout) findViewById(R.id.ll_camera);
        llSave = (LinearLayout) findViewById(R.id.ll_save);
        llShare = (LinearLayout) findViewById(R.id.ll_share);
        // 拍照
        llCamera.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                mCamera.autoFocus(new AutoFocusCallback() {

                    @Override
                    public void onAutoFocus(boolean focused, Camera arg1) {
                        takePicture();
                    }
                });
            }
        });
        // 保存照片
        llSave.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                if (Environment.getExternalStorageState().equals(
                        android.os.Environment.MEDIA_MOUNTED)) {
                    ImageTool.saveImage(bmp, "MirrorPic", "mp", 100);
                    Toast.makeText(MainActivity.this, "照片保存成功",
                            Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(MainActivity.this, "操作SDCard失败,请检查是否插入SD卡",
                            Toast.LENGTH_SHORT).show();
                }
                llSave.setVisibility(View.GONE);
                llShare.setVisibility(View.GONE);
                handler.postDelayed(runnable, 5000);
                mCamera.startPreview();
            }
        });

        // 分享照片
        llShare.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                Intent shareIntent = new Intent(Intent.ACTION_SEND);
                shareIntent.putExtra(Intent.EXTRA_STREAM, Uri
                        .fromFile(ImageTool.saveImage(bmp, "MirrorPic", "mp",
                                100)));
                shareIntent.setType("image/*");
                startActivity(Intent.createChooser(shareIntent, "分享照片"));
                llSave.setVisibility(View.GONE);
                llShare.setVisibility(View.GONE);
                handler.postDelayed(runnable, 5000);
                mCamera.startPreview();
            }
        });
    }

    private void initSurfaceView() {
        mSurfaceView = (SurfaceView) findViewById(R.id.mSurfaceView);
        holder = mSurfaceView.getHolder();
        // 添加回调监听
        holder.addCallback(new Callback() {

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                stopPreviewAndReleaseCamera();
            }

            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
                mCamera.setDisplayOrientation(90);
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format,
                    int width, int height) {
                setCameraParametersAndStartPreview(holder);
            }
        });

        // SurfaceView触摸监听,实现隐藏或显示底部操作栏
        mSurfaceView.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View arg0, MotionEvent arg1) {
                if (llBottom.isShown()) {
                    llBottom.setVisibility(View.GONE);
                } else {
                    llBottom.setVisibility(View.VISIBLE);
                    handler.postDelayed(runnable, 5000);
                }
                return false;
            }
        });
    }

    // 停止预览并释放相机
    private void stopPreviewAndReleaseCamera() {
        mCamera.stopPreview();
        mCamera.release();
        mCamera = null;
    }

    private void setCameraParametersAndStartPreview(SurfaceHolder holder) {
        try {
            Camera.Parameters parameters = mCamera.getParameters();
            // 设置预览照片大小 
            parameters.setPreviewSize(ScreenUtils.getScreenWidth(mContext),
                    ScreenUtils.getScreenHeight(mContext));
            // 设置预览照片时每秒显示多少帧最小值和最大值
            parameters.setPreviewFpsRange(4, 10);
            // 设置图片格式
            parameters.setPictureFormat(PixelFormat.RGB_565);
            // 设置照片大小
            parameters.setPictureSize(ScreenUtils.getScreenWidth(mContext),
                    ScreenUtils.getScreenHeight(mContext));
            mCamera.setParameters(parameters);
            // 通过SurfaceView显示取景画面
            mCamera.setPreviewDisplay(holder);
            // 开始预览
            mCamera.startPreview();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 拍照
    private void takePicture() {
        if (mCamera != null) {
            mCamera.takePicture(new ShutterCallback() {

                @Override
                public void onShutter() {
                    // TODO 当用户按下快门时执行此处的代码

                }
            }, new PictureCallback() {

                @Override
                public void onPictureTaken(byte[] arg0, Camera arg1) {
                    // TODO 当相机获取原始照片时执行此处代码,可在此处保存原始照片信息

                }
            }, new PictureCallback() {

                @Override
                public void onPictureTaken(byte[] data, Camera arg1) {
                    // 此处根据拍照所得数据创建位图
                    bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
                    llSave.setVisibility(View.VISIBLE);
                    llShare.setVisibility(View.VISIBLE);
                }
            });
            // 拍完照片后取消所有隐藏底部操作栏的Runnable
            handler.removeCallbacks(runnable);
            // 设置底部操作栏可见
            llBottom.setVisibility(View.VISIBLE);
        }
    }

    // 初始化电源锁
    private void initWakeLock() {
        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                "MainActivity");
    }

    @Override
    protected void onResume() {
        super.onResume();
        // 友盟统计代码
        MobclickAgent.onResume(this);
        // 获取电源锁,以避免黑屏
        mWakeLock.acquire();
    }

    @Override
    protected void onPause() {
        super.onPause();
        // 友盟统计代码
        MobclickAgent.onPause(this);
        // 释放电源锁
        if (mWakeLock != null) {
            mWakeLock.release();
        }
    }
}

源码下载地址:http://download.csdn.net/detail/tailyou/9074561

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
android调用camera时,可以自己写一个activity,赋上相关参数,打开前camera就可以了; 需要申请的permission,在AndroidManifest.xml中添加: 主要功能,打开前camera 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; } 根据打开时的横竖屏方向来调整preview角度 //根据横竖屏自动调节preview方向,Starting from API level 14, this method can be called when preview is active. 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); }
### 回答1: UniApp是一种基于Vue.js框架开发的多端应用开发框架,可以轻松地开发出运行在微信小程序、App、H5、快应用等平台上的应用程序。为了在UniApp中通过前置摄像头拍摄照片或者录制视频,我们需要调用uni.chooseVideo和uni.chooseImage这两个API。 其中,uni.chooseVideo实现调用前置摄像头功能,可以通过以下步骤来实现: 1. 在uni-app项目的pages.json文件中注册一个页面,比如:video. 2. 在video.vue文件中通过调用uni.chooseVideo()方法来控制前置摄像头的开启。 3. 在uni.chooseVideo()的配置参数中,设置camera属性为“front”,即可调用前置摄像头。 具体实现代码如下所示: <template> <view> <button @tap="takeVideo">调用前置摄像头</button> </view> </template> <script> export default { methods: { takeVideo(){ uni.chooseVideo({ camera: 'front', // 调用前置摄像头 maxDuration: 60, success: function (res) { console.log(res.tempFilePaths[0]) } }) } } } </script> 通过上述方法,我们可以在uni-app中调用前置摄像头来拍摄或录制视频,并且可以根据自己的需求自定义参数来实现更多的自定义功能。 ### 回答2: Uniapp是一款跨平台开发框架,它通过一套代码可以在多个平台上运行,包括Android、iOS、H5等。如果我们想要在Uniapp中调用前置摄像头,需要进行以下步骤。 首先,在我们的项目中安装uni-chose-image插件,它可以提供一个包含相机、相册、预览等功能的页面,相机模块默认使用的是后置摄像头,因此我们需要设定使用前置摄像头。 其次,在页面的mounted函数中,找到uni.chooseImage的函数调用。根据文档,我们可以看到它接受一个对象作为参数,该对象包含count、scope、sizeType、sourceType和success等属性。其中,scope属性可以用来设定使用的摄像头,其取值有camera表示后置摄像头,frontCamera表示前置摄像头,unspecified表示不指定使用哪个摄像头。 最后,我们需要在manifest.json文件中,声明我们的应用需要使用摄像头权限。可以在app-plus节点中的nvue节点中添加支持的权限名称,例如camera。这样,当我们在使用uni.chooseImage函数时,系统会弹出一个权限请求对话框,询问用户是否授权应用使用摄像头。 综上所述,如果我们想在Uniapp中调用前置摄像头,我们需要安装uni-chose-image插件,在mounted函数中配置使用前置摄像头,以及在manifest.json文件中声明应用需要使用摄像头权限。通过这些步骤,我们可以很方便地实现前置摄像头调用。 ### 回答3: Uniapp是一种跨平台的开发框架,开发者可以在不同的平台上快速地实现应用的开发。在Uniapp的应用中,调用前置摄像头可以帮助开发者实现许多在应用中需要使用的功能。以下是Uniapp调用前置摄像头的详细说明: 首先,在Uniapp中调用前置摄像头需要使用到uni-app插件,这个插件可以帮助开发者快速地实现在不同平台中使用前置摄像头功能。 其次,在使用前置摄像头的时候,开发者需要注意以下两个问题: 1. 平台差异性:因为不同的平台上支持前置摄像头的方式不同,所以开发者需要在不同的平台上分别实现调用前置摄像头的方法。在uni-app插件中,可以使用#ifdef、#endif来判断需要调用的平台是哪个,然后进行相应的调用。 2. 权限问题:在调用前置摄像头时,开发者需要注意权限问题,不同的平台上可能需要不同的权限才能使用前置摄像头。在uni-app插件中,可以使用uni.requestAuth来请求相应的权限。在获取到权限之后,就可以正常地调用前置摄像头了。 最后,在进行前置摄像头调用时,需要注意一些技巧。例如,在使用前置摄像头进行拍照时,需要指定前置摄像头的ID。在uni-app插件中,可以使用uni.getSystemInfoSync获取到摄像头的ID,然后通过camera组件来进行拍照。此外,还需要注意前置摄像头和后置摄像头的差异,例如拍照时需要注意照片的方向等问题。 总之,在使用Uniapp调用前置摄像头的过程中,需要注意平台差异性、权限问题、技巧等方面,才能够顺利实现调用前置摄像头功能

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值