Skip to content

Commit 564e8aa

Browse files
committed
docs: Android University - Camera class
Change-Id: Idc0c6ca88b42908289701c8367cd5c403d85f71e
1 parent d25ad2f commit 564e8aa

File tree

5 files changed

+744
-0
lines changed

5 files changed

+744
-0
lines changed
14.9 KB
Binary file not shown.
Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
page.title=Controlling the Camera
2+
parent.title=Capturing Photos with the Camera
3+
parent.link=index.html
4+
5+
trainingnavtop=true
6+
previous.title=Recording Videos Simply
7+
previous.link=videobasics.html
8+
9+
@jd:body
10+
11+
12+
<div id="tb-wrapper">
13+
<div id="tb">
14+
15+
<h2>This lesson teaches you to</h2>
16+
<ol>
17+
<li><a href="#TaskOpenCamera">Open the Camera Object</a></li>
18+
<li><a href="#camera-preview">Create the Camera Preview</a></li>
19+
<li><a href="#TaskSettings">Modify Camera Settings</a></li>
20+
<li><a href="#TaskOrientation">Set the Preview Orientation</a></li>
21+
<li><a href="#TaskTakePicture">Take a Picture</a></li>
22+
<li><a href="#TaskRestartPreview">Restart the Preview</a></li>
23+
<li><a href="#TaskReleaseCamera">Stop the Preview and Release the Camera</a></li>
24+
</ol>
25+
26+
<h2>You should also read</h2>
27+
<ul>
28+
<li><a href="{@docRoot}guide/topics/media/camera.html#custom-camera">Building
29+
a Camera App</a></li>
30+
</ul>
31+
</div>
32+
</div>
33+
34+
<p>In this lesson, we discuss how to control the camera hardware directly using
35+
the framework APIs.</p>
36+
37+
<p>Directly controlling a device camera requires a lot more code than requesting pictures or videos
38+
from existing camera applications. However, if you want to build a specialized camera application or
39+
or something fully integrated in your app UI, this lesson shows you how.</p>
40+
41+
42+
<h2 id="TaskOpenCamera">Open the Camera Object</h2>
43+
44+
<p>Getting an instance of the {@link android.hardware.Camera} object is the first step in the
45+
process of directly controlling the camera. As Android's own Camera application does, the
46+
recommended way to access the camera is to open {@link android.hardware.Camera} on a separate thread
47+
that's launched from {@link android.app.Activity#onCreate onCreate()}. This approach is a good idea
48+
since it can take a while and might bog down the UI thread. However, in the sample application
49+
associated with this lesson, opening the camera is deferred to the {@link
50+
android.app.Activity#onResume onResume()} method to facilitate code reuse and keep the flow of
51+
control simple.</p>
52+
53+
<pre>
54+
private void openCameraPerIdAndSetPreview() {
55+
if (! safeCameraOpen(mCameraId)) {
56+
mCameraId = getFirstRearCameraID();
57+
safeCameraOpen(mCameraId);
58+
}
59+
60+
mPreview.setCamera(mCamera);
61+
}
62+
</pre>
63+
64+
<p>Since API level 9, the camera framework supports multiple cameras. If you use the
65+
legacy API and call {@link android.hardware.Camera#open open()} without an
66+
argument, you get the first rear-facing camera. Dealing with multiple cameras
67+
is an advanced topic and beyond the scope of this lesson. If you are really
68+
interested, check out the implementation of {@code getFirstRearCameraID()} in
69+
the sample app (downloadable at the top).</p>
70+
71+
<p>Calling {@link android.hardware.Camera#open Camera.open()} throws an
72+
exception if the camera is already in use by another application, so we wrap it
73+
in a {@code try} block.</p>
74+
75+
<pre>
76+
private boolean safeCameraOpen(int id) {
77+
boolean qOpened = false;
78+
79+
try {
80+
releaseCameraAndPreview();
81+
mCamera = Camera.open(mCameraId);
82+
qOpened = (mCamera != null);
83+
} catch (Exception e) {
84+
Log.e(getString(R.string.app_name), "failed to open Camera");
85+
e.printStackTrace();
86+
}
87+
88+
return qOpened;
89+
}
90+
91+
private void releaseCameraAndPreview() {
92+
mPreview.setCamera(null);
93+
if (mCamera != null) {
94+
mCamera.release();
95+
mCamera = null;
96+
}
97+
}
98+
</pre>
99+
100+
101+
<h2 id="camera-preview">Create the Camera Preview</h2>
102+
103+
<p>Taking a picture usually requires that your users see a preview of their subject before clicking
104+
the shutter. To do so, you can use a {@link android.view.SurfaceView} to draw previews of what the
105+
camera sensor is picking up.</p>
106+
107+
<h3 id="TaskSetPreview">Preview Class</h3>
108+
109+
<p>To get started with displaying a preview, you need preview class. The
110+
preview requires an implementation of the {@code
111+
android.view.SurfaceHolder.Callback} interface, which is used to pass image
112+
data from the camera hardware the application.</p>
113+
114+
<pre>
115+
class Preview extends ViewGroup implements SurfaceHolder.Callback {
116+
...
117+
118+
SurfaceView mSurfaceView;
119+
SurfaceHolder mHolder;
120+
121+
...
122+
123+
Preview(Context context) {
124+
super(context);
125+
126+
mSurfaceView = new SurfaceView(context);
127+
addView(mSurfaceView);
128+
129+
// Install a SurfaceHolder.Callback so we get notified when the
130+
// underlying surface is created and destroyed.
131+
mHolder = mSurfaceView.getHolder();
132+
mHolder.addCallback(this);
133+
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
134+
}
135+
...
136+
}
137+
</pre>
138+
139+
<p>The preview class must be passed to the {@link android.hardware.Camera} object before the live
140+
image preview can be started, as seen in {@code setCamera()} method of the sample,
141+
as shown in the next section.</p>
142+
143+
144+
<h3 id="TaskStartPreview">Set and Start the Preview</h2>
145+
146+
<p>A camera instance and its related preview must be created in a specific
147+
order, with the camera object being first. In the sample application, the
148+
process of initializing the camera is encapsulated so that {@link
149+
android.hardware.Camera#startPreview Camera.startPreview()} is called by the
150+
{@code setCamera()} method, whenever the user does something to change the
151+
camera. The preview must also be restarted in the preview class {@code
152+
surfaceChanged()} callback method.</p>
153+
154+
<pre>
155+
public void setCamera(Camera camera) {
156+
if (mCamera == camera) { return; }
157+
158+
stopPreviewAndFreeCamera();
159+
160+
mCamera = camera;
161+
162+
if (mCamera != null) {
163+
List&lt;Size> localSizes = mCamera.getParameters().getSupportedPreviewSizes();
164+
mSupportedPreviewSizes = localSizes;
165+
requestLayout();
166+
167+
try {
168+
mCamera.setPreviewDisplay(mHolder);
169+
} catch (IOException e) {
170+
e.printStackTrace();
171+
}
172+
173+
/*
174+
Important: Call startPreview() to start updating the preview surface. Preview must
175+
be started before you can take a picture.
176+
*/
177+
mCamera.startPreview();
178+
}
179+
}
180+
</pre>
181+
182+
183+
<h2 id="TaskSettings">Modify Camera Settings</h2>
184+
185+
<p>Camera settings change the way that the camera takes pictures, from the zoom
186+
level to exposure compensation. This example doesn’t do a whole lot with camera
187+
settings, but the APIs provide a wide array of options. The {@code surfaceChanged()} method in the
188+
sample app demonstrates how to get and set camera parameters:</p>
189+
190+
<pre>
191+
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
192+
// Now that the size is known, set up the camera parameters and begin
193+
// the preview.
194+
Camera.Parameters parameters = mCamera.getParameters();
195+
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
196+
requestLayout();
197+
mCamera.setParameters(parameters);
198+
199+
/*
200+
Important: Call startPreview() to start updating the preview surface. Preview must be
201+
started before you can take a picture.
202+
*/
203+
mCamera.startPreview();
204+
}
205+
</pre>
206+
207+
208+
<h2 id="TaskOrientation">Set the Preview Orientation</h2>
209+
210+
<p>Most camera applications lock the display into landscape mode because that is the natural
211+
orientation of the camera sensor. This setting does not prevent you from taking portrait-mode
212+
photos, because the orientation of the device is recorded in the EXIF header. The {@link
213+
android.hardware.Camera#setDisplayOrientation setCameraDisplayOrientation()} method lets you change
214+
how the preview is displayed without affecting how the image is recorded. However, in Android prior
215+
to API level 14, you must stop your preview before changing the orientation and then restart it.</p>
216+
217+
218+
<h2 id="TaskTakePicture">Take a Picture</h2>
219+
220+
<p>Use the {@link android.hardware.Camera#takePicture Camera.takePicture()}
221+
method to take a picture once the preview is started. You can create {@link
222+
android.hardware.Camera.PictureCallback} and {@link
223+
android.hardware.Camera.ShutterCallback} objects and pass them into {@link
224+
android.hardware.Camera#takePicture Camera.takePicture()}. Since the Android
225+
Camera application already does a great job capturing JPEG images, you should
226+
probably implement the raw-image callback.</p>
227+
228+
<p>If you want to grab images continously, you can create a {@link
229+
android.hardware.Camera.PreviewCallback} that implements {@link
230+
android.hardware.Camera.PreviewCallback#onPreviewFrame onPreviewFrame()}. For
231+
something in between, you can capture only selected preview frames, or set up a
232+
delayed action to call {@link android.hardware.Camera#takePicture
233+
takePicture()}.</p>
234+
235+
236+
<h2 id="TaskRestartPreview">Restart the Preview</h2>
237+
238+
<p>After a picture is taken, you must to restart the preview before the user
239+
can take another picture. In the example, the restart is done by overloading
240+
the shutter button, as shown below.</p>
241+
242+
<pre>
243+
&#64;Override
244+
public void onClick(View v) {
245+
switch(mPreviewState) {
246+
case K_STATE_FROZEN:
247+
mCamera.startPreview();
248+
mPreviewState = K_STATE_PREVIEW;
249+
break;
250+
251+
default:
252+
mCamera.takePicture( null, rawCallback, null);
253+
mPreviewState = K_STATE_BUSY;
254+
} // switch
255+
shutterBtnConfig();
256+
}
257+
</pre>
258+
259+
260+
<h2 id="TaskReleaseCamera">Stop the Preview and Release the Camera</h2>
261+
262+
<p>Once your application is done using the camera, it's time to clean up. In
263+
particular, you must release the {@link android.hardware.Camera} object, or you risk crashing other
264+
applications, including new instances of your own application.</p>
265+
266+
<p>When should you stop the preview and release the camera? Well, having your
267+
preview surface destroyed is a pretty good hint that it’s time to stop the
268+
preview and release the camera, as shown in these methods from the {@code
269+
Preview} class.</p>
270+
271+
<pre>
272+
public void surfaceDestroyed(SurfaceHolder holder) {
273+
// Surface will be destroyed when we return, so stop the preview.
274+
if (mCamera != null) {
275+
/*
276+
Call stopPreview() to stop updating the preview surface.
277+
*/
278+
mCamera.stopPreview();
279+
}
280+
}
281+
282+
/**
283+
* When this function returns, mCamera will be null.
284+
*/
285+
private void stopPreviewAndFreeCamera() {
286+
287+
if (mCamera != null) {
288+
/*
289+
Call stopPreview() to stop updating the preview surface.
290+
*/
291+
mCamera.stopPreview();
292+
293+
/*
294+
Important: Call release() to release the camera for use by other applications.
295+
Applications should release the camera immediately in onPause() (and re-open() it in
296+
onResume()).
297+
*/
298+
mCamera.release();
299+
300+
mCamera = null;
301+
}
302+
}
303+
</pre>
304+
305+
<p>In the example application, this procedure is also part of the {@code
306+
setCamera()} method, so initializing a camera always begins with stopping the
307+
preview.</p>
308+

docs/html/training/camera/index.jd

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
page.title=Capturing Photos with the Camera
2+
3+
trainingnavtop=true
4+
startpage=true
5+
next.title=Taking Photos Simply
6+
next.link=photobasics.html
7+
8+
@jd:body
9+
10+
<div id="tb-wrapper">
11+
<div id="tb">
12+
13+
14+
<h2>Dependencies and prerequisites</h2>
15+
<ul>
16+
<li>Android 1.5 (API level 3) or higher</li>
17+
<li>A device with a camera</li>
18+
</ul>
19+
20+
21+
<h2>You should also read</h2>
22+
<ul>
23+
<li><a href="{@docRoot}guide/topics/media/camera.html">Camera</a></li>
24+
<li><a href="{@docRoot}guide/topics/fundamentals/activities.html">Activities</a></li>
25+
</ul>
26+
27+
28+
<h2>Try it out</h2>
29+
30+
<div class="download-box">
31+
<a href="{@docRoot}shareables/training/PhotoIntentActivity.zip" class="button">Download the Intent sample</a>
32+
<p class="filename">PhotoIntentActivity.zip</p>
33+
</div>
34+
35+
</div>
36+
</div>
37+
38+
<p>The world was a dismal and featureless place before rich media became
39+
prevalent. Remember Gopher? We don't, either. For your app to become
40+
part of your users' lives, give them a way to put their lives into it.
41+
Using the on-board cameras, your application can enable users to augment what
42+
they see around them, make unique avatars, look for zombies around the corner,
43+
or simply share their experiences.</p>
44+
45+
<p>This class gets you clicking fast with some super-easy ways of
46+
leveraging existing camera applications. In later lessons, you dive deeper
47+
and learn how to control the camera hardware directly.</p>
48+
49+
50+
<h2>Lessons</h2>
51+
52+
<dl>
53+
<dt><b><a href="photobasics.html">Taking Photos Simply</a></b></dt>
54+
<dd>Leverage other applications and capture photos with just a few lines of code.</dd>
55+
<dt><b><a href="videobasics.html">Recording Videos Simply</a></b></dt>
56+
<dd>Leverage other applications and record videos with just a few lines of code.</dd>
57+
<dt><b><a href="cameradirect.html">Controlling the Camera</a></b></dt>
58+
<dd>Control the camera hardware directly and implement your own camera application.</dd>
59+
</dl>
60+

0 commit comments

Comments
 (0)