简体   繁体   中英

How to get the GUI activity of an application using Java

Is there a way to track the gui idleness and activity of a given application in Java. I have done this using C# referring this tutorial: http://www.codeproject.com/Articles/13756/Detecting-Application-Idleness How do I do it in Java?

If you can modify the application you can install your own EventQueue - http://docs.oracle.com/javase/7/docs/api/java/awt/EventQueue.html#push(java.awt.EventQueue) - processing UI events and paint requests. If changing the application is not possible you can still do similar thing with JVMTI ( http://docs.oracle.com/javase/7/docs/technotes/guides/jvmti/ ). The implementation will be a bit more difficult.

This answer applied to Windows.

Here are a few snippets that should get you started. This code is for example only and is not complete. The complete solution is lengthy.

Jump from Java to the native side and make a call to CallNtPowerInformation() requesting SystemPowerInformation. Pass the results up to the Java side.

    ntStatus = CallNtPowerInformation(SystemPowerInformation, lpInputBuffer, nInputBufferSize, &systemPowerInformation, systemPowerInformationSize);
    success = ntStatus == STATUS_SUCCESS;
    if (success == FALSE) {
        logErrorMessage(thisFunctionName, ntStatus);
    } else {
        SYSTEM_POWER_INFORMATION * p = (SYSTEM_POWER_INFORMATION *) &systemPowerInformation;
        javaDefineLong(env, o, "SYSTEM_POWER_INFORMATION.CoolingMode", 0, p->CoolingMode);
        javaDefineLong(env, o, "SYSTEM_POWER_INFORMATION.Idleness", 0, p->Idleness);
        javaDefineLong(env, o, "SYSTEM_POWER_INFORMATION.TimeRemaining", 0, p->TimeRemaining);
        javaDefineLong(env, o, "SYSTEM_POWER_INFORMATION.MaxIdlenessAllowed", 0, p->MaxIdlenessAllowed);
    }

Do the same for ProcessorInformation.

ntStatus = CallNtPowerInformation(ProcessorInformation, lpInputBuffer, nInputBufferSize, &processorPowerInformation, processorPowerInformationSize);
    success = ntStatus == STATUS_SUCCESS;
    if (success == FALSE) {
        logErrorMessage(thisFunctionName, ntStatus);
    } else {
        int x;
        for (x=0; x!=32; x++) {
            PROCESSOR_POWER_INFORMATION * p = (PROCESSOR_POWER_INFORMATION *) &(processorPowerInformation[x]);
            if (x != p->Number) {
                break;
            }
            else {
                javaDefineLong(env, o, "PROCESSOR_POWER_INFORMATION.CurrentIdleState", x, p->CurrentIdleState);
                javaDefineLong(env, o, "PROCESSOR_POWER_INFORMATION.CurrentMhz", x, p->CurrentMhz);
                javaDefineLong(env, o, "PROCESSOR_POWER_INFORMATION.MaxIdleState", x, p->MaxIdleState);
                javaDefineLong(env, o, "PROCESSOR_POWER_INFORMATION.MaxMhz", x, p->MaxMhz);
                javaDefineLong(env, o, "PROCESSOR_POWER_INFORMATION.MhzLimit", x, p->MhzLimit);
                javaDefineLong(env, o, "PROCESSOR_POWER_INFORMATION.Number", x, p->Number);
            }
        }
    }

Do the same for SystemPowerPolicyCurrent.

ntStatus = CallNtPowerInformation(SystemPowerPolicyCurrent, lpInputBuffer, nInputBufferSize, &systemPowerPolicy, systemPowerPolicySize);
    success = ntStatus == STATUS_SUCCESS;
    if (success == FALSE) {
        logErrorMessage(thisFunctionName, ntStatus);
    } else {
        SYSTEM_POWER_POLICY * p = (SYSTEM_POWER_POLICY *) &systemPowerPolicy;
        javaDefineLong(env, o, "SYSTEM_POWER_POLICY.VideoTimeout", 0, p->VideoTimeout);
        javaDefineLong(env, o, "SYSTEM_POWER_POLICY.IdleTimeout", 0, p->IdleTimeout);
        javaDefineLong(env, o, "SYSTEM_POWER_POLICY.LidClose.Action", 0, p->LidClose.Action);
        javaDefineLong(env, o, "SYSTEM_POWER_POLICY.IdleSensitivity", 0, p->IdleSensitivity);
        javaDefineLong(env, o, "SYSTEM_POWER_POLICY.PowerButton.Action", 0, p->PowerButton.Action);
    }

Back to the Java side. Calculate Idle & Busy.

final long id = Java2WinPower.longs.get("SYSTEM_POWER_INFORMATION.Idleness.0").longValue();
final long is = Java2WinPower.longs.get("SYSTEM_POWER_POLICY.IdleSensitivity.0").longValue();
final float aboveT = id - is;
final float belowT = is - id;
final float hi = 100 - is;
final float lo = is;
final int a = (int) ((aboveT / hi) * 100);
final int b = (int) ((belowT / lo) * 100);

 textID.setText(a == b ? "" : a > b ? ("Idle:" + a + "%") : ("Busy:" + b + "%"));

Here is a static view. Real view is, of course, dynamic.

在此处输入图片说明

There are degrees of Idle and Busy. For example, idle of 30% is more idle compared to idle of 5%. Same for busy. Busy of 50% is busier than a busy of 5%. The SleepTimer you see in the image is a countdown timer when the computer is allowed to sleep or hibernate. All data comes from the OS.

Radim's answer is correct if you would like to only monitor your java application for activity. If you would like to monitor the entire system for user activity as suggested by Hovercraft Full Of Eels, you will need some native code. You should be able to leverage something like JNativeHook to accomplish the latter.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM