bindService从不调用onServiceConnected

时间:2015-07-29 16:42:21

标签: android android-service android-service-binding

我公司生产的SDK作为Android Library aar文件提供。作为该SDK的一部分,我们定义了一项服务:

    <service
        android:name=".session.internal.ChatSession"
        android:description="@string/description"
        android:enabled="true"
        android:exported="false"
        android:label="Network communication service"
    />

然后启动此服务并受SDK中更多代码的约束:

public boolean bindService(final Runnable whenBound) {
    if (connection == null) {
        // Make sure the service is running
        boolean success = startService();
        if(BuildConfig.DEBUG && !success) {
            throw new AssertionError("startService failed");
        }

        connection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                chatSession = (IChatSession) service;
                if(whenBound != null) {
                    whenBound.run();
                }
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                chatSession = null;
                connection = null;
            }
        };

        success = context.bindService(new Intent(context, ChatSession.class), connection, Context.BIND_IMPORTANT);
        if(BuildConfig.DEBUG && !success) {
            throw new AssertionError("bindService failed");
        }

        return success;
    }

    if(whenBound != null) {
        whenBound.run();
    }

    return true;
}

boolean startService() {
    boolean success = true;

    if(!isServiceRunning()) {
        success = context.startService(new Intent(context, ChatSession.class)) != null;
    }
    return success;
}

只要只有一个应用程序使用移动设备上安装的SDK,这一切都可以正常工作。

由于服务明确地未导出(android:exported="false")并且隐式未导出(没有定义<intent-filter>),我们预计这也可以在安装了多个应用程序的情况下正常工作,每个应用程序都可以获得当调用bindService时,它是自己的私有服务实例。

实际发生的事情是,由于ServiceConnection.onServiceConnectedServiceConnected.onServiceDisconnected的调用都返回成功,因此任何应用程序都不再起作用,因为context.startServicecontext.bindService都没有被调用。 / p>

一旦安装了两个应用程序,让它们中的任何一个工作的唯一方法是卸载它们,然后只重新安装一个。仅独立卸载是不够的。

1 个答案:

答案 0 :(得分:0)

事实证明,问题实际上是这一段代码阻止了服务首先启动:

if(!isServiceRunning()) {
    success = context.startService(new Intent(context, ChatSession.class)) != null;
}

我已经为isServiceRunning编写了代码,该代码错误地确定服务是否仅根据名称运行:

public boolean isServiceRunning() {
    ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningServiceInfo> services = manager.getRunningServices(Integer.MAX_VALUE);
    if(services == null) {
        return false;
    }
    for (ActivityManager.RunningServiceInfo service : services) {
        if (ChatSession.class.getName().equals(service.service.getClassName())) {
            return true;
        }
    }
    return false;
}

将if替换为:

        if (Process.myPid() == service.pid && ChatSession.class.getName().equals(service.service.getClassName())) {

似乎解决了这个问题。

我仍然对此感到不满,因为看起来应该有更好的检查方法。