CIS 694EEC 693 Android Sensor Programming Lecture 20

  • Slides: 32
Download presentation
CIS 694/EEC 693 Android Sensor Programming Lecture 20 Wenbing Zhao Department of Electrical Engineering

CIS 694/EEC 693 Android Sensor Programming Lecture 20 Wenbing Zhao Department of Electrical Engineering and Computer Science Cleveland State University w. zhao 1@csuohio. edu 6/7/2021 Android Sensor Programming 1

Outline n n Take a picture using default camera app Live view using camera

Outline n n Take a picture using default camera app Live view using camera 2 APIs 6/7/2021 Android Sensor Programming 2

Take a Picture Using Default Camera App n n n Add permission to write

Take a Picture Using Default Camera App n n n Add permission to write on device and request it in the code Check to see if there is camera and default camera app Create an Intent that describes the action Media. Store. ACTION_IMAGE_CAPTURE Call start. Activity. For. Result: start the external camera activity on. Activity. Result(): Camera app returns the captured image as a bitmap in the bundle of the passed intent argument 6/7/2021 Android Sensor Programming 3

Basic Camera Usage n n Create a new app and name it Basic. Camera

Basic Camera Usage n n Create a new app and name it Basic. Camera Add permission in manifest <uses-permission android: name="android. permission. READ_EXTERNAL_STORAGE" /> <uses-permission android: name="android. permission. WRITE_EXTERNAL_STORAGE" /> n Modify activity_main. xml: <? xml version="1. 0" encoding="utf-8"? > <Linear. Layout xmlns: android="http: //schemas. android. com/apk/res/android" android: orientation="vertical" android: layout_width="fill_parent” android: layout_height="fill_parent” android: weight. Sum="1"> <Linear. Layout android: layout_height="wrap_content” android: layout_width="match_parent” android: id="@+id/linear. Layout 1"> <Button android: id="@+id/btn. Capture" android: text="Capture” android: layout_height="wrap_content” android: layout_width="wrap_content" android: enabled="true"></Button> </Linear. Layout> <Image. View android: id="@+id/image. View 1" android: layout_weight="0. 69” android: layout_width="match_parent” android: layout_height="match_parent"> </Image. View> </Linear. Layout> 6/7/2021 Android Sensor Programming 4

Basic Camera Usage n @Override public void on. Create(Bundle saved. Instance. State) { super.

Basic Camera Usage n @Override public void on. Create(Bundle saved. Instance. State) { super. on. Create(saved. Instance. State); set. Content. View(R. layout. activity_main); Strict. Mode. Vm. Policy. Builder builder = new Strict. Mode. Vm. Policy. Builder(); Strict. Mode. set. Vm. Policy(builder. build()); Modify Main. Activity. java import java. io. File; import java. io. IOException; import android. app. Activity; import android. content. Intent; import android. content. pm. Package. Manager; import android. net. Uri; import android. os. Bundle; import android. provider. Media. Store; import android. support. v 4. app. Activity. Compat; import android. view. View. On. Click. Listener; import android. widget. Button; import android. widget. Image. View; import android. os. Environment; import android. support. v 4. content. File. Provider; import android. os. Strict. Mode; import android. widget. Toast; if (Activity. Compat. check. Self. Permission(this, android. Manifest. permission. WRITE_EXTERNAL_STORAGE) != Package. Manager. PERMISSION_GRANTED) { Activity. Compat. request. Permissions(this, new String[]{android. Manifest. permission. WRITE_EXTERNAL_STORAGE}, 124); System. out. println("write permission not enabled"); return; } basic. Camera(); } public class Main. Activity extends Activity { private final int PICTURE_ACTIVITY_CODE = 1; private final String FILENAME = "photo. jpg"; private Button m. Button. Capture; private File m. File; 6/7/2021 @Override public void on. Request. Permissions. Result(int request. Code, String permissions[], int[] grant. Results) { switch (request. Code) { case 124: { if (grant. Results. length > 0 && grant. Results[0] == Package. Manager. PERMISSION_GRANTED) { basic. Camera(); } } Android Sensor Programming 5

Basic Camera Usage n Modify Main. Activity. java private void basic. Camera() { if(!has.

Basic Camera Usage n Modify Main. Activity. java private void basic. Camera() { if(!has. Camera()) { Toast. make. Text(Main. Activity. this, "Has no physical camera", Toast. LENGTH_SHORT). show(); } if(!has. Defualt. Camera. App(Media. Store. ACTION_IMAGE_CAPTURE)) { Toast. make. Text(Main. Activity. this, "Has no default camera app", Toast. LENGTH_SHORT). show(); } m. Button. Capture = (Button) find. View. By. Id(R. id. btn. Capture); m. Button. Capture. set. On. Click. Listener(m. Capture. Listener); } protected void on. Activity. Result(int request. Code, int result. Code, Intent data) { if (request. Code == PICTURE_ACTIVITY_CODE) { if (result. Code == RESULT_OK) { Image. View image. View = (Image. View) find. View. By. Id(R. id. image. View 1); Uri input. File. Uri = Uri. from. File(m. File); Display the captured image. View. set. Image. URI(input. File. Uri); } } } 6/7/2021 Android Sensor Programming image in the Image. View 6

private void launch. Take. Photo() { Intent intent = new Intent(Media. Store. ACTION_IMAGE_CAPTURE); File

private void launch. Take. Photo() { Intent intent = new Intent(Media. Store. ACTION_IMAGE_CAPTURE); File images. Folder = new File(Environment. get. External. Storage. Public. Directory( Environment. DIRECTORY_PICTURES), "My. Images"); images. Folder. mkdirs(); m. File = new File(images. Folder, FILENAME); if(!m. File. exists()) { try { m. File. create. New. File(); } catch(IOException e) { e. print. Stack. Trace(); } } Uri uri. Saved. Image = Uri. from. File(m. File); intent. put. Extra(Media. Store. EXTRA_OUTPUT, uri. Saved. Image); start. Activity. For. Result(intent, PICTURE_ACTIVITY_CODE); } private On. Click. Listener m. Capture. Listener = new On. Click. Listener() { @Override public void on. Click(View v) { launch. Take. Photo(); } }; } 6/7/2021 Android Sensor Programming 7

// method to check if you have a Camera private boolean has. Camera(){ return

// method to check if you have a Camera private boolean has. Camera(){ return get. Package. Manager(). has. System. Feature(Package. Manager. FEATURE_CAMERA); } // method to check you have Camera Apps private boolean has. Defualt. Camera. App(String action){ final Package. Manager package. Manager = get. Package. Manager(); final Intent intent = new Intent(action); List<Resolve. Info> list = package. Manager. query. Intent. Activities(intent, Package. Manager. MATCH_DEFAULT_ONLY); return list. size() > 0; } 6/7/2021 Android Sensor Programming 8

Basic Camera Usage n This app brings up the default camera app to take

Basic Camera Usage n This app brings up the default camera app to take a picture. Then save it to a file and display it on screen 6/7/2021 Android Sensor Programming 9

Android Camera 2 APIs n n The android. hardware. camera 2 package provides an

Android Camera 2 APIs n n The android. hardware. camera 2 package provides an interface to individual camera devices connected to an Android device. It replaces the deprecated Camera class This package models a camera device as a pipeline, which takes in input requests for capturing a single frame, captures the single image per the request, and then outputs one capture result metadata packet, plus a set of output image buffers for the request The requests are processed in-order, and multiple requests can be in flight at once Since the camera device is a pipeline with multiple stages, having multiple requests in flight is required to maintain full framerate on most Android devices 6/7/2021 Android Sensor Programming 10

Android Camera 2 APIs n n To enumerate, query, and open available camera devices,

Android Camera 2 APIs n n To enumerate, query, and open available camera devices, obtain a Camera. Manager instance Individual Camera. Devices provide a set of static property information that describes the hardware device and the available settings and output parameters for the device. This information is provided through the Camera. Characteristics object, and is available through get. Camera. Characteristics(String) To capture or stream images from a camera device, the application must first create a camera capture session with a set of output Surfaces for use with the camera device, with create. Capture. Session(Session. Configuration) Each Surface has to be pre-configured with an appropriate size and format to match the sizes and formats available from the camera device q A target Surface can be obtained from a variety of classes, including Surface. View, Surface. Texture via Surface(Surface. Texture), Media. Codec, Media. Recorder, Allocation, and Image. Reader 6/7/2021 Android Sensor Programming 11

Android Camera 2 APIs n n Generally, camera preview images are sent to Surface.

Android Camera 2 APIs n n Generally, camera preview images are sent to Surface. View or Texture. View (via its Surface. Texture) Capture of JPEG images or RAW buffers for Dng. Creator can be done with Image. Reader with the JPEG and RAW_SENSOR formats Application-driven processing of camera data in Render. Script, Open. GL ES, or directly in managed or native code is best done through Allocation with a YUV Type, Surface. Texture, and Image. Reader with a YUV_420_888 format, respectively The app then needs to construct a Capture. Request, which defines all the capture parameters needed by a camera device to capture a single image q q The request also lists which of the configured output Surfaces should be used as targets for this capture The Camera. Device has a factory method for creating a request builder for a given use case, which is optimized for the Android device the application is running on 6/7/2021 Android Sensor Programming 12

Android Camera 2 APIs n Once the request has been set up, it can

Android Camera 2 APIs n Once the request has been set up, it can be handed to the active capture session either for a one-shot capture or for an endlessly repeating use q n Both methods also have a variant that accepts a list of requests to use as a burst capture / repeating burst After processing a request, the camera device will produce a Total. Capture. Result object, which contains information about the state of the camera device at time of capture, and the final settings used q q q These may vary somewhat from the request, if rounding or resolving contradictory parameters was necessary The camera device will also send a frame of image data into each of the output Surfaces included in the request These are produced asynchronously relative to the output Capture. Result, sometimes substantially later 6/7/2021 Android Sensor Programming 13

Android Camera 2 APIs http: //pierrchen. blogspot. com/2015/01/android-camera 2 -api-explained. html 6/7/2021 Android Sensor

Android Camera 2 APIs http: //pierrchen. blogspot. com/2015/01/android-camera 2 -api-explained. html 6/7/2021 Android Sensor Programming 14

Android Camera 2 APIs n Step 1. Start from Camera. Manager q q q

Android Camera 2 APIs n Step 1. Start from Camera. Manager q q q n We use it to iterate all the cameras that are available in the system, each with a designated camera. Id Using the camera. Id, we can get the properties of the specified camera device Those properties are represented by class Camera. Characteristics. Things like "is it front or back camera", "output resolutions supported" can be queried there Step 2. Setup the output targets q q The camera image data should always go to somewhere. Use Surface. View or Surface. Texture for preview, Image. Reader for still picture or Media. Recoder for video recording For all those classes mentioned, you always can create or get a surface, and pass that surface to camera, as a capture request target 6/7/2021 Android Sensor Programming 15

Android Camera 2 APIs n Step 3. Get a Camera. Device q q n

Android Camera 2 APIs n Step 3. Get a Camera. Device q q n You call Camera. Manager. open(camera. Id) to get a Camera. Device Since the call is asynchronized, you will get the Camera. Device in the on. Opened() callback 4. Create a Capture. Request from the Camera. Device q q A Capture. Request is a immutable package of settings and outputs needed to capture a single image from the camera device As shown in the class diagram, a Capture. Reques. Builder is created from Camera. Device with a predefined template (create. Capture. Request(Camera. Device. TEMPLATE_PREVIEW)). Then, we use the builder to set up the stuffs that varies. For example, usually you need to call add. Target(Surface) to set up the output targets for this specific Capture. Request 6/7/2021 Android Sensor Programming 16

Android Camera 2 APIs n Step 5. Create a Capture. Request. Session from the

Android Camera 2 APIs n Step 5. Create a Capture. Request. Session from the Camera. Device. q q n Consider a Capture. Request. Session as a context in which Capture. Request will be submitted To initialize a Capture. Request. Session, you have to provided the initialized Surface as the target surfaces, which were discussed at step 2 Step 6. Submit a Capture. Request to Capture. Request. Session q q There a couple of APIs to do that. Capture() is used to issue a one-time take picture command, while set. Repeating. Request() is used to issue a repeating request for the showing preview Also, you may want to set various settings, such as the auto focus mode and white balance mode, before submitting the request to start the preview or take a picture 6/7/2021 Android Sensor Programming 17

Android Camera 2 APIs n 7. Get the Capture Results q q q n

Android Camera 2 APIs n 7. Get the Capture Results q q q n The capture result will get back to you asynchronously through Camera. Capture. Session. Capture. Callback It is the place you can play a sound when the capture starts, or finishes The results will approach you piece by piece in Capture. Result on on. Capture. Processed, or you can wait and get them all in Total. Capture. Result on on. Capture. Complete. That is the step 8 in the diagram In all cases, the camera is the producer and the targets are the consumer q q q The camera keeps enqueuing the picture data and once the data is available the consumer will be notified to process them Texture. View will turn the picture data into textures and draw them in the area taken by the Texure. View Media. Recoder will pass the image to codec to compress and then write them out. For Image. Reader, it is up to you how to process the data. 6/7/2021 Android Sensor Programming 18

Live View Using Android Camera 2 APIs n n Build an app that display

Live View Using Android Camera 2 APIs n n Build an app that display the live view (without the need of the default camera app). Name the app Live. Capture Add permission to camera in manifest <uses-permission android: name="android. permission. CAMERA" /> <uses-permission android: name="android. permission. WRITE_EXTERNAL_STORAGE" /> <uses-feature android: name="android. hardware. camera 2. full" /> 6/7/2021 Android Sensor Programming 19

Live View n Modify activity_main. xml <? xml version="1. 0" encoding="utf-8"? > <Relative. Layout

Live View n Modify activity_main. xml <? xml version="1. 0" encoding="utf-8"? > <Relative. Layout xmlns: android="http: //schemas. android. com/apk/res/android" xmlns: app="http: //schemas. android. com/apk/res-auto" xmlns: tools="http: //schemas. android. com/tools" android: layout_width="match_parent" android: layout_height="match_parent" tools: context=". Main. Activity"> <Texture. View android: id="@+id/texture" android: layout_width="match_parent" android: layout_height="wrap_content" android: layout_above="@+id/btn. Takepicture" android: layout_align. Parent. Top="true"/> <Button android: id="@+id/btn. Switch. Camera" android: layout_width="wrap_content" android: layout_height="wrap_content" android: layout_align. Parent. Bottom="true" android: layout_to. Left. Of="@id/btn. Takepicture" android: layout_margin. Bottom="16 dp" android: layout_margin. Top="16 dp" android: text="Front Camera" /> <Button android: id="@+id/btn. Takepicture" android: layout_width="wrap_content" android: layout_height="wrap_content" android: layout_align. Parent. Bottom="true" android: layout_center. Horizontal="true" android: layout_margin. Bottom="16 dp" android: layout_margin. Top="16 dp" android: text=”Take Picture" /> </Relative. Layout> 6/7/2021 Android Sensor Programming 20

Live View n Modify Main. Activity. java import android. Manifest; import android. content. Context;

Live View n Modify Main. Activity. java import android. Manifest; import android. content. Context; import android. content. pm. Package. Manager; import android. graphics. Image. Format; import android. graphics. Surface. Texture; import android. hardware. camera 2. Camera. Access. Exception; import android. hardware. camera 2. Camera. Capture. Session; import android. hardware. camera 2. Camera. Characteristics; import android. hardware. camera 2. Camera. Device; import android. hardware. camera 2. Camera. Manager; import android. hardware. camera 2. Camera. Metadata; import android. hardware. camera 2. Capture. Request; import android. hardware. camera 2. Total. Capture. Result; import android. hardware. camera 2. params. Stream. Configuration. Map; import android. media. Image. Reader; import android. os. Bundle; import android. os. Environment; import android. os. Handler. Thread; import android. support. annotation. Null; import android. support. v 4. app. Activity. Compat; import android. support. v 7. app. App. Compat. Activity; 6/7/2021 Android Sensor Programming import android. util. Log; import android. util. Size; import android. util. Sparse. Int. Array; import android. view. Surface; import android. view. Texture. View; import android. view. View; import android. widget. Button; import android. widget. Toast; import java. io. File. Not. Found. Exception; import java. io. File. Output. Stream; import java. io. IOException; import java. io. Output. Stream; import java. nio. Byte. Buffer; import java. util. Array. List; import java. util. Arrays; import java. util. List; 21

Live View n Member variables 6/7/2021 public class Main. Activity extends App. Compat. Activity

Live View n Member variables 6/7/2021 public class Main. Activity extends App. Compat. Activity { private static final String TAG = "Android. Camera. Api"; private Button take. Picture. Button, switch. Camera. Button; private int current. Camera = 0; private Texture. View texture. View; private static final Sparse. Int. Array ORIENTATIONS = new Sparse. Int. Array(); 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 String camera. Id; protected Camera. Device camera. Device; protected Camera. Capture. Session camera. Capture. Sessions; protected Capture. Request capture. Request; protected Capture. Request. Builder capture. Request. Builder; private Size image. Dimension; private Image. Reader image. Reader; private File file; private static final int REQUEST_CAMERA_PERMISSION = 200; private boolean m. Flash. Supported; private Handler m. Background. Handler; private Handler. Thread m. Background. Thread; Android Sensor Programming 22

@Override protected void on. Create(Bundle saved. Instance. State) { super. on. Create(saved. Instance. State);

@Override protected void on. Create(Bundle saved. Instance. State) { super. on. Create(saved. Instance. State); set. Content. View(R. layout. activity_main); texture. View = (Texture. View) find. View. By. Id(R. id. texture); assert texture. View != null; texture. View. set. Surface. Texture. Listener(texture. Listener); 6/7/2021 take. Picture. Button = (Button) find. View. By. Id(R. id. btn. Takepicture); assert take. Picture. Button != null; take. Picture. Button. set. On. Click. Listener(new View. On. Click. Listener() { @Override public void on. Click(View v) { take. Picture(); } }); switch. Camera. Button = (Button) find. View. By. Id(R. id. btn. Switch. Camera); assert switch. Camera. Button != null; switch. Camera. Button. set. On. Click. Listener(new View. On. Click. Listener() { @Override public void on. Click(View v) { close. Camera(); if(current. Camera == 0) { open. Camera(1); current. Camera = 1; switch. Camera. Button. set. Text("Back Camera"); } else { open. Camera(0); current. Camera = 0; switch. Camera. Button. set. Text("Front Camera"); } } }); Android Sensor Programming } 23

Texture. View. Surface. Texture. Listener texture. Listener = new Texture. View. Surface. Texture. Listener()

Texture. View. Surface. Texture. Listener texture. Listener = new Texture. View. Surface. Texture. Listener() { @Override public void on. Surface. Texture. Available(Surface. Texture surface, int width, int height) { open. Camera(current. Camera); } @Override public void on. Surface. Texture. Size. Changed(Surface. Texture surface, int width, int height) { // Transform you image captured size according to the surface width and height } @Override public boolean on. Surface. Texture. Destroyed(Surface. Texture surface) { return false; } @Override public void on. Surface. Texture. Updated(Surface. Texture surface) { } }; private final Camera. Device. State. Callback state. Callback = new Camera. Device. State. Callback() { @Override public void on. Opened(Camera. Device camera) { //This is called when the camera is open Log. e(TAG, "on. Opened"); camera. Device = camera; create. Camera. Preview(); } @Override public void on. Disconnected(Camera. Device camera) { camera. Device. close(); } @Override public void on. Error(Camera. Device camera, int error) { camera. Device. close(); camera. Device = null; } }; 6/7/2021 Android Sensor Programming 24

final Camera. Capture. Session. Capture. Callback capture. Callback. Listener = new Camera. Capture. Session.

final Camera. Capture. Session. Capture. Callback capture. Callback. Listener = new Camera. Capture. Session. Capture. Callback() { @Override public void on. Capture. Completed(Camera. Capture. Session session, Capture. Request request, Total. Capture. Result result) { super. on. Capture. Completed(session, request, result); Toast. make. Text(Main. Activity. this, "Saved: " + file, Toast. LENGTH_SHORT). show(); create. Camera. Preview(); } }; protected void start. Background. Thread() { m. Background. Thread = new Handler. Thread("Camera Background"); m. Background. Thread. start(); m. Background. Handler = new Handler(m. Background. Thread. get. Looper()); } protected void stop. Background. Thread() { m. Background. Thread. quit. Safely(); try { m. Background. Thread. join(); m. Background. Thread = null; m. Background. Handler = null; } catch (Interrupted. Exception e) { e. print. Stack. Trace(); } } 6/7/2021 Android Sensor Programming 25

protected void create. Camera. Preview() { try { Surface. Texture texture = texture. View.

protected void create. Camera. Preview() { try { Surface. Texture texture = texture. View. get. Surface. Texture(); assert texture != null; texture. set. Default. Buffer. Size(image. Dimension. get. Width(), image. Dimension. get. Height()); Surface surface = new Surface(texture); capture. Request. Builder = camera. Device. create. Capture. Request(Camera. Device. TEMPLATE_PREVIEW); capture. Request. Builder. add. Target(surface); camera. Device. create. Capture. Session(Arrays. as. List(surface), new Camera. Capture. Session. State. Callback(){ @Override public void on. Configured(@Non. Null Camera. Capture. Session camera. Capture. Session) { //The camera is already closed if (null == camera. Device) { return; } // When the session is ready, we start displaying the preview. camera. Capture. Sessions = camera. Capture. Session; update. Preview(); } @Override public void on. Configure. Failed(@Non. Null Camera. Capture. Session camera. Capture. Session) { Toast. make. Text(Main. Activity. this, "Configuration change", Toast. LENGTH_SHORT). show(); } }, null); } catch (Camera. Access. Exception e) { e. print. Stack. Trace(); } } 6/7/2021 Android Sensor Programming 26

private void open. Camera(int cid) { Camera. Manager manager = (Camera. Manager) get. System.

private void open. Camera(int cid) { Camera. Manager manager = (Camera. Manager) get. System. Service(Context. CAMERA_SERVICE); Log. e(TAG, "is camera open"); try { assert manager. get. Camera. Id. List(). length == 2; camera. Id = manager. get. Camera. Id. List()[cid]; Camera. Characteristics characteristics = manager. get. Camera. Characteristics(camera. Id); Stream. Configuration. Map map = characteristics. get(Camera. Characteristics. SCALER_STREAM_CONFIGURATION_MAP); assert map != null; image. Dimension = map. get. Output. Sizes(Surface. Texture. class)[0]; // Add permission for camera and let user grant the permission if (Activity. Compat. check. Self. Permission(this, Manifest. permission. CAMERA) != Package. Manager. PERMISSION_GRANTED && Activity. Compat. check. Self. Permission(this, Manifest. permission. WRITE_EXTERNAL_STORAGE) != Package. Manager. PERMISSION_GRANTED) { Activity. Compat. request. Permissions(Main. Activity. this, new String[]{Manifest. permission. CAMERA, Manifest. permission. WRITE_EXTERNAL_STORAGE}, REQUEST_CAMERA_PERMISSION); return; } manager. open. Camera(camera. Id, state. Callback, null); } catch (Camera. Access. Exception e) { e. print. Stack. Trace(); } } protected void update. Preview() { if(null == camera. Device) { Log. e(TAG, "update. Preview error, return"); } capture. Request. Builder. set(Capture. Request. CONTROL_MODE, Camera. Metadata. CONTROL_MODE_AUTO); try { camera. Capture. Sessions. set. Repeating. Request(capture. Request. Builder. build(), null, m. Background. Handler); } catch (Camera. Access. Exception e) { e. print. Stack. Trace(); } 6/7/2021 Android Sensor Programming 27

@Override public void on. Request. Permissions. Result(int request. Code, @Non. Null String[] permissions, @Non.

@Override public void on. Request. Permissions. Result(int request. Code, @Non. Null String[] permissions, @Non. Null int[] grant. Results) { if (request. Code == REQUEST_CAMERA_PERMISSION) { if (grant. Results[0] == Package. Manager. PERMISSION_DENIED) { // close the app Toast. make. Text(Main. Activity. this, ”Please grant permission", Toast. LENGTH_LONG). show(); finish(); } } } @Override protected void on. Resume() { private void close. Camera() { super. on. Resume(); if (null != camera. Device) { Log. e(TAG, "on. Resume"); camera. Device. close(); start. Background. Thread(); camera. Device = null; if (texture. View. is. Available()) { } open. Camera(current. Camera); if (null != image. Reader) { } else { image. Reader. close(); texture. View. set. Surface. Texture. Listener(texture. Listener); image. Reader = null; } } @Override protected void on. Pause() { Log. e(TAG, "on. Pause"); //close. Camera(); stop. Background. Thread(); super. on. Pause(); } 6/7/2021 Android Sensor Programming 28

protected void take. Picture() { if(null == camera. Device) { Log. e(TAG, "camera. Device

protected void take. Picture() { if(null == camera. Device) { Log. e(TAG, "camera. Device is null"); return; } Camera. Manager manager = (Camera. Manager) get. System. Service(Context. CAMERA_SERVICE); try { Camera. Characteristics characteristics = manager. get. Camera. Characteristics(camera. Device. get. Id()); Size[] jpeg. Sizes = null; if (characteristics != null) { jpeg. Sizes = characteristics. get(Camera. Characteristics. SCALER_STREAM_CONFIGURATION_MAP). get. Output. Sizes(Image. Format. JPEG); } int width = 640; int height = 480; if (jpeg. Sizes != null && 0 < jpeg. Sizes. length) { width = jpeg. Sizes[0]. get. Width(); height = jpeg. Sizes[0]. get. Height(); } Image. Reader reader = Image. Reader. new. Instance(width, height, Image. Format. JPEG, 1); List<Surface> output. Surfaces = new Array. List<Surface>(2); output. Surfaces. add(reader. get. Surface()); output. Surfaces. add(new Surface(texture. View. get. Surface. Texture())); final Capture. Request. Builder capture. Builder = camera. Device. create. Capture. Request(Camera. Device. TEMPLATE_STILL_CAPTURE); capture. Builder. add. Target(reader. get. Surface()); capture. Builder. set(Capture. Request. CONTROL_MODE, Camera. Metadata. CONTROL_MODE_AUTO); // Orientation int rotation = get. Window. Manager(). get. Default. Display(). get. Rotation(); capture. Builder. set(Capture. Request. JPEG_ORIENTATION, ORIENTATIONS. get(rotation)); final File file = new File(Environment. get. External. Storage. Directory()+"/pic. jpg"); take. Picture() continue on next page 6/7/2021 Android Sensor Programming 29

Image. Reader. On. Image. Available. Listener reader. Listener = new Image. Reader. On. Image.

Image. Reader. On. Image. Available. Listener reader. Listener = new Image. Reader. On. Image. Available. Listener() { @Override public void on. Image. Available(Image. Reader reader) { Image image = null; try { image = reader. acquire. Latest. Image(); Byte. Buffer buffer = image. get. Planes()[0]. get. Buffer(); byte[] bytes = new byte[buffer. capacity()]; buffer. get(bytes); save(bytes); } catch (File. Not. Found. Exception e) { e. print. Stack. Trace(); } catch (IOException e) { e. print. Stack. Trace(); } finally { if (image != null) { image. close(); } } } private void save(byte[] bytes) throws IOException { Output. Stream output = null; try { output = new File. Output. Stream(file); output. write(bytes); } finally { if (null != output) { output. close(); } }; reader. set. On. Image. Available. Listener(reader. Listener, m. Background. Handler); take. Picture() continue on next page 6/7/2021 Android Sensor Programming 30

final Camera. Capture. Session. Capture. Callback capture. Listener = new Camera. Capture. Session. Capture.

final Camera. Capture. Session. Capture. Callback capture. Listener = new Camera. Capture. Session. Capture. Callback() { @Override public void on. Capture. Completed(Camera. Capture. Session session, Capture. Request request, Total. Capture. Result result) { super. on. Capture. Completed(session, request, result); Toast. make. Text(Main. Activity. this, "Saved: " + file, Toast. LENGTH_SHORT). show(); create. Camera. Preview(); } }; camera. Device. create. Capture. Session(output. Surfaces, new Camera. Capture. Session. State. Callback() { @Override public void on. Configured(Camera. Capture. Session session) { try { session. capture(capture. Builder. build(), capture. Listener, m. Background. Handler); } catch (Camera. Access. Exception e) { e. print. Stack. Trace(); } } @Override public void on. Configure. Failed(Camera. Capture. Session session) { } }, m. Background. Handler); } catch (Camera. Access. Exception e) { e. print. Stack. Trace(); } } This conclude take. Picture() 6/7/2021 Android Sensor Programming 31

Homework# 24 n Develop the live view app using Camera 2 APIs 6/7/2021 CIS

Homework# 24 n Develop the live view app using Camera 2 APIs 6/7/2021 CIS 470: Mobile App Development 32