Can I use SpiceManager inside a service?

4

我正在尝试将SpiceManager附加到服务上,但是我遇到了以下问题:

java.lang.ClassCastException: android.os.BinderProxy cannot be cast to com.octo.android.robospice.SpiceService$SpiceServiceBinder
        at com.octo.android.robospice.SpiceManager$SpiceServiceConnection.onServiceConnected(SpiceManager.java:1072)
        at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java)
        at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java)
        at android.os.Handler.handleCallback(Handler.java)
        at android.os.Handler.dispatchMessage(Handler.java)
        at android.os.Looper.loop(Looper.java)
        at android.app.ActivityThread.main(ActivityThread.java)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
        at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:115)
        at dalvik.system.NativeStart.main(Native Method)

服务流程大致如下:
class MyService extends Service {
    // ...
    SpiceManager mSpiceManager = new SpiceManager(UncachedSpiceService.class);
    // ...

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        mSpiceManager.start(this);
        mSpiceManager.execute(new MyRequest(), new RequestListener<String>() {
            // Handle of request
        })
        // ...
        return START_STICKY;
    }

    // + additional calls to mSpiceManager.execute() in other methods
}

这会在服务启动时立即引发“类转换异常”?

非常奇怪。您可以在任何上下文中使用SpiceManager。请问您的RS版本和完整堆栈是什么? - Snicolas
我的RS版本是1.4.9,最低SDK版本为15,目标SDK版本为17。 - canni
好的,堆栈跟踪呢? - Snicolas
@Snicolas 在周末我无法访问代码库,我会在周一发布完整的ST。 - canni
哦,我们能看一下你的清单吗?看起来应用程序和Spice服务不在同一个进程中。这是使用RoboSpice必须遵守的规定。 - Snicolas
显示剩余4条评论
2个回答

6
要使用RoboSpice,使用SpiceManager和SpiceService的实体(上下文)必须位于同一个进程中。
RoboSpice就像是Android服务和任何其他上下文之间的桥梁。而这座桥是面向对象的,允许上下文和服务之间建立基于对象的双向通信渠道。
在Android上,只有当SpiceService和使用SpiceManager的实体位于同一进程中时,才能实现这一点。这种非常特殊的“技巧”是Android中的硬编码行为,称为“本地服务绑定”。
如果不满足这个条件,就无法以正确的方式绑定到RS服务。当SpiceManager绑定到SpiceService时,它将收到一个BinderProxy,无法共享引用:所有通信都必须基于Bundle、可序列化或可包裹的对象。在这种情况下,RS根本无法工作。
我查看了你在https://github.com/rovo89/XposedBridge/blob/master/src/de/robv/android/xposed/XposedBridge.java中的项目,似乎你在其中涉及相当低层次的事情,并从那里启动新的Zygote进程。我假设你通过分叉zygote来创建的进程不会在SpiceService本身的同一进程中,这就是你遇到此异常的原因。
非常抱歉告诉你,但你不能在这个项目中使用RoboSpice。如果你找到了解决方法,我会很感兴趣听取你的意见,但我认为这是不可能的,因为Android本身的设计如此。

XposedBridge(和 Xposed 框架)不是我的项目,它只是安装在我的(自定义)ROM 上的软件组件 - 我在原始 ROM 上也得到了相同的行为。 - canni
但是你是对的,我试图为所有我的活动/服务使用一个SpiceService,其中一个在不同的进程中。感谢您的耐心和帮助 :) - canni

-1

你不能从后台线程调用另一个后台服务/线程。

你可以通过以下方式实现。

public void callService() {
        try {
            org.springframework.web.client.RestTemplate rt = new org.springframework.web.client.RestTemplate();
            rt.getMessageConverters().add(
                    new MappingJacksonHttpMessageConverter());
            String url = "xyz";

            Contacts contacts = rt.postForObject(url, body,
                    Contacts.class);
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "Called-" + e.toString());
        }
    }

错误的,你可以用RS做到这一点。甚至有样例可供参考。 - Snicolas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接