WindowAndroid.java revision 558790d6acca3451cf3a6b497803a5f07d0bec58
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5package org.chromium.ui;
6
7import android.app.Activity;
8import android.content.ActivityNotFoundException;
9import android.content.ContentResolver;
10import android.content.Context;
11import android.content.Intent;
12import android.os.Bundle;
13import android.util.SparseArray;
14import android.view.WindowManager;
15import android.widget.Toast;
16
17import java.util.HashMap;
18
19import org.chromium.base.JNINamespace;
20
21/**
22 * The window base class that has the minimum functionality.
23 */
24@JNINamespace("ui")
25public class WindowAndroid {
26
27    // Native pointer to the c++ WindowAndroid object.
28    private int mNativeWindowAndroid = 0;
29
30    // Constants used for intent request code bounding.
31    private static final int REQUEST_CODE_PREFIX = 1000;
32    private static final int REQUEST_CODE_RANGE_SIZE = 100;
33    // A string used as a key to store intent errors in a bundle
34    static final String WINDOW_CALLBACK_ERRORS = "window_callback_errors";
35
36    private int mNextRequestCode = 0;
37    protected Activity mActivity;
38    protected SparseArray<IntentCallback> mOutstandingIntents;
39    protected HashMap<Integer, String> mIntentErrors;
40
41    /**
42     * @param activity
43     */
44    public WindowAndroid(Activity activity) {
45        mActivity = activity;
46        mOutstandingIntents = new SparseArray<IntentCallback>();
47        mIntentErrors = new HashMap<Integer, String>();
48
49    }
50
51    /**
52     * Shows an intent and returns the results to the callback object.
53     * @param intent The intent that needs to be showed.
54     * @param callback The object that will receive the results for the intent.
55     * @param error The error string to be show if activity is paused before intent results.
56     * @return Whether the intent was shown.
57     */
58    public boolean showIntent(Intent intent, IntentCallback callback, String error) {
59        int requestCode = REQUEST_CODE_PREFIX + mNextRequestCode;
60        mNextRequestCode = (mNextRequestCode + 1) % REQUEST_CODE_RANGE_SIZE;
61
62        try {
63            mActivity.startActivityForResult(intent, requestCode);
64        } catch (ActivityNotFoundException e) {
65            return false;
66        }
67
68        mOutstandingIntents.put(requestCode, callback);
69        if (error != null) mIntentErrors.put(requestCode, error);
70
71        return true;
72    }
73
74    /**
75     * Displays an error message with a provided error message string.
76     * @param error The error message string to be displayed.
77     */
78    public void showError(String error) {
79        if (error != null) {
80            Toast.makeText(mActivity, error, Toast.LENGTH_SHORT).show();
81        }
82    }
83
84    /**
85     * Displays an error message from the given resource id.
86     * @param resId The error message string's resource id.
87     */
88    public void showError(int resId) {
89        showError(mActivity.getString(resId));
90    }
91
92    /**
93     * Displays an error message for a nonexistent callback.
94     * @param error The error message string to be displayed.
95     */
96    protected void showCallbackNonExistentError(String error) {
97        showError(error);
98    }
99
100    /**
101     * Broadcasts the given intent to all interested BroadcastReceivers.
102     */
103    public void sendBroadcast(Intent intent) {
104        mActivity.sendBroadcast(intent);
105    }
106
107    /**
108     * TODO(nileshagrawal): Stop returning Activity Context crbug.com/233440.
109     * @return Activity context.
110     */
111    @Deprecated
112    public Context getContext() {
113        return mActivity;
114    }
115
116    /**
117     * Saves the error messages that should be shown if any pending intents would return
118     * after the application has been put onPause.
119     * @param bundle The bundle to save the information in onPause
120     */
121    public void saveInstanceState(Bundle bundle) {
122        bundle.putSerializable(WINDOW_CALLBACK_ERRORS, mIntentErrors);
123    }
124
125    /**
126     * Restores the error messages that should be shown if any pending intents would return
127     * after the application has been put onPause.
128     * @param bundle The bundle to restore the information from onResume
129     */
130    public void restoreInstanceState(Bundle bundle) {
131        if (bundle == null) return;
132
133        Object errors = bundle.getSerializable(WINDOW_CALLBACK_ERRORS);
134        if (errors instanceof HashMap) {
135            @SuppressWarnings("unchecked")
136            HashMap<Integer, String> intentErrors = (HashMap<Integer, String>) errors;
137            mIntentErrors = intentErrors;
138        }
139    }
140
141    /**
142     * Responds to the intent result if the intent was created by the native window.
143     * @param requestCode Request code of the requested intent.
144     * @param resultCode Result code of the requested intent.
145     * @param data The data returned by the intent.
146     * @return Boolean value of whether the intent was started by the native window.
147     */
148    public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
149        IntentCallback callback = mOutstandingIntents.get(requestCode);
150        mOutstandingIntents.delete(requestCode);
151        String errorMessage = mIntentErrors.remove(requestCode);
152
153        if (callback != null) {
154            callback.onIntentCompleted(this, resultCode,
155                    mActivity.getContentResolver(), data);
156            return true;
157        } else {
158            if (errorMessage != null) {
159                showCallbackNonExistentError(errorMessage);
160                return true;
161            }
162        }
163        return false;
164    }
165
166    /**
167     * An interface that intent callback objects have to implement.
168     */
169    public interface IntentCallback {
170        /**
171         * Handles the data returned by the requested intent.
172         * @param window A window reference.
173         * @param resultCode Result code of the requested intent.
174         * @param contentResolver An instance of ContentResolver class for accessing returned data.
175         * @param data The data returned by the intent.
176         */
177        public void onIntentCompleted(WindowAndroid window, int resultCode,
178                ContentResolver contentResolver, Intent data);
179    }
180
181    /**
182     * Destroys the c++ WindowAndroid object if one has been created.
183     */
184    public void destroy() {
185        if (mNativeWindowAndroid != 0) {
186            nativeDestroy(mNativeWindowAndroid);
187            mNativeWindowAndroid = 0;
188        }
189    }
190
191    /**
192     * Returns a pointer to the c++ AndroidWindow object and calls the initializer if
193     * the object has not been previously initialized.
194     * @return A pointer to the c++ AndroidWindow.
195     */
196    public int getNativePointer() {
197        if (mNativeWindowAndroid == 0) {
198            mNativeWindowAndroid = nativeInit();
199        }
200        return mNativeWindowAndroid;
201    }
202
203    public void keepScreenOn(boolean screenOn) {
204        if (screenOn) {
205            mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
206        } else {
207            mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
208        }
209    }
210
211    private native int nativeInit();
212    private native void nativeDestroy(int nativeWindowAndroid);
213
214}
215