英文:
Registering SIP Profile using Android SIP stack
问题
我一直在开发一个应用程序,通过 SIPDemo 提供的灵感,使用户能够使用 SIP 进行呼叫和接听呼叫,在我从手机中卸载应用程序之前,它运行得很好,它进行了注册,显示了消息“准备就绪”,然后继续进行呼叫处理。现在它没有进入 Sipregistrationlistener,并显示错误“尝试关闭管理器 1 时出错 SipException:Failed to create SipSession; network unavailable?”。
据我所知,我怀疑问题是由于之前的 SIP 帐户仍然链接在应用程序中自动打开,不允许任何注册,正如解决此帖子的方法所述:“https://stackoverflow.com/questions/49414650/android-native-sip-stack-not-registering-client”,但我不知道如何处理这个问题,在 onDestroy、onPause 中引入 closelocalprofile 函数没有效果。此外,直到最近,它仍然显示消息“SipManager is ready for calls”并且它是打开的,但是现在它没有了,尽管代码没有更改,所以问题可能不一定是这个。
在打印方面,显示了以下消息:
- 没有与状态相关联的消息显示;
- 日志显示“Creating Manager”和“Building a new profile”。
此外,我已经具备了支持 SIP 通信的权限和清单代码。
我现在知道这个堆栈不是最好的,但我不想放弃这个项目,所以非常感谢任何帮助或建议。
在最后一种情况下,为了准备如果找不到解决方案/进展,如果你们中的任何人也能为类似的替代堆栈提供建议,那也将不胜感激。
以下是代码:
public SipManager sipManager = null; // SIPMANAGER
public SipProfile sipProfile = null; // SIPPROFILE
public SipAudioCall call = null; // SIPAUDIOCALL
public IncomingCallReceiver callReceiver;
@Override
protected void onCreate(Bundle savedInstanceState)
{
Permissions();
Supported();
initManager();
MakeCallButton.setOnClickListener(new View.OnClickListener() // 点击事件
{
@Override
public void onClick(View view)
{
initCall();
}
});
EndCallButton.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view) {
try
{
call.endCall();
}
catch (SipException e)
{
status("尝试结束通话时出错。 " + e);
}
}
});
}
public void initManager() // SIPMANAGER
{
if(sipManager == null)
{
sipManager = SipManager.newInstance(this); // 创建管理器实例。如果不支持 SIP API,则返回 null
Log.d("Manager", "创建 Manager");
}
initLocalProfile();
}
public void initLocalProfile()
{
if (sipManager == null)
{
Log.d("Manager", "没有 Manager");
return;
}
if (sipProfile != null)
{
Log.d("Profile", "已经有一个配置文件 1");
closeLocalProfile();
}
// 本地配置数据
String user = "x";
String domain = "xxx";
String pass = "zzzz";
try
{
Log.d("Profile", "正在构建新配置文件");
SipProfile.Builder builder = new SipProfile.Builder(user, domain); // SIP 帐户的用户和 SIP 服务器域
builder.setPassword(pass); // 设置 SIP 帐户的密码
builder.setOutboundProxy(domain); // 设置 SIP 服务器的出站代理
builder.setPort(5060); // 端口号
builder.setProtocol("UDP");
builder.setAutoRegistration(false);
sipProfile = builder.build(); // 构建并返回 SIP 配置文件对象。
Intent sipIntent = new Intent(); // 呼叫的 intent
sipIntent.setAction("android.Login.INCOMING_CALL");
PendingIntent pi = PendingIntent.getBroadcast(this, 0, sipIntent, Intent.FILL_IN_DATA);
sipManager.open(sipProfile, pi, null); // 打开配置文件以进行呼叫和/或接收通用 SIP 呼叫
// 设置监听器以侦听注册事件。如果配置文件尚未打开以接收呼叫,则没有效果
sipManager.setRegistrationListener(sipProfile.getUriString(), new SipRegistrationListener()
{
public void onRegistering(String localProfileUri)
{
// 当发送注册请求时调用
status("正在注册");
}
public void onRegistrationDone(String localProfileUri, long expiryTime)
{
// 当注册成功时调用
status("准备就绪");
}
public void onRegistrationFailed(String localProfileUri, int errorCode, String errorMessage)
{
// 当注册失败时调用
status("注册失败 " + localProfileUri + errorCode + errorMessage );
}
});
if (sipManager.isRegistered(sipProfile.getUriString()))
{
Log.d("Profile","SipManager 准备就绪");
}
if (sipManager.isOpened(sipProfile.getUriString()))
{
Log.d("Profile","SipManager 已打开");
}
}
catch (ParseException pe)
{
status("连接错误");
}
catch (SipException sipe) // 如果调用 SIP 服务会产生错误
{
status("SIP 出错 " + sipe);
}
catch (SecurityException se)
{
status("安全性出错" + se);
}
catch (RuntimeException re)
{
status("运行时出错" + re);
}
catch (Exception e)
{
status("出错" + e);
}
}
public void closeLocalProfile()
{
if (sipManager == null)
{
Log.d("Manager", "没有 Manager 1");
return;
}
try
{
if (sipProfile != null)
{
Log.d("Profile", "已经有一个配置文件 2");
sipManager.close(sipProfile.getUriString()); // 关闭指定的配置文件以不进行/接收通话
}
}
catch (SipException se) // 如果调用 SIP 服务会产生错误
{
<details>
<summary>英文:</summary>
I have been developing an app that ables the user to call and receive calls using SIP inspired the by the SIPDemo, in which up until i unsinstalled the app from my phone it worked fine, it did the registration, showed the message "Ready" and then proceeded to do the call treatment. Now it does not enter the Sipregistrationlistener and displays the error "Error when trying to close manager 1 SipException:Failed to create SipSession; network unavailable?".
From what I understand I suspect that the problem is due to the fact that the previous SIP account is still linked and therefore automatically opened in the app, not letting any registration, as stated in the solution to this post "https://stackoverflow.com/questions/49414650/android-native-sip-stack-not-registering-client", but I have no clue on how to deal with this, introducing the closelocalprofile function on the onDestroy, onPause did no effect. Besides up until recently it did showed the messages "SipManager is ready for calls" and that it was opened, but now it doesn't despite not changing anything in the code so the problem might not be necessarily this.
In terms of printing the following messages are shown:
-no message associated to the status are shown;
-the log shows "Creating Manager" & "Building a new profile";
Furthermore i already have the permissions and the manifest coded to support SIP comunnications.
I know by now that this stack is not the best but I would like not to abandon this project so any help or tips would be much appreciated.
In last case, in preparation if no solution/progress is found, if any of you could also give recomendations to an alternative stack that is similar that would be also appreciated.
Here is the code:
public SipManager sipManager = null;//SIPMANAGER
public SipProfile sipProfile = null;//SIPPROFILE
public SipAudioCall call = null;//SIPAUDIOCALL
public IncomingCallReceiver callReceiver;
@Override
protected void onCreate(Bundle savedInstanceState)
{
Permissions();
Supported();
initManager();
MakeCallButton.setOnClickListener(new View.OnClickListener() /onclick event
{
@Override
public void onClick(View view)
{
initCall();
}
});
EndCallButton.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view) {
try
{
call.endCall();
}
catch (SipException e)
{
status("Error when trying to end call. " + e);
}
}
});
}
public void initManager()//SIPMANAGER
{
if(sipManager == null)
{
sipManager = SipManager.newInstance(this); //Creates a manager instance. Returns null if SIP API is not supported
Log.d("Manager", "Creating Manager");
}
initLocalProfile();
}
public void initLocalProfile()
{
if (sipManager == null)
{
Log.d("Manager", "There is no manager");
return;
}
if (sipProfile != null)
{
Log.d("Profile", "There is already a profile 1");
closeLocalProfile();
}
//localprofiledata
String user = "x";
String domain = "xxx";
String pass = "zzzz";
try
{
Log.d("Profile", "Building a new profile");
SipProfile.Builder builder = new SipProfile.Builder(user, domain); //user of the SIP account & the SIP server domain
builder.setPassword(pass);//Sets the password of the SIP account
builder.setOutboundProxy(domain);//Sets the outbound proxy of the SIP server
builder.setPort(5060);//port number
builder.setProtocol("UDP");
builder.setAutoRegistration(false);
sipProfile = builder.build();//Builds and returns the SIP profile object.
Intent sipIntent = new Intent();//intent for the calls
sipIntent.setAction("android.Login.INCOMING_CALL");
PendingIntent pi = PendingIntent.getBroadcast(this, 0, sipIntent, Intent.FILL_IN_DATA);
sipManager.open(sipProfile, pi, null);//Opens the profile for making calls and/or receiving generic SIP calls
//Sets the listener to listen to registration events. No effect if the profile has not been opened to receive call
sipManager.setRegistrationListener(sipProfile.getUriString(), new SipRegistrationListener()
{
public void onRegistering(String localProfileUri)
{
//Called when a registration request is sent
status("Registering");
}
public void onRegistrationDone(String localProfileUri, long expiryTime)
{
//Called when the registration succeeded
status("Ready");
}
public void onRegistrationFailed(String localProfileUri, int errorCode, String errorMessage)
{
//Called when the registration failed
status("Registration Failed " + localProfileUri + errorCode + errorMessage );
}
});
if (sipManager.isRegistered(sipProfile.getUriString()))
{
Log.d("Profile","SipManager is ready for calls");
}
if (sipManager.isOpened(sipProfile.getUriString()))
{
Log.d("Profile","SipManager is open");
}
}
catch (ParseException pe)
{
status("Connection Error");
}
catch (SipException sipe)//if calling the SIP service results in an error
{
status("Error with SIP " + sipe);
}
catch (SecurityException se)
{
status("Error with security" + se);
}
catch (RuntimeException re)
{
status("Error with runtime" + re);
}
catch (Exception e)
{
status("Error" + e);
}
}
public void closeLocalProfile()
{
if (sipManager == null)
{
Log.d("Manager", "There is no manager 1");
return;
}
try
{
if (sipProfile != null)
{
Log.d("Profile", "There is already a profile 2");
sipManager.close(sipProfile.getUriString()); //Closes the specified profile to not make/receive calls
}
}
catch (SipException se)//if calling the SIP service results in an error
{
status("Error while closing SIP" + se);
}
}
public void initCall()
{
callstatus("Adress: " + sipAddress);
try
{
SipAudioCall.Listener listener = new SipAudioCall.Listener() //Listener for events relating to a SIP call, such as when a call is being recieved ("on ringing") or a call is outgoing ("on calling")
{
@Override
public void onCalling(SipAudioCall call)
{
Log.d("initCall", "Initiating session! " + sipAddress);
}
@Override
public void onCallEstablished(SipAudioCall call)
{
Log.d("initCall", "Call started! " + sipAddress);
call.startAudio();//Starts the audio for the established call. This method should be called after onCallEstablished(SipAudioCall) is called
Enter();
}
@Override
public void onRinging(SipAudioCall call, SipProfile caller)
{
Log.d("initCall", "Ringing " + sipAddress);
}
@Override
public void onRingingBack(SipAudioCall call) //Called when a RINGING response is received for the INVITE request sent
{
Log.d("initCall", "Ringing back " + sipAddress);
}
@Override
public void onCallBusy(SipAudioCall call)
{
Log.d("initCall", "Call busy " + sipAddress);
}
@Override
public void onCallEnded(SipAudioCall call)
{
Log.d("initCall", "Call Over ");
call.close();
}
@Override
public void onError(SipAudioCall call, int errorCode, String errorMessage)
{
//super.onError(call, errorCode, errorMessage);
Log.d("initCall", "Error! " + errorMessage + errorCode);
}
};
//the call object that carries out the audio call
call = sipManager.makeAudioCall(sipProfile.getUriString(), sipAddress, listener, 30);
}
catch (Exception e)
{
status("Error when trying to close manager 1. " + e);
if (sipProfile != null)
{
try
{
sipManager.close(sipProfile.getUriString());
}
catch (Exception ee)
{
status("Error when trying to close manager 2. " + ee);
}
}
if (call != null)
{
call.close();
}
}
}
public void status(final String status)//status about the program
{
StatusTextView = (TextView) findViewById(R.id.StatusTextView);
StatusTextView.setText(status);
}
public void callstatus(final String callstatus)//status about the call
{
CallTextView = (TextView) findViewById(R.id.CallTextView);
CallTextView.setText(callstatus);
}
Thanks for your time & attention.
</details>
# 答案1
**得分**: 1
**更新**
通过在重新安装应用程序并将代码从Android Studio重新发送到手机后重新启动设备的组合方式成功地避开了先前的这些错误。正如我之前所述,我对错误来源的怀疑是由于这个堆栈存在的错误,尽管如此,现在它已经可以运行了,我对最终的成品感到满意。
尽管在这里没有得到任何回应,我希望这个帖子能对某人有所帮助。
感谢您的时间和关注。
<details>
<summary>英文:</summary>
**Update**
Managed to circumnavigate these previous errors by a combination of rebooting the device after reinstalling the app and resending the code from Android Studio to the phone. My suspicions about the source of the error is, as I stated above, due to the bugs that this stack has, nevertheless it now works and I'm satisfied with the finished product.
Despite not getting any response here, I hope that this thread can be of help to somebody.
Thanks for your time & attention.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论