summaryrefslogtreecommitdiffstats
path: root/docs/html/guide/topics/media/camera.jd
blob: 56ef624b8f82c321d51ef9c38098d4f8db7513d5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
page.title=Camera
page.tags=photo,video,picture,mediarecorder
@jd:body

<div id="qv-wrapper">
  <div id="qv">
  <h2>In this document</h2>
  <ol>
    <li><a href="#considerations">Considerations</a></li>
    <li><a href="#basics">The Basics</a>
    <li><a href="#manifest">Manifest Declarations</a></li>
    <li><a href="#intents">Using Existing Camera Apps</a>
      <ol>
        <li><a href="#intent-image">Image capture intent</a></li>
        <li><a href="#intent-video">Video capture intent</a></li>
        <li><a href="#intent-receive">Receiving camera intent result</a></li>
      </ol>
    <li><a href="#custom-camera">Building a Camera App</a>
      <ol>
        <li><a href="#detect-camera">Detecting camera hardware</a></li>
        <li><a href="#access-camera">Accessing cameras</a></li>
        <li><a href="#check-camera-features">Checking camera features</a></li>
        <li><a href="#camera-preview">Creating a preview class</a></li>
        <li><a href="#preview-layout">Placing preview in a layout</a></li>
        <li><a href="#capture-picture">Capturing pictures</a></li>
        <li><a href="#capture-video">Capturing videos</a></li>
        <li><a href="#release-camera">Releasing the camera</a></li>
      </ol>
    </li>
    <li><a href="#saving-media">Saving Media Files</a></li>
    <li><a href="#camera-features">Camera Features</a>
      <ol>
        <li><a href="#check-feature">Checking feature availability</a></li>
        <li><a href="#using-features">Using camera features</a></li>
        <li><a href="#metering-focus-areas">Metering and focus areas</a></li>
        <li><a href="#face-detection">Face detection</a></li>
        <li><a href="#time-lapse-video">Time lapse video</a></li>
      </ol>
    </li>
  </ol>
  <h2>Key Classes</h2>
  <ol>
    <li>{@link android.hardware.Camera}</li>
    <li>{@link android.view.SurfaceView}</li>
    <li>{@link android.media.MediaRecorder}</li>
    <li>{@link android.content.Intent}</li>
  </ol>
  <h2>See also</h2>
  <ol>
    <li><a href="{@docRoot}guide/topics/media/mediaplayer.html">Media Playback</a></li>
    <li><a href="{@docRoot}guide/topics/data/data-storage.html">Data Storage</a></li>
  </ol>
  </div>
</div>


<p>The Android framework includes support for various cameras and camera features available on
devices, allowing you to capture pictures and videos in your applications. This document discusses a
quick, simple approach to image and video capture and outlines an advanced approach for creating
custom camera experiences for your users.</p>

<h2 id="considerations">Considerations</h2>
<p>Before enabling your application to use cameras on Android devices, you should consider a few
questions about how your app intends to use this hardware feature.</p>

<ul>
  <li><strong>Camera Requirement</strong> - Is the use of a camera so important to your
application that you do not want your application installed on a device that does not have a
camera? If so, you should declare the <a href="#manifest">camera requirement in your
manifest</a>.</li>

  <li><strong>Quick Picture or Customized Camera</strong> - How will your application use the
camera? Are you just interested in snapping a quick picture or video clip, or will your application
provide a new way to use cameras? For a getting a quick snap or clip, consider
<a href="#intents">Using Existing Camera Apps</a>. For developing a customized camera feature, check
out the <a href="#custom-camera">Building a Camera App</a> section.</li>

  <li><strong>Storage</strong> - Are the images or videos your application generates intended to be
only visible to your application or shared so that other applications such as Gallery or other
media and social apps can use them? Do you want the pictures and videos to be available even if your
application is uninstalled? Check out the <a href="#saving-media">Saving Media Files</a> section to
see how to implement these options.</li>
</ul>



<h2 id="basics">The Basics</h2>
<p>The Android framework supports capturing images and video through the
{@link android.hardware.Camera} API or camera {@link android.content.Intent}. Here are the relevant
classes:</p>

<dl>
  <dt>{@link android.hardware.Camera}</dt>
  <dd>This class is the primary API for controlling device cameras. This class is used to take
pictures or videos when you are building a camera application.</dd>

  <dt>{@link android.view.SurfaceView}</dt>
  <dd>This class is used to present a live camera preview to the user.</dd>

  <dt>{@link android.media.MediaRecorder}</dt>
  <dd>This class is used to record video from the camera.</dd>

  <dt>{@link android.content.Intent}</dt>
  <dd>An intent action type of {@link android.provider.MediaStore#ACTION_IMAGE_CAPTURE
MediaStore.ACTION_IMAGE_CAPTURE} or {@link android.provider.MediaStore#ACTION_VIDEO_CAPTURE
MediaStore.ACTION_VIDEO_CAPTURE} can be used to capture images or videos without directly
using the {@link android.hardware.Camera} object.</dd>
</dl>


<h2 id="manifest">Manifest Declarations</h2>
<p>Before starting development on your application with the Camera API, you should make sure
your manifest has the appropriate declarations to allow use of camera hardware and other
related features.</p>

<ul>
  <li><strong>Camera Permission</strong> - Your application must request permission to use a device
camera.
<pre>
&lt;uses-permission android:name=&quot;android.permission.CAMERA&quot; /&gt;
</pre>
  <p class="note"><strong>Note:</strong> If you are using the camera <a href="#intents">via an
intent</a>, your application does not need to request this permission.</p>
  </li>
  <li><strong>Camera Features</strong> - Your application must also declare use of camera features,
for example:
<pre>
&lt;uses-feature android:name=&quot;android.hardware.camera&quot; /&gt;
</pre>
  <p>For a list of camera features, see the manifest
<a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#hw-features">Features
Reference</a>.</p>
  <p>Adding camera features to your manifest causes Google Play to prevent your application from
being installed to devices that do not include a camera or do not support the camera features you
specify. For more information about using feature-based filtering with Google Play, see <a
href="{@docRoot}guide/topics/manifest/uses-feature-element.html#market-feature-filtering">Google
Play and Feature-Based Filtering</a>.</p>
  <p>If your application <em>can use</em> a camera or camera feature for proper operation, but does
not <em>require</em> it, you should specify this in the manifest by including the {@code
android:required} attribute, and setting it to {@code false}:</p>
<pre>
&lt;uses-feature android:name="android.hardware.camera" android:required="false" /&gt;
</pre>

  </li>
  <li><strong>Storage Permission</strong> - If your application saves images or videos to the
device's external storage (SD Card), you must also specify this in the manifest.
<pre>
&lt;uses-permission android:name=&quot;android.permission.WRITE_EXTERNAL_STORAGE&quot; /&gt;
</pre>
  </li>
  <li><strong>Audio Recording Permission</strong> - For recording audio with video capture, your
application must request the audio capture permission.
<pre>
&lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
</pre>
  </li>
  <li><strong>Location Permission</strong> - If your application tags images with GPS location
information, you must request location permission:
<pre>
&lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /&gt;
</pre>
<p>For more information about getting user location, see
<a href="{@docRoot}guide/topics/location/strategies.html">Location Strategies</a>.</p>
  </li>
</ul>


<h2 id="intents">Using Existing Camera Apps</h2>
<p>A quick way to enable taking pictures or videos in your application without a lot of extra code
is to use an {@link android.content.Intent} to invoke an existing Android camera application. A
camera intent makes a request to capture a picture or video clip through an existing camera app and
then returns control back to your application. This section shows you how to capture an image or
video using this technique.</p>

<p>The procedure for invoking a camera intent follows these general steps:</p>

<ol>
  <li><strong>Compose a Camera Intent</strong> - Create an {@link android.content.Intent} that
requests an image or video, using one of these intent types:
    <ul>
      <li>{@link android.provider.MediaStore#ACTION_IMAGE_CAPTURE MediaStore.ACTION_IMAGE_CAPTURE} -
Intent action type for requesting an image from an existing camera application.</li>
      <li>{@link android.provider.MediaStore#ACTION_VIDEO_CAPTURE MediaStore.ACTION_VIDEO_CAPTURE} -
Intent action type for requesting a video from an existing camera application. </li>
    </ul>
  </li>
  <li><strong>Start the Camera Intent</strong> - Use the {@link
android.app.Activity#startActivityForResult(android.content.Intent, int) startActivityForResult()}
method to execute the camera intent. After you start the intent, the Camera application user
interface appears on the device screen and the user can take a picture or video.</li>
  <li><strong>Receive the Intent Result</strong> - Set up an {@link
android.app.Activity#onActivityResult(int, int, android.content.Intent) onActivityResult()} method
in your application to receive the callback and data from the camera intent. When the user
finishes taking a picture or video (or cancels the operation), the system calls this method.</li>
</ol>


<h3 id="intent-image">Image capture intent</h3>
<p>Capturing images using a camera intent is quick way to enable your application to take pictures
with minimal coding. An image capture intent can include the following extra information:</p>

<ul>
  <li>{@link android.provider.MediaStore#EXTRA_OUTPUT MediaStore.EXTRA_OUTPUT} - This setting
requires a {@link android.net.Uri} object specifying a path and file name where you'd like to
save the picture. This setting is optional but strongly recommended. If you do not specify this
value, the camera application saves the requested picture in the default location with a default
name, specified in the returned intent's {@link android.content.Intent#getData() Intent.getData()}
field.</li>
</ul>

<p>The following example demonstrates how to construct a image capture intent and execute it.
The {@code getOutputMediaFileUri()} method in this example refers to the sample code shown in <a
href= "#saving-media">Saving Media Files</a>.</p>

<pre>
private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
private Uri fileUri;

&#64;Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // create Intent to take a picture and return control to the calling application
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

    fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); // create a file to save the image
    intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name

    // start the image capture Intent
    startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
}
</pre>

<p>When the {@link android.app.Activity#startActivityForResult(android.content.Intent, int)
startActivityForResult()} method is executed, users see a camera application interface.
After the user finishes taking a picture (or cancels the operation), the user interface returns to
your application, and you must intercept the {@link
android.app.Activity#onActivityResult(int, int, android.content.Intent) onActivityResult()}
method to receive the result of the intent and continue your application execution. For information
on how to receive the completed intent, see <a href="#intent-receive">Receiving camera intent
result</a>.</p>


<h3 id="intent-video">Video capture intent</h3>
<p>Capturing video using a camera intent is a quick way to enable your application to take videos
with minimal coding. A video capture intent can include the following extra information:</p>

<ul>
  <li>{@link android.provider.MediaStore#EXTRA_OUTPUT MediaStore.EXTRA_OUTPUT} - This setting
requires a {@link android.net.Uri} specifying a path and file name where you'd like to save the
video. This setting is optional but strongly recommended. If you do not specify this value, the
Camera application saves the requested video in the default location with a default name, specified
in the returned intent's {@link android.content.Intent#getData() Intent.getData()} field.</li>
  <li>{@link android.provider.MediaStore#EXTRA_VIDEO_QUALITY MediaStore.EXTRA_VIDEO_QUALITY} -
This value can be 0 for lowest quality and smallest file size or 1 for highest quality and
larger file size.</li>
  <li>{@link android.provider.MediaStore#EXTRA_DURATION_LIMIT MediaStore.EXTRA_DURATION_LIMIT} -
Set this value to limit the length, in seconds, of the video being captured.</li>
  <li>{@link android.provider.MediaStore#EXTRA_SIZE_LIMIT MediaStore.EXTRA_SIZE_LIMIT} -
Set this value to limit the file size, in bytes, of the video being captured.
</li>
</ul>

<p>The following example demonstrates how to construct a video capture intent and execute it.
The {@code getOutputMediaFileUri()} method in this example refers to the sample code shown in <a
href= "#saving-media">Saving Media Files</a>.</p>

<pre>
private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200;
private Uri fileUri;

&#64;Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    //create new Intent
    Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);

    fileUri = getOutputMediaFileUri(MEDIA_TYPE_VIDEO);  // create a file to save the video
    intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);  // set the image file name

    intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); // set the video image quality to high

    // start the Video Capture Intent
    startActivityForResult(intent, CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE);
}
</pre>

<p>When the {@link
android.app.Activity#startActivityForResult(android.content.Intent, int)
startActivityForResult()} method is executed, users see a modified camera application interface.
After the user finishes taking a video (or cancels the operation), the user interface
returns to your application, and you must intercept the {@link
android.app.Activity#onActivityResult(int, int, android.content.Intent) onActivityResult()}
method to receive the result of the intent and continue your application execution. For information
on how to receive the completed intent, see the next section.</p>

<h3 id="intent-receive">Receiving camera intent result</h3>
<p>Once you have constructed and executed an image or video camera intent, your application must be
configured to receive the result of the intent. This section shows you how to intercept the callback
from a camera intent so your application can do further processing of the captured image or
video.</p>

<p>In order to receive the result of an intent, you must override the {@link
android.app.Activity#onActivityResult(int, int, android.content.Intent) onActivityResult()} in the
activity that started the intent. The following example demonstrates how to override {@link
android.app.Activity#onActivityResult(int, int, android.content.Intent) onActivityResult()} to
capture the result of the <a href="#intent-image">image camera intent</a> or <a
href="#intent-video">video camera intent</a> examples shown in the previous sections.</p>

<pre>
private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200;

&#64;Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
        if (resultCode == RESULT_OK) {
            // Image captured and saved to fileUri specified in the Intent
            Toast.makeText(this, "Image saved to:\n" +
                     data.getData(), Toast.LENGTH_LONG).show();
        } else if (resultCode == RESULT_CANCELED) {
            // User cancelled the image capture
        } else {
            // Image capture failed, advise user
        }
    }

    if (requestCode == CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE) {
        if (resultCode == RESULT_OK) {
            // Video captured and saved to fileUri specified in the Intent
            Toast.makeText(this, "Video saved to:\n" +
                     data.getData(), Toast.LENGTH_LONG).show();
        } else if (resultCode == RESULT_CANCELED) {
            // User cancelled the video capture
        } else {
            // Video capture failed, advise user
        }
    }
}
</pre>

<p>Once your activity receives a successful result, the captured image or video is available in the
specified location for your application to access.</p>



<h2 id="custom-camera">Building a Camera App</h2>
<p>Some developers may require a camera user interface that is customized to the look of their
application or provides special features. Creating a customized camera activity requires more
code than <a href="#intents">using an intent</a>, but it can provide a more compelling experience
for your users.</p>

<p>The general steps for creating a custom camera interface for your application are as follows:</p>

<ul>
   <li><strong>Detect and Access Camera</strong> - Create code to check for the existence of
cameras and request access.</li>
   <li><strong>Create a Preview Class</strong> - Create a camera preview class that extends {@link
android.view.SurfaceView} and implements the {@link android.view.SurfaceHolder} interface. This
class previews the live images from the camera.</li>
   <li><strong>Build a Preview Layout</strong> - Once you have the camera preview class, create a
view layout that incorporates the preview and the user interface controls you want.</li>
   <li><strong>Setup Listeners for Capture</strong> - Connect listeners for your interface
controls to start image or video capture in response to user actions, such as pressing a
button.</li>
   <li><strong>Capture and Save Files</strong> - Setup the code for capturing pictures or
videos and saving the output.</li>
   <li><strong>Release the Camera</strong> - After using the camera, your application must
properly release it for use by other applications.</li>
</ul>

<p>Camera hardware is a shared resource that must be carefully managed so your application does
not collide with other applications that may also want to use it. The following sections discusses
how to detect camera hardware, how to request access to a camera, how to capture pictures or video
and how to release the camera when your application is done using it.</p>

<p class="caution"><strong>Caution:</strong> Remember to release the {@link android.hardware.Camera}
object by calling the {@link android.hardware.Camera#release() Camera.release()} when your
application is done using it! If your application does not properly release the camera, all
subsequent attempts to access the camera, including those by your own application, will fail and may
cause your or other applications to be shut down.</p>


<h3 id="detect-camera">Detecting camera hardware</h3>
<p>If your application does not specifically require a camera using a manifest declaration, you
should check to see if a camera is available at runtime. To perform this check, use the {@link
android.content.pm.PackageManager#hasSystemFeature(java.lang.String)
PackageManager.hasSystemFeature()} method, as shown in the example code below:</p>

<pre>
/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
    if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
        // this device has a camera
        return true;
    } else {
        // no camera on this device
        return false;
    }
}
</pre>

<p>Android devices can have multiple cameras, for example a back-facing camera for photography and a
front-facing camera for video calls. Android 2.3 (API Level 9) and later allows you to check the
number of cameras available on a device using the {@link
android.hardware.Camera#getNumberOfCameras() Camera.getNumberOfCameras()} method.</p>

<h3 id="access-camera">Accessing cameras</h3>
<p>If you have determined that the device on which your application is running has a camera, you
must request to access it by getting an instance of {@link android.hardware.Camera} (unless you
are using an <a href="#intents">intent to access the camera</a>). </p>

<p>To access the primary camera, use the {@link android.hardware.Camera#open() Camera.open()} method
and be sure to catch any exceptions, as shown in the code below:</p>

<pre>
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(){
    Camera c = null;
    try {
        c = Camera.open(); // attempt to get a Camera instance
    }
    catch (Exception e){
        // Camera is not available (in use or does not exist)
    }
    return c; // returns null if camera is unavailable
}
</pre>

<p class="caution"><strong>Caution:</strong> Always check for exceptions when using {@link
android.hardware.Camera#open() Camera.open()}. Failing to check for exceptions if the camera is in
use or does not exist will cause your application to be shut down by the system.</p>

<p>On devices running Android 2.3 (API Level 9) or higher, you can access specific cameras using
{@link android.hardware.Camera#open(int) Camera.open(int)}. The example code above will access
the first, back-facing camera on a device with more than one camera.</p>

<h3 id="check-camera-features">Checking camera features</h3>
<p>Once you obtain access to a camera, you can get further information about its capabilities using
the {@link android.hardware.Camera#getParameters() Camera.getParameters()} method and checking the
returned {@link android.hardware.Camera.Parameters} object for supported capabilities. When using
API Level 9 or higher, use the {@link android.hardware.Camera#getCameraInfo(int,
android.hardware.Camera.CameraInfo) Camera.getCameraInfo()} to determine if a camera is on the front
or back of the device, and the orientation of the image.</p>



<h3 id="camera-preview">Creating a preview class</h3>
<p>For users to effectively take pictures or video, they must be able to see what the device camera
sees. A camera preview class is a {@link android.view.SurfaceView} that can display the live image
data coming from a camera, so users can frame and capture a picture or video.</p>

<p>The following example code demonstrates how to create a basic camera preview class that can be
included in a {@link android.view.View} layout. This class implements {@link
android.view.SurfaceHolder.Callback SurfaceHolder.Callback} in order to capture the callback events
for creating and destroying the view, which are needed for assigning the camera preview input.</p>

<pre>
/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder mHolder;
    private Camera mCamera;

    public CameraPreview(Context context, Camera camera) {
        super(context);
        mCamera = camera;

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, now tell the camera where to draw the preview.
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
            Log.d(TAG, "Error setting camera preview: " + e.getMessage());
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        // empty. Take care of releasing the Camera preview in your activity.
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // If your preview can change or rotate, take care of those events here.
        // Make sure to stop the preview before resizing or reformatting it.

        if (mHolder.getSurface() == null){
          // preview surface does not exist
          return;
        }

        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e){
          // ignore: tried to stop a non-existent preview
        }

        // set preview size and make any resize, rotate or
        // reformatting changes here

        // start preview with new settings
        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();

        } catch (Exception e){
            Log.d(TAG, "Error starting camera preview: " + e.getMessage());
        }
    }
}
</pre>

<p>If you want to set a specific size for your camera preview, set this in the {@code
surfaceChanged()} method as noted in the comments above. When setting preview size, you
<em>must use</em> values from {@link android.hardware.Camera.Parameters#getSupportedPreviewSizes}.
<em>Do not</em> set arbitrary values in the {@link
android.hardware.Camera.Parameters#setPreviewSize setPreviewSize()} method.</p>


<h3 id="preview-layout">Placing preview in a layout</h3>
<p>A camera preview class, such as the example shown in the previous section, must be placed in the
layout of an activity along with other user interface controls for taking a picture or video. This
section shows you how to build a basic layout and activity for the preview.</p>

<p>The following layout code provides a very basic view that can be used to display a camera
preview. In this example, the {@link android.widget.FrameLayout} element is meant to be the
container for the camera preview class. This layout type is used so that additional picture
information or controls can be overlayed on the live camera preview images.</p>

<pre>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    android:orientation=&quot;horizontal&quot;
    android:layout_width=&quot;fill_parent&quot;
    android:layout_height=&quot;fill_parent&quot;
    &gt;
  &lt;FrameLayout
    android:id=&quot;@+id/camera_preview&quot;
    android:layout_width=&quot;fill_parent&quot;
    android:layout_height=&quot;fill_parent&quot;
    android:layout_weight=&quot;1&quot;
    /&gt;

  &lt;Button
    android:id=&quot;@+id/button_capture&quot;
    android:text=&quot;Capture&quot;
    android:layout_width=&quot;wrap_content&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:layout_gravity=&quot;center&quot;
    /&gt;
&lt;/LinearLayout&gt;
</pre>

<p>On most devices, the default orientation of the camera preview is landscape. This example layout
specifies a horizontal (landscape) layout and the code below fixes the orientation of the
application to landscape. For simplicity in rendering a camera preview, you should change your
application's preview activity orientation to landscape by adding the following to your
manifest.</p>

<pre>
&lt;activity android:name=&quot;.CameraActivity&quot;
          android:label=&quot;@string/app_name&quot;

          android:screenOrientation=&quot;landscape&quot;&gt;
          &lt;!-- configure this activity to use landscape orientation --&gt;

          &lt;intent-filter&gt;
        &lt;action android:name=&quot;android.intent.action.MAIN&quot; /&gt;
        &lt;category android:name=&quot;android.intent.category.LAUNCHER&quot; /&gt;
    &lt;/intent-filter&gt;
&lt;/activity&gt;
</pre>

<p class="note"><strong>Note:</strong> A camera preview does not have to be in landscape mode.
Starting in Android 2.2 (API Level 8), you can use the {@link
android.hardware.Camera#setDisplayOrientation(int) setDisplayOrientation()} method to set the
rotation of the preview image. In order to change preview orientation as the user re-orients the
phone, within the {@link
android.view.SurfaceHolder.Callback#surfaceChanged(android.view.SurfaceHolder, int, int, int)
surfaceChanged()} method of your preview class, first stop the preview with {@link
android.hardware.Camera#stopPreview() Camera.stopPreview()} change the orientation and then
start the preview again with {@link android.hardware.Camera#startPreview()
Camera.startPreview()}.</p>

<p>In the activity for your camera view, add your preview class to the {@link
android.widget.FrameLayout} element shown in the example above. Your camera activity must also
ensure that it releases the camera when it is paused or shut down. The following example shows how
to modify a camera activity to attach the preview class shown in <a href="#camera-preview">Creating
a preview class</a>.</p>

<pre>
public class CameraActivity extends Activity {

    private Camera mCamera;
    private CameraPreview mPreview;

    &#64;Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // Create an instance of Camera
        mCamera = getCameraInstance();

        // Create our Preview view and set it as the content of our activity.
        mPreview = new CameraPreview(this, mCamera);
        FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
        preview.addView(mPreview);
    }
}
</pre>

<p class="note"><strong>Note:</strong> The {@code getCameraInstance()} method in the example above
refers to the example method shown in <a href="#access-camera">Accessing cameras</a>.</p>


<h3 id="capture-picture">Capturing pictures</h3>
<p>Once you have built a preview class and a view layout in which to display it, you are ready to
start capturing images with your application. In your application code, you must set up listeners
for your user interface controls to respond to a user action by taking a picture.</p>

<p>In order to retrieve a picture, use the {@link
android.hardware.Camera#takePicture(android.hardware.Camera.ShutterCallback,
android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback)
Camera.takePicture()} method. This method takes three parameters which receive data from the camera.
In order to receive data in a JPEG format, you must implement an {@link
android.hardware.Camera.PictureCallback} interface to receive the image data and
write it to a file. The following code shows a basic implementation of the {@link
android.hardware.Camera.PictureCallback} interface to save an image received from the camera.</p>

<pre>
private PictureCallback mPicture = new PictureCallback() {

    &#64;Override
    public void onPictureTaken(byte[] data, Camera camera) {

        File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
        if (pictureFile == null){
            Log.d(TAG, "Error creating media file, check storage permissions: " +
                e.getMessage());
            return;
        }

        try {
            FileOutputStream fos = new FileOutputStream(pictureFile);
            fos.write(data);
            fos.close();
        } catch (FileNotFoundException e) {
            Log.d(TAG, "File not found: " + e.getMessage());
        } catch (IOException e) {
            Log.d(TAG, "Error accessing file: " + e.getMessage());
        }
    }
};
</pre>

<p>Trigger capturing an image by calling the {@link
android.hardware.Camera#takePicture(android.hardware.Camera.ShutterCallback,
android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback)
Camera.takePicture()} method. The following example code shows how to call this method from a
button {@link android.view.View.OnClickListener}.</p>

<pre>
// Add a listener to the Capture button
Button captureButton = (Button) findViewById(id.button_capture);
captureButton.setOnClickListener(
    new View.OnClickListener() {
        &#64;Override
        public void onClick(View v) {
            // get an image from the camera
            mCamera.takePicture(null, null, mPicture);
        }
    }
);
</pre>

<p class="note"><strong>Note:</strong> The {@code mPicture} member in the following example refers
to the example code above.</p>

<p class="caution"><strong>Caution:</strong> Remember to release the {@link android.hardware.Camera}
object by calling the {@link android.hardware.Camera#release() Camera.release()} when your
application is done using it! For information about how to release the camera, see <a
href="#release-camera">Releasing the camera</a>.</p>


<h3 id="capture-video">Capturing videos</h3>

<p>Video capture using the Android framework requires careful management of the {@link
android.hardware.Camera} object and coordination with the {@link android.media.MediaRecorder}
class. When recording video with {@link android.hardware.Camera}, you must manage the {@link
android.hardware.Camera#lock() Camera.lock()} and {@link android.hardware.Camera#unlock()
Camera.unlock()} calls to allow {@link android.media.MediaRecorder} access to the camera hardware,
in addition to the {@link android.hardware.Camera#open() Camera.open()} and {@link
android.hardware.Camera#release() Camera.release()} calls.</p>

<p class="note"><strong>Note:</strong> Starting with Android 4.0 (API level 14), the {@link
android.hardware.Camera#lock() Camera.lock()} and {@link android.hardware.Camera#unlock()
Camera.unlock()} calls are managed for you automatically.</p>

<p>Unlike taking pictures with a device camera, capturing video requires a very particular call
order. You must follow a specific order of execution to successfully prepare for and capture video
with your application, as detailed below.</p>

<ol>
  <li><strong>Open Camera</strong> - Use the {@link android.hardware.Camera#open() Camera.open()}
to get an instance of the camera object.</li>
  <li><strong>Connect Preview</strong> - Prepare a live camera image preview by connecting a {@link
android.view.SurfaceView} to the camera using {@link
android.hardware.Camera#setPreviewDisplay(android.view.SurfaceHolder) Camera.setPreviewDisplay()}.
  </li>
  <li><strong>Start Preview</strong> - Call {@link android.hardware.Camera#startPreview()
Camera.startPreview()} to begin displaying the live camera images.</li>
  <li><strong>Start Recording Video</strong> - The following steps must be completed <em>in
order</em> to successfully record video:
    <ol style="list-style-type: lower-alpha;">
      <li><strong>Unlock the Camera</strong> - Unlock the camera for use by {@link
android.media.MediaRecorder} by calling {@link android.hardware.Camera#unlock()
Camera.unlock()}.</li>
      <li><strong>Configure MediaRecorder</strong> - Call in the following {@link
android.media.MediaRecorder} methods <em>in this order</em>. For more information, see the {@link
android.media.MediaRecorder} reference documentation.
        <ol>
          <li>{@link android.media.MediaRecorder#setCamera(android.hardware.Camera)
setCamera()} - Set the camera to be used for video capture, use your application's current instance
of {@link android.hardware.Camera}.</li>
          <li>{@link android.media.MediaRecorder#setAudioSource(int) setAudioSource()} - Set the
audio source, use {@link android.media.MediaRecorder.AudioSource#CAMCORDER
MediaRecorder.AudioSource.CAMCORDER}. </li>
          <li>{@link android.media.MediaRecorder#setVideoSource(int) setVideoSource()} - Set
the video source, use {@link android.media.MediaRecorder.VideoSource#CAMERA
MediaRecorder.VideoSource.CAMERA}.</li>
          <li>Set the video output format and encoding. For Android 2.2 (API Level 8) and
higher, use the {@link android.media.MediaRecorder#setProfile(android.media.CamcorderProfile)
MediaRecorder.setProfile} method, and get a profile instance using {@link
android.media.CamcorderProfile#get(int) CamcorderProfile.get()}. For versions of Android prior to
2.2, you must set the video output format and encoding parameters:
          <ol style="list-style-type: lower-roman;">
            <li>{@link android.media.MediaRecorder#setOutputFormat(int) setOutputFormat()} - Set
the output format, specify the default setting or {@link
android.media.MediaRecorder.OutputFormat#MPEG_4 MediaRecorder.OutputFormat.MPEG_4}.</li>
            <li>{@link android.media.MediaRecorder#setAudioEncoder(int) setAudioEncoder()} - Set
the sound encoding type, specify the default setting or {@link
android.media.MediaRecorder.AudioEncoder#AMR_NB MediaRecorder.AudioEncoder.AMR_NB}.</li>
            <li>{@link android.media.MediaRecorder#setVideoEncoder(int) setVideoEncoder()} - Set
the video encoding type, specify the default setting or {@link
android.media.MediaRecorder.VideoEncoder#MPEG_4_SP MediaRecorder.VideoEncoder.MPEG_4_SP}.</li>
          </ol>
          </li>
          <li>{@link android.media.MediaRecorder#setOutputFile(java.lang.String) setOutputFile()} -
Set the output file, use {@code getOutputMediaFile(MEDIA_TYPE_VIDEO).toString()} from the example
method in the <a href="#saving-media">Saving Media Files</a> section.</li>
          <li>{@link android.media.MediaRecorder#setPreviewDisplay(android.view.Surface)
setPreviewDisplay()} - Specify the {@link android.view.SurfaceView} preview layout element for
your application. Use the same object you specified for <strong>Connect Preview</strong>.</li>
        </ol>
        <p class="caution"><strong>Caution:</strong> You must call these {@link
android.media.MediaRecorder} configuration methods <em>in this order</em>, otherwise your
application will encounter errors and the recording will fail.</p>
      </li>
      <li><strong>Prepare MediaRecorder</strong> - Prepare the {@link android.media.MediaRecorder}
with provided configuration settings by calling {@link android.media.MediaRecorder#prepare()
MediaRecorder.prepare()}.</li>
      <li><strong>Start MediaRecorder</strong> - Start recording video by calling {@link
android.media.MediaRecorder#start() MediaRecorder.start()}.</li>
    </ol>
  </li>
  <li><strong>Stop Recording Video</strong> - Call the following methods <em>in order</em>, to
successfully complete a video recording:
    <ol style="list-style-type: lower-alpha;">
      <li><strong>Stop MediaRecorder</strong> - Stop recording video by calling {@link
android.media.MediaRecorder#stop() MediaRecorder.stop()}.</li>
      <li><strong>Reset MediaRecorder</strong> - Optionally, remove the configuration settings from
the recorder by calling {@link android.media.MediaRecorder#reset() MediaRecorder.reset()}.</li>
      <li><strong>Release MediaRecorder</strong> - Release the {@link android.media.MediaRecorder}
by calling {@link android.media.MediaRecorder#release() MediaRecorder.release()}.</li>
      <li><strong>Lock the Camera</strong> - Lock the camera so that future {@link
android.media.MediaRecorder} sessions can use it by calling {@link android.hardware.Camera#lock()
Camera.lock()}. Starting with Android 4.0 (API level 14), this call is not required unless the
{@link android.media.MediaRecorder#prepare() MediaRecorder.prepare()} call fails.</li>
    </ol>
  </li>
  <li><strong>Stop the Preview</strong> - When your activity has finished using the camera, stop the
preview using {@link android.hardware.Camera#stopPreview() Camera.stopPreview()}.</li>
  <li><strong>Release Camera</strong> - Release the camera so that other applications can use
it by calling {@link android.hardware.Camera#release() Camera.release()}.</li>
</ol>

<p class="note"><strong>Note:</strong> It is possible to use {@link android.media.MediaRecorder}
without creating a camera preview first and skip the first few steps of this process. However,
since users typically prefer to see a preview before starting a recording, that process is not
discussed here.</p>

<p class="note"><strong>Tip:</strong> If your application is typically used for recording video, set
{@link android.hardware.Camera.Parameters#setRecordingHint} to {@code true} prior to starting your
preview. This setting can help reduce the time it takes to start recording.</p>

<h4 id="configuring-mediarecorder">Configuring MediaRecorder</h4>
<p>When using the {@link android.media.MediaRecorder} class to record video, you must perform
configuration steps in a <em>specific order</em> and then call the {@link
android.media.MediaRecorder#prepare() MediaRecorder.prepare()} method to check and implement the
configuration. The following example code demonstrates how to properly configure and prepare the
{@link android.media.MediaRecorder} class for video recording.</p>

<pre>
private boolean prepareVideoRecorder(){

    mCamera = getCameraInstance();
    mMediaRecorder = new MediaRecorder();

    // Step 1: Unlock and set camera to MediaRecorder
    mCamera.unlock();
    mMediaRecorder.setCamera(mCamera);

    // Step 2: Set sources
    mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
    mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

    // Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
    mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));

    // Step 4: Set output file
    mMediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString());

    // Step 5: Set the preview output
    mMediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());

    // Step 6: Prepare configured MediaRecorder
    try {
        mMediaRecorder.prepare();
    } catch (IllegalStateException e) {
        Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
        releaseMediaRecorder();
        return false;
    } catch (IOException e) {
        Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
        releaseMediaRecorder();
        return false;
    }
    return true;
}
</pre>

<p>Prior to Android 2.2 (API Level 8), you must set the output format and encoding formats
parameters directly, instead of using {@link android.media.CamcorderProfile}. This approach is
demonstrated in the following code:</p>

<pre>
    // Step 3: Set output format and encoding (for versions prior to API Level 8)
    mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
    mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
</pre>

<p>The following video recording parameters for {@link android.media.MediaRecorder} are given
default settings, however, you may want to adjust these settings for your application:</p>

<ul>
  <li>{@link android.media.MediaRecorder#setVideoEncodingBitRate(int)
setVideoEncodingBitRate()}</li>
  <li>{@link android.media.MediaRecorder#setVideoSize(int, int) setVideoSize()}</li>
  <li>{@link android.media.MediaRecorder#setVideoFrameRate(int) setVideoFrameRate()}</li>
  <li>{@link android.media.MediaRecorder#setAudioEncodingBitRate(int)
setAudioEncodingBitRate()}</li>  <li>{@link android.media.MediaRecorder#setAudioChannels(int)
setAudioChannels()}</li>
  <li>{@link android.media.MediaRecorder#setAudioSamplingRate(int) setAudioSamplingRate()}</li>
</ul>

<h4 id="start-stop-mediarecorder">Starting and stopping MediaRecorder</h4>
<p>When starting and stopping video recording using the {@link android.media.MediaRecorder} class,
you must follow a specific order, as listed below.</p>

<ol>
  <li>Unlock the camera with {@link android.hardware.Camera#unlock() Camera.unlock()}</li>
  <li>Configure {@link android.media.MediaRecorder} as shown in the code example above</li>
  <li>Start recording using {@link android.media.MediaRecorder#start()
MediaRecorder.start()}</li>
  <li>Record the video</li>
  <li>Stop recording using {@link
android.media.MediaRecorder#stop() MediaRecorder.stop()}</li>
  <li>Release the media recorder with {@link android.media.MediaRecorder#release()
MediaRecorder.release()}</li>
  <li>Lock the camera using {@link android.hardware.Camera#lock() Camera.lock()}</li>
</ol>

<p>The following example code demonstrates how to wire up a button to properly start and stop
video recording using the camera and the {@link android.media.MediaRecorder} class.</p>

<p class="note"><strong>Note:</strong> When completing a video recording, do not release the camera
or else your preview will be stopped.</p>

<pre>
private boolean isRecording = false;

// Add a listener to the Capture button
Button captureButton = (Button) findViewById(id.button_capture);
captureButton.setOnClickListener(
    new View.OnClickListener() {
        &#64;Override
        public void onClick(View v) {
            if (isRecording) {
                // stop recording and release camera
                mMediaRecorder.stop();  // stop the recording
                releaseMediaRecorder(); // release the MediaRecorder object
                mCamera.lock();         // take camera access back from MediaRecorder

                // inform the user that recording has stopped
                setCaptureButtonText("Capture");
                isRecording = false;
            } else {
                // initialize video camera
                if (prepareVideoRecorder()) {
                    // Camera is available and unlocked, MediaRecorder is prepared,
                    // now you can start recording
                    mMediaRecorder.start();

                    // inform the user that recording has started
                    setCaptureButtonText("Stop");
                    isRecording = true;
                } else {
                    // prepare didn't work, release the camera
                    releaseMediaRecorder();
                    // inform user
                }
            }
        }
    }
);
</pre>

<p class="note"><strong>Note:</strong> In the above example, the {@code prepareVideoRecorder()}
method refers to the example code shown in <a
href="#configuring-mediarecorder">Configuring MediaRecorder</a>. This method takes care of locking
the camera, configuring and preparing the {@link android.media.MediaRecorder} instance.</p>


<h3 id="release-camera">Releasing the camera</h3>
<p>Cameras are a resource that is shared by applications on a device. Your application can make
use of the camera after getting an instance of {@link android.hardware.Camera}, and you must be
particularly careful to release the camera object when your application stops using it, and as
soon as your application is paused ({@link android.app.Activity#onPause() Activity.onPause()}). If
your application does not properly release the camera, all subsequent attempts to access the camera,
including those by your own application, will fail and may cause your or other applications to be
shut down.</p>

<p>To release an instance of the {@link android.hardware.Camera} object, use the {@link
android.hardware.Camera#release() Camera.release()} method, as shown in the example code below.</p>

<pre>
public class CameraActivity extends Activity {
    private Camera mCamera;
    private SurfaceView mPreview;
    private MediaRecorder mMediaRecorder;

    ...

    &#64;Override
    protected void onPause() {
        super.onPause();
        releaseMediaRecorder();       // if you are using MediaRecorder, release it first
        releaseCamera();              // release the camera immediately on pause event
    }

    private void releaseMediaRecorder(){
        if (mMediaRecorder != null) {
            mMediaRecorder.reset();   // clear recorder configuration
            mMediaRecorder.release(); // release the recorder object
            mMediaRecorder = null;
            mCamera.lock();           // lock camera for later use
        }
    }

    private void releaseCamera(){
        if (mCamera != null){
            mCamera.release();        // release the camera for other applications
            mCamera = null;
        }
    }
}
</pre>

<p class="caution"><strong>Caution:</strong> If your application does not properly release the
camera, all subsequent attempts to access the camera, including those by your own application, will
fail and may cause your or other applications to be shut down.</p>


<h2 id="saving-media">Saving Media Files</h2>
<p>Media files created by users such as pictures and videos should be saved to a device's external
storage directory (SD Card) to conserve system space and to allow users to access these files
without their device. There are many possible directory locations to save media files on a device,
however there are only two standard locations you should consider as a developer:</p>

<ul>
  <li><strong>{@link android.os.Environment#getExternalStoragePublicDirectory(java.lang.String)
Environment.getExternalStoragePublicDirectory}({@link android.os.Environment#DIRECTORY_PICTURES
Environment.DIRECTORY_PICTURES})</strong> - This method returns the standard, shared and recommended
location for saving pictures and videos. This directory is shared (public), so other applications
can easily discover, read, change and delete files saved in this location. If your application is
uninstalled by the user, media files saved to this location will not be removed. To avoid
interfering with users existing pictures and videos, you should create a sub-directory for your
application's media files within this directory, as shown in the code sample below. This method is
available in Android 2.2 (API Level 8), for equivalent calls in earlier API versions, see <a
href="{@docRoot}guide/topics/data/data-storage.html#SavingSharedFiles">Saving Shared Files</a>.</li>
  <li><strong>{@link android.content.Context#getExternalFilesDir(java.lang.String)
Context.getExternalFilesDir}({@link android.os.Environment#DIRECTORY_PICTURES
Environment.DIRECTORY_PICTURES})</strong> - This method returns a standard location for saving
pictures and videos which are associated with your application. If your application is uninstalled,
any files saved in this location are removed. Security is not enforced for files in this
location and other applications may read, change and delete them.</li>
</ul>

<p>The following example code demonstrates how to create a {@link java.io.File} or {@link
android.net.Uri} location for a media file that can be used when invoking a device's camera with
an {@link android.content.Intent} or as part of a <a href="#custom-camera">Building a Camera
App</a>.</p>

<pre>
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;

/** Create a file Uri for saving an image or video */
private static Uri getOutputMediaFileUri(int type){
      return Uri.fromFile(getOutputMediaFile(type));
}

/** Create a File for saving an image or video */
private static File getOutputMediaFile(int type){
    // To be safe, you should check that the SDCard is mounted
    // using Environment.getExternalStorageState() before doing this.

    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
              Environment.DIRECTORY_PICTURES), "MyCameraApp");
    // This location works best if you want the created images to be shared
    // between applications and persist after your app has been uninstalled.

    // Create the storage directory if it does not exist
    if (! mediaStorageDir.exists()){
        if (! mediaStorageDir.mkdirs()){
            Log.d("MyCameraApp", "failed to create directory");
            return null;
        }
    }

    // Create a media file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    File mediaFile;
    if (type == MEDIA_TYPE_IMAGE){
        mediaFile = new File(mediaStorageDir.getPath() + File.separator +
        "IMG_"+ timeStamp + ".jpg");
    } else if(type == MEDIA_TYPE_VIDEO) {
        mediaFile = new File(mediaStorageDir.getPath() + File.separator +
        "VID_"+ timeStamp + ".mp4");
    } else {
        return null;
    }

    return mediaFile;
}
</pre>

<p class="note"><strong>Note:</strong> {@link
android.os.Environment#getExternalStoragePublicDirectory(java.lang.String)
Environment.getExternalStoragePublicDirectory()} is available in Android 2.2 (API Level 8) or
higher. If you are targeting devices with earlier versions of Android, use {@link
android.os.Environment#getExternalStorageDirectory() Environment.getExternalStorageDirectory()}
instead. For more information, see <a
href="{@docRoot}guide/topics/data/data-storage.html#SavingSharedFiles">Saving Shared Files</a>.</p>

<p>For more information about saving files on an Android device, see <a
href="{@docRoot}guide/topics/data/data-storage.html">Data Storage</a>.</p>


<h2 id="camera-features">Camera Features</h2>
<p>Android supports a wide array of camera features you can control with your camera application,
such as picture format, flash mode, focus settings, and many more. This section lists the common
camera features, and briefly discusses how to use them. Most camera features can be accessed and set
using the through {@link android.hardware.Camera.Parameters} object. However, there are several
important features that require more than simple settings in {@link
android.hardware.Camera.Parameters}. These features are covered in the following sections:<p>

<ul>
  <li><a href="#metering-focus-areas">Metering and focus areas</a></li>
  <li><a href="#face-detection">Face detection</a></li>
  <li><a href="#time-lapse-video">Time lapse video</a></li>
</ul>

<p>For general information about how to use features that are controlled through {@link
android.hardware.Camera.Parameters}, review the <a href="#using-features">Using camera
features</a> section. For more detailed information about how to use features controlled through the
camera parameters object, follow the links in the feature list below to the API reference
documentation.</p>

<p class="table-caption" id="table1">
  <strong>Table 1.</strong> Common camera features sorted by the Android API Level in which they
were introduced.</p>
<table>
  <tr>
    <th>Feature</th>  <th>API Level</th>  <th>Description</th>
  </tr>
  <tr>
    <td><a href="#face-detection">Face Detection</a></td>
    <td>14</td>
    <td>Identify human faces within a picture and use them for focus, metering and white
balance</td>
  </tr>
  <tr>
    <td><a href="#metering-focus-areas">Metering Areas</a></td>
    <td>14</td>
    <td>Specify one or more areas within an image for calculating white balance</td>
  </tr>
  <tr>
    <td><a href="#metering-focus-areas">Focus Areas</a></td>
    <td>14</td>
    <td>Set one or more areas within an image to use for focus</td>
  </tr>
  <tr>
    <td>{@link android.hardware.Camera.Parameters#setAutoWhiteBalanceLock White Balance Lock}</td>
    <td>14</td>
    <td>Stop or start automatic white balance adjustments</td>
  </tr>
  <tr>
    <td>{@link android.hardware.Camera.Parameters#setAutoExposureLock Exposure Lock}</td>
    <td>14</td>
    <td>Stop or start automatic exposure adjustments</td>
  </tr>
  <tr>
    <td>{@link android.hardware.Camera#takePicture Video Snapshot}</td>
    <td>14</td>
    <td>Take a picture while shooting video (frame grab)</td>
  </tr>
  <tr>
    <td><a href="#time-lapse-video">Time Lapse Video</a></td>
    <td>11</td>
    <td>Record frames with set delays to record a time lapse video</td>
  </tr>
  <tr>
    <td>{@link android.hardware.Camera#open(int) Multiple Cameras}</td>
    <td>9</td>
    <td>Support for more than one camera on a device, including front-facing and back-facing
cameras</td>
  </tr>
  <tr>
    <td>{@link android.hardware.Camera.Parameters#getFocusDistances Focus Distance}</td>
    <td>9</td>
    <td>Reports distances between the camera and objects that appear to be in focus</td>
  </tr>
  <tr>
    <td>{@link android.hardware.Camera.Parameters#setZoom Zoom}</td>
    <td>8</td>
    <td>Set image magnification</td>
  </tr>
  <tr>
    <td>{@link android.hardware.Camera.Parameters#setExposureCompensation Exposure
Compensation}</td>
    <td>8</td>
    <td>Increase or decrease the light exposure level</td>
  </tr>
  <tr>
    <td>{@link android.hardware.Camera.Parameters#setGpsLatitude GPS Data}</td>
    <td>5</td>
    <td>Include or omit geographic location data with the image</td>
  </tr>
  <tr>
    <td>{@link android.hardware.Camera.Parameters#setWhiteBalance White Balance}</td>
    <td>5</td>
    <td>Set the white balance mode, which affects color values in the captured image</td>
  </tr>
  <tr>
    <td>{@link android.hardware.Camera.Parameters#setFocusMode Focus Mode}</td>
    <td>5</td>
    <td>Set how the camera focuses on a subject such as automatic, fixed, macro or infinity</td>
  </tr>
  <tr>
    <td>{@link android.hardware.Camera.Parameters#setSceneMode Scene Mode}</td>
    <td>5</td>
    <td>Apply a preset mode for specific types of photography situations such as night, beach, snow
or candlelight scenes</td>
  </tr>
  <tr>
    <td>{@link android.hardware.Camera.Parameters#setJpegQuality JPEG Quality}</td>
    <td>5</td>
    <td>Set the compression level for a JPEG image, which increases or decreases image output file
quality and size</td>
  </tr>
  <tr>
    <td>{@link android.hardware.Camera.Parameters#setFlashMode Flash Mode}</td>
    <td>5</td>
    <td>Turn flash on, off, or use automatic setting</td>
  </tr>
  <tr>
    <td>{@link android.hardware.Camera.Parameters#setColorEffect Color Effects}</td>
    <td>5</td>
    <td>Apply a color effect to the captured image such as black and white, sepia tone or negative.
</td>
  </tr>
  <tr>
    <td>{@link android.hardware.Camera.Parameters#setAntibanding Anti-Banding}</td>
    <td>5</td>
    <td>Reduces the effect of banding in color gradients due to JPEG compression</td>
  </tr>
  <tr>
    <td>{@link android.hardware.Camera.Parameters#setPictureFormat Picture Format}</td>
    <td>1</td>
    <td>Specify the file format for the picture</td>
  </tr>
  <tr>
    <td>{@link android.hardware.Camera.Parameters#setPictureSize Picture Size}</td>
    <td>1</td>
    <td>Specify the pixel dimensions of the saved picture</td>
  </tr>
</table>

<p class="note"><strong>Note:</strong> These features are not supported on all devices due to
hardware differences and software implementation. For information on checking the availability
of features on the device where your application is running, see <a href="#check-feature">Checking
feature availability</a>.</p>


<h3 id="check-feature">Checking feature availability</h3>
<p>The first thing to understand when setting out to use camera features on Android devices is that
not all camera features are supported on all devices. In addition, devices that support a particular
feature may support them to different levels or with different options. Therefore, part of your
decision process as you develop a camera application is to decide what camera features you want to
support and to what level. After making that decision, you should plan on including code in your
camera application that checks to see if device hardware supports those features and fails
gracefully if a feature is not available.</p>

<p>You can check the availabilty of camera features by getting an instance of a camera’s parameters
object, and checking the relevant methods. The following code sample shows you how to obtain a
{@link android.hardware.Camera.Parameters} object and check if the camera supports the autofocus
feature:</p>

<pre>
// get Camera parameters
Camera.Parameters params = mCamera.getParameters();

List&lt;String&gt; focusModes = params.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
  // Autofocus mode is supported
}
</pre>

<p>You can use the technique shown above for most camera features. The
{@link android.hardware.Camera.Parameters} object provides a {@code getSupported...()}, {@code
is...Supported()} or {@code getMax...()} method to determine if (and to what extent) a feature is
supported.</p>

<p>If your application requires certain camera features in order to function properly, you can
require them through additions to your application manifest. When you declare the use of specific
camera features, such as flash and auto-focus, Google Play restricts your application from
being installed on devices which do not support these features. For a list of camera features that
can be declared in your app manifest, see the manifest
<a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#hw-features"> Features
Reference</a>.</p>

<h3 id="using-features">Using camera features</h3>
<p>Most camera features are activated and controlled using a {@link
android.hardware.Camera.Parameters} object. You obtain this object by first getting an instance of
the {@link android.hardware.Camera} object, calling the {@link
android.hardware.Camera#getParameters getParameters()} method, changing the returned parameter
object and then setting it back into the camera object, as demonstrated in the following example
code:</p>

<pre>
// get Camera parameters
Camera.Parameters params = mCamera.getParameters();
// set the focus mode
params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
// set Camera parameters
mCamera.setParameters(params);
</pre>

<p>This technique works for nearly all camera features, and most parameters can be changed at any
time after you have obtained an instance of the {@link android.hardware.Camera} object. Changes to
parameters are typically visible to the user immediately in the application’s camera preview.
On the software side, parameter changes may take several frames to actually take effect as the
camera hardware processes the new instructions and then sends updated image data.</p>

<p class="caution"><strong>Important:</strong> Some camera features cannot be changed at will. In
particular, changing the size or orientation of the camera preview requires that you first stop the
preview, change the preview size, and then restart the preview. Starting with Android 4.0 (API
Level 14) preview orientation can be changed without restarting the preview.</p>

<p>Other camera features require more code in order to implement, including:</p>
<ul>
  <li>Metering and focus areas</li>
  <li>Face detection</li>
  <li>Time lapse video</li>
</ul>
<p>A quick outline of how to implement these features is provided in the following sections.</p>


<h3 id="metering-focus-areas">Metering and focus areas</h3>
<p>In some photographic scenarios, automatic focusing and light metering may not produce the
desired results. Starting with Android 4.0 (API Level 14), your camera application can provide
additional controls to allow your app or users to specify areas in an image to use for determining
focus or light level settings and pass these values to the camera hardware for use in capturing
images or video.</p>

<p>Areas for metering and focus work very similarly to other camera features, in that you control
them through methods in the {@link android.hardware.Camera.Parameters} object. The following code
demonstrates setting two light metering areas for an instance of
{@link android.hardware.Camera}:</p>

<pre>
// Create an instance of Camera
mCamera = getCameraInstance();

// set Camera parameters
Camera.Parameters params = mCamera.getParameters();

if (params.getMaxNumMeteringAreas() > 0){ // check that metering areas are supported
    List&lt;Camera.Area&gt; meteringAreas = new ArrayList&lt;Camera.Area&gt;();

    Rect areaRect1 = new Rect(-100, -100, 100, 100);    // specify an area in center of image
    meteringAreas.add(new Camera.Area(areaRect1, 600)); // set weight to 60%
    Rect areaRect2 = new Rect(800, -1000, 1000, -800);  // specify an area in upper right of image
    meteringAreas.add(new Camera.Area(areaRect2, 400)); // set weight to 40%
    params.setMeteringAreas(meteringAreas);
}

mCamera.setParameters(params);
</pre>

<p>The {@link android.hardware.Camera.Area} object contains two data parameters: A {@link
android.graphics.Rect} object for specifying an area within the camera’s field of view and a weight
value, which tells the camera what level of importance this area should be given in light metering
or focus calculations.</p>

<p>The {@link android.graphics.Rect} field in a {@link android.hardware.Camera.Area} object
describes a rectangular shape mapped on a 2000 x 2000 unit grid. The coordinates -1000, -1000
represent the top, left corner of the camera image, and coordinates 1000, 1000 represent the
bottom, right corner of the camera image, as shown in the illustration below.</p>

<img src='images/camera-area-coordinates.png' />
<p class="img-caption">
  <strong>Figure 1.</strong> The red lines illustrate the coordinate system for specifying a
{@link android.hardware.Camera.Area} within a camera preview. The blue box shows the location and
shape of an camera area with the {@link android.graphics.Rect} values 333,333,667,667.
</p>

<p>The bounds of this coordinate system always correspond to the outer edge of the image visible in
the camera preview and do not shrink or expand with the zoom level. Similarly, rotation of the image
preview using {@link android.hardware.Camera#setDisplayOrientation Camera.setDisplayOrientation()}
does not remap the coordinate system.</p>


<h3 id="face-detection">Face detection</h3>
<p>For pictures that include people, faces are usually the most important part of the picture, and
should be used for determining both focus and white balance when capturing an image. The Android 4.0
(API Level 14) framework provides APIs for identifying faces and calculating picture settings using
face recognition technology.</p>

<p class="note"><strong>Note:</strong> While the face detection feature is running,
{@link android.hardware.Camera.Parameters#setWhiteBalance},
{@link android.hardware.Camera.Parameters#setFocusAreas} and
{@link android.hardware.Camera.Parameters#setMeteringAreas} have no effect.</p>

<p>Using the face detection feature in your camera application requires a few general steps:</p>
<ul>
  <li>Check that face detection is supported on the device</li>
  <li>Create a face detection listener</li>
  <li>Add the face detection listener to your camera object</li>
  <li>Start face detection after preview (and after <em>every</em> preview restart)</li>
</ul>

<p>The face detection feature is not supported on all devices. You can check that this feature is
supported by calling {@link android.hardware.Camera.Parameters#getMaxNumDetectedFaces}. An
example of this check is shown in the {@code startFaceDetection()} sample method below.</p>

<p>In order to be notified and respond to the detection of a face, your camera application must set
a listener for face detection events. In order to do this, you must create a listener class that
implements the {@link android.hardware.Camera.FaceDetectionListener} interface as shown in the
example code below.</p>

<pre>
class MyFaceDetectionListener implements Camera.FaceDetectionListener {

    &#064;Override
    public void onFaceDetection(Face[] faces, Camera camera) {
        if (faces.length > 0){
            Log.d("FaceDetection", "face detected: "+ faces.length +
                    " Face 1 Location X: " + faces[0].rect.centerX() +
                    "Y: " + faces[0].rect.centerY() );
        }
    }
}
</pre>

<p>After creating this class, you then set it into your application’s
{@link android.hardware.Camera} object, as shown in the example code below:</p>

<pre>
mCamera.setFaceDetectionListener(new MyFaceDetectionListener());
</pre>

<p>Your application must start the face detection function each time you start (or restart) the
camera preview. Create a method for starting face detection so you can call it as needed, as shown
in the example code below.</p>

<pre>
public void startFaceDetection(){
    // Try starting Face Detection
    Camera.Parameters params = mCamera.getParameters();

    // start face detection only *after* preview has started
    if (params.getMaxNumDetectedFaces() > 0){
        // camera supports face detection, so can start it:
        mCamera.startFaceDetection();
    }
}
</pre>

<p>You must start face detection <em>each time</em> you start (or restart) the camera preview. If
you use the preview class shown in <a href="#camera-preview">Creating a preview class</a>, add your
{@link android.hardware.Camera#startFaceDetection startFaceDetection()} method to both the
{@link android.view.SurfaceHolder.Callback#surfaceCreated surfaceCreated()} and {@link
android.view.SurfaceHolder.Callback#surfaceChanged surfaceChanged()} methods in your preview class,
as shown in the sample code below.</p>

<pre>
public void surfaceCreated(SurfaceHolder holder) {
    try {
        mCamera.setPreviewDisplay(holder);
        mCamera.startPreview();

        startFaceDetection(); // start face detection feature

    } catch (IOException e) {
        Log.d(TAG, "Error setting camera preview: " + e.getMessage());
    }
}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {

    if (mHolder.getSurface() == null){
        // preview surface does not exist
        Log.d(TAG, "mHolder.getSurface() == null");
        return;
    }

    try {
        mCamera.stopPreview();

    } catch (Exception e){
        // ignore: tried to stop a non-existent preview
        Log.d(TAG, "Error stopping camera preview: " + e.getMessage());
    }

    try {
        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();

        startFaceDetection(); // re-start face detection feature

    } catch (Exception e){
        // ignore: tried to stop a non-existent preview
        Log.d(TAG, "Error starting camera preview: " + e.getMessage());
    }
}
</pre>

<p class="note"><strong>Note:</strong> Remember to call this method <em>after</em> calling
{@link android.hardware.Camera#startPreview startPreview()}. Do not attempt to start face detection
in the {@link android.app.Activity#onCreate onCreate()} method of your camera app’s main activity,
as the preview is not available by this point in your application's the execution.</p>


<h3 id="time-lapse-video">Time lapse video</h3>
<p>Time lapse video allows users to create video clips that combine pictures taken a few seconds or
minutes apart. This feature uses {@link android.media.MediaRecorder} to record the images for a time
lapse sequence. </p>

<p>To record a time lapse video with {@link android.media.MediaRecorder}, you must configure the
recorder object as if you are recording a normal video, setting the captured frames per second to a
low number and using one of the time lapse quality settings, as shown in the code example below.</p>

<pre>
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH));
...
// Step 5.5: Set the video capture rate to a low number
mMediaRecorder.setCaptureRate(0.1); // capture a frame every 10 seconds
</pre>

<p>These settings must be done as part of a larger configuration procedure for {@link
android.media.MediaRecorder}. For  a full configuration code example, see <a
href="#configuring-mediarecorder">Configuring MediaRecorder</a>. Once the configuration is complete,
you start the video recording as if you were recording a normal video clip. For more information
about configuring and running {@link android.media.MediaRecorder}, see <a
href="#capture-video">Capturing videos</a>.</p>