I'm trying to access the IDesktopWallpaper interface with JNA, but I've hit a wall.
I went through ShOljIdl_core.idl (from Windows 10 SDK) and discovered the GUID of the interface as follows
// IDesktopWallpaper
[
uuid(B92B56A9-8B55-4E14-9A89-0199BBB6F93B),
object
]
and the GUID of the concrete class that implements the interface
// CLSID_DesktopWallpaper
[uuid(C2CF3110-460E-4fc1-B9D0-8A1C0C9CC4BD)] coclass DesktopWallpaper { interface IDesktopWallpaper; }
So I followed the official example in the JDA github and wrote the following
#ComObject(clsId="{C2CF3110-460E-4fc1-B9D0-8A1C0C9CC4BD}")
public interface DesktopWallpaper extends IUnknown{
}
and in Main
Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_MULTITHREADED);
try {
Factory factory = new Factory();
try {
DesktopWallpaper dw = factory.createObject(DesktopWallpaper.class);
} finally {
factory.disposeAll();
factory.getComThread().terminate(1 * 1000);
}
} finally {
Ole32.INSTANCE.CoUninitialize();
}
But the factory.createObject(DesktopWallpaper.class) throws No such interface supported(HRESULT: 80004002) (puArgErr=)and I don't know how to get around this or why it is happening.
Can any experts enlighten me on what's happening? (I am a complete noob) I will provide any further info that's necessary. Can JNA achieve what I want or do I have to use something else like Com4j?
TL;DR
After a lot of googling, I finally got it to work. The problem (at least to my current understanding) is that the current JNA helpers only work with interfaces that inherit from IDispatch. So if the interface in question such as IDesktopWallpaper does not inherit from IDispatch, then one should use vtable for function calls. I got this information from this amazing Google forum post in which the poster also provided a code sample that got me started.
Here is some working code for the SetWallpaper() function:
public class DesktopWallpaperHandler extends Unknown{
private static final GUID CLSID_DesktopWallpaper = new GUID("{C2CF3110-460E-4fc1-B9D0-8A1C0C9CC4BD}");
private static final GUID IID_IDesktopWallpaper = new GUID("{B92B56A9-8B55-4E14-9A89-0199BBB6F93B}");
private DesktopWallpaperHandler(Pointer pvInstance) {
super(pvInstance);
}
public static DesktopWallpaperHandler create(){
PointerByReference p = new PointerByReference();
WinNT.HRESULT hr = Ole32.INSTANCE.CoCreateInstance(CLSID_DesktopWallpaper, null, WTypes.CLSCTX_SERVER, IID_IDesktopWallpaper, p);
COMUtils.checkRC(hr);
DesktopWallpaperHandler handler = new DesktopWallpaperHandler(p.getValue());
return handler;
}
public void SetWallpaper(WTypes.LPWSTR monitor, WTypes.LPWSTR wallpaper){
int result = this._invokeNativeInt(3, new Object[]{this.getPointer(), monitor, wallpaper});
COMUtils.checkRC(new HRESULT(result));
}
}
And then in Main:
Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, Ole32.COINIT_MULTITHREADED);
try {
WTypes.LPWSTR path = new LPWSTR("C:\\Users\\Harry\\Desktop\\1.jpg");
DesktopWallpaperHandler handler = DesktopWallpaperHandler.create();
handler.SetWallpaper(null, path);
} finally {
Ole32.INSTANCE.CoUninitialize();
}
The original motive to use IDesktopWallpaper was to access the fade in transition effect, and now that can be done by adding the following:
User32.INSTANCE.SendMessageTimeout(User32.INSTANCE.FindWindow("Progman", null), 0x52c, 0, 0, 0, 500, null);
Related
A common problem we find in code review is people writing this:
assertThat(thing, nullValue());
instead of this:
assertThat(thing, is(nullValue()));
In order to catch it sooner, I thought I'd try writing a custom error-prone check. This is a poorly documented area though so I've been doing so by digging inside GitHub for working examples.
I have so far:
#AutoService(BugChecker.class)
#BugPattern(
name = "AssertThatThingNullValue",
summary = "`assertThat(thing, nullValue())` doesn't sound like English, wrap `nullValue` in `is`"
severity = WARNING)
public class AssertThatThingNullValue extends BugChecker implements MethodInvocationTreeMatcher
{
private static final Matcher<ExpressionTree> ASSERT_THAT = staticMethod()
.onClassAny("org.hamcrest.MatcherAssert", "org.junit.Assert")
.named("assertThat");
private static final Matcher<ExpressionTree> NULL_VALUE = staticMethod()
.onClass("org.hamcrest.Matchers")
.named("nullValue");
private static final Matcher<ExpressionTree> NULL_VALUE_INVOCATION =
methodInvocation(NULL_VALUE);
private static final Matcher<ExpressionTree> ASSSERT_THAT_THING_NULL_VALUE =
methodInvocation(ASSERT_THAT, MatchType.LAST, NULL_VALUE_INVOCATION);
#Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state)
{
if (ASSSERT_THAT_THING_NULL_VALUE.matches(tree))
{
buildDescription(tree)
.addFix(SuggestedFixes.somethingGoesHere(...))
.build();
}
return Description.NO_MATCH;
}
}
My problem is I can't figure out how to build the suggested fix from the available methods in SuggestedFixes. I'm wondering whether this API just isn't fleshed out well or whether I'm just going down the wrong track entirely and should be writing the check in a better way?
Not able to call native code in Unity
I'm quite at wits end, and thats saying something. It seems no matter what I do I'm not able to succesfully make a crosscall back to an android class from Unity. My C# class
AndroidJavaClass soundActivityJavaClass;
AndroidJavaObject soundActivityObject;
string parse = "";
// Use this for initialization
void Start () {
AndroidJNIHelper.debug = true;
AndroidJNI.AttachCurrentThread();
soundActivityJavaClass = new AndroidJavaClass("com.stuff.oro.UnityBridge");
soundActivityObject = soundActivityJavaClass.GetStatic<AndroidJavaObject>("instance");
parse = soundActivityObject.Call<string>("testBridge");
}
// Update is called once per frame
void Update () {
}
void OnGUI()
{
if (GUI.Button(new Rect(300, 0, 100, 50), "Get mode..."))
{
AndroidJavaClass jc = new AndroidJavaClass("com.stuff.oro.UnityBridge");
AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("instance");
print(jo.Call<string>("testBridge"));
Debug.Log(jo.Call<string>("testBridge"));
}
}
My current android class:
public class UnityBridge extends UnityPlayerActivity{
public static UnityBridge instance;
public String testBridge(){
return "this is a test";
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
UnityBridge.instance = this;
}
public UnityBridge getInstance(){
return instance;
}
}
Any help would be greatly appreciated, I got from not being able to compile, to having
11-30 23:27:53.960: I/Unity(25864): AndroidJavaException: java.lang.NoSuchFieldError: no static field with name='instance' signature='Ljava/lang/Object;' in class Lcom/stuff/oro/UnityBridge;
11-30 23:27:53.960: I/Unity(25864): at UnityEngine.AndroidJNISafe.CheckException () [0x00000] in :0
For anyone who will ever wonder:
Essentially I was never able to specifically call non-static methods on classes that inherited UnityPlayerActivity. Eventually I just dropped inherreting from it at all (which is possible enough) and if I ever was in a situation where I needed the actual Activity (for context or the like), I called UnityPlayer.currentActivity
Hope this helps someone
I have Java-related question:
I want to know is there a way to create path to class (in program) by using a variable(s).
Im making a program that will download pictures from certain sites and show them to a user. However, different sites have different forms, that's why I have to define a series of functions specific to each. They cannot be put in the same class because functions that preform same job (just for another site) would have to have same names. I'm trying to make adding support for another site later as simple as possible.
Anyway, the question is, could I call a function in program using a variable to determine its location.
For example: code.picturesite.functionINeed();
code is the package containing all of the coding, and picturesite is not a class but rather a variable containing the name of the desired class - that way I can only change value of the variable to call a different function (or the same function in a different class).
I don't really expect that to be possible (this was more for you to understand the nature of the problem), but is there another way to do what I'm trying to achieve here?
Yes, there is a way. It's called reflection.
Given a String containing the class name, you can get an instance like this:
Class<?> c = Class.forName("com.foo.SomeClass");
Object o = c.newInstance(); // assuming there's a default constructor
If there isn't a default constructor, you can get a reference to one via c.getConstructor(param1.getClass(), param2.getClass(), etc)
Given a String containing the method name and an instance, you can invoke that method like this:
Method m = o.getClass().getMethod("someMethod", param1.getClass(), param2.getClass(), etc);
Object result = m.invoke(o, param1, param2, etc);
I'm not immediately seeing anything in your question that couldn't be solved by, instead of having a variable containing a class name, having a variable containing an instance of that class -- to call a function on the class, you would have to know it implements that function, so you could put the function in an interface.
interface SiteThatCanFoo {
void foo();
}
And
class SiteA extends Site implements SiteThatCanFoo {
public void foo() {
System.out.println("Foo");
}
}
Then:
Site currentSite = getCurrentSite(); // or getSiteObjectForName(siteName), or similar
if (SiteThatCanFoo.isAssignableFrom(currentSite.class)) {
((SiteThatCanFoo)currentSite).foo();
}
So you want to do something like this (check ImageDownloader.getImageFrom method)
class SiteADownloader {
public static Image getImage(URI uri) {
System.out.println("invoking SiteADownloader on "+uri);
Image i = null;
// logic for dowlnoading image from siteA
return i;
}
}
class SiteBDownloader {
public static Image getImage(URI uri) {
System.out.println("invoking SiteBDownloader on "+uri);
Image i = null;
// logic for dowlnoading image from siteB
return i;
}
}
// MAIN CLASS
class ImageDownloader {
public static Image getImageFrom(String serverName, URI uri) {
Image i = null;
try {
// load class
Class<?> c = Class.forName(serverName + "Downloader");
// find method to dowload img
Method m = c.getDeclaredMethod("getImage", URI.class);
// invoke method and store result (method should be invoked on
// object, in case of static methods they are invoked on class
// object stored earlier in c reference
i = (Image) m.invoke(c, uri);
} catch (NoSuchMethodException | SecurityException
| IllegalAccessException | IllegalArgumentException
| InvocationTargetException | ClassNotFoundException e) {
e.printStackTrace();
}
return i;
}
// time for test
public static void main(String[] args) {
try {
Image img = ImageDownloader.getImageFrom("SiteB", new URI(
"adress"));
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
}
I develop an app using PhoneGap. I got a service which is in background and is coded natively (the service and the phone gap app is in the same project). Unfortunatly, I want to call a javascript function from this service. So I searched on the Web and founded something interesting : create a class extending Plugin and do some treatment in it. Then I found this :
this.ctx.sendJavascript("myJavascriptFunction");
I tested with this code, but something wrong happened :
java.lang.NullPointerException
Here is how I tested :
class c = new class();
c.execute("myFunction",null,null);
In the class c, the execute method is like this :
public PluginResult execute(String action, JSONArray args, String callbackId) {
if (action.equals("myFunction")){
Log.d(TAG,"start actions to do");
this.ctx.sendJavascript("nameOfFunctionToLaunch");
Log.d(TAG,"end actions to do");
return new PluginResult(PluginResult.Status.OK);
}
}
When the app start, I have the first
Log.d(TAG,"start actions to do");
How can I solve this problem ?
Finally I found the solution : in fact the NullPointerException was on ctx.
To fix it, I setup the Context value of my object c like this :
c.setContext(use_An_Object_Of_Type_PhonegapActivity);
To get the object, I grab it from the AppActivity in this method :
public class CloudPhoneAppActivity extends DroidGap {
private class NoScaleWebViewClient extends GapViewClient {
public NoScaleWebViewClient(DroidGap ctx) {
super(ctx);
myApp.ctx = ctx;
}
public void onScaleChanged(WebView view, float oldScale, float newScale) {
Log.d("NoScaleWebViewClient", "Scale changed: " + String.valueOf(oldScale) + " => " + String.valueOf(newScale));
}
}
/** other stuff after**/
}
So finally here is the solution :
class c = new class();
c.setContext(myApp.ctx);
c.execute("myFunction",null,null);
There is no change to do in the execute method which is describe before. But be careful of how you call the javascript function.
Erwan
You cant call object.loadUrl("javascript:function();"); from the plugin as plugin doesnt extend the WebView of Android.
To call loadUrl you would have to pass the call back to the Home class which extends DroidGap.
In the plugin you can define
Home home = null;
Looper.prepare();
home = new Home();
home.somefunc();
and in somefunc call
super.loadUrl("javascript:function();");
So i'm trying to get my Apache xmlrpc client/server implementation to play ball. Everything works fine except for one crucial issue:
my handler class (mapped through the properties file org.apache.xmlrpc.webserver.XmlRpcServlet.properties) reacts as it should but it's constructor is called at every method invocation. It would seem that the handler class is instantiated at each call which is bad because I have data stored in instance variables that I need to save between calls.
How do I save a reference to the instantiated handler so that I can access it's instance variables?
So, for anyone else who still wants to use XMLRPC here's how I fixed this issue:
http://xmlrpc.sourceforge.net/
far superior to apache xmlrpc, in my opinion.
This is standard behaviour of Apache XMLRPC 3.x. http://ws.apache.org/xmlrpc/handlerCreation.html:
By default, Apache XML-RPC creates a new object for processing each
request received at the server side.
However, you can emulate the behaviour of XMLRPC 2.x, where you registered handler objects instead of handler classes, using a RequestProcessorFactoryFactory. I have written a custom RequestProcessorFactoryFactory that you can use:
public class CustomHandler implements RequestProcessorFactoryFactory {
Map<Class<?>, RequestProcessorFactory> handlers =
Collections.synchronizedMap(
new HashMap<Class<?>, RequestProcessorFactory>());
#Override
public RequestProcessorFactory getRequestProcessorFactory(Class pClass)
throws XmlRpcException {
return handlers.get(pClass);
}
public void addHandler(final Object handler) {
handlers.put(handler.getClass(), new RequestProcessorFactory() {
#Override
public Object getRequestProcessor(XmlRpcRequest pRequest)
throws XmlRpcException {
return handler;
}
});
}
}
This can then be used with e.g. a XMLRPC WebServer like this
WebServer server = ...
PropertyHandlerMapping phm = new PropertyHandlerMapping();
server.getXmlRpcServer().setHandlerMapping(phm);
Custom sh = new CustomHandler();
phm.setRequestProcessorFactoryFactory(sh);
Object handler = ... /** The object you want to expose via XMLRPC */
sh.addHandler(handler);
phm.addHandler(serverName, handler.getClass());
Maybe something to do with javax.xml.rpc.session.maintain set to true?
I know this is a really old post but I managed to solve the problem with Apache's Java XML-RPC.
First, I thought this could be solved with singleton class in Java but it doesn't work and throws "illegal access exception".
These are what I have done:
public class XmlRpcServer {
private static JFrame frame = new JFrame();
private static JPanel pane = new JPanel();
public static XmlRpcServer singleton_inst = new XmlRpcServer();
public XmlRpcServer() {
// I kept the constructor empty.
}
public static void main(String[] args) throws XmlRpcException, IOException {
// In my case, I put the constructor code here.
// Then stuff for XML-RPC server
// Server Part
WebServer ws = new WebServer(8741);
PropertyHandlerMapping mapping = new PropertyHandlerMapping();
mapping.addHandler("SERVER", singleton_inst.getClass());
ws.getXmlRpcServer().setHandlerMapping(mapping);
ws.start();
////
}
// I called doTheJob() from python via XML-RPC
public String doTheJob(String s) throws XmlRpcException {
loop();
return s;
}
// It executed loop() forever
private static void loop() throws XmlRpcException {
// Actual work is here
}
But metaspace increases gradually:
I worked too much on this metaspace issue when looping forever in Java but I couldn't figure out a solution.