【问题标题】:GCM: onMessage() from GCMIntentService is called very few timesGCM:GCMIntentService 中的 onMessage() 被调用的次数很少
【发布时间】:2013-03-19 18:21:54
【问题描述】:

我正在我的应用程序中实现GCM。我已按照 developer.android.com 的 GCM 教程中给出的所有步骤进行操作

我的应用程序的构建目标指向Goolge API 8 (Android 2.2 version)

我能够成功地从 GCM 获取注册 ID,并将此 ID 传递给我的应用程序服务器。这样注册步骤就成功了。

现在,当我的应用服务器向我的设备发送 PUSH 消息时,服务器收到的消息为SUCCESS=1 FAILURE=0, etc.,即服务器发送消息成功,但我的设备从未收到消息。

经过大量搜索,我知道 GCM 在端口号 5228、5229 或 5230 上推送消息。

最初,我的设备和笔记本电脑被限制访问某些网站,但后来我被授予访问所有网站的所有权限,所以我猜这些端口号对我的设备是开放的。

所以我的问题是:我很少收到来自 GCM 的 PUSH 消息。为什么谷歌在传递信息方面如此不确定? 可能是什么原因?

请查看我的以下代码并相应地指导我:

我已在清单中声明以下内容:

<uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="8" />

    <permission
        android:name="package.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />

    <!-- App receives GCM messages. -->
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

    <!-- GCM connects to Google Services. -->
    <uses-permission android:name="android.permission.INTERNET" />

    <!-- GCM requires a Google account. -->
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />

    <!-- Keeps the processor from sleeping when a message is received. -->
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="package.permission.C2D_MESSAGE" />
    <uses-permission android:name="android.permission.INTERNET" />

    <receiver
            android:name="com.google.android.gcm.GCMBroadcastReceiver"
            android:permission="com.google.android.c2dm.permission.SEND" >
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <action android:name="com.google.android.c2dm.intent.REGISTRATION" />

                <category android:name="packageName" />
            </intent-filter>
        </receiver>
        <receiver
            android:name=".ReceiveBroadcast"
            android:exported="false" >
            <intent-filter>
                <action android:name="GCM_RECEIVED_ACTION" />
            </intent-filter>
        </receiver>

        <service
            android:name=".GCMIntentService"
            />


/**
 * @author Shrikant.
 * 
 */
public class GCMIntentService extends GCMBaseIntentService {

    /**
     * The Sender ID used for GCM.
     */
    public static final String SENDER_ID = "myProjectID";

    /**
     * This field is used to call Web-Service for GCM.
     */
    SendUserCredentialsGCM sendUserCredentialsGCM = null;

    public GCMIntentService() {
        super(SENDER_ID);
        sendUserCredentialsGCM = new SendUserCredentialsGCM();
    }

    @Override
    protected void onRegistered(Context arg0, String registrationId) {
        Log.i(TAG, "Device registered: regId = " + registrationId);
        sendUserCredentialsGCM.sendRegistrationID(registrationId);
    }

    @Override
    protected void onUnregistered(Context context, String arg1) {
        Log.i(TAG, "unregistered = " + arg1);
        sendUserCredentialsGCM
                .unregisterFromGCM(LoginActivity.API_OR_BROWSER_KEY);
    }

    @Override
    protected void onMessage(Context context, Intent intent) {
        Log.e("GCM MESSAGE", "Message Recieved!!!");
        String message = intent.getStringExtra("message");
        if (message == null) {
            Log.e("NULL MESSAGE", "Message Not Recieved!!!");
        } else {
            Log.i(TAG, "new message= " + message);
            sendGCMIntent(context, message);
        }
    }

    private void sendGCMIntent(Context context, String message) {
        Intent broadcastIntent = new Intent();
        broadcastIntent.setAction("GCM_RECEIVED_ACTION");
        broadcastIntent.putExtra("gcm", message);
        context.sendBroadcast(broadcastIntent);
    }

    @Override
    protected void onError(Context context, String errorId) {
        Log.e(TAG, "Received error: " + errorId);
        Toast.makeText(context, "PUSH Notification failed.", Toast.LENGTH_LONG)
                .show();
    }

    @Override
    protected boolean onRecoverableError(Context context, String errorId) {
        return super.onRecoverableError(context, errorId);
    }
}

谢谢。

【问题讨论】:

  • 您是否确认这些端口已在您的设备上打开?您可能希望使用在线端口测试工具来验证这些端口是否全部打开。我认为您不能根据您所说的假设这些端口是开放的。如果你想在你的设备上测试一个已知的工作 GCM 项目,Github 上有一个示例应用程序可用:github.com/indigorose/airbop-client
  • (AirBop是第三方GCM注册服务,最多可免费使用1000台设备。)
  • 如果这些端口在我这边关闭,我将永远不会收到 PUSH 消息,但我有时会收到 PUSH 消息(非常少)。
  • 您能告诉我,为什么 GCM 无法向我发送 PUSH 消息吗?我可以试试 AirBop,但由于 Google 是免费的,我的第一选择是使用 Google 服务。我完全不知道为什么我没有收到推送消息。
  • (需要说明的是,AirBop 使用 GCM——GCM 本身是免费的,但您仍然需要一个服务器端组件来处理设备注册 ID。)您在发送推送消息?在某些情况下您可能不会收到该消息,例如,如果您将 dry_run 设置为 true,或者如果您使用折叠键。例如,如果您为每条消息设置不同的折叠键,您肯定会丢失一些消息,因为 GCM 在任何给定时间最多只支持 4 个折叠键。

标签: android push-notification google-cloud-messaging


【解决方案1】:

检查调试证书是否过期,如果是则创建新证书并生成新密钥。

【讨论】:

  • 我已经这样做了...没有帮助...还有其他解决方案吗?
  • OMG... 从哪里得到的 :) 说真的,你节省了我很多时间。 :)
【解决方案2】:

尝试将您的类名更改为带有包名的全名。喜欢:

<service android:name="com.xx.xx.xx" />

别忘了把你的包名放在这里:

<category android:name="packageName" />

【讨论】:

  • 您应该确保您的软件包名称正确写入清单文件。这一定是问题所在。
  • 我已经把它放在接收器里了,我应该把它放在服务标签里吗?服务标签中没有类别标签。我没明白你在说什么。是不是一定要启动服务,因为我的服务还没有启动,但是还是注册了,请问我的服务有什么问题吗?
  • 包名正确。我没有在这篇文章中提到它。
  • 我的意思是你已经在你的接收者标签中写了 。你确定你的名字写对了吗?
  • 服务标签也使用完整的包名,正如我在回答中所写的那样
【解决方案3】:

确保您的应用名称和您在谷歌控制台上注册用于获取 api 密钥的名称相同。相同的名称意味着完全相同

【讨论】:

  • 如果该名称不匹配,我将永远不会收到 PUSH 消息,但我收到的 PUSH 消息很少。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-30
  • 2020-03-28
相关资源
最近更新 更多