4 package org
.netxms
.ui
.android
.service
;
6 import java
.text
.DateFormat
;
7 import java
.util
.ArrayList
;
8 import java
.util
.Calendar
;
13 import org
.netxms
.api
.client
.SessionListener
;
14 import org
.netxms
.api
.client
.SessionNotification
;
15 import org
.netxms
.base
.Logger
;
16 import org
.netxms
.client
.NXCNotification
;
17 import org
.netxms
.client
.NXCSession
;
18 import org
.netxms
.client
.datacollection
.DciValue
;
19 import org
.netxms
.client
.events
.Alarm
;
20 import org
.netxms
.client
.objects
.GenericObject
;
21 import org
.netxms
.client
.objecttools
.ObjectTool
;
22 import org
.netxms
.ui
.android
.NXApplication
;
23 import org
.netxms
.ui
.android
.R
;
24 import org
.netxms
.ui
.android
.helpers
.SafeParser
;
25 import org
.netxms
.ui
.android
.main
.activities
.AlarmBrowser
;
26 import org
.netxms
.ui
.android
.main
.activities
.DashboardBrowser
;
27 import org
.netxms
.ui
.android
.main
.activities
.GraphBrowser
;
28 import org
.netxms
.ui
.android
.main
.activities
.HomeScreen
;
29 import org
.netxms
.ui
.android
.main
.activities
.NodeBrowser
;
30 import org
.netxms
.ui
.android
.receivers
.AlarmIntentReceiver
;
31 import org
.netxms
.ui
.android
.service
.helpers
.AndroidLoggingFacility
;
32 import org
.netxms
.ui
.android
.service
.tasks
.ConnectTask
;
33 import org
.netxms
.ui
.android
.service
.tasks
.ExecActionTask
;
35 import android
.app
.AlarmManager
;
36 import android
.app
.Notification
;
37 import android
.app
.NotificationManager
;
38 import android
.app
.PendingIntent
;
39 import android
.app
.Service
;
40 import android
.content
.BroadcastReceiver
;
41 import android
.content
.Context
;
42 import android
.content
.Intent
;
43 import android
.content
.IntentFilter
;
44 import android
.content
.SharedPreferences
;
45 import android
.content
.SharedPreferences
.Editor
;
46 import android
.content
.res
.Resources
;
47 import android
.media
.Ringtone
;
48 import android
.media
.RingtoneManager
;
49 import android
.net
.Uri
;
50 import android
.os
.Binder
;
51 import android
.os
.Handler
;
52 import android
.os
.IBinder
;
53 import android
.preference
.PreferenceManager
;
54 import android
.support
.v4
.app
.NotificationCompat
;
55 import android
.support
.v4
.content
.Loader
;
56 import android
.util
.Log
;
57 import android
.widget
.Toast
;
60 * Background communication service for NetXMS client.
62 * @author Victor Kirhenshtein
63 * @author Marco Incalcaterra (marco.incalcaterra@thinksoft.it)
67 public class ClientConnectorService
extends Service
implements SessionListener
69 public enum ConnectionStatus
71 CS_NOCONNECTION
, CS_INPROGRESS
, CS_ALREADYCONNECTED
, CS_CONNECTED
, CS_DISCONNECTED
, CS_ERROR
74 public static final String ACTION_CONNECT
= "org.netxms.ui.android.ACTION_CONNECT";
75 public static final String ACTION_FORCE_CONNECT
= "org.netxms.ui.android.ACTION_FORCE_CONNECT";
76 public static final String ACTION_DISCONNECT
= "org.netxms.ui.android.ACTION_DISCONNECT";
77 public static final String ACTION_FORCE_DISCONNECT
= "org.netxms.ui.android.ACTION_FORCE_DISCONNECT";
78 public static final String ACTION_RESCHEDULE
= "org.netxms.ui.android.ACTION_RESCHEDULE";
79 public static final String ACTION_CONFIGURE
= "org.netxms.ui.android.ACTION_CONFIGURE";
80 private static final String TAG
= "nxclient/ClientConnectorService";
81 private static final String LASTALARM_KEY
= "LastALarmIdNotified";
83 private static final int NOTIFY_ALARM
= 1;
84 private static final int NOTIFY_STATUS
= 2;
85 private static final int NOTIFY_STATUS_ON_CONNECT
= 1;
86 private static final int NOTIFY_STATUS_ON_DISCONNECT
= 2;
87 private static final int NOTIFY_STATUS_ALWAYS
= 3;
88 private static final int ONE_DAY_MINUTES
= 24 * 60;
89 private static final int NETXMS_REQUEST_CODE
= 123456;
91 private final String mutex
= "MUTEX";
92 private final Binder binder
= new ClientConnectorBinder();
93 private Handler uiThreadHandler
;
94 private NotificationManager notificationManager
;
95 private NXCSession session
= null;
96 private ConnectionStatus connectionStatus
= ConnectionStatus
.CS_DISCONNECTED
;
97 private String connectionStatusText
= "";
98 private int connectionStatusColor
= 0;
99 private Map
<Long
, Alarm
> alarms
= null;
100 private HomeScreen homeScreen
= null;
101 private AlarmBrowser alarmBrowser
= null;
102 private NodeBrowser nodeBrowser
= null;
103 private GraphBrowser graphBrowser
= null;
104 private Alarm unknownAlarm
= null;
105 private long lastAlarmIdNotified
;
106 private List
<ObjectTool
> objectTools
= null;
107 private BroadcastReceiver receiver
= null;
108 private DashboardBrowser dashboardBrowser
;
109 private SharedPreferences sp
;
110 private final List
<Loader
<Alarm
[]>> alarmLoaders
= new ArrayList
<Loader
<Alarm
[]>>(0);
111 private final List
<Loader
<DciValue
[]>> dciValueLoaders
= new ArrayList
<Loader
<DciValue
[]>>(0);
112 private final List
<Loader
<GenericObject
>> genericObjectLoaders
= new ArrayList
<Loader
<GenericObject
>>(0);
113 private final List
<Loader
<Set
<GenericObject
>>> genericObjectChildrenLoaders
= new ArrayList
<Loader
<Set
<GenericObject
>>>(0);
114 private String server
= "";
115 private int port
= 4701;
116 private String login
= "";
117 private String password
= "";
118 private boolean encrypt
= false;
119 private boolean enabled
= false;
120 private boolean notifyAlarm
= false;
121 private int notificationType
= 0;
122 private boolean notifyIcon
= false;
123 private boolean notifyToast
= false;
124 private int schedulerPostpone
= 0;
125 private int schedulerDuration
= 0;
126 private int schedulerInterval
= 0;
127 private boolean schedulerDailyEnabled
= false;
128 private int schedulerDailyOn
= 0;
129 private int schedulerDailyOff
= 0;
132 * Class for clients to access. Because we know this service always runs in
133 * the same process as its clients, we don't need to deal with IPC.
135 public class ClientConnectorBinder
extends Binder
137 public ClientConnectorService
getService()
139 return ClientConnectorService
.this;
146 * @see android.app.Service#onCreate()
149 public void onCreate()
153 Logger
.setLoggingFacility(new AndroidLoggingFacility());
154 uiThreadHandler
= new Handler(getMainLooper());
155 notificationManager
= (NotificationManager
)getSystemService(NOTIFICATION_SERVICE
);
157 showToast(getString(R
.string
.notify_started
));
159 sp
= PreferenceManager
.getDefaultSharedPreferences(this);
160 lastAlarmIdNotified
= sp
.getInt(LASTALARM_KEY
, 0);
163 receiver
= new BroadcastReceiver()
166 public void onReceive(Context context
, Intent intent
)
168 Intent i
= new Intent(context
, ClientConnectorService
.class);
169 i
.setAction(ACTION_RESCHEDULE
);
170 context
.startService(i
);
173 registerReceiver(receiver
, new IntentFilter(Intent
.ACTION_TIME_TICK
));
175 if (NXApplication
.isActivityVisible())
182 * @see android.app.Service#onStartCommand(android.content.Intent, int, int)
185 public int onStartCommand(Intent intent
, int flags
, int startId
)
187 if ((intent
!= null) && (intent
.getAction() != null))
188 if (intent
.getAction().equals(ACTION_CONNECT
))
190 else if (intent
.getAction().equals(ACTION_FORCE_CONNECT
))
192 else if (intent
.getAction().equals(ACTION_DISCONNECT
))
194 else if (intent
.getAction().equals(ACTION_FORCE_DISCONNECT
))
196 else if (intent
.getAction().equals(ACTION_RESCHEDULE
))
197 if (NXApplication
.isActivityVisible())
201 else if (intent
.getAction().equals(ACTION_CONFIGURE
))
202 reconnect(configure());
203 return super.onStartCommand(intent
, flags
, startId
);
209 * @see android.app.Service#onBind(android.content.Intent)
212 public IBinder
onBind(Intent intent
)
220 * @see android.app.Service#onDestroy()
223 public void onDestroy()
229 * Shutdown background service
231 public void shutdown()
234 clearNotifications();
236 unregisterReceiver(receiver
);
243 public void savePreferences()
245 SharedPreferences
.Editor editor
= sp
.edit();
246 editor
.putInt(LASTALARM_KEY
, (int)lastAlarmIdNotified
);
251 * Show alarm notification
253 * @param severity notification severity (used to determine icon and sound)
254 * @param text notification text
256 public void alarmNotification(int severity
, String text
)
260 Intent notifyIntent
= new Intent(getApplicationContext(), AlarmBrowser
.class);
261 PendingIntent intent
= PendingIntent
.getActivity(getApplicationContext(), 0, notifyIntent
, Intent
.FLAG_ACTIVITY_NEW_TASK
);
262 NotificationCompat
.Builder nb
= new NotificationCompat
.Builder(getApplicationContext())
263 .setSmallIcon(getAlarmIcon(severity
))
264 .setWhen(System
.currentTimeMillis())
265 .setDefaults(Notification
.DEFAULT_LIGHTS
)
266 .setContentText(text
)
267 .setContentTitle(getString(R
.string
.notification_title
))
268 .setContentIntent(intent
);
269 final String sound
= GetAlarmSound(severity
);
270 if ((sound
!= null) && (sound
.length() > 0))
271 nb
.setSound(Uri
.parse(sound
));
272 notificationManager
.notify(NOTIFY_ALARM
, nb
.build());
276 Ringtone r
= RingtoneManager
.getRingtone(getApplicationContext(), Uri
.parse(GetAlarmSound(severity
)));
282 * Show status notification
284 * @param status connection status
285 * @param extra extra text to add at the end of the toast
287 public void statusNotification(ConnectionStatus status
, String extra
)
294 if (notificationType
== NOTIFY_STATUS_ON_CONNECT
|| notificationType
== NOTIFY_STATUS_ALWAYS
)
296 icon
= R
.drawable
.ic_stat_connected
;
298 text
= getString(R
.string
.notify_connected
, extra
);
300 case CS_DISCONNECTED
:
301 if (notificationType
== NOTIFY_STATUS_ON_DISCONNECT
|| notificationType
== NOTIFY_STATUS_ALWAYS
)
303 icon
= R
.drawable
.ic_stat_disconnected
;
305 text
= getString(R
.string
.notify_disconnected
) + getNextConnectionRetry();
308 if (notificationType
== NOTIFY_STATUS_ON_DISCONNECT
|| notificationType
== NOTIFY_STATUS_ALWAYS
)
310 icon
= R
.drawable
.ic_stat_disconnected
;
312 text
= getString(R
.string
.notify_connection_failed
, extra
);
314 case CS_NOCONNECTION
:
316 case CS_ALREADYCONNECTED
:
321 hideNotification(NOTIFY_STATUS
);
328 Intent notifyIntent
= new Intent(getApplicationContext(), HomeScreen
.class);
329 PendingIntent intent
= PendingIntent
.getActivity(getApplicationContext(), 0, notifyIntent
, Intent
.FLAG_ACTIVITY_NEW_TASK
);
330 NotificationCompat
.Builder nb
= new NotificationCompat
.Builder(getApplicationContext())
332 .setWhen(System
.currentTimeMillis())
333 .setAutoCancel(false)
334 .setOnlyAlertOnce(true)
336 .setContentText(text
)
337 .setContentTitle(getString(R
.string
.notification_title
))
338 .setContentIntent(intent
);
339 notificationManager
.notify(NOTIFY_STATUS
, nb
.build());
350 private void hideNotification(int id
)
352 notificationManager
.cancel(id
);
356 * Clear all notifications
358 public void clearNotifications()
360 notificationManager
.cancelAll();
364 * Configure service, notify callers if it is necessary to reconnect
365 * depending if a particular subset of parameters have been changed.
367 * @return true If it is necessary to force a reconnection
369 private boolean configure()
371 boolean needsToReconnect
= enabled
!= sp
.getBoolean("global.scheduler.enable", false) ||
372 server
!= sp
.getString("connection.server", "") ||
373 port
!= SafeParser
.parseInt(sp
.getString("connection.port", "4701"), 4701) ||
374 login
!= sp
.getString("connection.login", "") ||
375 password
!= sp
.getString("connection.password", "") ||
376 encrypt
!= sp
.getBoolean("connection.encrypt", false) ||
377 notifyAlarm
!= sp
.getBoolean("global.notification.alarm", true) ||
378 notificationType
!= Integer
.parseInt(sp
.getString("global.notification.status", "0")) ||
379 notifyIcon
!= sp
.getBoolean("global.notification.icon", false) ||
380 notifyToast
!= sp
.getBoolean("global.notification.toast", true) ||
381 schedulerPostpone
!= Integer
.parseInt(sp
.getString("global.scheduler.postpone", "1")) ||
382 schedulerDuration
!= Integer
.parseInt(sp
.getString("global.scheduler.duration", "1")) ||
383 schedulerInterval
!= Integer
.parseInt(sp
.getString("global.scheduler.interval", "15")) ||
384 schedulerDailyEnabled
!= sp
.getBoolean("global.scheduler.daily.enable", false) ||
385 schedulerDailyOn
!= getMinutes("global.scheduler.daily.on") ||
386 schedulerDailyOff
!= getMinutes("global.scheduler.daily.off");
388 enabled
= sp
.getBoolean("global.scheduler.enable", false);
389 server
= sp
.getString("connection.server", "");
390 port
= SafeParser
.parseInt(sp
.getString("connection.port", "4701"), 4701);
391 login
= sp
.getString("connection.login", "");
392 password
= sp
.getString("connection.password", "");
393 encrypt
= sp
.getBoolean("connection.encrypt", false);
394 notifyAlarm
= sp
.getBoolean("global.notification.alarm", true);
395 notificationType
= Integer
.parseInt(sp
.getString("global.notification.status", "0"));
396 notifyIcon
= sp
.getBoolean("global.notification.icon", false);
397 notifyToast
= sp
.getBoolean("global.notification.toast", true);
398 schedulerPostpone
= Integer
.parseInt(sp
.getString("global.scheduler.postpone", "1"));
399 schedulerDuration
= Integer
.parseInt(sp
.getString("global.scheduler.duration", "1"));
400 schedulerInterval
= Integer
.parseInt(sp
.getString("global.scheduler.interval", "15"));
401 schedulerDailyEnabled
= sp
.getBoolean("global.scheduler.daily.enable", false);
402 schedulerDailyOn
= getMinutes("global.scheduler.daily.on");
403 schedulerDailyOff
= getMinutes("global.scheduler.daily.off");
405 return needsToReconnect
;
409 * Reconnect to server.
411 * @param forceReconnect if set to true forces disconnection before connecting
413 public void reconnect(boolean force
)
415 if (force
|| (isScheduleExpired() || NXApplication
.isActivityVisible()) &&
416 connectionStatus
!= ConnectionStatus
.CS_CONNECTED
&&
417 connectionStatus
!= ConnectionStatus
.CS_ALREADYCONNECTED
)
419 Log
.i(TAG
, "Reconnecting...");
422 if (connectionStatus
!= ConnectionStatus
.CS_INPROGRESS
)
424 setConnectionStatus(ConnectionStatus
.CS_INPROGRESS
, "");
425 statusNotification(ConnectionStatus
.CS_INPROGRESS
, "");
426 new ConnectTask(this).execute(server
, port
, login
, password
, encrypt
, force
);
433 * Disconnect from server. Only when scheduler is enabled and connected.
436 public void disconnect(boolean force
)
438 if (force
|| enabled
&& !NXApplication
.isActivityVisible() &&
439 (connectionStatus
== ConnectionStatus
.CS_CONNECTED
||
440 connectionStatus
== ConnectionStatus
.CS_ALREADYCONNECTED
))
442 Log
.i(TAG
, "Disconnecting...");
444 setConnectionStatus(ConnectionStatus
.CS_DISCONNECTED
, "");
445 statusNotification(ConnectionStatus
.CS_DISCONNECTED
, "");
450 * Called by connect task after successful connection
455 public void onConnect(NXCSession session
, Map
<Long
, Alarm
> alarms
)
461 schedule(ACTION_DISCONNECT
);
462 this.session
= session
;
463 this.alarms
= alarms
;
464 session
.addListener(this);
465 setConnectionStatus(ConnectionStatus
.CS_CONNECTED
, session
.getServerAddress());
466 statusNotification(ConnectionStatus
.CS_CONNECTED
, session
.getServerAddress());
471 // Find the newest alarm received when we were offline
472 for (Alarm itAlarm
: alarms
.values())
473 if (itAlarm
.getId() > id
)
476 id
= itAlarm
.getId();
478 if (alarm
!= null && alarm
.getId() > lastAlarmIdNotified
)
479 processAlarmChange(alarm
);
486 * Called by connect task or session notification listener after unsuccessful
487 * connection or disconnect
489 public void onDisconnect()
491 schedule(ACTION_CONNECT
);
493 setConnectionStatus(ConnectionStatus
.CS_DISCONNECTED
, "");
494 statusNotification(ConnectionStatus
.CS_DISCONNECTED
, "");
498 * Called by connect task on error during connection
500 public void onError(String error
)
503 setConnectionStatus(ConnectionStatus
.CS_ERROR
, error
);
504 statusNotification(ConnectionStatus
.CS_ERROR
, error
);
508 * Check for expired pending connection schedule
510 private boolean isScheduleExpired()
514 Calendar cal
= Calendar
.getInstance(); // get a Calendar object with current time
515 return cal
.getTimeInMillis() > sp
.getLong("global.scheduler.next_activation", 0);
521 * Gets stored time settings in minutes
523 private int getMinutes(String time
)
525 String
[] vals
= sp
.getString(time
, "00:00").split(":");
526 return Integer
.parseInt(vals
[0]) * 60 + Integer
.parseInt(vals
[1]);
530 * Sets the offset used to compute the next schedule
532 private void setDayOffset(Calendar cal
, int minutes
)
534 cal
.set(Calendar
.HOUR_OF_DAY
, 0);
535 cal
.set(Calendar
.MINUTE
, 0);
536 cal
.set(Calendar
.SECOND
, 0);
537 cal
.set(Calendar
.MILLISECOND
, 0);
538 cal
.add(Calendar
.MINUTE
, minutes
);
542 * Schedule a new connection/disconnection
544 public void schedule(String action
)
546 Log
.i(TAG
, "Schedule: " + action
);
551 Calendar cal
= Calendar
.getInstance(); // get a Calendar object with current time
552 if (action
== ACTION_RESCHEDULE
)
553 cal
.add(Calendar
.MINUTE
, schedulerPostpone
);
554 if (action
== ACTION_DISCONNECT
)
555 cal
.add(Calendar
.MINUTE
, schedulerDuration
);
556 else if (!schedulerDailyEnabled
)
557 cal
.add(Calendar
.MINUTE
, schedulerInterval
);
560 int on
= schedulerDailyOn
;
561 int off
= schedulerDailyOff
;
563 off
+= ONE_DAY_MINUTES
; // Next day!
564 Calendar calOn
= (Calendar
)cal
.clone();
565 setDayOffset(calOn
, on
);
566 Calendar calOff
= (Calendar
)cal
.clone();
567 setDayOffset(calOff
, off
);
568 cal
.add(Calendar
.MINUTE
, schedulerInterval
);
569 if (cal
.before(calOn
))
571 cal
= (Calendar
)calOn
.clone();
572 Log
.i(TAG
, "schedule (before): rescheduled for daily interval");
574 else if (cal
.after(calOff
))
576 cal
= (Calendar
)calOn
.clone();
577 setDayOffset(cal
, on
+ ONE_DAY_MINUTES
); // Move to the next activation of the excluded range
578 Log
.i(TAG
, "schedule (after): rescheduled for daily interval");
581 setSchedule(cal
.getTimeInMillis(), action
);
586 * Set a connection schedule
588 private void setSchedule(long milliseconds
, String action
)
590 Intent intent
= new Intent(this, AlarmIntentReceiver
.class);
591 intent
.putExtra("action", action
);
592 PendingIntent sender
= PendingIntent
.getBroadcast(this, NETXMS_REQUEST_CODE
, intent
, PendingIntent
.FLAG_UPDATE_CURRENT
);
593 ((AlarmManager
)getSystemService(ALARM_SERVICE
)).set(AlarmManager
.RTC_WAKEUP
, milliseconds
, sender
);
595 long last
= sp
.getLong("global.scheduler.next_activation", 0);
596 Editor e
= sp
.edit();
597 e
.putLong("global.scheduler.last_activation", last
);
598 e
.putLong("global.scheduler.next_activation", milliseconds
);
603 * Cancel a pending connection schedule (if any)
605 public void cancelSchedule()
607 Intent intent
= new Intent(this, AlarmIntentReceiver
.class);
608 PendingIntent sender
= PendingIntent
.getBroadcast(this, NETXMS_REQUEST_CODE
, intent
, PendingIntent
.FLAG_UPDATE_CURRENT
);
609 ((AlarmManager
)getSystemService(ALARM_SERVICE
)).cancel(sender
);
610 if (sp
.getLong("global.scheduler.next_activation", 0) != 0)
612 Editor e
= sp
.edit();
613 e
.putLong("global.scheduler.next_activation", 0);
619 * Release internal resources nullifying current session (if any)
621 private void nullifySession()
627 session
.disconnect();
628 session
.removeListener(this);
637 * Process alarm change
641 private void processAlarmChange(Alarm alarm
)
643 GenericObject object
= findObjectById(alarm
.getSourceObjectId());
648 lastAlarmIdNotified
= alarm
.getId();
649 alarms
.put(lastAlarmIdNotified
, alarm
);
651 unknownAlarm
= object
== null ? alarm
: null;
652 alarmNotification(alarm
.getCurrentSeverity(), ((object
!= null) ? object
.getObjectName() : getString(R
.string
.node_unknown
)) + ": " + alarm
.getMessage());
653 refreshAlarmBrowser();
658 * Process alarm change
662 private void processAlarmDelete(long id
)
668 if (lastAlarmIdNotified
== id
)
669 hideNotification(NOTIFY_ALARM
);
670 refreshAlarmBrowser();
675 * Synchronize information about specific object in background
677 * @param objectId object ID
679 private void doBackgroundObjectSync(final long objectId
)
681 new Thread("Background object sync")
688 session
.syncObjectSet(new long[] { objectId
}, false, NXCSession
.OBJECT_SYNC_NOTIFY
);
692 Log
.d(TAG
, "Exception in doBackgroundObjectSync", e
);
702 public GenericObject
findObjectById(long objectId
)
704 return findObjectById(objectId
, GenericObject
.class);
708 * Find object by ID with class filter
714 public GenericObject
findObjectById(long objectId
, Class
<?
extends GenericObject
> classFilter
)
716 // we can't search without active session
720 GenericObject object
= session
.findObjectById(objectId
, classFilter
);
721 // if we don't have object - probably we never synced it
722 // request object synchronization in that case
725 doBackgroundObjectSync(objectId
);
733 private void processObjectUpdate(GenericObject object
)
737 if (unknownAlarm
!= null && unknownAlarm
.getSourceObjectId() == object
.getObjectId()) // Update <Unknown> notification
739 alarmNotification(unknownAlarm
.getCurrentSeverity(), object
.getObjectName() + ": " + unknownAlarm
.getMessage());
743 refreshAlarmBrowser();
744 refreshNodeBrowser();
745 refreshDashboardBrowser();
750 * Refresh homescreen activity
752 private void refreshHomeScreen()
754 if (homeScreen
!= null)
756 homeScreen
.runOnUiThread(new Runnable()
761 homeScreen
.refreshActivityStatus();
768 * Refresh the alarms related activities
770 private void refreshAlarmBrowser()
772 if (alarmBrowser
!= null)
774 alarmBrowser
.runOnUiThread(new Runnable()
779 alarmBrowser
.refreshList();
783 if (homeScreen
!= null)
785 homeScreen
.runOnUiThread(new Runnable()
790 homeScreen
.refreshPendingAlarms();
794 for (Loader
<Alarm
[]> l
: alarmLoaders
)
799 * Refresh the node browser activity
801 private void refreshNodeBrowser()
803 if (nodeBrowser
!= null)
805 nodeBrowser
.runOnUiThread(new Runnable()
810 nodeBrowser
.refreshList();
814 for (Loader
<DciValue
[]> l
: dciValueLoaders
)
816 for (Loader
<GenericObject
> l
: genericObjectLoaders
)
818 for (Loader
<Set
<GenericObject
>> l
: genericObjectChildrenLoaders
)
822 * Refresh dashboard browser activity
824 private void refreshDashboardBrowser()
826 if (dashboardBrowser
!= null)
828 dashboardBrowser
.runOnUiThread(new Runnable()
833 dashboardBrowser
.refreshList();
840 * Process graph update event
842 private void processGraphUpdate()
846 if (this.graphBrowser
!= null)
848 graphBrowser
.runOnUiThread(new Runnable()
853 graphBrowser
.refreshList();
861 * Get alarm sound based on alarm severity
865 private String
GetAlarmSound(int severity
)
870 return sp
.getString("alarm.sound.normal", "");
872 return sp
.getString("alarm.sound.warning", "");
874 return sp
.getString("alarm.sound.minor", "");
876 return sp
.getString("alarm.sound.major", "");
878 return sp
.getString("alarm.sound.critical", "");
884 * Get alarm icon based on alarm severity
888 private int getAlarmIcon(int severity
)
893 return R
.drawable
.status_normal
;
895 return R
.drawable
.status_warning
;
897 return R
.drawable
.status_minor
;
899 return R
.drawable
.status_major
;
901 return R
.drawable
.status_critical
;
903 return android
.R
.drawable
.stat_notify_sdcard
;
910 * org.netxms.api.client.SessionListener#notificationHandler(org.netxms.api
911 * .client.SessionNotification)
914 public void notificationHandler(SessionNotification n
)
918 case SessionNotification
.CONNECTION_BROKEN
:
919 case SessionNotification
.SERVER_SHUTDOWN
:
922 case NXCNotification
.NEW_ALARM
:
923 case NXCNotification
.ALARM_CHANGED
:
924 processAlarmChange((Alarm
)n
.getObject());
926 case NXCNotification
.ALARM_DELETED
:
927 case NXCNotification
.ALARM_TERMINATED
:
928 processAlarmDelete(((Alarm
)n
.getObject()).getId());
930 case NXCNotification
.OBJECT_CHANGED
:
931 case NXCNotification
.OBJECT_SYNC_COMPLETED
:
932 processObjectUpdate((GenericObject
)n
.getObject());
934 case NXCNotification
.PREDEFINED_GRAPHS_CHANGED
:
935 processGraphUpdate();
943 * Get list of active alarms
945 * @return list of active alarms
947 public Alarm
[] getAlarms()
953 a
= alarms
.values().toArray(new Alarm
[alarms
.size()]);
963 public void acknowledgeAlarm(ArrayList
<Long
> ids
, boolean sticky
)
967 for (int i
= 0; i
< ids
.size(); i
++)
968 session
.acknowledgeAlarm(ids
.get(i
).longValue(), sticky
);
972 Log
.d(TAG
, "Exception while executing session.acknowledgeAlarm", e
);
979 public void resolveAlarm(ArrayList
<Long
> ids
)
983 for (int i
= 0; i
< ids
.size(); i
++)
984 session
.resolveAlarm(ids
.get(i
).longValue());
988 Log
.d(TAG
, "Exception while executing session.resolveAlarm", e
);
995 public void terminateAlarm(ArrayList
<Long
> ids
)
999 for (int i
= 0; i
< ids
.size(); i
++)
1000 session
.terminateAlarm(ids
.get(i
).longValue());
1004 Log
.d(TAG
, "Exception while executing session.terminateAlarm", e
);
1012 public void setObjectMgmtState(long id
, boolean state
)
1016 session
.setObjectManaged(id
, state
);
1020 Log
.d(TAG
, "Exception while executing session.setObjectManaged", e
);
1027 public void loadTools()
1031 this.objectTools
= session
.getObjectTools();
1035 this.objectTools
= null;
1036 Log
.d(TAG
, "Exception while executing session.getObjectTools", e
);
1041 * Execute agent action. Communication with server will be done in separate worker thread.
1046 public void executeAction(long objectId
, String action
)
1048 new ExecActionTask().execute(new Object
[] { session
, objectId
, action
, this });
1054 public List
<ObjectTool
> getTools()
1056 return this.objectTools
;
1062 public void registerHomeScreen(HomeScreen homeScreen
)
1064 this.homeScreen
= homeScreen
;
1070 public void registerAlarmBrowser(AlarmBrowser browser
)
1072 alarmBrowser
= browser
;
1078 public void registerNodeBrowser(NodeBrowser browser
)
1080 nodeBrowser
= browser
;
1086 public void registerGraphBrowser(GraphBrowser browser
)
1088 graphBrowser
= browser
;
1094 public void registerDashboardBrowser(DashboardBrowser browser
)
1096 dashboardBrowser
= browser
;
1099 public void registerAlarmLoader(Loader
<Alarm
[]> loader
)
1101 if (!alarmLoaders
.contains(this))
1102 alarmLoaders
.add(loader
);
1105 public void unregisterAlarmLoader(Loader
<Alarm
[]> loader
)
1107 alarmLoaders
.remove(loader
);
1110 public void registerDciValueLoader(Loader
<DciValue
[]> loader
)
1112 if (!dciValueLoaders
.contains(this))
1113 dciValueLoaders
.add(loader
);
1116 public void unregisterDciValueLoader(Loader
<DciValue
[]> loader
)
1118 dciValueLoaders
.remove(loader
);
1121 public void registerGenericObjectLoader(Loader
<GenericObject
> loader
)
1123 if (!genericObjectLoaders
.contains(this))
1124 genericObjectLoaders
.add(loader
);
1127 public void unregisterGenericObjectLoader(Loader
<GenericObject
> loader
)
1129 genericObjectLoaders
.remove(loader
);
1132 public void registerGenericObjectChildrenLoader(Loader
<Set
<GenericObject
>> loader
)
1134 if (!genericObjectChildrenLoaders
.contains(this))
1135 genericObjectChildrenLoaders
.add(loader
);
1138 public void unregisterGenericObjectChildrenLoader(Loader
<Set
<GenericObject
>> loader
)
1140 genericObjectChildrenLoaders
.remove(loader
);
1144 * @return the connectionStatus
1146 public ConnectionStatus
getConnectionStatus()
1148 return connectionStatus
;
1152 * @return the connectionStatusText
1154 public String
getConnectionStatusText()
1156 return connectionStatusText
;
1160 * @return the connectionStatusColor
1162 public int getConnectionStatusColor()
1164 return connectionStatusColor
;
1168 * @param connectionStatus
1169 * the connectionStatus to set
1171 public void setConnectionStatus(ConnectionStatus connectionStatus
, String extra
)
1173 Resources r
= getResources();
1174 this.connectionStatus
= connectionStatus
;
1175 switch (connectionStatus
)
1177 case CS_NOCONNECTION
:
1178 connectionStatusText
= getString(R
.string
.notify_no_connection
);
1179 connectionStatusColor
= r
.getColor(R
.color
.notify_no_connection
);
1182 connectionStatusText
= getString(R
.string
.notify_connecting
);
1183 connectionStatusColor
= r
.getColor(R
.color
.notify_connecting
);
1185 case CS_ALREADYCONNECTED
:
1186 connectionStatusText
= getString(R
.string
.notify_connected
, extra
);
1187 connectionStatusColor
= r
.getColor(R
.color
.notify_connected
);
1190 connectionStatusText
= getString(R
.string
.notify_connected
, extra
);
1191 connectionStatusColor
= r
.getColor(R
.color
.notify_connected
);
1193 case CS_DISCONNECTED
:
1194 connectionStatusText
= getString(R
.string
.notify_disconnected
) + getNextConnectionRetry();
1195 connectionStatusColor
= r
.getColor(R
.color
.notify_disconnected
);
1198 connectionStatusText
= getString(R
.string
.notify_connection_failed
, extra
);
1199 connectionStatusColor
= r
.getColor(R
.color
.notify_connection_failed
);
1204 if (homeScreen
!= null)
1206 homeScreen
.runOnUiThread(new Runnable()
1211 homeScreen
.setStatusText(connectionStatusText
, connectionStatusColor
);
1212 homeScreen
.refreshActivityStatus();
1218 public String
getNextConnectionRetry()
1220 long next
= sp
.getLong("global.scheduler.next_activation", 0);
1223 Calendar cal
= Calendar
.getInstance(); // get a Calendar object with current time
1224 if (cal
.getTimeInMillis() < next
)
1226 cal
.setTimeInMillis(next
);
1227 return " " + getString(R
.string
.notify_next_connection_schedule
, DateFormat
.getDateTimeInstance().format(cal
));
1234 * @return the session
1236 public NXCSession
getSession()
1242 * Show toast with given text
1244 * @param text message text
1246 public void showToast(final String text
)
1248 uiThreadHandler
.post(new Runnable()
1253 Toast
.makeText(getApplicationContext(), text
, Toast
.LENGTH_SHORT
).show();