简体   繁体   中英

Not receiving push notification using GCM

I am implementing push notification using GCM.I m getting the token and instance id successfully, the server is also returning success on sending the notification but im unable to reveive notification on my phone. Please help!!!

Below is my code

Android Manifest:

 <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.appname"
        android:versionCode="1"
        android:versionName="1.0">

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

        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
        <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

        <!-- [START gcm_permission] -->
        <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
        <uses-permission android:name="android.permission.WAKE_LOCK" />
        <!-- [END gcm_permission] -->

        <permission android:name="com.example.appname.permission.C2D_MESSAGE"
            android:protectionLevel="signature" />
        <uses-permission android:name="com.example.appname.permission.C2D_MESSAGE" />


        <supports-screens
            android:anyDensity="true"
            android:largeScreens="true"
            android:normalScreens="true"
            android:smallScreens="true" />



        <application
            android:allowBackup="true"
            android:icon="@drawable/appicon"
            android:label="@string/app_name"
            android:theme="@style/Theme.AppCompat.NoActionBar">
            <activity
                android:name=".Outlet.Activities.SplashActivity"
                android:label="@string/app_name"
                android:screenOrientation="portrait">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />

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

                <intent-filter>
                    <action android:name="gcm_test_app_notification_click_action"/>
                    <category android:name="android.intent.category.DEFAULT"/>
                </intent-filter>
            </activity>

            <activity
                android:name=".Outlet.Activities.LoginActivity"
                android:screenOrientation="portrait" />



            <service
                android:name="com.paypal.android.sdk.payments.PayPalService"
                android:exported="false" />

            <activity android:name="com.paypal.android.sdk.payments.PaymentActivity" />
            <activity android:name="com.paypal.android.sdk.payments.LoginActivity" />
            <activity android:name="com.paypal.android.sdk.payments.PaymentMethodActivity" />
            <activity android:name="com.paypal.android.sdk.payments.PaymentConfirmActivity" />
            <activity
                android:name="io.card.payment.CardIOActivity"
                android:configChanges="keyboardHidden|orientation" />
            <activity android:name="io.card.payment.DataEntryActivity" />

            <!-- [START gcm_receiver] -->
            <receiver
                android:name="com.google.android.gms.gcm.GcmReceiver"
                android:exported="true"
                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.example.appname" />
                    <!--<category android:name="gcm.play.android.samples.com.gcmquickstart" />-->
                </intent-filter>
            </receiver>
            <!-- [END gcm_receiver] -->

            <!-- [START gcm_listener] -->
            <service
                android:name="com.example.appname.CommonFiles.Push.MyGcmListenerService"
                android:exported="false" >
                <intent-filter>
                    <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                </intent-filter>
            </service>
            <!-- [END gcm_listener] -->
            <!-- [START instanceId_listener] -->
            <service
                android:name="com.example.appname.CommonFiles.Push.MyInstanceIDListenerService"
                android:exported="false">
                <intent-filter>
                    <action android:name="com.google.android.gms.iid.InstanceID"/>
                </intent-filter>
            </service>
            <!-- [END instanceId_listener] -->
            <service
                android:name="com.example.appname.CommonFiles.Push.RegistrationIntentService"
                android:exported="false">
            </service>

        </application>

    </manifest>

GCMIntentservice class:-

public class MyGcmListenerService extends GcmListenerService {

    private static final String TAG = "MyGcmListenerService";

    public static final int MESSAGE_NOTIFICATION_ID = 435345;

    /**
     * Called when message is received.
     *
     * @param from SenderID of the sender.
     * @param data Data bundle containing message data as key/value pairs.
     *             For Set of keys use data.keySet().
     */
    // [START receive_message]
    @Override
    public void onMessageReceived(String from, Bundle data) {
        String message = data.getString("message");
        Log.d(TAG, "From: " + from);
        Log.d(TAG, "Message: " + message);

        if (from.startsWith("/topics/")) {
            // message received from some topic.

        } else {
            // normal downstream message.
        }

        // [START_EXCLUDE]
        /**
         * Production applications would usually process the message here.
         * Eg: - Syncing with server.
         *     - Store message in local database.
         *     - Update UI.
         */

        /**
         * In some cases it may be useful to show a notification indicating to the user
         * that a message was received.
         */
        sendNotification(message);
        // [END_EXCLUDE]
    }
    // [END receive_message]

    /**
     * Create and show a simple notification containing the received GCM message.
     *
     * @param message GCM message received.
     */
    private void sendNotification(String message) {
        Intent intent = new Intent(this, LoginActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);

        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.ic_launcher)
                .setContentTitle("GCM Message")
                .setContentText(message)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        notificationManager.notify(MESSAGE_NOTIFICATION_ID /* ID of notification */, notificationBuilder.build());
    }
}

RegisterIntentService:-

public class RegistrationIntentService extends IntentService {

    private static final String TAG = "RegIntentService";
    private static final String[] TOPICS = {"global"};

    UserSession userSession;

    public RegistrationIntentService() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);

        userSession=new UserSession(this);

        try {
            // [START register_for_gcm]
            // Initially this call goes out to the network to retrieve the token, subsequent calls
            // are local.
            // [START get_token]
            InstanceID instanceID = InstanceID.getInstance(this);
            // R.string.gcm_defaultSenderId (the Sender ID) is typically derived from google-services.json.
            // See https://developers.google.com/cloud-messaging/android/start for details on this file.
            String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
                    GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);

            userSession.saveGCMToken(token);

            // [END get_token]
            Log.i(TAG, "GCM Registration Token: " + token);

            // TODO: Implement this method to send any registration to your app's servers.
            sendRegistrationToServer(token);

            // Subscribe to topic channels
            subscribeTopics(token);

            // You should store a boolean that indicates whether the generated token has been
            // sent to your server. If the boolean is false, send the token to your server,
            // otherwise your server should have already received the token.
            sharedPreferences.edit().putBoolean(QuickstartPreferences.SENT_TOKEN_TO_SERVER, true).apply();

            // [END register_for_gcm]
        } catch (Exception e) {
            Log.d(TAG, "Failed to complete token refresh", e);
            // If an exception happens while fetching the new token or updating our registration data
            // on a third-party server, this ensures that we'll attempt the update at a later time.
            sharedPreferences.edit().putBoolean(QuickstartPreferences.SENT_TOKEN_TO_SERVER, false).apply();
        }
        // Notify UI that registration has completed, so the progress indicator can be hidden.
        Intent registrationComplete = new Intent(QuickstartPreferences.REGISTRATION_COMPLETE);
        LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
    }

    /**
     * Persist registration to third-party servers.
     *
     * Modify this method to associate the user's GCM registration token with any server-side account
     * maintained by your application.
     *
     * @param token The new token.
     */
    private void sendRegistrationToServer(String token) {
        // Add custom implementation, as needed.

        GCMHelper gcmHelper = new GCMHelper(this);

        gcmHelper.checkRegisterDevice();
    }

    /**
     * Subscribe to any GCM topics of interest, as defined by the TOPICS constant.
     *
     * @param token GCM token
     * @throws IOException if unable to reach the GCM PubSub service
     */
    // [START subscribe_topics]
    private void subscribeTopics(String token) throws IOException {
        GcmPubSub pubSub = GcmPubSub.getInstance(this);
        for (String topic : TOPICS) {
            pubSub.subscribe(token, "/topics/" + topic, null);
        }
    }
    // [END subscribe_topics]

}

You have write in manifest

<permission android:name="com.example.gcm.permission.C2D_MESSAGE"
            android:protectionLevel="signature" />
<uses-permission android:name="com.example.gcm.permission.C2D_MESSAGE" />

where com.example is your package name.

But your application package name is com.example.appname

So, you have to write

<permission android:name="com.example.appname.permission.C2D_MESSAGE"
            android:protectionLevel="signature" />
 <uses-permission android:name="com.example.appname.permission.C2D_MESSAGE" />

Change the permission like below and check

<!-- Creates a custom permission so only this app can receive its messages. --> 
    <permission android:name="YOUR_PACKAGE_NAME.permission.C2D_MESSAGE" android:protectionLevel="signature" /> 
    <uses-permission android:name="YOUR_PACKAGE_NAME.permission.C2D_MESSAGE" /> 
    <!-- This app has permission to register and receive data message. -->
     <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

I have got the soluion to my problem.

Firstly,Corrected these permissions in my app although these do not create problem with new vesrions

 <permission
    android:name="com.example.appname.permission.C2D_MESSAGE"
                                android:protectionLevel="signature" />

        <uses-permission android:name="com.example.appname.permission.C2D_MESSAGE" />

Second,The problem was wifi privacy. When I used my company wifi, I coudn't receive message in mobile, since they were blocked GCM server port .

You can use to following links to implement GCM effectively:

https://developers.google.com/cloud-messaging/ https://github.com/codepath/android_guides/wiki/Google-Cloud-Messaging

Happy Coding :)

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