我最终设法破解了这个问题,方法如下。
由于这个限制性 API 存在于特定于平台的插件中,即 SWT 32 位和 SWT 64 位,我创建了两个特定于平台的片段来保存代码。
要让 maven 编译片段,需要在 build.properties 文件中的 32 位片段中添加以下行:
extra.. = platform:/fragment/org.eclipse.swt.win32.win32.x86
以及 64 位片段 build.properties 的以下内容
extra.. = platform:/fragment/org.eclipse.swt.win32.win32.x86_64
maven pom 配置文件也应该是特定于平台的,这可以通过在 32 位片段的 pom.xml 中添加以下部分来完成
<build>
<plugins>
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>target-platform-configuration</artifactId>
<configuration>
<environments>
<environment>
<os>win32</os>
<ws>win32</ws>
<arch>x86</arch>
</environment>
</environments>
</configuration>
</plugin>
</plugins>
</build>
这里是 64 位版本。
<build>
<plugins>
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>target-platform-configuration</artifactId>
<configuration>
<environments>
<environment>
<os>win32</os>
<ws>win32</ws>
<arch>x86_64</arch>
</environment>
</environments>
</configuration>
</plugin>
</plugins>
</build>
也不要忘记在片段清单中设置相应的平台过滤器,如下所示
Eclipse-PlatformFilter: (& (osgi.os=win32) (osgi.arch=x86))
Eclipse-PlatformFilter: (& (osgi.os=win32) (osgi.arch=x86_64))
然后我们将静音代码放在每个片段的一个类中。这个类应该在宿主插件中实现一个接口。
主机插件定义了一个扩展点,该扩展点采用实现主机插件中接口的类。然后片段声明一个扩展并在片段中提供类名。
当宿主代码需要运行静默代码时,它需要检查扩展并实例化并调用静默代码。
例子:
package com.mypackage;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.e4.core.di.annotations.Creatable;
import com.mypackage.ISilencer;
@Creatable
public class BrowserSilencer {
private static final Logger LOGGER = Logger.getLogger(BrowserSilencer.class);
@Inject
IExtensionRegistry exReg;
public void silence=() {
IConfigurationElement[] config = exReg.getConfigurationElementsFor("com.mypackage.silencer");
try {
for (IConfigurationElement e : config) {
final Object o = e.createExecutableExtension("class");
if (o instanceof ISilencer) {
executeExtension(o);
}
}
} catch (CoreException ex) {
LOGGER.error("Error finding the com.mypackage.silencer extension");
}
}
private void executeExtension(final Object o) {
ISafeRunnable runnable = new ISafeRunnable() {
@Override
public void handleException(Throwable e) {
LOGGER.error("Exception while attempting to silence browser");
}
@Override
public void run() throws Exception {
((ISilencer) o).silence();
}
};
SafeRunner.run(runnable);
}
}
主机插件中的接口
package com.mypackage;
public interface ISilencer {
public void silence();
}
以及 64 位插件中的代码示例。 32位几乎一样
package com.mypackage.fragment.win64;
import org.apache.log4j.Logger;
import org.eclipse.swt.internal.win32.OS; // yes i DO mean win32 here
import com.mypackage.ISilencer;
@SuppressWarnings("restriction")
public class Silencer implements ISilencer {
private static final Logger LOGGER = Logger.getLogger(Silencer.class);
@Override
public void silence() {
// removes the annoying browser clicking sound!
try {
OS.CoInternetSetFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.SET_FEATURE_ON_PROCESS, true);
} catch (Throwable e1) {
// I am just catching any exceptions that may come off this one since it is using restricted API so that if in any case it fail well it will just click.
LOGGER.error("Caught exception while setting FEATURE_DISABLE_NAVIGATION_SOUNDS.");
}
}
}
由于 BrowserSilencer 被标记为 @Creatable,您可以简单地将其注入您的类并调用 silence() 方法
如果不清楚如何创建和扩展点,我可以在后续帖子中说明。