为啥 GCM 不在 android 设备中提供推送通知?

Posted

技术标签:

【中文标题】为啥 GCM 不在 android 设备中提供推送通知?【英文标题】:why GCM is not giving push notification in android device?为什么 GCM 不在 android 设备中提供推送通知? 【发布时间】:2012-11-07 07:23:45 【问题描述】:

我是 android 新手,正在为 gcm 推送通知做一个演示应用程序。

我已经开发了所有这些代码,并且 GCM 推送通知正在我的环境中的设备上发送,但是当我在其他网络设备中测试此代码时获得注册 ID,但服务器端在向云端发送消息时收到不匹配的发件人 ID 响应。 我的代码如下:

        checkNotNull(CommonUtilities.SENDER_ID, "SENDER_ID");

    GCMRegistrar.checkDevice(this);
    GCMRegistrar.checkManifest(this);

    setContentView(R.layout.activity_push_android);
    mDisplay = (TextView) findViewById(R.id.display);

    final String regId = GCMRegistrar.getRegistrationId(this);
    Log.i(TAG, "registration id =====  " + regId);

    if (regId.equals("")) 
        GCMRegistrar.register(this, CommonUtilities.SENDER_ID);
     else 
        // Device is already registered on GCM
        if (GCMRegistrar.isRegisteredOnServer(this)) 
            // Skips registration.
            Toast.makeText(getApplicationContext(),
                    "Already registered with GCM", Toast.LENGTH_LONG)
                    .show();
         else 
            // Try to register again, but not in the UI thread.
            // It's also necessary to cancel the thread onDestroy(),
            // hence the use of AsyncTask instead of a raw thread.
            // final Context context = this;
            mRegisterTask = new AsyncTask<Void, Void, Void>() 

                @Override
                protected Void doInBackground(Void... params) 
                    // Register on our server
                    // On server creates a new user
                    // ServerUtilities.register(context, name, email,
                    // regId);
                    return null;
                

                @Override
                protected void onPostExecute(Void result) 
                    mRegisterTask = null;
                    mDisplay.setText("ffffff        " + regId);
                

            ;
            mRegisterTask.execute(null, null, null);
        
    
    // regId = GCMRegistrar.getRegistrationId(this);
    mDisplay.setText("ffffff        " + regId);
    Log.i(TAG, "registration id =====!!!!  " + regId);


private void checkNotNull(Object reference, String name) 
    if (reference == null) 
        throw new NullPointerException(getString(R.string.error_config,
                name));
    


@Override
protected void onPause() 
    super.onPause();
    GCMRegistrar.unregister(this);

  

接收者:

public GCMIntentService() 
    super(CommonUtilities.SENDER_ID);



private static final String TAG = "===GCMIntentService===";

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


@Override
protected void onUnregistered(Context arg0, String arg1) 
    Log.i(TAG, "unregistered = " + arg1);


@Override
protected void onMessage(Context arg0, Intent message) 
    Bundle extras = message.getExtras();

    for (String key : extras.keySet()) 
        Log.d(getClass().getSimpleName(),
                String.format("onMessage: %s=%s", key,
                        extras.getString(key)));

        Toast.makeText(getApplicationContext(), "hii", Toast.LENGTH_LONG)
                .show();
    
    Log.i(TAG, "new message= ");

    // ///////////////////

    long when = System.currentTimeMillis();
    NotificationManager notificationManager = (NotificationManager) context
            .getSystemService(Context.NOTIFICATION_SERVICE);
    Notification notification = new Notification(R.drawable.ic_launcher,
            (CharSequence) message, when);
    String title = context.getString(R.string.app_name);
    Intent notificationIntent = new Intent(context,
            PushAndroidActivity.class);
    // set intent so it does not start a new activity
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
            | Intent.FLAG_ACTIVITY_SINGLE_TOP);
    PendingIntent intent = PendingIntent.getActivity(context, 0,
            notificationIntent, 0);
    notification.setLatestEventInfo(context, title, (CharSequence) message,
            intent);
    notification.flags |= Notification.FLAG_AUTO_CANCEL;
    notificationManager.notify(0, notification);


@Override
protected void onError(Context arg0, String errorId) 
    Log.i(TAG, "Received error: " + errorId);


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

  

这段代码成功地给了我一个注册ID。为了测试我的代码,我执行了一个java类来向云发送消息。那个java类是:

  public static void main(String args[]) 

    try 

        Sender sender = new Sender(
                "my server api");

        ArrayList<String> devicesList = new ArrayList<String>();

        devicesList
                .add("reg id");
        // devicesList.add("reg id");

        // Use this line to send message without payload data
        // Message message = new Message.Builder().build();

        // use this line to send message with payload data
        Message message = new Message.Builder()
                .collapseKey("1")
                .timeToLive(3)
                .delayWhileIdle(true)
                .addData("message",
                        "this text be will be seen in notification bar!!")
                .build();

        // Use this code to send to a single device
        // Result result = sender
        // .send(message,
        // "APA91bGiRaramjyohc2lKjAgFGpzBwtEmI8tJC30O89C2b3IjP1CuMeU1h9LMjKhmWuZwcXZjy1eqC4cE0tWBNt61Kx_SuMF6awzIt8WNq_4AfwflaVPHQ0wYHG_UX3snjp_U-5kJkmysdRlN6T8xChB1n3DtIq98w",
        // 1);

        // Use this for multicast messages
        MulticastResult result = sender.send(message, devicesList, 1);
        sender.send(message, devicesList, 1);

        System.out.println(result.toString() + "\n");
        if (result.getResults() != null) 
            int canonicalRegId = result.getCanonicalIds();
            if (canonicalRegId != 0) 
                System.out.println(canonicalRegId);
            
         else 
            int error = result.getFailure();
            System.out.println(error);
        
     catch (Exception e) 
        e.printStackTrace();
    

  

现在的问题是我没有收到任何推送通知或日志猫消息。在此先感谢您的帮助。 清单:

sdk 安卓:m​​inSdkVersion="8" android:targetSdkVersion="16" />

<permission
    android:name="com.sagar.gcma.permission.C2D_MESSAGE"
    android:protectionLevel="signature" />

<uses-permission android:name="com.sagar.gcma.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".PushAndroidActivity"
        android:label="@string/title_activity_push_android" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <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="com.sagar.gcma" />
        </intent-filter>
    </receiver>

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

【问题讨论】:

发布您的清单文件。也许广播接收器声明有问题或其他什么 服务器端设置可能有问题。 @almaz_from_kazan:查看我的编辑 @SahilMahajanMj:我没有服务器部分。所以我只是使用那个 java 类来发送消息。 也许您忘记在清单文件中声明 GCMIntentService? &lt;service android:name=".GCMIntentService" /&gt; 【参考方案1】:

我终于找到了原因。我公司的防火墙阻止了来自 GCM 的所有消息。所以我只是删除了防火墙并能够接收来自 GCM . Go through this link to know more about firewall issues 的消息

希望将来能对某人有所帮助。

【讨论】:

你好@chubbi 我在我的组织中早些时候遇到过防火墙问题。我打开了端口 5258,29,30。现在我可以从 GCM 服务器接收 regId,但我仍然无法收到推送通知。在其他网络上收到 PN,但是当我使用组织的 wifi n/w 时,没有收到 PN。是否还有更多需要打开的端口。我只是不明白,如果我能够接收 regId,接收推送通知会出现什么问题?【参考方案2】:

尝试从您的服务器 ping google.com。如果不成功,请尝试调查您的服务器配置。

例如检查你的 /etc/resolv.conf 看看你有没有:

nameserver 8.8.8.8
nameserver 8.8.4.4

【讨论】:

以上是关于为啥 GCM 不在 android 设备中提供推送通知?的主要内容,如果未能解决你的问题,请参考以下文章

Android GCM 注册失败。为啥?

设备如何接收 Android GCM 推送通知?

某些 android 设备未收到 GCM 推送通知

推送示例android gcm,已注册设备但未收到推送通知

如何使用 GCM 在 android 设备上分别显示每个推送通知

使用 GCM、PHP 和 MySQL 的 Android 推送通知