1 // Copyright 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.
5 package org.chromium.ui.base;
7 import android.app.PendingIntent;
8 import android.content.ContentResolver;
9 import android.content.Context;
10 import android.content.Intent;
11 import android.os.Bundle;
12 import android.util.Log;
13 import android.util.SparseArray;
14 import android.widget.Toast;
16 import org.chromium.base.CalledByNative;
17 import org.chromium.base.JNINamespace;
19 import java.util.HashMap;
22 * The window base class that has the minimum functionality.
25 public class WindowAndroid {
26 private static final String TAG = "WindowAndroid";
28 // Native pointer to the c++ WindowAndroid object.
29 private long mNativeWindowAndroid = 0;
31 // A string used as a key to store intent errors in a bundle
32 static final String WINDOW_CALLBACK_ERRORS = "window_callback_errors";
34 // Error code returned when an Intent fails to start an Activity.
35 public static final int START_INTENT_FAILURE = -1;
37 protected Context mApplicationContext;
38 protected SparseArray<IntentCallback> mOutstandingIntents;
39 protected HashMap<Integer, String> mIntentErrors;
42 * @param context The application context.
44 public WindowAndroid(Context context) {
45 assert context == context.getApplicationContext();
46 mApplicationContext = context;
47 mOutstandingIntents = new SparseArray<IntentCallback>();
48 mIntentErrors = new HashMap<Integer, String>();
52 * Shows an intent and returns the results to the callback object.
53 * @param intent The PendingIntent that needs to be shown.
54 * @param callback The object that will receive the results for the intent.
55 * @param errorId The ID of error string to be show if activity is paused before intent
57 * @return Whether the intent was shown.
59 public boolean showIntent(PendingIntent intent, IntentCallback callback, int errorId) {
60 return showCancelableIntent(intent, callback, errorId) >= 0;
64 * Shows an intent and returns the results to the callback object.
65 * @param intent The intent that needs to be shown.
66 * @param callback The object that will receive the results for the intent.
67 * @param errorId The ID of error string to be show if activity is paused before intent
69 * @return Whether the intent was shown.
71 public boolean showIntent(Intent intent, IntentCallback callback, int errorId) {
72 return showCancelableIntent(intent, callback, errorId) >= 0;
76 * Shows an intent that could be canceled and returns the results to the callback object.
77 * @param intent The PendingIntent that needs to be shown.
78 * @param callback The object that will receive the results for the intent.
79 * @param errorId The ID of error string to be show if activity is paused before intent
81 * @return A non-negative request code that could be used for finishActivity, or
82 * START_INTENT_FAILURE if failed.
84 public int showCancelableIntent(PendingIntent intent, IntentCallback callback, int errorId) {
85 Log.d(TAG, "Can't show intent as context is not an Activity: " + intent);
86 return START_INTENT_FAILURE;
90 * Shows an intent that could be canceled and returns the results to the callback object.
91 * @param intent The intent that needs to be showed.
92 * @param callback The object that will receive the results for the intent.
93 * @param errorId The ID of error string to be show if activity is paused before intent
95 * @return A non-negative request code that could be used for finishActivity, or
96 * START_INTENT_FAILURE if failed.
98 public int showCancelableIntent(Intent intent, IntentCallback callback, int errorId) {
99 Log.d(TAG, "Can't show intent as context is not an Activity: " + intent);
100 return START_INTENT_FAILURE;
104 * Force finish another activity that you had previously started with showCancelableIntent.
105 * @param requestCode The request code returned from showCancelableIntent.
107 public void cancelIntent(int requestCode) {
108 Log.d(TAG, "Can't cancel intent as context is not an Activity: " + requestCode);
112 * Removes a callback from the list of pending intents, so that nothing happens if/when the
113 * result for that intent is received.
114 * @param callback The object that should have received the results
115 * @return True if the callback was removed, false if it was not found.
117 public boolean removeIntentCallback(IntentCallback callback) {
118 int requestCode = mOutstandingIntents.indexOfValue(callback);
119 if (requestCode < 0) return false;
120 mOutstandingIntents.remove(requestCode);
121 mIntentErrors.remove(requestCode);
126 * Displays an error message with a provided error message string.
127 * @param error The error message string to be displayed.
129 public void showError(String error) {
131 Toast.makeText(mApplicationContext, error, Toast.LENGTH_SHORT).show();
136 * Displays an error message from the given resource id.
137 * @param resId The error message string's resource id.
139 public void showError(int resId) {
140 showError(mApplicationContext.getString(resId));
144 * Displays an error message for a nonexistent callback.
145 * @param error The error message string to be displayed.
147 protected void showCallbackNonExistentError(String error) {
152 * Broadcasts the given intent to all interested BroadcastReceivers.
154 public void sendBroadcast(Intent intent) {
155 mApplicationContext.sendBroadcast(intent);
159 * TODO(nileshagrawal): Stop returning Activity Context crbug.com/233440.
160 * @return Activity context, it could be null. Note, in most cases, you probably
161 * just need Application Context returned by getApplicationContext().
162 * @see #getApplicationContext()
165 public Context getContext() {
170 * @return The application context for this activity.
172 public Context getApplicationContext() {
173 return mApplicationContext;
177 * Saves the error messages that should be shown if any pending intents would return
178 * after the application has been put onPause.
179 * @param bundle The bundle to save the information in onPause
181 public void saveInstanceState(Bundle bundle) {
182 bundle.putSerializable(WINDOW_CALLBACK_ERRORS, mIntentErrors);
186 * Restores the error messages that should be shown if any pending intents would return
187 * after the application has been put onPause.
188 * @param bundle The bundle to restore the information from onResume
190 public void restoreInstanceState(Bundle bundle) {
191 if (bundle == null) return;
193 Object errors = bundle.getSerializable(WINDOW_CALLBACK_ERRORS);
194 if (errors instanceof HashMap) {
195 @SuppressWarnings("unchecked")
196 HashMap<Integer, String> intentErrors = (HashMap<Integer, String>) errors;
197 mIntentErrors = intentErrors;
202 * Responds to the intent result if the intent was created by the native window.
203 * @param requestCode Request code of the requested intent.
204 * @param resultCode Result code of the requested intent.
205 * @param data The data returned by the intent.
206 * @return Boolean value of whether the intent was started by the native window.
208 public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
213 * An interface that intent callback objects have to implement.
215 public interface IntentCallback {
217 * Handles the data returned by the requested intent.
218 * @param window A window reference.
219 * @param resultCode Result code of the requested intent.
220 * @param contentResolver An instance of ContentResolver class for accessing returned data.
221 * @param data The data returned by the intent.
223 public void onIntentCompleted(WindowAndroid window, int resultCode,
224 ContentResolver contentResolver, Intent data);
228 * Tests that an activity is available to handle the passed in intent.
229 * @param intent The intent to check.
230 * @return True if an activity is available to process this intent when started, meaning that
231 * Context.startActivity will not throw ActivityNotFoundException.
233 public boolean canResolveActivity(Intent intent) {
234 return mApplicationContext.getPackageManager().resolveActivity(intent, 0) != null;
238 * Destroys the c++ WindowAndroid object if one has been created.
240 public void destroy() {
241 if (mNativeWindowAndroid != 0) {
242 nativeDestroy(mNativeWindowAndroid);
243 mNativeWindowAndroid = 0;
248 * Returns a pointer to the c++ AndroidWindow object and calls the initializer if
249 * the object has not been previously initialized.
250 * @return A pointer to the c++ AndroidWindow.
252 public long getNativePointer() {
253 if (mNativeWindowAndroid == 0) {
254 mNativeWindowAndroid = nativeInit();
256 return mNativeWindowAndroid;
260 * Returns a PNG-encoded screenshot of the the window region at (|windowX|,
261 * |windowY|) with the size |width| by |height| pixels.
264 public byte[] grabSnapshot(int windowX, int windowY, int width, int height) {
268 private native long nativeInit();
269 private native void nativeDestroy(long nativeWindowAndroid);