首先先介绍一下我使用的编写软件:Android studio。
注:图片看不清楚不同着急,最后会将所有的代码都给各位的
接下来我们创建一个新的项目,之后来到activity_main.xml下:
将<TextView******/>删除,换上这个
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
tools:layout_editor_absoluteX="8dp">
</RelativeLayout>
这是一种布局方式。
接下来就可以在这里添加工具了
我选用的是SurfaceView、Button、ImageView这三个工具。
打算通过SurfaceView来显示照相机的预览信息,Button来控制拍照,ImageView来显示拍摄的图片。
布局文件部分代码如下
具体的layout_width和layout_height可自己调整
之后我们来到MainActivity.java之中,我们在这里添加一些变量个体
这里要特别注意包含的文件,不能是android.graphics,应当是带划线的android.hardware。
接下来要做的就是将布局的工具和代码联系起来
最后我们添加一个回调函数,如上。选择之后会出现如下界面
上面选中的三个函数就是我们添加的回调函数了。
第一个函数是SurfaceView创建的时候会调用的函数,我们在这个函数里面打开摄像头,并调整摄像头的一些参数,在这个函数最后,我们预览照相机的信息,将预览信息放在SurfaceView上显示。
意思就是当SurfaceView创建好的时候我们就打开摄像头,调整摄像头的参数,在将摄像头获取的图片放到SurfaceView中预览。
而第二个函数我们什么都不写,意思就是在SurfaceView改变的时候我们什么都不做。
在第三个函数中,我们将摄像头释放,避免资源占用。算是保护措施的一种
之后我们就可以设置单击事件了,我们先在最上边的大函数里添加一个这个
接着将鼠标光标放在这个上边,按Alt+Enter呼出这个
选择选中的那一项,就会出现这个
之后,我们来到系统自动创建的这个函数里。
这个函数就是处理所有单击事件的地方
我们在里面做一个判断,是否是按钮被单击了,如果是,我们就用摄像头聚焦一下,然后拍照。
其他更加优秀的聚焦代码就不在这里累赘。
接着我们写出这个回调函数。回调函数的名字(mPictureCallback)可以随便改
这个回调函数的意思就是在这摄像头执行拍照指令之后,程序会到这里来。
这个onPictureTaken函数的参数data中保存的就是拍照形成的图像信息,只不过不是图形。
所以我们要将data转换成图像,最后再在ImageView中显示这个图像。
程序编到这里就差不多了,但是我们要是想调用系统的摄像头,就必须要用户同意,我们才能调用。
所以我们需要向用户申请调用摄像头的权限。
我们到AndroidManifest.xml中添加这样一行代码
<uses-permission android:name="android.permission.CAMERA"/>
就可以了
图片如下
接下来就是代码了。
首先是布局文件(activity_main.xml)中的代码
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
tools:layout_editor_absoluteX="8dp">
<SurfaceView
android:id="@+id/surfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentEnd="true"
android:layout_toEndOf="@+id/imageView"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:text="拍照"
tools:layout_editor_absoluteX="160dp"
tools:layout_editor_absoluteY="447dp" />
<ImageView
android:id="@+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
app:srcCompat="@android:color/background_light"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp" />
</RelativeLayout>
布局文件中不能只有这些代码,这些代码只是替换掉原来<TextView*******/>的部分
下面是MainActivity.java中的代码
package com.example.wdx.myapplication;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import java.io.IOException;
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback ,View.OnClickListener{
private Button btn;//按钮的在代码中的体现,btn为名称可随意更改
private SurfaceView mSurFaceView;
private ImageView mImageView;
private SurfaceHolder mSurfaceHolder;//用于获取SurfaceView的句柄,使其能被mCamera使用,以打开相机
private Camera mCamera;//照相机的个体。
private Camera.Parameters parameters;//相机的参数设置的变量
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//接下来的代码是将布局中的工具和代码中的个体对应起来,或者说联系起来
btn = (Button) findViewById(R.id.button);
mSurFaceView = (SurfaceView) findViewById(R.id.surfaceView);
mImageView = (ImageView) findViewById(R.id.imageView);
//在此之后就可以使用btn、mSurfaceView、mImageView来对布局中的工具进行操作了
mImageView.setVisibility(View.GONE);//设置这个工具不可见
btn.setText("拍照");//如代码所示,可以更改按钮的名字
mSurfaceHolder = mSurFaceView.getHolder();//代码作用直译即可
mSurfaceHolder.addCallback(this);
btn.setOnClickListener(this);//设置按钮监听事件,这样当用户按按钮的时候就可以在单击事件函数里得到单击的信息了
}
//在Surface创建的时候执行这个函数
@Override
public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open();//打开摄像头(后摄像头),效果就是从此,mCamera就控制了手机的摄像头
try{
mCamera.setPreviewDisplay(mSurfaceHolder);//之后,mCamera从摄像机里获得的图像,就会实时的显示在mSurfaceView中。
mCamera.setDisplayOrientation(90);//使你预览的画面呈现为正常的视觉画面,可是删除此行试试效果
parameters = mCamera.getParameters();//将现在camera的参数设置保存到变量parameter中
//接下来的代码是对mCamera参数的调整,或者说设置
parameters.setPreviewSize(parameters.getSupportedPreviewSizes().get(0).width,parameters.getSupportedPreviewSizes().get(0).height);//设置预览的尺寸,通过此种方法可设置为最大预览尺寸(我觉得)
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); //设置适合照片对焦
parameters.setRotation(90);//跟mCamera.setDisplayOrientation(90);有类似的作用
parameters.setPictureFormat(ImageFormat.JPEG);//设置得到的照片模式
mCamera.setParameters(parameters);//这就是将我们改变的相机参数设置到相机里了
mCamera.startPreview();//开始预览相机画面
}catch (IOException e){//如果上面try中的代码有代码执行出错,就会来到这里
e.printStackTrace();
mCamera.release();//释放摄像头,避免发生一直占用摄像头的情况
mCamera=null;//使mCamera为空,就是不代表任何东西。这也是保护代码
}
}
//在Surface被改变的时候执行这个函数
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
//此处不填任何代码,因为本程序中不需要这个功能,但是这个函数不能删除
}
//在Surface销毁的时候执行这个函数
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();//停止预览,毕竟Surface都已经销毁了
mCamera.release();
mCamera=null;
}
//单击事件,这个函数收集所有的单击事件
@Override
public void onClick(View v) {
if(v.getId()==R.id.button){//当用户单击的是button的时候执行下面的代码
mCamera.autoFocus(null);//聚焦
mCamera.takePicture(null,null,mPictureCallback);//开始照相,mPictureCallback为回调函数
}
}
private Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
mImageView.setVisibility(View.VISIBLE);//设置这个工具可见
Bitmap btm = BitmapFactory.decodeByteArray(data, 0, data.length);//将照片数据变成图像
mImageView.setImageBitmap(btm);//显示这个图像
}
};
}
最后是AndroidManifest.xml中的代码
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.wdx.myapplication">
<uses-permission android:name="android.permission.CAMERA"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
可以在android:label="********",的双引号中更改标题栏中显示的信息。
最后,在所有的都没什么问题的时候,就可以单击build,选择build apk
在apk创建完毕之后就会出现
单击蓝色字体Show in Explorer,就可以在文件夹里看到创建的apk了。
最后,因为这个只是最简单的利用camera1制作的一个照相的app,所以只能进行一次性拍照,在拍完一次之后如果再按拍照按钮的话就会闪退,等等还有一些问题。所以大家只是借鉴就好。