I am developing one application and in that application I need to implement push notifications. Can anyone suggest how I should go about implementing push notifications? If I could be provided with a good tutorial, that would be great!
Thanks.
// Call when your application start
public void StartRegistrationNotification()
{
Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER");
registrationIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0));
registrationIntent.putExtra("sender", "....#gmail.com");
this.startService(registrationIntent);
}
// change in Manifest File
<receiver android:name="com.ReceiverC2DM"
android:permission="com.google.android.c2dm.permission.SEND">
<!-- Receive the actual message -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="yourpackagename" />
</intent-filter>
<!-- Receive the registration id -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="yourpackagename" />
</intent-filter>
</receiver>
<permission android:name="yourpackagename.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="yourpackagename.permission.C2D_MESSAGE" />
<!-- This app has permission to register and receive message -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
// ReceiverC2DM.java .....
public class ReceiverC2DM extends BroadcastReceiver {
private static String KEY = "c2dmPref";
private static String REGISTRATION_KEY = "registrationKey";
private Context context;
// wakelock
private static final String WAKELOCK_KEY = "C2DM_FAX";
private static PowerManager.WakeLock mWakeLock;
#Override
public void onReceive(Context context, Intent intent) {
this.context = context;
runIntentInService(context, intent);
if (intent.getAction().equals("com.google.android.c2dm.intent.REGISTRATION")) {
handleRegistration(context, intent);
} else if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) {
handleMessage(context, intent);
}
}
private void handleRegistration(Context context, Intent intent) {
String registration = intent.getStringExtra("registration_id");
Log.e("registration :","registration :"+registration);
if (intent.getStringExtra("error") != null) {
// Registration failed, should try again later.
Log.d("c2dm", "registration failed");
String error = intent.getStringExtra("error");
if(error == "SERVICE_NOT_AVAILABLE"){
Log.d("c2dm", "SERVICE_NOT_AVAILABLE");
}else if(error == "ACCOUNT_MISSING"){
Log.d("c2dm", "ACCOUNT_MISSING");
}else if(error == "AUTHENTICATION_FAILED"){
Log.d("c2dm", "AUTHENTICATION_FAILED");
}else if(error == "TOO_MANY_REGISTRATIONS"){
Log.d("c2dm", "TOO_MANY_REGISTRATIONS");
}else if(error == "INVALID_SENDER"){
Log.d("c2dm", "INVALID_SENDER");
}else if(error == "PHONE_REGISTRATION_ERROR"){
Log.d("c2dm", "PHONE_REGISTRATION_ERROR");
}
} else if (intent.getStringExtra("unregistered") != null) {
// unregistration done, new messages from the authorized sender will be rejected
Log.d("c2dm", "unregistered");
} else if (registration != null) {
Log.d("c2dm", registration);
Editor editor =
context.getSharedPreferences(KEY, Context.MODE_PRIVATE).edit();
editor.putString(REGISTRATION_KEY, registration);
editor.commit();
// Send the registration ID to the 3rd party site that is sending the messages.
// This should be done in a separate thread.
// When done, remember that all registration is done.
}
}
private void handleMessage(Context context, Intent intent)
{
String message = intent.getExtras().getString("payload");
String key = intent.getExtras().getString("collapse_key");
Log.e("","accountName : " +accountName);
Log.e("","message : " +message);
Intent startActivity = new Intent();
startActivity.setClass(context, NotificationAlert.class);
startActivity.setAction(NotificationAlert.class.getName());
startActivity.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
startActivity.putExtra("Title", "Hello");
startActivity.putExtra("Message", message);
context.startActivity(startActivity);
//Do whatever you want with the message
}
static void runIntentInService(Context context, Intent intent) {
if (mWakeLock == null) {
// This is called from BroadcastReceiver, there is no init.
PowerManager pm =
(PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
WAKELOCK_KEY);
}
mWakeLock.acquire();
}
// Server Side ... New Test App
ServerSimulator.java
private SharedPreferences prefManager;
private final static String AUTH = "authentication";
private static final String UPDATE_CLIENT_AUTH = "Update-Client-Auth";
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";
// Registration is currently hardcoded
private final static String YOUR_REGISTRATION_STRING = "put registration key";
private SharedPreferences prefs;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
prefManager = PreferenceManager.getDefaultSharedPreferences(this);
}
public void getAuthentification(View view) {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(this);
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(
"https://www.google.com/accounts/ClientLogin");
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("Email", "....#gmail.com"));
nameValuePairs.add(new BasicNameValuePair("Passwd","....."));
nameValuePairs.add(new BasicNameValuePair("accountType", "GOOGLE"));
nameValuePairs.add(new BasicNameValuePair("source",
"Google-cURL-Example"));
nameValuePairs.add(new BasicNameValuePair("service", "ac2dm"));
post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = client.execute(post);
BufferedReader rd = new BufferedReader(new InputStreamReader(
response.getEntity().getContent()));
String line = "";
while ((line = rd.readLine()) != null) {
Log.e("HttpResponse", line);
if (line.startsWith("Auth=")) {
Editor edit = prefManager.edit();
edit.putString(AUTH, line.substring(5));
edit.commit();
String s = prefManager.getString(AUTH, "n/a");
Toast.makeText(this, s, Toast.LENGTH_LONG).show();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void showAuthentification(View view) {
String s = prefManager.getString(AUTH, "n/a");
Toast.makeText(this, s, Toast.LENGTH_LONG).show();
}
public void sendMessage(View view) {
try {
Log.e("Tag", "Started");
String auth_key = prefManager.getString(AUTH, "n/a");
// Send a sync message to this Android device.
StringBuilder postDataBuilder = new StringBuilder();
postDataBuilder.append(PARAM_REGISTRATION_ID).append("=")
.append(YOUR_REGISTRATION_STRING);
// if (delayWhileIdle) {
// postDataBuilder.append("&").append(PARAM_DELAY_WHILE_IDLE)
// .append("=1");
// }
postDataBuilder.append("&").append(PARAM_COLLAPSE_KEY).append("=")
.append("0");
postDataBuilder.append("&").append("data.payload").append("=")
.append(URLEncoder.encode("Fax Sent ... Test Push Notification ....", UTF8));
Log.e("postDataBuilder ","postDataBuilder :" + postDataBuilder.toString());
byte[] postData = postDataBuilder.toString().getBytes(UTF8);
// Hit the dm URL.
URL url = new URL("https://android.clients.google.com/c2dm/send");
HttpURLConnection conn = (HttpURLConnection) 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_key);
OutputStream out = conn.getOutputStream();
out.write(postData);
out.close();
int responseCode = conn.getResponseCode();
Log.e("Tag", String.valueOf(responseCode));
// Validate the response code
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.e("C2DM", "Unauthorized - need token");
}
// Check for updated token header
String updatedAuthToken = conn.getHeaderField(UPDATE_CLIENT_AUTH);
if (updatedAuthToken != null && !auth_key.equals(updatedAuthToken)) {
Log.i("C2DM",
"Got updated auth token from datamessaging servers: "
+ updatedAuthToken);
Editor edit = prefManager.edit();
edit.putString(AUTH, updatedAuthToken);
}
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);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
C2DM is deprecated and has been replaced by Google Cloud Messaging for Android (GCM).
Google's statement:
Important: C2DM has been officially deprecated as of June 26, 2012.
This means that C2DM has stopped accepting new users and quota
requests. No new features will be added to C2DM. However, apps using
C2DM will continue to work. Existing C2DM developers are encouraged
to migrate to the new version of C2DM, called Google Cloud Messaging
for Android (GCM). See the C2DM-to-GCM Migration document for more
information. Developers must use GCM for new development.
There is a demo app tutorial for GCM and also for migration from C2DM.
Related
I am new to the community and I have joined because of the need to highlight a problem that I have not been able to solve.
Thank you in advance for any answer you can give me to help me.
I am currently developing a project in android studio and I am using as a firebase database, I have come to have the need to share a product, post or list that is within my application. Because of this I have decided to use Firebase Dynamic Link to share some specific object.
My current code tries to create a link and share it, I would like to know what I am doing wrong, since it creates the link and lets me share it, but it is not getting the parameter that I am passing. In my case "Lid" is the parameter that I want to pass through the link and when clicking on the link, just take the part where the "Lid" is stored.
holder.BtnShare.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View v) {
generateDeepLinkUrl(postCurrent.getLid());
String url="https://palsuper.page.link/lista_compartida";
FirebaseDynamicLinks.getInstance().createDynamicLink()
.setLink( Uri.parse(url))
.setDomainUriPrefix("https://palsuper.page.link")
.setAndroidParameters(
new DynamicLink.AndroidParameters.Builder("com.ibrahim.palsuper")
.setMinimumVersion(1)
.build())
.buildShortDynamicLink( ShortDynamicLink.Suffix.SHORT).addOnCompleteListener( new OnCompleteListener<ShortDynamicLink>() {
#Override
public void onComplete(#NonNull Task<ShortDynamicLink> task) {
if (task.isSuccessful()) {
Uri shortURL = task.getResult().getShortLink();
shareDeepLink(shortURL.toString());
} else {
Toast.makeText(mContext, "error", Toast.LENGTH_SHORT).show();
}
}
});
shareDeepLink( url );
}
} );
}
private String generateDeepLinkUrl(String Lid) {
return "https://palsuper.com/lista_compartida=" + Lid ;
}
private void shareDeepLink(String url) {
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT, "Hey! check this content out " + url);
shareIntent.putExtra(Intent.EXTRA_SUBJECT, "Check this out !");
mContext.startActivity(Intent.createChooser(shareIntent, "Share this cool content"));
}
GetLink.
private void getDynamicLink() {
FirebaseDynamicLinks.getInstance()
.getDynamicLink(getIntent())
.addOnSuccessListener(this, new OnSuccessListener<PendingDynamicLinkData>() {
#Override
public void onSuccess(PendingDynamicLinkData pendingDynamicLinkData) {
// Get deep link from result (may be null if no link is found)
Uri deepLink = null;
if (pendingDynamicLinkData != null) {
deepLink = pendingDynamicLinkData.getLink();
Toast.makeText(HomeActivity.this, "Link obtenido del intent " + deepLink, Toast.LENGTH_SHORT).show();
// Log.d(TAG, "Link obtenido del intent " + deepLink.getPath());
getAndParseSharedData(deepLink.getPath());
}
}
})
.addOnFailureListener(this, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// Log.w(TAG, "getDynamicLink:onFailure", e);
}
});
}
private void getAndParseSharedData(String url) {
String pushKey = "";
if (url.contains("_")) {
String[] parts = url.split("=");
pushKey = parts[1];
// Log.d(TAG, "getAndParseSharedData: " + pushKey);
Toast.makeText(HomeActivity.this, pushKey, Toast.LENGTH_SHORT).show();
}
}
}
Joe you need to pass the parameter you want to fetch as a query parameter.
Like this:
"https://palsuper.com?lista_compartida=" + Lid;
or
"https://palsuper.com/lista_compartida?lista_compartida=" + Lid;
And then you can fetch it simply using this firebase provided method:
Uri deepLink = null;
if (pendingDynamicLinkData != null) {
deepLink = pendingDynamicLinkData.getLink();
String lista_compartida = deepLink.getQueryParameter("lista_compartida");
}
Hope this answer helps.
Go to firbase console dynamic link section and then create a dynamic link such as
https://xyz.page.link and then use below code to generate and share dynamic link
fun generateContentLink(): Uri? {
val baseUrl = Uri.parse(BASE_URL)
val domain = "https://xyz.page.link"
val link = FirebaseDynamicLinks.getInstance()
.createDynamicLink()
.setLink(baseUrl)
.setDomainUriPrefix(domain)
.setAndroidParameters(AndroidParameters.Builder("com.xyz").build())
.buildDynamicLink()
return link.uri
}
private fun onShareClicked() {
try {
val link = generateContentLink()
Log.e("DynamicLnk", "onShareClicked: " + link.toString())
val subject = " Welcome to QuickPe"
val msg =
"Hi,\nInviting you to join xyz\n an interesting app which provides you\n" +
"incredible offers on Recharge, Shopping & many more.\n\n" +
"Use my referrer code :\n\n " + session()?.getInviteCode().toString() +
"\n\nDownload app from link : \n"
val intent = Intent(Intent.ACTION_SEND)
intent.type = "text/plain"
intent.putExtra(Intent.EXTRA_SUBJECT, subject)
intent.putExtra(Intent.EXTRA_TEXT,
msg + "\n" + link + "/" + session()?.getInviteCode().toString())
if (intent.resolveActivity(packageManager) != null) {
startActivity(intent)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
Now to receive code as below code in AndroidManifest.xml
<activity android:name=".xyzActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:host="https://xyz.page.link"
android:scheme="https"/>
</intent-filter>
</activity>
and in activity where you want to receive code
FirebaseDynamicLinks.getInstance()
.getDynamicLink(intent)
.addOnSuccessListener(this
) { pendingDynamicLinkData ->
// Get deep link from result (may be null if no link is found)
var deepLink: Uri? = null
if (pendingDynamicLinkData != null) {
deepLink = pendingDynamicLinkData.link
}
if (deepLink != null) { //Intent.ACTION_VIEW.equals(appLinkAction) &&
val code = deepLink.lastPathSegment
edtReferralCode.setText(code)
}
// Handle the deep link. For example, open the linked
// content, or apply promotional credit to the user's
// account.
// ...
// ...
}
.addOnFailureListener(this
) { e -> Log.w("=================>", "getDynamicLink:onFailure", e) }
I am using data messages where we can send messages even when the app is killed or in background or in foreground. I am using FCM .
But in my case sometimes my app does not get those messages . I am sending messages from app to app. Sometimes the app get messages even when it is killed or removed from background but again , sometimes it wont.
When i open the app , then suddenly the message appears. I am opening activities when a particular message is received . I know that data messages are used for sending messages even when the app is killed or in background or in foreground , but i am having problem like this . please help !..
I want it to be absolute .
I just want my app to be connected to FirebaseMessagingServices always , even when it is killed. I don't know about services and some says that i need to create a foreground services . How to create it and implement to FirebaseMessagingServices .?
MYFirebaseMessaging.java
package com.example.praful.ubercoustomer.Service;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationCompat;
import android.widget.Toast;
import com.example.praful.ubercoustomer.AcceptedWindow;
import com.example.praful.ubercoustomer.Common.Common;
import com.example.praful.ubercoustomer.CompanycancelledtheBooking;
import com.example.praful.ubercoustomer.DeclinedWindow;
import com.example.praful.ubercoustomer.Helper.NotificationHelper;
import com.example.praful.ubercoustomer.Onthewayandimreached;
import com.example.praful.ubercoustomer.R;
import com.example.praful.ubercoustomer.RateActivity;
import com.example.praful.ubercoustomer.VerifyingCompletedBooking;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import java.util.Map;
public class MyFirebaseMessaging extends FirebaseMessagingService {
#Override
public void onMessageReceived(final RemoteMessage remoteMessage) {
if (remoteMessage.getData() != null) {
Map<String, String> data = remoteMessage.getData();
String title = data.get("title");
final String companyName = data.get("CompanyName");
final String BookingIdC = data.get("BookingIdC");
final String BookingIdT = data.get("BookingIdT");
final String companyPhone = data.get("CompanyPhone");
final String companyRates = data.get("CompanyRates");
final String companyId = data.get("CompanyId");
final String Date = data.get("Date");
final String companyIdC = data.get("companyIdC");
final String Time = data.get("Time");
final String Id = data.get("Id");
final String Address = data.get("Address");
final String Bookingid = data.get("Bookingid");
final String TimeCB = data.get("TimeCB");
final String DateCB = data.get("DateCB");
final String EventType = data.get("EventType");
final String messageCB = data.get("messageCB");
final String AddressCB = data.get("AddressCB");
final String companythatcancelledthebooking = data.get("CompanyNamethatcancelledthebooking");
final String message = data.get("message");
// remoteMessage.getNotification().getTitle() = title and remoteMessage.getNotification().getBody() = message
if (title != null && title.equals("Cancel")) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(MyFirebaseMessaging.this, DeclinedWindow.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Common.isCompanyFound = false;
Common.companyId = "";
Toast.makeText(MyFirebaseMessaging.this, "" + message, Toast.LENGTH_SHORT).show();
}
});
} else if (title != null && title.equals("cancelAdvanceBooking")) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(getBaseContext(), CompanycancelledtheBooking.class);
intent.putExtra("DateCB", DateCB);
intent.putExtra("TimeCB", TimeCB);
intent.putExtra("messageCB", messageCB);
intent.putExtra("AddressCB", AddressCB);
intent.putExtra("EventType", EventType);
intent.putExtra("Id", Id);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Common.isCompanyFound = false;
Common.companyId = "";
Toast.makeText(MyFirebaseMessaging.this, "" + messageCB, Toast.LENGTH_SHORT).show();
}
});
} else if (title != null && title.equals("Accept")) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(MyFirebaseMessaging.this, AcceptedWindow.class);
intent.putExtra("Date", Date);
intent.putExtra("Time", Time);
intent.putExtra("Address", Address);
intent.putExtra("companyName", companyName);
intent.putExtra("companyPhone", companyPhone);
intent.putExtra("companyRates", companyRates);
intent.putExtra("companyId", companyId);
intent.putExtra("Bookingid", Bookingid);
intent.putExtra("EventType", EventType);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Common.isCompanyFound = false;
Common.companyId = "";
Toast.makeText(MyFirebaseMessaging.this, "" + message, Toast.LENGTH_SHORT).show();
}
});
} else if (title != null && title.equals("Arrived")) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
showArrivedNotifAPI26(message);
else
showArrivedNotif(message);
}
});
} else if (title != null && title.equals("Completed")) {
openRateactivity(message);
} else if (title != null && title.equals("completedAdvancebooking")) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(MyFirebaseMessaging.this, VerifyingCompletedBooking.class);
intent.putExtra("BookingIdC", BookingIdC);
intent.putExtra("message", message);
intent.putExtra("companyid", companyIdC);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
});
} else if (title != null && title.equals("Ontheway")) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(MyFirebaseMessaging.this, Onthewayandimreached.class);
intent.putExtra("message", message);
intent.putExtra("BookingIdT", BookingIdT);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
});
} else if (title != null && title.equals("Reached")) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(MyFirebaseMessaging.this, Onthewayandimreached.class);
intent.putExtra("message", message);
intent.putExtra("BookingIdT", BookingIdT);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
});
}
}
}
#RequiresApi(api = Build.VERSION_CODES.O)
private void showArrivedNotifAPI26(String body) {
PendingIntent contentIntent = PendingIntent.getActivity(getBaseContext(), 0,
new Intent(), PendingIntent.FLAG_ONE_SHOT);
Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationHelper notificationHelper = new NotificationHelper(getBaseContext());
Notification.Builder builder = notificationHelper.getUberNotification("Arrived", body, contentIntent, defaultSound);
notificationHelper.getManager().notify(1, builder.build());
}
private void openRateactivity(String body) {
Intent intent = new Intent(this, RateActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
private void showArrivedNotif(String body) {
PendingIntent contentIntent = PendingIntent.getActivity(getBaseContext(), 0,
new Intent(), PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(getBaseContext());
builder.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND)
.setWhen(System.currentTimeMillis()).
setSmallIcon(R.drawable.ic_menu_camera)
.setContentTitle("Arrived")
.setContentText(body)
.setContentIntent(contentIntent);
NotificationManager manager = (NotificationManager) getBaseContext().getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(1, builder.build());
}
}
MyFirebaseIdService
package com.example.praful.ubercoustomer.Service;
import com.example.praful.ubercoustomer.Common.Common;
import com.example.praful.ubercoustomer.Model.Token;
import com.example.praful.ubercoustomer.Common.Common;
import com.example.praful.ubercoustomer.Model.Token;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
public class MyFirebaseIdService extends FirebaseInstanceIdService {
#Override
public void onTokenRefresh() {
super.onTokenRefresh();
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
updateTokenToServer(refreshedToken);
}
private void updateTokenToServer(String refreshedToken) {
FirebaseDatabase db =FirebaseDatabase.getInstance();
DatabaseReference tokens = db.getReference(Common.token_table);
Token token = new Token(refreshedToken);
if(FirebaseAuth.getInstance().getCurrentUser() != null)
tokens.child(FirebaseAuth.getInstance().getCurrentUser().getUid()).setValue(token);
}
}
First check this remote message contains payload, May be payload get corrupt for any reason.
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "REMOTE_MSG";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
if (remoteMessage == null)
return;
// check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.e(TAG, "Notification body: " + remoteMessage.getNotification().getBody());
createNotification(remoteMessage.getNotification());
}
// check if message contains a data payload
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}
}
DON'T forgent to update your FCM device token on your DB.
public class MyFirebaseInstanceIdService extends FirebaseInstanceIdService {
private static final String TAG = "FCM_ID";
#Override
public void onTokenRefresh() {
// get hold of the registration token
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
// lg the token
Log.d(TAG, "Refreshed token: " + refreshedToken);
sendRegistrationToServer(refreshedToken);
}
private void sendRegistrationToServer(String token) {
// implement this method if you want to store the token on your server
}
}
Update 1
As mentioned Firebase repo issue expected that issue to be related to device, Please try another device aspect.
Update 2 Quote from firebase repo contributor kroikie
FCM does not process messages if an app is "killed" or force stopped.
When a user kills an app it is an indication that the user does not
want the app running so that app should not run till the user
explicitly starts it again.
Note that swiping an app from recents list should NOT "kill" or force
stop it. If messages are not being received after swiping from recents
list then please identify these devices and we will work with the
manufactures to correct this behaviour.
Only being able to handle messages when the app is in the foreground
or background is working as intended.
Update 3
Try hacks mentioned on this issue.
Inserting this lines in Manifest.xml
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
It is because of DOZE mode and battery optimization,you just have to turn off battery optimization for all apps or particular app. Go to Settings>> apps >> select your app>> battery>>
battery optimization> select your app>> select don't optimise.
Problem solved.
Now (for APP IS CLOSED case) I write Notification text to file and read this text if extras == null and notificationText.txt is exists... its stupid solution but it works. How can I catch this extras when app is closed in other way.
Update 4
Try to Setting the priority of a message,
Disable Battery Optimization
Users can manually configure the whitelist in Settings > Battery >
Battery Optimization. Alternatively, the system provides ways for apps
to ask users to whitelist them.
An app can fire the ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS intent
to take the user directly to the Battery Optimization, where they can
add the app. An app holding the REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
permission can trigger a system dialog to let the user add the app to
the whitelist directly, without going to settings. The app fires a
ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS Intent to trigger the
dialog. The user can manually remove apps from the whitelist as
needed.
Programmatically open Battery Optimization, check this answer.
TAKE CARE ABOUT THIS
Before asking the user to add your app to the whitelist, make sure the
app matches the acceptable use cases for whitelisting.
Note:
Google Play policies prohibit apps from requesting direct exemption from
Power Management features in Android 6.0+ (Doze and App Standby)
unless the core function of the app is adversely affected.
Update 5
Check PowerManager.isIgnoringBatteryOptimizations() from this answer.
When disable battery optimization, Consider to check first if it's already disabled then no need to show dialog, else you can show dialog.
/**
* return false if in settings "Not optimized" and true if "Optimizing battery use"
*/
private boolean checkBatteryOptimized() {
final PowerManager pwrm = (PowerManager) getSystemService(Context.POWER_SERVICE);
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return !pwrm.isIgnoringBatteryOptimizations(getBaseContext().getPackageName());
}
}catch (Exception ignored){}
return false;
}
private void startBatteryOptimizeDialog(){
try {
Intent intent = new Intent(android.provider.Settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:PUT_YOUR_PACKAGE_NAME_HERE"));
startActivity(intent);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
}
}
I want to make an app to send some information to the company via email if I have internet connection as a user and I use email intent
String priceMassage = creatOrderSummery(price, hasWippedCream, hasChocolate, name);
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto: ")); // only email apps should handle this
intent.putExtra(Intent.EXTRA_SUBJECT, "Just Java order for " + name);
intent.putExtra(Intent.EXTRA_TEXT, priceMassage);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
displayMessage(priceMassage);
but if I don't internet connection I want the information sent to company mobile number via SMS, how can I do it?
You need to check for internet connectivity first if present use email otherwise open the intent to send sms message.
for connectivity check see this helpful answer : https://stackoverflow.com/a/8548926/4428159
For sending sms I'm assuming you need to just open the sms app and send the message so have a look at this code: https://stackoverflow.com/a/9798870/4428159
For this you don't need sms permission in your application.
public void sendSMS(View v)
{
Uri uri = Uri.parse("smsto:12346556");
Intent it = new Intent(Intent.ACTION_SENDTO, uri);
it.putExtra("sms_body", "Here you can set the SMS text to be sent");
startActivity(it);
}
you need to check if the device is connected to the internet
you can check internet connection via ConnectionManager class.
ConnectivityManager cm = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
cm.getActiveNetworkInfo().isConnected(); // return true if internet or otherwise flase
if (internet){
// Email send code here
} else {
// SMS send code here
}
this is the sample solution
In order to send sms
In AndroidManifest.xml add permission
<uses-permission android:name="android.permission.SEND_SMS" />
public void sendSMS(String phoneNo, String msg) {
try {
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(phoneNo, null, msg, null, null);
Toast.makeText(getApplicationContext(), "Message Sent",
Toast.LENGTH_LONG).show();
} catch (Exception ex) {
Toast.makeText(getApplicationContext(),ex.getMessage().toString(),
Toast.LENGTH_LONG).show();
ex.printStackTrace();
}
}
You have two options to send SMS.
Using SmsManager API
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage("phoneNo", null, "sms message", null, null);
Using Built-in SMS application
Intent sendIntent = new Intent(Intent.ACTION_VIEW);
sendIntent.putExtra("sms_body", "default content");
sendIntent.setType("vnd.android-dir/mms-sms");
startActivity(sendIntent);
Both need SEND_SMS permission.
<uses-permission android:name="android.permission.SEND_SMS" />
More details can be found here
use this code to check intenet connection..in main
TestInternet testInternet = new TestInternet();
testInternet.execute();
out of main
class TestInternet extends AsyncTask<Void, Void, Boolean>
{
#Override
protected Boolean doInBackground(Void... params) {
try {
URL url = new URL("http://www.google.com");
HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
urlc.setConnectTimeout(4000);
urlc.connect();
if (urlc.getResponseCode() == 200) {
return true;
}
} catch (MalformedURLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
return false;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
return false;
}
#Override
protected void onPostExecute(Boolean result)
{
if (!result)
{
// send sms
else
{
//send mail
}
}
}
I am looking to do the following in andriod studio
User will open his mail client and click preview on a PDF. It opens the file in adobe reader.
The user makes comments in adobe and when done press share
My andriod app is shown and the users selects my app
My andriod app gets the pdf and saves it externally to my server.
I have part 1,2,3 so far but not 4,5. Its my understanding that you can not access applications storage, but a poster posted this, but I am unsure on how to use that?
In order to get the PDF you'll need to create an activity for this use case that listens for those "sharing" intents.
ShareActivity.java
void onCreate (Bundle savedInstanceState) {
// Get intent, action and MIME type
Intent intent = getIntent();
String action = intent.getAction();
String type = intent.getType();
if (Intent.ACTION_SEND.equals(action) && type != null) {
if ("application/pdf".equals(type)) {
handlePDF(intent);
}
} else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) {
if (type.startsWith("application/pdf")) {
// Handle multiple pdfs being sent
}
} else {
// Handle other intents, such as being started from the home screen
}
}
void handlePDF(Intent intent) {
Uri pdfUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
if (pdfUri != null) {
// TODO: Use your server-side here to save.
}
}
And then add this to your AndroidManifest.xml so Android knows what activity to get when they select your application to share to:
<activity android:name=".ui.ShareActivity" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/pdf" />
</intent-filter>
</activity>
public class savepdf extends ActionBarActivity {
static final int REQUEST_IMAGE_OPEN = 1;
private static final int WRITE_REQUEST_CODE = 43;
private Uri mData;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_savepdf);
// Get intent, action and MIME type
Intent intent = getIntent();
String action = intent.getAction();
String type = intent.getType();
if (Intent.ACTION_SEND.equals(action) && type != null) {
if ("application/pdf".equals(type)) {
handlePDF(intent);
}
} else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) {
if (type.startsWith("application/pdf")) {
// Handle multiple pdfs being sent
}
} else {
// Handle other intents, such as being started from the home screen
}
}
void handlePDF(Intent intent) {
Uri pdfUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
if (pdfUri != null) {
//savefile(pdfUri);
String sourceFilename= pdfUri.getPath();
String destinationFilename = android.os.Environment.getExternalStorageDirectory().getPath()+File.separatorChar+"abc.pdf";
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(sourceFilename));
bos = new BufferedOutputStream(new FileOutputStream(destinationFilename, false));
byte[] buf = new byte[1024];
bis.read(buf);
do {
bos.write(buf);
} while(bis.read(buf) != -1);
} catch (IOException e) {
} finally {
try {
if (bis != null) bis.close();
if (bos != null) bos.close();
} catch (IOException e) {
}
}
// TODO: Use your server-side here to save.
}
}
I am very new in android and web services. I am trying to login into my android app where the data is coming from web service and at the same time I want to register the Id of android device using GCM in web server database. Until now I have done so far. If possible please give me your time to assets me.
Config.Java
public class Config {
static final String SERVER_URL = "http://example/stich/wsTest/?c=profile&func=login";
static final String GOOGLE_SENDER_ID = "499319758496";
static final String TAG = "GCM";
static final String DISPLAY_MESSAGE_ACTION = "com.google.android.gcm.demo.app.DISPLAY_MESSAGE";
static final String EXTRA_MESSAGE = "message";
}
Controller.java
public class Controller extends Application {
private final int MAX_ATTEMPTS = 5;
private final int BACKOFF_MILLI_SECONDS = 2000;
private final Random random = new Random();
/**
* Creating post request and store GCM RegistrationID, email and password in
* database on our web server for later use.
*
* #param context
* #param email
* #param password
* #param RegistrationID
*/
void register(final Context context, String email, String password,
final String RegistrationID) {
Log.i(Config.TAG, "registering device (RegistrationID = "
+ RegistrationID + ")");
String serverUrl = Config.SERVER_URL;
Map<String, String> params = new HashMap<String, String>();
params.put("androidToken", RegistrationID);
params.put("email", email);
params.put("password", password);
long backoff = BACKOFF_MILLI_SECONDS + random.nextInt(1000);
// Once GCM returns a RegistrationID, we need to register on our server.
// As the server might be down, we will retry it a couple of times.
for (int i = 1; i <= MAX_ATTEMPTS; i++) {
Log.d(Config.TAG, "Attempt #" + i + "to register");
try {
// Send Broadcast to Show message on screen
displayMessageOnScreen(context, context.getString(
R.string.server_registering, i, MAX_ATTEMPTS));
// Post registration values to web server
post(serverUrl, params);
GCMRegistrar.setRegisteredOnServer(context, true);
// Send Broadcast to Show message on screen
String message = context.getString(R.string.server_registered);
displayMessageOnScreen(context, message);
return;
} catch (IOException e) {
// Here we are simplifying and retrying on any error; in a real
// application, it should retry only on unrecoverable errors
// (like HTTP error code 503).
Log.e(Config.TAG, "Failed to register on attempt " + i + ":"
+ e);
if (i == MAX_ATTEMPTS) {
break;
}
try {
Log.d(Config.TAG, "Sleeping for " + backoff
+ " ms before retry");
Thread.sleep(backoff);
} catch (InterruptedException e1) {
// Activity finished before we complete - exit.
Log.d(Config.TAG,
"Thread interrupted: abort remaining retries!");
Thread.currentThread().interrupt();
return;
}
// increase backoff exponentially
backoff *= 2;
}
}
String message = context.getString(R.string.server_register_error,
MAX_ATTEMPTS);
// Send Broadcast to show message on screen
displayMessageOnScreen(context, message);
}
/**
* Unregister device from GCM server and also creating a post request on
* server to delete stored RegistrationID from database on our web server.
*
* #param context
* #param RegistrationID
*/
void unregister(final Context context, final String RegistrationID) {
Log.i(Config.TAG, "unregistering device (regId =" + RegistrationID
+ ")");
String serverUrl = Config.CLIPME_SERVER_URL + "/unregister";
Map<String, String> params = new HashMap<String, String>();
params.put("regId", RegistrationID);
try {
post(serverUrl, params);
GCMRegistrar.setRegisteredOnServer(context, false);
String message = context.getString(R.string.server_unregistered);
displayMessageOnScreen(context, message);
} catch (IOException e) {
// At this point the device is unregistered from GCM, but still
// registered in the our server.
// We could try to unregister again, but it is not necessary:
// if the server tries to send a message to the device, it will get
// a "NotRegistered" error message and should unregister the device.
String message = context.getString(
R.string.server_unregister_error, e.getMessage());
displayMessageOnScreen(context, message);
}
}
/**
* Create HTTP Post request to server, requested url is defined in
* Config.java.
*
* #param endpoint
* #param params
* #throws IOException
*/
private void post(String endpoint, Map<String, String> params) throws IOException {
URL url;
try {
url = new URL(endpoint);
} catch (MalformedURLException e) {
throw new IllegalArgumentException("Invalid url: " + endpoint);
}
StringBuilder bodyBuilder = new StringBuilder();
Iterator<Entry<String, String>> iterator = params.entrySet().iterator();
// constructs the POST body using the parameters
while (iterator.hasNext()) {
Entry<String, String> param = iterator.next();
bodyBuilder.append(param.getKey()).append('=')
.append(param.getValue());
if(iterator.hasNext()){
bodyBuilder.append('&');
}
}
String body = bodyBuilder.toString();
Log.v(Config.TAG, "Posting'" +body + "'to"+url);
byte[] bytes = body.getBytes();
HttpURLConnection conn = null;
try{
Log.e("URL",">" + url);
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setFixedLengthStreamingMode(bytes.length);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
//Post the request
OutputStream out = conn.getOutputStream();
out.write(bytes);
out.close();
//handle the response
int status = conn.getResponseCode();
//If response is not success
if(status != 200){
throw new IOException("Get failed with error code" + status);
}
}finally{
if (conn != null){
conn.disconnect();
}
}
}
/**
* Checks internet connectivity.
* #return false
*/
public boolean isConnectingToInternet(){
ConnectivityManager connectivity = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
if(connectivity != null){
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if(info != null){
for(int i = 0; i < info.length; i++)
if(info[i].getState() == NetworkInfo.State.CONNECTED);
{
return true;
}
}
}
return false;
}
/**
* Send broadcast to show message on activity, broadcast receiver mHandleMessageReceiver
* defined in Login.java.
* #param context
* #param message
*/
void displayMessageOnScreen(Context context, String message) {
Intent intent = new Intent(Config.DISPLAY_MESSAGE_ACTION);
intent.putExtra(Config.EXTRA_MESSAGE, message);
// Send Broadcast to Broadcast receiver with message
context.sendBroadcast(intent);
}
/**
* It displays the simple Alert dialog
* #param context
* #param title
* #param message
* #param status
*/
#SuppressWarnings("deprecation")
public void showAlertDialog(Context context, String title, String message,
Boolean status) {
AlertDialog alertDialog = new AlertDialog.Builder(context).create();
//Set Dialog Title
alertDialog.setTitle(title);
//Set Dialog Message
alertDialog.setMessage(message);
if(status != null)
//set alert dialog icon
alertDialog.setIcon((status) ? R.drawable
.ic_launcher : R.drawable.ic_launcher);
//Set OK button
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(final DialogInterface dialog, final int which) {
}
});
alertDialog.show();
}
private PowerManager.WakeLock wakeLock;
/**
* Device wakeup when any push notification reveived.
* #param context
*/
#SuppressWarnings("deprecation")
#SuppressLint("Wakelock")
public void acquireWakeLock (Context context){
if (wakeLock != null) wakeLock.release();
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP |
PowerManager.ON_AFTER_RELEASE, "WakeLock");
wakeLock.acquire();
}
public void releaseWakeLock(){
if (wakeLock != null) wakeLock.release();
wakeLock =null;
}
}
LoginActivity.java
public class LoginActivity extends Activity {
EditText inputEmail;
EditText inputPassword;
Button loginBtn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
final Controller controller = (Controller) getApplicationContext();
// Check if the internet coneection is present
if (!controller.isConnectingToInternet()) {
// Internet connection is not present
controller.showAlertDialog(LoginActivity.this,
"Internet Connection Error!!", "Please connect your"
+ "device to internet.", false);
// Stop executing code by return
return;
}
// Check if GCM configuration is set
if (Config.SERVER_URL == null || Config.GOOGLE_SENDER_ID == null
|| Config.SERVER_URL.length() == 0
|| Config.GOOGLE_SENDER_ID.length() == 0) {
// GCM sender id / server url is missing
controller.showAlertDialog(LoginActivity.this,
"Configuration Error!",
"Please set your Server URL and GCM Sender Id", false);
// Stop executing code by return
return;
}
inputEmail = (EditText) findViewById(R.id.email);
inputPassword = (EditText) findViewById(R.id.password);
loginBtn = (Button) findViewById(R.id.btnLogin);
loginBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// Get data from EditText
String email = inputEmail.getText().toString();
String password = inputPassword.getText().toString();
// Check if the user filled the form
if (email.trim().length() > 0 && password.trim().length() > 0) {
// Launch MainActivity
Intent i = new Intent(getApplicationContext(), MainActivity.class);
// Registering user to our server
// Sending registration details to MainActivity
i.putExtra("email", email);
startActivity(i);
finish();
} else {
// User donĀ“t filled that data
controller.showAlertDialog(LoginActivity.this,
"Login Error",
"Please enter your full details", false);
}
}
});
}
}
GCMIntentService.java
public class GCMIntentService extends GCMBaseIntentService {
private static final String TAG = "GCMIntentService";
private Controller controller = null;
public GCMIntentService() {
// Call extended class Constructor GCMBaseIntentService
super(Config.GOOGLE_SENDER_ID);
}
/**
* Method called on Error
**/
#Override
protected void onError(Context context, String errorId) {
if(controller == null)
controller = (Controller) getApplicationContext();
Log.i(TAG, "Received error: " + errorId);
controller.displayMessageOnScreen(context,
getString(R.string.gcm_error, errorId));
}
/**
* Method called on Receiving a new message from GCM server
**/
#Override
protected void onMessage(Context context, Intent intent) {
if(controller == null)
controller = (Controller) getApplicationContext();
Log.i(TAG, "Received message");
String message = intent.getExtras().getString("price");
controller.displayMessageOnScreen(context, message);
// notifies user
generateNotification(context, message);
}
#Override
protected boolean onRecoverableError(Context context, String errorId) {
if(controller == null)
controller = (Controller) getApplicationContext();
// log message
Log.i(TAG, "Received recoverable error: " + errorId);
controller.displayMessageOnScreen(context,
getString(R.string.gcm_recoverable_error,
errorId));
return super.onRecoverableError(context, errorId);
}
/**
* Create a notification to inform the user that server has sent a message.
*/
#SuppressWarnings("deprecation")
private void generateNotification(Context context, String message) {
int icon = R.drawable.ic_launcher;
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(icon, message, when);
String title = context.getString(R.string.app_name);
Intent notificationIntent = new Intent(context, MainActivity.class);
// set intent so it does not start a new activity
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent =
PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, title, message, intent);
//notification.flags |= Notification.FLAG_AUTO_CANCEL;
// Play default notification sound
// notification.defaults |= Notification.DEFAULT_SOUND;
//notification.sound = Uri.parse(
// "android.resource://"
// + context.getPackageName()
// + "your_sound_file_name.mp3");
// Vibrate if vibrate is enabled
notification.defaults |= Notification.DEFAULT_VIBRATE;
notificationManager.notify(0, notification);
}
/**
* Method called on device registered
**/
#Override
protected void onRegistered(Context context, String RegistrationID) {
// Get Global Controller Class object (see application tag in
// AndroidManifest.xml)
if (controller == null)
controller = (Controller) getApplicationContext();
Log.i(TAG, "Device registered: regId = " + RegistrationID);
controller.displayMessageOnScreen(context,
"Your device registred with GCM");
Log.d("NAME", MainActivity.email);
controller.register(context, MainActivity.password, MainActivity.email,
RegistrationID);
}
/**
* Method called on device unregistred
**/
#Override
protected void onUnregistered(Context context, String RegistrationID) {
if (controller == null)
controller = (Controller) getApplicationContext();
Log.i(TAG, "Device unregistered");
controller.displayMessageOnScreen(context,
getString(R.string.gcm_unregistered));
controller.unregister(context, RegistrationID);
}
}
MainActivity.java
public class MainActivity extends Activity {
// label to display gcm message
TextView lblMessage;
Controller controller;
// Asyntask
AsyncTask<Void, Void, Void> mRegisterTask;
static String email;
static String password;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
controller = (Controller) getApplicationContext();
// Check if Internet present
if (!controller.isConnectingToInternet()) {
// Internet Connection is not present
controller.showAlertDialog(MainActivity.this,
"Internet Connection Error",
"Please connect to Internet connection", false);
// stop executing code by return
return;
}
// Getting email from intent
Intent i = getIntent();
email = i.getStringExtra("email");
password = i.getStringExtra("password");
// Make sure the device has the proper dependencies.
GCMRegistrar.checkDevice(this);
// Make sure the manifest permissions was properly set
GCMRegistrar.checkManifest(this);
lblMessage = (TextView) findViewById(R.id.lblMessage);
// Register custom Broadcast receiver to show messages on activity
registerReceiver(mHandleMessageReceiver, new IntentFilter(
Config.DISPLAY_MESSAGE_ACTION));
// Get GCM registration id
final String regId = GCMRegistrar.getRegistrationId(this);
// Check if regid already presents
if (regId.equals("")) {
// Register with GCM
GCMRegistrar.register(this, Config.GOOGLE_SENDER_ID);
} else {
// Device is already registered on GCM Server
if (GCMRegistrar.isRegisteredOnServer(this)) {
// Skips registration.
Toast.makeText(getApplicationContext(),
"Already registered with GCM Server", Toast.LENGTH_LONG)
.show();
} else {
// Try to register again, but not in the UI thread.
// It's also necessary to cancel the thread onDestroy(),
// hence the use of AsyncTask instead of a raw thread.
final Context context = this;
mRegisterTask = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
// Register on our server
// On server creates a new user
controller.register(context, email, regId, regId);
return null;
}
#Override
protected void onPostExecute(Void result) {
mRegisterTask = null;
}
};
// execute AsyncTask
mRegisterTask.execute(null, null, null);
}
}
}
private BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String newMessage = intent.getExtras().getString(
Config.EXTRA_MESSAGE);
// Waking up mobile if it is sleeping
controller.acquireWakeLock(getApplicationContext());
// Display message on the screen
lblMessage.append(newMessage + "");
Toast.makeText(getApplicationContext(),
"Got Message: " + newMessage, Toast.LENGTH_LONG).show();
// Releasing wake lock
controller.releaseWakeLock();
}
};
#Override
protected void onDestroy() {
// Cancel AsyncTask
if (mRegisterTask != null) {
mRegisterTask.cancel(true);
}
try {
// Unregister Broadcast Receiver
unregisterReceiver(mHandleMessageReceiver);
// Clear internal resources.
GCMRegistrar.onDestroy(this);
} catch (Exception e) {
Log.e("UnRegister Receiver Error", "> " + e.getMessage());
}
super.onDestroy();
}
}
Manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.appname"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="19" />
<!-- GCM connects to Internet Services. -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- GCM requires a Google account. -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<!-- Keeps the processor from sleeping when a message is received. -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!--
Creates a custom permission so only this app can receive its messages.
NOTE: the permission *must* be called PACKAGE.permission.C2D_MESSAGE,
where PACKAGE is the application's package name.
-->
<permission
android:name="com.example.appname.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.appname.permission.C2D_MESSAGE" />
<!-- This app has permission to register and receive data message. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!-- Network State Permissions to detect Internet status -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Permission to vibrate -->
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:name ="com.example.appname.Controller"
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.appname.LoginActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.DELETE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="com.idrivecare.familypro" />
</intent-filter>
</activity>
<activity android:name="com.example.appname.MainActivity" />
<!--
BroadcastReceiver that will receive intents from GCM
services and handle them to the custom IntentService.
The com.google.android.c2dm.permission.SEND permission is necessary
so only GCM services can send data messages for the app.
-->
<receiver
android:name="com.google.android.gcm.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<!-- Receives the actual messages. -->
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<!-- Receives the registration id. -->
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<!-- <category android:name="com.google.android.gcm.demo.app" /> -->
<category android:name="com.example.appname" />
</intent-filter>
</receiver>
<service android:name="com.example.appname.gcm.GCMIntentService" />
</application>
After I login I get this in LogCat;
05-03 12:02:06.386: D/GCMRegistrar(20407): resetting backoff for com.example.appname
05-03 12:02:06.386: V/GCMRegistrar(20407): Registering app com.example.appname of senders 499319758496
05-03 12:02:06.456: V/GCMBroadcastReceiver(20407): onReceive: com.google.android.c2dm.intent.REGISTRATION
05-03 12:02:06.456: V/GCMBroadcastReceiver(20407): GCM IntentService class: com.example.appname.GCMIntentService
05-03 12:02:06.456: V/GCMBaseIntentService(20407): Acquiring wakelock
Help me if you find any problems in the code.
You are using the old way of registering to GCM, which is deprecated. The new way of registering simply requires calling GoogleCloudMessaing.register method, which is blocking, and therefore you don't have to get the result in the intent service.
You can follow the official GCM demo app if you wish to use the new way.
If you wish to stick with the old way, it can still work, but you'll have to make some fixes :
If your app's package name is com.example.appname, the manifest should use it consistently. Therefore, instead of :
<permission
android:name="com.example.clipme.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.appname.permission.C2D_MESSAGE" />
you should have
<permission
android:name="com.example.appname.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.appname.permission.C2D_MESSAGE" />
In addition, your intent service class com.example.appname.gcm.GCMIntentService is in the package com.example.appname.gcm, but the broadcast receiver you are using - com.google.android.gcm.GCMBroadcastReceiver - looks for it by default in the main package (com.example.appname.GCMIntentService). Therefore it doesn't find it. You shuold either move the service class to the main package or override the broadcast receiver class to change where it expects to find the intent service class.