I have developed a push notification application in Android from this tutorial:push notification in android app. The register button is displayed when I run the app. When I click on the register button, and when registration is successful, a notification is displayed on my device.
How can I include it in my own app? My app has one xml parsing example app. Here when any new item is added, I wish to display (the new order is displayed ) a notification message on the device. It is automatically generated here.
I am posting demo application of Google Cloud Messaging.
Make sure you create demo application with API level equal or higher than Android OS 2.2 with Google API
User have to signed in at-least one Google Account to use this service.
First you have to add GCM library.
Than create on class which I named GCMIntentService which extends GCMBaseIntentService as follows:
package com.example.gcmdemo;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import com.google.android.gcm.GCMBaseIntentService;
import com.google.android.gcm.GCMConstants;
public class GCMIntentService extends GCMBaseIntentService {
private static final String TAG = "Push Notification Demo GCMIntentService";
#Override
protected void onError(Context context, String errorId) {
if(GCMConstants.ERROR_ACCOUNT_MISSING.equalsIgnoreCase(errorId)) {
Log.v(TAG, "Error Account Missing");
} else if(GCMConstants.ERROR_AUTHENTICATION_FAILED.equalsIgnoreCase(errorId)) {
Log.v(TAG, "Error Authentication Failed");
} else if(GCMConstants.ERROR_INVALID_PARAMETERS.equalsIgnoreCase(errorId)) {
Log.v(TAG, "Error Invalid Parameters");
} else if(GCMConstants.ERROR_INVALID_SENDER.equalsIgnoreCase(errorId)) {
Log.v(TAG, "Error Invalid Sender");
} else if(GCMConstants.ERROR_PHONE_REGISTRATION_ERROR.equalsIgnoreCase(errorId)) {
Log.v(TAG, "Error Phone Registration Error");
} else if(GCMConstants.ERROR_SERVICE_NOT_AVAILABLE.equalsIgnoreCase(errorId)) {
Log.v(TAG, "Error Service Not Available");
}
}
#Override
protected void onMessage(Context context, Intent intent) {
// App Server Sends message as key value pairs
String value1 = intent.getStringExtra("key1");
String value2 = intent.getStringExtra("key2");
Log.v(TAG, "key1: "+value1 );
Log.v(TAG, "key2: "+value2 );
}
#Override
protected void onRegistered(Context context, String regId) {
Log.v(TAG, "Successfull Registration : "+regId);
}
#Override
protected void onUnregistered(Context context, String regId) {
Log.v(TAG, "Successfully Unregistred : "+regId);
}
#Override
protected String[] getSenderIds(Context context) {
return super.getSenderIds(context);
}
#Override
protected void onDeletedMessages(Context context, int total) {
super.onDeletedMessages(context, total);
}
#Override
protected boolean onRecoverableError(Context context, String errorId) {
return super.onRecoverableError(context, errorId);
}
}
Here is how you should check registration in following demo activity :
package com.example.gcmdemo;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import com.google.android.gcm.GCMRegistrar;
public class MainActivity extends Activity {
private static final String TAG = "Push Notification Demo Activity";
private static final String SENDER_ID = "1069713227710";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
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 : "+regId);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
And finally the demo manifest :
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.gcmdemo"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="8" />
<permission
android:name="com.example.gcmdemo.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.gcmdemo.permission.C2D_MESSAGE" />
<!-- 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" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<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.example.gcmdemo" />
</intent-filter>
</receiver>
<service android:name=".GCMIntentService" />
</application>
</manifest>
Also you will need third party server side script as specified here.
Sending Push Notification using FCM
Google deprecated the Google Cloud Messaging (GCM) and launched new Push notification server that is Firebase Cloud Messaging (FCM). FCM is same like GCM, FCM is also a cross-platform messaging solution for mobile platforms
Firebase Cloud Messaging can send three types of messages (Message types)
1.Notification Message
2.Data Message
3.message with both Notification and Data
Firebase Cloud Messaging Integrating steps:-
1.SetUp New Project or Import project in Firbase Console(https://firebase.google.com/)
2.Add the Same Package Name of App in Firebase App.
3.Get the "google-services.json" file and put that file to your project’s app folder.This file contains all the Urls and the Keys for Google service's, So don't change or edit this file.
4.Add new Gradle dependencies in Project for Firebase.
//app/build.gradle
dependencies {
compile 'com.google.firebase:firebase-messaging:9.6.0'
}
apply plugin: 'com.google.gms.google-services'
5.Create a Class that contains all the constant values that we use across the app for FCM.
public class Config {
public static final String TOPIC_GLOBAL = "global";
// broadcast receiver intent filters
public static final String REGISTRATION_COMPLETE = "registrationComplete";
public static final String PUSH_NOTIFICATION = "pushNotification";
// id to handle the notification in the notification tray
public static final int NOTIFICATION_ID = 100;
public static final int NOTIFICATION_ID_BIG_IMAGE = 101;
public static final String SHARED_PREF = "ah_firebase";
}
6. Create a class named MyFirebaseInstanceIDService.java which will receives the firebase registration id which will be unique to each app. Registration id is used to send message to a single device.
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
private static final String TAG = MyFirebaseInstanceIDService.class.getSimpleName();
#Override
public void onTokenRefresh() {
super.onTokenRefresh();
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
// Saving reg id to shared preferences
storeRegIdInPref(refreshedToken);
// sending reg id to your server
sendRegistrationToServer(refreshedToken);
// Notify UI that registration has completed, so the progress indicator can be hidden.
Intent registrationComplete = new Intent(Config.REGISTRATION_COMPLETE);
registrationComplete.putExtra("token", refreshedToken);
LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
}
private void sendRegistrationToServer(final String token) {
// sending gcm token to server
Log.e(TAG, "sendRegistrationToServer: " + token);
}
private void storeRegIdInPref(String token) {
SharedPreferences pref = getApplicationContext().getSharedPreferences(Config.SHARED_PREF, 0);
SharedPreferences.Editor editor = pref.edit();
editor.putString("regId", token);
editor.commit();
}
}
7.Create one more service class named MyFirebaseMessagingService.java. This will receive firebase messages.
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = MyFirebaseMessagingService.class.getSimpleName();
private NotificationUtils notificationUtils;
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.e(TAG, "From: " + remoteMessage.getFrom());
if (remoteMessage == null)
return;
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.e(TAG, "Notification Body: " + remoteMessage.getNotification().getBody());
handleNotification(remoteMessage.getNotification().getBody());
}
}
private void handleNotification(String message) {
if (!NotificationUtils.isAppIsInBackground(getApplicationContext())) {
// app is in foreground, broadcast the push message
Intent pushNotification = new Intent(Config.PUSH_NOTIFICATION);
pushNotification.putExtra("message", message);
LocalBroadcastManager.getInstance(this).sendBroadcast(pushNotification);
// play notification sound
NotificationUtils notificationUtils = new NotificationUtils(getApplicationContext());
notificationUtils.playNotificationSound();
}else{
// If the app is in background, firebase itself handles the notification
}
}
/**
* Showing notification with text only
*/
private void showNotificationMessage(Context context, String title, String message, String timeStamp, Intent intent) {
notificationUtils = new NotificationUtils(context);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
notificationUtils.showNotificationMessage(title, message, timeStamp, intent);
}
/**
* Showing notification with text and image
*/
private void showNotificationMessageWithBigImage(Context context, String title, String message, String timeStamp, Intent intent, String imageUrl) {
notificationUtils = new NotificationUtils(context);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
notificationUtils.showNotificationMessage(title, message, timeStamp, intent, imageUrl);
}
}
8.In the AndroidManifest.xml add these two firebase services MyFirebaseMessagingService and MyFirebaseInstanceIDService.
<!-- Firebase Notifications -->
<service android:name=".service.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service android:name=".service.MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<!-- ./Firebase Notifications -->
Now simply Send your First Message
Notes :
*1.Read the Google Doc for Firebase Cloud Messaging *
2.If you want to Migrate a GCM Client App for Android to Firebase Cloud Messaging follow these steps and Doc (Migrate a GCM Client
App)
3.Android Sample tutorial and Code (Receive Reengagement Notifications)
personally suggest you that instead of GCM there is also other library named Parse for PushNotification, it works same as Google Cloud Messaging but it is so so so so much easy then GCM
You have to just download JAR file and simple two-three line of code for PUSH-NOTIFICATION
to learn use this site https://parse.com/tutorials/android-push-notifications
Even you don't have to use PHP or any kind of server side code it provide you facility
look i will give u demo
Parse.initialize(this, "YOUR_APP_ID", "YOUR_CLIENT_KEY");
PushService.setDefaultPushCallback(this, YourDefaultActivity.class);
from above code is enough for receiving push notification
if you want to send notification they provide nice UI look the picture of UI they provide
Related
I am super beginner. Now I am try to make Android notification using NotificationListenerService.
Problem:
[A]application don't post notification but I can get to check (A)application debuglog in logcat .
I want to automatically post notification as [B]application when [A] post notification .
(I am making [B]application. )
Now:
I can get [A]application package name when it post. And then ...stop , how can I post notification(id & package name) from [B]application? use broadcastreceiver?
NotificationService.java
package com.testnotification;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
public class NotificationService extends NotificationListenerService {
private String TAG = "Notification";
private String Sample = "com.notification.sample"; ///this is [A]application
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
String packagename = sbn.getPackageName();
if(packagename.equals(Sample)){
showLog(sbn);
}
}
private void showLog( StatusBarNotification sbn ){
int id = sbn.getId();
String name = sbn.getPackageName();
Log.d(TAG,"id:" + id +
" name:" + name);
}
}
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.testnotification">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.Testnotification">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".NotificationService"
android:label="#string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
android:exported="true">
<intent-filter>
<action android:name=
"android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
</application>
</manifest>
MainActivity.java(empty yet)
Please teach me.
Have you checked if the user granted your app permission for notification listener
/**
* Is Notification Service Enabled.
* Verifies if the notification listener service is enabled.
* Got it from: https://github.com/kpbird/NotificationListenerService-Example/blob/master/NLSExample/src/main/java/com/kpbird/nlsexample/NLService.java
* #return True if enabled, false otherwise.
*/
private boolean isNotificationServiceEnabled(){
String pkgName = getPackageName();
final String flat = Settings.Secure.getString(getContentResolver(),
ENABLED_NOTIFICATION_LISTENERS);
if (!TextUtils.isEmpty(flat)) {
final String[] names = flat.split(":");
for (int i = 0; i < names.length; i++) {
final ComponentName cn = ComponentName.unflattenFromString(names[i]);
if (cn != null) {
if (TextUtils.equals(pkgName, cn.getPackageName())) {
return true;
}
}
}
}
return false;
}
if you don't have permission you can open settings app for user to enable permission
/**
* Build Notification Listener Alert Dialog.
* Builds the alert dialog that pops up if the user has not turned
* the Notification Listener Service on yet.
* #return An alert dialog which leads to the notification enabling screen
*/
private AlertDialog buildNotificationServiceAlertDialog(){
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle(R.string.notification_listener_service);
alertDialogBuilder.setMessage(R.string.notification_listener_service_explanation);
alertDialogBuilder.setPositiveButton(R.string.yes,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
startActivity(new Intent(ACTION_NOTIFICATION_LISTENER_SETTINGS));
}
});
alertDialogBuilder.setNegativeButton(R.string.no,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// If you choose to not enable the notification listener
// the app. will not work as expected
}
});
return(alertDialogBuilder.create());
}
Here is complete project for notification listener I found in GitHub
https://github.com/Chagall/notification-listener-service-example
I am trying to handle the messaged from FCM(Firebase Cloud Messaging) in andorid;
This is my code
FirebaseMessaging.getInstance().getToken()
.addOnCompleteListener(new OnCompleteListener<String>() {
#Override
public void onComplete(#NonNull Task<String> task) {
if (!task.isSuccessful()) {
Log.w("TAG", "Fetching FCM registration token failed", task.getException());
return;
}
// Get new FCM registration token
String token = task.getResult();
// Log and toast
Log.d("TAG", token);
Toast.makeText(StartActivity.this, token, Toast.LENGTH_SHORT).show();
}
});
FirebaseMessaging.getInstance().setAutoInitEnabled(true);
And i have send messaged from firebase console.
But i want to handle the messages.
So i'have did this doc says https://firebase.google.com/docs/cloud-messaging/android/receive
This is manifest.xml
<service
android:name="com.google.firebase.messaging.FirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#android:drawable/ic_notification_overlay" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="#color/white" />
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
This is my FirebaseMessagingService extended class
public class MessageService extends FirebaseMessagingService {
private static final String TAG = "MessageService";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Toast.makeText(this, "Got it", Toast.LENGTH_SHORT).show();
}
}
But I don't know how to resgister this FirebaseMessagingService class to Firebase messaging
You don't need to register the class of your messaging service, you need to register the application itself. It should be google-services.json configuration file in your project with all necessary info about the project in firebase console. It will make kind of connection between your app and project created in Firebase console.
There are several ways to get this configuration file:
Generate google-services.json via Firebase console https://firebase.google.com/docs/cloud-messaging/android/client#register_your_app_with_firebase
Generate it via Android studio. Tools -> Firebase -> Cloud messaging -> complete wizard "Setup Firebase cloud messaging"
You have done a mistake in manifest.xml file.
You had to replace this
<service
android:name="com.google.firebase.messaging.FirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#android:drawable/ic_notification_overlay" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="#color/white" />
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
with this
<service android:name=".helpers.MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<service android:name=".helpers.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
and create these classes
MyFirebaseInstanceIDService
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d("TAG", "Refreshed token: " + refreshedToken);
// If you want to send messages to this application instance or
// manage this apps subscriptions on the server side, send the
// Instance ID token to your app server.
}
}
and MyFirebaseMessagingService
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "DEEDDEED";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
public void run() {
Toast.makeText(MyFirebaseMessagingService.this,"Hello",Toast.LENGTH_SHORT).show();
}
});
// ...
// TODO(developer): Handle FCM messages here.
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
if (/* Check if data needs to be processed by long running job */ true) {
// For long-running tasks (10 seconds or more) use Firebase Job Dispatcher.
// scheduleJob();
} else {
// Handle message within 10 seconds
// handleNow();
}
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated. See sendNotification method below.
}
#Override
public void onNewToken(#NonNull String s) {
super.onNewToken(s);
HashMap<String,String> map = new HashMap<>();
Database database = new Database(getApplicationContext());
map.put("user",database.getPhone());
map.put("token",s);
Call<Void> call = new Server().getRetrofitInterface().executeUpdatePTK(map);
call.enqueue(new Callback<Void>() {
#Override
public void onResponse(Call<Void> call, Response<Void> response) {
}
#Override
public void onFailure(Call<Void> call, Throwable t) {
}
});
}
}
I have added firebase dependencies and included google-services.json. I am able to use Firebase database successfully. But Push notifications are not being sent from fireabse console.
Please let me know what is wrong here.
I have following classes
public class FirebaseIDService extends FirebaseInstanceIdService {
private static final String TAG = "FirebaseIDService";
#Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Refreshed token: " + refreshedToken);
// TODO: Implement this method to send any registration to your app's servers.
sendRegistrationToServer(refreshedToken);
}
/**
* Persist token to third-party servers.
* <p>
* Modify this method to associate the user's FCM InstanceID 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.
}
}
And Messaging Service
public class GalleryMessagingService extends FirebaseMessagingService {
private static final String TAG = "FCM Service";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
send();
}
private void send() {
Intent resultIntent = new Intent(this, ImageGridActivity.class);
PendingIntent resultPendingIntent =
PendingIntent.getActivity(
this,
0,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("My notification")
.setContentText("First Notification");
mBuilder.setContentIntent(resultPendingIntent);
// Sets an ID for the notification
int mNotificationId = 001;
NotificationManager mNotifyMgr =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotifyMgr.notify(mNotificationId, mBuilder.build());
}
I have added following in Manifest.xml as well
<service android:name="com.doublenine.apps.ui.GalleryMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<service android:name="com.doublenine.apps.ui.FirebaseIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<!-- Set custom default icon. This is used when no icon is set for incoming notification messages.
-->
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#drawable/ic_launcher" />
<!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
notification message. for more. -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="#android:color/holo_green_dark" />
FirebaseIDService class looks incomplete as I don't know what to write in sendRegistrationToServer()
I am new to android programming . I am trying to develop simple gcm test application to register the app on gcm server. the code is
public class MainActivity extends ActionBarActivity implements OnClickListener {
Button btnRegId;
Context context;
EditText etRegId;
GoogleCloudMessaging gcm;
AtomicInteger msgId = new AtomicInteger();
String regid;
public static final String EXTRA_MESSAGE = "message";
public static final String PROPERTY_REG_ID = "registration_id";
private static final String PROPERTY_APP_VERSION = "appVersion";
String SENDER_ID = "507707796382";
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
static final String TAG = "GCM";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = getApplicationContext();
btnRegId = (Button) findViewById(R.id.btnGetRegId);
etRegId = (EditText) findViewById(R.id.etRegId);
if (checkPlayServices()) {
btnRegId.setOnClickListener(this);
gcm = GoogleCloudMessaging.getInstance(this);
regid = getRegistrationId(context);
if (regid.isEmpty()) {
registerInBackground();
}
} else {
Log.i(TAG, "No valid Google Play Services APK found.");
Toast.makeText(getApplicationContext(), "No valid Google Play Services APK found.", Toast.LENGTH_LONG).show();
}
}
/**
* Gets the current registration ID for application on GCM service.
*
* If result is empty, the app needs to register.
*
* #return registration ID, or empty string if there is no existing
* registration ID.
*/
private String getRegistrationId(Context context) {
final SharedPreferences prefs = getGCMPreferences(context);
String registrationId = prefs.getString(PROPERTY_REG_ID, "");
if (registrationId.isEmpty()) {
Log.i(TAG, "Registration not found.");
return "";
}
// Check if app was updated; if so, it must clear the registration ID
// since the existing registration ID is not guaranteed to work with
// the new app version.
int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
int currentVersion = getAppVersion(context);
if (registeredVersion != currentVersion) {
Log.i(TAG, "App version changed.");
return "";
}
return registrationId;
}
/**
* #return Application's {#code SharedPreferences}.
*/
private SharedPreferences getGCMPreferences(Context context) {
// This sample app persists the registration ID in shared preferences, but
// how you store the registration ID in your app is up to you.
return getSharedPreferences(MainActivity.class.getSimpleName(),
Context.MODE_PRIVATE);
}
/**
* #return Application's version code from the {#code PackageManager}.
*/
private static int getAppVersion(Context context) {
try {
PackageInfo packageInfo = context.getPackageManager()
.getPackageInfo(context.getPackageName(), 0);
return packageInfo.versionCode;
} catch (PackageManager.NameNotFoundException e) {
// should never happen
throw new RuntimeException("Could not get package name: " + e);
}
}
#Override
public void onClick(View view) {
}
#Override
protected void onResume() {
super.onResume();
checkPlayServices();
}
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.i("GCM", "This device is not supported.");
finish();
}
return false;
}
return true;
}
/**
* Registers the application with GCM servers asynchronously.
*
* Stores the registration ID and app versionCode in the application's
* shared preferences.
*/
private void registerInBackground() {
new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
String msg = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
regid = gcm.register(SENDER_ID);
msg = "Device registered, registration ID=" + regid;
// send the registration ID to server over HTTP,
// so it can use GCM/HTTP or CCS to send messages to app.
// The request to server should be authenticated if app
// is using accounts.
sendRegistrationIdToBackend();
// For this demo: we don't need to send it because the device
// will send upstream messages to a server that echo back the
// message using the 'from' address in the message.
// Persist the registration ID - no need to register again.
storeRegistrationId(context, regid);
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
// If there is an error, don't just keep trying to register.
// Require the user to click a button again, or perform
// exponential back-off.
}
return msg;
}
#Override
protected void onPostExecute(String msg) {
etRegId.setText(msg + "\n");
}
}.execute(null, null, null);
}
/**
* Sends the registration ID to your server over HTTP, so it can use GCM/HTTP
* or CCS to send messages to your app. Not needed for this demo since the
* device sends upstream messages to a server that echoes back the message
* using the 'from' address in the message.
*/
private void sendRegistrationIdToBackend() {
// implementation .
}
/**
* Stores the registration ID and app versionCode in the application's
* {#code SharedPreferences}.
*
* #param context application's context.
* #param regId registration ID
*/
private void storeRegistrationId(Context context, String regId) {
final SharedPreferences prefs = getGCMPreferences(context);
int appVersion = getAppVersion(context);
Log.i(TAG, "Saving regId on app version " + appVersion);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(PROPERTY_REG_ID, regId);
editor.putInt(PROPERTY_APP_VERSION, appVersion);
editor.commit();
}
}
while executing this i get an error . My logcat window shows:
03-15 09:48:58.052 2686-2702/com.example.bhaskar.mygcm E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1
Process: com.example.bhaskar.mygcm, PID: 2686
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:300)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.SecurityException: Not allowed to start service Intent { act=com.google.android.c2dm.intent.REGISTER pkg=com.google.android.gms (has extras) } without permission com.google.android.c2dm.permission.RECEIVE
at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1710)
at android.app.ContextImpl.startService(ContextImpl.java:1687)
at android.content.ContextWrapper.startService(ContextWrapper.java:515)
at com.google.android.gms.gcm.GoogleCloudMessaging.e(Unknown Source)
at com.google.android.gms.gcm.GoogleCloudMessaging.register(Unknown Source)
at com.example.bhaskar.mygcm.MainActivity$1.doInBackground(MainActivity.java:158)
at com.example.bhaskar.mygcm.MainActivity$1.doInBackground(MainActivity.java:150)
at android.os.AsyncTask$2.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
On line no 158 I have ;
regid = gcm.register(SENDER_ID);
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.bhaskar.mygcm" >
<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="com.google.android.c2dm.permission.C2D_RECEIVE"/>
<permission android:name="com.google.android.c2dm.permission.C2D_MESSAGE" android:protectionLevel="signature"/>
<uses-permission android:name="com.google.android.c2dm.permission.C2D_MESSAGE"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver android:name=".GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.C2D_SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE"/>
<category android:name="com.example.bhaskar.mygcm"/>
</intent-filter>
</receiver>
<service android:name=".GcmMessageHandler"/>
<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>
<meta-data android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version"/>
</application>
</manifest>
Can anyone help me figure out the bug.Any help would be appreciated.
have you added the
<uses-permission android:name=" com.google.android.c2dm.permission.RECEIVE " />
<uses-permission android:name="com.google.android.c2dm.permission.C2D_MESSAGE">
in your manifest? The logcat says otherwise.
I am having issue when sending data from Service to Activity through Notification , I click a Notification an Activity get invoked but when i try to add some parameters through bundle i am not able to get the parameters in that called intent , I have gone through the link
How to send parameters from a notification-click to an activity?
But still no luck.
Has the same issue occurred with somebody else ?
Thanks in advance.
You have to modify the Manifest file as well.
Here is the example that works:
These variables and methods are members of Service class:
public static final String MOVEMENT_UPDATE = "com.client.gaitlink.AccelerationService.action.MOVEMENT_UPDATE";
public static final String ACCELERATION_X = "com.client.gaitlink.AccelerationService.ACCELERATION_X";
public static final String ACCELERATION_Y = "com.client.gaitlink.AccelerationService.ACCELERATION_Y";
public static final String ACCELERATION_Z = "com.client.gaitlink.AccelerationService.ACCELERATION_Z";
private void announceAccelerationChanges()//this method sends broadcast messages
{
Intent intent = new Intent(MOVEMENT_UPDATE);
intent.putExtra(ACCELERATION_X, accelerationX);
intent.putExtra(ACCELERATION_Y, accelerationY);
intent.putExtra(ACCELERATION_Z, accelerationZ);
sendBroadcast(intent);
}
And this are the methods from Main activity:
You have to register receiver in the onResume method:
#Override
public void onResume()
{
IntentFilter movementFilter;
movementFilter = new IntentFilter(AccelerationService.MOVEMENT_UPDATE);
accelerationReceiver = new AccelerationServiceReceiver();
registerReceiver(accelerationReceiver, movementFilter);
startAccelerationService();
super.onResume();
}
private void startAccelerationService()
{
startService(new Intent(this, AccelerationService.class));
}
public class AccelerationServiceReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)//this method receives broadcast messages. Be sure to modify AndroidManifest.xml file in order to enable message receiving
{
accelerationX = intent.getDoubleExtra(AccelerationService.ACCELERATION_X, 0);
accelerationY = intent.getDoubleExtra(AccelerationService.ACCELERATION_Y, 0);
accelerationZ = intent.getDoubleExtra(AccelerationService.ACCELERATION_Z, 0);
announceSession();
updateGUI();
}
}
This is the part of AndroidManifest.xml file that has to be set in order to receive broadcast messages:
<activity android:name=".GaitLink"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="com.client.gaitlink.CommunicationService.action.ACTIVITY_STATUS_UPDATE" />
</intent-filter>
</activity>