1515 */
1616package com .google .android .gms .samples .vision .face .facetracker ;
1717
18+ import android .Manifest ;
1819import android .app .Activity ;
20+ import android .app .AlertDialog ;
21+ import android .app .Dialog ;
1922import android .content .Context ;
23+ import android .content .DialogInterface ;
24+ import android .content .pm .PackageManager ;
2025import android .os .Bundle ;
26+ import android .support .design .widget .Snackbar ;
27+ import android .support .v4 .app .ActivityCompat ;
28+ import android .support .v7 .app .AppCompatActivity ;
2129import android .util .Log ;
30+ import android .view .View ;
2231
32+ import com .google .android .gms .common .ConnectionResult ;
33+ import com .google .android .gms .common .GoogleApiAvailability ;
2334import com .google .android .gms .vision .CameraSource ;
2435import com .google .android .gms .vision .MultiProcessor ;
2536import com .google .android .gms .vision .Tracker ;
3445 * Activity for the face tracker app. This app detects faces with the rear facing camera, and draws
3546 * overlay graphics to indicate the position, size, and ID of each face.
3647 */
37- public final class FaceTrackerActivity extends Activity {
48+ public final class FaceTrackerActivity extends AppCompatActivity {
3849 private static final String TAG = "FaceTracker" ;
3950
40- private CameraSource mCameraSource ;
51+ private CameraSource mCameraSource = null ;
52+
4153 private CameraSourcePreview mPreview ;
4254 private GraphicOverlay mGraphicOverlay ;
4355
56+ private static final int RC_HANDLE_GMS = 9001 ;
57+ // permission request codes need to be < 256
58+ private static final int RC_HANDLE_CAMERA_PERM = 2 ;
59+
4460 //==============================================================================================
4561 // Activity Methods
4662 //==============================================================================================
@@ -56,12 +72,63 @@ public void onCreate(Bundle icicle) {
5672 mPreview = (CameraSourcePreview ) findViewById (R .id .preview );
5773 mGraphicOverlay = (GraphicOverlay ) findViewById (R .id .faceOverlay );
5874
75+ // Check for the camera permission before accessing the camera. If the
76+ // permission is not granted yet, request permission.
77+ int rc = ActivityCompat .checkSelfPermission (this , Manifest .permission .CAMERA );
78+ if (rc == PackageManager .PERMISSION_GRANTED ) {
79+ createCameraSource ();
80+ } else {
81+ requestCameraPermission ();
82+ }
83+ }
84+
85+ /**
86+ * Handles the requesting of the camera permission. This includes
87+ * showing a "Snackbar" message of why the permission is needed then
88+ * sending the request.
89+ */
90+ private void requestCameraPermission () {
91+ Log .w (TAG , "Camera permission is not granted. Requesting permission" );
92+
93+ final String [] permissions = new String []{Manifest .permission .CAMERA };
94+
95+ if (!ActivityCompat .shouldShowRequestPermissionRationale (this ,
96+ Manifest .permission .CAMERA )) {
97+ ActivityCompat .requestPermissions (this , permissions , RC_HANDLE_CAMERA_PERM );
98+ return ;
99+ }
100+
101+ final Activity thisActivity = this ;
102+
103+ View .OnClickListener listener = new View .OnClickListener () {
104+ @ Override
105+ public void onClick (View view ) {
106+ ActivityCompat .requestPermissions (thisActivity , permissions ,
107+ RC_HANDLE_CAMERA_PERM );
108+ }
109+ };
110+
111+ Snackbar .make (mGraphicOverlay , R .string .permission_camera_rationale ,
112+ Snackbar .LENGTH_INDEFINITE )
113+ .setAction (R .string .ok , listener )
114+ .show ();
115+ }
116+
117+ /**
118+ * Creates and starts the camera. Note that this uses a higher resolution in comparison
119+ * to other detection examples to enable the barcode detector to detect small barcodes
120+ * at long distances.
121+ */
122+ private void createCameraSource () {
123+
59124 Context context = getApplicationContext ();
60- FaceDetector .Builder detectorBuilder = new FaceDetector .Builder (context );
61- detectorBuilder .setClassificationType (FaceDetector .ALL_CLASSIFICATIONS );
62- FaceDetector detector = detectorBuilder .build ();
125+ FaceDetector detector = new FaceDetector .Builder (context )
126+ .setClassificationType (FaceDetector .ALL_CLASSIFICATIONS )
127+ .build ();
128+
63129 detector .setProcessor (
64- new MultiProcessor .Builder <>(new GraphicFaceTrackerFactory ()).build ());
130+ new MultiProcessor .Builder <>(new GraphicFaceTrackerFactory ())
131+ .build ());
65132
66133 if (!detector .isOperational ()) {
67134 // Note: The first time that an app using face API is installed on a device, GMS will
@@ -88,6 +155,7 @@ public void onCreate(Bundle icicle) {
88155 @ Override
89156 protected void onResume () {
90157 super .onResume ();
158+
91159 startCameraSource ();
92160 }
93161
@@ -107,7 +175,56 @@ protected void onPause() {
107175 @ Override
108176 protected void onDestroy () {
109177 super .onDestroy ();
110- mCameraSource .release ();
178+ if (mCameraSource != null ) {
179+ mCameraSource .release ();
180+ }
181+ }
182+
183+ /**
184+ * Callback for the result from requesting permissions. This method
185+ * is invoked for every call on {@link #requestPermissions(String[], int)}.
186+ * <p>
187+ * <strong>Note:</strong> It is possible that the permissions request interaction
188+ * with the user is interrupted. In this case you will receive empty permissions
189+ * and results arrays which should be treated as a cancellation.
190+ * </p>
191+ *
192+ * @param requestCode The request code passed in {@link #requestPermissions(String[], int)}.
193+ * @param permissions The requested permissions. Never null.
194+ * @param grantResults The grant results for the corresponding permissions
195+ * which is either {@link PackageManager#PERMISSION_GRANTED}
196+ * or {@link PackageManager#PERMISSION_DENIED}. Never null.
197+ * @see #requestPermissions(String[], int)
198+ */
199+ @ Override
200+ public void onRequestPermissionsResult (int requestCode , String [] permissions , int [] grantResults ) {
201+ if (requestCode != RC_HANDLE_CAMERA_PERM ) {
202+ Log .d (TAG , "Got unexpected permission result: " + requestCode );
203+ super .onRequestPermissionsResult (requestCode , permissions , grantResults );
204+ return ;
205+ }
206+
207+ if (grantResults .length != 0 && grantResults [0 ] == PackageManager .PERMISSION_GRANTED ) {
208+ Log .d (TAG , "Camera permission granted - initialize the camera source" );
209+ // we have permission, so create the camerasource
210+ createCameraSource ();
211+ return ;
212+ }
213+
214+ Log .e (TAG , "Permission not granted: results len = " + grantResults .length +
215+ " Result code = " + (grantResults .length > 0 ? grantResults [0 ] : "(empty)" ));
216+
217+ DialogInterface .OnClickListener listener = new DialogInterface .OnClickListener () {
218+ public void onClick (DialogInterface dialog , int id ) {
219+ finish ();
220+ }
221+ };
222+
223+ AlertDialog .Builder builder = new AlertDialog .Builder (this );
224+ builder .setTitle ("Face Tracker sample" )
225+ .setMessage (R .string .no_camera_permission )
226+ .setPositiveButton (R .string .ok , listener )
227+ .show ();
111228 }
112229
113230 //==============================================================================================
@@ -120,12 +237,24 @@ protected void onDestroy() {
120237 * again when the camera source is created.
121238 */
122239 private void startCameraSource () {
123- try {
124- mPreview .start (mCameraSource , mGraphicOverlay );
125- } catch (IOException e ) {
126- Log .e (TAG , "Unable to start camera source." , e );
127- mCameraSource .release ();
128- mCameraSource = null ;
240+
241+ // check that the device has play services available.
242+ int code = GoogleApiAvailability .getInstance ().isGooglePlayServicesAvailable (
243+ getApplicationContext ());
244+ if (code != ConnectionResult .SUCCESS ) {
245+ Dialog dlg =
246+ GoogleApiAvailability .getInstance ().getErrorDialog (this , code , RC_HANDLE_GMS );
247+ dlg .show ();
248+ }
249+
250+ if (mCameraSource != null ) {
251+ try {
252+ mPreview .start (mCameraSource , mGraphicOverlay );
253+ } catch (IOException e ) {
254+ Log .e (TAG , "Unable to start camera source." , e );
255+ mCameraSource .release ();
256+ mCameraSource = null ;
257+ }
129258 }
130259 }
131260
0 commit comments