2

I'm trying to write a Kotlin client that uses jsonrpc4j (https://github.com/briandilley/jsonrpc4j) to talk to a server running on an Android device. This is the server I'm using: https://github.com/xiaocong/android-uiautomator-server

Calling methods that take single arguments, such as null or single String objects work fine. However, if I try to call the method boolean exist(Selector obj); the method matching does not work and I get an exception:

Invalid method parameters
com.googlecode.jsonrpc4j.JsonRpcClientException: Invalid method parameters
    at com.googlecode.jsonrpc4j.DefaultExceptionResolver.createJsonRpcClientException(DefaultExceptionResolver.java:53)
    at com.googlecode.jsonrpc4j.DefaultExceptionResolver.resolveException(DefaultExceptionResolver.java:28)
    at com.googlecode.jsonrpc4j.JsonRpcClient.handleErrorResponse(JsonRpcClient.java:272)
    at com.googlecode.jsonrpc4j.JsonRpcClient.readResponse(JsonRpcClient.java:196)
    at com.googlecode.jsonrpc4j.JsonRpcClient.readResponse(JsonRpcClient.java:531)
    at com.googlecode.jsonrpc4j.JsonRpcHttpClient.invoke(JsonRpcHttpClient.java:148)
    at com.googlecode.jsonrpc4j.JsonRpcHttpClient.invoke(JsonRpcHttpClient.java:118)
    at com.googlecode.jsonrpc4j.JsonRpcHttpClient.invoke(JsonRpcHttpClient.java:176)
    ...

https://github.com/xiaocong/android-uiautomator-server/blob/master/app/src/androidTest/java/com/github/uiautomator/stub/AutomatorService.java#L400

Here's my test code:

@Test fun methodTest() {
    val client = JsonRpcHttpClient(URL("http://localhost:9008/jsonrpc/0"))
    val invoke = client.invoke("ping", null, Object::class.java)
    println(invoke) // prints "pong"
    val selector = Selector()
    selector.packageName = "com.company.appname"
    val exists = client.invoke("exist", selector, Boolean::class.java) // throws Exception
    println(exists)
}

I debugged the server code and it looks as if the Selector type is lost and all parameters are "flattened" to a list of strings:

09-17 18:05:58.216 D/UIAutomatorStub(17611): URI: /jsonrpc/0, Method: POST, Header: {content-length=620, remote-addr=127.0.0.1, http-client-ip=127.0.0.1, host=localhost:9008, content-type=application/json-rpc, connection=keep-alive, cache-control=no-cache, pragma=no-cache, user-agent=Java/1.8.0_265, accept=text/html, image/gif, image/jpeg, *; q=.2, /; q=.2}, params, {NanoHttpd.QUERY_STRING=null}, files: {postData={"id":"61840997","jsonrpc":"2.0","method":"exist","params":{"packageName":"com.company.appname","text":null,"className":null,"description":null,"textContains":null,"textMatches":null,"textStartsWith":null,"classNameMatches":null,"descriptionContains":null,"descriptionMatches":null,"descriptionStartsWith":null,"checkable":false,"checked":false,"clickable":false,"scrollable":false,"longClickable":false,"enabled":false,"focusable":false,"focused":false,"selected":false,"packageNameMatches":null,"resourceId":null,"resourceIdMatches":null,"mask":0,"childOrSiblingSelector":[],"childOrSibling":[],"index":0,"instance":0}}}

I copied the Selector class from the server into the host project and used it as is: https://github.com/xiaocong/android-uiautomator-server/blob/master/app/src/androidTest/java/com/github/uiautomator/stub/Selector.java

I also tried annotating the class with @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property="class") but the only effect that had was that it added a "class" attribute to "params".

How do make it work so that I can use the server's parameter types on the client side?

fejd
  • 2,545
  • 1
  • 16
  • 39

1 Answers1

0

Any parameter must be passed into an array. So in your case, the code in JAVA would be:

Boolean exists = client.invoke("exist", new Object[]{selector}, Boolean.class);