Android, как получить контекст в конструкторе C2DMReceiver?

У меня есть класс получателя C2DM, который инициализирует электронную почту отправителя C2DM в конструкторе. Дело в том, что мне нужно получить адрес электронной почты отправителя из строки ресурса, и поэтому мне нужно получить контекст в конструкторе для получателя.

Приемник выглядит так

public class C2DMReceiver extends C2DMBaseReceiver {

    public C2DMReceiver() {
        super(AppConstants.getC2DMSender(this)); // How do I get the context here?
    }

    @Override
    public void onRegistered(Context context, String registrationId)
            throws java.io.IOException { ...

Соответствующий код на C2DMBaseReceiver

public abstract class C2DMBaseReceiver extends IntentService {
...
    private final String senderId;

    /**
     * The C2DMReceiver class must create a no-arg constructor and pass the 
     * sender id to be used for registration.
     */
    public C2DMBaseReceiver(String senderId) {
        // senderId is used as base name for threads, etc.
        super(senderId);
        this.senderId = senderId;
    }
...

Это не совсем относится к вопросу, но для фоновых целей причина необходимости в этом заключается в том, что код находится в проекте библиотеки, который используется во многих проектах Android, каждый из которых имеет собственный адрес электронной почты отправителя, определенный в файле ресурсов. Класс AppConstants выполняет чтение различных строк ресурсов и следует из моего принятого ответа на предыдущий вопрос здесь Android, лучший способ предоставить конкретные константы приложения в библиотечном проекте?

Наконец, для полноты метод AppConstants.getC2DMSender выглядит следующим образом.

public static String getC2DMSender(Context c){
    return c.getResources().getString(uk.co.the_prize_quiz.quiz_template.R.string.c2dm_sender);
}

Конкретное приложение, использующее эту библиотеку, отвечает за установку переменной c2dm_sender в ресурсе xml. Итак, чтобы получить эту переменную, мне нужен контекст

<item type="string" name="c2dm_sender" format="string">app_specific_registered_c2dm@email_address</item>

Поскольку это задается в строке ресурса, конкретное приложение может установить это значение, и шаблон будет использовать его автоматически.


person jamesc    schedule 23.04.2012    source источник
comment
Если вы обнаружите какие-либо сложности с получением контекста в проекте библиотеки, вы можете скопировать эти файлы или пакет в свой проект и изменить по своему усмотрению.   -  person fargath    schedule 23.04.2012
comment
Не знал, что это можно сделать, и мне, возможно, просто придется это сделать, но я действительно предпочел бы этого не делать, если нет другого варианта. Спасибо за информацию   -  person jamesc    schedule 23.04.2012
comment
Как вы планируете работать с различными пакетами для разных электронных писем отправителя? При регистрации в C2DM вам необходимо указать запрошенный адрес электронной почты отправителя и пакет вашего приложения. Пакет используется C2DM для вызова вашего класса C2DMReceiver (определенного в манифесте). Вы уверены, что этот класс будет правильно вызван, когда вы сможете правильно установить адрес электронной почты в конструкторе?   -  person marmor    schedule 30.04.2012
comment
@marmor манифест для каждого конкретного приложения устанавливает разрешения для этого приложения, которое, кажется, работает.   -  person jamesc    schedule 30.04.2012


Ответы (4)


Добавьте одноэлементный класс в свою библиотеку. Имейте член для хранения senderid и соответствующих методов getter и setter...

public class ClassicSingleton {
   private static ClassicSingleton instance = null;
   private String mSenderId = nulll; // Your data holder

   protected ClassicSingleton() {
      // Exists only to defeat instantiation.
   }

   public static ClassicSingleton getInstance() {
      if(instance == null) {
         instance = new ClassicSingleton();
      }
      return instance;
   }

   /* Setter and Getter for the mAppContext member here */
   public void setSender(String sender) {
       mSenderId = sender;
   }

}

В активности вашего приложения ClassicSingleton.getInstance().setSender("SENDER_ID")

В вашем классе C2DM

public C2DMReceiver() {
    super(ClassicSingleton.getInstance().getSender());
}

Попробуйте использовать контекст приложения в качестве члена вместо senderId. Тогда вы можете получить любой ресурс, который вам нужен, я думаю.. Дайте мне знать.

person Ronnie    schedule 02.05.2012
comment
Я принял ответ, но у меня не было времени попробовать, я свяжусь с вами позже и спасибо за вашу настойчивость. - person jamesc; 02.05.2012

Я пришел к выводу, что это невозможно сделать так, как я пытался. Я временно решил свою проблему, создав новый класс в каждом приложении, который происходит от класса в проекте библиотеки, и просто переопределив конструктор в каждом приложении.

Это не идеальное решение, и оно как бы лишает возможности иметь библиотеку, но, по крайней мере, я могу поделиться большей частью своего кода.

person jamesc    schedule 02.05.2012
comment
Я тоже думаю, что это невозможно сделать так, как вы хотели. Но вы все равно можете попробовать — иметь в библиотеке класс, содержащий данные, необходимые для регистрации в C2DM. Установите эти данные в своей активности перед регистрационным звонком. Вам нужно будет сделать статические ссылки. - person Ronnie; 02.05.2012
comment
@ userSeven7s Я бы хотел попробовать этот вариант. если бы вы хотели ответить на предложенный пример кода о том, как это можно сделать, я был бы признателен - person jamesc; 02.05.2012

C2DMBaseReceiver на самом деле не использует senderId, если только ему не нужно повторить запрос на регистрацию. C2DMBaseReceiver — это объект (IntentService), который создается и уничтожается для каждой операции (регистрация ответа, сообщение с сервера и повторная попытка регистрации). Пока вы устанавливаете senderId перед регистрацией, все должно быть в порядке.

Кажется, это работает:

public class C2DMReceiver extends C2DMBaseReceiver {
    private static String gSenderId = "dummy";

    public C2DMReceiver() {
        super(gSenderId);
    }

    public static void register(Context context, String senderId) {
        gSenderId = senderId;
        C2DMessaging.register(context, senderId);
    }

    ...
}

Поскольку вы создаете библиотеку, которая предоставляет службу C2DM, вам следует учесть то, что сказал @fargath, и включить функции c2dm.jar непосредственно в вашу библиотеку. Затем вы можете настроить интерфейс по мере необходимости. Кроме того, c2dm.jar обеспечивает косвенное обращение к коду вашей библиотеки, тогда код вашей библиотеки обеспечивает эквивалентное косвенное обращение к приложению. Это немного пустая трата времени.

Код c2dm.jar состоит всего из трех коротких файлов. Я пишу библиотеку, похожую на вашу, и, скорее всего, возьму функциональность на себя.

person CaveMike    schedule 06.05.2012
comment
Благодарю за ваш ответ. Я не хочу менять косвенность, хотя я уже рассматривал это ранее, исходя из того, что если это работает, не исправляйте это. Я нашел решение, которое очень хорошо отвечает моим потребностям, основанное на моем принятом ответе, только с использованием синглтона приложения, а не пользовательского синглтона, который работает очень хорошо. Однако вы предоставили много пищи для размышлений и, возможно, гораздо более приятное решение. Теперь у меня есть работающая библиотека. Ограничения по времени означают, что мне нужно двигаться дальше, но тот факт, что у меня есть библиотека, позволяет мне проводить рефакторинг, когда есть время. Спасибо - person jamesc; 06.05.2012

person    schedule
comment
Это не работает, я получаю 2 ошибки о том, что неявный суперконструктор C2DMBaseReceiver() не определен. Должен явно вызывать другой конструктор И вызов конструктора должен быть первым оператором в конструкторе, спасибо за ответ - person jamesc; 26.04.2012
comment
@jamesw попробуй это super(AppConstants.getC2DMSender(getApplicationContext())); - person Ronnie; 01.05.2012
comment
@userSeven7s Спасибо за предложение, но это дает мне ошибку Невозможно ссылаться на метод экземпляра при явном вызове конструктора - person jamesc; 02.05.2012