1*90c8c64dSAndroid Build Coastguard Worker /*
2*90c8c64dSAndroid Build Coastguard Worker * Copyright 2015 The Android Open Source Project
3*90c8c64dSAndroid Build Coastguard Worker *
4*90c8c64dSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*90c8c64dSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*90c8c64dSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*90c8c64dSAndroid Build Coastguard Worker *
8*90c8c64dSAndroid Build Coastguard Worker *     http://www.apache.org/licenses/LICENSE-2.0
9*90c8c64dSAndroid Build Coastguard Worker *
10*90c8c64dSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*90c8c64dSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*90c8c64dSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*90c8c64dSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*90c8c64dSAndroid Build Coastguard Worker * limitations under the License.
15*90c8c64dSAndroid Build Coastguard Worker */
16*90c8c64dSAndroid Build Coastguard Worker 
17*90c8c64dSAndroid Build Coastguard Worker package com.example.android.system.runtimepermissions;
18*90c8c64dSAndroid Build Coastguard Worker 
19*90c8c64dSAndroid Build Coastguard Worker import com.example.android.common.logger.Log;
20*90c8c64dSAndroid Build Coastguard Worker import com.example.android.common.logger.LogFragment;
21*90c8c64dSAndroid Build Coastguard Worker import com.example.android.common.logger.LogWrapper;
22*90c8c64dSAndroid Build Coastguard Worker import com.example.android.common.logger.MessageOnlyLogFilter;
23*90c8c64dSAndroid Build Coastguard Worker import com.example.android.system.runtimepermissions.camera.CameraPreviewFragment;
24*90c8c64dSAndroid Build Coastguard Worker import com.example.android.system.runtimepermissions.contacts.ContactsFragment;
25*90c8c64dSAndroid Build Coastguard Worker 
26*90c8c64dSAndroid Build Coastguard Worker import android.Manifest;
27*90c8c64dSAndroid Build Coastguard Worker import android.app.Activity;
28*90c8c64dSAndroid Build Coastguard Worker import android.content.Context;
29*90c8c64dSAndroid Build Coastguard Worker import android.content.pm.PackageManager;
30*90c8c64dSAndroid Build Coastguard Worker import android.os.Bundle;
31*90c8c64dSAndroid Build Coastguard Worker import android.support.annotation.NonNull;
32*90c8c64dSAndroid Build Coastguard Worker import android.support.design.widget.Snackbar;
33*90c8c64dSAndroid Build Coastguard Worker import android.support.v4.app.ActivityCompat;
34*90c8c64dSAndroid Build Coastguard Worker import android.support.v4.app.FragmentTransaction;
35*90c8c64dSAndroid Build Coastguard Worker import android.view.Menu;
36*90c8c64dSAndroid Build Coastguard Worker import android.view.MenuItem;
37*90c8c64dSAndroid Build Coastguard Worker import android.view.View;
38*90c8c64dSAndroid Build Coastguard Worker import android.widget.ViewAnimator;
39*90c8c64dSAndroid Build Coastguard Worker 
40*90c8c64dSAndroid Build Coastguard Worker import common.activities.SampleActivityBase;
41*90c8c64dSAndroid Build Coastguard Worker 
42*90c8c64dSAndroid Build Coastguard Worker /**
43*90c8c64dSAndroid Build Coastguard Worker  * Launcher Activity that demonstrates the use of runtime permissions for Android M.
44*90c8c64dSAndroid Build Coastguard Worker  * It contains a summary sample description, sample log and a Fragment that calls callbacks on this
45*90c8c64dSAndroid Build Coastguard Worker  * Activity to illustrate parts of the runtime permissions API.
46*90c8c64dSAndroid Build Coastguard Worker  * <p>
47*90c8c64dSAndroid Build Coastguard Worker  * This Activity requests permissions to access the camera ({@link android.Manifest.permission#CAMERA})
48*90c8c64dSAndroid Build Coastguard Worker  * when the 'Show Camera' button is clicked to display the camera preview.
49*90c8c64dSAndroid Build Coastguard Worker  * Contacts permissions (({@link android.Manifest.permission#READ_CONTACTS} and ({@link
50*90c8c64dSAndroid Build Coastguard Worker  * android.Manifest.permission#WRITE_CONTACTS})) are requested when the 'Show and Add Contacts'
51*90c8c64dSAndroid Build Coastguard Worker  * button is
52*90c8c64dSAndroid Build Coastguard Worker  * clicked to display the first contact in the contacts database and to add a placeholder contact
53*90c8c64dSAndroid Build Coastguard Worker  * directly to it. Permissions are verified and requested through compat helpers in the support v4
54*90c8c64dSAndroid Build Coastguard Worker  * library, in this Activity using {@link ActivityCompat}.
55*90c8c64dSAndroid Build Coastguard Worker  * First, permissions are checked if they have already been granted through {@link
56*90c8c64dSAndroid Build Coastguard Worker  * ActivityCompat#checkSelfPermission(Context, String)}.
57*90c8c64dSAndroid Build Coastguard Worker  * If permissions have not been granted, they are requested through
58*90c8c64dSAndroid Build Coastguard Worker  * {@link ActivityCompat#requestPermissions(Activity, String[], int)} and the return value checked
59*90c8c64dSAndroid Build Coastguard Worker  * in
60*90c8c64dSAndroid Build Coastguard Worker  * a callback to the {@link android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback}
61*90c8c64dSAndroid Build Coastguard Worker  * interface.
62*90c8c64dSAndroid Build Coastguard Worker  * <p>
63*90c8c64dSAndroid Build Coastguard Worker  * Before requesting permissions, {@link ActivityCompat#shouldShowRequestPermissionRationale(Activity,
64*90c8c64dSAndroid Build Coastguard Worker  * String)}
65*90c8c64dSAndroid Build Coastguard Worker  * should be called to provide the user with additional context for the use of permissions if they
66*90c8c64dSAndroid Build Coastguard Worker  * have been denied previously.
67*90c8c64dSAndroid Build Coastguard Worker  * <p>
68*90c8c64dSAndroid Build Coastguard Worker  * If this sample is executed on a device running a platform version below M, all permissions
69*90c8c64dSAndroid Build Coastguard Worker  * declared
70*90c8c64dSAndroid Build Coastguard Worker  * in the Android manifest file are always granted at install time and cannot be requested at run
71*90c8c64dSAndroid Build Coastguard Worker  * time.
72*90c8c64dSAndroid Build Coastguard Worker  * <p>
73*90c8c64dSAndroid Build Coastguard Worker  * This sample targets the M platform and must therefore request permissions at runtime. Change the
74*90c8c64dSAndroid Build Coastguard Worker  * targetSdk in the file 'Application/build.gradle' to 22 to run the application in compatibility
75*90c8c64dSAndroid Build Coastguard Worker  * mode.
76*90c8c64dSAndroid Build Coastguard Worker  * Now, if a permission has been disable by the system through the application settings, disabled
77*90c8c64dSAndroid Build Coastguard Worker  * APIs provide compatibility data.
78*90c8c64dSAndroid Build Coastguard Worker  * For example the camera cannot be opened or an empty list of contacts is returned. No special
79*90c8c64dSAndroid Build Coastguard Worker  * action is required in this case.
80*90c8c64dSAndroid Build Coastguard Worker  * <p>
81*90c8c64dSAndroid Build Coastguard Worker  * (This class is based on the MainActivity used in the SimpleFragment sample template.)
82*90c8c64dSAndroid Build Coastguard Worker  */
83*90c8c64dSAndroid Build Coastguard Worker public class MainActivity extends SampleActivityBase
84*90c8c64dSAndroid Build Coastguard Worker         implements ActivityCompat.OnRequestPermissionsResultCallback {
85*90c8c64dSAndroid Build Coastguard Worker 
86*90c8c64dSAndroid Build Coastguard Worker     public static final String TAG = "MainActivity";
87*90c8c64dSAndroid Build Coastguard Worker 
88*90c8c64dSAndroid Build Coastguard Worker     /**
89*90c8c64dSAndroid Build Coastguard Worker      * Id to identify a camera permission request.
90*90c8c64dSAndroid Build Coastguard Worker      */
91*90c8c64dSAndroid Build Coastguard Worker     private static final int REQUEST_CAMERA = 0;
92*90c8c64dSAndroid Build Coastguard Worker 
93*90c8c64dSAndroid Build Coastguard Worker     /**
94*90c8c64dSAndroid Build Coastguard Worker      * Id to identify a contacts permission request.
95*90c8c64dSAndroid Build Coastguard Worker      */
96*90c8c64dSAndroid Build Coastguard Worker     private static final int REQUEST_CONTACTS = 1;
97*90c8c64dSAndroid Build Coastguard Worker 
98*90c8c64dSAndroid Build Coastguard Worker     /**
99*90c8c64dSAndroid Build Coastguard Worker      * Permissions required to read and write contacts. Used by the {@link ContactsFragment}.
100*90c8c64dSAndroid Build Coastguard Worker      */
101*90c8c64dSAndroid Build Coastguard Worker     private static String[] PERMISSIONS_CONTACT = {Manifest.permission.READ_CONTACTS,
102*90c8c64dSAndroid Build Coastguard Worker             Manifest.permission.WRITE_CONTACTS};
103*90c8c64dSAndroid Build Coastguard Worker 
104*90c8c64dSAndroid Build Coastguard Worker     // Whether the Log Fragment is currently shown.
105*90c8c64dSAndroid Build Coastguard Worker     private boolean mLogShown;
106*90c8c64dSAndroid Build Coastguard Worker 
107*90c8c64dSAndroid Build Coastguard Worker     /**
108*90c8c64dSAndroid Build Coastguard Worker      * Root of the layout of this Activity.
109*90c8c64dSAndroid Build Coastguard Worker      */
110*90c8c64dSAndroid Build Coastguard Worker     private View mLayout;
111*90c8c64dSAndroid Build Coastguard Worker 
112*90c8c64dSAndroid Build Coastguard Worker     /**
113*90c8c64dSAndroid Build Coastguard Worker      * Called when the 'show camera' button is clicked.
114*90c8c64dSAndroid Build Coastguard Worker      * Callback is defined in resource layout definition.
115*90c8c64dSAndroid Build Coastguard Worker      */
showCamera(View view)116*90c8c64dSAndroid Build Coastguard Worker     public void showCamera(View view) {
117*90c8c64dSAndroid Build Coastguard Worker         Log.i(TAG, "Show camera button pressed. Checking permission.");
118*90c8c64dSAndroid Build Coastguard Worker         // BEGIN_INCLUDE(camera_permission)
119*90c8c64dSAndroid Build Coastguard Worker         // Check if the Camera permission is already available.
120*90c8c64dSAndroid Build Coastguard Worker         if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
121*90c8c64dSAndroid Build Coastguard Worker                 != PackageManager.PERMISSION_GRANTED) {
122*90c8c64dSAndroid Build Coastguard Worker             // Camera permission has not been granted.
123*90c8c64dSAndroid Build Coastguard Worker 
124*90c8c64dSAndroid Build Coastguard Worker             requestCameraPermission();
125*90c8c64dSAndroid Build Coastguard Worker 
126*90c8c64dSAndroid Build Coastguard Worker         } else {
127*90c8c64dSAndroid Build Coastguard Worker 
128*90c8c64dSAndroid Build Coastguard Worker             // Camera permissions is already available, show the camera preview.
129*90c8c64dSAndroid Build Coastguard Worker             Log.i(TAG,
130*90c8c64dSAndroid Build Coastguard Worker                     "CAMERA permission has already been granted. Displaying camera preview.");
131*90c8c64dSAndroid Build Coastguard Worker             showCameraPreview();
132*90c8c64dSAndroid Build Coastguard Worker         }
133*90c8c64dSAndroid Build Coastguard Worker         // END_INCLUDE(camera_permission)
134*90c8c64dSAndroid Build Coastguard Worker 
135*90c8c64dSAndroid Build Coastguard Worker     }
136*90c8c64dSAndroid Build Coastguard Worker 
137*90c8c64dSAndroid Build Coastguard Worker     /**
138*90c8c64dSAndroid Build Coastguard Worker      * Requests the Camera permission.
139*90c8c64dSAndroid Build Coastguard Worker      * If the permission has been denied previously, a SnackBar will prompt the user to grant the
140*90c8c64dSAndroid Build Coastguard Worker      * permission, otherwise it is requested directly.
141*90c8c64dSAndroid Build Coastguard Worker      */
requestCameraPermission()142*90c8c64dSAndroid Build Coastguard Worker     private void requestCameraPermission() {
143*90c8c64dSAndroid Build Coastguard Worker         Log.i(TAG, "CAMERA permission has NOT been granted. Requesting permission.");
144*90c8c64dSAndroid Build Coastguard Worker 
145*90c8c64dSAndroid Build Coastguard Worker         // BEGIN_INCLUDE(camera_permission_request)
146*90c8c64dSAndroid Build Coastguard Worker         if (ActivityCompat.shouldShowRequestPermissionRationale(this,
147*90c8c64dSAndroid Build Coastguard Worker                 Manifest.permission.CAMERA)) {
148*90c8c64dSAndroid Build Coastguard Worker             // Provide an additional rationale to the user if the permission was not granted
149*90c8c64dSAndroid Build Coastguard Worker             // and the user would benefit from additional context for the use of the permission.
150*90c8c64dSAndroid Build Coastguard Worker             // For example if the user has previously denied the permission.
151*90c8c64dSAndroid Build Coastguard Worker             Log.i(TAG,
152*90c8c64dSAndroid Build Coastguard Worker                     "Displaying camera permission rationale to provide additional context.");
153*90c8c64dSAndroid Build Coastguard Worker             Snackbar.make(mLayout, R.string.permission_camera_rationale,
154*90c8c64dSAndroid Build Coastguard Worker                     Snackbar.LENGTH_INDEFINITE)
155*90c8c64dSAndroid Build Coastguard Worker                     .setAction(R.string.ok, new View.OnClickListener() {
156*90c8c64dSAndroid Build Coastguard Worker                         @Override
157*90c8c64dSAndroid Build Coastguard Worker                         public void onClick(View view) {
158*90c8c64dSAndroid Build Coastguard Worker                             ActivityCompat.requestPermissions(MainActivity.this,
159*90c8c64dSAndroid Build Coastguard Worker                                     new String[]{Manifest.permission.CAMERA},
160*90c8c64dSAndroid Build Coastguard Worker                                     REQUEST_CAMERA);
161*90c8c64dSAndroid Build Coastguard Worker                         }
162*90c8c64dSAndroid Build Coastguard Worker                     })
163*90c8c64dSAndroid Build Coastguard Worker                     .show();
164*90c8c64dSAndroid Build Coastguard Worker         } else {
165*90c8c64dSAndroid Build Coastguard Worker 
166*90c8c64dSAndroid Build Coastguard Worker             // Camera permission has not been granted yet. Request it directly.
167*90c8c64dSAndroid Build Coastguard Worker             ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA},
168*90c8c64dSAndroid Build Coastguard Worker                     REQUEST_CAMERA);
169*90c8c64dSAndroid Build Coastguard Worker         }
170*90c8c64dSAndroid Build Coastguard Worker         // END_INCLUDE(camera_permission_request)
171*90c8c64dSAndroid Build Coastguard Worker     }
172*90c8c64dSAndroid Build Coastguard Worker 
173*90c8c64dSAndroid Build Coastguard Worker     /**
174*90c8c64dSAndroid Build Coastguard Worker      * Called when the 'show camera' button is clicked.
175*90c8c64dSAndroid Build Coastguard Worker      * Callback is defined in resource layout definition.
176*90c8c64dSAndroid Build Coastguard Worker      */
showContacts(View v)177*90c8c64dSAndroid Build Coastguard Worker     public void showContacts(View v) {
178*90c8c64dSAndroid Build Coastguard Worker         Log.i(TAG, "Show contacts button pressed. Checking permissions.");
179*90c8c64dSAndroid Build Coastguard Worker 
180*90c8c64dSAndroid Build Coastguard Worker         // Verify that all required contact permissions have been granted.
181*90c8c64dSAndroid Build Coastguard Worker         if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)
182*90c8c64dSAndroid Build Coastguard Worker                 != PackageManager.PERMISSION_GRANTED
183*90c8c64dSAndroid Build Coastguard Worker                 || ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_CONTACTS)
184*90c8c64dSAndroid Build Coastguard Worker                 != PackageManager.PERMISSION_GRANTED) {
185*90c8c64dSAndroid Build Coastguard Worker             // Contacts permissions have not been granted.
186*90c8c64dSAndroid Build Coastguard Worker             Log.i(TAG, "Contact permissions has NOT been granted. Requesting permissions.");
187*90c8c64dSAndroid Build Coastguard Worker             requestContactsPermissions();
188*90c8c64dSAndroid Build Coastguard Worker 
189*90c8c64dSAndroid Build Coastguard Worker         } else {
190*90c8c64dSAndroid Build Coastguard Worker 
191*90c8c64dSAndroid Build Coastguard Worker             // Contact permissions have been granted. Show the contacts fragment.
192*90c8c64dSAndroid Build Coastguard Worker             Log.i(TAG,
193*90c8c64dSAndroid Build Coastguard Worker                     "Contact permissions have already been granted. Displaying contact details.");
194*90c8c64dSAndroid Build Coastguard Worker             showContactDetails();
195*90c8c64dSAndroid Build Coastguard Worker         }
196*90c8c64dSAndroid Build Coastguard Worker     }
197*90c8c64dSAndroid Build Coastguard Worker 
198*90c8c64dSAndroid Build Coastguard Worker     /**
199*90c8c64dSAndroid Build Coastguard Worker      * Requests the Contacts permissions.
200*90c8c64dSAndroid Build Coastguard Worker      * If the permission has been denied previously, a SnackBar will prompt the user to grant the
201*90c8c64dSAndroid Build Coastguard Worker      * permission, otherwise it is requested directly.
202*90c8c64dSAndroid Build Coastguard Worker      */
requestContactsPermissions()203*90c8c64dSAndroid Build Coastguard Worker     private void requestContactsPermissions() {
204*90c8c64dSAndroid Build Coastguard Worker         // BEGIN_INCLUDE(contacts_permission_request)
205*90c8c64dSAndroid Build Coastguard Worker         if (ActivityCompat.shouldShowRequestPermissionRationale(this,
206*90c8c64dSAndroid Build Coastguard Worker                 Manifest.permission.READ_CONTACTS)
207*90c8c64dSAndroid Build Coastguard Worker                 || ActivityCompat.shouldShowRequestPermissionRationale(this,
208*90c8c64dSAndroid Build Coastguard Worker                 Manifest.permission.WRITE_CONTACTS)) {
209*90c8c64dSAndroid Build Coastguard Worker 
210*90c8c64dSAndroid Build Coastguard Worker             // Provide an additional rationale to the user if the permission was not granted
211*90c8c64dSAndroid Build Coastguard Worker             // and the user would benefit from additional context for the use of the permission.
212*90c8c64dSAndroid Build Coastguard Worker             // For example, if the request has been denied previously.
213*90c8c64dSAndroid Build Coastguard Worker             Log.i(TAG,
214*90c8c64dSAndroid Build Coastguard Worker                     "Displaying contacts permission rationale to provide additional context.");
215*90c8c64dSAndroid Build Coastguard Worker 
216*90c8c64dSAndroid Build Coastguard Worker             // Display a SnackBar with an explanation and a button to trigger the request.
217*90c8c64dSAndroid Build Coastguard Worker             Snackbar.make(mLayout, R.string.permission_contacts_rationale,
218*90c8c64dSAndroid Build Coastguard Worker                     Snackbar.LENGTH_INDEFINITE)
219*90c8c64dSAndroid Build Coastguard Worker                     .setAction(R.string.ok, new View.OnClickListener() {
220*90c8c64dSAndroid Build Coastguard Worker                         @Override
221*90c8c64dSAndroid Build Coastguard Worker                         public void onClick(View view) {
222*90c8c64dSAndroid Build Coastguard Worker                             ActivityCompat
223*90c8c64dSAndroid Build Coastguard Worker                                     .requestPermissions(MainActivity.this, PERMISSIONS_CONTACT,
224*90c8c64dSAndroid Build Coastguard Worker                                             REQUEST_CONTACTS);
225*90c8c64dSAndroid Build Coastguard Worker                         }
226*90c8c64dSAndroid Build Coastguard Worker                     })
227*90c8c64dSAndroid Build Coastguard Worker                     .show();
228*90c8c64dSAndroid Build Coastguard Worker         } else {
229*90c8c64dSAndroid Build Coastguard Worker             // Contact permissions have not been granted yet. Request them directly.
230*90c8c64dSAndroid Build Coastguard Worker             ActivityCompat.requestPermissions(this, PERMISSIONS_CONTACT, REQUEST_CONTACTS);
231*90c8c64dSAndroid Build Coastguard Worker         }
232*90c8c64dSAndroid Build Coastguard Worker         // END_INCLUDE(contacts_permission_request)
233*90c8c64dSAndroid Build Coastguard Worker     }
234*90c8c64dSAndroid Build Coastguard Worker 
235*90c8c64dSAndroid Build Coastguard Worker 
236*90c8c64dSAndroid Build Coastguard Worker     /**
237*90c8c64dSAndroid Build Coastguard Worker      * Display the {@link CameraPreviewFragment} in the content area if the required Camera
238*90c8c64dSAndroid Build Coastguard Worker      * permission has been granted.
239*90c8c64dSAndroid Build Coastguard Worker      */
showCameraPreview()240*90c8c64dSAndroid Build Coastguard Worker     private void showCameraPreview() {
241*90c8c64dSAndroid Build Coastguard Worker         getSupportFragmentManager().beginTransaction()
242*90c8c64dSAndroid Build Coastguard Worker                 .replace(R.id.sample_content_fragment, CameraPreviewFragment.newInstance())
243*90c8c64dSAndroid Build Coastguard Worker                 .addToBackStack("contacts")
244*90c8c64dSAndroid Build Coastguard Worker                 .commit();
245*90c8c64dSAndroid Build Coastguard Worker     }
246*90c8c64dSAndroid Build Coastguard Worker 
247*90c8c64dSAndroid Build Coastguard Worker     /**
248*90c8c64dSAndroid Build Coastguard Worker      * Display the {@link ContactsFragment} in the content area if the required contacts
249*90c8c64dSAndroid Build Coastguard Worker      * permissions
250*90c8c64dSAndroid Build Coastguard Worker      * have been granted.
251*90c8c64dSAndroid Build Coastguard Worker      */
showContactDetails()252*90c8c64dSAndroid Build Coastguard Worker     private void showContactDetails() {
253*90c8c64dSAndroid Build Coastguard Worker         getSupportFragmentManager().beginTransaction()
254*90c8c64dSAndroid Build Coastguard Worker                 .replace(R.id.sample_content_fragment, ContactsFragment.newInstance())
255*90c8c64dSAndroid Build Coastguard Worker                 .addToBackStack("contacts")
256*90c8c64dSAndroid Build Coastguard Worker                 .commit();
257*90c8c64dSAndroid Build Coastguard Worker     }
258*90c8c64dSAndroid Build Coastguard Worker 
259*90c8c64dSAndroid Build Coastguard Worker 
260*90c8c64dSAndroid Build Coastguard Worker     /**
261*90c8c64dSAndroid Build Coastguard Worker      * Callback received when a permissions request has been completed.
262*90c8c64dSAndroid Build Coastguard Worker      */
263*90c8c64dSAndroid Build Coastguard Worker     @Override
onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)264*90c8c64dSAndroid Build Coastguard Worker     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
265*90c8c64dSAndroid Build Coastguard Worker             @NonNull int[] grantResults) {
266*90c8c64dSAndroid Build Coastguard Worker 
267*90c8c64dSAndroid Build Coastguard Worker         if (requestCode == REQUEST_CAMERA) {
268*90c8c64dSAndroid Build Coastguard Worker             // BEGIN_INCLUDE(permission_result)
269*90c8c64dSAndroid Build Coastguard Worker             // Received permission result for camera permission.
270*90c8c64dSAndroid Build Coastguard Worker             Log.i(TAG, "Received response for Camera permission request.");
271*90c8c64dSAndroid Build Coastguard Worker 
272*90c8c64dSAndroid Build Coastguard Worker             // Check if the only required permission has been granted
273*90c8c64dSAndroid Build Coastguard Worker             if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
274*90c8c64dSAndroid Build Coastguard Worker                 // Camera permission has been granted, preview can be displayed
275*90c8c64dSAndroid Build Coastguard Worker                 Log.i(TAG, "CAMERA permission has now been granted. Showing preview.");
276*90c8c64dSAndroid Build Coastguard Worker                 Snackbar.make(mLayout, R.string.permision_available_camera,
277*90c8c64dSAndroid Build Coastguard Worker                         Snackbar.LENGTH_SHORT).show();
278*90c8c64dSAndroid Build Coastguard Worker             } else {
279*90c8c64dSAndroid Build Coastguard Worker                 Log.i(TAG, "CAMERA permission was NOT granted.");
280*90c8c64dSAndroid Build Coastguard Worker                 Snackbar.make(mLayout, R.string.permissions_not_granted,
281*90c8c64dSAndroid Build Coastguard Worker                         Snackbar.LENGTH_SHORT).show();
282*90c8c64dSAndroid Build Coastguard Worker 
283*90c8c64dSAndroid Build Coastguard Worker             }
284*90c8c64dSAndroid Build Coastguard Worker             // END_INCLUDE(permission_result)
285*90c8c64dSAndroid Build Coastguard Worker 
286*90c8c64dSAndroid Build Coastguard Worker         } else if (requestCode == REQUEST_CONTACTS) {
287*90c8c64dSAndroid Build Coastguard Worker             Log.i(TAG, "Received response for contact permissions request.");
288*90c8c64dSAndroid Build Coastguard Worker 
289*90c8c64dSAndroid Build Coastguard Worker             // We have requested multiple permissions for contacts, so all of them need to be
290*90c8c64dSAndroid Build Coastguard Worker             // checked.
291*90c8c64dSAndroid Build Coastguard Worker             if (PermissionUtil.verifyPermissions(grantResults)) {
292*90c8c64dSAndroid Build Coastguard Worker                 // All required permissions have been granted, display contacts fragment.
293*90c8c64dSAndroid Build Coastguard Worker                 Snackbar.make(mLayout, R.string.permision_available_contacts,
294*90c8c64dSAndroid Build Coastguard Worker                         Snackbar.LENGTH_SHORT)
295*90c8c64dSAndroid Build Coastguard Worker                         .show();
296*90c8c64dSAndroid Build Coastguard Worker             } else {
297*90c8c64dSAndroid Build Coastguard Worker                 Log.i(TAG, "Contacts permissions were NOT granted.");
298*90c8c64dSAndroid Build Coastguard Worker                 Snackbar.make(mLayout, R.string.permissions_not_granted,
299*90c8c64dSAndroid Build Coastguard Worker                         Snackbar.LENGTH_SHORT)
300*90c8c64dSAndroid Build Coastguard Worker                         .show();
301*90c8c64dSAndroid Build Coastguard Worker             }
302*90c8c64dSAndroid Build Coastguard Worker 
303*90c8c64dSAndroid Build Coastguard Worker         } else {
304*90c8c64dSAndroid Build Coastguard Worker             super.onRequestPermissionsResult(requestCode, permissions, grantResults);
305*90c8c64dSAndroid Build Coastguard Worker         }
306*90c8c64dSAndroid Build Coastguard Worker     }
307*90c8c64dSAndroid Build Coastguard Worker 
308*90c8c64dSAndroid Build Coastguard Worker     /* Note: Methods and definitions below are only used to provide the UI for this sample and are
309*90c8c64dSAndroid Build Coastguard Worker     not relevant for the execution of the runtime permissions API. */
310*90c8c64dSAndroid Build Coastguard Worker 
311*90c8c64dSAndroid Build Coastguard Worker 
312*90c8c64dSAndroid Build Coastguard Worker     @Override
onCreateOptionsMenu(Menu menu)313*90c8c64dSAndroid Build Coastguard Worker     public boolean onCreateOptionsMenu(Menu menu) {
314*90c8c64dSAndroid Build Coastguard Worker         getMenuInflater().inflate(R.menu.main, menu);
315*90c8c64dSAndroid Build Coastguard Worker         return true;
316*90c8c64dSAndroid Build Coastguard Worker     }
317*90c8c64dSAndroid Build Coastguard Worker 
318*90c8c64dSAndroid Build Coastguard Worker     @Override
onPrepareOptionsMenu(Menu menu)319*90c8c64dSAndroid Build Coastguard Worker     public boolean onPrepareOptionsMenu(Menu menu) {
320*90c8c64dSAndroid Build Coastguard Worker         MenuItem logToggle = menu.findItem(R.id.menu_toggle_log);
321*90c8c64dSAndroid Build Coastguard Worker         logToggle.setVisible(findViewById(R.id.sample_output) instanceof ViewAnimator);
322*90c8c64dSAndroid Build Coastguard Worker         logToggle.setTitle(mLogShown ? R.string.sample_hide_log : R.string.sample_show_log);
323*90c8c64dSAndroid Build Coastguard Worker 
324*90c8c64dSAndroid Build Coastguard Worker         return super.onPrepareOptionsMenu(menu);
325*90c8c64dSAndroid Build Coastguard Worker     }
326*90c8c64dSAndroid Build Coastguard Worker 
327*90c8c64dSAndroid Build Coastguard Worker     @Override
onOptionsItemSelected(MenuItem item)328*90c8c64dSAndroid Build Coastguard Worker     public boolean onOptionsItemSelected(MenuItem item) {
329*90c8c64dSAndroid Build Coastguard Worker         switch (item.getItemId()) {
330*90c8c64dSAndroid Build Coastguard Worker             case R.id.menu_toggle_log:
331*90c8c64dSAndroid Build Coastguard Worker                 mLogShown = !mLogShown;
332*90c8c64dSAndroid Build Coastguard Worker                 ViewAnimator output = (ViewAnimator) findViewById(R.id.sample_output);
333*90c8c64dSAndroid Build Coastguard Worker                 if (mLogShown) {
334*90c8c64dSAndroid Build Coastguard Worker                     output.setDisplayedChild(1);
335*90c8c64dSAndroid Build Coastguard Worker                 } else {
336*90c8c64dSAndroid Build Coastguard Worker                     output.setDisplayedChild(0);
337*90c8c64dSAndroid Build Coastguard Worker                 }
338*90c8c64dSAndroid Build Coastguard Worker                 supportInvalidateOptionsMenu();
339*90c8c64dSAndroid Build Coastguard Worker                 return true;
340*90c8c64dSAndroid Build Coastguard Worker         }
341*90c8c64dSAndroid Build Coastguard Worker         return super.onOptionsItemSelected(item);
342*90c8c64dSAndroid Build Coastguard Worker     }
343*90c8c64dSAndroid Build Coastguard Worker 
344*90c8c64dSAndroid Build Coastguard Worker     /** Create a chain of targets that will receive log data */
345*90c8c64dSAndroid Build Coastguard Worker     @Override
initializeLogging()346*90c8c64dSAndroid Build Coastguard Worker     public void initializeLogging() {
347*90c8c64dSAndroid Build Coastguard Worker         // Wraps Android's native log framework.
348*90c8c64dSAndroid Build Coastguard Worker         LogWrapper logWrapper = new LogWrapper();
349*90c8c64dSAndroid Build Coastguard Worker         // Using Log, front-end to the logging chain, emulates android.util.log method signatures.
350*90c8c64dSAndroid Build Coastguard Worker         Log.setLogNode(logWrapper);
351*90c8c64dSAndroid Build Coastguard Worker 
352*90c8c64dSAndroid Build Coastguard Worker         // Filter strips out everything except the message text.
353*90c8c64dSAndroid Build Coastguard Worker         MessageOnlyLogFilter msgFilter = new MessageOnlyLogFilter();
354*90c8c64dSAndroid Build Coastguard Worker         logWrapper.setNext(msgFilter);
355*90c8c64dSAndroid Build Coastguard Worker 
356*90c8c64dSAndroid Build Coastguard Worker         // On screen logging via a fragment with a TextView.
357*90c8c64dSAndroid Build Coastguard Worker         LogFragment logFragment = (LogFragment) getSupportFragmentManager()
358*90c8c64dSAndroid Build Coastguard Worker                 .findFragmentById(R.id.log_fragment);
359*90c8c64dSAndroid Build Coastguard Worker         msgFilter.setNext(logFragment.getLogView());
360*90c8c64dSAndroid Build Coastguard Worker     }
361*90c8c64dSAndroid Build Coastguard Worker 
onBackClick(View view)362*90c8c64dSAndroid Build Coastguard Worker     public void onBackClick(View view) {
363*90c8c64dSAndroid Build Coastguard Worker         getSupportFragmentManager().popBackStack();
364*90c8c64dSAndroid Build Coastguard Worker     }
365*90c8c64dSAndroid Build Coastguard Worker 
366*90c8c64dSAndroid Build Coastguard Worker     @Override
onCreate(Bundle savedInstanceState)367*90c8c64dSAndroid Build Coastguard Worker     protected void onCreate(Bundle savedInstanceState) {
368*90c8c64dSAndroid Build Coastguard Worker         super.onCreate(savedInstanceState);
369*90c8c64dSAndroid Build Coastguard Worker         setContentView(R.layout.activity_main);
370*90c8c64dSAndroid Build Coastguard Worker         mLayout = findViewById(R.id.sample_main_layout);
371*90c8c64dSAndroid Build Coastguard Worker 
372*90c8c64dSAndroid Build Coastguard Worker         if (savedInstanceState == null) {
373*90c8c64dSAndroid Build Coastguard Worker             FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
374*90c8c64dSAndroid Build Coastguard Worker             RuntimePermissionsFragment fragment = new RuntimePermissionsFragment();
375*90c8c64dSAndroid Build Coastguard Worker             transaction.replace(R.id.sample_content_fragment, fragment);
376*90c8c64dSAndroid Build Coastguard Worker             transaction.commit();
377*90c8c64dSAndroid Build Coastguard Worker         }
378*90c8c64dSAndroid Build Coastguard Worker 
379*90c8c64dSAndroid Build Coastguard Worker         // This method sets up our custom logger, which will print all log messages to the device
380*90c8c64dSAndroid Build Coastguard Worker         // screen, as well as to adb logcat.
381*90c8c64dSAndroid Build Coastguard Worker         initializeLogging();
382*90c8c64dSAndroid Build Coastguard Worker     }
383*90c8c64dSAndroid Build Coastguard Worker }
384