Soy un novato en el patrón MVP para Android y Firebase Cloud Messaging. Tengo una aplicación que recibe notificaciones de FCM enviadas desde Firebase console.

Para probar la aplicación, agregué un usuario a Firebase con autenticación de correo electrónico y contraseña usando FirebaseAuth. El correo electrónico y el token de FCM se están guardando en SharedPreferences y se están recibiendo notificaciones.

Problema: ahora necesito enviar un correo electrónico desde SharedPreferences y el token de FCM a mi servidor de aplicaciones. Leí mucho en línea sobre la recuperación de datos de SharedPreferences y Context, pero aún así, no puedo unir las cosas.

Recibo un error que indica que el método getInstance(this) no se puede aplicar a LoginPresenter.java (consulte el fragmento de código a continuación). Estoy bastante seguro de que estoy haciendo algo mal. Por favor amigos, apúnteme en la dirección correcta.

public class LoginPresenter implements LoginContract.Presenter, LoginInteractor.Callback {

@Override
    public void onAuthSuccess() {
        //Show notifications
        mLoginView.showPushNotifications();

        //Get master token before sending it to the server
       String savedToken = FirebaseInstanceId.getInstance().getToken();
        //TODO:Check if token is not null.
        //Get user email
        final String savedEmail  = SharedPrefManager.getInstance(this).getUserEmail();
        saveTokenToServer(savedEmail, savedToken);
    }

Estoy usando la siguiente clase para administrar SharedPreferences:

public class SharedPrefManager {
  private static final String SHARED_PREF_NAME = "FCMSharedPref";
  private static final String TAG_EMAIL = "tagemail";

  private static SharedPrefManager mInstance;
  private static Context mCtx;

  private SharedPrefManager(Context context) {
    mCtx = context;
  }

  public static synchronized SharedPrefManager getInstance(Context context) {
    if (mInstance == null) {
      mInstance = new SharedPrefManager(context);
    }
    return mInstance;
  }

  //this method will save the email to shared preferences
  public boolean saveDeviceEmail(String email) {
    SharedPreferences sharedPreferences = mCtx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.putString(TAG_EMAIL, email);
    editor.apply();
    return true;
  }

  //this method will fetch the device token from shared preferences
  public String getUserEmail() {
    SharedPreferences sharedPreferences = mCtx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
    return sharedPreferences.getString(TAG_EMAIL, null);
  }

}

Gracias de antemano

1
Ngenazy 12 ene. 2017 a las 01:20
1
this se refiere a su presentador que no tiene Context al que puede referirse con this, debe pasar el Context a su presentador o recuperarlo de su Activity
 – 
Pztar
12 ene. 2017 a las 01:54

3 respuestas

Está utilizando SharedPrefs incorrectamente. No puedo proporcionar una respuesta más simple que la que ya se proporcionó en la página del desarrollador de Android:

Inicializando SharedPrefs:

Context context = getActivity();
SharedPreferences sharedPref = context.getSharedPreferences(
        getString(R.string.preference_file_key), Context.MODE_PRIVATE);

Escribir en SharedPrefs:

SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt(getString(R.string.saved_high_score), newHighScore);
editor.apply();

Para recuperar valores de un archivo de preferencias compartido, llame a métodos como getInt () y getString (), proporcionando la clave para el valor que desea y, opcionalmente, un valor predeterminado para devolver si la clave no está presente. Por ejemplo:

SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
int defaultValue = getResources().getInteger(R.string.saved_high_score_default);
long highScore = sharedPref.getInt(getString(R.string.saved_high_score), defaultValue);
0
David Kasabji 12 ene. 2017 a las 01:29
¿Qué se supone que es preference_file_key? ¿Cómo resolver este símbolo?
 – 
Enrico Maria De Angelis
26 ago. 2017 a las 15:50

Este es un código de muestra.

SharedPreferences sharedPref = MainActivity.this.getPreferences(Context.MODE_PRIVATE);
fileIncrementer = sharedPref.getInt("incrementor", 0);
fileIncrementer++;
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt("incrementor", fileIncrementer);
editor.commit();
0
brorbw 12 ene. 2017 a las 01:46

Debe pasar el context del Activity cuando inicialice el presenter o usar Dagger para inyectarlo.

Para mayor facilidad (y sospecho que no estás usando la inyección de dependencia) -En tu presentador, crea un Constructor que tome un parámetro Context que te proporcionará el Context para usar.

Algo así.

     private Context mContext;

     public LoginPresenter (Context context){
       mContext = context
     }


    @Override
    public void onAuthSuccess() {
        mLoginView.showPushNotifications();

       String savedToken = FirebaseInstanceId.getInstance().getToken();

        final String savedEmail  = SharedPrefManager.getInstance(mContext).getUserEmail(); //See context used here
        saveTokenToServer(savedEmail, savedToken);
    }
-1
Zain 12 ene. 2017 a las 15:40
Gracias, Zain, utilizo esta respuesta y mi proyecto se pudo construir correctamente. Pero cuando intento iniciar sesión en mi aplicación, obtengo un java.lang.NullPointerException debido a esta línea de código SharedPrefManager.getInstance(getApplicationContext()).saveDeviceToken(token); dentro de un método para guardando el token en sharedPreferences. El método se llama dentro de onTokenRefresh()
 – 
Ngenazy
14 ene. 2017 a las 10:44
Está pasando contexto a Presentador, lo que anula el propósito de separar la lógica empresarial del código de Android.
 – 
Ali_Waris
10 may. 2018 a las 12:15
Cierto, idealmente debería inyectar el contexto (como se indica en la respuesta), pero para facilitar, paso como un parámetro.
 – 
Zain
10 may. 2018 a las 15:22