简体   繁体   中英

Mobile Backend Starter subscribeToCloudMessage will not work

When I use the subscribeToCloudMessage() function with CloudBackendMessaging.TOPIC_ID_BROADCAST as the topicId as is done in CloudBackendFragment.java everything works fine but when I give this function my own string I get this message:

error:

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)

This error message means that property SubscriptionIDs (you can find it under the _DeviceSubscription Kind in your datastore) value exceeds 500 Unicode characters limit. Read docs for the reference.

From the docs:

For text strings and unencoded binary data (byte strings), the Datastore supports two value types:

  1. Short strings (up to 500 Unicode characters or bytes) are indexed and can be used in query filter conditions and sort orders.
  2. Longstrings (up to 1 megabyte) are not indexed and cannot be used in query filters and sort orders.

The reason for this happening is that MBS trying to write all subscriptions into one property.

So to overcome this issue we need to use Text instead of String type in MBS backend source code for the SubscriptionIDs property. To do so you need to make following changes in DeviceSubscription.java class:

To set Text property replace this line of code:

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

with this line:

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

To get Text property from the datastore:

  1. Replace this line:

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

    with this:

     Text text = (Text) deviceSubscription.getProperty(PROPERTY_SUBSCRIPTION_IDS); String subscriptionString = text.getValue();
  2. Replace this line:

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

    with this:

     Text text = (Text) deviceSubscription.getProperty(PROPERTY_SUBSCRIPTION_IDS); String ids = text.getValue();
  3. Replace this line:

     String[] ids = new Gson().fromJson((String) entity.getProperty(PROPERTY_SUBSCRIPTION_IDS), String[].class);

    with this:

     Text text = (Text) entity.getProperty(PROPERTY_SUBSCRIPTION_IDS); String[] ids = new Gson().fromJson(text.getValue(), String[].class);

Seems to be valid solution. I have not noticed negative influence on my project so far.

NOTE: As docs stated Text is not indexed and cannot be used in query filters and sort orders . So this limitation could have cause another issues if the property SubscriptionIDs required to be indexed.

I went to the cloud.google.com query view and deleted my old device_subscription IDs, thereafter it worked fine. Not sure if you're able to do this.

It seems like the subscription ids are being generated using some algorythm that mainly uses the regid that is obtained when you first fire up the mobile backend starter app. To solve this issue when I had it I just called substring on the given regid and shortened it considerably but still left it long enough to guarantee some level of uniqueness.

private static String doRegister(Context context) { String msg = ""; try { GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context); String regId = gcm.register(Consts.PROJECT_NUMBER).substring(0,16); msg = "Device registered, registration ID=" + regId;

This method is located in the GCMIntentService.java file. Notice the

.substring(0,16);

Worked for me! just thought I'd share.

@Juniper's answer makes sense according to the Documentation. @jamrockRay's answer didn't work for me.

However i have a feeling that this might be related to the value of the String passed as Entitykind. If i change it from "Guestbook" (as in the example) to something else the error occurs. If i change it back everything works as expected, even with different entity properties. Can you confirm this?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM