Подтвердить что ты не робот

Приемник как внутренний класс в Android

В моем коде есть внутренний класс, который расширяет BroadcastReceiver.

И я добавил следующую строку в AndroidManifest.xml:

<receiver android:name="OuterClass$InnerClass android:enabled="true"/>

Но я получаю следующую ошибку:

невозможно создать экземпляр получателя org.example.test.OuterClass $InnerClass

Как я могу решить эту проблему?

4b9b3361

Ответ 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

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

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