首先,你必須定義一個管理器類,這是一樣的東西:
package foo.bar
public class SomeHookManager {
public static void initialize (...) {
// <pre-initialization-routing>
_native_init_();
// <post-initialization-routing>
}
public static void registerCallback (IHookCallback callback)
{ /* save this callback */ }
// this method will be invoked in your C code.
protected static void invokeCallback() { /* invoke the saved callback */ }
// this is a native method, the native modifier tells the compiler this method
// is implemented in C, and linked at runtime.
protected native static void _native_init_();
}
然後使用javah
生成C頭,結果是一樣的東西(我其實沒有編譯這段代碼,所以這是假設):
/*
* Class: Win32
* Method: _native_init_
* Signature:()V
*/
JNIEXPORT void JNICALL Java_foo_bar_Win32_native_init_
(JNIEnv * env, jobject obj);
創建一個C項目,包括這個文件並執行此方法。確保當實際掛鉤觸發,在C代碼中調用invokeCallback
:
jclass cls = (*env)->GetObjectClass(env, obj);
jmethodID mId = (*env)->GetStaticMethodID(env, cls, "invokeCallback", "()V");
if (mId == 0) { /* error handling */ }
(*env)->CallStaticVoidMethod(env, cls, mId);
編譯C項目到一個DLL文件,說hookimpl_win32.dll
,並動態地在Java代碼中的某處將其鏈接:
static {
System.loadLibrary("hookimpl_win32"); // no need of .dll or .so in Unix alike OS's
}
確保該dll與您的jar在同一個文件夾中。或者在虛擬機參數中指定-Djava.library.path=/path/to/your/dlls
。
至於如何記錄每個關鍵事件,操作系統通常會提供一些API來攔截關鍵事件。對於Windows系統,您可以通過攔截全局密鑰消息來實現此目的。我在其他系統上沒有任何經驗。無論如何,你可以設置適當的中斷,這是安靜的低水平。你總是可以將你的答案谷歌。 :)
我認爲你的朋友的意思是說你需要使用本地方法。你可以用C編寫一個本地方法,並使用Java Native Interface(JNI)從Java調用它。 – toto2
@ toto2和那個本地方法會做什麼? – saplingPro
這將是一個記錄密鑰的系統函數。事實上,你最好完全拋棄Java來完成這樣的工作。 Java是可移植的,缺點是它不能執行與操作系統有關的東西。我不太瞭解Windows,但可能C#會更合適。 – toto2