0

I'm currently working on GCM notifications, especially on silent push notification. For the moment, I receive the silent notification, even when the app is closed (which is the aim of my notification). The problem is the code I am trying to execute when receiving this silent push notification :

private void sendPingNotification() {
    mWebServiceCoordinator = new WebServiceCoordinator(UserSingleton.getContext(), this);
    mWebServiceCoordinator.fetchSessionConnectionData(
            UserSingleton.getInstance().getLogin(),
            UserSingleton.getInstance().getPassword(),
            UserSingleton.getInstance().getDeviceId(),
            UserSingleton.getInstance().getDeviceType(),
            UserSingleton.getInstance().getAvailability());
}

As you can see, I want to send the UserSingleton's login, password, etc... to my server. First, I create a new WebServiceCoordinator, which takes the Context of UserSingleton in parameter. And this is where there is a problem : as the application is totally closed, there is not any Context ! Here is the function trying to get the Context in my UserSingleton :

public static Context getContext() {
    if (context == null) {
        if (MainActivity.isRunning) {
            context = MainActivity.getContext();
        } else {
            Log.e(LOG_TAG, "Unable to get the context");
        }
    }
    return context;
}

This function is perfectly working when the application is running. But as the application is closed and nothing is running, even not MainActivity, the value of context returned by the function is still null

Thus, the next part of my sendPingNotification() doesn't work... I'm pretty sure there is no way to get a context when an application isn't running (it's logical), but how can I still use my UserSingleton methods ? Because they need a Context to work, for exemple, the getSharedValue() method :

public String getSharedValue(String key, String defaultValue) {
    final SharedPreferences data_r = UserSingleton.getContext().getSharedPreferences(SHARED_KEY, Context.MODE_PRIVATE);
    return data_r.getString(key, defaultValue);
}

Any ideas ? Thanks

------ EDIT ------

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.Bundle;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

public class MyGcmListenerService extends GcmListenerService implements WebServiceCoordinator.Listener {

private static final String TAG = "MyGcmListenerService";
private WebServiceCoordinator mWebServiceCoordinator;

/**
 * Called when message is received.
 *
 * @param from SenderID of the sender.
 * @param data Data bundle containing message data as key/value pairs.
 *             For Set of keys use data.keySet().
 */
@Override
public void onMessageReceived(String from, Bundle data) {
    String type = data.getString("type");
    String title = data.getString("title");
    String message = data.getString("message");
    Log.d(TAG, "Notification from " + from + " : (" + type + ")" + " " + message);

    if (type.equals("appointment_details")) {
        String nom = data.getString("nom");
        String prenom = data.getString("prenom");
        String mail = data.getString("mail");
        String telephone = data.getString("telephone");
        String state = data.getString("state");
        Integer stateId = Integer.parseInt(data.getString("stateId"));
        String date = data.getString("date");
        String token = data.getString("token");
        String length = data.getString("length");
        sendDetailsRendezvousNotification(title, message, nom, prenom, mail, telephone, state, stateId, date, token, length);
    }
    else if (type.equals("appointment"))
        sendNormalNotification(title, message);
    else if (type.equals("newCall"))
        sendNewCallNotification();
    else if (type.equals("ping"))
        sendPingNotification();
    else if (type.equals("normal"))
        sendNormalNotification(title, message);
}

private void sendPingNotification() {
    mWebServiceCoordinator = new WebServiceCoordinator(UserSingleton.getContext(), this);
    mWebServiceCoordinator.fetchSessionConnectionData(UserSingleton.getInstance().getLogin(),
            UserSingleton.getInstance().getPassword(),
            UserSingleton.getInstance().getDeviceId(),
            UserSingleton.getInstance().getDeviceType(),
            UserSingleton.getInstance().getAvailability());
    }
}
Eliott
  • 840
  • 8
  • 10
  • you definitely can get context even when the app is not running. show the entire class of where your notification is received. If your using GCM you should have an on message received function which should have a context as a param – Tomer Shemesh May 17 '16 at 18:28
  • @TomerShemesh added the class that receives the GCM notifications at the end of my post. That would mean I have to do : `mWebServiceCoordinator = new WebServiceCoordinator(CONTEXT_OF_MYGCMLISTENER_SERVICE, this);` ? – Eliott May 17 '16 at 18:54
  • see me answer below. i think that might solve your problem – Tomer Shemesh May 17 '16 at 19:00
  • `Service` extends `Context`, therefore `this` is your context. – zapl May 17 '16 at 19:06
  • @zapl i would recommend against using this in terms of a service when creating a singleton. This will cause a memory leak if the service should end but the singleton is being used by another class or service. – Tomer Shemesh May 17 '16 at 19:10
  • @TomerShemesh if it's for a singleton then `getApplicationContext()`. The only thing you should roughly never use is `getBaseContext` since that can have special implications – zapl May 17 '16 at 19:16
  • @zapl yea that's true I wasn't sure – Tomer Shemesh May 17 '16 at 19:18
  • @TomerShemesh @zapl I used getApplicationContext() and it's working ! Now the question is : how to rewrite the `getContext()` method in `UserSingleton` ? Is there a way to create a `Context` of UserSingleton ? Or do I have to pass it the `getApplicationContext()` in `MyGCMListenerService` and save it as my UserSingleton's context ? My idea would be to create a `Context` in the default constructor of `UserSingleton`, and the save it for future uses. – Eliott May 18 '16 at 07:36

2 Answers2

0

Ok im pretty sure you can use getApplicationContext to get the context inside a gcm service

 mWebServiceCoordinator = new WebServiceCoordinator(getApplicationContext(), this);
Tomer Shemesh
  • 10,278
  • 4
  • 21
  • 44
  • I'm pretty sure it fixes the first line of sendPingNotification(), I will give it a try tomorrow (not at work right now). I'll let you know – Eliott May 17 '16 at 19:08
  • i think you should also change the way you get context in your singleton. The way you have it is not a good way. you should instansiate the singleton with a context that gets stored so that way if you create it in your service it wont try to use main activities context – Tomer Shemesh May 17 '16 at 19:12
0

So I edited my sendPingNotification() method as following :

private void sendPingNotification() {
    mWebServiceCoordinator = new WebServiceCoordinator(getApplicationContext(), this);
    UserSingleton.setContext(getApplicationContext());
    mWebServiceCoordinator.fetchSessionConnectionData(UserSingleton.getInstance().getLogin(),
            UserSingleton.getInstance().getPassword(),
            UserSingleton.getInstance().getDeviceId(),
            UserSingleton.getInstance().getDeviceType(),
            UserSingleton.getInstance().getAvailability());
}

I added a setContext() method in UserSingleton, so that I can set the context of my UserSingleton as getApplicationContext(). The context isn't null anymore and getContext() returns a valid Context. Everything is working ! Thanks to you two.

Eliott
  • 840
  • 8
  • 10