移动后端入门subscribeToCloudMessage将无法正常工作
当我使用带有CloudBackendMessaging.TOPIC_ID_BROADCAST的subscribeToCloudMessage()函数作为在CloudBackendFragment.java中完成的topicId时,一切正常但是当我给这个函数我自己的字符串时,我收到以下消息:
错误:
m.google.api.client.googleapis.json.GoogleJsonResponseException: 400 Bad Request "code": 400, "errors": [ { "domain": "global", "message": "SubscriptionIDs: String properties must be 500 characters or less. Instead, use com.google.appengine.api.datastore.Text, which can store strings of any length.", "reason": "badRequest" } ], "message": "SubscriptionIDs: String properties must be 500 characters or less. Instead, use com.google.appengine.api.datastore.Text, which can store strings of any length." at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:111) at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:38) at com.google.api.client.googleapis.services.AbstractGoogleClientRequest$1.interceptResponse(AbstractGoogleClientRequest.java:312) at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1042) at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:410) at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:343) at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:460) at com.google.cloud.backend.core.CloudBackend.list(CloudBackend.java:314) at com.google.cloud.backend.core.CloudBackendAsync.access$8(CloudBackendAsync.java:1) at com.google.cloud.backend.core.CloudBackendAsync$9.callBackend(CloudBackendAsync.java:270) at com.google.cloud.backend.core.CloudBackendAsync$9.callBackend(CloudBackendAsync.java:1) at com.google.cloud.backend.core.CloudBackendAsync$BackendCaller.run(CloudBackendAsync.java:402)
此错误消息表示属性SubscriptionIDs
(您可以在数据存储区中的_DeviceSubscription
Kind下找到它)值超过500个Unicode字符限制。 阅读文档以供参考。
来自文档:
对于文本字符串和未编码的二进制数据(字节字符串),数据存储区支持两种值类型:
- 短字符串(最多500个Unicode字符或字节)被编入索引,可用于查询过滤条件和排序顺序。
- Longstrings(最多1兆字节)未编入索引,不能用于查询filter和排序顺序。
发生这种情况的原因是MBS试图将所有订阅写入一个属性。
因此,为了克服这个问题,我们需要在SubscriptionIDs
属性的MBS后端源代码中使用Text
而不是String
类型。 为此,您需要在DeviceSubscription.java
类中进行以下更改:
要设置Text
属性,请替换以下代码行:
deviceSubscription.setProperty(PROPERTY_SUBSCRIPTION_IDS, this.gson.toJson(subscriptions));
用这一行:
deviceSubscription.setProperty(PROPERTY_SUBSCRIPTION_IDS, new Text(this.gson.toJson(subscriptions)));
要从数据存储区获取Text
属性:
-
替换此行:
String subscriptionString = (String) deviceSubscription.getProperty(PROPERTY_SUBSCRIPTION_IDS);
有了这个:
Text text = (Text) deviceSubscription.getProperty(PROPERTY_SUBSCRIPTION_IDS); String subscriptionString = text.getValue();
-
替换此行:
String ids = (String) deviceSubscription.getProperty(PROPERTY_SUBSCRIPTION_IDS);
有了这个:
Text text = (Text) deviceSubscription.getProperty(PROPERTY_SUBSCRIPTION_IDS); String ids = text.getValue();
-
替换此行:
String[] ids = new Gson().fromJson((String) entity.getProperty(PROPERTY_SUBSCRIPTION_IDS), String[].class);
有了这个:
Text text = (Text) entity.getProperty(PROPERTY_SUBSCRIPTION_IDS); String[] ids = new Gson().fromJson(text.getValue(), String[].class);
似乎是有效的解决方案。 到目前为止,我没有注意到对我项目的负面影响。
注意:作为文档说明Text
未编入索引,不能用于查询filter和排序顺序 。 因此,如果需要对属性SubscriptionIDs
进行索引,则此限制可能会导致另一个问题。
我转到了cloud.google.com查询视图并删除了旧的device_subscription ID,之后它运行正常。 不确定你是否能够做到这一点。
似乎订阅ID是使用一些algorythm生成的,主要使用当您第一次启动移动后端启动应用程序时获得的regid。 为了解决这个问题,当我拥有它时,我只是在给定的regid上调用了substring并大大缩短了它,但仍然保留了足够长的时间以保证某种程度的唯一性。
private static String doRegister(Context context){String msg =“”; 尝试{GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context); String regId = gcm.register(Consts.PROJECT_NUMBER).substring(0,16); msg =“设备已注册,注册ID =”+ regId;
此方法位于GCMIntentService.java文件中。 请注意
.substring(0,16);
为我工作! 只是想我会分享。
根据文档,@ Juniper的答案是有道理的。 @jackrockRay的回答对我不起作用。
但是我觉得这可能与作为Entitykind传递的String的值有关。 如果我将其从“留言簿”(如示例中)更改为其他错误,则会发生错误。 如果我改回来,即使使用不同的实体属性,一切都按预期工作。 你能证实一下吗?