折腾:
【未解决】rcsjta中RCS的RI中各种功能都提示:The service is not available Please retry later
期间,先去研究代码中,和此处服务没启动,有哪些相关的代码和逻辑。
搜:
The service is not available
找到:
很多个。其中RI中的是:
/Users/xxx/dev/xxx/RCS/rcsjta/RI/res/values/strings.xml
<string name="label_service_not_available">The service is not available. Please retry later.</string>

去找找代码中哪里用到了:label_service_not_available
看到了 Capability的对应代码
/Users/xxx/dev/xxx/RCS/rcsjta/RI/src/com/gsma/rcs/ri/capabilities/MyCapabilities.java
public class MyCapabilities extends RcsActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.capabilities_mine);
/* Register to API connection manager */
if (!isServiceConnected(RcsServiceName.CAPABILITY)) {
showMessageThenExit(R.string.label_service_not_available);
return;
}
startMonitorServices(RcsServiceName.CAPABILITY);
}
继续去研究代码
搜
isServiceConnected(
找到多处定义

找到了
rcsjta/libs/api_cnx/src/main/java/com/gsma/rcs/api/connection/ConnectionManager.java
/**
* Check if services are connected
*
* @param services list of services
* @return true if all services of the list are connected
*/
public boolean isServiceConnected(RcsServiceName... services) {
for (RcsServiceName service : services) {
if (!mManagedServices.contains(service)) {
throw new IllegalArgumentException("Service " + service
+ " does not belong to set of managed services!");
}
if (!mConnectedServices.contains(service)) {
return false;
}
}
return true;
}
其他地方都是调用这个ConnectionManager.java中的isServiceConnected
且其中的:mManagedServices
是开始初始化包含的一个列表:
/**
* The set of managed services
*/
private final Set<RcsServiceName> mManagedServices;
/**
* Constructor
*
* @param context The context
* @param managedServices Set of managed services
* @param rcsServiceControl instance of RcsServiceControl
*/
private ConnectionManager(Context context, Set<RcsServiceName> managedServices,
RcsServiceControl rcsServiceControl) {
mCtx = context;
mCnxIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_CONNECT), 0);
mAlarmManager = (AlarmManager) mCtx.getSystemService(Context.ALARM_SERVICE);
mManagedServices = managedServices;
mRcsServiceControl = rcsServiceControl;
/* Construct list of connected services */
mConnectedServices = new HashSet<>();
/* Construct list of clients to notify */
mClientsToNotify = new HashMap<>();
/* Construct list of APIs */
mApis = new HashMap<>();
if (managedServices == null || managedServices.isEmpty()) {
throw new RuntimeException("Incorrect parameter managedService!");
}
/* Instantiate APIs */
for (RcsServiceName service : mManagedServices) {
switch (service) {
case CAPABILITY:
mApis.put(RcsServiceName.CAPABILITY, new CapabilityService(context,
newRcsServiceListener(RcsServiceName.CAPABILITY)));
break;
case CHAT:
mApis.put(RcsServiceName.CHAT, new ChatService(context,
newRcsServiceListener(RcsServiceName.CHAT)));
break;
case CONTACT:
mApis.put(RcsServiceName.CONTACT, new ContactService(context,
newRcsServiceListener(RcsServiceName.CONTACT)));
break;
case FILE_TRANSFER:
mApis.put(RcsServiceName.FILE_TRANSFER, new FileTransferService(context,
newRcsServiceListener(RcsServiceName.FILE_TRANSFER)));
break;
case FILE_UPLOAD:
mApis.put(RcsServiceName.FILE_UPLOAD, new FileUploadService(context,
newRcsServiceListener(RcsServiceName.FILE_UPLOAD)));
break;
case GEOLOC_SHARING:
mApis.put(RcsServiceName.GEOLOC_SHARING, new GeolocSharingService(context,
newRcsServiceListener(RcsServiceName.GEOLOC_SHARING)));
break;
case HISTORY:
mApis.put(RcsServiceName.HISTORY, new HistoryService(context,
newRcsServiceListener(RcsServiceName.HISTORY)));
break;
case IMAGE_SHARING:
mApis.put(RcsServiceName.IMAGE_SHARING, new ImageSharingService(context,
newRcsServiceListener(RcsServiceName.IMAGE_SHARING)));
break;
case MULTIMEDIA:
mApis.put(RcsServiceName.MULTIMEDIA, new MultimediaSessionService(context,
newRcsServiceListener(RcsServiceName.MULTIMEDIA)));
break;
case VIDEO_SHARING:
mApis.put(RcsServiceName.VIDEO_SHARING, new VideoSharingService(context,
newRcsServiceListener(RcsServiceName.VIDEO_SHARING)));
break;
}
}
}其中容易看出是各个功能和服务项目:
- CAPABILITY
- CHAT
- CONTACT
- FILE_TRANSFER
- FILE_UPLOAD
- GEOLOC_SHARING
- HISTORY
- IMAGE_SHARING
- MULTIMEDIA
- VIDEO_SHARING
再去看看mConnectedServices
/**
* Set of connected services
*/
private final Set<RcsServiceName> mConnectedServices;
mConnectedServices = new HashSet<>();
/**
* Create a RCS service listener to monitor API connection
*
* @param service the service to monitor
* @return the listener
*/
private RcsServiceListener newRcsServiceListener(final RcsServiceName service) {
return new RcsServiceListener() {
@Override
public void onServiceConnected() {
mConnectedServices.add(service);
notifyConnection(service);
}
@Override
public void onServiceDisconnected(ReasonCode error) {
mConnectedServices.remove(service);
notifyDisconnection(service, error);
}
};
}
public void notifyConnection() {
if (mListener == null) {
return;
}
if (mConnectedServices.containsAll(mMonitoredServices)) {
/* All monitored services are connected -> notify connection */
mListener.onServiceConnected();
mRetryCount = 0;
}
}其中的:newRcsServiceListener
就是前面调用的
不过注意到开始的ConnectionManager()初始化期间,是根据传入的mManagedServices去初始化对应服务的
所以要再去找找,有哪些用到了:
ConnectionManager(
只有自己
libs/api_cnx/src/main/java/com/gsma/rcs/api/connection/ConnectionManager.java
/**
* Get an instance of ConnectionManager.
*
* @param ctx the context
* @param rcsServiceControl instance of RcsServiceControl
* @param managedServices Set of managed services
* @return the singleton instance.
*/
public static ConnectionManager createInstance(Context ctx,
RcsServiceControl rcsServiceControl, Set<RcsServiceName> managedServices) {
if (sInstance != null) {
return sInstance;
}
synchronized (ConnectionManager.class) {
if (sInstance == null) {
if (ctx == null) {
throw new IllegalArgumentException("Context is null");
}
sInstance = new ConnectionManager(ctx, managedServices, rcsServiceControl);
}
}
return sInstance;
}继续研究原因
继续找:
createInstance(
找到:
libs/api_cnx/src/main/java/com/gsma/rcs/api/connection/ConnectionManager.java
/**
* Get an instance of ConnectionManager.
*
* @param context the context
* @param rcsServiceControl instance of RcsServiceControl
* @param services list of managed services
* @return the singleton instance.
*/
public static ConnectionManager createInstance(Context context,
RcsServiceControl rcsServiceControl, RcsServiceName... services) {
Set<RcsServiceName> managedServices = new HashSet<>();
Collections.addAll(managedServices, services);
return createInstance(context, rcsServiceControl, managedServices);
}以及真正的调用去初始化:
RI/src/com/gsma/rcs/ri/RiApplication.java
@Override
public void onCreate() {
super.onCreate();
。。。
mRcsServiceControl = RcsServiceControl.getInstance(mContext);
/* Starts the RCS service notification manager */
startService(new Intent(this, RcsServiceNotifManager.class));
/* Do not execute the ConnectionManager on the main thread */
Handler mainThreadHandler = new Handler(Looper.getMainLooper());
final ConnectionManager cnxManager = ConnectionManager.createInstance(mContext,
mRcsServiceControl, EnumSet.allOf(RcsServiceName.class));
mainThreadHandler.postDelayed(new Runnable() {
@Override
public void run() {
try {
cnxManager.start();
sCnxManagerStarted = true;
} catch (RuntimeException e) {
Log.e(LOGTAG, "Failed to start connection manager!", e);
}
}
}, DELAY_FOR_STARTING_CNX_MANAGER);
}和:
tools/settings/src/com/gsma/rcs/core/control/CoreControlApplication.java
public class CoreControlApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Context context = getApplicationContext();
mRcsServiceControl = RcsServiceControl.getInstance(context);
final ConnectionManager cnxManager = ConnectionManager.createInstance(context,
mRcsServiceControl, RcsServiceName.FILE_TRANSFER, RcsServiceName.CHAT,
RcsServiceName.CONTACT);
/* Do not execute the ConnectionManager on the main thread */
Handler mainThreadHandler = new Handler(Looper.getMainLooper());
mainThreadHandler.postDelayed(new Runnable() {
@Override
public void run() {
cnxManager.start();
sCnxManagerStarted = true;
}
}, DELAY_FOR_STARTING_CNX_MANAGER);
}此处很明显,Core的control的application中,最开始启动时,只初始化了:
- FILE_TRANSFER
- CHAT
- CONTACT
并没有初始化其他的服务
比如Capability之类的
不知道为何?
去搜索其他的:
RcsServiceName.CAPABILITY
能找到其他的
但是没有找到 去启用的相关逻辑
所以难怪app中没看到服务启动
那如何启动其他如Capability的服务?
直接修改代码去加上?
感觉好像不太对啊,应该是哪里有配置,最开始启动哪些服务才对
去Core的app中看看
不过才注意到:
RI/src/com/gsma/rcs/ri/RiApplication.java
中的:
final ConnectionManager cnxManager = ConnectionManager.createInstance(mContext, mRcsServiceControl, EnumSet.allOf(RcsServiceName.class));
就是:
启动了RcsServiceName的所有的类名
就是启动了所有的服务才对
即:
RI的参考实现中,最开始是去启动了所有的服务的
对于RcsServiceName的定义,找了半天终于通过搜:
package com.gsma.rcs.api
间接的,最后找到了位置:
是在api_cnx中的:
libs/api_cnx/src/main/java/com/gsma/rcs/api/connection/ConnectionManager.java
而以为能找到原始定义:
/* Instantiate APIs */
for (RcsServiceName service : mManagedServices) {
switch (service) {
case CAPABILITY:
mApis.put(RcsServiceName.CAPABILITY, new CapabilityService(context,
newRcsServiceListener(RcsServiceName.CAPABILITY)));
break;
case CHAT:
mApis.put(RcsServiceName.CHAT, new ChatService(context,
newRcsServiceListener(RcsServiceName.CHAT)));
break;
case CONTACT:
mApis.put(RcsServiceName.CONTACT, new ContactService(context,
newRcsServiceListener(RcsServiceName.CONTACT)));
break;
case FILE_TRANSFER:
mApis.put(RcsServiceName.FILE_TRANSFER, new FileTransferService(context,
newRcsServiceListener(RcsServiceName.FILE_TRANSFER)));
break;
case FILE_UPLOAD:
mApis.put(RcsServiceName.FILE_UPLOAD, new FileUploadService(context,
newRcsServiceListener(RcsServiceName.FILE_UPLOAD)));
break;
case GEOLOC_SHARING:
mApis.put(RcsServiceName.GEOLOC_SHARING, new GeolocSharingService(context,
newRcsServiceListener(RcsServiceName.GEOLOC_SHARING)));
break;
case HISTORY:
mApis.put(RcsServiceName.HISTORY, new HistoryService(context,
newRcsServiceListener(RcsServiceName.HISTORY)));
break;
case IMAGE_SHARING:
mApis.put(RcsServiceName.IMAGE_SHARING, new ImageSharingService(context,
newRcsServiceListener(RcsServiceName.IMAGE_SHARING)));
break;
case MULTIMEDIA:
mApis.put(RcsServiceName.MULTIMEDIA, new MultimediaSessionService(context,
newRcsServiceListener(RcsServiceName.MULTIMEDIA)));
break;
case VIDEO_SHARING:
mApis.put(RcsServiceName.VIDEO_SHARING, new VideoSharingService(context,
newRcsServiceListener(RcsServiceName.VIDEO_SHARING)));
break;
}还是没有直接定义。
然后去找最原始的定义
通过:
VIDEO_SHARING
找到:
core/src/com/gsma/rcs/provider/sharing/VideoSharingProvider.java
private static final class UriType {
private static final class VideoSharing {
private static final int VIDEO_SHARING = 1;
private static final int VIDEO_SHARING_WITH_ID = 2;
}
private static final class InternalVideoSharing {
private static final int VIDEO_SHARING = 3;
private static final int VIDEO_SHARING_WITH_ID = 4;
}
}看来是:不同的类和实现中,有最原始的定义,且是 int值
不过后来终于找到了定义:
libs/api_cnx/src/main/java/com/gsma/rcs/api/connection/ConnectionManager.java
/**
* Enumerated type for RCS service name
*/
@SuppressWarnings("javadoc")
public enum RcsServiceName {
CAPABILITY, CONTACT, CHAT, FILE_TRANSFER, IMAGE_SHARING, VIDEO_SHARING, GEOLOC_SHARING, FILE_UPLOAD, MULTIMEDIA, HISTORY
}即:该文件中是有定义的。
不是在每个具体实现中定义的。前面理解有误。
反推再去搜:
enum RcsServiceName
只能找到此处这一处:

也是对的。
至此:
基本上确定,代码逻辑上来说,应该就是:
RI/src/com/gsma/rcs/ri/RiApplication.java
/* Do not execute the ConnectionManager on the main thread */
Handler mainThreadHandler = new Handler(Looper.getMainLooper());
final ConnectionManager cnxManager = ConnectionManager.createInstance(mContext,
mRcsServiceControl, EnumSet.allOf(RcsServiceName.class));
mainThreadHandler.postDelayed(new Runnable() {
@Override
public void run() {
try {
cnxManager.start();
sCnxManagerStarted = true;
} catch (RuntimeException e) {
Log.e(LOGTAG, "Failed to start connection manager!", e);
}
}
}, DELAY_FOR_STARTING_CNX_MANAGER);
}这句:
final ConnectionManager cnxManager = ConnectionManager.createInstance(mContext, mRcsServiceControl, EnumSet.allOf(RcsServiceName.class));
去启动了RCS所有的服务。
至于后续为何服务还是没启动,则需要深入调研其他方面,继续找原因了。