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