AlarmManager.java revision c42a1e1071937ae48b7aa5d6291a32c29078b74b
1/* 2 * Copyright (C) 2007 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 android.app; 18 19import android.annotation.SdkConstant; 20import android.content.Context; 21import android.content.Intent; 22import android.os.Build; 23import android.os.RemoteException; 24import android.os.UserHandle; 25import android.os.WorkSource; 26 27/** 28 * This class provides access to the system alarm services. These allow you 29 * to schedule your application to be run at some point in the future. When 30 * an alarm goes off, the {@link Intent} that had been registered for it 31 * is broadcast by the system, automatically starting the target application 32 * if it is not already running. Registered alarms are retained while the 33 * device is asleep (and can optionally wake the device up if they go off 34 * during that time), but will be cleared if it is turned off and rebooted. 35 * 36 * <p>The Alarm Manager holds a CPU wake lock as long as the alarm receiver's 37 * onReceive() method is executing. This guarantees that the phone will not sleep 38 * until you have finished handling the broadcast. Once onReceive() returns, the 39 * Alarm Manager releases this wake lock. This means that the phone will in some 40 * cases sleep as soon as your onReceive() method completes. If your alarm receiver 41 * called {@link android.content.Context#startService Context.startService()}, it 42 * is possible that the phone will sleep before the requested service is launched. 43 * To prevent this, your BroadcastReceiver and Service will need to implement a 44 * separate wake lock policy to ensure that the phone continues running until the 45 * service becomes available. 46 * 47 * <p><b>Note: The Alarm Manager is intended for cases where you want to have 48 * your application code run at a specific time, even if your application is 49 * not currently running. For normal timing operations (ticks, timeouts, 50 * etc) it is easier and much more efficient to use 51 * {@link android.os.Handler}.</b> 52 * 53 * <p class="caution"><strong>Note:</strong> Beginning with API 19 54 * ({@link android.os.Build.VERSION_CODES#KITKAT}) alarm delivery is inexact: 55 * the OS will shift alarms in order to minimize wakeups and battery use. There are 56 * new APIs to support applications which need strict delivery guarantees; see 57 * {@link #setWindow(int, long, long, PendingIntent)} and 58 * {@link #setExact(int, long, PendingIntent)}. Applications whose {@code targetSdkVersion} 59 * is earlier than API 19 will continue to see the previous behavior in which all 60 * alarms are delivered exactly when requested. 61 * 62 * <p>You do not 63 * instantiate this class directly; instead, retrieve it through 64 * {@link android.content.Context#getSystemService 65 * Context.getSystemService(Context.ALARM_SERVICE)}. 66 */ 67public class AlarmManager 68{ 69 private static final String TAG = "AlarmManager"; 70 71 /** 72 * Alarm time in {@link System#currentTimeMillis System.currentTimeMillis()} 73 * (wall clock time in UTC), which will wake up the device when 74 * it goes off. 75 */ 76 public static final int RTC_WAKEUP = 0; 77 /** 78 * Alarm time in {@link System#currentTimeMillis System.currentTimeMillis()} 79 * (wall clock time in UTC). This alarm does not wake the 80 * device up; if it goes off while the device is asleep, it will not be 81 * delivered until the next time the device wakes up. 82 */ 83 public static final int RTC = 1; 84 /** 85 * Alarm time in {@link android.os.SystemClock#elapsedRealtime 86 * SystemClock.elapsedRealtime()} (time since boot, including sleep), 87 * which will wake up the device when it goes off. 88 */ 89 public static final int ELAPSED_REALTIME_WAKEUP = 2; 90 /** 91 * Alarm time in {@link android.os.SystemClock#elapsedRealtime 92 * SystemClock.elapsedRealtime()} (time since boot, including sleep). 93 * This alarm does not wake the device up; if it goes off while the device 94 * is asleep, it will not be delivered until the next time the device 95 * wakes up. 96 */ 97 public static final int ELAPSED_REALTIME = 3; 98 99 /** 100 * Broadcast Action: Sent after the value returned by 101 * {@link #getNextAlarmClock()} has changed. 102 * 103 * <p class="note">This is a protected intent that can only be sent by the system. 104 * It is only sent to registered receivers.</p> 105 */ 106 @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) 107 public static final String ACTION_NEXT_ALARM_CLOCK_CHANGED = 108 "android.app.action.NEXT_ALARM_CLOCK_CHANGED"; 109 110 /** @hide */ 111 public static final long WINDOW_EXACT = 0; 112 /** @hide */ 113 public static final long WINDOW_HEURISTIC = -1; 114 115 private final IAlarmManager mService; 116 private final boolean mAlwaysExact; 117 118 119 /** 120 * package private on purpose 121 */ 122 AlarmManager(IAlarmManager service, Context ctx) { 123 mService = service; 124 125 final int sdkVersion = ctx.getApplicationInfo().targetSdkVersion; 126 mAlwaysExact = (sdkVersion < Build.VERSION_CODES.KITKAT); 127 } 128 129 private long legacyExactLength() { 130 return (mAlwaysExact ? WINDOW_EXACT : WINDOW_HEURISTIC); 131 } 132 133 /** 134 * <p>Schedule an alarm. <b>Note: for timing operations (ticks, timeouts, 135 * etc) it is easier and much more efficient to use {@link android.os.Handler}.</b> 136 * If there is already an alarm scheduled for the same IntentSender, that previous 137 * alarm will first be canceled. 138 * 139 * <p>If the stated trigger time is in the past, the alarm will be triggered 140 * immediately. If there is already an alarm for this Intent 141 * scheduled (with the equality of two intents being defined by 142 * {@link Intent#filterEquals}), then it will be removed and replaced by 143 * this one. 144 * 145 * <p> 146 * The alarm is an Intent broadcast that goes to a broadcast receiver that 147 * you registered with {@link android.content.Context#registerReceiver} 148 * or through the <receiver> tag in an AndroidManifest.xml file. 149 * 150 * <p> 151 * Alarm intents are delivered with a data extra of type int called 152 * {@link Intent#EXTRA_ALARM_COUNT Intent.EXTRA_ALARM_COUNT} that indicates 153 * how many past alarm events have been accumulated into this intent 154 * broadcast. Recurring alarms that have gone undelivered because the 155 * phone was asleep may have a count greater than one when delivered. 156 * 157 * <div class="note"> 158 * <p> 159 * <b>Note:</b> Beginning in API 19, the trigger time passed to this method 160 * is treated as inexact: the alarm will not be delivered before this time, but 161 * may be deferred and delivered some time later. The OS will use 162 * this policy in order to "batch" alarms together across the entire system, 163 * minimizing the number of times the device needs to "wake up" and minimizing 164 * battery use. In general, alarms scheduled in the near future will not 165 * be deferred as long as alarms scheduled far in the future. 166 * 167 * <p> 168 * With the new batching policy, delivery ordering guarantees are not as 169 * strong as they were previously. If the application sets multiple alarms, 170 * it is possible that these alarms' <em>actual</em> delivery ordering may not match 171 * the order of their <em>requested</em> delivery times. If your application has 172 * strong ordering requirements there are other APIs that you can use to get 173 * the necessary behavior; see {@link #setWindow(int, long, long, PendingIntent)} 174 * and {@link #setExact(int, long, PendingIntent)}. 175 * 176 * <p> 177 * Applications whose {@code targetSdkVersion} is before API 19 will 178 * continue to get the previous alarm behavior: all of their scheduled alarms 179 * will be treated as exact. 180 * </div> 181 * 182 * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP}, 183 * {@link #RTC}, or {@link #RTC_WAKEUP}. 184 * @param triggerAtMillis time in milliseconds that the alarm should go 185 * off, using the appropriate clock (depending on the alarm type). 186 * @param operation Action to perform when the alarm goes off; 187 * typically comes from {@link PendingIntent#getBroadcast 188 * IntentSender.getBroadcast()}. 189 * 190 * @see android.os.Handler 191 * @see #setExact 192 * @see #setRepeating 193 * @see #setWindow 194 * @see #cancel 195 * @see android.content.Context#sendBroadcast 196 * @see android.content.Context#registerReceiver 197 * @see android.content.Intent#filterEquals 198 * @see #ELAPSED_REALTIME 199 * @see #ELAPSED_REALTIME_WAKEUP 200 * @see #RTC 201 * @see #RTC_WAKEUP 202 */ 203 public void set(int type, long triggerAtMillis, PendingIntent operation) { 204 setImpl(type, triggerAtMillis, legacyExactLength(), 0, operation, null, null); 205 } 206 207 /** 208 * Schedule a repeating alarm. <b>Note: for timing operations (ticks, 209 * timeouts, etc) it is easier and much more efficient to use 210 * {@link android.os.Handler}.</b> If there is already an alarm scheduled 211 * for the same IntentSender, it will first be canceled. 212 * 213 * <p>Like {@link #set}, except you can also supply a period at which 214 * the alarm will automatically repeat. This alarm continues 215 * repeating until explicitly removed with {@link #cancel}. If the stated 216 * trigger time is in the past, the alarm will be triggered immediately, with an 217 * alarm count depending on how far in the past the trigger time is relative 218 * to the repeat interval. 219 * 220 * <p>If an alarm is delayed (by system sleep, for example, for non 221 * _WAKEUP alarm types), a skipped repeat will be delivered as soon as 222 * possible. After that, future alarms will be delivered according to the 223 * original schedule; they do not drift over time. For example, if you have 224 * set a recurring alarm for the top of every hour but the phone was asleep 225 * from 7:45 until 8:45, an alarm will be sent as soon as the phone awakens, 226 * then the next alarm will be sent at 9:00. 227 * 228 * <p>If your application wants to allow the delivery times to drift in 229 * order to guarantee that at least a certain time interval always elapses 230 * between alarms, then the approach to take is to use one-time alarms, 231 * scheduling the next one yourself when handling each alarm delivery. 232 * 233 * <p class="note"> 234 * <b>Note:</b> as of API 19, all repeating alarms are inexact. If your 235 * application needs precise delivery times then it must use one-time 236 * exact alarms, rescheduling each time as described above. Legacy applications 237 * whose {@code targetSdkVersion} is earlier than API 19 will continue to have all 238 * of their alarms, including repeating alarms, treated as exact. 239 * 240 * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP}, 241 * {@link #RTC}, or {@link #RTC_WAKEUP}. 242 * @param triggerAtMillis time in milliseconds that the alarm should first 243 * go off, using the appropriate clock (depending on the alarm type). 244 * @param intervalMillis interval in milliseconds between subsequent repeats 245 * of the alarm. 246 * @param operation Action to perform when the alarm goes off; 247 * typically comes from {@link PendingIntent#getBroadcast 248 * IntentSender.getBroadcast()}. 249 * 250 * @see android.os.Handler 251 * @see #set 252 * @see #setExact 253 * @see #setWindow 254 * @see #cancel 255 * @see android.content.Context#sendBroadcast 256 * @see android.content.Context#registerReceiver 257 * @see android.content.Intent#filterEquals 258 * @see #ELAPSED_REALTIME 259 * @see #ELAPSED_REALTIME_WAKEUP 260 * @see #RTC 261 * @see #RTC_WAKEUP 262 */ 263 public void setRepeating(int type, long triggerAtMillis, 264 long intervalMillis, PendingIntent operation) { 265 setImpl(type, triggerAtMillis, legacyExactLength(), intervalMillis, operation, null, null); 266 } 267 268 /** 269 * Schedule an alarm to be delivered within a given window of time. This method 270 * is similar to {@link #set(int, long, PendingIntent)}, but allows the 271 * application to precisely control the degree to which its delivery might be 272 * adjusted by the OS. This method allows an application to take advantage of the 273 * battery optimizations that arise from delivery batching even when it has 274 * modest timeliness requirements for its alarms. 275 * 276 * <p> 277 * This method can also be used to achieve strict ordering guarantees among 278 * multiple alarms by ensuring that the windows requested for each alarm do 279 * not intersect. 280 * 281 * <p> 282 * When precise delivery is not required, applications should use the standard 283 * {@link #set(int, long, PendingIntent)} method. This will give the OS the most 284 * flexibility to minimize wakeups and battery use. For alarms that must be delivered 285 * at precisely-specified times with no acceptable variation, applications can use 286 * {@link #setExact(int, long, PendingIntent)}. 287 * 288 * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP}, 289 * {@link #RTC}, or {@link #RTC_WAKEUP}. 290 * @param windowStartMillis The earliest time, in milliseconds, that the alarm should 291 * be delivered, expressed in the appropriate clock's units (depending on the alarm 292 * type). 293 * @param windowLengthMillis The length of the requested delivery window, 294 * in milliseconds. The alarm will be delivered no later than this many 295 * milliseconds after {@code windowStartMillis}. Note that this parameter 296 * is a <i>duration,</i> not the timestamp of the end of the window. 297 * @param operation Action to perform when the alarm goes off; 298 * typically comes from {@link PendingIntent#getBroadcast 299 * IntentSender.getBroadcast()}. 300 * 301 * @see #set 302 * @see #setExact 303 * @see #setRepeating 304 * @see #cancel 305 * @see android.content.Context#sendBroadcast 306 * @see android.content.Context#registerReceiver 307 * @see android.content.Intent#filterEquals 308 * @see #ELAPSED_REALTIME 309 * @see #ELAPSED_REALTIME_WAKEUP 310 * @see #RTC 311 * @see #RTC_WAKEUP 312 */ 313 public void setWindow(int type, long windowStartMillis, long windowLengthMillis, 314 PendingIntent operation) { 315 setImpl(type, windowStartMillis, windowLengthMillis, 0, operation, null, null); 316 } 317 318 /** 319 * Schedule an alarm to be delivered precisely at the stated time. 320 * 321 * <p> 322 * This method is like {@link #set(int, long, PendingIntent)}, but does not permit 323 * the OS to adjust the delivery time. The alarm will be delivered as nearly as 324 * possible to the requested trigger time. 325 * 326 * <p> 327 * <b>Note:</b> only alarms for which there is a strong demand for exact-time 328 * delivery (such as an alarm clock ringing at the requested time) should be 329 * scheduled as exact. Applications are strongly discouraged from using exact 330 * alarms unnecessarily as they reduce the OS's ability to minimize battery use. 331 * 332 * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP}, 333 * {@link #RTC}, or {@link #RTC_WAKEUP}. 334 * @param triggerAtMillis time in milliseconds that the alarm should go 335 * off, using the appropriate clock (depending on the alarm type). 336 * @param operation Action to perform when the alarm goes off; 337 * typically comes from {@link PendingIntent#getBroadcast 338 * IntentSender.getBroadcast()}. 339 * 340 * @see #set 341 * @see #setRepeating 342 * @see #setWindow 343 * @see #cancel 344 * @see android.content.Context#sendBroadcast 345 * @see android.content.Context#registerReceiver 346 * @see android.content.Intent#filterEquals 347 * @see #ELAPSED_REALTIME 348 * @see #ELAPSED_REALTIME_WAKEUP 349 * @see #RTC 350 * @see #RTC_WAKEUP 351 */ 352 public void setExact(int type, long triggerAtMillis, PendingIntent operation) { 353 setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, operation, null, null); 354 } 355 356 /** 357 * Schedule an alarm that represents an alarm clock. 358 * 359 * The system may choose to display information about this alarm to the user. 360 * 361 * <p> 362 * This method is like {@link #setExact(int, long, PendingIntent)}, but implies 363 * {@link #RTC_WAKEUP}. 364 * 365 * @param info 366 * @param operation Action to perform when the alarm goes off; 367 * typically comes from {@link PendingIntent#getBroadcast 368 * IntentSender.getBroadcast()}. 369 * 370 * @see #set 371 * @see #setRepeating 372 * @see #setWindow 373 * @see #setExact 374 * @see #cancel 375 * @see #getNextAlarmClock() 376 * @see android.content.Context#sendBroadcast 377 * @see android.content.Context#registerReceiver 378 * @see android.content.Intent#filterEquals 379 */ 380 public void setAlarmClock(AlarmClockInfo info, PendingIntent operation) { 381 setImpl(RTC_WAKEUP, info.getTriggerTime(), WINDOW_EXACT, 0, operation, null, info); 382 } 383 384 /** @hide */ 385 public void set(int type, long triggerAtMillis, long windowMillis, long intervalMillis, 386 PendingIntent operation, WorkSource workSource) { 387 setImpl(type, triggerAtMillis, windowMillis, intervalMillis, operation, workSource, null); 388 } 389 390 private void setImpl(int type, long triggerAtMillis, long windowMillis, long intervalMillis, 391 PendingIntent operation, WorkSource workSource, AlarmClockInfo alarmClock) { 392 if (triggerAtMillis < 0) { 393 /* NOTYET 394 if (mAlwaysExact) { 395 // Fatal error for KLP+ apps to use negative trigger times 396 throw new IllegalArgumentException("Invalid alarm trigger time " 397 + triggerAtMillis); 398 } 399 */ 400 triggerAtMillis = 0; 401 } 402 403 try { 404 mService.set(type, triggerAtMillis, windowMillis, intervalMillis, operation, 405 workSource, alarmClock); 406 } catch (RemoteException ex) { 407 } 408 } 409 410 /** 411 * Available inexact recurrence interval recognized by 412 * {@link #setInexactRepeating(int, long, long, PendingIntent)} 413 * when running on Android prior to API 19. 414 */ 415 public static final long INTERVAL_FIFTEEN_MINUTES = 15 * 60 * 1000; 416 417 /** 418 * Available inexact recurrence interval recognized by 419 * {@link #setInexactRepeating(int, long, long, PendingIntent)} 420 * when running on Android prior to API 19. 421 */ 422 public static final long INTERVAL_HALF_HOUR = 2*INTERVAL_FIFTEEN_MINUTES; 423 424 /** 425 * Available inexact recurrence interval recognized by 426 * {@link #setInexactRepeating(int, long, long, PendingIntent)} 427 * when running on Android prior to API 19. 428 */ 429 public static final long INTERVAL_HOUR = 2*INTERVAL_HALF_HOUR; 430 431 /** 432 * Available inexact recurrence interval recognized by 433 * {@link #setInexactRepeating(int, long, long, PendingIntent)} 434 * when running on Android prior to API 19. 435 */ 436 public static final long INTERVAL_HALF_DAY = 12*INTERVAL_HOUR; 437 438 /** 439 * Available inexact recurrence interval recognized by 440 * {@link #setInexactRepeating(int, long, long, PendingIntent)} 441 * when running on Android prior to API 19. 442 */ 443 public static final long INTERVAL_DAY = 2*INTERVAL_HALF_DAY; 444 445 /** 446 * Schedule a repeating alarm that has inexact trigger time requirements; 447 * for example, an alarm that repeats every hour, but not necessarily at 448 * the top of every hour. These alarms are more power-efficient than 449 * the strict recurrences traditionally supplied by {@link #setRepeating}, since the 450 * system can adjust alarms' delivery times to cause them to fire simultaneously, 451 * avoiding waking the device from sleep more than necessary. 452 * 453 * <p>Your alarm's first trigger will not be before the requested time, 454 * but it might not occur for almost a full interval after that time. In 455 * addition, while the overall period of the repeating alarm will be as 456 * requested, the time between any two successive firings of the alarm 457 * may vary. If your application demands very low jitter, use 458 * one-shot alarms with an appropriate window instead; see {@link 459 * #setWindow(int, long, long, PendingIntent)} and 460 * {@link #setExact(int, long, PendingIntent)}. 461 * 462 * <p class="note"> 463 * As of API 19, all repeating alarms are inexact. Because this method has 464 * been available since API 3, your application can safely call it and be 465 * assured that it will get similar behavior on both current and older versions 466 * of Android. 467 * 468 * @param type One of {@link #ELAPSED_REALTIME}, {@link #ELAPSED_REALTIME_WAKEUP}, 469 * {@link #RTC}, or {@link #RTC_WAKEUP}. 470 * @param triggerAtMillis time in milliseconds that the alarm should first 471 * go off, using the appropriate clock (depending on the alarm type). This 472 * is inexact: the alarm will not fire before this time, but there may be a 473 * delay of almost an entire alarm interval before the first invocation of 474 * the alarm. 475 * @param intervalMillis interval in milliseconds between subsequent repeats 476 * of the alarm. Prior to API 19, if this is one of INTERVAL_FIFTEEN_MINUTES, 477 * INTERVAL_HALF_HOUR, INTERVAL_HOUR, INTERVAL_HALF_DAY, or INTERVAL_DAY 478 * then the alarm will be phase-aligned with other alarms to reduce the 479 * number of wakeups. Otherwise, the alarm will be set as though the 480 * application had called {@link #setRepeating}. As of API 19, all repeating 481 * alarms will be inexact and subject to batching with other alarms regardless 482 * of their stated repeat interval. 483 * @param operation Action to perform when the alarm goes off; 484 * typically comes from {@link PendingIntent#getBroadcast 485 * IntentSender.getBroadcast()}. 486 * 487 * @see android.os.Handler 488 * @see #set 489 * @see #cancel 490 * @see android.content.Context#sendBroadcast 491 * @see android.content.Context#registerReceiver 492 * @see android.content.Intent#filterEquals 493 * @see #ELAPSED_REALTIME 494 * @see #ELAPSED_REALTIME_WAKEUP 495 * @see #RTC 496 * @see #RTC_WAKEUP 497 * @see #INTERVAL_FIFTEEN_MINUTES 498 * @see #INTERVAL_HALF_HOUR 499 * @see #INTERVAL_HOUR 500 * @see #INTERVAL_HALF_DAY 501 * @see #INTERVAL_DAY 502 */ 503 public void setInexactRepeating(int type, long triggerAtMillis, 504 long intervalMillis, PendingIntent operation) { 505 setImpl(type, triggerAtMillis, WINDOW_HEURISTIC, intervalMillis, operation, null, null); 506 } 507 508 /** 509 * Remove any alarms with a matching {@link Intent}. 510 * Any alarm, of any type, whose Intent matches this one (as defined by 511 * {@link Intent#filterEquals}), will be canceled. 512 * 513 * @param operation IntentSender which matches a previously added 514 * IntentSender. 515 * 516 * @see #set 517 */ 518 public void cancel(PendingIntent operation) { 519 try { 520 mService.remove(operation); 521 } catch (RemoteException ex) { 522 } 523 } 524 525 /** 526 * Set the system wall clock time. 527 * Requires the permission android.permission.SET_TIME. 528 * 529 * @param millis time in milliseconds since the Epoch 530 */ 531 public void setTime(long millis) { 532 try { 533 mService.setTime(millis); 534 } catch (RemoteException ex) { 535 } 536 } 537 538 /** 539 * Set the system default time zone. 540 * Requires the permission android.permission.SET_TIME_ZONE. 541 * 542 * @param timeZone in the format understood by {@link java.util.TimeZone} 543 */ 544 public void setTimeZone(String timeZone) { 545 try { 546 mService.setTimeZone(timeZone); 547 } catch (RemoteException ex) { 548 } 549 } 550 551 /** 552 * Gets information about the next alarm clock currently scheduled. 553 * 554 * The alarm clocks considered are those scheduled by {@link #setAlarmClock} 555 * from any package of the calling user. 556 * 557 * @see #setAlarmClock 558 * @see AlarmClockInfo 559 */ 560 public AlarmClockInfo getNextAlarmClock() { 561 return getNextAlarmClock(UserHandle.myUserId()); 562 } 563 564 /** 565 * Gets information about the next alarm clock currently scheduled. 566 * 567 * The alarm clocks considered are those scheduled by {@link #setAlarmClock} 568 * from any package of the given {@parm userId}. 569 * 570 * @see #setAlarmClock 571 * @see AlarmClockInfo 572 * 573 * @hide 574 */ 575 public AlarmClockInfo getNextAlarmClock(int userId) { 576 try { 577 return mService.getNextAlarmClock(userId); 578 } catch (RemoteException ex) { 579 return null; 580 } 581 } 582} 583