android.net.sip.SipException: VOIP API is not supported - android

i Build the app which contain SIP/VOIP call.i Run the app in samsung,Redmi,One plus One it Work fine But When i run the same app in Micromax,Moto G devices it crash when i Call SIP/VOIP Function.Its Showing the error in Logcat.
Error:
Error when trying to close manager. android.net.sip.SipException: VOIP API is not supported
and my function is
public void initiateCall() {
EditText Concode;
Concode=(EditText)findViewById(R.id.ConfCode);
String sipadd="sip address";
if(sipadd!= null && !sipadd.isEmpty()){
// updateStatus(sipAddress);
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
// Much of the client's interaction with the SIP Stack will
// happen via listeners. Even making an outgoing call, don't
// forget to set up a listener to set things up once the call is established.
#Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(false);
// call.toggleMute();
//updateStatus(call);
}
#Override
public void onCallEnded(SipAudioCall call) {
//updateStatus("Ready.");
}
};
call = manager.makeAudioCall(me.getUriString(), sipadd, listener, 30);
}
catch (Exception e) {
Log.i("JoinConfWithoutLogin/InitiateCall", "Error when trying to close manager.", e);
if (me != null) {
try {
manager.close(me.getUriString());
} catch (Exception ee) {
Log.i("MainActivity/InitiateCall",
"Error when trying to close manager.", ee);
ee.printStackTrace();
}
}
if (call != null) {
call.close();
}
}}
else {
new AlertDialog.Builder(this)
.setTitle("Error")
.setMessage("Enter Conferance Code")
.setNegativeButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// do nothing
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
}
Whats the problem behind this?
Help Me to solve this issue
Thanks in advance.

Not all Android-powered devices support VOIP calls using SIP. You should always call isVoipSupported() to verify that the device supports VOIP calling and isApiSupported() to verify that the device supports the SIP APIs. Your application must also request the Manifest.permission.INTERNET and Manifest.permission.USE_SIP permissions.

Related

How to call an Android app's method remotely?

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
});

Chromecast Android Sender RemoteMediaPlayer producing No current media session

I have been able to successfully cast video to a Chromecast and have the option let the video play when disconnecting and it all works great. However, if I choose to quit the application and let the video continue playing and then try to re-join the currently playing session and try to use the RemoteMediaPlayer to control the video I am getting: "java.lang.IllegalStateException: No current media session".
Just as a background, I am saving the route id and session id on the initial connect into preferences and am able to successfully call "Cast.CastApi.joinApplication" and when in the onResult I am recreating the Media Channel and setting the setMessageReceivedCallbacks like so:
Cast.CastApi.joinApplication(mApiClient,"xxxxxxxx",persistedSessionId).setResultCallback(new ResultCallback<Cast.ApplicationConnectionResult>() {
#Override
public void onResult(Cast.ApplicationConnectionResult applicationConnectionResult) {
Status status = applicationConnectionResult.getStatus();
if (status.isSuccess()) {
mRemoteMediaPlayer = new RemoteMediaPlayer();
mRemoteMediaPlayer.setOnStatusUpdatedListener(
new RemoteMediaPlayer.OnStatusUpdatedListener() {
#Override
public void onStatusUpdated() {
Log.d("----Chromecast----", "in onStatusUpdated");
}
});
mRemoteMediaPlayer.setOnMetadataUpdatedListener(
new RemoteMediaPlayer.OnMetadataUpdatedListener() {
#Override
public void onMetadataUpdated() {
Log.d("----Chromecast----", "in onMetadataUpdated");
}
});
try {
Cast.CastApi.setMessageReceivedCallbacks(mApiClient,mRemoteMediaPlayer.getNamespace(), mRemoteMediaPlayer);
} catch (IOException e) {
Log.e("----Chromecast----", "Exception while creating media channel", e);
}
//-----------RESOLUTION START EDIT------------------
mRemoteMediaPlayer.requestStatus(mApiClient).setResultCallback(new ResultCallback<RemoteMediaPlayer.MediaChannelResult>() {
#Override
public void onResult(RemoteMediaPlayer.MediaChannelResult mediaChannelResult) {
Status stat = mediaChannelResult.getStatus();
if(stat.isSuccess()){
Log.d("----Chromecast----", "mMediaPlayer getMediaStatus success");
// Enable controls
}else{
Log.d("----Chromecast----", "mMediaPlayer getMediaStatus failure");
// Disable controls and handle failure
}
}
});
//-----------RESOLUTION END EDIT------------------
}else{
Log.d("----Chromecast----", "in status failed");
}
}
}
If I declare the RemoteMediaPlayer as static:
private static RemoteMediaPlayer mRemoteMediaPlayer;
I can join the existing session as well as control the media using commands like:
mRemoteMediaPlayer.play(mApiClient);
or
mRemoteMediaPlayer.pause(mApiClient);
But once I quit the application obviously the static object is destroyed and the app produces the aforementioned "No current media session" exception. I am definitely missing something because after I join the session and register the callback perhaps I need to start the session just like it was creating when I initially loaded the media using mRemoteMediaPlayer.load(.
Can someone please help as this is very frustrating?
The media session ID is part of the internal state of the RemoteMediaPlayer object. Whenever the receiver state changes, it sends updated state information to the sender, which then causes the internal state of the RemoteMediaPlayer object to get updated.
If you disconnect from the application, then this state inside the RemoteMediaPlayer will be cleared.
When you re-establish the connection to the (still running) receiver application, you need to call RemoteMediaPlayer.requestStatus() and wait for the OnStatusUpdatedListener.onStatusUpdated() callback. This will fetch the current media status (including the current session ID) from the receiver and update the internal state of the RemoteMediaPlayer object accordingly. Once this is done, if RemoteMediaPlayer.getMediaStatus() returns non-null, then it means that there is an active media session that you can control.
As user3408864 pointed out, requestStatus() after rejoining the session works. Here is how i managed to solve it in my case and it should work in yours.
if(MAIN_ACTIVITY.isConnected()){
if(MAIN_ACTIVITY.mRemoteMediaPlayer == null){
MAIN_ACTIVITY.setRemoteMediaPlayer();
}
MAIN_ACTIVITY.mRemoteMediaPlayer.requestStatus(MAIN_ACTIVITY.mApiClient).setResultCallback( new ResultCallback<RemoteMediaPlayer.MediaChannelResult>() {
#Override
public void onResult(RemoteMediaPlayer.MediaChannelResult mediaChannelResult) {
if(playToggle ==0){
try {
MAIN_ACTIVITY.mRemoteMediaPlayer.pause(MAIN_ACTIVITY.mApiClient);
playToggle =1;
} catch (IOException e) {
e.printStackTrace();
}
}else{
try {
MAIN_ACTIVITY.mRemoteMediaPlayer.play(MAIN_ACTIVITY.mApiClient);
playToggle =0;
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
}
Ignore, MAIN_ACTIVITY, it is just a static reference to my activity since i run this piece of code from a Service. Also, setRemoteMediaPlayer() is a method where i create a new RemoteMediaPlayer() and attach the corresponding Listeners.
Hopefully this helps. Also, sorry if any mistake, it is my first post to StackOverFlow.

Try Catch method for open bluetooth function

I made a simple android appication for connect with bluetooth serial device and I want to add closeBT if android not connected maybe the device is out of range because crash.
How do I do this? This code is correct?
protected void onStart() {
super.onStart();
findBT(); //Check if bluettoth enable and paired devices
try {
openBT(); //open sockets,streams
} catch (IOException e) {
e.printStackTrace();
closeBT();
}
}
Try-catch is not for the application logic! It is for doing stuff when something went wrong! You want to use an if-else here, like
if (findBT() != null) { // I don't know what findBT does, but maybe it returns BT-devices
try {
openBT(); //open sockets,streams
} catch (IOException e) {
e.printStackTrace();
// inform the user that a connection could not be established or something similar
}
} else {
// inform the user, that no BT-device was found.
}
you want to use closeBT() for instance when the user or your application decides to disconnect the BT-devices.

How to take a variable's value in the end of the code to use it in the begin of it

I have to post the code to understand what i want to say:
public void répondre()
{
mt = MediaPlayer.create(context,R.raw.ringtone);
mt.setVolume(5,5);
mt.start();
mt.setLooping(true);
//startActivity((new Intent(Intent.ACTION_ANSWER)));
AlertDialog.Builder ad = new AlertDialog.Builder(context);
ad.setTitle("Appel en cours...");
ad.setMessage("Voulez vous répondre à cet appel?");
ad.setPositiveButton("Oui",
new OnClickListener() {
public void onClick(DialogInterface dialog,
int arg1) {
mt.stop();
SipAudioCall incomingCall = null;
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
#Override
public void onRinging(SipAudioCall call, SipProfile caller) {
try {
call.answerCall(30);
} catch (Exception e) {
Log.d("Call not answered","Call not answered",e);
}
}
};
SIPCommunicator wtActivity = (SIPCommunicator) context;
incomingCall = wtActivity.manager.takeAudioCall(intent, listener);
incomingCall.answerCall(30);
incomingCall.startAudio();
incomingCall.setSpeakerMode(true);
if(incomingCall.isMuted()) {
incomingCall.toggleMute();
}
wtActivity.call = incomingCall;
String useName = wtActivity.call.getPeerProfile().getDisplayName();
wtActivity.updateStatus("Vous êtes en communication avec " + useName);
} catch (Exception e) {
if (incomingCall != null) {
incomingCall.close();
}
}
}
});
I want to show the caller's name(useName variable) in the AlertDialog. If i put this line(String useName = wtActivity.call.getPeerProfile().getDisplayName();) before MediaPlayerand make ad.setTitle("Appel en cours"+useName); the variable useName is null ! So how doing this ?
Thank you very much.
Fortunatelly, we do not need to break causality as indicated in the question title. Thing is (and that is not something so uncommon with phone applications handling) that in the moment when you get indication about incoming call, caller name is not ready. It is because it takes some time until callers number/uri has to be searched for in the contacts.
So, in order to handle this issue I would suggest that you do one of the following:
indicate incoming call via AlertDialog, but present just caller number/URI. Start Handler and second later update the dialog so it displays name.
when call arrives, start handler and execute your code just second later. Hopefully at that moment Name will be available.
So, in any case you need to update your AlertDialog some safe time after incoming call is indicated.

Exception when trying to call(SIP)

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.

Categories

Resources