我公司生产的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.onServiceConnected
和ServiceConnected.onServiceDisconnected
的调用都返回成功,因此任何应用程序都不再起作用,因为context.startService
或context.bindService
都没有被调用。 / p>
一旦安装了两个应用程序,让它们中的任何一个工作的唯一方法是卸载它们,然后只重新安装一个。仅独立卸载是不够的。
答案 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())) {
似乎解决了这个问题。
我仍然对此感到不满,因为看起来应该有更好的检查方法。