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