【问题标题】:Broadcast Receiver as inner class in Android广播接收器作为Android中的内部类
【发布时间】:2010-08-31 12:23:32
【问题描述】:

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

我在AndroidManifest.xml 中添加了以下行:

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

但我收到以下错误:

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

我该如何解决这个问题?

【问题讨论】:

  • AndroidManifest.xml 行不知何故丢失并且没有显示 - 请检查一下
  • 嘿马丁,thanx,现在请检查一下..

标签: java android broadcastreceiver


【解决方案1】:

Android 无法通过 AndroidManifest.xml (Android developer documentation on BroadcastReceiver) 实例化(非静态)inner class

你可以动态注册这个类的一个实例 Context.registerReceiver() 或静态发布实现 通过您的 AndroidManifest.xml 中的标签。

所以你可以动态注册接收者。在我的应用程序中,我想使用 Google 的云到设备消息传递 (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>

我删除了 receiver 部分并动态注册了接收器,如下所示:

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

【讨论】:

  • 我对此有疑问。 MyC2dmReceiver 收到意图后注册的对象会发生什么?它是否保持活动状态并准备好接收另一个,或者它是否可以被 GC 删除并且我们需要注册它的另一个实例?
【解决方案2】:

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

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

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

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

另见:

【讨论】:

  • 感谢 BalusC 的回答 :) 但在我的情况下,我想调用一个异步类,它是我使用警报的活动的内部类。有什么想法吗?
  • 我可以确认可以使用 Outer$Inner 表示法使用静态嵌套类;在我的例子中,我创建了一个 AppWidgetProvider 接收器,内部类扩展了外部类,为每个尺寸指定一个唯一的 AppWidgetProvider。
【解决方案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" />

【讨论】:

  • 这里的OuterClassConnector 是什么?
  • 我现在在我的代码中没有发现它,它在过去 2 年中发生了很大变化。我认为它是在我实现 GoogleApiClient.OnConnectionFailedListener、GoogleApiClient.ConnectionCallbacks 接口时由 android 生成的。但是现在我使用了一个带有显式意图类的解决方案:new Intent(mContext, InnerStaticClass.class);
  • 谢谢..这对我有用。但我也在清单中定义的接收器标签中定义了:android:enabled="true"。
【解决方案5】:

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

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

【讨论】:

    【解决方案6】:

    我也遇到了同样的问题。

    我有一个服务来与许多活动进行通信,并且我的服务中还有一个接收器作为内部类。当接收方收到消息时,它必须调用服务方法。就这样继续下去:

    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"/>
    

    【讨论】:

    • 这让我印象深刻。可能正是我想要的。我会试试这个,如果它有效,我会恢复。
    • 这是有效的。谢谢你。好吧,我没有写android:enable="true",但它正在工作。任何的想法?还是只是为了更安全?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多