【问题标题】:Programmatically (in Java) keep OS X from going asleep以编程方式(在 Java 中)防止 OS X 进入休眠状态
【发布时间】:2011-12-27 00:03:41
【问题描述】:

OS X Lion 仍会进入睡眠状态,即使 Java 机器人定期发出程序化鼠标“摆动”(这是防止机器进入睡眠状态的标准方法,并且在 stackoverflow 的其他地方有文档,它适用于我在 OS X Lion 之前)。

任何人都可以提出一种不需要升级权限的替代方法来保持机器从 Java 应用程序唤醒吗?

((后备解决方案显然是更改节能首选项,以便机器永远不会休眠,但我们希望比这更聪明,因为要求机器保持清醒是例外而不是规则))。

【问题讨论】:

    标签: java macos


    【解决方案1】:

    事实证明,使用纯 Java hack 不再可能做到这一点,必须求助于实现 JNI I/O 侦听器,其代码将包含类似

    http://developer.apple.com/library/mac/#qa/qa1340/_index.html

    如果您可以容忍调用命令行工具,另一种方法是在守护线程中调用pmset noidle

    【讨论】:

      【解决方案2】:

      您需要防止显示器休眠或系统休眠吗?如果是后者,您可以通过磁盘活动防止系统睡眠 - 例如读取或写入文件。

      硬盘活动不会阻止显示器休眠,但会阻止 系统休眠。显示器在 如果两种类型的睡眠都设置为在 相同的不活动时间。 http://support.apple.com/kb/ht1776

      This answer 指向可用于防止睡眠的 Objective-C 代码,使用 UpdateSystemActivity 调用。您能否在此基础上创建一个简单的 JNI 包装器,您可以从 Java 代码中调用它作为本机方法?

      似乎也可以使用 applescript 禁用和重新启用睡眠。您能否使用 Java 代码中的 Runtime.exec() 调用这样的脚本?

      【讨论】:

      • 显示睡眠对我来说无关紧要,我只对阻止机器进入系统睡眠感兴趣。根据经验,我可以告诉你,读取和写入文件绝对不会阻止 iMac 进入睡眠状态!
      【解决方案3】:

      以下 JNI 解决方案适用于 macOS 10.5 / GCC

      我。定义 Java 原生接口

      // File KalleInterface.java
      public class KalleInterface
      {
          static
          {
              // java.library.path set to libKalleInterface.dylib
              System.loadLibrary("KalleInterface");
          }   
      
          public static native boolean preventSleep();
          public static native boolean allowSleep();
      }
      

      二。生成等效的 C++ 接口

      假设编译的java类文件是./bin/KalleInterface.class

      javah -jni -d "${PWD}" -classpath "${PWD}/bin" KalleInterface
      

      生成一个 C++ 标头 KalleInterface.h

      /* DO NOT EDIT THIS FILE - it is machine generated */
      #include <jni.h>
      /* Header for class KalleInterface */
      
      #ifndef _Included_KalleInterface
      #define _Included_KalleInterface
      #ifdef __cplusplus
      extern "C" {
      #endif
      /*
      * Class:     KalleInterface
      * Method:    preventSleep
      * Signature: ()Z
      */
      JNIEXPORT jboolean JNICALL Java_KalleInterface_preventSleep(JNIEnv *, jclass);
      
      /*
      * Class:     KalleInterface
      * Method:    allowSleep
      * Signature: ()Z
      */
      JNIEXPORT jboolean JNICALL Java_KalleInterface_allowSleep(JNIEnv *, jclass);
      
      #ifdef __cplusplus
      }
      #endif
      #endif
      

      三。实现 C++ 接口

      #include "esc_util_KalleInterface.h"
      
      #include <IOKit/pwr_mgt/IOPMLib.h>
      
      // IOPMAssertionCreateWithName ...
      // kIOPMAssertionTypeNoDisplaySleep prevents display sleep,
      // kIOPMAssertionTypeNoIdleSleep prevents idle sleep
      
      //reasonForActivity is a descriptive string used by the system whenever it needs
      // to tell the user why the system is not sleeping. For example,
      // "Mail Compacting Mailboxes" would be a useful string.
      
      // IOPMAssertionDeclareUserActivity ...
      // claims user activity
      
      
      #ifdef __cplusplus
      extern "C" {
      #endif
      
      CFStringRef reasonForActivity= CFSTR("User Activity Type");
      // NOTE: IOPMAssertionCreateWithName limits the string to 128 characters.
      
      
      IOPMAssertionID assertionID;
      
      
      static bool active = false;
      
      /*
       * Class:     KalleInterface
       * Method:    preventSleep
       * Signature: ()Z
       */
      JNIEXPORT jboolean JNICALL Java_esc_util_KalleInterface_preventSleep(JNIEnv*, jclass)
      {
          IOReturn success = 0;
          
          if (active)
          {
              return (jboolean)true;
          }
          //success = IOPMAssertionCreateWithName(kIOPMAssertionTypeNoIdleSleep, kIOPMAssertionLevelOn, reasonForActivity, &assertionID);
          //success = IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep,   kIOPMAssertionLevelOn, reasonForActivity, &assertionID);
          success = IOPMAssertionDeclareUserActivity(reasonForActivity, kIOPMUserActiveLocal, &assertionID);
          active =(success == kIOReturnSuccess);
          return (jboolean)active;
      
      //Add the work you need to do without 
      //  the system sleeping here.
          
      }
      
      /*
       * Class:     KalleInterface
       * Method:    allowSleep
       * Signature: ()Z
       */
      JNIEXPORT jboolean JNICALL Java_esc_util_KalleInterface_allowSleep(JNIEnv *, jclass)
      {
          IOReturn success = 0;
          
          if (!active)
          {
              return (jboolean)true;
          }
      
          success = IOPMAssertionRelease(assertionID);
          active = !(success == kIOReturnSuccess);
          //The system will be able to sleep again. 
          return (jboolean)(!active);
      }
      
      
      #ifdef __cplusplus
      }
      #endif
      

      四。构建共享库

      构建libKalleInterface.dylib的命令行步骤是

      g++ -c -fPIC -I ${JAVA_HOME}/include -I ${JAVA_HOME}/include/darwin -o KalleInterfaceCPP.o  KalleInterfaceCPP.cpp
      
      g++  -dynamiclib -framework CoreFoundation -framework IOKit -o libKalleInterface.dylib KalleInterfaceCPP.o -lc
      

      V.测试类

      // File KalleTest.java
      
      public class KalleTest
      {
          public static void main(String...args)
          {
              boolean ok1 = KalleInterface.preventSleep();
              System.out.println(ok1);
              try
              {
                  Thread.sleep(60*10*1000);
              }
              catch (Exception x)
              {
                  x.printStackTrace();
              }
              boolean ok2 = KalleInterface.allowSleep();
              System.out.println(ok2);
          }
      }
      

      假设编译类为./bin/KalleTest.class,共享库为./libKalleInterface.dylib,则调用测试

      java -Djava.library.path=${PWD} -classpath ./bin KalleTest
      

      预期行为:Mac 保持活动状态 10 分钟,preventSleep()allowSleep() 中的每一个都产生结果/输出 true

      【讨论】:

      • 该问题明确表示来自 Robot 的鼠标移动被忽略。那是 OP 以前的解决方案停止工作,他们开始寻找替代方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-02
      • 2011-09-08
      • 1970-01-01
      • 2012-07-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多