ActivityBase.java revision 475b4c6eca6f7e7ca0e4b3ee0ee234c6fe079687
1/* 2 * Copyright (C) 2009 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 17package com.android.camera; 18 19import android.app.Activity; 20import android.app.KeyguardManager; 21import android.content.ContentResolver; 22import android.content.Context; 23import android.content.Intent; 24import android.content.pm.ActivityInfo; 25import android.os.AsyncTask; 26import android.os.Bundle; 27import android.util.Log; 28import android.view.KeyEvent; 29import android.view.View; 30import android.view.WindowManager; 31 32import com.android.camera.ui.PopupManager; 33import com.android.camera.ui.RotateImageView; 34 35import java.io.File; 36 37/** 38 * Superclass of Camera and VideoCamera activities. 39 */ 40abstract public class ActivityBase extends Activity { 41 private static final String TAG = "ActivityBase"; 42 private static boolean LOGV = false; 43 private int mResultCodeForTesting; 44 private boolean mOnResumePending; 45 private Intent mResultDataForTesting; 46 private OnScreenHint mStorageHint; 47 // The bitmap of the last captured picture thumbnail and the URI of the 48 // original picture. 49 protected Thumbnail mThumbnail; 50 // An imageview showing showing the last captured picture thumbnail. 51 protected RotateImageView mThumbnailView; 52 protected AsyncTask<Void, Void, Thumbnail> mLoadThumbnailTask; 53 protected boolean mOpenCameraFail; 54 protected boolean mCameraDisabled; 55 protected CameraManager.CameraProxy mCameraDevice; 56 57 // multiple cameras support 58 protected int mNumberOfCameras; 59 protected int mCameraId; 60 61 protected class CameraOpenThread extends Thread { 62 @Override 63 public void run() { 64 try { 65 mCameraDevice = Util.openCamera(ActivityBase.this, mCameraId); 66 } catch (CameraHardwareException e) { 67 mOpenCameraFail = true; 68 } catch (CameraDisabledException e) { 69 mCameraDisabled = true; 70 } 71 } 72 } 73 74 @Override 75 public void onCreate(Bundle icicle) { 76 if (Util.isTabletUI()) { 77 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 78 } else { 79 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 80 } 81 getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); 82 super.onCreate(icicle); 83 } 84 85 @Override 86 public void onWindowFocusChanged(boolean hasFocus) { 87 if (LOGV) Log.v(TAG, "onWindowFocusChanged.hasFocus=" + hasFocus 88 + ".mOnResumePending=" + mOnResumePending); 89 if (hasFocus && mOnResumePending) { 90 doOnResume(); 91 mOnResumePending = false; 92 } 93 } 94 95 @Override 96 protected void onResume() { 97 super.onResume(); 98 // Don't grab the camera if in use by lockscreen. For example, face 99 // unlock may be using the camera. Camera may be already opened in 100 // onCreate. doOnResume should continue if mCameraDevice != null. 101 // Suppose camera app is in the foreground. If users turn off and turn 102 // on the screen very fast, camera app can still have the focus when the 103 // lock screen shows up. The keyguard takes input focus, so the camera 104 // app will lose focus when it is displayed. 105 if (LOGV) Log.v(TAG, "onResume. hasWindowFocus()=" + hasWindowFocus()); 106 if (mCameraDevice == null && isKeyguardLocked()) { 107 if (LOGV) Log.v(TAG, "onResume. mOnResumePending=true"); 108 mOnResumePending = true; 109 } else { 110 if (LOGV) Log.v(TAG, "onResume. mOnResumePending=false"); 111 doOnResume(); 112 mOnResumePending = false; 113 } 114 } 115 116 @Override 117 protected void onPause() { 118 if (LOGV) Log.v(TAG, "onPause"); 119 saveThumbnailToFile(); 120 super.onPause(); 121 122 if (mLoadThumbnailTask != null) { 123 mLoadThumbnailTask.cancel(true); 124 mLoadThumbnailTask = null; 125 } 126 127 if (mStorageHint != null) { 128 mStorageHint.cancel(); 129 mStorageHint = null; 130 } 131 132 mOnResumePending = false; 133 } 134 135 // Put the code of onResume in this method. 136 abstract protected void doOnResume(); 137 138 @Override 139 public boolean onSearchRequested() { 140 return false; 141 } 142 143 @Override 144 public boolean onKeyDown(int keyCode, KeyEvent event) { 145 // Prevent software keyboard or voice search from showing up. 146 if (keyCode == KeyEvent.KEYCODE_SEARCH 147 || keyCode == KeyEvent.KEYCODE_MENU) { 148 if (event.isLongPress()) return true; 149 } 150 151 return super.onKeyDown(keyCode, event); 152 } 153 154 protected void setResultEx(int resultCode) { 155 mResultCodeForTesting = resultCode; 156 setResult(resultCode); 157 } 158 159 protected void setResultEx(int resultCode, Intent data) { 160 mResultCodeForTesting = resultCode; 161 mResultDataForTesting = data; 162 setResult(resultCode, data); 163 } 164 165 public int getResultCode() { 166 return mResultCodeForTesting; 167 } 168 169 public Intent getResultData() { 170 return mResultDataForTesting; 171 } 172 173 @Override 174 protected void onDestroy() { 175 PopupManager.removeInstance(this); 176 super.onDestroy(); 177 } 178 179 private boolean isKeyguardLocked() { 180 KeyguardManager kgm = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); 181 if (LOGV) { 182 if (kgm != null) { 183 Log.v(TAG, "kgm.isKeyguardLocked()="+kgm.isKeyguardLocked() 184 + ". kgm.isKeyguardSecure()="+kgm.isKeyguardSecure()); 185 } 186 } 187 // isKeyguardSecure excludes the slide lock case. 188 return (kgm != null) && kgm.isKeyguardLocked() && kgm.isKeyguardSecure(); 189 } 190 191 protected void updateStorageHint(long storageSpace) { 192 String message = null; 193 if (storageSpace == Storage.UNAVAILABLE) { 194 message = getString(R.string.no_storage); 195 } else if (storageSpace == Storage.PREPARING) { 196 message = getString(R.string.preparing_sd); 197 } else if (storageSpace == Storage.UNKNOWN_SIZE) { 198 message = getString(R.string.access_sd_fail); 199 } else if (storageSpace < Storage.LOW_STORAGE_THRESHOLD) { 200 message = getString(R.string.spaceIsLow_content); 201 } 202 203 if (message != null) { 204 if (mStorageHint == null) { 205 mStorageHint = OnScreenHint.makeText(this, message); 206 } else { 207 mStorageHint.setText(message); 208 } 209 mStorageHint.show(); 210 } else if (mStorageHint != null) { 211 mStorageHint.cancel(); 212 mStorageHint = null; 213 } 214 } 215 216 private void updateThumbnailView() { 217 if (mThumbnail != null) { 218 mThumbnailView.setBitmap(mThumbnail.getBitmap()); 219 mThumbnailView.setVisibility(View.VISIBLE); 220 } else { 221 mThumbnailView.setBitmap(null); 222 mThumbnailView.setVisibility(View.GONE); 223 } 224 } 225 226 protected void getLastThumbnail() { 227 mThumbnail = ThumbnailHolder.getLastThumbnail(getContentResolver()); 228 // Suppose users tap the thumbnail view, go to the gallery, delete the 229 // image, and coming back to the camera. Thumbnail file will be invalid. 230 // Since the new thumbnail will be loaded in another thread later, the 231 // view should be set to gone to prevent from opening the invalid image. 232 updateThumbnailView(); 233 if (mThumbnail == null) { 234 mLoadThumbnailTask = new LoadThumbnailTask().execute(); 235 } 236 } 237 238 private class LoadThumbnailTask extends AsyncTask<Void, Void, Thumbnail> { 239 @Override 240 protected Thumbnail doInBackground(Void... params) { 241 // Load the thumbnail from the file. 242 ContentResolver resolver = getContentResolver(); 243 Thumbnail t = Thumbnail.getLastThumbnailFromFile(getFilesDir(), resolver); 244 245 if (isCancelled()) return null; 246 247 if (t == null) { 248 // Load the thumbnail from the media provider. 249 t = Thumbnail.getLastThumbnailFromContentResolver(resolver); 250 } 251 return t; 252 } 253 254 @Override 255 protected void onPostExecute(Thumbnail thumbnail) { 256 mThumbnail = thumbnail; 257 updateThumbnailView(); 258 } 259 } 260 261 protected void gotoGallery() { 262 Util.viewUri(mThumbnail.getUri(), this); 263 } 264 265 protected void saveThumbnailToFile() { 266 if (mThumbnail != null && !mThumbnail.fromFile()) { 267 new SaveThumbnailTask().execute(mThumbnail); 268 } 269 } 270 271 private class SaveThumbnailTask extends AsyncTask<Thumbnail, Void, Void> { 272 @Override 273 protected Void doInBackground(Thumbnail... params) { 274 final int n = params.length; 275 final File filesDir = getFilesDir(); 276 for (int i = 0; i < n; i++) { 277 params[i].saveLastThumbnailToFile(filesDir); 278 } 279 return null; 280 } 281 } 282} 283