I used the Android built-in sip library to write an app that makes calls via my server. The calls are being made correctly, but most of the time, the calls aren't ended correctly.
This is my code to end the call:
public void stopCalling(){
try {
call.endCall();
call.close();
} catch (SipException e) {
e.printStackTrace();
}
}
But it does not Ended properly.
Is there any other way to ended the sip call.
Related
I'm working on a project that improves Automation Test for Android's App. What I want to do is very "easy": I have this very simple SIP Client with a basic UI and developed just reading the API guides on the android developer website (https://developer.android.com/guide/topics/connectivity/sip.html) that receives and makes SIP calls.
I need to control remotely this app from my PC, connected at the same local network or the same wifi, by sending commands or similar (without interact with the phone) to the app itslef running normally on my phone.For a specific example I posted the method initiateCall() that calls sipAddress(in the app, sipAddress is taken from a Text Box), what I want to do is:
Starting the app on my phone
calling the method initiateCall() from my pc giving a sipAddress as a parameter (I must not use the UI from the app running, that's why I need to give the sipAddress)
check if an outgoing call starts from the app running on my phone
I thought that the solution must be something about web-services,but I don't have any better ideas and i don't know how to start and where to start solving this problem,that's why i need you help.
public void initiateCall() {
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
// set up the listener for outgoing calls
#Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
updateStatus(call, 2);
}
#Override
public void onCallEnded(SipAudioCall call) {
updateStatus("Call End");
}
};
call = manager.makeAudioCall(me.getUriString(), sipAddress,
listener, 30);
} catch (Exception e) {
Log.i("WalkieTalkieActivity/InitiateCall",
"Error when trying to close manager.", e);
if (me != null) {
try {
manager.close(me.getUriString());
} catch (Exception ee) {
Log.i("WalkieTalkieActivity/InitiateCall",
"Error when trying to close manager.", ee);
ee.printStackTrace();
}
}
if (call != null) {
call.close();
}
}
}
You could do it REST API style. You would need to set up a minimalistic webserver.
If you access for example the url phoneip/ctrl/makecall?number=yournumber a serverside method us called if set up correctly. Then you can call you method and use the GET or POST variables as arguments.
You would have to look into Java Webserver Libraries/Frameworks. You can pick a lightweight one for that purpose. For example this one.
You could then also add security features (authentification to protect it) quite easily.
Example with sparkjava
import static spark.Spark.*;
....
get("/ctrl/makecall", (request, response) -> {
String phonenum = request.queryParams("number"); //may not be accurate; you have to determine the GET variable called "number" in that case; you can rename it; see docs!!!
//call your method with proper arguments
});
I've made my own SIP client for Android. I'm facing an issue. I've made the test on SipDroid : if I call someone and hang up before he unhooked, the call end of the both side.
With my client, when I hang up, the call is not ended for the receiver, leading to a communication on one side.
Here is my code for ending a call :
if (call != null)
{
Log.i(TAG, "Trying to end call");
try
{
call.endCall();
}
catch (SipException e)
{
Log.i(TAG, "Service failed to end the call", e);
}
call.close();
updateStatus("Call Ended");
}
Where call is a SipAudioCall.
I get my call like this :
call = manager.makeAudioCall(profile.getUriString(), sipAddressToCall, listener, _Params.callWait);
I don't know about your API, but the SIP protocol itself has the "CANCEL" request to "hang up" before the call is answered.
On a normal, ongoing call, you send "BYE".
I have seen some hide methods in
/** #hide */
public void setDiscoverableTimeout(int timeout) {
if (getState() != STATE_ON) return;
try {
mService.setDiscoverableTimeout(timeout);
} catch (RemoteException e) {Log.e(TAG, "", e);}
}
I want to use the above method but still not aware that how can I use this method in my program so that my app should be always in discoverable mode?
you can use reflections, i have been using it. The only flip side is it may be google doesn't provide any guarantee for it.
I'm developping a SIP application, and when i want to call someone(with its identifier configured in the server) i have a NullPointerException => "Error when trying to close manager."
Here is the code:
public void initiateCall() {
updateStatus(sipAddress);
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
#Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
call.toggleMute();
updateStatus(call);
}
#Override
public void onCallEnded(SipAudioCall call) {
updateStatus("Ready.");
}
};
call = manager.makeAudioCall(me.getUriString(), sipAddress, listener, 30);
}
catch (Exception e) {
Log.i("WalkieTalkieActivity/InitiateCall", "Error when trying to close manager.", e);
if (me != null) {
try {
manager.close(me.getUriString());
} catch (Exception ee) {
Log.i("WalkieTalkieActivity/InitiateCall",
"Error when trying to close manager.", ee);
ee.printStackTrace();
}
}
if (call != null) {
call.close();
}
}
}
Thank you for your help.
The VOIP/SIP libary is not supported by default on Android emulator. The problem is that the manager == null - thats why you are getting the NullPointerException.
Luckily, there is a work-a-round. Download this link and copy it into ...\.android\avd\.avd folder.
Start your emulator and
Boolean voipSupported = SipManager.isVoipSupported(this);
Boolean apiSupported = SipManager.isApiSupported(this);
should now return true.
Source: http://xilard.hu/
Android.net.sip (Sip API) only works on G711 over Android 2.3+.
Also the phones supplied by carriers may have the SIP stack (android.net.sip) blocked or cripple. SipManager.isVoipSupported(this) && SipManager.isApiSupported(this) will return false for most of the devices is your ie. your SipManager object will always be null in such case.You should use third party library to implement SIP.
There are different open source sip stack libraries as well as projects are available on internet. You can download the source code of that projects.
Here is the List of some popular open source sip stack libraries which allows to voice call over internet.
1.Jain sip (I think the best option):
2.Pjsip
3.Mjsip
4.Doubango
There are different open source projects which have used these libraries in their projects.
1.Jain sip: Not used in a "famous" app.
2. Sipdroid uses MjSip
3. Csipsimple uses PjSip
4. Imsdroid uses doubango.
Check the bridge connection in Android and the SIP server in your application to obtain the SIP key of your application.
Ok, I understood, that when you bind to a remote Service, it won't bind until you return from the callback. I need to bind to a service and execute some method from it immediately. Is there any way? My code looks like:
try {
Parser parser = FrameworkBridge.getFrameworkBridge(this).getParser();
if (parser != null) {
for (Article a : parser.getArticlesList("http://www.bt.dk/mecommobile/latest/news_article/%s/%s?output_type=xml", 1379, 20)) {
listAdapter.add(a);
}
}
} catch (RemoteException e) {
Log.d(TAG, "Service communication failure");
} catch (FrameworkNotInstalledException e) {
Log.d(TAG, "No framework installed. Install it!");
}
Here FrameworkBridge.getFrameworkBridge(this).getParser() performs all service connection routine and returns remote interface. The problem is -- when I'm in the code above, the connection is not performed yet, therefore parser is null. How can I make it connect before exiting the code?
onServiceConnected(..) will tell you when the service is connected and the remote interface is established. Don't try to call any methods in the service until this is triggered.
mContext.bindService( new Intent("name of the class"), this, Context.BIND_AUTO_CREATE);
the above method call on the copy of the context you store should automatically bind the service when you need it. I am not 100% sure, but this should help you out somewhat.