Приемник как внутренний класс в Android
В моем коде есть внутренний класс, который расширяет BroadcastReceiver
,
И я добавил следующую строку к AndroidManifest.xml
:
<receiver android:name="OuterClass$InnerClass android:enabled="true"/>
Но я получаю следующую ошибку:
невозможно создать экземпляр получателя org.example.test.OuterClass$InnerClass
Как я могу решить эту проблему?
6 ответов
Android (не статичный) внутренний класс не может быть создан с помощью AndroidManifest.xml ( документация для разработчиков Android на BroadcastReceiver):
Вы можете либо динамически зарегистрировать экземпляр этого класса в Context.registerReceiver(), либо статически опубликовать реализацию через тег в вашем AndroidManifest.xml.
Таким образом, вы можете динамически зарегистрировать получателя. В моем приложении я хотел сделать то же самое для использования Google Cloud-Device Messaging (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 просто так не ест. Тогда я бы просто извлек его в отдельный класс.
Смотрите также:
- Учебник по Java - Вложенные классы
- Ответ с примером кода, как создать экземпляр внутреннего или статического вложенного класса, используя отражение (как Android должен делать "под прикрытием")
Может ли быть так, что пропущена только точка и заключительная цитата? подобно
<receiver android:name=".OuterClass$InnerClass" android:enabled="true"/>
Вот что сработало для меня:
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" />
Вам не нужно использовать $... Если вы получаете предупреждение для класса, который на самом деле не является внутренним классом, это потому, что вы используете заглавные буквы в имени вашего пакета, что не принято.
Я также пытался изменить только первую букву имени пакета на нижний регистр, предупреждение и ошибка исчезли.
Я только что встретил ту же проблему.
У меня есть служба общения со многими видами деятельности, и у меня также есть приемник в качестве внутреннего класса. Когда получатель получает сообщение, он должен вызвать метод обслуживания. так это продолжается так:
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"/>