java - 检测桌面应用程序中的用户不活动

标签 java eclipse-rcp

我在 Eclipse RCP 中有一个应用程序,如果用户让他/她的应用程序空闲五分钟,我想在其中触发一个名为“LogOutUser()”的函数。

我该怎么做?

最佳答案

我不知道RCP框架内部是否支持这个。但是,我编写了自己的“助手”类,它是一个单例客户端 session 管理器。 Eclipse 本身并不知道您如何连接到数据源。就我而言,我使用 EJB3 调用进行连接并监听 JMS 队列和主题。

我编写的类是为了检测数据源或“服务器”何时出现故障。当服务器出现时,它也会重新连接。服务器不活动是通过监听服务器发送的心跳 DTO 来检测的。此反馈对于呈现给用户很有用。我已调整此类以适应用户界面不活动的情况。

类(class)很简单。它是一个单例,因此可以在您的客户端 RCP 应用程序中的任何时候简单地调用它。心跳使用观察器,因此您必须添加一个 HeartBeatEventListener 来 Hook 此功能。您可以调整该类以针对用户界面不活动执行相同的操作。但是,我刚刚提供了一个 updateUserInterfaceActivity() 方法,您必须在有用户 Activity 时调用该方法。也许这可以连接到一个全局鼠标和一个全局键盘事件处理程序。

我还添加了一个 TrayItem 来更新用户...

这是类:

package com.kingsleywebb.clientsessionmanagement;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolTip;
import org.eclipse.swt.widgets.TrayItem;

import com.kingsleywebb.clientsessionmanagement.entity.HeartbeatDTO;

public class ClientSessionManagement implements HeartbeatEventListener {

    private static final Image IMG_CONNECTED = null;  // Set this to a "connected image"
    private static final Image IMG_DISCONNECTED = null;  // Set this to a "disconnected image"

    private static final long CONNECTION_INACTIVITY_TIME_MS = 30000L; // 30 seconds
    private static final long USER_INTERFACE_INACTIVITY_TIME_MS = 300000L; // 5 minutes

    private static final Log LOG = LogFactory.getLog(ClientSessionManagement.class);
    private static ClientSessionManagement theInstance = null;
    private static long connectionTimestamp = 0;
    private static long userInterfaceActivityTimestamp = 0;

    private synchronized static void createInstance() {
        if (theInstance == null) {
            theInstance = new ClientSessionManagement();
        }
    }

    public static ClientSessionManagement getInstance() {
        if (theInstance == null) {
            createInstance();
        }
        return theInstance;
    }

    private ClientSessionManagement() {

        this.connectionListenerList = new ArrayList<ConnectionListener>();

        updateConnectionTimestamp();

        Cron cron = new Cron();
        Thread cronThread = new Thread(cron);       
        cronThread.start();
    }

    private boolean connected = true;

    private ToolTip toolTipConnected;
    private ToolTip toolTipDisconnected;
    private TrayItem trayItem = null;
    private String appName = null;
    private String version = null;
    private String whiteLabel = null;
    private String userName = null;
    private String deskName = null;
    private String serverName = null;
    private String userMnemonic = null;
    private MenuItem miShowPopups;
    private MenuItem miSoundBeep;

    private List<ConnectionListener> connectionListenerList;

    private void updateConnectionTimestamp() {
        ClientSessionManagement.connectionTimestamp = System.currentTimeMillis();
    }

    private synchronized long getLastHeartbeatInMsAgo() {
        return System.currentTimeMillis() - ClientSessionManagement.connectionTimestamp;
    }

    public synchronized void updateHeartbeat() {
        updateConnectionTimestamp();        
    }

    public synchronized void checkHeartbeatInterval() {
        if (getLastHeartbeatInMsAgo() < CONNECTION_INACTIVITY_TIME_MS) {
            showConnected();
        }
        else {
            showDisconnected();
        }
    }

    private void updateUserInterfaceActivityTimestamp() {
        ClientSessionManagement.userInterfaceActivityTimestamp = System.currentTimeMillis();
    }

    private synchronized long getLastUserInterfaceActivityInMsAgo() {
        return System.currentTimeMillis() - ClientSessionManagement.userInterfaceActivityTimestamp;
    }

    public synchronized void updateUserInterfaceActivity() {
        updateUserInterfaceActivityTimestamp();
    }

    public synchronized void checkUserInterfaceActivityInterval() {
        if (getLastUserInterfaceActivityInMsAgo() > USER_INTERFACE_INACTIVITY_TIME_MS) {
            logoutUser();
        }
    }

    private void logoutUser() {
        // Implement logout functionality here      
    }

    private void showConnected() {
        if (!connected) {
            connected = true;

            Display.getDefault().asyncExec(new Runnable() {
                public void run() {
                    // Update icon
                    if (trayItem != null) {
                        trayItem.setImage(ClientSessionManagement.IMG_CONNECTED);
                        trayItem.getToolTip().setVisible(false);
                        trayItem.setToolTip(toolTipConnected);                      
                        trayItem.getToolTip().setVisible(true);
                    }

                    // Update hover tooltip
                    updateHoverTooltip();
                }               
            });

            notifyConnectionListeners();            
        }
    }

    private void showDisconnected() {
        if (connected) {
            connected = false;

            Display.getDefault().asyncExec(new Runnable() {
                public void run() {

                    // Update icon
                    if (trayItem != null) {
                        trayItem.setImage(ClientSessionManagement.IMG_DISCONNECTED);
                        trayItem.getToolTip().setVisible(false);
                        trayItem.setToolTip(toolTipDisconnected);
                        trayItem.getToolTip().setVisible(true);
                    }

                    // Update hover tooltip
                    updateHoverTooltip();                   
                }               
            });

            notifyConnectionListeners();
        }
    }

    private void updateHoverTooltip() {
        if (trayItem != null) {

            // Application info
            String applicationInfo = null;
            if (appName != null && version != null && whiteLabel != null) {
                // appName* | version | whitelabel
                applicationInfo =  "  Application: " + "  " + appName + " " + version + " [" + whiteLabel + "]\r\n";
            }           

            // User info
            String userInfo = null;
            if (userName != null && deskName != null && serverName != null) {
                userInfo = "  User: " + "  " + userName + " (" + deskName + ") on " + serverName + "\r\n";              
            }

            // Connection info
            String connectionInfo = connected ? "  Server Connected" : "  SERVER DISCONNECTED!!!";

            String status = connectionInfo + "\r\n\r\n" + (applicationInfo != null ? applicationInfo : "") +
                (userInfo != null ? userInfo : "");

            trayItem.setToolTipText(status);
            LOG.info(status);
        }
    }

    public void setTrayItem(Shell shell, TrayItem trayItem) {
        this.trayItem = trayItem;

        /* 
         * Property files to persist these settings - removed for simplicity
         * 
         * final WorkstationProperties p = WorkstationProperties.getInstance();
         * boolean showNotificationPopups = !"No".equalsIgnoreCase(p.getProperty("notifications.showNotificationPopups"));
         * boolean soundNotificationBeep = !"No".equalsIgnoreCase(p.getProperty("notifications.soundNotificationBeep"));        
         */

        boolean showNotificationPopups = true;
        boolean soundNotificationBeep = true;

        final Menu menu = new Menu (shell, SWT.POP_UP);
        miShowPopups = new MenuItem (menu, SWT.CHECK);
        miShowPopups.setSelection(showNotificationPopups);
        miShowPopups.setText("Show Notification Popups");
        miShowPopups.addListener (SWT.Selection, new Listener () {
            public void handleEvent (Event event) {
                LOG.info("notifications.showNotificationPopups = " + miShowPopups.getSelection());
                // Property files to persist these settings - removed for simplicity        
                //p.setProperty("notifications.showNotificationPopups", miShowPopups.getSelection() ? "Yes" : "No");
            }
        });

        miSoundBeep = new MenuItem (menu, SWT.CHECK);
        miSoundBeep.setSelection(soundNotificationBeep);
        miSoundBeep.setText("Play Notification Beep");
        miSoundBeep.addListener (SWT.Selection, new Listener () {
            public void handleEvent (Event event) {
                LOG.info("notifications.soundNotificationBeep = " + miSoundBeep.getSelection());
                // Property files to persist these settings - removed for simplicity    
                //p.setProperty("notifications.soundNotificationBeep", miSoundBeep.getSelection() ? "Yes" : "No");
            }
        });

        this.trayItem.addListener (SWT.MenuDetect, new Listener () {
            public void handleEvent (Event event) {
                menu.setVisible (true);
            }
        });

        toolTipConnected = new ToolTip(shell, SWT.BALLOON);
        toolTipConnected.setText((appName != null ? appName : "<Application Name>") + " Status");
        toolTipConnected.setMessage("Connected to server.");
        toolTipConnected.setLocation(600, 600);
        toolTipConnected.setVisible(false);

        toolTipDisconnected = new ToolTip(shell, SWT.ICON_WARNING);
        toolTipDisconnected.setText((appName != null ? appName : "<Application Name>") + " Status");
        toolTipDisconnected.setMessage("DISCONNECTED from server.");
        toolTipDisconnected.setLocation(500, 500);
        toolTipDisconnected.setVisible(false);

        this.trayItem.setToolTip(toolTipConnected);
    }

    public boolean isShowPopups() {
        return miShowPopups.getSelection();
    }

    public boolean isSoundBeep() {
        return miSoundBeep.getSelection();
    }

    public void setAppName(String appName) {
        this.appName = appName;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public void setWhiteLabel(String whiteLabel) {
        this.whiteLabel = whiteLabel;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public void setDeskName(String deskName) {
        this.deskName = deskName;
    }

    public void setServerName(String serverName) {
        this.serverName = serverName;
        updateHoverTooltip();
    }

    public String getUserMnemonic() {
        return userMnemonic;
    }

    public void setUserMnemonic(String userMnemonic) {
        this.userMnemonic = userMnemonic;
    }

    public void heartbeatArrived(HeartbeatDTO heartbeatDTO) {               
        updateHeartbeat();          
    }

    public boolean isConnected() {
        return connected;
    }

    public boolean addConnectionListener(ConnectionListener connectionListener) {
        return connectionListenerList.add(connectionListener);
    }

    public boolean removeConnectionListener(ConnectionListener connectionListener) {
        return connectionListenerList.remove(connectionListener);
    }

    public void notifyConnectionListeners() {
        for (Iterator<ConnectionListener> i = connectionListenerList.iterator(); i.hasNext();) {
            ConnectionListener connectionListener = i.next();
            if (connected) {
                connectionListener.connected();
            }
            else {
                connectionListener.disconnected();
            }
        }
    }

    /**
     * 
     * @author Kingsley Webb
     *
     * Check heartbeat interval periodically display warning to user accordingly.
     */
    class Cron implements Runnable {

        public void run() {

            // Wait 15s extra before 1st check
            try {
                Thread.sleep(15000);
            } catch (InterruptedException e) {
                LOG.error(e);
            }

            while (true) {
                // Check every 5s - increase for better performance, but you get the idea...
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    LOG.error(e);
                }           

                checkHeartbeatInterval();
                checkUserInterfaceActivityInterval();
            }           
        }

    }

}

一些其他的支持类:

package com.kingsleywebb.clientsessionmanagement;

public interface ConnectionListener {

    public void connected();
    public void disconnected();

}

package com.kingsleywebb.clientsessionmanagement;

import com.kingsleywebb.clientsessionmanagement.entity.HeartbeatDTO;

public interface HeartbeatEventListener {

     public void heartbeatArrived(HeartbeatDTO heartbeatDTO);

}

关于java - 检测桌面应用程序中的用户不活动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9425322/

相关文章:

java - Spring RestTemplate jackson 获取特定字段

java - JAVA计算short类型数组的平均值

Java 子字符串匹配失败

java - 如何在 Eclipse RCP 中的 View 之间进行通信?

java - 等待使用 Display::asyncExec() 提交到 SWT UI 线程的所有 Runnable 完成

java - 从 Java 方法返回多个变量

java - 对 Java 中的泛型感到困惑

java - eclipse RCP java.lang.ClassNotFoundException : org. eclipse.core.runtime.adaptor.EclipseStarter

Eclipse RCP 定义一种新的项目

java - 如何将 Swing 组件添加到 SWT 中?