How to push notifications with Google Cloud Messaging? - android

I'm trying to implement push notification in an Android app.
As I understand, we need a sender and receiver installed on the device.
I googled on GCM an found that I need to create a Project in Google dev console.
I got a project ID and an API key.
I found there are third party applications (mixpanel) which can send
push notifications with the information above. Can I use Google Play to
send notifications to all app users?
On the programming side, I got permissions required in the Manifest.xml file
<uses-permission android:name="android.permission.INTERNET" />
<!-- GCM connects to Internet 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" />
<!-- Creates a custom permission so only this app can receive its messages. -->
<permission
android:name="com.androidexample.gcm.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.androidexample.gcm.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" />
And a broadcast receiver
<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.androidexample.gcm" />
</intent-filter>
</receiver>
<service android:name="com.androidexample.gcm.GCMIntentService" />
From here on, I got confused about the "sender" and "receiver" parts.
Do I have to implement GCMBroadcastReceiver?
If I want to implement only the Receiving notification part, how does it look like ?
Any reference to a working code example will be good.

Yes, you have to implement GcmBroadcastReceiver class to catch messages from GCM service. The purpose of the receiver is to start the intent service even if the app is off. Here is the most common implementation:
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);
}
}
The purpose of the intent service is doing something with the caught GCM message:
public class GCMIntentService extends IntentService {
#Override
protected void onHandleIntent(Intent intent) {
// Getting GCM message fields
Bundle extras = intent.getExtras();
// Doing something with the message.
// E.g. showing push notification
}
}
You can see e.g. this article for details.

Related

save data in local storage in notification arrives when app is not running yet in android

I have a problem in storing data locally when push notification arrives and the app is not running. It works fine when the app is running or in background.
just check this thing inside manifest .. this permission
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/><uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<permission android:name="net.simplifiedcoding.androidgcm.permission.C2D_MESSAGE" android:protectionLevel="signature"/>
<uses-permission android:name="net.simplifiedcoding.androidgcm.permission.C2D_MESSAGE"/>
<application>
<!-- GCM Receiver -->
-<receiver android:name="com.google.android.gms.gcm.GcmReceiver" android:permission="com.google.android.c2dm.permission.SEND" android:exported="true">-<intent-filter><action android:name="com.google.android.c2dm.intent.RECEIVE"/><category android:name="com.gnirt69.gcmexample"/></intent-filter></receiver>
<!-- GCM Receiver Service -->
-<service android:name=".GCMPushReceiverService" android:exported="false">-<intent-filter><action android:name="com.google.android.c2dm.intent.RECEIVE"/></intent-filter></service>
<!-- GCM Registration Intent Service -->
-<service android:name=".GCMRegistrationIntentService" android:exported="false">-<intent-filter><action android:name="com.google.android.gms.iid.InstanceID"/></intent-filter></service>-<receiver android:name=".GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND">-<intent-filter>
<!-- Receives the actual messages. -->
<action android:name="com.google.android.c2dm.intent.RECEIVE"/><category android:name="com.google.android.gcm.demo.app"/></intent-filter></receiver>

After completely close the app, unable to receive notification from gcm

I have researching for hour and hour and found many similar question but have no a working solution for my question.
I'm understand if I close the app by force close that is normal that I not receive data from gcm. But I was unable to receive the notification with gcm until I start the app. So the application is running either foreground or background then I only be able to receive the data from gcm but when I close the app by sliding away it (which is not done by force close) the notification didn't show up which mean gcm wasn't receive any data at all. . So it mean I need to stay active but if I do so then there is no point for using gcm anymore which design for pushing notification.
Here is my manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.khooteckwei.google" >
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<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="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="com.example.gcmtesting.google.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.gcmtesting.google.permission.C2D_MESSAGE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".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>
<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="com.example.gcmtesting.google" />
</intent-filter>
</receiver>
<service android:name=".GcmIntentService" />
</application>
</manifest>
here is the wakefulBroadcastReceiver
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Explicitly specify that GcmIntentService will handle the 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);
}
}
The notification working fine when the app is active so I didn't include the function that use to display notification.Is there any problem with this 2 pages?
I think your problem is in your GcmBroadcastReceiver receiver, you can look at this link , I think it's will help you with GCM http://www.intertech.com/Blog/push-notifications-tutorial-for-android-using-google-cloud-messaging-gcm/
I think notifications doesn't work because your receiver doesn't check do your app running or not , if it is you need to handle notification or if not show android notification

Location Based Push Notifications For Android

Is there anyways in sending a location based push notification for android devices with out using a third party push notification service such as Parse? I would like to send push notification to my users without the annoyance of getting a notification that doesn't relate to that specific user because they are not in a certain area. Also, I could get the users location based on a time interval but I would rather do it a different way then that, if possible.
Yes, this is entirely possible, as long as I'm correctly interpreting what you are asking.
To accomplish this, you would send the GCM push notification to all of your users (unless you had a way, server-side of filtering some of them out). Then in your application, instead of just creating a Notification and passing it to the notification manager, you would first use the LocationManager (or the newer LocationServices API) to determine if the user is within the proper location first, and then just discard the GCM notification if they're not.
You'll need to take care of several things in order to do this:
Your AndroidManifest.xml will require several permission changes, both for the GCM changes, and for the Location access:
<!-- Needed for processing notifications -->
<permission android:name="com.myappname.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.myappname.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!-- Needed for Location -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
You'll also need to set up a Notification Receiver in the <application> section of the manifest:
<receiver android:name="com.myappname.NotificationReceiver" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.myappname" />
</intent-filter>
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.myappname" />
</intent-filter>
</receiver>
In addition, you'll need write your NotificationReceiver java class, and override the onReceive function:
public class NotificationReceiver extends BroadcastReceiver {
public void onReceive(final Context context, final Intent intent) {
if ("com.google.android.c2dm.intent.REGISTRATION".equals(intent.getAction())) {
handleRegistration(context, intent); // you'll have to write this function
} else if ("com.google.android.c2dm.intent.RECEIVE".equals(intent.getAction())) {
// the handle message function will need to check the user's current location using the location API you choose, and then create the proper Notification if necessary.
handleMessage(context, intent);
}
}

onRegistered() from GCMIntentService never called

I am trying to register my app on GCM but I don't know why my app is never registered. GCMRegistrar.register(this, SENDER_ID); is called but onRegistered() from my GCMIntentService is never called. I don't know WHY.
This is my Logcat
01-17 11:03:00.015: D/GCMRegistrar(3509): resetting backoff for com.abc.xyz.ui.activity
01-17 11:03:03.210: V/GCMRegistrar(3509): Registering app com.abc.xyz.ui.activity of senders 964256581311
01-17 11:03:06.070: V/GCMBroadcastReceiver(3509): onReceive: com.google.android.c2dm.intent.REGISTRATION
01-17 11:03:06.070: V/GCMBroadcastReceiver(3509): GCM IntentService class: com.abc.xyz.ui.activity.GCMIntentService
01-17 11:03:06.070: V/GCMBaseIntentService(3509): Acquiring wakelock
and this is my complete manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.abc.xyz.ui.activity"
android:versionCode="1"
android:versionName="1.5.6" xmlns:android="http://schemas.android.com/apk/res/android">
<uses-sdk
android:minSdkVersion="11" android:targetSdkVersion="16"/>
<uses-feature
android:name="android.hardware.usb.host"/>
<!-- This app has permission to register and receive data message. -->
<uses-permission
android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission
android:name="android.permission.INTERNET" />
<uses-permission
android:name="android.permission.READ_PHONE_STATE" />
<uses-permission
android:name="android.permission.GET_TASKS" />
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission
android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission
android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission
android:name="android.permission.CALL_PHONE" />
<uses-permission
android:name="android.permission.BLUETOOTH" />
<!-- 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.
NOTE: the permission *must* be called PACKAGE.permission.C2D_MESSAGE,
where PACKAGE is the application's package name.
-->
<uses-permission
android:name="com.abc.xyz.ui.activity.permission.C2D_MESSAGE" />
<permission
android:name="com.abc.xyz.ui.activity.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#android:style/Theme.Holo.Light"
android:name="com.abc.xyz.MyApplication"
android:allowBackup="false">
<activity
android:name=".StartupActivity"
android:noHistory="true"
android:label="#string/title_startup_screen"
android:configChanges="orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".LoginActivity"
android:windowSoftInputMode="stateAlwaysVisible|adjustResize"
android:label="#string/title_login_screen"
android:configChanges="orientation">
</activity>
//my other activity defination
<!--
BroadcastReceiver that will receive intents from GCM
services and handle them to the custom IntentService.
The com.google.android.c2dm.permission.SEND permission is necessary
so only GCM services can send data messages for the app.
-->
<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.abc.xyz.ui.activity" />
</intent-filter>
</receiver>
<!--
Application-specific subclass of GCMBaseIntentService that will
handle received messages.
By default, it must be named .GCMIntentService, unless the
application uses a custom BroadcastReceiver that redefines its name.
-->
<service android:name="com.abc.xyz.ui.activity.GCMIntentService" />
</application>
</manifest>
I don't know what is wrong and why onRegistered() is never called. Any help will be appreciated.
I figured out in another post what is the problem. My GCMIntentService Class was defined in my manifest as
<service android:name="MY_PACKAGE.gcm.GCMIntentService" />
because I didn't want to put this class at the root package, instead I put at MY_PACKAGE.gcm". This seems to cause a problem and as the documentation says,
Add the following intent service
<service android:name=".GCMIntentService" />
So when I moved to the root package it worked! There is another way to put the GCMIntentServiceSubclass wherever you want and name it differently. You should subclass GCMBroadcastReceiver and do the changes in manifest and in the subclass as shown in this other post.
I answer because pasting code is barely readable in comments:
I am missing some logs from your logcat that suggest your service is even called. I have this in my Logcat when registering:
GCMBroadcastReceiver V onReceive: com.google.android.c2dm.intent.REGISTRATION
GCMBroadcastReceiver V GCM IntentService class: com.package.android.app.GCMIntentService
GCMBaseIntentService V Acquiring wakelock
GCMBaseIntentService V Intent service name: GCMIntentService-DynamicSenderIds-1
Especially the last line is missing or you have forgotten to paste it. Could you make sure that you posted the complete LogCat? Filter for GCM to make sure you didn't missed something.
Update
As the OP mentioned in the comments, he used the service to do more. This somehow interfered with the GCM functionality and after separating this into two services it worked. Lessons learned: Don't use the GCMIntentService for anything else than GCM.

Using GCM, Urban Airship to send Push Notification

I have created a sample project in Google Console. Referring the sample from this site, http://code.google.com/p/blog-samples/downloads/detail?name=gcm_sample_update1.rar&can=2&q=#makechanges I got my registration Id. Now I don't know what to do next, how I can implement push notification in my app. I want to use Urban Airship to send push to my app. I have created a app in Urban Airship, by giving the package name, API key obtained through Google console. To my server I need to send the Apid to get the messages. But i don't know how to get the Apid.
It is explained here: http://developer.android.com/guide/google/gcm/gs.html
Writing the Android Application
You have to download and add gcm libraries.
Then make changes in manifest:
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="xx"/>
and
<permission android:name="my_app_package.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="my_app_package.permission.C2D_MESSAGE" />
inserting Your package name in "my_app_package".
Add other permissions
<!-- 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" />
receiver
<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="my_app_package" />
</intent-filter>
</receiver>
Again write Your package name in "my_app_package".
Then declare your service
<service android:name=".GCMIntentService" />
You have to create a class named GCMIntentService. This class is going to handle the push notifications.
It should look like this:
class GCMIntentService extends com.google.android.gcm.GCMBaseIntentService{
public void onRegistered(Context context, String regId){}
public void onUnregistered(Context context, String regId){}
public void onError(Context context, String errorId){}
public void onMessage(Context context, Intent intent){}
}
In onMessage() you will have to handle the push message. You can use notifications.
Then in Your starting Activity you will have to put this
GCMRegistrar.checkDevice(this);
GCMRegistrar.checkManifest(this);
final String regId = GCMRegistrar.getRegistrationId(this);
if (regId.equals("")) {
GCMRegistrar.register(this, SENDER_ID);
} else {
Log.v(TAG, "Already registered");
}
in onCreate().
SENDER_ID is the String containing all numbers that you got from the google console.
Well.. There are 3 steps to get APID
1. Run the application
2. Open logcat
3. Find the APID
Note first time you may get APID(Android Push ID) null so run it again you will get
If you want to use Urbanairship you have to use their SDK for user registration (look here), cause UA create a new id for each device and not using Google registration Id when pushing message using their API.
Not sure why they doing it like that but that it... =\

Categories

Resources