List of usage examples for android.app PendingIntent getService
public static PendingIntent getService(Context context, int requestCode, @NonNull Intent intent, @Flags int flags)
From source file:com.chen.mail.utils.NotificationActionUtils.java
/** * Creates a {@link PendingIntent} to be used for creating and canceling the undo timeout * alarm.//from www .j a va 2 s. co m */ private static PendingIntent createUndoTimeoutPendingIntent(final Context context, final NotificationAction notificationAction) { final Intent intent = new Intent(NotificationActionIntentService.ACTION_UNDO_TIMEOUT); intent.setPackage(context.getPackageName()); putNotificationActionExtra(intent, notificationAction); final int requestCode = notificationAction.getAccount().hashCode() ^ notificationAction.getFolder().hashCode(); final PendingIntent pendingIntent = PendingIntent.getService(context, requestCode, intent, 0); return pendingIntent; }
From source file:com.chen.mail.utils.NotificationUtils.java
/** * Validate the notifications notification. *///from w w w . j av a 2 s. co m private static void validateNotifications(Context context, final Folder folder, final Account account, boolean getAttention, boolean ignoreUnobtrusiveSetting, NotificationKey key) { NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); final NotificationMap notificationMap = getNotificationMap(context); if (LogUtils.isLoggable(LOG_TAG, LogUtils.VERBOSE)) { LogUtils.i(LOG_TAG, "Validating Notification: %s mapSize: %d " + "folder: %s getAttention: %b", createNotificationString(notificationMap), notificationMap.size(), folder.name, getAttention); } else { LogUtils.i(LOG_TAG, "Validating Notification, mapSize: %d " + "getAttention: %b", notificationMap.size(), getAttention); } // The number of unread messages for this account and label. final Integer unread = notificationMap.getUnread(key); final int unreadCount = unread != null ? unread.intValue() : 0; final Integer unseen = notificationMap.getUnseen(key); int unseenCount = unseen != null ? unseen.intValue() : 0; Cursor cursor = null; try { final Uri.Builder uriBuilder = folder.conversationListUri.buildUpon(); uriBuilder.appendQueryParameter(UIProvider.SEEN_QUERY_PARAMETER, Boolean.FALSE.toString()); // Do not allow this quick check to disrupt any active network-enabled conversation // cursor. uriBuilder.appendQueryParameter(UIProvider.ConversationListQueryParameters.USE_NETWORK, Boolean.FALSE.toString()); cursor = context.getContentResolver().query(uriBuilder.build(), UIProvider.CONVERSATION_PROJECTION, null, null, null); if (cursor == null) { // This folder doesn't exist. LogUtils.i(LOG_TAG, "The cursor is null, so the specified folder probably does not exist"); clearFolderNotification(context, account, folder, false); return; } final int cursorUnseenCount = cursor.getCount(); // Make sure the unseen count matches the number of items in the cursor. But, we don't // want to overwrite a 0 unseen count that was specified in the intent if (unseenCount != 0 && unseenCount != cursorUnseenCount) { LogUtils.i(LOG_TAG, "Unseen count doesn't match cursor count. unseen: %d cursor count: %d", unseenCount, cursorUnseenCount); unseenCount = cursorUnseenCount; } // For the purpose of the notifications, the unseen count should be capped at the num of // unread conversations. if (unseenCount > unreadCount) { unseenCount = unreadCount; } final int notificationId = getNotificationId(account.getAccountManagerAccount(), folder); if (unseenCount == 0) { LogUtils.i(LOG_TAG, "validateNotifications - cancelling account %s / folder %s", LogUtils.sanitizeName(LOG_TAG, account.name), LogUtils.sanitizeName(LOG_TAG, folder.persistentId)); nm.cancel(notificationId); return; } // We now have all we need to create the notification and the pending intent PendingIntent clickIntent; NotificationCompat.Builder notification = new NotificationCompat.Builder(context); notification.setSmallIcon(R.drawable.stat_notify_email); notification.setTicker(account.name); final long when; final long oldWhen = NotificationActionUtils.sNotificationTimestamps.get(notificationId); if (oldWhen != 0) { when = oldWhen; } else { when = System.currentTimeMillis(); } notification.setWhen(when); // The timestamp is now stored in the notification, so we can remove it from here NotificationActionUtils.sNotificationTimestamps.delete(notificationId); // Dispatch a CLEAR_NEW_MAIL_NOTIFICATIONS intent if the user taps the "X" next to a // notification. Also this intent gets fired when the user taps on a notification as // the AutoCancel flag has been set final Intent cancelNotificationIntent = new Intent( MailIntentService.ACTION_CLEAR_NEW_MAIL_NOTIFICATIONS); cancelNotificationIntent.setPackage(context.getPackageName()); cancelNotificationIntent.setData(Utils.appendVersionQueryParameter(context, folder.folderUri.fullUri)); cancelNotificationIntent.putExtra(Utils.EXTRA_ACCOUNT, account); cancelNotificationIntent.putExtra(Utils.EXTRA_FOLDER, folder); notification.setDeleteIntent( PendingIntent.getService(context, notificationId, cancelNotificationIntent, 0)); // Ensure that the notification is cleared when the user selects it notification.setAutoCancel(true); boolean eventInfoConfigured = false; final boolean isInbox = folder.folderUri.equals(account.settings.defaultInbox); final FolderPreferences folderPreferences = new FolderPreferences(context, account.getEmailAddress(), folder, isInbox); if (isInbox) { final AccountPreferences accountPreferences = new AccountPreferences(context, account.getEmailAddress()); moveNotificationSetting(accountPreferences, folderPreferences); } if (!folderPreferences.areNotificationsEnabled()) { LogUtils.i(LOG_TAG, "Notifications are disabled for this folder; not notifying"); // Don't notify return; } if (unreadCount > 0) { // How can I order this properly? if (cursor.moveToNext()) { final Intent notificationIntent; // Launch directly to the conversation, if there is only 1 unseen conversation final boolean launchConversationMode = (unseenCount == 1); if (launchConversationMode) { notificationIntent = createViewConversationIntent(context, account, folder, cursor); } else { notificationIntent = createViewConversationIntent(context, account, folder, null); } Analytics.getInstance().sendEvent("notification_create", launchConversationMode ? "conversation" : "conversation_list", folder.getTypeDescription(), unseenCount); if (notificationIntent == null) { LogUtils.e(LOG_TAG, "Null intent when building notification"); return; } // Amend the click intent with a hint that its source was a notification, // but remove the hint before it's used to generate notification action // intents. This prevents the following sequence: // 1. generate single notification // 2. user clicks reply, then completes Compose activity // 3. main activity launches, gets FROM_NOTIFICATION hint in intent notificationIntent.putExtra(Utils.EXTRA_FROM_NOTIFICATION, true); clickIntent = PendingIntent.getActivity(context, -1, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); notificationIntent.removeExtra(Utils.EXTRA_FROM_NOTIFICATION); configureLatestEventInfoFromConversation(context, account, folderPreferences, notification, cursor, clickIntent, notificationIntent, unreadCount, unseenCount, folder, when); eventInfoConfigured = true; } } final boolean vibrate = folderPreferences.isNotificationVibrateEnabled(); final String ringtoneUri = folderPreferences.getNotificationRingtoneUri(); final boolean notifyOnce = !folderPreferences.isEveryMessageNotificationEnabled(); if (!ignoreUnobtrusiveSetting && notifyOnce) { // If the user has "unobtrusive notifications" enabled, only alert the first time // new mail is received in this account. This is the default behavior. See // bugs 2412348 and 2413490. notification.setOnlyAlertOnce(true); } LogUtils.i(LOG_TAG, "Account: %s vibrate: %s", LogUtils.sanitizeName(LOG_TAG, account.name), Boolean.toString(folderPreferences.isNotificationVibrateEnabled())); int defaults = 0; /* * We do not want to notify if this is coming back from an Undo notification, hence the * oldWhen check. */ if (getAttention && oldWhen == 0) { final AccountPreferences accountPreferences = new AccountPreferences(context, account.name); if (accountPreferences.areNotificationsEnabled()) { if (vibrate) { defaults |= Notification.DEFAULT_VIBRATE; } notification.setSound(TextUtils.isEmpty(ringtoneUri) ? null : Uri.parse(ringtoneUri)); LogUtils.i(LOG_TAG, "New email in %s vibrateWhen: %s, playing notification: %s", LogUtils.sanitizeName(LOG_TAG, account.name), vibrate, ringtoneUri); } } // TODO(skennedy) Why do we do any of the above if we're just going to bail here? if (eventInfoConfigured) { defaults |= Notification.DEFAULT_LIGHTS; notification.setDefaults(defaults); if (oldWhen != 0) { // We do not want to display the ticker again if we are re-displaying this // notification (like from an Undo notification) notification.setTicker(null); } nm.notify(notificationId, notification.build()); } else { LogUtils.i(LOG_TAG, "event info not configured - not notifying"); } } finally { if (cursor != null) { cursor.close(); } } }
From source file:com.cyanogenmod.eleven.MusicPlaybackService.java
/** * {@inheritDoc}//from w w w . j a v a 2s.c o m */ @Override public void onCreate() { if (D) Log.d(TAG, "Creating service"); super.onCreate(); mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); // Initialize the favorites and recents databases mRecentsCache = RecentStore.getInstance(this); // gets the song play count cache mSongPlayCountCache = SongPlayCount.getInstance(this); // gets a pointer to the playback state store mPlaybackStateStore = MusicPlaybackState.getInstance(this); // Initialize the image fetcher mImageFetcher = ImageFetcher.getInstance(this); // Initialize the image cache mImageFetcher.setImageCache(ImageCache.getInstance(this)); // Start up the thread running the service. Note that we create a // separate thread because the service normally runs in the process's // main thread, which we don't want to block. We also make it // background priority so CPU-intensive work will not disrupt the UI. mHandlerThread = new HandlerThread("MusicPlayerHandler", android.os.Process.THREAD_PRIORITY_BACKGROUND); mHandlerThread.start(); // Initialize the handler mPlayerHandler = new MusicPlayerHandler(this, mHandlerThread.getLooper()); // Initialize the audio manager and register any headset controls for // playback mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); mMediaButtonReceiverComponent = new ComponentName(getPackageName(), MediaButtonIntentReceiver.class.getName()); mAudioManager.registerMediaButtonEventReceiver(mMediaButtonReceiverComponent); // Use the remote control APIs to set the playback state setUpMediaSession(); // Initialize the preferences mPreferences = getSharedPreferences("Service", 0); mCardId = getCardId(); registerExternalStorageListener(); // Initialize the media player mPlayer = new MultiPlayer(this); mPlayer.setHandler(mPlayerHandler); // Initialize the intent filter and each action final IntentFilter filter = new IntentFilter(); filter.addAction(SERVICECMD); filter.addAction(TOGGLEPAUSE_ACTION); filter.addAction(PAUSE_ACTION); filter.addAction(STOP_ACTION); filter.addAction(NEXT_ACTION); filter.addAction(PREVIOUS_ACTION); filter.addAction(PREVIOUS_FORCE_ACTION); filter.addAction(REPEAT_ACTION); filter.addAction(SHUFFLE_ACTION); // Attach the broadcast listener registerReceiver(mIntentReceiver, filter); // Get events when MediaStore content changes mMediaStoreObserver = new MediaStoreObserver(mPlayerHandler); getContentResolver().registerContentObserver(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, true, mMediaStoreObserver); getContentResolver().registerContentObserver(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, true, mMediaStoreObserver); // Initialize the delayed shutdown intent final Intent shutdownIntent = new Intent(this, MusicPlaybackService.class); shutdownIntent.setAction(SHUTDOWN); mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); mShutdownIntent = PendingIntent.getService(this, 0, shutdownIntent, 0); // Listen for the idle state scheduleDelayedShutdown(); // Bring the queue back reloadQueue(); notifyChange(QUEUE_CHANGED); notifyChange(META_CHANGED); }
From source file:com.prod.intelligent7.engineautostart.ConnectDaemonService.java
void startHourlyCheckAlarm() { if (scheduleAlarm != null) { alarmManager.cancel(scheduleAlarm); //return; }//from w ww .ja v a 2 s .c om Intent jIntent = new Intent(this, ConnectDaemonService.class); //M1-00 (cool) or M1-01 (warm) jIntent.putExtra(ConnectDaemonService.ALARM_DONE, ALARM_HOUR); jIntent.setAction(ALARM_HOUR); scheduleAlarm = PendingIntent.getService(this, ++alarmRequestId % 100 + 500, jIntent, PendingIntent.FLAG_ONE_SHOT); alarmManager.set(AlarmManager.RTC_WAKEUP, 1 * 60 * 60 * 1000 + System.currentTimeMillis(), scheduleAlarm); Log.i("ALARM_SET", "restart check alarm set for 1 hour"); //startScheduledJobs(); }
From source file:com.massivcode.androidmusicplayer.services.MusicService.java
private void showNotificationUpperKitKat(MediaMetadataCompat metadata) { // Notification NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext()); // Hide the timestamp builder.setShowWhen(false);/*w w w . j a va2 s .c om*/ // Set the Notification style builder.setStyle(new NotificationCompat.MediaStyle().setMediaSession(mSession.getSessionToken()) .setShowActionsInCompactView(0, 1, 2)); // Set the Notification color builder.setColor(Color.parseColor("#2196F3")); // Set the large and small icons Bitmap bitmap = MusicInfoLoadUtil.getBitmap(getApplicationContext(), mCurrentMusicInfo.getUri(), 4); if (bitmap == null) { bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_no_image); } builder.setLargeIcon(bitmap); builder.setSmallIcon(R.mipmap.ic_no_image); builder.setContentTitle(mCurrentMusicInfo.getTitle()); builder.setContentText(mCurrentMusicInfo.getArtist()); int icon; if (mMediaPlayer.isPlaying()) { Log.d(TAG, "is playing"); icon = android.R.drawable.ic_media_pause; } else { Log.d(TAG, "is not playing"); icon = android.R.drawable.ic_media_play; } // ? ? ? // ========================================================================================= Intent musicPreviousIntent = new Intent(getApplicationContext(), MusicService.class); musicPreviousIntent.putExtra("metadata", metadata); musicPreviousIntent.setAction(ACTION_PLAY_PREVIOUS); musicPreviousIntent.putExtra("position", getPositionAtPreviousOrNext(ACTION_PLAY_PREVIOUS)); PendingIntent musicPreviousPendingIntent = PendingIntent.getService(getApplicationContext(), 0, musicPreviousIntent, PendingIntent.FLAG_UPDATE_CURRENT); builder.addAction(android.R.drawable.ic_media_previous, "prev", musicPreviousPendingIntent); // ========================================================================================= // ? ? ? // ========================================================================================= Intent musicStopIntent = new Intent(getApplicationContext(), MusicService.class); musicStopIntent.putExtra("metadata", metadata); musicStopIntent.setAction(ACTION_PAUSE); PendingIntent musicStopPendingIntent = PendingIntent.getService(getApplicationContext(), 1, musicStopIntent, PendingIntent.FLAG_UPDATE_CURRENT); builder.addAction(icon, "pause", musicStopPendingIntent); // ========================================================================================= // ? ? ? // ========================================================================================= Intent musicNextIntent = new Intent(getApplicationContext(), MusicService.class); musicNextIntent.putExtra("metadata", metadata); musicNextIntent.setAction(ACTION_PLAY_NEXT); musicNextIntent.putExtra("position", getPositionAtPreviousOrNext(ACTION_PLAY_NEXT)); PendingIntent musicNextPendingIntent = PendingIntent.getService(getApplicationContext(), 2, musicNextIntent, PendingIntent.FLAG_UPDATE_CURRENT); builder.addAction(android.R.drawable.ic_media_next, "next", musicNextPendingIntent); // ========================================================================================= // ? ? // ========================================================================================= Intent closeIntent = new Intent(getApplicationContext(), MusicService.class); closeIntent.setAction(ACTION_FINISH); PendingIntent closePendingIntent = PendingIntent.getService(getApplicationContext(), 3, closeIntent, PendingIntent.FLAG_UPDATE_CURRENT); builder.addAction(android.R.drawable.arrow_up_float, "close", closePendingIntent); // ========================================================================================= // Notification ? PendingIntent // ========================================================================================= Intent activityStartIntent = new Intent(MainActivity.ACTION_NAME); activityStartIntent.putExtra("restore", getCurrentInfo()); PendingIntent activityStartPendingIntent = PendingIntent.getActivity(getApplicationContext(), 1, activityStartIntent, PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentIntent(activityStartPendingIntent); // ========================================================================================= Notification notification = builder.setAutoCancel(true).build(); startForeground(1, notification); }
From source file:com.yohpapa.research.simplemusicplayer.PlaybackService.java
private void showNotification(int playState, int audioPath, String title, String artist, String album, Bitmap artwork) {// www. j a v a 2s. c om NotificationCompat.Builder builder = new NotificationCompat.Builder(this); builder.setWhen(System.currentTimeMillis()); builder.setContentTitle(title); if (artwork != null) { builder.setLargeIcon(artwork); } int icon = R.drawable.ic_launcher; if (audioPath == AUDIO_PATH_SPEAKER) { icon = R.drawable.ic_speaker; } else if (audioPath == AUDIO_PATH_A2DP) { icon = R.drawable.ic_a2dp; } else if (audioPath == AUDIO_PATH_WIRED) { icon = R.drawable.ic_wired; } builder.setSmallIcon(icon); builder.setTicker(title); builder.setPriority(NotificationCompat.PRIORITY_HIGH); builder.setContentText(artist); builder.setSubText(album); PendingIntent pendingIntent = null; Intent intent = new Intent(this, PlaybackService.class); String keyTop; String action; if (playState == PLAY_STATE_PAUSED) { action = ACTION_PAUSE; keyTop = "Pause"; icon = android.R.drawable.ic_media_pause; intent = new Intent(this, PlaybackService.class); intent.setAction(ACTION_TRACK_DOWN); pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); builder.addAction(android.R.drawable.ic_media_previous, "Prev", pendingIntent); } else { action = ACTION_PLAY; keyTop = "Play"; icon = android.R.drawable.ic_media_play; intent = new Intent(this, PlaybackService.class); intent.setAction(ACTION_STOP); pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); builder.addAction(android.R.drawable.ic_delete, "Stop", pendingIntent); } intent = new Intent(this, PlaybackService.class); intent.setAction(action); pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); builder.addAction(icon, keyTop, pendingIntent); intent = new Intent(this, PlaybackService.class); intent.setAction(ACTION_TRACK_UP); pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); builder.addAction(android.R.drawable.ic_media_next, "Next", pendingIntent); intent = new Intent(this, SimpleMusicPlayer.class); pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentIntent(pendingIntent); startForeground(R.id.notification_id, builder.build()); // startForeground(R.id.notification_id, new NotificationCompat.InboxStyle(builder).addLine("test1").addLine("test2").build()); }
From source file:com.umundus.service.NCallServiceOld.java
public void onCreate() { Log.d(TAG, "[*]Service-onCreate"); super.onCreate(); IntentFilter filter = new IntentFilter(ACTION_START_PATTERN_SEND_DATA); filter.addAction(ACTION_END_PATTERN_SEND_DATA); registerReceiver(mBroadcastReceiver, filter); int myID = 1234; Intent intent = new Intent(this, NCallServiceOld.class); //PendingIntent pendIntent = PendingIntent.getActivity(this, 0, bindIntent, 0); PendingIntent pi = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_NO_CREATE); Notification notice = new Notification.Builder(this).setContentTitle("(Rang)") .setContentText("(Rang)? .").setSmallIcon(R.drawable.ic_launcher) .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher)).setOngoing(true) .setContentIntent(pi).build(); notice.flags |= Notification.FLAG_NO_CLEAR; notice.flags |= Notification.FLAG_ONGOING_EVENT; startForeground(myID, notice);/*from www . j ava 2 s. com*/ AlarmManager al = (AlarmManager) this.getSystemService(this.ALARM_SERVICE); al.setRepeating(AlarmManager.RTC, System.currentTimeMillis(), 1000 * 15, pi); }
From source file:com.android.mail.utils.NotificationActionUtils.java
public static Notification createUndoNotification(final Context context, final NotificationAction notificationAction, final int notificationId) { LogUtils.i(LOG_TAG, "createUndoNotification for %s", notificationAction.getNotificationActionType()); final NotificationCompat.Builder builder = new NotificationCompat.Builder(context); builder.setSmallIcon(R.drawable.ic_notification_mail_24dp); builder.setWhen(notificationAction.getWhen()); builder.setCategory(NotificationCompat.CATEGORY_EMAIL); final RemoteViews undoView = new RemoteViews(context.getPackageName(), R.layout.undo_notification); undoView.setTextViewText(R.id.description_text, context.getString(notificationAction.getActionTextResId())); final String packageName = context.getPackageName(); final Intent clickIntent = new Intent(NotificationActionIntentService.ACTION_UNDO); clickIntent.setPackage(packageName); clickIntent.setData(notificationAction.mConversation.uri); putNotificationActionExtra(clickIntent, notificationAction); final PendingIntent clickPendingIntent = PendingIntent.getService(context, notificationId, clickIntent, PendingIntent.FLAG_CANCEL_CURRENT); undoView.setOnClickPendingIntent(R.id.status_bar_latest_event_content, clickPendingIntent); builder.setContent(undoView);//w ww . j a v a 2s . co m // When the notification is cleared, we perform the destructive action final Intent deleteIntent = new Intent(NotificationActionIntentService.ACTION_DESTRUCT); deleteIntent.setPackage(packageName); deleteIntent.setData(notificationAction.mConversation.uri); putNotificationActionExtra(deleteIntent, notificationAction); final PendingIntent deletePendingIntent = PendingIntent.getService(context, notificationId, deleteIntent, PendingIntent.FLAG_CANCEL_CURRENT); builder.setDeleteIntent(deletePendingIntent); final Notification notification = builder.build(); return notification; }
From source file:com.prod.intelligent7.engineautostart.ConnectDaemonService.java
void startScheduleAlarm() { if (scheduleAlarm != null) { alarmManager.cancel(scheduleAlarm); //return; }/*from w w w . ja va2s . c o m*/ Intent jIntent = new Intent(this, ConnectDaemonService.class); //M1-00 (cool) or M1-01 (warm) jIntent.putExtra(ConnectDaemonService.ALARM_DONE, ALARM_DONE); scheduleAlarm = PendingIntent.getService(this, ++alarmRequestId, jIntent, PendingIntent.FLAG_ONE_SHOT); alarmManager.set(AlarmManager.RTC_WAKEUP, 1 * 60 * 60 * 1000 + System.currentTimeMillis(), scheduleAlarm); Log.i("ALARM_SET", "restart new alarm set for 1 hour"); startScheduledJobs(); }
From source file:com.googlecode.android_scripting.facade.AndroidFacade.java
@Rpc(description = "Displays a notification that will be canceled when the user clicks on it.") public void notify(@RpcParameter(name = "title", description = "title") String title, @RpcParameter(name = "message") String message) { Notification notification = new Notification(mResources.getLogo48(), message, System.currentTimeMillis()); // This contentIntent is a noop. PendingIntent contentIntent = PendingIntent.getService(mService, 0, new Intent(), 0); notification.setLatestEventInfo(mService, title, message, contentIntent); notification.flags = Notification.FLAG_AUTO_CANCEL; // Get a unique notification id from the application. final int notificationId = NotificationIdFactory.create(); mNotificationManager.notify(notificationId, notification); }