1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.camera.app; 18 19 import android.Manifest; 20 import android.app.Dialog; 21 import android.app.Activity; 22 import android.content.Context; 23 import android.content.DialogInterface; 24 import android.content.pm.PackageManager; 25 import android.view.ViewGroup; 26 27 import com.android.camera.device.CameraId; 28 import com.android.camera.exif.Rational; 29 import com.android.camera.one.OneCamera.Facing; 30 import com.android.camera.one.OneCameraAccessException; 31 import com.android.camera.one.OneCameraManager; 32 import com.android.camera.settings.Keys; 33 import com.android.camera.settings.ResolutionSetting; 34 import com.android.camera.settings.ResolutionUtil; 35 import com.android.camera.settings.SettingsManager; 36 import com.android.camera.util.ApiHelper; 37 import com.android.camera.widget.AspectRatioDialogLayout; 38 import com.android.camera.widget.LocationDialogLayout; 39 40 /** 41 * The dialog to show when users open the app for the first time. 42 */ 43 public class FirstRunDialog { 44 45 public interface FirstRunDialogListener { onFirstRunStateReady()46 public void onFirstRunStateReady(); 47 onFirstRunDialogCancelled()48 public void onFirstRunDialogCancelled(); 49 onCameraAccessException()50 public void onCameraAccessException(); 51 } 52 53 /** The default preference of aspect ratio. */ 54 private static final Rational DEFAULT_ASPECT_RATIO = ResolutionUtil.ASPECT_RATIO_4x3; 55 56 /** The default preference of whether enabling location recording. */ 57 private static final boolean DEFAULT_LOCATION_RECORDING_ENABLED = true; 58 59 /** Request code to PackageManager */ 60 private static final int PERMISSION_REQUEST_CODE = 1; 61 62 /** Listener to receive events. */ 63 private final FirstRunDialogListener mListener; 64 65 /** The app controller. */ 66 private final AppController mAppController; 67 68 /** The hardware manager. */ 69 private final OneCameraManager mOneCameraManager; 70 71 /** The activity context. */ 72 private final Context mContext; 73 74 /** The resolution settings. */ 75 private final ResolutionSetting mResolutionSetting; 76 77 /** The settings manager. */ 78 private final SettingsManager mSettingsManager; 79 80 /** Aspect ratio preference dialog */ 81 private Dialog mAspectRatioPreferenceDialog; 82 83 /** Location preference dialog */ 84 private Dialog mLocationPreferenceDialog; 85 86 /** 87 * Constructs a first run dialog. 88 */ FirstRunDialog( AppController appController, Context activityContext, ResolutionSetting resolutionSetting, SettingsManager settingManager, OneCameraManager hardwareManager, FirstRunDialogListener listener)89 public FirstRunDialog( 90 AppController appController, 91 Context activityContext, 92 ResolutionSetting resolutionSetting, 93 SettingsManager settingManager, 94 OneCameraManager hardwareManager, 95 FirstRunDialogListener listener) { 96 mAppController = appController; 97 mContext = activityContext; 98 mResolutionSetting = resolutionSetting; 99 mSettingsManager = settingManager; 100 mOneCameraManager = hardwareManager; 101 mListener = listener; 102 } 103 104 /** 105 * Shows first run dialogs if necessary. 106 */ showIfNecessary()107 public void showIfNecessary() { 108 if (shouldShowLocationDialog()) { 109 // When people open the app for the first time, prompt two dialogs to 110 // ask preferences about location and aspect ratio. The first dialog is 111 // location reference. 112 promptLocationPreferenceDialog(); 113 } else if (shouldShowAspectRatioDialog()) { 114 /** 115 * If people already set location preference, prompt aspect ratio dialog. 116 */ 117 promptAspectRatioPreferenceDialog(); 118 } else { 119 mListener.onFirstRunStateReady(); 120 } 121 } 122 123 /** 124 * Dismiss all shown dialogs. 125 */ dismiss()126 public void dismiss() { 127 if (mAspectRatioPreferenceDialog != null) { 128 // Remove the listener since we actively dismiss the dialog. 129 mAspectRatioPreferenceDialog.setOnDismissListener(null); 130 mAspectRatioPreferenceDialog.dismiss(); 131 mAspectRatioPreferenceDialog = null; 132 } 133 if (mLocationPreferenceDialog != null) { 134 // Remove the listener since we actively dismiss the dialog. 135 mLocationPreferenceDialog.setOnDismissListener(null); 136 mLocationPreferenceDialog.dismiss(); 137 mLocationPreferenceDialog = null; 138 } 139 } 140 141 /** 142 * Whether first run dialogs should be presented to the user. 143 * 144 * @return Whether first run dialogs should be presented to the user. 145 */ shouldShowLocationDialog()146 private boolean shouldShowLocationDialog() { 147 return !mSettingsManager.isSet(SettingsManager.SCOPE_GLOBAL, Keys.KEY_RECORD_LOCATION); 148 } 149 shouldShowAspectRatioDialog()150 private boolean shouldShowAspectRatioDialog() { 151 return mAppController.getCameraAppUI().shouldShowAspectRatioDialog(); 152 } 153 154 /** 155 * Prompts a dialog to allow people to choose aspect ratio preference when 156 * people open the app for the first time. If the preference has been set, 157 * this will return false. 158 */ promptAspectRatioPreferenceDialog()159 private void promptAspectRatioPreferenceDialog() { 160 // Create a content view for the dialog. 161 final AspectRatioDialogLayout dialogLayout = new AspectRatioDialogLayout( 162 mContext, DEFAULT_ASPECT_RATIO); 163 dialogLayout.setListener(new AspectRatioDialogLayout.AspectRatioDialogListener() { 164 @Override 165 public void onConfirm(Rational aspectRatio) { 166 // Change resolution setting based on the chosen aspect ratio. 167 try { 168 CameraId backCameraId = mOneCameraManager.findFirstCameraFacing(Facing.BACK); 169 if (backCameraId != null) { 170 mResolutionSetting.setPictureAspectRatio(backCameraId, aspectRatio); 171 } 172 CameraId frontCameraId = mOneCameraManager.findFirstCameraFacing(Facing.FRONT); 173 if (frontCameraId != null) { 174 mResolutionSetting.setPictureAspectRatio(frontCameraId, aspectRatio); 175 } 176 } catch (OneCameraAccessException ex) { 177 mListener.onCameraAccessException(); 178 return; 179 } 180 181 // Mark that user has made the choice. 182 mSettingsManager.set( 183 SettingsManager.SCOPE_GLOBAL, 184 Keys.KEY_USER_SELECTED_ASPECT_RATIO, 185 true); 186 187 // Dismiss all dialogs. 188 dismiss(); 189 190 // Notify that the app is ready to go. 191 mListener.onFirstRunStateReady(); 192 } 193 }); 194 195 // Create the dialog. 196 mAspectRatioPreferenceDialog = mAppController.createDialog(); 197 mAspectRatioPreferenceDialog.setContentView(dialogLayout, new ViewGroup.LayoutParams( 198 ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 199 // Detect if the dialog is dismissed by back button. 200 mAspectRatioPreferenceDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { 201 @Override 202 public void onDismiss(DialogInterface dialog) { 203 mAspectRatioPreferenceDialog = null; 204 dismiss(); 205 mListener.onFirstRunDialogCancelled(); 206 } 207 }); 208 209 // Show the dialog. 210 mAspectRatioPreferenceDialog.show(); 211 } 212 checkLocationPermission()213 private void checkLocationPermission() { 214 if (mContext.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) 215 == PackageManager.PERMISSION_GRANTED || mContext.checkSelfPermission( 216 Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { 217 return; 218 } 219 220 Activity activity = (Activity) mContext; 221 activity.requestPermissions( 222 new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, 223 Manifest.permission.ACCESS_FINE_LOCATION}, 224 PERMISSION_REQUEST_CODE); 225 mSettingsManager.set(SettingsManager.SCOPE_GLOBAL, 226 Keys.KEY_HAS_SEEN_PERMISSIONS_DIALOGS, true); 227 228 } 229 230 /** 231 * Prompts a dialog to allow people to choose location preference when 232 * people open the app for the first time. If the preference has been set, 233 * this will return false. 234 */ promptLocationPreferenceDialog()235 private void promptLocationPreferenceDialog() { 236 // Create a content view for the dialog. 237 final LocationDialogLayout dialogLayout = new LocationDialogLayout( 238 mContext, DEFAULT_LOCATION_RECORDING_ENABLED); 239 dialogLayout.setListener(new LocationDialogLayout.LocationDialogListener() { 240 @Override 241 public void onConfirm(boolean locationRecordingEnabled) { 242 // Change the location preference setting. 243 mSettingsManager.set( 244 SettingsManager.SCOPE_GLOBAL, 245 Keys.KEY_RECORD_LOCATION, 246 locationRecordingEnabled); 247 if (locationRecordingEnabled) { 248 checkLocationPermission(); 249 } 250 251 if (shouldShowAspectRatioDialog()) { 252 // Prompt the second dialog about aspect ratio preference. 253 promptAspectRatioPreferenceDialog(); 254 } else { 255 // Dismiss all dialogs. 256 dismiss(); 257 // Notify that the app is ready to go. 258 mListener.onFirstRunStateReady(); 259 } 260 } 261 }); 262 263 // Create the dialog. 264 mLocationPreferenceDialog = mAppController.createDialog(); 265 mLocationPreferenceDialog.setContentView(dialogLayout, new ViewGroup.LayoutParams( 266 ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 267 // Detect if the dialog is dismissed by back button. 268 mLocationPreferenceDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { 269 @Override 270 public void onDismiss(DialogInterface dialog) { 271 mLocationPreferenceDialog = null; 272 dismiss(); 273 mListener.onFirstRunDialogCancelled(); 274 } 275 }); 276 277 // Show the dialog. 278 mLocationPreferenceDialog.show(); 279 } 280 } 281