如何注册 android 设备以通过 App Engine 后端接收推送通知?

Posted

技术标签:

【中文标题】如何注册 android 设备以通过 App Engine 后端接收推送通知?【英文标题】:How to register android device for receiving Push notifications via App Engine backend? 【发布时间】:2016-03-14 16:48:58 【问题描述】:

我使用this tutorial 创建了以 android 应用和 App Engine 作为后端的示例 android 项目。但是在步骤 2.4 中,我一直在显示来自 GCM 后端的推送通知。调试的时候发现我的RegistrastionRecord中有0个注册设备。那么,如何正确注册应用以使用 App Engine 本地后端接收推送通知?

我收到了这个错误:

Failed to complete token refresh  com.google.api.client.googleapis.json.GoogleJsonResponseException: 404 Not Found
                                                                     <html><head><title>Error 404</title></head>
                                                                     <body><h2>Error 404</h2></body>
                                                                     </html>

这是我的注册端点:

@Api(
    name = "registration",
    version = "v1",
    namespace = @ApiNamespace(
            ownerDomain = "backend.myapplication.Mikhail.example.com",
            ownerName = "backend.myapplication.Mikhail.example.com",
            packagePath=""
    )
 )
  public class RegistrationEndpoint 

private static final Logger log = Logger.getLogger(RegistrationEndpoint.class.getName());

/**
 * Register a device to the backend
 *
 * @param regId The Google Cloud Messaging registration Id to add
 */
@ApiMethod(name = "register")
public void registerDevice(@Named("regId") String regId) 
    if (findRecord(regId) != null) 
        log.info("Device " + regId + " already registered, skipping register");
        return;
    
    RegistrationRecord record = new RegistrationRecord();
    record.setRegId(regId);
    ofy().save().entity(record).now();


/**
 * Unregister a device from the backend
 *
 * @param regId The Google Cloud Messaging registration Id to remove
 */
@ApiMethod(name = "unregister")
public void unregisterDevice(@Named("regId") String regId) 
    RegistrationRecord record = findRecord(regId);
    if (record == null) 
        log.info("Device " + regId + " not registered, skipping unregister");
        return;
    
    ofy().delete().entity(record).now();


/**
 * Return a collection of registered devices
 *
 * @param count The number of devices to list
 * @return a list of Google Cloud Messaging registration Ids
 */
@ApiMethod(name = "listDevices")
public CollectionResponse<RegistrationRecord> listDevices(@Named("count") int count) 
    List<RegistrationRecord> records = ofy().load().type(RegistrationRecord.class).limit(count).list();
    return CollectionResponse.<RegistrationRecord>builder().setItems(records).build();


private RegistrationRecord findRecord(String regId) 
    return ofy().load().type(RegistrationRecord.class).filter("regId", regId).first().now();

这里是 sendRegistrationToServer()。我从 RegistrationIntentService 的 onHandleIntent() 调用它:

   private void sendRegistrationToServer(String token) throws IOException 
    // Add custom implementation, as needed.

    Registration.Builder builder = new Registration.Builder(AndroidHttp.newCompatibleTransport(),
            new AndroidJsonFactory(), null)
            // Need setRootUrl and setGoogleClientRequestInitializer only for local testing,
            // otherwise they can be skipped
            .setRootUrl("http://10.0.2.2:8080/_ah/api/")

            .setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() 
                @Override
                public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest)
                        throws IOException 
                    abstractGoogleClientRequest.setDisableGZipContent(true);
                
            );
    Registration regService = builder.build();
    regService.register(token).execute();

    //regService.register(token).execute();

【问题讨论】:

试试这个链接***.com/questions/15563913/… ie.you may be missing application id at appengine-web.xml 你有什么解决办法吗? 【参考方案1】:

我曾经有这个问题很长时间。在我将插件所有库升级到最新版本后,它对我来说非常好用。

插件:

classpath 'com.google.appengine:gradle-appengine-plugin:1.9.34'

图书馆:

ext 
    appEngineVersion = '1.9.38'


dependencies 
    appengineSdk "com.google.appengine:appengine-java-sdk:$appEngineVersion"
    compile "com.google.appengine:appengine-endpoints:$appEngineVersion"
    compile "com.google.appengine:appengine-endpoints-deps:$appEngineVersion"
    ...

希望这会有所帮助。

【讨论】:

【参考方案2】:

您收到错误无法完成令牌刷新 com.google.api.client.googleapis.json.GoogleJsonResponseException: 404 Not Found,因为找不到与请求关联的资源。请重新部署 App Engine 应用并再次尝试调用它。

基于此SO question,您必须与https 连接才能连接到端点,如果您在setRootUrl 中与http 连接,那么您可能会收到404 错误。使用setRootUrl 时,您必须在https 中包含完整的端点URL。生成客户端库时,您还需要在 appengine-web.xml 中设置应用 ID。这会在生成时回到端点。

这个thread 也可能有帮助。

【讨论】:

以上是关于如何注册 android 设备以通过 App Engine 后端接收推送通知?的主要内容,如果未能解决你的问题,请参考以下文章

如何从应用服务器向 GCM 服务器发送发送重新注册请求以注册设备?

如何注册我的 android 应用程序以解析网站

如何通过 GCM 通过 Windows azure 为特定的 android 设备发送通知?

android设备 如何通过mac地址知道ip地址

玩转OneNET物联网平台之MQTT服务④ —— 远程控制LED(设备自注册)+ Android App控制

如何通过Web App(ReactJS)检测Android设备虚拟键盘中的空格键