我正在使用 RPC 开发具有 GAE 和 Android 的应用程序。但是当我尝试将 RPCall 从 Android 发送到服务器时,我收到以下错误。
03-14 12:00:57.445: E/AndroidRuntime(30718): FATAL EXCEPTION: IntentService[domiii.1992@gmail.com]
03-14 12:00:57.445: E/AndroidRuntime(30718): java.lang.RuntimeException: Could not parse payload: payload[0] = <
03-14 12:00:57.445: E/AndroidRuntime(30718): at com.google.web.bindery.autobean.vm.impl.JsonSplittable.create(JsonSplittable.java:70)
03-14 12:00:57.445: E/AndroidRuntime(30718): at com.google.web.bindery.autobean.shared.impl.StringQuoter.split(StringQuoter.java:73)
03-14 12:00:57.445: E/AndroidRuntime(30718): at com.google.web.bindery.autobean.shared.AutoBeanCodex.decode(AutoBeanCodex.java:54)
03-14 12:00:57.445: E/AndroidRuntime(30718): at com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext$StandardPayloadDialect.processPayload(AbstractRequestContext.java:323)
03-14 12:00:57.445: E/AndroidRuntime(30718): at com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext$5.onTransportSuccess(AbstractRequestContext.java:1108)
03-14 12:00:57.445: E/AndroidRuntime(30718): at com.cloudsmsplus.util.AndroidRequestTransport.send(AndroidRequestTransport.java:68)
03-14 12:00:57.445: E/AndroidRuntime(30718): at com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext.doFire(AbstractRequestContext.java:1102)
03-14 12:00:57.445: E/AndroidRuntime(30718): at com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext.fire(AbstractRequestContext.java:569)
03-14 12:00:57.445: E/AndroidRuntime(30718): at com.google.web.bindery.requestfactory.shared.impl.AbstractRequest.fire(AbstractRequest.java:54)
03-14 12:00:57.445: E/AndroidRuntime(30718): at com.google.web.bindery.requestfactory.shared.impl.AbstractRequest.fire(AbstractRequest.java:59)
03-14 12:00:57.445: E/AndroidRuntime(30718): at com.cloudsmsplus.c2dm.DeviceRegistrar.registerOrUnregister(DeviceRegistrar.java:70)
03-14 12:00:57.445: E/AndroidRuntime(30718): at com.cloudsmsplus.C2DMReceiver.onRegistered(C2DMReceiver.java:51)
03-14 12:00:57.445: E/AndroidRuntime(30718): at com.google.android.c2dm.C2DMBaseReceiver.handleRegistration(C2DMBaseReceiver.java:191)
03-14 12:00:57.445: E/AndroidRuntime(30718): at com.google.android.c2dm.C2DMBaseReceiver.onHandleIntent(C2DMBaseReceiver.java:110)
03-14 12:00:57.445: E/AndroidRuntime(30718): at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
03-14 12:00:57.445: E/AndroidRuntime(30718): at android.os.Handler.dispatchMessage(Handler.java:99)
03-14 12:00:57.445: E/AndroidRuntime(30718): at android.os.Looper.loop(Looper.java:137)
03-14 12:00:57.445: E/AndroidRuntime(30718): at android.os.HandlerThread.run(HandlerThread.java:60)
要访问我的应用程序,用户必须经过身份验证,因此我将每个 url 的安全约束设置为 *。即使我正在生成 cookie,我也会收到此错误。我认为我得到的响应是登录页面。
在我的情况下,我发送一个 RPCall 来为 C2DM 注册设备。我使用的大部分代码都是使用 Appengine 连接的 Android 项目生成的。是否有人已经找到了解决方法或解决方法。
PS:我使用的是 GAE 1.6.3、Android API v8、GWT 2.4.0(但我认为这无关紧要)
编辑:
好的,我发现了一些新东西。如果您使用 RPC 从 Android 向 App Engine 发送内容,则客户端实际上并未经过身份验证。您只需获取令牌,然后是 cookie,然后(所以我认为)RequestFactory 将 cookie 包含为一个额外的数据字段。所以我在 App Engine 上的 web.xml 看起来像这样:
<!-- Require user login for every access -->
<security-constraint>
<web-resource-collection>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
要访问我的应用程序,用户必须经过身份验证,无论他请求哪个 URL。由于 RequestFactory 未通过登录页面的 html 对服务器响应进行身份验证,并且 Android 客户端抛出错误“无法解析有效负载”。奇怪的是,您可以从 GWT 端发送经过身份验证的 RPC,我不明白为什么这个 API 的开发人员会这样做,GWT 端能够发送那些经过身份验证的调用而 Android 端不能能够发送它们。
我现在所做的是,我使用 web.xml 中的这些附加行从我的安全约束中排除了 gwtRequest servlet
<security-constraint>
<web-resource-collection>
<url-pattern>/gwtRequest</url-pattern>
</web-resource-collection>
</security-constraint>
我还注意到,如果您创建一个新的连接 App Engine 的 Android 项目,web.xml 只会在 ProjectName.html 上设置所需的身份验证。