How to send notifucation using firebase by android side coding? - android

I am try to send notification using firebase using android side code.
please suggest me how can I do.
Please help me.
Thanks in advance

First of all make sure you have an firebase project, if no than create one.
After that store the device id(firebase token) while registering the device using this code.
class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
private static final String TAG = "MyFirebaseIIDService";
/**
* Called if InstanceID token is updated. This may occur if the security of
* the previous token had been compromised. Note that this is called when the InstanceID token
* is initially generated so this is where you would retrieve the token.
*/
// [START refresh_token]
#Override
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.
sendRegistrationToServer(refreshedToken);
}
// [END refresh_token]
/**
* 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(final String token) {
new SharedPrefUtil(getApplicationContext()).saveString(Constants.ARG_FIREBASE_TOKEN, token);
if (FirebaseAuth.getInstance().getCurrentUser() != null) {
FirebaseDatabase.getInstance()
.getReference()
.child(Constants.ARG_USERS)
.child(FirebaseAuth.getInstance().getCurrentUser().getUid())
.child(Constants.ARG_FIREBASE_TOKEN)
.setValue(token);
}
}}
after that send notification to the user you want using following code-
void sendPushNotificationToReceiver(String username,
String message,
String uid,
String firebaseToken,
String receiverFirebaseToken) {
Log.d(":asdfasd",username+" "+message);
FcmNotificationBuilder.initialize()
.title(username)
.message(message)
.username(username)
.uid(uid)
.firebaseToken(firebaseToken)
.receiverFirebaseToken(receiverFirebaseToken)
.send();
}
here is the FCMNotificationBuilder class-
class FcmNotificationBuilder {
public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");
private static final String TAG = "FcmNotificationBuilder";
private static final String SERVER_API_KEY = "YOUR SERVER API KEY";
private static final String CONTENT_TYPE = "Content-Type";
private static final String APPLICATION_JSON = "application/json";
private static final String AUTHORIZATION = "Authorization";
private static final String AUTH_KEY = "key=" + SERVER_API_KEY;
private static final String FCM_URL = "https://fcm.googleapis.com/fcm/send";
// json related keys
private static final String KEY_TO = "to";
private static final String KEY_NOTIFICATION = "notification";
private static final String KEY_TITLE = "title";
private static final String KEY_TEXT = "text";
private static final String KEY_DATA = "data";
private static final String KEY_USERNAME = "username";
private static final String KEY_UID = "uid";
private static final String KEY_FCM_TOKEN = "fcm_token";
private String mTitle;
private String mMessage;
private String mUsername;
private String mUid;
private String mFirebaseToken;
private String mReceiverFirebaseToken;
private FcmNotificationBuilder() {
}
public static FcmNotificationBuilder initialize() {
return new FcmNotificationBuilder();
}
public FcmNotificationBuilder title(String title) {
mTitle = title;
return this;
}
public FcmNotificationBuilder message(String message) {
mMessage = message;
return this;
}
public FcmNotificationBuilder username(String username) {
mUsername = username;
return this;
}
public FcmNotificationBuilder uid(String uid) {
mUid = uid;
return this;
}
public FcmNotificationBuilder firebaseToken(String firebaseToken) {
mFirebaseToken = firebaseToken;
return this;
}
public FcmNotificationBuilder receiverFirebaseToken(String receiverFirebaseToken) {
mReceiverFirebaseToken = receiverFirebaseToken;
return this;
}
public void send() {
RequestBody requestBody = null;
try {
requestBody = RequestBody.create(MEDIA_TYPE_JSON, getValidJsonBody().toString());
} catch (JSONException e) {
e.printStackTrace();
}
Request request = new Request.Builder()
.addHeader(CONTENT_TYPE, APPLICATION_JSON)
.addHeader(AUTHORIZATION, AUTH_KEY)
.url(FCM_URL)
.post(requestBody)
.build();
Call call = new OkHttpClient().newCall(request);
call.enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
Log.e(TAG, "onGetAllUsersFailure: " + e.getMessage());
}
#Override
public void onResponse(Call call, Response response) throws IOException {
Log.e(TAG, "onResponse: " + response.body().string());
}
});
}
private JSONObject getValidJsonBody() throws JSONException {
JSONObject jsonObjectBody = new JSONObject();
jsonObjectBody.put(KEY_TO, mReceiverFirebaseToken);
JSONObject jsonObjectData = new JSONObject();
jsonObjectData.put(KEY_TITLE, mTitle);
jsonObjectData.put(KEY_TEXT, mMessage);
jsonObjectData.put(KEY_USERNAME, mUsername);
jsonObjectData.put(KEY_UID, mUid);
jsonObjectData.put(KEY_FCM_TOKEN, mFirebaseToken);
jsonObjectBody.put(KEY_DATA, jsonObjectData);
return jsonObjectBody;
}}
and receive notifications as normally we do using services.
This is working for me in my chat application , hope it will help you also.

First thing is to get the Token of the user you want to send the notification to.
Then I use this code in an AsyncTask
protected String doInBackground(String... strings) {
try{
JSONObject jo = new JSONObject();
jo.put("message", "<Message>"));
jo.put("title", "<Message Title>");
JSONObject mainObj = new JSONObject();
mainObj.put("to",<TOKEN_OF_DEVICE>);
mainObj.put("data", jo);
URL url = new URL("https://android.googleapis.com/gcm/send");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Authorization", "key=<API_KEY>");
connection.setDoOutput(true);
//Log.e("sent",mainObj.toString());
DataOutputStream dStream = new DataOutputStream(connection.getOutputStream());
dStream.writeBytes(mainObj.toString());
dStream.flush();
dStream.close();
String line;
int responseCode = connection.getResponseCode();
//Log.e("code", responseCode+" hi");
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder responseOutput = new StringBuilder();
while((line = br.readLine()) != null ){
responseOutput.append(line);
}
br.close();
//Log.e("output", responseOutput.toString());
}
catch (Exception e){
e.printStackTrace();
}
return null;
}

First of all connect Firebase to your project from Android Studio.
Generate token
Follow the link Firebase Notification
Also sample github code link isGithub code
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
/**
* Called when message is received.
*
* remoteMessage Object representing the message received from Firebase Cloud Messaging.
*/
// [START receive_message]
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// [START_EXCLUDE]
// There are two types of messages data messages and notification messages. Data messages are handled
// here in onMessageReceived whether the app is in the foreground or background. Data messages are the type
// traditionally used with GCM. Notification messages are only received here in onMessageReceived when the app
// is in the foreground. When the app is in the background an automatically generated notification is displayed.
// When the user taps on the notification they are returned to the app. Messages containing both notification
// and data payloads are treated as notification messages. The Firebase console always sends notification
// messages.
// [END_EXCLUDE]
// TODO(developer): Handle FCM messages here.
// Not getting messages here?
// Log.d(TAG, "From: " + remoteMessage.getFrom());
sendNotification(remoteMessage.getNotification().getBody());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
// Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}
// 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.
}
// [END receive_message]
/**
* Create and show a simple notification containing the received FCM message.
*
* #param messageBody FCM message body received.
*/
private void sendNotification(String messageBody) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Title")
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}

Related

InvalidRegistration error when trying to use Volley to send push notifications over FCM

I am trying to send push notifications using Volley to FCM, but they are not received on the other side. The response I am gettin from Volley is this one
{"multicast_id":7351526324257141941,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]}
I am new to FCM and Volley, and have followed this guide. The idea is that every user subscribes to their uid as a topic, and when a a certain action related to them happens (someone likes their photo for example) then a message would be sent with the topic as their ID.
Whenever the user logs in to the app I execute the follwong code:
val uid = FirebaseAuth.getInstance().uid
val userRef = FirebaseDatabase.getInstance().getReference("/users/$uid/services/firebase-token")
userRef.setValue(token)
FirebaseMessaging.getInstance().subscribeToTopic(uid)
I am currently in the testing, so the message I am trying to send is pretty generic. These are the functions that should execute it.
static void sendMessageTopic(String receiverId, String initiatorId, String post, Activity activity) {
String NOTIFICATION_TITLE = "some title";
String NOTIFICATION_MESSAGE = "This is the message";
JSONObject notification = new JSONObject();
JSONObject notificationBody = new JSONObject();
try {
notificationBody.put("title", NOTIFICATION_TITLE);
notificationBody.put("message", NOTIFICATION_MESSAGE);
notification.put("to", receiverId);
notification.put("data", notificationBody);
} catch (
JSONException e) {
Log.e("notificationStuff", "onCreate: " + e.getMessage());
}
sendNotification(notification, activity);
}
Then:
static void sendNotification(JSONObject notification, Activity activity) {
String FCM_API = "https://fcm.googleapis.com/fcm/send";
String serverKey =
"AAAAA6gibkM:APA91bG8UUtfNFwNLI6-Peu_KsbpTskmjutdJDyHq-qi5fj2UdCcjIVRCO5PlhZUNfJdeyW4-3oznOxMDWdjpfSAnpltlvtBFCoM_vir7pQLKbxc_aDzWJPs8xu27CADbMkHkq5tKgT7";
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(FCM_API, notification,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.i("notificationStuff", "onResponse: " + response.toString());
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(activity, "Request error", Toast.LENGTH_LONG).show();
Log.i("notificationStuff", "onErrorResponse: Didn't work");
}
}){
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("Authorization", "key=" + serverKey);
params.put("Content-Type", "application/json");
return params;
}
};
MySingleton.getInstance(activity.getApplicationContext()).addToRequestQueue(jsonObjectRequest);
}
The singleton:
public class MySingleton {
private static MySingleton instance;
private RequestQueue requestQueue;
private Context ctx;
private MySingleton(Context context) {
ctx = context;
requestQueue = getRequestQueue();
}
public static synchronized MySingleton getInstance(Context context) {
if (instance == null) {
instance = new MySingleton(context);
}
return instance;
}
public RequestQueue getRequestQueue() {
if (requestQueue == null) {
// getApplicationContext() is key, it keeps you from leaking the
// Activity or BroadcastReceiver if someone passes one in.
requestQueue = Volley.newRequestQueue(ctx.getApplicationContext());
}
return requestQueue;
}
public <T> void addToRequestQueue(Request<T> req) {
getRequestQueue().add(req);
}
}
And then my method to catch receiving messages:
public class MyJavaFCM extends FirebaseMessagingService {
private final String ADMIN_CHANNEL_ID ="admin_channel";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
final Intent intent = new Intent(this, MainActivity.class);
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
int notificationID = new Random().nextInt(3000);
/*
Apps targeting SDK 26 or above (Android O) must implement notification channels and add its notifications
to at least one of them. Therefore, confirm if version is Oreo or higher, then setup notification channel
*/
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
setupChannels(notificationManager);
}
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this , 0, intent,
PendingIntent.FLAG_ONE_SHOT);
Bitmap largeIcon = BitmapFactory.decodeResource(getResources(),
R.drawable.profile_icon);
Uri notificationSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, ADMIN_CHANNEL_ID)
.setSmallIcon(R.drawable.logo_fallback)
.setLargeIcon(largeIcon)
.setContentTitle(remoteMessage.getData().get("title"))
.setContentText(remoteMessage.getData().get("message"))
.setAutoCancel(true)
.setSound(notificationSoundUri)
.setContentIntent(pendingIntent);
//Set notification color to match your app color template
notificationBuilder.setColor(getResources().getColor(R.color.colorPrimaryDark));
notificationManager.notify(notificationID, notificationBuilder.build());
}
#RequiresApi(api = Build.VERSION_CODES.O)
private void setupChannels(NotificationManager notificationManager){
CharSequence adminChannelName = "New notification";
String adminChannelDescription = "Device to devie notification";
NotificationChannel adminChannel;
adminChannel = new NotificationChannel(ADMIN_CHANNEL_ID, adminChannelName, NotificationManager.IMPORTANCE_HIGH);
adminChannel.setDescription(adminChannelDescription);
adminChannel.enableLights(true);
adminChannel.setLightColor(Color.RED);
adminChannel.enableVibration(true);
if (notificationManager != null) {
notificationManager.createNotificationChannel(adminChannel);
}
}
}
The only indication of what's wrong I get is that message I've adde in the beginning but I'm not quite sure what to make of it (tried to read on it but couldn't understand much of what was said and not sure if it is related to my specific case.
When following the guide, the author wrote the topics destination in a format similar to this /topics/yourTopic but I thought this is how it is organized in his database or something like this. I dind't think much of it and didn't copy the /topics part to my code, but this is the reason it didn't go through.
I had to change this
notification.put("to", receiverId);
to this:
notification.put("to", "/topics/" + receiverId);

Pass string between non-activity classes

I have two non-activity class and I need to send one string from one class to another, my approach is to use shared preference but I cannot get the shared string in the second class. First class will run every time the app is opened and will generate a token
First class:
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
private static final String TAG = "MyFirebaseIDService";
/**
* Called if InstanceID token is updated. This may occur if the security of
* the previous token had been compromised. Note that this is called when the InstanceID token
* is initially generated so this is where you would retrieve the token.
*/
// [START refresh_token]
#Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Refreshed token: " + refreshedToken);
sendRegistrationToServer(refreshedToken);
}
// [END refresh_token]
/**
* Persist token to third-party servers.
*
* 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.
*/
public void sendRegistrationToServer(String token) {
// TODO: Implement this method to send token to your app server.
SharedPreferences sp = getSharedPreferences("PUSHToken", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putString("PUSHToken", token);
editor.commit();
}
}
I am trying to pass the string token and store in my second non-activity class for my volley request:
public class VolleyPut {
private static final String TAG = "VolleyPut";
private static VolleyPut instance = null;
public static final String KEY_TOKEN = "token";
//for Volley API
public RequestQueue requestQueue;
SharedPreferences sp2=getSharedPreferences("PUSHToken", Context.MODE_PRIVATE);
String token = sp2.getString("PUSHToken", "");
private VolleyPut(Context context)
{
this.token = token;
requestQueue = Volley.newRequestQueue(context.getApplicationContext());
return;
}
public static synchronized VolleyPut getInstance(Context context)
{
if (null == instance)
instance = new VolleyPut(context);
return instance;
}
public static synchronized VolleyPut getInstance()
{
if (null == instance)
{
throw new IllegalStateException(VolleyPut.class.getSimpleName() +
" is not initialized, call getInstance(...) first");
}
return instance;
}
public void VolleyPUT(String domain, String api, final String finalToken, final CustomListener<String> listener){
JSONArray jsonArray = new JSONArray();
JSONObject jsonObject = new JSONObject();
try{
jsonObject.put("token", token);
jsonArray.put(jsonObject);
Log.i("JsonString :", jsonObject.toString());
}catch (Exception e){
System.out.println("Error:" + e);
}
StringRequest sr = new StringRequest(Request.Method.PUT, domain + api,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.e("HttpClient", "success! response: " + response);
if(null != response)
listener.getResult(response);
return;
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
if (null != error.networkResponse)
{
Log.d(TAG + ": ", "Error Response code: " + error.networkResponse.statusCode);
//listener.getResult(false);
}
}
})
{
#Override
public Map<String,String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers= new HashMap<>();
headers.put("Authorization",finalToken);
headers.put("Content-Type","application/json");
headers.put(KEY_TOKEN,token);
return headers;
}
};
requestQueue.add(sr);
}
}
However I am getting error unable to resolve method getsharedpreference in my second class. How is the way to solve this and are there anyway to pass strings between non-activity class?
The problem is that FirebaseInstanceIdService innherits from class android.content.Context so, in MyFirebaseInstanceIDService you have a Context and can use getSharedPreferences.
The solution is (to modify the minimum code) pass a context to the second class, and use it to get the shared preferences.
Better solution (my own think) is create a custom Application and use it always as a common context for all your app. Lower params and lower dependencies, because you always have the "CustomApplication" and can use it.
Here how to implement it:
https://stackoverflow.com/a/27416998/585540
Remember, if you use this approach, must put it in Manifest:
<application ....
android:name="com.you.yourapp.CustomApplication"
......>
You can create a global variable as:-
public Context context;
public VolleyPut(Context context)
{
this.token = token;
this.context=context
requestQueue = Volley.newRequestQueue(context.getApplicationContext());
return;
}
SharedPreferences sp2=**context**.getSharedPreferences("PUSHToken", Context.MODE_PRIVATE);
This will resolve error unable to resolve method getsharedpreference

AmazonSNS - AwsCredentials.properties - NullPointerException

I am new to Android Studio and intelliJ.
I am trying to work with AmazonSNS - Push. I am unable to figure out how to add AwsCredentials.properties file to classpath of the module. I get a NPE at line 57 in the image below(at method getResourceAsStream()). I added the required keys in AwsCredentials.properties file.
Error:
In the questions that i have come across on StackOverflow regarding similar issues, some suggested that the file should be in the root folder, where, src is. I placed it in the same folder as that of src, but still getting the NPE. I also tried placing the file in com/test/ but with no use.
How do i solve this? Are there any other steps involved?
EDIT after starting a bounty - Adding java files
Here is what i did till now..
Create an Android Application called MyApplication. Imported all classes(AndroidMobilePushApp.java, ExternalReceiver.java, MessageReceivingService.java) from the demo application. Added required libs, and ran it and got the registationId as response from Amazon.
In the same application, i created a new module called snspush and imported SNSMobilePush.java file into it. Also imported the AwsCredentials.properties file to the same path as that of SNSMobilePush.java. Added the keys in AwsCredentials.properties file.
Followed the steps in documentation to uncomment necessary funtions.
Project Structure:
Java files:
AndroidMobilePushApp.java:
public class AndroidMobilePushApp extends AppCompatActivity {
private TextView tView;
private SharedPreferences savedValues;
private String numOfMissedMessages;
// Since this activity is SingleTop, there can only ever be one instance. This variable corresponds to this instance.
public static Boolean inBackground = true;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
numOfMissedMessages = getString(R.string.num_of_missed_messages);
setContentView(R.layout.activity_main);
tView = (TextView) findViewById(R.id.tViewId);
tView.setMovementMethod(new ScrollingMovementMethod());
startService(new Intent(this, MessageReceivingService.class));
}
public void onStop(){
super.onStop();
inBackground = true;
}
public void onRestart(){
super.onRestart();
tView.setText("");;
}
public void onResume(){
super.onResume();
inBackground = false;
savedValues = MessageReceivingService.savedValues;
int numOfMissedMessages = 0;
if(savedValues != null){
numOfMissedMessages = savedValues.getInt(this.numOfMissedMessages, 0);
}
String newMessage = getMessage(numOfMissedMessages);
if(newMessage!=""){
Log.i("displaying message", newMessage);
tView.append(newMessage);
}
}
public void onNewIntent(Intent intent){
super.onNewIntent(intent);
setIntent(intent);
}
// If messages have been missed, check the backlog. Otherwise check the current intent for a new message.
private String getMessage(int numOfMissedMessages) {
String message = "";
String linesOfMessageCount = getString(R.string.lines_of_message_count);
if(numOfMissedMessages > 0){
String plural = numOfMissedMessages > 1 ? "s" : "";
Log.i("onResume","missed " + numOfMissedMessages + " message" + plural);
tView.append("You missed " + numOfMissedMessages +" message" + plural + ". Your most recent was:\n");
for(int i = 0; i < savedValues.getInt(linesOfMessageCount, 0); i++){
String line = savedValues.getString("MessageLine"+i, "");
message+= (line + "\n");
}
NotificationManager mNotification = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotification.cancel(R.string.notification_number);
SharedPreferences.Editor editor=savedValues.edit();
editor.putInt(this.numOfMissedMessages, 0);
editor.putInt(linesOfMessageCount, 0);
editor.commit();
}
else{
Log.i("onResume","no missed messages");
Intent intent = getIntent();
if(intent!=null){
Bundle extras = intent.getExtras();
if(extras!=null){
for(String key: extras.keySet()){
message+= key + "=" + extras.getString(key) + "\n";
}
}
}
}
message+="\n";
return message;
}
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == R.id.menu_clear){
tView.setText("");
return true;
}
else{
return super.onOptionsItemSelected(item);
}
}
}
ExternalReceiver.java
package com.test.awstestapp;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
public class ExternalReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
if(intent!=null){
Bundle extras = intent.getExtras();
if(!AndroidMobilePushApp.inBackground){
MessageReceivingService.sendToApp(extras, context);
}
else{
MessageReceivingService.saveToLog(extras, context);
}
}
}
}
MessageReceivingService.java
public class MessageReceivingService extends Service{
private GoogleCloudMessaging gcm;
public static SharedPreferences savedValues;
public static void sendToApp(Bundle extras, Context context){
Intent newIntent = new Intent();
newIntent.setClass(context, AndroidMobilePushApp.class);
newIntent.putExtras(extras);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(newIntent);
}
public void onCreate(){
super.onCreate();
final String preferences = getString(R.string.preferences);
savedValues = getSharedPreferences(preferences, Context.MODE_PRIVATE);
// In later versions multi_process is no longer the default
if(VERSION.SDK_INT > 9){
savedValues = getSharedPreferences(preferences, Context.MODE_MULTI_PROCESS);
}
gcm = GoogleCloudMessaging.getInstance(getBaseContext());
SharedPreferences savedValues = PreferenceManager.getDefaultSharedPreferences(this);
if(savedValues.getBoolean(getString(R.string.first_launch), true)){
register();
SharedPreferences.Editor editor = savedValues.edit();
editor.putBoolean(getString(R.string.first_launch), false);
editor.commit();
}
// Let AndroidMobilePushApp know we have just initialized and there may be stored messages
sendToApp(new Bundle(), this);
}
protected static void saveToLog(Bundle extras, Context context){
SharedPreferences.Editor editor=savedValues.edit();
String numOfMissedMessages = context.getString(R.string.num_of_missed_messages);
int linesOfMessageCount = 0;
for(String key : extras.keySet()){
String line = String.format("%s=%s", key, extras.getString(key));
editor.putString("MessageLine" + linesOfMessageCount, line);
linesOfMessageCount++;
}
editor.putInt(context.getString(R.string.lines_of_message_count), linesOfMessageCount);
editor.putInt(context.getString(R.string.lines_of_message_count), linesOfMessageCount);
editor.putInt(numOfMissedMessages, savedValues.getInt(numOfMissedMessages, 0) + 1);
editor.commit();
postNotification(new Intent(context, AndroidMobilePushApp.class), context);
}
protected static void postNotification(Intent intentAction, Context context){
final NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
final PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intentAction, Notification.DEFAULT_LIGHTS | Notification.FLAG_AUTO_CANCEL);
final Notification notification = new NotificationCompat.Builder(context).setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Message Received!")
.setContentText("")
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.getNotification();
mNotificationManager.notify(R.string.notification_number, notification);
}
private void register() {
new AsyncTask(){
protected Object doInBackground(final Object... params) {
String token;
try {
token = gcm.register(getString(R.string.project_number));
Log.i("registrationId", token);
}
catch (IOException e) {
Log.i("Registration Error", e.getMessage());
}
return true;
}
}.execute(null, null, null);
}
public IBinder onBind(Intent arg0) {
return null;
}
}
SNSMobilePush.java
package com.test;
public class SNSMobilePush {
private AmazonSNSClientWrapper snsClientWrapper;
public SNSMobilePush(AmazonSNS snsClient) {
this.snsClientWrapper = new AmazonSNSClientWrapper(snsClient);
}
public static final Map<Platform, Map<String, MessageAttributeValue>> attributesMap = new HashMap<Platform, Map<String, MessageAttributeValue>>();
static {
attributesMap.put(Platform.ADM, null);
attributesMap.put(Platform.GCM, null);
attributesMap.put(Platform.APNS, null);
attributesMap.put(Platform.APNS_SANDBOX, null);
attributesMap.put(Platform.BAIDU, addBaiduNotificationAttributes());
attributesMap.put(Platform.WNS, addWNSNotificationAttributes());
attributesMap.put(Platform.MPNS, addMPNSNotificationAttributes());
}
public static void main(String[] args) throws IOException {
/*
* TODO: Be sure to fill in your AWS access credentials in the
* AwsCredentials.properties file before you try to run this sample.
* http://aws.amazon.com/security-credentials
*/
AmazonSNS sns = new AmazonSNSClient(new PropertiesCredentials(
SNSMobilePush.class
.getResourceAsStream("AwsCredentials.properties")));
sns.setEndpoint("https://sns.us-west-2.amazonaws.com");
System.out.println("===========================================\n");
System.out.println("Getting Started with Amazon SNS");
System.out.println("===========================================\n");
try {
SNSMobilePush sample = new SNSMobilePush(sns);
/* TODO: Uncomment the services you wish to use. */
sample.demoAndroidAppNotification();
// sample.demoKindleAppNotification();
// sample.demoAppleAppNotification();
// sample.demoAppleSandboxAppNotification();
// sample.demoBaiduAppNotification();
// sample.demoWNSAppNotification();
// sample.demoMPNSAppNotification();
} catch (AmazonServiceException ase) {
System.out
.println("Caught an AmazonServiceException, which means your request made it "
+ "to Amazon SNS, but was rejected with an error response for some reason.");
System.out.println("Error Message: " + ase.getMessage());
System.out.println("HTTP Status Code: " + ase.getStatusCode());
System.out.println("AWS Error Code: " + ase.getErrorCode());
System.out.println("Error Type: " + ase.getErrorType());
System.out.println("Request ID: " + ase.getRequestId());
} catch (AmazonClientException ace) {
System.out
.println("Caught an AmazonClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with SNS, such as not "
+ "being able to access the network.");
System.out.println("Error Message: " + ace.getMessage());
}
}
public void demoAndroidAppNotification() {
// TODO: Please fill in following values for your application. You can
// also change the notification payload as per your preferences using
// the method
// com.amazonaws.sns.samples.tools.SampleMessageGenerator.getSampleAndroidMessage()
String serverAPIKey = "REPLACED_WITH_SERVER_API_KEY";
String applicationName = "snspushtest";
String registrationId = "REPLACED_WITH_REG_ID_FROM_AMAZON";
snsClientWrapper.demoNotification(Platform.GCM, "", serverAPIKey,
registrationId, applicationName, attributesMap);
}
public void demoKindleAppNotification() {
// TODO: Please fill in following values for your application. You can
// also change the notification payload as per your preferences using
// the method
// com.amazonaws.sns.samples.tools.SampleMessageGenerator.getSampleKindleMessage()
String clientId = "";
String clientSecret = "";
String applicationName = "";
String registrationId = "";
snsClientWrapper.demoNotification(Platform.ADM, clientId, clientSecret,
registrationId, applicationName, attributesMap);
}
public void demoAppleAppNotification() {
// TODO: Please fill in following values for your application. You can
// also change the notification payload as per your preferences using
// the method
// com.amazonaws.sns.samples.tools.SampleMessageGenerator.getSampleAppleMessage()
String certificate = ""; // This should be in pem format with \n at the
// end of each line.
String privateKey = ""; // This should be in pem format with \n at the
// end of each line.
String applicationName = "";
String deviceToken = ""; // This is 64 hex characters.
snsClientWrapper.demoNotification(Platform.APNS, certificate,
privateKey, deviceToken, applicationName, attributesMap);
}
public void demoAppleSandboxAppNotification() {
// TODO: Please fill in following values for your application. You can
// also change the notification payload as per your preferences using
// the method
// com.amazonaws.sns.samples.tools.SampleMessageGenerator.getSampleAppleMessage()
String certificate = ""; // This should be in pem format with \n at the
// end of each line.
String privateKey = ""; // This should be in pem format with \n at the
// end of each line.
String applicationName = "";
String deviceToken = ""; // This is 64 hex characters.
snsClientWrapper.demoNotification(Platform.APNS_SANDBOX, certificate,
privateKey, deviceToken, applicationName, attributesMap);
}
public void demoBaiduAppNotification() {
/*
* TODO: Please fill in the following values for your application. If
* you wish to change the properties of your Baidu notification, you can
* do so by modifying the attribute values in the method
* addBaiduNotificationAttributes() . You can also change the
* notification payload as per your preferences using the method
* com.amazonaws
* .sns.samples.tools.SampleMessageGenerator.getSampleBaiduMessage()
*/
String userId = "";
String channelId = "";
String apiKey = "";
String secretKey = "";
String applicationName = "";
snsClientWrapper.demoNotification(Platform.BAIDU, apiKey, secretKey,
channelId + "|" + userId, applicationName, attributesMap);
}
public void demoWNSAppNotification() {
/*
* TODO: Please fill in the following values for your application. If
* you wish to change the properties of your WNS notification, you can
* do so by modifying the attribute values in the method
* addWNSNotificationAttributes() . You can also change the notification
* payload as per your preferences using the method
* com.amazonaws.sns.samples
* .tools.SampleMessageGenerator.getSampleWNSMessage()
*/
String notificationChannelURI = "";
String packageSecurityIdentifier = "";
String secretKey = "";
String applicationName = "";
snsClientWrapper.demoNotification(Platform.WNS,
packageSecurityIdentifier, secretKey, notificationChannelURI,
applicationName, attributesMap);
}
public void demoMPNSAppNotification() {
/*
* TODO: Please fill in the following values for your application. If
* you wish to change the properties of your MPNS notification, you can
* do so by modifying the attribute values in the method
* addMPNSNotificationAttributes() . You can also change the
* notification payload as per your preferences using the method
* com.amazonaws
* .sns.samples.tools.SampleMessageGenerator.getSampleMPNSMessage ()
*/
String notificationChannelURI = "";
String applicationName = "";
snsClientWrapper.demoNotification(Platform.MPNS, "", "",
notificationChannelURI, applicationName, attributesMap);
}
private static Map<String, MessageAttributeValue> addBaiduNotificationAttributes() {
Map<String, MessageAttributeValue> notificationAttributes = new HashMap<String, MessageAttributeValue>();
notificationAttributes.put("AWS.SNS.MOBILE.BAIDU.DeployStatus",
new MessageAttributeValue().withDataType("String")
.withStringValue("1"));
notificationAttributes.put("AWS.SNS.MOBILE.BAIDU.MessageKey",
new MessageAttributeValue().withDataType("String")
.withStringValue("default-channel-msg-key"));
notificationAttributes.put("AWS.SNS.MOBILE.BAIDU.MessageType",
new MessageAttributeValue().withDataType("String")
.withStringValue("0"));
return notificationAttributes;
}
private static Map<String, MessageAttributeValue> addWNSNotificationAttributes() {
Map<String, MessageAttributeValue> notificationAttributes = new HashMap<String, MessageAttributeValue>();
notificationAttributes.put("AWS.SNS.MOBILE.WNS.CachePolicy",
new MessageAttributeValue().withDataType("String")
.withStringValue("cache"));
notificationAttributes.put("AWS.SNS.MOBILE.WNS.Type",
new MessageAttributeValue().withDataType("String")
.withStringValue("wns/badge"));
return notificationAttributes;
}
private static Map<String, MessageAttributeValue> addMPNSNotificationAttributes() {
Map<String, MessageAttributeValue> notificationAttributes = new HashMap<String, MessageAttributeValue>();
notificationAttributes.put("AWS.SNS.MOBILE.MPNS.Type",
new MessageAttributeValue().withDataType("String")
.withStringValue("token")); // This attribute is required.
notificationAttributes.put("AWS.SNS.MOBILE.MPNS.NotificationClass",
new MessageAttributeValue().withDataType("String")
.withStringValue("realtime")); // This attribute is required.
return notificationAttributes;
}
}
EDIT 2:
EDIT 3:
I changed the following code to:
AmazonSNS sns = new AmazonSNSClient(new PropertiesCredentials(
SNSMobilePush.class
.getResourceAsStream("AwsCredentials.properties")));
to
AmazonSNS sns = new AmazonSNSClient(new BasicAWSCredentials("ACCESS_KEY_REPLACED",
"SECRET_KEY_REPLACED"));
Now, there is a different error: Logcat
===========================================
Getting Started with Amazon SNS
===========================================
Exception in thread "main" java.lang.NoClassDefFoundError: org/xmlpull/v1/XmlPullParserException
at com.amazonaws.services.sns.AmazonSNSClient.invoke(AmazonSNSClient.java:2263)
at com.amazonaws.services.sns.AmazonSNSClient.createPlatformApplication(AmazonSNSClient.java:358)
at com.test.tools.AmazonSNSClientWrapper.createPlatformApplication(AmazonSNSClientWrapper.java:49)
at com.test.tools.AmazonSNSClientWrapper.demoNotification(AmazonSNSClientWrapper.java:119)
at com.test.SNSMobilePush.demoAndroidAppNotification(SNSMobilePush.java:104)
at com.test.SNSMobilePush.main(SNSMobilePush.java:71)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.lang.ClassNotFoundException: org.xmlpull.v1.XmlPullParserException
at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 11 more
Process finished with exit code 1
I'm using sns v2.2.5 :
build.gradle > compile 'com.amazonaws:aws-android-sdk-sns:2.2.5'
Here is my solution for subscribe/unsubscribe:
public class AmazonPushClient {
private static final String TAG = "AmazonPushClient";
private static final String PLATFORM_APPLICATION_ARN = "*****";
private static final String IDENTITY_POOL_ID = "******";
private AmazonSNSClient mClient;
private boolean isUnregistering;
private Application mApp;
private NotifPreferencesHelper mNotifPreferencesHelper;
public AmazonPushClient(Application application) {
try {
mApp = application;
mClient = createPushClient(application);
mNotifPreferencesHelper = new NotifPreferencesHelper(application);
} catch (Exception e) {
LOGE(TAG, "AmazonPushClient", e);
}
}
#Nullable
private String token() {
try {
return InstanceID.getInstance(mApp).getToken(mApp.getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
} catch (Exception e) {
LOGW(TAG, "token", e);
return null;
}
}
private CognitoCachingCredentialsProvider cognitoCachingCredentialsProvider(Application application) {
return new CognitoCachingCredentialsProvider(
application,
IDENTITY_POOL_ID,
Regions.EU_WEST_1 // if your identity_pool_id start with : eu-west-1
);
}
private AmazonSNSClient createPushClient(Application application) {
AmazonSNSClient client = new AmazonSNSClient(cognitoCachingCredentialsProvider(application));
client.setRegion(Region.getRegion(Regions.EU_WEST_1));
client.addRequestHandler(mHandler);
return client;
}
public void pRegister() {
synchronized (TAG) {
LOGD(TAG, "registering");
isUnregistering = true;
String token = token();
if(TextUtils.isEmpty(token)) {
return;
}
mNotifPreferencesHelper.saveNotificationPreferences(true);
CreatePlatformEndpointRequest platformEndpointRequest = new CreatePlatformEndpointRequest();
platformEndpointRequest.setToken(token());
platformEndpointRequest.setPlatformApplicationArn(PLATFORM_APPLICATION_ARN);
CreatePlatformEndpointResult result = mClient.createPlatformEndpoint(platformEndpointRequest);
mNotifPreferencesHelper.storeEndpointArn(result.getEndpointArn());
}
}
public void pUnregister() {
synchronized (TAG) {
LOGD(TAG, "unregistering");
isUnregistering = false;
mNotifPreferencesHelper.saveNotificationPreferences(false);
DeleteEndpointRequest deletePlatformApplicationRequest = new DeleteEndpointRequest();
deletePlatformApplicationRequest.setEndpointArn(mNotifPreferencesHelper.getEndpointArn());
mClient.deleteEndpoint(deletePlatformApplicationRequest);
}
}
private RequestHandler2 mHandler = new RequestHandler2() {
#Override
public void beforeRequest(Request<?> request) {
}
#Override
public void afterResponse(Request<?> request, Response<?> response) {
if (isUnregistering) {
mNotifPreferencesHelper.storeEndpointArn(null);
}
}
#Override
public void afterError(Request<?> request, Response<?> response, Exception e) {
}
};
}
NotifPreferencesHelper is just something to store the EndpointARN. You have to use this class in a background thread
In association you have to implements GcmListenerService etc.. SNS is just for subscribe, not receive.
https://developers.google.com/cloud-messaging/
With respect to the Properties Credentials
A. Are you sure you are exporting the file in the build? Have you made sure you can access the file using regular file I/O outside of the credentials provider? Are you sure the file is formatted correctly (see https://github.com/aws/aws-sdk-android/blob/master/aws-android-sdk-core/src/main/java/com/amazonaws/auth/PropertiesCredentials.java)
accessKey=KEY
secretKey=SECRET
Also looking at the source you should be able to load this file yourself using http://developer.android.com/reference/java/util/Properties.html.
However, I highly recommend not using this credentials provider. It is extremely unsafe in a mobile applications. Anyone could decompile your app and steal your credentials. A much safer approach is to use Amazon Cognito, which there is a plethora of examples. (Bottom of https://docs.aws.amazon.com/mobile/sdkforandroid/developerguide/setup.html , any of the examples here: https://docs.aws.amazon.com/mobile/sdkforandroid/developerguide/getting-started-android.html as well as samples in the GitHub repo https://github.com/awslabs/aws-sdk-android-samples
Cognito requires a little bit of set-up but the guides are tested, and it really doesn't take much more than a few minutes to be much more secure.
Don't think you should import 'SNSMobilePush' to a module of your android application
In the same application, i created a new module called snspush and
imported SNSMobilePush.java file into it. Also imported the
AwsCredentials.properties file to the same path as that of
SNSMobilePush.java. Added the keys in AwsCredentials.properties file.
SNSMobilePush is just a Java app provided by AWS to do tasks like
upload (bulkupload package) several tokens (device tokens or registration IDs) to Amazon SNS or
send a push notification.
You need to register your mobile app with AWS (using AndroidMobilePushApp android app). You should obtain below information (refer this link)
Client ID and client secret
API key
Device token or Registration ID (per device)
Then you can use SNSMobilePush java app or even a AWS SNS console as described here to send push notification to your registered device.
I would suggest you to try out sending push notification from the console instead of java app. You can register tokens from devices that will install your app in the future as described in the one of the options (preferably the last option) as described here

Is it possible to understand notification comes from which client?

I send notification one client to another successfully. With this method:
ParsePush push = new ParsePush();
String yourMessage = "hello world";
push.setChannel("seconddevice");
push.setMessage(yourMessage);
push.sendInBackground();
my application:
public class ParseApplication extends Application {
String YOUR_APPLICATION_ID="xxx",YOUR_CLIENT_KEY="yyy";
#Override
public void onCreate() {
super.onCreate();
// Add your initialization code here
Parse.initialize(this, YOUR_APPLICATION_ID, YOUR_CLIENT_KEY);
ParseUser.enableAutomaticUser();
ParseACL defaultACL = new ParseACL();
// If you would like all objects to be private by default, remove this line.
defaultACL.setPublicReadAccess(true);
ParseACL.setDefaultACL(defaultACL, true);
PushService.subscribe(this, DEVICE_NAME, NotificationBck.class);
}
}
It works. But when I receive message in second device can I have which device send this notification?
From the Parse Android docs:
The Intent object which is passed to the receiver contains an extras Bundle with two useful mappings. The com.parse.Channel key points to a string representing the channel that the message was sent on. The com.parse.Data key points to a string representing the JSON-encoded value of the "data" dictionary that was set in the push notification.
So, in your receiver, you'd be able to check the data (assuming you've set it when pushing):
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
String channel = intent.getExtras().getString("com.parse.Channel");
String encodedJson = intent.getExtras().getString("com.parse.Data");
Log.d(TAG, "got action " + action + " on channel " + channel + " with:");
JSONObject json = decodeJsonObjectFrom(encodedJson);
logContentsOf(json);
}
private JSONObject decodeJsonObjectFrom(String encodedJson) {
try {
return new JSONObject(encodedJson);
} catch (JSONException e) {
return new JSONObject();
}
}
private void logContentsOf(JSONObject json) {
while (json.keys().hasNext()) {
String key = (String) json.keys().next();
Log.d(TAG, "..." + key + " => " + getStringFrom(json, key));
}
}
private String getStringFrom(JSONObject json, String key) {
try {
return (String) json.get(key);
} catch (JSONException e) {
return "";
}
}

how to retrive Registration id and send message to third-party application in android c2dm0+

The sender ID is used in the registration process for c2dm.but there has no receive messages or any register id.
//Akashc2dmActivity.java file
public class Akashc2dmActivity extends Activity implements OnClickListener {
Button Register,id;
private static PowerManager.WakeLock mWakeLock;
private static final String WAKELOCK_KEY = "C2DM_LIB";
#Override
protected void onCreate(Bundle savedInstanceState) {
if (mWakeLock == null) {
PowerManager pm = (PowerManager) Akashc2dmActivity.this
.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
WAKELOCK_KEY);
}
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Register = (Button) findViewById(R.id.button);
Register.setOnClickListener(this);
}
public void sendRequest(View ignored) {
Log.d("Register", "hello");
Intent registrationIntent = new Intent(Constants.SEND_REGISTRATION_TO_GOOGLE);
iHaveNoClueWhatThisSettingDoesButItIsRequiredForTheIntentToWorkSoIBetterSetIt(registrationIntent);
registrationIntent.putExtra("sender", Constants.C2DM_APPLICATION_SERVER_ID);
startService(registrationIntent);
}
private void iHaveNoClueWhatThisSettingDoesButItIsRequiredForTheIntentToWorkSoIBetterSetIt(Intent registrationIntent) {
registrationIntent.putExtra("app", PendingIntent.getBroadcast(Akashc2dmActivity.this, 0, new Intent(), 0));
Log.d("app", ""+PendingIntent.getBroadcast(Akashc2dmActivity.this, 0, new Intent(), 0));
}
#Override
public void onClick(View v) {
if(v == Register){
sendRequest(Register);
}
}
}
// Constants.java files
public class Constants {
public static final String TAG = "c2dm";
public static final String REGISTRATION_INTENT = "com.google.android.c2dm.intent.REGISTER";
public static final String SEND_REGISTRATION_TO_GOOGLE = "com.google.android.c2dm.intent.REGISTER";
public static final String RECEIVED_REGISTRATION_ID_FROM_GOOGLE = "com.google.android.c2dm.intent.REGISTRATION";
public static final String RECEIVED_C2DM_MESSAGE_FROM_GOOGLE = "com.google.android.c2dm.intent.RECEIVE";
public static final String START_C2DM_SERVICE = "com.google.android.c2dm.intent.START_SERVICE";
public static final String C2DM_APPLICATION_SERVER_ID = "akash.singh55#gmail.com";
private Constants() {
}
}
//C2DMBroadcastReceiver.java file
public class C2DMBroadcastReceiver extends BroadcastReceiver {
#Override
public final void onReceive(Context context, Intent intent) {
if (Constants.RECEIVED_REGISTRATION_ID_FROM_GOOGLE.equals(intent.getAction())) {
Log.d(Constants.TAG, "Received a registration ID from Google.");
intent.setAction(Constants.REGISTRATION_INTENT);
intent.setClassName(context, RegistrationIDReceiver.class.getName());
} else if (Constants.RECEIVED_C2DM_MESSAGE_FROM_GOOGLE.equals(intent.getAction())) {
Log.d(Constants.TAG, "Received a C2DM message from Google.");
intent.setAction(Constants.START_C2DM_SERVICE);
intent.setClass(context, C2DMService.class);
}
context.startService(intent);
}
}
//C2DMService.java file
public class C2DMService extends Service {
#Override
public IBinder onBind(Intent intent) {
Log.e(com.technosoft.Akashc2dm.Constants.TAG, "I was awakend by C2DM!");
return new Binder();
}
}
//RegistrationException.java files
public class RegistrationException extends Exception {
private final String usedUrl;
private final int responseCode;
public RegistrationException(String message, String usedUrl, int responseCode) {
super(message);
this.usedUrl = usedUrl;
this.responseCode = responseCode;
}
public RegistrationException(String message, Throwable cause) {
super(message, cause);
usedUrl = "";
responseCode = 0;
}
public RegistrationException(String message, String usedUrl, IOException e) {
super(message, e);
this.usedUrl = usedUrl;
responseCode = 0;
}
#Override
public String getMessage() {
return String.format("%s; URL: %s; Response code: %d",
super.getMessage(), usedUrl, responseCode);
}
}
//RegistrationIDReceiver.java files
public class RegistrationIDReceiver extends IntentService {
NotificationManager nm;
public static final String EXTRA_UNREGISTERED = "unregistered";
private final RegistrationIDRegistrar registrar =
RegistrationIDRegistrar.getInstance();
private static final String EXTRA_ERROR = "error";
private static final String EXTRA_REGISTRATION_ID = "registration_id";
public RegistrationIDReceiver() {
super(Constants.C2DM_APPLICATION_SERVER_ID);
}
#Override
public final void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
String message = (String)extras.get("message");
Log.d("Tag", "msg:" + message);
Log.d(Constants.TAG, "Received intent to register");
final String registrationId = intent.getStringExtra(
EXTRA_REGISTRATION_ID);
notifcation(registrationId);
String error = intent.getStringExtra(EXTRA_ERROR);
if (error == null) {
registerDevice(registrationId);
} else {
handleRegistrationError(error);
}
}
private void notifcation(String id) {
nm = (NotificationManager) RegistrationIDReceiver.this.getSystemService(Context.NOTIFICATION_SERVICE);
CharSequence from = "Please Testing for Recive id";
CharSequence message = "received ID"+id;
Intent notifyintent = new Intent(getApplicationContext(),Akashc2dmActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 0,notifyintent, 0);
Notification notif = new Notification(R.drawable.ic_launcher,"Please take your Looking 4 Answers daily survey now", System.currentTimeMillis());
notif.setLatestEventInfo(getApplicationContext(), from, message, contentIntent);
nm.notify(1, notif);
}
private void registerDevice(String registrationId) {
Log.d(Constants.TAG, "Will now register device with ID: " +
registrationId);
try {
registrar.registerIdWithC2DMService(registrationId);
} catch (RegistrationException e) {
Log.e(Constants.TAG, e.getMessage(), e);
}
}
private void handleRegistrationError(String error) {
Log.e(Constants.TAG, "Registration error " + error);
Log.e(Constants.TAG,
"Please click the registration button again to register the device.");
}
}
//RegistrationIDRegistrar.java files
class RegistrationIDRegistrar {
private static final String REGISTER_NEW_DEVICE = "register_device";
private static final String NODE_ID_PARAMETER = "nodeid";
private static final String REGISTRATION_IS_PARAMETER = "registrationid";
private final String url;
static final String MASHMOBILE_C2DM_SERVER_URL = "http://10.0.1.3:8888";
private RegistrationIDRegistrar(String url) {
this.url = url;
}
void registerIdWithC2DMService(final String registrationId) throws RegistrationException {
DefaultHttpClient httpClient = new DefaultHttpClient();
String nodeId = "realNodeId";
final String requestUrl = createRegistrationUrl(registrationId, nodeId);
HttpGet request = new HttpGet(requestUrl);
try {
HttpResponse response = httpClient.execute(request);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != 200) {
throw new RegistrationException(String.format(
"Could not register %s with the server.", registrationId),
requestUrl, statusCode);
}
} catch (IOException e) {
throw new RegistrationException(String.format(
"Registration of %s failed.", registrationId), requestUrl, e);
}
}
private String createRegistrationUrl(String registrationId, String nodeId) {
return String.format("%s/%s?%s=%s&%s=%s",
url, REGISTER_NEW_DEVICE, NODE_ID_PARAMETER, nodeId,
REGISTRATION_IS_PARAMETER, registrationId);
}
static RegistrationIDRegistrar getInstance() {
return new RegistrationIDRegistrar(MASHMOBILE_C2DM_SERVER_URL);
}
}
and at last use manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.technosoft.Akashc2dm"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<permission
android:name="com.google.android.c2dm.permission.C2D_MESSAGE"
android:protectionLevel="signature"/>
<uses-permission
android:name="com.google.android.c2dm.permission.C2D_MESSAGE"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".Akashc2dmActivity"
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=".C2DMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND"
>
<intent-filter>
<action
android:name="com.google.android.c2dm.intent.REGISTRATION"/>
<category android:name="com.technosoft.Akashc2dm"/>
</intent-filter>
<intent-filter>
<action
android:name="com.google.android.c2dm.intent.RECEIVE"/>
<category android:name="com.technosoft.Akashc2dm"/>
</intent-filter>
</receiver>
<service android:name=".RegistrationIDReceiver"
>
<intent-filter>
<action
android:name="com.technosoft.c2dm.intent.REGISTER"/>
<category android:name="com.technosoft.Akashc2dm"/>
</intent-filter>
</service>
<service
android:name=".C2DMService">
<intent-filter>
<action
android:name="com.technosoft.c2dm.intent.START_SERVICE"/>
<category android:name="com.technosoft.Akashc2dm"/>
</intent-filter>
</service>
<meta-data android:value="true" android:name="ADMOB_ALLOW_LOCATION_FOR_ADS"/>
</application>
please tell me how to fetch register id and send massage to third party appication in c2dm
There has above code code working successfully.There has some change
in C2DMBroadcastReceiver.java class for receive message and There has
add MessageClass.java class for sending message to server
C2DMBroadcastReceiver.java file
public class C2DMBroadcastReceiver extends BroadcastReceiver {
NotificationManager nm;
#Override
public final void onReceive(Context context, Intent intent) {
if (Constants.RECEIVED_REGISTRATION_ID_FROM_GOOGLE.equals(intent.getAction())) {
Log.d(Constants.TAG, "Received a registration ID from Google.");
intent.setAction(Constants.REGISTRATION_INTENT);
intent.setClassName(context, RegistrationIDReceiver.class.getName());
} else if (Constants.RECEIVED_C2DM_MESSAGE_FROM_GOOGLE.equals(intent.getAction())) {
Function_notification(context,intent);
Log.d(Constants.TAG, "Received a C2DM message from Google.");
intent.setAction(Constants.START_C2DM_SERVICE);
intent.setClass(context, C2DMService.class);
}
context.startService(intent);
}
private void Function_notification(Context context,Intent intent ) {
Bundle extras = intent.getExtras();
Log.d("extras",""+extras);
String message2 = (String)extras.get("collapse_key");
Log.d("collapse_key","collapse_key=" + message2);
String message1 = (String)extras.get("payload");
Log.d("extras","payload=" + message1);
String error = intent.getStringExtra("error");
Log.d("extras","error=" + error);
nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
CharSequence from = "Please Testing for Recive message";
CharSequence message = message1;
Intent notifyintent = new Intent(context,Akashc2dmActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,notifyintent, 0);
Notification notif = new Notification(R.drawable.icon,"Please take your Recive message", System.currentTimeMillis());
notif.setLatestEventInfo(context, from, message, contentIntent);
nm.notify(1, notif);
}
}
> **Add This class in com.technosoft.C2dm_Server_1 package**
MessageClass .java file
public class MessageClass {
public static final String PARAM_REGISTRATION_ID = "registration_id";
public static final String PARAM_DELAY_WHILE_IDLE = "delay_while_idle";
public static final String PARAM_COLLAPSE_KEY = "collapse_key";
private static final String UTF8 = "UTF-8";
public static String sendMessage(String auth_token, String registrationId,
String message) throws IOException {
StringBuilder postDataBuilder = new StringBuilder();
postDataBuilder.append(PARAM_REGISTRATION_ID).append("=")
.append(registrationId);
postDataBuilder.append("&").append(PARAM_COLLAPSE_KEY).append("=")
.append("1");
postDataBuilder.append("&").append("data.payload").append("=")
.append(URLEncoder.encode("hello", UTF8));
byte[] postData = postDataBuilder.toString().getBytes(UTF8);
// Hit the dm URL.
URL url = new URL("https://android.clients.google.com/c2dm/send");
HttpsURLConnection
.setDefaultHostnameVerifier(new CustomizedHostnameVerifier());
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded;charset=UTF-8");
conn.setRequestProperty("Content-Length",
Integer.toString(postData.length));
conn.setRequestProperty("Authorization", "GoogleLogin auth="
+ auth_token);
OutputStream out = conn.getOutputStream();
out.write(postData);
out.close();
int responseCode = conn.getResponseCode();
if (responseCode == 401 || responseCode == 403) {
// The token is too old - return false to retry later, will
// fetch the token
// from DB. This happens if the password is changed or token
// expires. Either admin
// is updating the token, or Update-Client-Auth was received by
// another server,
// and next retry will get the good one from database.
Log.d("C2DM", "Unauthorized - need token");
}
String updatedAuthToken = conn.getHeaderField("Update-Client-Auth");
if (updatedAuthToken != null && !auth_token.equals(updatedAuthToken)) {
Log.d("C2DM",
"Got updated auth token from datamessaging servers: "
+ updatedAuthToken);
sendMessage(updatedAuthToken,registrationId,
message);
}
String responseLine = new BufferedReader(new InputStreamReader(
conn.getInputStream())).readLine();
// NOTE: You *MUST* use exponential backoff if you receive a 503
// response code.
// Since App Engine's task queue mechanism automatically does this
// for tasks that
// return non-success error codes, this is not explicitly
// implemented here.
// If we weren't using App Engine, we'd need to manually implement
// this.
if (responseLine == null || responseLine.equals("")) {
Log.i("C2DM", "Got " + responseCode
+ " response from Google AC2DM endpoint.");
throw new IOException(
"Got empty response from Google AC2DM endpoint.");
}
String[] responseParts = responseLine.split("=", 2);
if (responseParts.length != 2) {
Log.e("C2DM", "Invalid message from google: " + responseCode
+ " " + responseLine);
throw new IOException("Invalid response from Google "
+ responseCode + " " + responseLine);
}
if (responseParts[0].equals("id")) {
Log.i("Tag", "Successfully sent data message to device: "
+ responseLine);
}
if (responseParts[0].equals("Error")) {
String err = responseParts[1];
Log.w("C2DM",
"Got error response from Google datamessaging endpoint: "
+ err);
// No retry.
throw new IOException(err);
}
return responseLine;
}
private static class CustomizedHostnameVerifier implements HostnameVerifier {
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
}
**This class use in RegistrationIDRegistrar.java class**
RegistrationIDRegistrar.java file
class RegistrationIDRegistrar {
static final String MASHMOBILE_C2DM_SERVER_URL = "http://10.0.1.3:8888";
String response;
private RegistrationIDRegistrar(String url) {
}
void registerIdWithC2DMService(final String registrationId){
//getAuthentification();
Log.d("registrationId", ""+registrationId);
try {
String auth_key =getToken(Constants.C2DM_APPLICATION_SERVER_ID,Constants.C2DM_APPLICATION_SERVER_Password);
Log.d("auth_key", ""+auth_key);
response = MessageClass.sendMessage(auth_key,registrationId, "hello test android");
Log.d("Response code", ""+response);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static String getToken(String email, String password)
throws IOException {
// Create the post data
// Requires a field with the email and the password
StringBuilder builder = new StringBuilder();
builder.append("Email=").append(email);
builder.append("&Passwd=").append(password);
builder.append("&accountType=GOOGLE");
builder.append("&source=MyLittleExample");
builder.append("&service=ac2dm");
// Setup the Http Post
byte[] data = builder.toString().getBytes();
URL url = new URL("https://www.google.com/accounts/ClientLogin");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setUseCaches(false);
con.setDoOutput(true);
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
con.setRequestProperty("Content-Length", Integer.toString(data.length));
// Issue the HTTP POST request
OutputStream output = con.getOutputStream();
output.write(data);
output.close();
// Read the response
BufferedReader reader = new BufferedReader(new InputStreamReader(
con.getInputStream()));
String line = null;
String auth_key = null;
while ((line = reader.readLine()) != null) {
if (line.startsWith("Auth=")) {
auth_key = line.substring(5);
Log.d("auth_key", ""+auth_key);
}
}
// Finally get the authentication token
// To something useful with it
return auth_key;
}
static RegistrationIDRegistrar getInstance() {
return new RegistrationIDRegistrar(MASHMOBILE_C2DM_SERVER_URL);
}
}
C2DMBroadcastReceiver.java file
if (Constants.RECEIVED_REGISTRATION_ID_FROM_GOOGLE.equals(intent.getAction())) {
//here you can get registration id
final String registrationId = intent
.getStringExtra("registration_id");
/*your code*/
}
and then call registerIdWithC2DMService(registrationId) method from RegistrationIDRegistrar class.

Categories

Resources