1

I am new to push notifications and I'm trying to send a push notification to a particular device which has already been registered to GCM service. I implemented my app according to this example and modified accordingly in my program. However, I am not able to receive push notifications on the device.

Here is my code:

package com.markattendence.activites;

import static com.markattendence.activites.CommonUtilities.DISPLAY_MESSAGE_ACTION;
import static com.markattendence.activites.CommonUtilities.EXTRA_MESSAGE;
import static com.markattendence.activites.CommonUtilities.SENDER_ID;

import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.content.WakefulBroadcastReceiver;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gcm.GCMRegistrar;
import com.markattendence.activites.MainActivity.YourAsyncTaskLogin;
import com.markattendence.markattendence.R;

public class NotificationActivity extends Activity {
// label to display gcm messages
TextView lblMessage;

// Asyntask
AsyncTask<Void, Void, Void> mRegisterTask;

// Alert dialog manager
AlertDialogManager alert = new AlertDialogManager();

// Connection detector
ConnectionDetector cd;

private String userFName;

private String latitude;

private String longitude;
private static String KEY_SUCCESS = "success";
private static String KEY_ERROR = "error";
private static String KEY_ERROR_MSG = "error_msg";
private static String KEY_UID = "uid";
private static String KEY_FNAME = "fname";
private static String KEY_EMAIL = "email";
private static String KEY_LNAME = "lname";

UserFunctions userFunction;
private JSONObject json;

public static String name;
public static String email;

SharedPreferences prefs;
public static final String MyPREFERENCES = "MyPrefs";

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_notification);

    cd = new ConnectionDetector(getApplicationContext());
    prefs = getSharedPreferences(MyPREFERENCES, Context.MODE_PRIVATE);

    if (prefs.contains("message")) {
        lblMessage.setText(prefs.getString("message", ""));

    }

    // Check if Internet present
    if (!cd.isConnectingToInternet()) {
        // Internet Connection is not present
        alert.showAlertDialog(NotificationActivity.this,
                "Internet Connection Error",
                "Please connect to working Internet connection", false);
        // stop executing code by return
        return;
    }

    // Getting name, email from intent
    Intent i = getIntent();

    name = i.getStringExtra("uFName");
    userFName = i.getStringExtra("uFName");
    email = i.getStringExtra("email");
    latitude = i.getStringExtra("latitude");
    longitude = i.getStringExtra("longitude");

    // Make sure the device has the proper dependencies.
    GCMRegistrar.checkDevice(this);

    // Make sure the manifest was properly set - comment out this line
    // while developing the app, then uncomment it when it's ready.
    GCMRegistrar.checkManifest(this);

    lblMessage = (TextView) findViewById(R.id.lblMessage);

    registerReceiver(mHandleMessageReceiver, new IntentFilter(
            DISPLAY_MESSAGE_ACTION));

    // Get GCM registration id
    final String regId = GCMRegistrar.getRegistrationId(this);

    // Check if regid already presents
    if (regId.equals("")) {
        // Registration is not present, register now with GCM
        GCMRegistrar.register(this, 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;
                }

            };
            mRegisterTask.execute(null, null, null);
        }
    }
    if(name != null){
    userFunction = new UserFunctions();
    new YourAsyncTaskLogin().execute();
    }
}

/**
 * Receiving push messages
 * */
private final WakefulBroadcastReceiver mHandleMessageReceiver = new WakefulBroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        ComponentName comp = new ComponentName(context.getPackageName(),
                GCMIntentService.class.getName());
        // Start the service, keeping the device awake while it is launching.
        startWakefulService(context, (intent.setComponent(comp)));
        setResultCode(Activity.RESULT_OK);

        String newMessage = intent.getExtras().getString(EXTRA_MESSAGE);
        // Waking up mobile if it is sleeping
        WakeLocker.acquire(getApplicationContext());

        /**
         * Take appropriate action on this message depending upon your app
         * requirement For now i am just displaying it on the screen
         * */

        // Showing received message
        lblMessage.append(newMessage + "\n");
        Toast.makeText(getApplicationContext(),
                "New Message: asd" + newMessage, Toast.LENGTH_LONG).show();

        prefs = context.getSharedPreferences(MyPREFERENCES,
                Context.MODE_PRIVATE);
        Editor editor = prefs.edit();
        editor.putString("message", lblMessage.getText().toString());
        editor.commit();
        // Releasing wake lock
        WakeLocker.release();
    }
};

@Override
protected void onDestroy() {
    if (mRegisterTask != null) {
        mRegisterTask.cancel(true);
    }
    try {
        unregisterReceiver(mHandleMessageReceiver);
        GCMRegistrar.onDestroy(this);
    } catch (Exception e) {
        Log.e("UnRegister Receiver Error", "> " + e.getMessage());
    }
    super.onDestroy();
}

class YourAsyncTaskLogin extends AsyncTask<Void, Void, Void> {

    private ProgressDialog _ProgressDialog;
    private String userId;

    @Override
    protected void onPreExecute() {
        // show your dialog here

        _ProgressDialog = ProgressDialog.show(NotificationActivity.this,
                "", "Loading", true);

    }

    @Override
    protected Void doInBackground(Void... params) {

        try {

            json = userFunction.sendMessage(userFName,
                    " has marked attendence of ", "CheckIN", latitude,
                    longitude);
            /*
             * HttpClient Client = new DefaultHttpClient(); String
             * SetServerString = "";
             * 
             * // Create Request to server and get response
             * 
             * HttpGet httpget = new HttpGet(
             * "http://wibman.com/pnt/send_message.php?message=" + name +
             * "checked in&Latitude=" + latitude + "&Longitude=" +
             * longitude); ResponseHandler<String> responseHandler = new
             * BasicResponseHandler(); SetServerString =
             * Client.execute(httpget, responseHandler);
             */

            // Show response on activity

            // content.setText(SetServerString);
        } catch (Exception ex) {
            ex.printStackTrace();
            // content.setText("Fail!");
        }
        return null;
    }

    protected void onPostExecute(Void result) {

        try {
            Log.e("aaaaaaaaaaaaaaaaaaaaaaaaaaa",
                    json.getString(KEY_SUCCESS));
            if (json.getString(KEY_SUCCESS) != null) {
                // loginErrorMsg.setText("");
                String res = json.getString(KEY_SUCCESS);

                if (Integer.parseInt(res) == 1) {
                    /*userId = json.getString(KEY_UID);
                    userFName = json.getString(KEY_FNAME);

                    userFName.replace("\"", "");

                    userId.replace("\"", "");

                    Log.e("uid=aaa", userId);
                    Log.e("nameuser", userFName);*/

                    Intent dashboard = new Intent(getApplicationContext(),
                            MainActivity.class);

                    // Close all views before launching
                    // Dashboard
                    startActivity(dashboard);

                    // Close Login Screen
                    finish();

                } else {
                    // Error in login
                    // loginErrorMsg.setText("Incorrect username/password");

                    _ProgressDialog.cancel();

                    alert.showAlertDialog(NotificationActivity.this,
                            "Attendence Failed..",
                            "Mark Attendence Failed.", false);
                    // loginStatusTxtView.setText("Incorrect username/password");
                }

            } else {
                // Error in login
                // loginErrorMsg.setText("Incorrect username/password");

                _ProgressDialog.cancel();

                alert.showAlertDialog(NotificationActivity.this,
                        "Attendence Failed..", "Mark Attendence Failed.",
                        false);
                // loginStatusTxtView.setText("Incorrect username/password");
            }
        } catch (JSONException e) {
            e.printStackTrace();
            Log.e("error", e.getMessage());
        }

        _ProgressDialog.dismiss();

    }
}

 }

Manifest.xml

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

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

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<!-- 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" />

<!-- Creates a custom permission so only this app can receive its messages. -->
<permission
    android:name="com.markattendence.markattendence.permission.C2D_MESSAGE"
    android:protectionLevel="signature" />

<uses-permission android:name="com.markattendence.markattendence.permission.C2D_MESSAGE" />
<uses-permission android:name="com.markattendence.activites.permission.C2D_MESSAGE" />

<!-- This app has permission to register and receive data message. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

<!-- Network State Permissions to detect Internet status -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<!-- Permission to vibrate -->
<uses-permission android:name="android.permission.VIBRATE" />

<uses-feature android:name="android.hardware.camera" />
<uses-feature
    android:name="android.hardware.camera.front"
    android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" />

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<application
    android:allowBackup="true"
    android:icon="@drawable/mmes_logo"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="com.markattendence.markattendence.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name="com.markattendence.markattendence.MarkAttendenceActivity" >
    </activity>
    <activity android:name="com.markattendence.markattendence.NotificationActivity" >
    </activity>

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

            <!-- Receives the actual messages. -->
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <!-- Receives the registration id. -->
            <action android:name="com.google.android.c2dm.intent.REGISTRATION" />

            <category android:name="com.markattendence.markattendence" />
        </intent-filter>
    </receiver>

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

I am having a problem in receiving the notification. Server side code is working correctly.

My log cat says:

{"multicast_id":5884981605957538237,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1393495991926450%978fee92f9fd7ecd"}]}

The major problem is that, if device has the example app it get notification in that application rather than my customized application. And if I remove that application i don't get any notification. So i am confused that notification has to be received in my app rather than that of androidhive application but push notification is displayed in androidhive application. Please help me to solve this issue. Thanks in advance.

Himanshu Agarwal
  • 4,623
  • 5
  • 35
  • 49
  • i am also developing chat base application in android using XMPP, and i have to implement notification. for example when a user-A send a friend request user-B then the notification goes to user-B and same case when a one user like a picture to user xyz the notification send to that user \. will u please guide me how could i implement that. i am able to get friend from roster and get only online friends and also messaging implemented. – Ali Ashiq Sep 15 '14 at 07:38
  • need help http://stackoverflow.com/questions/35812304/pushnotification-not-working-properly – albert Mar 05 '16 at 09:29
  • If you use Firebase, check that you actually did send the message to Android apps – onmyway133 Feb 05 '19 at 14:35

3 Answers3

2

For sending the push to a specific device. First of all you need to pick the token from the FCM :

String token = FirebaseInstanceId.getInstance().getToken();

Then this unique token is used to send the push request from server post request. Please find the headers of the post request along with required structure of the body.

Headers

Content-Type     'application/json'
Authorization    'key=(server-key)'

Note: Not other than these values are allowed in headers. And here the 'server-key' is your browser key provide from FCM console.

Body For Push Request

{
  "data": {
    "NotificationDetailsID": 1131,
    "MessageGroup": "HR",
    "Message": "this is notification"
  },
  "to": "firebase-token-of-androidDevice"
}

This is the server side implementation and this will definitely work. As we have tested at our end. You will receive the push while the app is even closed.

Manmohan Soni
  • 6,472
  • 2
  • 23
  • 29
1

You have some errors in your manifest that only cause problems on old Android versions :

Your packagge name is com.markattendence.markattendence.

Therefore you should change this :

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

To this:

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

And this:

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

        <!-- Receives the actual messages. -->
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <!-- Receives the registration id. -->
        <action android:name="com.google.android.c2dm.intent.REGISTRATION" />

        <category android:name="com.markattendence.activites" />
    </intent-filter>
</receiver>

To this:

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

        <!-- Receives the actual messages. -->
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <!-- Receives the registration id. -->
        <action android:name="com.google.android.c2dm.intent.REGISTRATION" />

        <category android:name="com.markattendence.markattendence" />
    </intent-filter>
</receiver>
Eran
  • 387,369
  • 54
  • 702
  • 768
  • This give error : 02-27 18:38:20.033: E/AndroidRuntime(18666): java.lang.RuntimeException: Unable to instantiate service com.markattendence.markattendence.GCMIntentService: java.lang.ClassNotFoundException: com.markattendence.markattendence.GCMIntentService – Himanshu Agarwal Feb 27 '14 at 13:13
  • @user3360307 Perhaps your GCMIntentService class is in a different package. You should put it in com.markattendence.markattendence – Eran Feb 27 '14 at 13:20
  • My package structre is src -> com.markattendence.activities This package contains all classes. – Himanshu Agarwal Feb 27 '14 at 13:26
  • 1
    @user3360307 Your main package as defined in your manifest is `com.markattendence.markattendence`. The GCMBroadcastReceiver class you are using is looking for GCMIntentService in that main package. You should either change the packages declared in your manifest or change the receiver class (by creating a new class inheriting from this class) to specify where to find the GCMIntentService. – Eran Feb 27 '14 at 15:00
  • I updated that but still i am not getting any notification. And log cat says: {"multicast_id":8576925643238404960,"success":1,"failure":0,"canonical_ids":0,"results": [{"message_id":"0:1393563435884942%978fee92f9fd7ecd"}]} – Himanshu Agarwal Feb 28 '14 at 05:01
  • can you please help me out from this problem. It would be great help for your support. Thanks in advance. Please solve this problem of mine. – Himanshu Agarwal Feb 28 '14 at 10:06
  • @user3360307 The server response shows there is no problem in the server, so the problem is in the app. I don't know what you updated. Can you update your question with the current version of the manifest and the package where the intent service is located? – Eran Feb 28 '14 at 23:22
  • Please check updated manifest of my app. The package structure is : 'src-com.markattendence.markattendence.*' this package contain all classes and services. – Himanshu Agarwal Mar 01 '14 at 06:21
  • @user3360307 I don't see the point of this line - ``. Do you get any errors now in the logcat? In your first comment your only error was the location of GCMIntentService. If you fixed that, it should work. – Eran Mar 01 '14 at 21:15
  • yes GCMIntentService error is resolved but problem now is that i get notification only when if i had androidhive application (demo Example for push notification) and notification open in androidhive application not in mine. and if i remove that application i don't get any notification. – Himanshu Agarwal Mar 03 '14 at 08:10
0

IF you could send a notification and configure a GCM so the problem should be with network. Try to look if your ports are not blocked for notification (I had similar problem - I could send but not receive notification after unlocking ports I received notifications).

Unii
  • 1,587
  • 15
  • 33
  • Ports are not blocked I already checked that answer and found everything is correct with network. and when i run the androidhive example it works correctly and I get notification for that application but when i implement in mine its not working – Himanshu Agarwal Feb 27 '14 at 12:22
  • Did you unlock on GCM sending notifications? – Unii Feb 27 '14 at 12:27
  • what do mean by that ? – Himanshu Agarwal Feb 27 '14 at 12:51
  • In developer console you should look at GCM cloud and turn it on. Using GSM means to login to google to developer console and unlock some options. – Unii Feb 27 '14 at 13:15