这里有新鲜出炉的精品教程,程序狗速度看过来!
Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发。尚未有统一中文名称,中国大陆地区较多人使用“安卓”或“安致”。
这篇文章主要为大家详细介绍了Android图片识别的应用,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
最近由于参加一个小小的创意比赛,用安卓做了一个小小的图片识别应用,主要是通过拍照识别图片中的菜品,还有对象位置查找的东西。之前没有做过安卓,都是拼拼凑凑多篇博客完成的,我也把这个项目的一些过程分享一下。先把功能贴一下,其实就是点击拍照,将照片保存在本地,然后识别出图中的菜品,然后用红色方框圈出来,并显示菜品种类。采用最新的Camera2的API,的确是比Camera好用。
1、界面
我采用了一个SurfaceView用来显示摄像头的预览画面,重写了一个SurfaceView来进行红色方框还有菜品名字的绘制。图片是一个ImageVIew,相当于拍照按钮的功能。
- <?xml version="1.0" encoding="utf-8"?>
- <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="com.hd.hd.MainActivity">
- <SurfaceView
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:id="@+id/surfaceView"
- android:layout_centerHorizontal="true"
- android:layout_centerVertical="true"/>
- <com.hd.hd.SVDraw
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:id="@+id/mySurfaceView"
- android:layout_centerHorizontal="true"
- android:layout_centerVertical="true"/>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_alignParentBottom="true"
- >
- <ImageView
- android:id="@+id/btngal"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal"
- android:layout_alignParentBottom="true"
- android:src="@drawable/s_8"
- android:layout_alignParentLeft="true"
- />
- <TextView
- android:id="@+id/textview"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:textColor="@color/white"
- android:textSize="20dp"
- android:layout_toRightOf="@id/btngal"
- android:layout_alignParentTop="true"
- />
- </LinearLayout>
- </RelativeLayout>
SVDraw,,继承SurfaceView,用于绘制红色方框
- package com.hd.hd;
- import android.content.Context;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.graphics.PixelFormat;
- import android.graphics.PorterDuff;
- import android.util.AttributeSet;
- import android.view.SurfaceHolder;
- import android.view.SurfaceView;
- import java.util.List;
- /*定义一个画矩形框的类*/
- public class SVDraw extends SurfaceView implements SurfaceHolder.Callback {
- protected SurfaceHolder sh;
- private int mWidth;
- private int mHeight;
- public SVDraw(Context context, AttributeSet attrs) {
- super(context, attrs);
- // TODO Auto-generated constructor stub
- sh = getHolder();
- sh.addCallback(this);
- sh.setFormat(PixelFormat.TRANSPARENT);
- setZOrderOnTop(true);
- }
- public void surfaceChanged(SurfaceHolder arg0, int arg1, int w, int h) {
- // TODO Auto-generated method stub
- }
- public void surfaceCreated(SurfaceHolder sh) {
- // TODO Auto-generated method stub
- mWidth = this.getWidth();
- mHeight = this.getHeight();
- }
- public void surfaceDestroyed(SurfaceHolder arg0) {
- // TODO Auto-generated method stub
- }
- void clearDraw() {
- Canvas canvas = sh.lockCanvas();
- canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
- sh.unlockCanvasAndPost(canvas);
- }
- public void drawLine(List < String > keys, List < String > values) {
- Canvas canvas = sh.lockCanvas();
- canvas.drawColor(Color.TRANSPARENT);
- Paint p = new Paint();
- p.setAntiAlias(true);
- p.setColor(Color.RED);
- p.setStrokeWidth(6);
- p.setStyle(Paint.Style.STROKE); //设置空心
- p.setTextSize(160);
- Paint p1 = new Paint();
- p1.setColor(Color.WHITE);
- p1.setTextSize(80);
- for (int i = 0; i < keys.size(); i++) {
- String v = values.get(i);
- v = v.replace("[", "");
- v = v.replace("]", "");
- String[] value = v.split(",");
- canvas.drawRect(mWidth - Integer.parseInt(value[3]), Integer.parseInt(value[0]), mHeight - Integer.parseInt(value[1]), Integer.parseInt(value[2]), p); // 正方形
- canvas.drawText(keys.get(i), mWidth - Integer.parseInt(value[3]), Integer.parseInt(value[0]) - 5, p1);
- }
- sh.unlockCanvasAndPost(canvas);
- }
- }
2、上传图片到服务器,我没有采用JSon的格式,而是直接将图片文件转化为字节数组,发送给服务器。使用一个异步任务,完成后,直接在onPostExcute()方法里绘制。
- package com.hd.hd;
- import android.os.AsyncTask;
- import android.util.Log;
- import android.widget.TextView;
- import org.json.JSONException;
- import org.json.JSONObject;
- import java.io.DataOutputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.net.HttpURLConnection;
- import java.net.MalformedURLException;
- import java.net.URL;
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.List;
- import java.util.UUID;
- /**
- * Created by asus on 2017/8/13.
- */
- public class MyTask extends AsyncTask < String,
- Integer,
- String > {
- private static String TAG = "MainActivity";
- private File file; //需要发送的图片
- private String result_content; //服务器返回的结果
- private SVDraw surfaceView; //需要绘制的surfaceview
- private TextView tv; //显示文字
- private static final int TIME_OUT = 10 * 1000; // 超时时间
- private static final String CHARSET = "utf-8"; // 设置编码
- public MyTask(File f, SVDraw s, TextView tv) {
- this.file = f;
- this.surfaceView = s;
- this.tv = tv;
- }
- @Override protected void onPreExecute() {
- }
- //doInBackground方法内部执行后台任务,不可在此方法内修改UI
- @Override protected String doInBackground(String...params) {
- //调用文件上传方法
- result_content = uploadFile(file, "http://13.76.211.62/");
- return null;
- }
- //onProgressUpdate方法用于更新进度信息
- @Override protected void onProgressUpdate(Integer...progresses) {
- }
- //onPostExecute方法用于在执行完后台任务后更新UI,显示结果
- @Override protected void onPostExecute(String result) {
- //由于返回的是一个python的字典形式的字符串,用json来解析
- JSONObject obj = null;
- List < String > keys = new ArrayList < String > ();
- List < String > values = new ArrayList < String > ();
- try {
- obj = new JSONObject(result_content);
- //json对象的Key的迭代器,用来遍历json
- Iterator it = obj.keys();
- while (it.hasNext()) {
- String key = (String) it.next();
- String value = obj.getString(key);
- keys.add(key);
- values.add(value);
- }
- } catch(JSONException e) {
- e.printStackTrace();
- }
- //绘制图形
- surfaceView.clearDraw();
- surfaceView.drawLine(keys, values);
- tv.setText("搭配很赞哦");
- }
- //onCancelled方法用于在取消执行中的任务时更改UI
- @Override protected void onCancelled() {
- }
- /**
- * 上传图片文件到服务器
- * @param file
- * @param RequestURL
- * @return
- */
- public static String uploadFile(File file, String RequestURL) {
- String result = null;
- String BOUNDARY = UUID.randomUUID().toString(); // 边界标识 随机生成
- String PREFIX = "--",
- LINE_END = "\r\n";
- String CONTENT_TYPE = "multipart/form-data"; // 内容类型
- try {
- //创建URL连接,指明连接地址
- URL url = new URL(RequestURL);
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- //设置http请求的属性为POST
- conn.setReadTimeout(TIME_OUT);
- conn.setConnectTimeout(TIME_OUT);
- conn.setDoInput(true); // 允许输入流
- conn.setDoOutput(true); // 允许输出流
- conn.setUseCaches(false); // 不允许使用缓存
- conn.setRequestMethod("POST"); // 请求方式
- conn.setRequestProperty("Charset", CHARSET); // 设置编码
- conn.setRequestProperty("connection", "keep-alive");
- conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY);
- if (file != null) {
- /**
- * 当文件不为空,把文件包装并且上传
- */
- Log.i(TAG, "upload");
- DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
- Log.e(TAG, "not null");
- /**
- * 这里重点注意: name里面的值为服务端需要key 只有这个key 才可以得到对应的文件
- * filename是文件的名字,包含后缀名的 比如:abc.png
- */
- InputStream is = new FileInputStream(file);
- byte[] bytes = new byte[1024];
- int len;
- while ((len = is.read(bytes)) != -1) {
- dos.write(bytes, 0, len);
- }
- is.close();
- dos.flush();
- Log.e(TAG, "sent");
- /**
- * 获取响应码 200=成功 当响应成功,获取响应的流
- */
- int res = conn.getResponseCode();
- Log.e(TAG, "response code:" + res);
- Log.e(TAG, "request success");
- InputStream input = conn.getInputStream();
- StringBuffer sb1 = new StringBuffer();
- int ss;
- while ((ss = input.read()) != -1) {
- sb1.append((char) ss);
- }
- result = sb1.toString();
- Log.e(TAG, "result : " + result);
- }
- } catch(MalformedURLException e) {
- e.printStackTrace();
- } catch(IOException e) {
- e.printStackTrace();
- }
- return result;
- }
- }
3、初始化界面、照相机,使得照相机能够实时预览,并实现拍照功能
- package com.hd.hd;
- import android.Manifest;
- import android.content.Context;
- import android.content.pm.PackageManager;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.ImageFormat;
- import android.hardware.camera2.CameraAccessException;
- import android.hardware.camera2.CameraCaptureSession;
- import android.hardware.camera2.CameraCharacteristics;
- import android.hardware.camera2.CameraDevice;
- import android.hardware.camera2.CameraManager;
- import android.hardware.camera2.CaptureRequest;
- import android.hardware.camera2.CaptureResult;
- import android.hardware.camera2.TotalCaptureResult;
- import android.media.Image;
- import android.media.ImageReader;
- import android.os.Build;
- import android.os.Bundle;
- import android.os.Environment;
- import android.os.Handler;
- import android.os.HandlerThread;
- import android.support.annotation.NonNull;
- import android.support.annotation.RequiresApi;
- import android.support.v4.app.ActivityCompat;
- import android.support.v7.app.AppCompatActivity;
- import android.util.Log;
- import android.util.SparseIntArray;
- import android.view.Surface;
- import android.view.SurfaceHolder;
- import android.view.SurfaceView;
- import android.view.View;
- import android.widget.ImageView;
- import android.widget.TextView;
- import android.widget.Toast;
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.nio.ByteBuffer;
- import java.util.Arrays;
- public class MainActivity extends AppCompatActivity {
- private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
- private String TAG = "MainActivity";
- ///为了使照片竖直显示
- static {
- ORIENTATIONS.append(Surface.ROTATION_0, 90);
- ORIENTATIONS.append(Surface.ROTATION_90, 0);
- ORIENTATIONS.append(Surface.ROTATION_180, 270);
- ORIENTATIONS.append(Surface.ROTATION_270, 180);
- }
- private SurfaceView mSurfaceView;
- private SurfaceHolder mSurfaceHolder;
- private CameraManager mCameraManager; //摄像头管理器
- private Handler childHandler,
- mainHandler;
- private String mCameraID; //摄像头Id 0 为后 1 为前
- private ImageReader mImageReader;
- private CameraCaptureSession mCameraCaptureSession;
- private CameraDevice mCameraDevice;
- private SVDraw hSurfaceView;
- private MyTask myTask;
- private CaptureRequest.Builder captureRequestBuilder;
- private TextView tv;
- private final int DRAW_ORDER = 10;
- private Handler myHandler;
- private ImageView imageView;
- private String dir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Healthy_d/";
- @Override protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- //此步骤非常重要,安卓不用自动帮你创建文件夹来保存拍照的照片
- File dirFirstFolder = new File(dir); //方法二:通过变量文件来获取需要创建的文件夹名字
- if (!dirFirstFolder.exists()) { //如果该文件夹不存在,则进行创建
- dirFirstFolder.mkdirs(); //创建文件夹
- }
- //Android 6后有些敏感的权限不能随意分配,必须向用户发送请求赋予
- //这里请求用户赋予拍照,读写内存卡,连接网络的权限,其实只有拍照权限需要向用户请求,但是有备无患吧
- if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
- Log.e(TAG, ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) + "");
- ActivityCompat.requestPermissions(MainActivity.this, new String[] {
- Manifest.permission.WRITE_EXTERNAL_STORAGE
- },
- 43);
- }
- if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
- ActivityCompat.requestPermissions(MainActivity.this, new String[] {
- Manifest.permission.READ_EXTERNAL_STORAGE
- },
- 44);
- }
- if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED) {
- ActivityCompat.requestPermissions(MainActivity.this, new String[] {
- Manifest.permission.INTERNET
- },
- 45);
- }
- initVIew();
- }
- /**
- * 初始化视图
- */
- private void initVIew() {
- HandlerThread handlerThread = new HandlerThread("Camera2");
- handlerThread.start();
- childHandler = new Handler(handlerThread.getLooper());
- //mSurfaceView
- mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView);
- hSurfaceView = (SVDraw) findViewById(R.id.mySurfaceView);
- imageView = (ImageView) findViewById(R.id.btngal);
- tv = (TextView) findViewById(R.id.textview);
- //设置ImageView监听器,点击图片,拍照
- imageView.setOnClickListener(new View.OnClickListener() {@Override public void onClick(View v) {
- Toast.makeText(MainActivity.this, "正在识别,请稍等", Toast.LENGTH_LONG).show();
- if (mCameraDevice == null) return;
- // 创建拍照需要的CaptureRequest.Builder
- try {
- captureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
- // 将imageReader的surface作为CaptureRequest.Builder的目标
- captureRequestBuilder.addTarget(mImageReader.getSurface());
- // 自动对焦
- captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
- // 自动曝光
- captureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
- // 获取手机方向
- int rotation = getWindowManager().getDefaultDisplay().getRotation();
- // 根据设备方向计算设置照片的方向
- captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
- //拍照
- CaptureRequest mCaptureRequest = captureRequestBuilder.build();
- mCameraCaptureSession.capture(mCaptureRequest, mSessionCaptureCallback, childHandler);
- } catch(CameraAccessException e) {
- e.printStackTrace();
- }
- }
- });
- mSurfaceHolder = mSurfaceView.getHolder();
- mSurfaceHolder.setKeepScreenOn(true);
- // mSurfaceView添加回调
- mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {@Override public void surfaceCreated(SurfaceHolder holder) { //SurfaceView创建
- // 初始化Camera
- initCamera2();
- }
- @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
- @Override public void surfaceDestroyed(SurfaceHolder holder) { //SurfaceView销毁
- // 释放Camera资源
- if (null != mCameraDevice) {
- mCameraDevice.close();
- mCameraDevice = null;
- }
- }
- });
- }
- //拍照时,可以对照片进行操作,这里可以不写,因为我没对其进行操作
- private CameraCaptureSession.CaptureCallback mSessionCaptureCallback = new CameraCaptureSession.CaptureCallback() {
- @Override public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {}
- @Override public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request, CaptureResult partialResult) {}
- };
- /**
- * 初始化Camera2
- */
- @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) private void initCamera2() {
- HandlerThread handlerThread = new HandlerThread("Camera2");
- handlerThread.start();
- childHandler = new Handler(handlerThread.getLooper());
- mainHandler = new Handler(getMainLooper());
- mCameraID = "" + CameraCharacteristics.LENS_FACING_FRONT; //后摄像头
- mImageReader = ImageReader.newInstance(mSurfaceView.getWidth(), mSurfaceView.getHeight(), ImageFormat.JPEG, 1);
- mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() { //可以在这里处理拍照得到的临时照片 例如,写入本地
- @Override public void onImageAvailable(ImageReader reader) {
- Image image = reader.acquireNextImage();
- ByteBuffer buffer = image.getPlanes()[0].getBuffer();
- byte[] bytes = new byte[buffer.remaining()];
- buffer.get(bytes); //由缓冲区存入字节数组
- Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
- String fileName = "test";
- File file = new File(dir + fileName + ".jpg");
- String state = Environment.getExternalStorageState();
- //如果状态不是mounted,无法读写
- if (!state.equals(Environment.MEDIA_MOUNTED)) {
- return;
- }
- FileOutputStream out = null;
- try {
- out = new FileOutputStream(file);
- bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out); //转化为jpeg图片
- out.flush();
- out.close();
- image.close(); //一定要记得关,否则会出现程序崩溃
- } catch(FileNotFoundException e) {
- e.printStackTrace();
- } catch(IOException e) {
- e.printStackTrace();
- }
- new MyTask(file, hSurfaceView, tv).execute();
- }
- },
- mainHandler);
- //获取摄像头管理
- mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
- try {
- if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
- ActivityCompat.requestPermissions(this, new String[] {
- Manifest.permission.CAMERA
- },
- 42);
- }
- //打开摄像头
- mCameraManager.openCamera(mCameraID, stateCallback, mainHandler);
- } catch(CameraAccessException e) {
- e.printStackTrace();
- }
- }
- /**
- * 当发送权限请求用户响应时,回调该函数
- * @param requestCode
- * @param permissions
- * @param grantResults
- */
- @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- if (requestCode == 42) {
- Toast.makeText(this, "CAMERA PERMISSION GRANTED", Toast.LENGTH_SHORT).show();
- if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- //申请成功,可以拍照
- Log.i(TAG, "apply camera success");
- CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
- try {
- if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
- Toast.makeText(this, "CAMERA PERMISSION DENIED", Toast.LENGTH_SHORT).show();
- }
- mCameraManager.openCamera(mCameraID, stateCallback, mainHandler);
- } catch(CameraAccessException e) {
- e.printStackTrace();
- }
- } else {
- Toast.makeText(this, "CAMERA PERMISSION DENIED", Toast.LENGTH_SHORT).show();
- }
- return;
- }
- super.onRequestPermissionsResult(requestCode, permissions, grantResults);
- }
- /**
- * 摄像头创建监听
- */
- private CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {@Override public void onOpened(CameraDevice camera) { //打开摄像头
- mCameraDevice = camera;
- //开启预览
- takePreview();
- }
- @Override public void onDisconnected(CameraDevice camera) { //关闭摄像头
- if (null != mCameraDevice) {
- mCameraDevice.close();
- mCameraDevice = null;
- }
- }
- @Override public void onError(CameraDevice camera, int error) { //发生错误
- Toast.makeText(MainActivity.this, "摄像头开启失败", Toast.LENGTH_SHORT).show();
- }
- };
- /**
- * 开始预览
- */
- private void takePreview() {
- try {
- // 创建预览需要的CaptureRequest.Builder
- final CaptureRequest.Builder previewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
- // 将SurfaceView的surface作为CaptureRequest.Builder的目标
- previewRequestBuilder.addTarget(mSurfaceHolder.getSurface());
- // previewRequestBuilder.addTarget(mImageReader.getSurface());
- // 创建CameraCaptureSession,该对象负责管理处理预览请求和拍照请求
- mCameraDevice.createCaptureSession(Arrays.asList(mSurfaceHolder.getSurface(), mImageReader.getSurface()), new CameraCaptureSession.StateCallback() // ③
- {@Override public void onConfigured(CameraCaptureSession cameraCaptureSession) {
- if (null == mCameraDevice) return;
- // 当摄像头已经准备好时,开始显示预览
- mCameraCaptureSession = cameraCaptureSession;
- try {
- // 自动对焦
- previewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
- // 打开闪光灯
- previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
- // 显示预览
- CaptureRequest previewRequest = previewRequestBuilder.build();
- mCameraCaptureSession.setRepeatingRequest(previewRequest, null, childHandler);
- } catch(CameraAccessException e) {
- e.printStackTrace();
- }
- }
- @Override public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
- Toast.makeText(MainActivity.this, "配置失败", Toast.LENGTH_SHORT).show();
- }
- },
- childHandler);
- } catch(CameraAccessException e) {
- e.printStackTrace();
- }
- }
- }
4、AndroidManifest.xml
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.hd.hd">
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
- <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
- <uses-permission android:name="android.permission.CAMERA"/>
- <uses-feature android:name="android.hardware.camera2.full" />
- <uses-permission android:name="android.permission.INTERNET" />
- <application
- android:allowBackup="true"
- android:icon="@mipmap/ic_launcher"
- android:label="@string/app_name"
- 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>
今天代码先分享到那么多,明天给大家分享一下Camera2的架构。有不懂的可以评论,一起讨论。
来源: http://www.phperz.com/article/17/0916/345810.html