1 /* 2 * Copyright (C) 2008 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 17 package android.app.stubs; 18 19 import android.app.Activity; 20 import android.app.AlertDialog; 21 import android.app.DatePickerDialog; 22 import android.app.DatePickerDialog.OnDateSetListener; 23 import android.app.Dialog; 24 import android.app.TimePickerDialog; 25 import android.app.TimePickerDialog.OnTimeSetListener; 26 import android.content.Context; 27 import android.content.DialogInterface; 28 import android.content.DialogInterface.OnCancelListener; 29 import android.content.Intent; 30 import android.os.Bundle; 31 import android.os.Handler; 32 import android.os.Message; 33 import android.util.Log; 34 import android.view.KeyEvent; 35 import android.view.LayoutInflater; 36 import android.view.View; 37 import android.widget.DatePicker; 38 import android.widget.TimePicker; 39 40 import androidx.test.core.app.ActivityScenario; 41 42 /* 43 * Stub class for Dialog, AlertDialog, DatePickerDialog, TimePickerDialog etc. 44 */ 45 public class DialogStubActivity extends Activity { 46 public static final int TEST_DIALOG_WITHOUT_THEME = 0; 47 public static final int TEST_DIALOG_WITH_THEME = 1; 48 public static final int TEST_ALERTDIALOG = 2; 49 public static final int TEST_CUSTOM_ALERTDIALOG = 3; 50 public static final int TEST_DATEPICKERDIALOG = 4; 51 public static final int TEST_DATEPICKERDIALOG_WITH_THEME = 5; 52 public static final int TEST_TIMEPICKERDIALOG = 6; 53 public static final int TEST_TIMEPICKERDIALOG_WITH_THEME = 7; 54 public static final int TEST_ONSTART_AND_ONSTOP = 8; 55 public static final int TEST_ALERTDIALOG_DEPRECATED = 9; 56 public static final int TEST_ALERTDIALOG_CALLBACK = 10; 57 public static final int TEST_CUSTOM_ALERTDIALOG_VIEW = 11; 58 public static final int TEST_ALERTDIALOG_DEPRECATED_WITH_MESSAGE = 12; 59 public static final int TEST_ALERTDIALOG_THEME = 13; 60 public static final int TEST_ALERTDIALOG_CANCELABLE = 14; 61 public static final int TEST_ALERTDIALOG_NOT_CANCELABLE = 15; 62 public static final int TEST_PROTECTED_CANCELABLE = 16; 63 public static final int TEST_PROTECTED_NOT_CANCELABLE = 17; 64 public static final int TEST_ALERT_DIALOG_ICON_DRAWABLE = 18; 65 public static final int TEST_ALERT_DIALOG_ICON_ATTRIBUTE = 19; 66 public static final int TEST_ALERTDIALOG_WITH_MESSAGE = 20; 67 68 public static final int SPACING_LEFT = 10; 69 public static final int SPACING_TOP = 20; 70 public static final int SPACING_RIGHT = 30; 71 public static final int SPACING_BOTTOM = 40; 72 public static int buttonIndex; 73 74 public static final String DEFAULT_ALERTDIALOG_TITLE = "AlertDialog"; 75 public static final String DEFAULT_ALERTDIALOG_MESSAGE = "AlertDialog message"; 76 private static final String LOG_TAG = "DialogStubActivity"; 77 78 public boolean isPositiveButtonClicked = false; 79 public boolean isNegativeButtonClicked = false; 80 public boolean isNeutralButtonClicked = false; 81 public boolean isCallBackCalled; 82 public boolean onCancelCalled; 83 public boolean onKeyDownCalled; 84 public boolean onKeyUpCalled; 85 public boolean onCreateCalled; 86 public boolean onCancelListenerCalled; 87 public boolean onClickCalled; 88 public static boolean onDateChangedCalled; 89 public static boolean onRestoreInstanceStateCalled; 90 public boolean onSaveInstanceStateCalled; 91 public int updatedYear; 92 public int updatedMonth; 93 public int updatedDay; 94 95 public final int INITIAL_YEAR = 2008; 96 public final int INITIAL_MONTH = 7; 97 public final int INITIAL_DAY_OF_MONTH = 27; 98 private final int INITIAL_HOUR = 10; 99 private final int INITIAL_MINUTE = 35; 100 private Dialog mDialog; 101 private AlertDialog mAlertDialog; 102 private OnDateSetListener mOnDateSetListener = new OnDateSetListener() { 103 public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { 104 updatedYear = year; 105 updatedMonth = monthOfYear; 106 updatedDay = dayOfMonth; 107 } 108 }; 109 110 @SuppressWarnings("deprecation") 111 @Override onCreateDialog(int id)112 protected Dialog onCreateDialog(int id) { 113 switch (id) { 114 case TEST_DIALOG_WITHOUT_THEME: 115 mDialog = new Dialog(this); 116 mDialog.setTitle("Hello, Dialog"); 117 break; 118 119 case TEST_DIALOG_WITH_THEME: 120 mDialog = new Dialog(this, 1); 121 break; 122 123 case TEST_ALERTDIALOG: 124 mDialog = getAlertDialogInstance(false); 125 break; 126 127 case TEST_CUSTOM_ALERTDIALOG: 128 mDialog = getCustomAlertDialogInstance(false); 129 break; 130 131 case TEST_CUSTOM_ALERTDIALOG_VIEW: 132 mDialog = getCustomAlertDialogInstance(true); 133 break; 134 135 case TEST_DATEPICKERDIALOG: 136 mDialog = new MockDatePickerDialog(this, mOnDateSetListener, INITIAL_YEAR, 137 INITIAL_MONTH, INITIAL_DAY_OF_MONTH); 138 break; 139 140 case TEST_DATEPICKERDIALOG_WITH_THEME: 141 mDialog = new MockDatePickerDialog(this, 142 com.android.internal.R.style.Theme_Translucent, mOnDateSetListener, 143 INITIAL_YEAR, INITIAL_MONTH, INITIAL_DAY_OF_MONTH); 144 break; 145 146 case TEST_TIMEPICKERDIALOG: 147 mDialog = new TimePickerDialog(this, new OnTimeSetListener() { 148 public void onTimeSet(TimePicker view, int hourOfDay, int minute) { 149 isCallBackCalled = true; 150 } 151 }, INITIAL_HOUR, INITIAL_MINUTE, true); 152 break; 153 154 case TEST_TIMEPICKERDIALOG_WITH_THEME: 155 mDialog = new TimePickerDialog(this, 156 com.android.internal.R.style.Theme_Translucent, null, INITIAL_HOUR, 157 INITIAL_MINUTE, true); 158 break; 159 160 case TEST_ONSTART_AND_ONSTOP: 161 mDialog = new TestDialog(this); 162 Log.i(LOG_TAG, "mTestDialog:" + mDialog); 163 return mDialog; 164 165 case TEST_ALERTDIALOG_DEPRECATED: 166 mDialog = getAlertDialogInstance(true); 167 break; 168 169 case TEST_ALERTDIALOG_DEPRECATED_WITH_MESSAGE: 170 case TEST_ALERTDIALOG_WITH_MESSAGE: 171 final Handler handler = new Handler() { 172 @Override 173 public void handleMessage(Message msg) { 174 buttonIndex = msg.what; 175 super.handleMessage(msg); 176 } 177 }; 178 final Message positiveMessage = Message.obtain(); 179 positiveMessage.setTarget(handler); 180 positiveMessage.what = DialogInterface.BUTTON_POSITIVE; 181 182 final Message negativeMessage = Message.obtain(); 183 negativeMessage.setTarget(handler); 184 negativeMessage.what = DialogInterface.BUTTON_NEGATIVE; 185 186 final Message neutralMessage = Message.obtain(); 187 neutralMessage.setTarget(handler); 188 neutralMessage.what = DialogInterface.BUTTON_NEUTRAL; 189 mAlertDialog = getAlertDialogInstance(false); 190 if (id == TEST_ALERTDIALOG_DEPRECATED_WITH_MESSAGE) { 191 mAlertDialog.setButton(getString(R.string.alert_dialog_positive), 192 positiveMessage); 193 mAlertDialog.setButton2(getString(R.string.alert_dialog_negative), 194 negativeMessage); 195 mAlertDialog.setButton3(getString(R.string.alert_dialog_neutral), 196 neutralMessage); 197 } else { 198 mAlertDialog.setButton(AlertDialog.BUTTON_POSITIVE, 199 getString(R.string.alert_dialog_positive), positiveMessage); 200 mAlertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, 201 getString(R.string.alert_dialog_neutral), neutralMessage); 202 mAlertDialog.setButton(AlertDialog.BUTTON_NEGATIVE, 203 getString(R.string.alert_dialog_negative), negativeMessage); 204 } 205 mDialog = mAlertDialog; 206 break; 207 208 case TEST_ALERTDIALOG_CALLBACK: 209 mDialog = new MockAlertDialog(this); 210 break; 211 case TEST_ALERTDIALOG_THEME: 212 mDialog = new MockAlertDialog(this, R.style.Theme_AlertDialog); 213 break; 214 case TEST_ALERTDIALOG_CANCELABLE: 215 mDialog = getAlertDialogCancelableInstance(true); 216 break; 217 case TEST_ALERTDIALOG_NOT_CANCELABLE: 218 mDialog = getAlertDialogCancelableInstance(false); 219 break; 220 case TEST_PROTECTED_CANCELABLE: 221 mDialog = new TestDialog(this, true, new OnCancelListener() { 222 public void onCancel(DialogInterface dialog) { 223 onCancelListenerCalled = true; 224 } 225 }); 226 break; 227 case TEST_PROTECTED_NOT_CANCELABLE: 228 mDialog = new TestDialog(this, false, new OnCancelListener() { 229 public void onCancel(DialogInterface dialog) { 230 onCancelListenerCalled = true; 231 } 232 }); 233 break; 234 case TEST_ALERT_DIALOG_ICON_DRAWABLE: 235 mAlertDialog = getAlertDialogInstance(false); 236 mAlertDialog.setIcon(mAlertDialog.getContext().getDrawable(R.drawable.robot)); 237 mDialog = mAlertDialog; 238 break; 239 case TEST_ALERT_DIALOG_ICON_ATTRIBUTE: 240 mAlertDialog = getAlertDialogInstance(false); 241 mAlertDialog.setIconAttribute(android.R.attr.alertDialogIcon); 242 mDialog = mAlertDialog; 243 break; 244 245 default: 246 break; 247 } 248 249 Log.i(LOG_TAG, "mDialog:" + mDialog); 250 return mDialog; 251 } 252 getAlertDialogCancelableInstance(boolean cancelable)253 private AlertDialog getAlertDialogCancelableInstance(boolean cancelable) { 254 OnCancelListener cancelListener = new OnCancelListener() { 255 public void onCancel(DialogInterface dialog) { 256 onCancelCalled = true; 257 } 258 }; 259 return new MockAlertDialog(this, cancelable, cancelListener); 260 } 261 262 @SuppressWarnings("deprecation") getAlertDialogInstance(boolean deprecated)263 private AlertDialog getAlertDialogInstance(boolean deprecated) { 264 mAlertDialog = new AlertDialog.Builder(DialogStubActivity.this).create(); 265 mAlertDialog.setIcon(R.drawable.pass); 266 mAlertDialog.setTitle(DEFAULT_ALERTDIALOG_TITLE); 267 mAlertDialog.setMessage(DEFAULT_ALERTDIALOG_MESSAGE); 268 mAlertDialog.setInverseBackgroundForced(true); 269 final DialogInterface.OnClickListener positiveListener = new MockOnClickListener( 270 DialogInterface.BUTTON_POSITIVE); 271 final DialogInterface.OnClickListener netativeListener = new MockOnClickListener( 272 DialogInterface.BUTTON_NEGATIVE); 273 final DialogInterface.OnClickListener neutralListener = new MockOnClickListener( 274 DialogInterface.BUTTON_NEUTRAL); 275 276 if (deprecated) { 277 mAlertDialog.setButton(getString(R.string.alert_dialog_positive), positiveListener); 278 mAlertDialog.setButton2(getString(R.string.alert_dialog_negative), netativeListener); 279 mAlertDialog.setButton3(getString(R.string.alert_dialog_neutral), neutralListener); 280 } else { 281 mAlertDialog.setButton(DialogInterface.BUTTON_POSITIVE, 282 getString(R.string.alert_dialog_positive), positiveListener); 283 mAlertDialog.setButton(DialogInterface.BUTTON_NEGATIVE, 284 getString(R.string.alert_dialog_negative), netativeListener); 285 mAlertDialog.setButton(DialogInterface.BUTTON_NEUTRAL, 286 getString(R.string.alert_dialog_neutral), neutralListener); 287 } 288 return mAlertDialog; 289 290 } 291 getCustomAlertDialogInstance(boolean withSpacing)292 private AlertDialog getCustomAlertDialogInstance(boolean withSpacing) { 293 final LayoutInflater inflate = getLayoutInflater(); 294 final View customTitleViewCustom = inflate.inflate(R.layout.alertdialog_custom_title, null); 295 final View textEntryView = inflate.inflate(R.layout.alert_dialog_text_entry_2, null); 296 mAlertDialog = new AlertDialog.Builder(DialogStubActivity.this).create(); 297 mAlertDialog.setCustomTitle(customTitleViewCustom); 298 mAlertDialog.setMessage(DEFAULT_ALERTDIALOG_MESSAGE); 299 if (withSpacing) { 300 mAlertDialog.setView(textEntryView, SPACING_LEFT, SPACING_TOP, SPACING_RIGHT, 301 SPACING_BOTTOM); 302 } else { 303 mAlertDialog.setView(textEntryView); 304 } 305 306 return mAlertDialog; 307 308 } 309 getDialog()310 public Dialog getDialog() { 311 return mDialog; 312 } 313 getDialogTitle()314 public String getDialogTitle() { 315 return (String) mDialog.getWindow().getAttributes().getTitle(); 316 } 317 318 private static final String TEST_DIALOG_NUMBER_EXTRA = "testDialogNumber"; 319 startDialogActivity( Context context, int dialogNumber)320 public static ActivityScenario<DialogStubActivity> startDialogActivity( 321 Context context, int dialogNumber) { 322 Intent intent = new Intent(Intent.ACTION_MAIN); 323 intent.putExtra(TEST_DIALOG_NUMBER_EXTRA, dialogNumber); 324 intent.setClass(context, DialogStubActivity.class); 325 return ActivityScenario.launch(intent); 326 } 327 328 @Override onCreate(Bundle savedInstanceState)329 protected void onCreate(Bundle savedInstanceState) { 330 super.onCreate(savedInstanceState); 331 332 setContentView(R.layout.dialog_stub_layout); 333 334 Intent intent = getIntent(); 335 int dialogNum = intent.getIntExtra(TEST_DIALOG_NUMBER_EXTRA, -1); 336 if (dialogNum != -1) { 337 showDialog(dialogNum); 338 } 339 } 340 setUpTitle(final String title)341 public void setUpTitle(final String title) { 342 runOnUiThread(new Runnable() { 343 public void run() { 344 getDialog().setTitle(title); 345 } 346 }); 347 } 348 setUpTitle(final int id)349 public void setUpTitle(final int id) { 350 runOnUiThread(new Runnable() { 351 public void run() { 352 getDialog().setTitle(id); 353 } 354 }); 355 } 356 357 class MockAlertDialog extends AlertDialog { MockAlertDialog(Context context)358 public MockAlertDialog(Context context) { 359 super(context); 360 } 361 MockAlertDialog(Context context, int theme)362 public MockAlertDialog(Context context, int theme) { 363 super(context, theme); 364 } 365 MockAlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener)366 public MockAlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener) { 367 super(context, cancelable, cancelListener); 368 } 369 370 @Override onKeyDown(int keyCode, KeyEvent event)371 public boolean onKeyDown(int keyCode, KeyEvent event) { 372 onKeyDownCalled = true; 373 return super.onKeyDown(keyCode, event); 374 } 375 376 @Override onKeyUp(int keyCode, KeyEvent event)377 public boolean onKeyUp(int keyCode, KeyEvent event) { 378 onKeyUpCalled = true; 379 return super.onKeyUp(keyCode, event); 380 } 381 382 @Override onCreate(Bundle savedInstanceState)383 protected void onCreate(Bundle savedInstanceState) { 384 onCreateCalled = true; 385 super.onCreate(savedInstanceState); 386 } 387 388 } 389 390 class MockOnClickListener implements DialogInterface.OnClickListener { 391 private final int mId; 392 MockOnClickListener(final int buttonId)393 public MockOnClickListener(final int buttonId) { 394 mId = buttonId; 395 } 396 onClick(DialogInterface dialog, int which)397 public void onClick(DialogInterface dialog, int which) { 398 switch (mId) { 399 case DialogInterface.BUTTON_POSITIVE: 400 isPositiveButtonClicked = true; 401 break; 402 case DialogInterface.BUTTON_NEGATIVE: 403 isNegativeButtonClicked = true; 404 break; 405 case DialogInterface.BUTTON_NEUTRAL: 406 isNeutralButtonClicked = true; 407 break; 408 default: 409 break; 410 } 411 } 412 } 413 414 class MockDatePickerDialog extends DatePickerDialog { MockDatePickerDialog(Context context, OnDateSetListener callBack, int year, int monthOfYear, int dayOfMonth)415 public MockDatePickerDialog(Context context, OnDateSetListener callBack, int year, 416 int monthOfYear, int dayOfMonth) { 417 super(context, callBack, year, monthOfYear, dayOfMonth); 418 } 419 MockDatePickerDialog(Context context, int theme, OnDateSetListener callBack, int year, int monthOfYear, int dayOfMonth)420 public MockDatePickerDialog(Context context, int theme, OnDateSetListener callBack, 421 int year, int monthOfYear, int dayOfMonth) { 422 super(context, theme, callBack, year, monthOfYear, dayOfMonth); 423 } 424 425 @Override onClick(DialogInterface dialog, int which)426 public void onClick(DialogInterface dialog, int which) { 427 onClickCalled = true; 428 super.onClick(dialog, which); 429 } 430 431 @Override onDateChanged(DatePicker view, int year, int month, int day)432 public void onDateChanged(DatePicker view, int year, int month, int day) { 433 onDateChangedCalled = true; 434 super.onDateChanged(view, year, month, day); 435 } 436 437 @Override onRestoreInstanceState(Bundle savedInstanceState)438 public void onRestoreInstanceState(Bundle savedInstanceState) { 439 onRestoreInstanceStateCalled = true; 440 super.onRestoreInstanceState(savedInstanceState); 441 } 442 443 @Override onSaveInstanceState()444 public Bundle onSaveInstanceState() { 445 onSaveInstanceStateCalled = true; 446 return super.onSaveInstanceState(); 447 } 448 449 } 450 } 451