Android GCM basic implementation

32,907

Solution 1

this is incorrect

protected GCMIntentService( String senderId ) {         
super(senderId);}

As it states in the documentation. you must declare a PUBLIC, NO ARGUMENT constructor for GCMIntentService. Otherwise the GCMIntentService can't be instantiated properly by background intent services.

public GCMIntentService(){
super(senderID);}

the senderID can be a hard coded constant string because it will no longer change with the new GCM. It's also very important you use the correct senderID. 24 hours is long enough for yours to be active so if my above solution doesn't work you are using the incorrect senderID. Everything else looks great.

The senderID is in the URL of your web browser when you are browsing the Google API access page. Click on GCM and a 12 digit number will be present in the browser URL. That is the correct key to use. NOT your API key. That is used on the App server side.

Solution 2

I also had this ANNOYing bug, til now. The Problem was, that i declared the intentservice inside another package... even if i declared the name in the android manifest and no classnotfound exception had been place... no error at all could be found... so i made sure the intentservice is in the root package.

Solution 3

I think you have some issues in the code.

You should do the registration of your own broadcast receiver in the manifest file and that receiver will trigger the <service android:name=".GCMIntentService" />.

Therefore you must do something like I write below.

  • The receiver must be declared like:

    <receiver
        android:name="your.package.name.YourBroadCastReceiver"
        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" />
        </intent-filter>
    

  • Your broadcast receiver that will start the service.

    public class YourBroadCastReceiver extends BroadcastReceiver {
    
    @Override
     public final void onReceive(Context context, Intent intent) {
         GCMIntentService .runIntentInService(context, intent);
         setResult(Activity.RESULT_OK, null, null);
     }  
    }
    

I advice you to take a look at the official GCM documentation where you can find a good example.

And... don't forget to enable the Google Cloud Messaging service in the main Google APIs Console page.

Let me know if it helps!

Solution 4

See below tutorial for GCM:-

http://www.androidhive.info/2012/10/android-push-notifications-using-google-cloud-messaging-gcm-php-and-mysql/

Solution 5

Here I have written few steps for How to Get RegID and Notification starting from scratch

  1. Create/Register App on Google Cloud
  2. Setup Cloud SDK with Development
  3. Configure project for GCM
  4. Get Device Registration ID
  5. Send Push Notifications
  6. Receive Push Notifications

You can find complete tutorial in below URL link

Getting Started with Android Push Notification : Latest Google Cloud Messaging (GCM) - step by step complete tutorial

enter image description here

Code snip to get Registration ID (Device Token for Push Notification).

Configure project for GCM


Update AndroidManifest file

For enable GCM in our project we need to add few permission in our manifest file Go to AndroidManifest.xml and add below code Add Permission

<uses-permission android:name="android.permission.INTERNET”/>
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

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

<uses-permission android:name=“.permission.RECEIVE" />
<uses-permission android:name=“<your_package_name_here>.permission.C2D_MESSAGE" />
<permission android:name=“<your_package_name_here>.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />

Add GCM Broadcast Receiver declaration

add GCM Broadcast Receiver declaration in your application tag

<application
        <receiver
            android:name=".GcmBroadcastReceiver"
            android:permission="com.google.android.c2dm.permission.SEND" ]]>
            <intent-filter]]>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <category android:name="" />
            </intent-filter]]>

        </receiver]]>
     
<application/>

Add GCM Servie declaration

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

Get Registration ID (Device Token for Push Notification)

Now Go to your Launch/Splash Activity

Add Constants and Class Variables

private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
public static final String EXTRA_MESSAGE = "message";
public static final String PROPERTY_REG_ID = "registration_id";
private static final String PROPERTY_APP_VERSION = "appVersion";
private final static String TAG = "LaunchActivity";
protected String SENDER_ID = "Your_sender_id";
private GoogleCloudMessaging gcm =null;
private String regid = null;
private Context context= null;

Update OnCreate and OnResume methods

@Override
protected void onCreate(Bundle savedInstanceState)
{
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_launch);
     context = getApplicationContext();
         if (checkPlayServices()) 
     {
            gcm = GoogleCloudMessaging.getInstance(this);
            regid = getRegistrationId(context);

            if (regid.isEmpty())
            {
                registerInBackground();
            }
            else
            {
            Log.d(TAG, "No valid Google Play Services APK found.");
            }
      }
 }

@Override protected void onResume()
{
       super.onResume();       checkPlayServices();
}


# Implement GCM Required methods (Add below methods in LaunchActivity)

private boolean checkPlayServices() {
        int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
        if (resultCode != ConnectionResult.SUCCESS) {
            if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
                GooglePlayServicesUtil.getErrorDialog(resultCode, this,
                        PLAY_SERVICES_RESOLUTION_REQUEST).show();
            } else {
                Log.d(TAG, "This device is not supported - Google Play Services.");
                finish();
            }
            return false;
        }
        return true;
 }

private String getRegistrationId(Context context) 
{
   final SharedPreferences prefs = getGCMPreferences(context);
   String registrationId = prefs.getString(PROPERTY_REG_ID, "");
   if (registrationId.isEmpty()) {
       Log.d(TAG, "Registration ID not found.");
       return "";
   }
   int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
   int currentVersion = getAppVersion(context);
   if (registeredVersion != currentVersion) {
        Log.d(TAG, "App version changed.");
        return "";
    }
    return registrationId;
}

private SharedPreferences getGCMPreferences(Context context) 
{
    return getSharedPreferences(LaunchActivity.class.getSimpleName(),
                Context.MODE_PRIVATE);
}

private static int getAppVersion(Context context) 
{
     try 
     {
         PackageInfo packageInfo = context.getPackageManager()
                    .getPackageInfo(context.getPackageName(), 0);
            return packageInfo.versionCode;
      } 
      catch (NameNotFoundException e) 
      {
            throw new RuntimeException("Could not get package name: " + e);
      }
}


private void registerInBackground() 
{     new AsyncTask() {
     Override
     protected Object doInBackground(Object... params) 
     {
          String msg = "";
          try 
          {
               if (gcm == null) 
               {
                        gcm = GoogleCloudMessaging.getInstance(context);
               }
               regid = gcm.register(SENDER_ID);               Log.d(TAG, "########################################");
               Log.d(TAG, "Current Device's Registration ID is: "+msg);     
          } 
          catch (IOException ex) 
          {
              msg = "Error :" + ex.getMessage();
          }
          return null;
     }     protected void onPostExecute(Object result) 
     { //to do here };
  }.execute(null, null, null);
}

Note : please store REGISTRATION_KEY, it is important for sending PN Message to GCM also keep in mine this will be unique for all device, by using this only GCM will send Push Notification.

Receive Push Notifications

Add GCM Broadcast Receiver Class

As we have already declared “GcmBroadcastReceiver.java” in our Manifest file, So lets create this class update receiver class code this way

public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) 
    {        ComponentName comp = new ComponentName(context.getPackageName(),
                GcmIntentService.class.getName());        startWakefulService(context, (intent.setComponent(comp)));
        setResultCode(Activity.RESULT_OK);
        Toast.makeText(context, “wow!! received new push notification", Toast.LENGTH_LONG).show();
    }
}

Add GCM Service Class

As we have already declared “GcmBroadcastReceiver.java” in our Manifest file, So lets create this class update receiver class code this way

public class GcmIntentService extends IntentService
{     public static final int NOTIFICATION_ID = 1;     private NotificationManager mNotificationManager;     private final static String TAG = "GcmIntentService";     public GcmIntentService() {
     super("GcmIntentService");     
     }     @Override
     protected void onHandleIntent(Intent intent) {
          Bundle extras = intent.getExtras();
          Log.d(TAG, "Notification Data Json :" + extras.getString("message"));

          GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
          String messageType = gcm.getMessageType(intent);          if (!extras.isEmpty()) {          if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR
               .equals(messageType)) {
               sendNotification("Send error: " + extras.toString());
          } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED
          .equals(messageType)) {
          sendNotification("Deleted messages on server: "
          + extras.toString());          // If it's a regular GCM message, do some work.
          } else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE
          .equals(messageType)) {
          // This loop represents the service doing some work.
          for (int i = 0; i < 5; i++) {
               Log.d(TAG," Working... " + (i + 1) + "/5 @ "
               + SystemClock.elapsedRealtime());               try {
                    Thread.sleep(5000);
               } catch (InterruptedException e) {
               }
             }
             Log.i(TAG, "Completed work @ " + SystemClock.elapsedRealtime());
             sendNotification(extras.getString("message"));
           }
        }        // Release the wake lock provided by the WakefulBroadcastReceiver.
        GcmBroadcastReceiver.completeWakefulIntent(intent);
     }     // Put the message into a notification and post it.
     // This is just one simple example of what you might choose to do with
     // a GCM message.
     private void sendNotification(String msg) {          mNotificationManager = (NotificationManager) this
          .getSystemService(Context.NOTIFICATION_SERVICE);
          PendingIntent contentIntent = PendingIntent.getActivity(this, 0,          new Intent(this, LaunchActivity.class), 0);

          NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(          this)
          .setSmallIcon(R.drawable.icon)
          .setContentTitle("Ocutag Snap")
          .setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
          .setContentText(msg)
          .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE);

          mBuilder.setContentIntent(contentIntent);          mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
     }
}
Share:
32,907
Rooster242
Author by

Rooster242

Updated on July 09, 2022

Comments

  • Rooster242
    Rooster242 almost 2 years

    UPDATE: I fixed the problems in the code below so this makes a nice basic working example of how to use GCM


    So, I'm trying to implement Android GCM into my app. Here are the relevant parts I've added to the manifest:

    <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="20" />
    
    <permission
        android:name=".permission.C2D_MESSAGE"
        android:protectionLevel="signature" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <uses-permission android:name=".permission.C2D_MESSAGE" />
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
    

    ...

    <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.badbob.app.gmctestapp" />
        </intent-filter>
    </receiver>
    
    <service android:name=".GCMIntentService" />
    

    I've added the following code to the onCreate of my main activity:

        GCMRegistrar.checkDevice( this );
        GCMRegistrar.checkManifest( this );
        final String regId = GCMRegistrar.getRegistrationId( this );
        if( regId.equals( "" ) ) {
            GCMRegistrar.register( this, GCM_SENDER_ID );
        }
        else {
            Log.v( LOG_TAG, "Already registered" );
        }
    

    I've also created the GCMIntenetService class like so:

    public class GCMIntentService extends GCMBaseIntentService {
    
        private static final String LOG_TAG = "GetAClue::GCMIntentService";
    
        public GCMIntentService() {
            super( GCM_SENDER_ID );
            // TODO Auto-generated constructor stub
            Log.i( LOG_TAG, "GCMIntentService constructor called" );
        }
    
        @Override
        protected void onError( Context arg0, String errorId ) {
            // TODO Auto-generated method stub
            Log.i( LOG_TAG, "GCMIntentService onError called: " + errorId );
        }
    
        @Override
        protected void onMessage( Context arg0, Intent intent ) {
            // TODO Auto-generated method stub
            Log.i( LOG_TAG, "GCMIntentService onMessage called" );
            Log.i( LOG_TAG, "Message is: " + intent.getStringExtra( "message" ) );
        }
    
        @Override
        protected void onRegistered( Context arg0, String registrationId ) {
            // TODO Auto-generated method stub
            Log.i( LOG_TAG, "GCMIntentService onRegistered called" );
            Log.i( LOG_TAG, "Registration id is: " + registrationId );
        }
    
        @Override
        protected void onUnregistered( Context arg0, String registrationId ) {
            // TODO Auto-generated method stub
            Log.i( LOG_TAG, "GCMIntentService onUnregistered called" );
            Log.i( LOG_TAG, "Registration id is: " + registrationId );
        }
    }
    

    When I run this I get this in LogCat:

    07-11 11:28:46.340: V/GCMRegistrar(27435): Registering receiver
    07-11 11:28:46.370: D/GCMRegistrar(27435): resetting backoff for com.badbob.app.getacluebeta
    07-11 11:28:46.380: V/GCMRegistrar(27435): Registering app com.badbob.app.getacluebeta of senders 128205395388
    

    From what I've gleaned from other posts I should get a registration ID in LogCat but I"m not. Also onRegistered() in GCMIntentService never gets called. So what am I doing wrong?