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(); onFirstRunDialogCancelled()47 public void onFirstRunDialogCancelled(); onCameraAccessException()48 public void onCameraAccessException(); 49 } 50 51 /** The default preference of aspect ratio. */ 52 private static final Rational DEFAULT_ASPECT_RATIO = ResolutionUtil.ASPECT_RATIO_4x3; 53 54 /** The default preference of whether enabling location recording. */ 55 private static final boolean DEFAULT_LOCATION_RECORDING_ENABLED = true; 56 57 /** Request code to PackageManager */ 58 private static final int PERMISSION_REQUEST_CODE = 1; 59 60 /** Listener to receive events. */ 61 private final FirstRunDialogListener mListener; 62 63 /** The app controller. */ 64 private final AppController mAppController; 65 66 /** The hardware manager. */ 67 private final OneCameraManager mOneCameraManager; 68 69 /** The activity context. */ 70 private final Context mContext; 71 72 /** The resolution settings. */ 73 private final ResolutionSetting mResolutionSetting; 74 75 /** The settings manager. */ 76 private final SettingsManager mSettingsManager; 77 78 /** Aspect ratio preference dialog */ 79 private Dialog mAspectRatioPreferenceDialog; 80 81 /** Location preference dialog */ 82 private Dialog mLocationPreferenceDialog; 83 84 /** 85 * Constructs a first run dialog. 86 * 87 */ FirstRunDialog( AppController appController, Context activityContext, ResolutionSetting resolutionSetting, SettingsManager settingManager, OneCameraManager hardwareManager, FirstRunDialogListener listener)88 public FirstRunDialog( 89 AppController appController, 90 Context activityContext, 91 ResolutionSetting resolutionSetting, 92 SettingsManager settingManager, 93 OneCameraManager hardwareManager, 94 FirstRunDialogListener listener) { 95 mAppController = appController; 96 mContext = activityContext; 97 mResolutionSetting = resolutionSetting; 98 mSettingsManager = settingManager; 99 mOneCameraManager = hardwareManager; 100 mListener = listener; 101 } 102 103 /** 104 * Shows first run dialogs if necessary. 105 */ showIfNecessary()106 public void showIfNecessary() { 107 if (shouldShowLocationDialog()) { 108 // When people open the app for the first time, prompt two dialogs to 109 // ask preferences about location and aspect ratio. The first dialog is 110 // location reference. 111 promptLocationPreferenceDialog(); 112 } else if (shouldShowAspectRatioDialog()) { 113 /** 114 * If people already set location preference, prompt aspect ratio dialog. 115 */ 116 promptAspectRatioPreferenceDialog(); 117 } else { 118 mListener.onFirstRunStateReady(); 119 } 120 } 121 122 /** 123 * Dismiss all shown dialogs. 124 */ dismiss()125 public void dismiss() { 126 if (mAspectRatioPreferenceDialog != null) { 127 // Remove the listener since we actively dismiss the dialog. 128 mAspectRatioPreferenceDialog.setOnDismissListener(null); 129 mAspectRatioPreferenceDialog.dismiss(); 130 mAspectRatioPreferenceDialog = null; 131 } 132 if (mLocationPreferenceDialog != null) { 133 // Remove the listener since we actively dismiss the dialog. 134 mLocationPreferenceDialog.setOnDismissListener(null); 135 mLocationPreferenceDialog.dismiss(); 136 mLocationPreferenceDialog = null; 137 } 138 } 139 140 /** 141 * Whether first run dialogs should be presented to the user. 142 * 143 * @return Whether first run dialogs should be presented to the user. 144 */ shouldShowLocationDialog()145 private boolean shouldShowLocationDialog() { 146 return !mSettingsManager.isSet(SettingsManager.SCOPE_GLOBAL, Keys.KEY_RECORD_LOCATION); 147 } 148 shouldShowAspectRatioDialog()149 private boolean shouldShowAspectRatioDialog() { 150 return mAppController.getCameraAppUI().shouldShowAspectRatioDialog(); 151 } 152 153 /** 154 * Prompts a dialog to allow people to choose aspect ratio preference when 155 * people open the app for the first time. If the preference has been set, 156 * this will return false. 157 */ promptAspectRatioPreferenceDialog()158 private void promptAspectRatioPreferenceDialog() { 159 // Create a content view for the dialog. 160 final AspectRatioDialogLayout dialogLayout = new AspectRatioDialogLayout( 161 mContext, DEFAULT_ASPECT_RATIO); 162 dialogLayout.setListener(new AspectRatioDialogLayout.AspectRatioDialogListener() { 163 @Override 164 public void onConfirm(Rational aspectRatio) { 165 // Change resolution setting based on the chosen aspect ratio. 166 try { 167 CameraId backCameraId = mOneCameraManager.findFirstCameraFacing(Facing.BACK); 168 if (backCameraId != null) { 169 mResolutionSetting.setPictureAspectRatio(backCameraId, aspectRatio); 170 } 171 CameraId frontCameraId = mOneCameraManager.findFirstCameraFacing(Facing.FRONT); 172 if (frontCameraId != null) { 173 mResolutionSetting.setPictureAspectRatio(frontCameraId, aspectRatio); 174 } 175 } catch (OneCameraAccessException ex) { 176 mListener.onCameraAccessException(); 177 return; 178 } 179 180 // Mark that user has made the choice. 181 mSettingsManager.set( 182 SettingsManager.SCOPE_GLOBAL, 183 Keys.KEY_USER_SELECTED_ASPECT_RATIO, 184 true); 185 186 // Dismiss all dialogs. 187 dismiss(); 188 189 // Notify that the app is ready to go. 190 mListener.onFirstRunStateReady(); 191 } 192 }); 193 194 // Create the dialog. 195 mAspectRatioPreferenceDialog = mAppController.createDialog(); 196 mAspectRatioPreferenceDialog.setContentView(dialogLayout, new ViewGroup.LayoutParams( 197 ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 198 // Detect if the dialog is dismissed by back button. 199 mAspectRatioPreferenceDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { 200 @Override 201 public void onDismiss(DialogInterface dialog) { 202 mAspectRatioPreferenceDialog = null; 203 dismiss(); 204 mListener.onFirstRunDialogCancelled(); 205 } 206 }); 207 208 // Show the dialog. 209 mAspectRatioPreferenceDialog.show(); 210 } 211 checkLocationPermission()212 private void checkLocationPermission() { 213 if (mContext.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) 214 != PackageManager.PERMISSION_GRANTED) { 215 Activity activity = (Activity) mContext; 216 activity.requestPermissions( 217 new String[] {Manifest.permission.ACCESS_COARSE_LOCATION}, 218 PERMISSION_REQUEST_CODE); 219 mSettingsManager.set(SettingsManager.SCOPE_GLOBAL, 220 Keys.KEY_HAS_SEEN_PERMISSIONS_DIALOGS, true); 221 } 222 } 223 224 /** 225 * Prompts a dialog to allow people to choose location preference when 226 * people open the app for the first time. If the preference has been set, 227 * this will return false. 228 */ promptLocationPreferenceDialog()229 private void promptLocationPreferenceDialog() { 230 // Create a content view for the dialog. 231 final LocationDialogLayout dialogLayout = new LocationDialogLayout( 232 mContext, DEFAULT_LOCATION_RECORDING_ENABLED); 233 dialogLayout.setListener(new LocationDialogLayout.LocationDialogListener() { 234 @Override 235 public void onConfirm(boolean locationRecordingEnabled) { 236 // Change the location preference setting. 237 mSettingsManager.set( 238 SettingsManager.SCOPE_GLOBAL, 239 Keys.KEY_RECORD_LOCATION, 240 locationRecordingEnabled); 241 if (locationRecordingEnabled) { 242 checkLocationPermission(); 243 } 244 245 if (shouldShowAspectRatioDialog()) { 246 // Prompt the second dialog about aspect ratio preference. 247 promptAspectRatioPreferenceDialog(); 248 } else { 249 // Dismiss all dialogs. 250 dismiss(); 251 // Notify that the app is ready to go. 252 mListener.onFirstRunStateReady(); 253 } 254 } 255 }); 256 257 // Create the dialog. 258 mLocationPreferenceDialog = mAppController.createDialog(); 259 mLocationPreferenceDialog.setContentView(dialogLayout, new ViewGroup.LayoutParams( 260 ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 261 // Detect if the dialog is dismissed by back button. 262 mLocationPreferenceDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { 263 @Override 264 public void onDismiss(DialogInterface dialog) { 265 mLocationPreferenceDialog = null; 266 dismiss(); 267 mListener.onFirstRunDialogCancelled(); 268 } 269 }); 270 271 // Show the dialog. 272 mLocationPreferenceDialog.show(); 273 } 274 } 275