Приемник как внутренний класс в Android
В моем коде есть внутренний класс, который расширяет BroadcastReceiver
.
И я добавил следующую строку в AndroidManifest.xml
:
<receiver android:name="OuterClass$InnerClass android:enabled="true"/>
Но я получаю следующую ошибку:
невозможно создать экземпляр получателя org.example.test.OuterClass $InnerClass
Как я могу решить эту проблему?
Ответы
Ответ 1
An (нестатический) внутренний класс не может быть создан Android через AndroidManifest.xml(Документация разработчика Android на BroadcastReceiver):
Вы можете динамически регистрировать экземпляр этого класса с помощью Context.registerReceiver() или статически публиковать реализацию через тег в вашем AndroidManifest.xml.
Таким образом, вы можете динамически регистрировать приемник. В моем приложении я хотел сделать то же самое для использования Google Cloud для обмена сообщениями устройств (C2DM), а мой оригинальный AndroidManifest.xml содержал:
<application...>
<receiver android:name=".MyC2dmReceiver" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.example.myapp" />
</intent-filter>
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.example.myapp" />
</intent-filter>
</receiver>
</application>
Я удалил эту секцию приемника и динамически зарегистрировал приемник следующим образом:
public class AndroidService extends IntentService
{
...
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
IntentFilter filter = new IntentFilter();
filter.addAction("com.google.android.c2dm.intent.RECEIVE");
filter.addAction("com.google.android.c2dm.intent.REGISTRATION");
filter.addCategory("com.example.myapp");
this.registerReceiver(new MyC2dmReceiver(), filter, "com.google.android.c2dm.permission.SEND", null);
return super.onStartCommand(intent,flags,startId);
}
public class MyC2dmReceiver extends BroadcastReceiver
{
...
}
}
Ответ 2
Обозначение $
не обозначает внутренний класс, а статический вложенный класс. Итак, в теории есть два способа решить эту конкретную проблему:
-
Обозначим его как действительный внутренний класс, т.е. OuterClass.InnerClass
(не уверен, хотя если Android будет есть, поскольку создание внутреннего класса довольно сложнее, чем просто делать Class#newInstance()
.
-
Объявите класс вместо статического вложенного класса, т.е. добавьте static
в class InnerClass {}
. Таким образом, OuterClass$InnerClass
должен иметь возможность создать из него новый экземпляр.
Если это не решит проблему, то, по-видимому, Android просто не елит это. Тогда я просто извлечу его в свой собственный автономный класс.
См. также:
Ответ 3
Может ли быть, что есть только точка и закрывающая цитата? Как
<receiver android:name=".OuterClass$InnerClass" android:enabled="true"/>
Ответ 4
Это то, что сработало для меня:
public class OuterClass {
public static class InnerStaticClass extends BroadcastReceiver {
@Override
public void onReceive(final Context context, final Intent intent) {
final Location location = (Location) intent.getExtras().get(LocationClient.KEY_LOCATION_CHANGED);
}
}
}
AndroidManifest.xml:
<receiver android:name=".OuterClass$OuterClassConnector$InnerStaticClass" />
Ответ 5
Я только что встретил ту же проблему, у меня есть служба для связи со многими действиями, и у меня также есть получатель в моей службе как внутренний класс, когда получатель получает сообщение, он должен вызывать метод обслуживания. так что это происходит следующим образом:
1: Сервисный код:
public class XXService extends Service{
// I want the inner receiver call the methd of XXService,
// so I have to write this constructor like this.
private XXService instance;
public XXService(){instance = this;}
public XXService getInstance(){
return instance;
}
public void sayHello(){
}
public static class XXReceiver extends BroadcastReceiver{
onReceive(......){
XXService.getInstance.sayHello();}}}
2: зарегистрировать получателя в manifest.xml
<receiver android:name=".XXService$XXReceiver" android:enabled="true"/>
Ответ 6
вам не нужно использовать $.
Если вы получите предупреждение для класса, который на самом деле не является внутренним классом, это потому, что вы используете символы верхнего регистра в имени вашего пакета, что не является обычным.
Я также попытался изменить только первую букву имени пакета, чтобы он был в нижнем регистре, предупреждение и ошибка исчезли.