• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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