Приемник как внутренний класс в Android - PullRequest
18 голосов
/ 31 августа 2010

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

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

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

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

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

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

Ответы [ 6 ]

32 голосов
/ 01 июня 2012

(не статичный) внутренний класс не может быть создан Android с помощью AndroidManifest.xml ( Документация для разработчиков Android на BroadcastReceiver ):

Вы можете динамически зарегистрировать экземпляр этого класса с помощью Context.registerReceiver () или статически опубликовать реализацию через тег в вашем AndroidManifest.xml.

Таким образом, вы можете динамически зарегистрировать получателя. В моем приложении я хотел сделать то же самое для использования Google Cloud 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
    {
        ...
    }
}
17 голосов
/ 31 августа 2010

Запись $ обозначает не внутренний класс, а статический вложенный класс. Таким образом, в теории есть 2 способа решения этой конкретной проблемы:

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

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

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

Смотри также:

7 голосов
/ 31 августа 2010

Может ли быть так, что пропущена только точка и заключительная цитата? Как

<receiver android:name=".OuterClass$InnerClass" android:enabled="true"/>
4 голосов
/ 13 октября 2014

Вот что у меня сработало:

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" />
0 голосов
/ 07 октября 2015

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

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

0 голосов
/ 27 января 2015

Я только что столкнулся с той же проблемой.

У меня есть служба для связи со многими видами деятельности, и у меня также есть приемник в моем служении в качестве внутреннего класса.Когда получатель получает сообщение, он должен вызвать метод обслуживания.так это продолжается так:

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"/>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...