Java 接收器作为 Android 中的内部类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3608955/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 02:36:07  来源:igfitidea点击:

Receiver as inner class in Android

javaandroidbroadcastreceiver

提问by Kunal P.Bharati

In my code there is an inner class that extends BroadcastReceiver.

在我的代码中有一个内部类扩展BroadcastReceiver.

And I have added the following line to the AndroidManifest.xml:

我已经添加了以下行AndroidManifest.xml

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

But I am receiving the following error:

但我收到以下错误:

unable to instantiate receiver org.example.test.OuterClass$InnerClass

无法实例化接收器 org.example.test.OuterClass$InnerClass

How can I solve this issue ?

我该如何解决这个问题?

回答by DonGru

Could it be that there is just a dot and a closing quote missing? Like

可能只是缺少一个点和一个结束语吗?喜欢

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

回答by BalusC

The $notation doesn't denote an inner class, but a static nested class. So there are in theory 2 ways to solve this particular problem:

$符号不表示内部类,而是表示静态嵌套类。所以理论上有两种方法可以解决这个特定问题:

  1. Denote it as a real inner class, i.e. OuterClass.InnerClass(not sure though if Android will eat that since the instantiation of an inner class is pretty more complex than just doing Class#newInstance().

  2. Declare the class to be a static nested class instead, i.e. add staticto class InnerClass {}. This way the OuterClass$InnerClassmust be able to create a new instance out of it.

  1. 将其表示为真正的内部类,即OuterClass.InnerClass(不确定 Android 是否会吃掉它,因为内部类的实例化比仅执行Class#newInstance().

  2. 将该类声明为静态嵌套类,即添加staticclass InnerClass {}. 这样,OuterClass$InnerClass必须能够从中创建一个新实例。

If that doesn't solve the problem, then apparently Android simply doesn't eat it that way. I'd just extract it into its own standalone class then.

如果这不能解决问题,那么显然 Android 根本不会那样吃。我只是将它提取到它自己的独立类中。

See also:

也可以看看:

回答by Bert Regelink

An (non-static) inner classcannot be instantiated by Android via the AndroidManifest.xml (Android developer documentation on BroadcastReceiver):

Android 无法通过 AndroidManifest.xml(关于 BroadcastReceiver 的 Android 开发人员文档)实例化(非静态)内部类

You can either dynamically register an instance of this class with Context.registerReceiver() or statically publish an implementation through the tag in your AndroidManifest.xml.

您可以使用 Context.registerReceiver() 动态注册此类的实例,也可以通过 AndroidManifest.xml 中的标记静态发布实现。

So you can dynamically register the receiver. In my application I wanted to do the same for using Google's Cloud to Device Messaging (C2DM) and my original AndroidManifest.xml contained:

所以你可以动态注册接收器。在我的应用程序中,我想对使用 Google 的 Cloud to 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>

I removed that receiversection and dynamically registered the receiver as follows:

我删除了该接收器部分并按如下方式动态注册接收器:

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
    {
        ...
    }
}

回答by Gavriel

This is what worked for me:

这对我有用:

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:

AndroidManifest.xml:

    <receiver android:name=".OuterClass$OuterClassConnector$InnerStaticClass" />

回答by River

I've just met the same problem.

我刚刚遇到了同样的问题。

I have a service to communicate with many activities, and I also have a receiver in my service as inner class. when the receiver get message ,it has to call the method of service. so it goes on like this :

我有一个服务可以与许多活动进行通信,而且我的服务中还有一个接收器作为内部类。当接收者收到消息时,它必须调用服务方法。所以它是这样的:

1. Service code:

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. Register receiver in manifest.xml :

2. 在 manifest.xml 中注册接收器:

<receiver android:name=".XXService$XXReceiver" android:enabled="true"/>

回答by MBH

you dont need to use $... If you get warning for a class which is not actually an inner class, it's because you are using uppercase characters in your package name, which is not conventional.

你不需要使用$... 如果你收到一个实际上不是内部类的类的警告,那是因为你在包名中使用了大写字符,这不符合惯例。

I tried also to change only the first letter of the package name to be lower case, the warning and error disappeared.

我也尝试将包名的第一个字母改为小写,警告和错误消失了。