移动后端入门subscribeToCloudMessage将无法正常工作

时间:2014-03-02 01:14:22

标签: java android json google-maps google-app-engine

当我使用带有CloudBackendMessaging.TOPIC_ID_BROADCAST的subscribeToCloudMessage()函数作为topicId时,就像在CloudBackendFragment.java中一样,一切正常但是当我给这个函数我自己的字符串时,我得到这样的信息:

错误:

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)

4 个答案:

答案 0 :(得分:5)

此错误消息表示属性SubscriptionIDs(您可以在数据存储区中的_DeviceSubscription种类下找到它)超过500个Unicode字符限制。请阅读docs作为参考。

来自文档:

  

对于文本字符串和未编码的二进制数据(字节字符串),   数据存储区支持两种值类型:

     
      
  1. 索引短字符串(最多500个Unicode字符或字节)   并可用于查询过滤条件和排序顺序。
  2.   
  3. Longstrings(最多1兆字节)未编入索引,无法在查询过滤器和排序顺序中使用。
  4.   

发生这种情况的原因是MBS试图将所有订阅写入一个属性。

因此,要解决此问题,我们需要在MBS backend source code中使用Text代替String类型SubscriptionIDs属性。为此,您需要在DeviceSubscription.java类中进行以下更改:

设置Text属性替换此行代码:

deviceSubscription.setProperty(PROPERTY_SUBSCRIPTION_IDS, this.gson.toJson(subscriptions));

这一行:

deviceSubscription.setProperty(PROPERTY_SUBSCRIPTION_IDS, new Text(this.gson.toJson(subscriptions)));

从数据存储区获取Text属性:

  1. 替换此行:

    String subscriptionString = (String) deviceSubscription.getProperty(PROPERTY_SUBSCRIPTION_IDS);
    

    用这个:

    Text text = (Text) deviceSubscription.getProperty(PROPERTY_SUBSCRIPTION_IDS);
        String subscriptionString = text.getValue();
    
  2. 替换此行:

    String ids = (String) deviceSubscription.getProperty(PROPERTY_SUBSCRIPTION_IDS);
    

    用这个:

    Text text = (Text) deviceSubscription.getProperty(PROPERTY_SUBSCRIPTION_IDS);
          String ids = text.getValue();
    
  3. 替换此行:

    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);
    
  4. 似乎是有效的解决方案。到目前为止,我还没有注意到对我项目的负面影响。

    注意:正如文档所述Text 未编入索引且无法在查询过滤器和排序顺序中使用。因此,如果需要对属性SubscriptionIDs建立索引,则此限制可能会导致另一个问题。

答案 1 :(得分:2)

我访问了cloud.google.com查询视图并删除了旧的device_subscription ID,此后它运行正常。不确定您是否能够这样做。

答案 2 :(得分:1)

似乎订阅ID是使用一些algorythm生成的,主要使用首次启动移动后端启动应用时获得的regid。为了解决这个问题,当我拥有它时,我只是在给定的regid上调用了子字符串并大大缩短了它,但仍然保留了足够长的时间以保证某种程度的唯一性。

  

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);

为我工作!只是想我会分享。

答案 3 :(得分:1)

根据文档,@ Juniper的答案是有道理的。 @jackrockRay的回答对我不起作用。

但是我觉得这可能与作为Entitykind传递的String的值有关。如果我将它从“留言簿”(如示例中)更改为其他错误,则会发生错误。如果我更改它,一切都按预期工作,即使使用不同的实体属性。你能证实一下吗?