【问题标题】:Android ClassCast exception when binding to service绑定到服务时的Android ClassCast异常
【发布时间】:2011-11-07 17:31:42
【问题描述】:

好的,我是 android 开发新手,我正在尝试绑定到服务,以便在服务启动后调用该服务的方法。下面描述的 Activity 和 Service 都是同一个应用程序的一部分,所以那里不应该有任何问题,但是每次我运行我的应用程序时,我都会收到以下错误:

java.lang.ClassCastException: android.os.BinderProxy

发生这种情况的行是:

LocalBinder binder = (LocalBinder) service;

我的Activity代码(简体为):

public class Main extends Activity {

    boolean gpsBound = false;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    /** Called whenever the activity is started. */
    @Override
    protected void onStart() {
        super.onStart();
        // Bind to GPSService
        Intent i = new Intent(this, GPSService.class);
    startService(i);
    bindService(i, connection, Context.BIND_AUTO_CREATE);
    }

    /** service binding */
    private ServiceConnection connection = new ServiceConnection() {

        public void onServiceConnected(ComponentName className, IBinder service) {
            // After binding to GPSService get the instance of it returned by IBinder
        LocalBinder binder = (LocalBinder) service;
            gpsBound = true;
        }

        public void onServiceDisconnected(ComponentName className) {
            gpsBound = false;
        }
    };

}

服务:

public class GPSService extends Service {

    @Override
    public void onCreate() {
            super.onCreate();
    }

    @Override
    public IBinder onBind(Intent i) {
    // TODO Auto-generated method stub
    return new LocalBinder<GPSService>(this);
    }


   /**
    * Our implementation of LocationListener that handles updates given to us
    * by the LocationManager.
    */
    public class CustomLocationListener implements LocationListener {

        DBHelper db;

        CustomLocationListener() {
            super();
        }

    // Overridden methods here...

    }

}

最后是我的 LocalBinder:

/**
 * A generic implementation of Binder to be used for local services
 * @author Geoff Bruckner  12th December 2009
 *
 * @param <S> The type of the service being bound
 */

public class LocalBinder<S> extends Binder {
    private String TAG = "LocalGPSBinder";
    private  WeakReference<S> mService;


    public LocalBinder(S service){
        mService = new WeakReference<S>(service);
    }


    public S getService() {
        return mService.get();
    }
}

我理解 ClassCast Exception 的含义,但不明白该怎么做!我已经按照谷歌文档中的示例进行操作,但它仍然无法正常工作。任何人都可以阐明可能导致这种情况的原因吗?

提前致谢!

【问题讨论】:

    标签: android binding service android-activity classcastexception


    【解决方案1】:

    删除服务的 AndroidManifest.xml 中的属性 process

    【讨论】:

    • 好奇,有详细原因吗?
    • @ThomasDecaux 我相信这是因为 LocalBinder 只能在服务与应用程序在同一进程(本地)中运行时使用。 process 属性为要在其中运行的服务创建一个单独的进程,因此,您必须使用 IPC 与它进行通信。在绑定过程中,Android 为您提供了一个 BinderProxy 来充当服务的桥梁,以便您可以实例化您的 IPC 类(用 AIDL 编写)。 stackoverflow.com/a/10610463/269876
    • 这是一个旧线程,但这只是救了我的后腿!不错的收获!
    • 您在没有 OP 发布他的清单的情况下发现了这一点 - 天才。谢谢!
    • 如果我需要在一个单独的进程上工作,那么正确的方法是什么?
    【解决方案2】:

    有同样的错误。我在清单中添加了 android:process=":process_description" 属性。当你添加它时,你的服务被创建为单独的进程,因此你得到 binderProxy 的实例(因此类转换异常)

    【讨论】:

      【解决方案3】:

      如果您尝试绑定到本地服务而不是是,则可以强制转换它。但是,如果您尝试绑定到远程(单独的进程)服务,则必须使用本文中规定的 AIDL 方法。

      http://developer.android.com/guide/components/aidl.html

      【讨论】:

      【解决方案4】:

      传入 onServiceConnected 的 LocalBinder 有一个泛型类型参数,而你的局部变量 LocalBinder binder 没有。

      通过从 LocalBinder 的定义中删除泛型类型或在 onServiceConnected 中的局部变量绑定器声明中添加一个来解决此问题

      class MyBoundService extends Service{
          private final IBinder mBinder = new MyBinder();
      
          @Override
          public IBinder onBind(Intent intent) {
              return mBinder;
          }
      
          public class MyBinder extends Binder{
      
              public void doStuff(){
                  //Stuff
              }
              //More Binder Methods
          }
      }
      
      class MyActivity extends Activity{
          private MyBinder mBinder;
      
          @Override
          protected void onStart(){
              Intent intent = new Intent(this, MyBoundService.class);
              bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
          }
      
          @Override
          protected void onStop(){
              unbindService(mConnection);
          }
      
          private ServiceConnection mConnection = new ServiceConnection() {
      
              @Override
              public void onServiceConnected(ComponentName className, IBinder service) {
                  mBinder = (TaskBinder) service;
                  mBound = true;
              }
      
              @Override
              public void onServiceDisconnected(ComponentName arg0) {
                  mBound = false;
              }
          };
      
          private void doStuff(){
              if (mBound)
                  mBinder.doStuff();
          }
      }
      

      没有必要摆弄弱引用之类的东西。一定要解绑(我没有在示例中)

      如果您想尽快调用服务方法,只需在设置 mBinder 后将调用放入 onServiceConnected。否则,只需从其他回调(onClick 事件等)调用。

      【讨论】:

      • 你的意思是像:'LocalBinder binder = (LocalBinder) service;'如果是这样,仍然会出现同样的错误!
      • 我倾向于完全去掉泛型。我将编辑一个使用我现在正在编写的 boundService 的快速示例。
      • 如果没有泛型,我自己会去尝试,但如果你能举个例子那就太好了!谢谢,詹姆斯
      • 应该这样做(除非你真的需要 IBinder 中的泛型,这会有点奇怪))。您不需要在 onStart/onStop 中绑定/取消绑定。 onCreate/onDestroy 也可以正常工作,但您应该避免 onResume/onPause,因为这些调用太多了。
      • 还是没有运气。您还有其他建议吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-29
      • 1970-01-01
      • 2015-11-18
      • 2021-12-31
      • 2017-01-03
      • 2013-01-12
      相关资源
      最近更新 更多