我的公司生产一个SDK,作为一个Android库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的调用都返回成功。
一旦这两个应用程序都安装好了,唯一的方法就是卸载这两个应用程序,然后只重新安装其中一个应用程序。单独卸载是不够的。
发布于 2015-07-29 19:07:10
结果,问题实际上是这段代码,它首先阻止了服务的启动:
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())) {似乎解决了这个问题。
我仍然对此不感兴趣,因为看起来应该有一个更好的检查方法。
https://stackoverflow.com/questions/31706378
复制相似问题