Приемник как внутренний класс в 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 способа решения этой конкретной проблемы:

  1. Обозначим его как настоящий внутренний класс, т.е. OuterClass.InnerClass (хотя не уверен, что Android это съест, так как создание внутреннего класса довольно сложно, чем просто Class#newInstance(),

  2. Объявите класс статическим вложенным классом, т.е. добавьте static в class InnerClass {}, Таким образом, OuterClass$InnerClass должен быть в состоянии создать новый экземпляр из этого.

Если это не решит проблему, то, очевидно, 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"/>
Другие вопросы по тегам