Android VoLTE 视频通话是否可用状态读取与监听

###展讯volte视频通话

  • 初始化状态读取

      TelephonyManager.isImsRegistered()
    

    在远程服务端中对应的接口实际上为:

      frameworks\opt\telephony\src\java\com\android\internal\telephony\PhoneBase.java
    
       /**
           * Get IMS Registration Status
           */
          @Override
          public boolean isImsRegistered() {
              ImsPhone imsPhone = mImsPhone;
              boolean isImsRegistered = false;
              if (imsPhone != null) {
                  isImsRegistered = imsPhone.isImsRegistered();
              } else {
                  ServiceStateTracker sst = getServiceStateTracker();
                  if (sst != null) {
                      isImsRegistered = sst.isImsRegistered();
                  }
              }
              Rlog.d(LOG_TAG, "isImsRegistered =" + isImsRegistered);
              return isImsRegistered;
          }
    

    在ImsPhone中

      frameworks\opt\telephony\src\java\com\android\internal\telephony\imsphone
      
      public boolean isImsRegistered() {
      	return mImsRegistered;
      }
    
      public void setImsRegistered(boolean value) {
      	mImsRegistered = value;
      }
      
      /* SPRD: Add for VoLTE. @{ */
      public boolean isVideoEnabled(){
      	return isVideoCallEnabled();
      }
    

**该接口存在一定问题,在某些时候,会始终返回false状态 **

目前可依照展讯6.0平台系统拨号应用方案实现

  • 展讯6.0实现

      //使用TelephonyManager.listen(mPhoneStateListener,PhoneStateListener.LISTEN_VOLTE_STATE)注册一个PhoneState的监听器
      //当注册监听器时,接口会理解回调onVoLteServiceStateChanged方法,返回当前volte状态
      
      class DialVoLteStateListener extends PhoneStateListener {
      
      	@Override
      	public void onVoLteServiceStateChanged(VoLteServiceState stateInfo) {
    
          	if (stateInfo.getSrvccState() == VoLteServiceState.IMS_REG_STATE_REGISTERED) {
              	LogUtil.d("VOLTE_SERVICE_STATE_IMS_REGISTERED");
          	} else if (stateInfo.getSrvccState() == VoLteServiceState.IMS_REG_STATE_NOT_EGISTERED) {
              	LogUtil.d("VOLTE_SERVICE_STATE_IMS_UNREGISTERED");
          	}
      }
    

    }

    • 当注册监听器时,立即回调,返回当前volte状态
    • 当volte状态变化时回调,对变化之后的状态给出通知

需注意,该监听方案不稳定,可能存在延迟、丢失等情况,只在进程启动时注册监听,会出现遗漏volte状态变化通知的情况,所以按照底版本方案,依靠该接口注册后立即返回状态的特点,在界面进入前台时注册,读取当前volte状态,当界面离开前台时反注册掉,依此反复。

  • 展讯7.0实现

      private class DialVoLteStateListener extends IImsRegisterListener.Stub {
    
      	@Override
      	public void imsRegisterStateChange(boolean isRegistered) {
          	LogUtil.d("imsRegisterStateChange: "+isRegistered);
      	}
      }
    

与展讯6.0实现思想相同,只是接口变化了

展讯7.0平台上,特别增加了一个aidl接口IImsRegisterListener,其中只定义了一个回调函数,imsRegisterStateChange。该接口相比6.0更加稳定可靠,只是注册和反注册该监听需要反射调用。
接口:

  IImsServiceEx imsService = ImsManagerEx.getIImsServiceEx();
  imsService.registerforImsRegisterStateChanged(mPhoneStateListener);
private void reflect(String methodName,DialVoLteStateListener listener) {     
    Class<?> clazz = null;
    Object result = null;
    try {
        clazz = Class.forName("com.android.ims.internal.ImsManagerEx");
        if(clazz != null){
        	Method method = clazz.getMethod("getIImsServiceEx", null);
        	if(method != null){
            	result = method.invoke(obj, null);
        	}
        }
    } catch (ClassNotFoundException e) {
        printError(e);
    }
       
    if (result != null) {
        Class<?> clazz = result.getClass();
        try {
            Method method = clazz.getMethod(methodName, new Class[]{IImsRegisterListener.class});
            if (null != method) {
                method.invoke(obj, new Object[]{listener});
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

//注册监听器
reflect("registerforImsRegisterStateChanged",mPhoneStateListener);

//反注册监听器
reflect("unregisterforImsRegisterStateChanged",mPhoneStateListener);

###MTK平台volte视频通话

MTK平台6.0和7.0的方案可通用

  • 主动读取当前volte状态

      TelephonyManager.isImsRegistered()
    

与展讯相同,该方法依然存在问题,目前可有两种解决方案

1.修改Phone代码

	packages\services\Telephony\src\com\android\phone\PhoneInterfaceManager.java
	
	public boolean isImsRegistered() {
    	//Solve inserted on Sim2 and reg ims always return false  >>>start
    	int phoneId = TelephonyUtilsEx.getMainPhoneId();
   		if(SubscriptionManager.isValidPhoneId(phoneId)) {
       		Phone phone = PhoneFactory.getPhone(phoneId);
       		if(null != phone) {
            	return phone.isImsRegistered();
        	}
    	}
		//>>>end  此间为增加代码
   		return mPhone.isImsRegistered();
	}

2.反射MTK平台特有接口读取

调用ITelephonyEx的isImsRegistered(int subId)

boolean isImsRegistered() {
    boolean flags = false;
    //获取主数据sim卡的 subId
    int subId = SubscriptionManager.getDefaultDataSubId();
    //注:7.0 接口变化为SubscriptionManager.getDefaultDataSubscriptionId()

    IBinder phoneEx = ServiceManager.getService("phoneEx");
    if (phoneEx != null) {
        Object telephonyEx = ReflectUtil.invokeStatic("com.mediatek.internal.telephony.ITelephonyEx$Stub", "asInterface",
                new Class[] { IBinder.class }, new Object[] { phoneEx });
        if (telephonyEx != null) {
            Object r = ReflectUtil.invoke(telephonyEx,"isImsRegistered",new Class[]{int.class},new Object[]{subId});
            if (r instanceof Boolean) {
                flags = (Boolean) r;
                LogUtil.d("ITelephonyEx isImsRegistered :" + flags);
            }
        }
    }
    return flags;
}
  • 动态监听volte状态变化

可以通过广播获取volte状态变化的通知,但是该广播不是StickyBroadcast,注册时无法获取当前状态,需上述接口辅助

//注册广播
IntentFilter filter = new IntentFilter();
filter.addAction("com.android.ims.IMS_STATE_CHANGED");
mContext.registerReceiver(mVoLTEStateBroadcast, filter);

class VoLTEStateBroadcast extends BroadcastReceiver{
	private static final String REG_STATE = "android:regState";
	private static final String REG_PHONE_ID = "android:phone_id";

    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();
        LogUtil.d("VoLTEStateBroadcast action:"+action);
        if ("com.android.ims.IMS_STATE_CHANGED".equals(action)) {
            int regState = intent.getIntExtra(REG_STATE, -1);
            int phoneId = intent.getIntExtra(REG_PHONE_ID, -1 );
            
            boolean enabled = (regState == ServiceState.STATE_IN_SERVICE);
        }            
    }
}

###高通平台volte视频通话

高通平台6.0和7.0的实现方案亦可通用

高通平台也通过注册广播实现,并且该广播是StickyBroadcast,注册立即返回当前volte状态

//注册粘性广播
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.intent.action.SERVICE_STATE");
mContext.registerReceiver(mServiceStateListener, intentFilter);

class ServiceStateListener extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if ("android.intent.action.SERVICE_STATE".equals(action)){
            int state = intent.getIntExtra("imsRadioTechnology",-1);
			boolean register = (state == ServiceState.RIL_RADIO_TECHNOLOGY_LTE)	
			//最终结果
			boolean result = isVideoRegister() && register;
        }
    }
}

//需要判断当前卡是否有视频通话的能力
public boolean isVideoRegister(Context context) {
    TelecomManager telecommMgr = (TelecomManager)context.getSystemService(Context.TELECOM_SERVICE);

    if (telecommMgr == null) {
        return false;
    }

    List<PhoneAccountHandle> accountHandles = telecommMgr.getCallCapablePhoneAccounts();
    for (PhoneAccountHandle accountHandle : accountHandles) {
        PhoneAccount account = telecommMgr.getPhoneAccount(accountHandle);
        if (account != null) {
            if(account.hasCapabilities(PhoneAccount.CAPABILITY_VIDEO_CALLING)) {
                return true;
            }
        }
    }
    LogUtil.d("isVideoRegister : false");
    return false;
}

在读取volte状态之前,首先要判断当前手机系统版本是否支持volte视频通话,这是一个属性配置:

  ImsManager.isVtEnabledByPlatform(mContext)

另,以上API的调用,需注意请求相关权限:

  <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
  <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程之路从0到1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值