I am working on voice calling app which is built in java and I need to know the call status when it is picked , rejected or complated.My server end is in java.
I set status callback url while placing a call as mention in the twilio docs. My question which url is to added in that code and do i need to add the funtion for that end point url also.
And what should be the code in that funtion like what are the parameters as I need to print the call status
com.twilio.type.Client clientEndpoint = new com.twilio.type.Client("client:" + to);
PhoneNumber from = new PhoneNumber(CALLER_ID);
// Make the call
Call call = Call.creator(clientEndpoint, from, uri).setMethod(HttpMethod.POST)
.setStatusCallbackMethod(HttpMethod.POST)
.setStatusCallback(URI.create("https://57fb8b2c.ngrok.io/events"))
.setStatusCallbackEvent(
Arrays.asList(Call.Event.ANSWERED.toString(), Call.Event.COMPLETED.toString(),
Call.Event.INITIATED.toString(), Call.Event.RINGING.toString()))
.create(client);
// Print the call SID (a 32 digit hex like CA123..)
System.out.println(call.getSid() + "//" + call.getStatus());
return call.getSid();
Twilio developer evangelist here.
I'm not particularly good at Java, but I can help with what happens when you set a statusCallback URL.
For each of the events you set as the statusCallbackEvent you will receive an HTTP request to your statusCallback URL when the call enters that state.
You will need to implement an endpoint (in your case, at the path /events as that's the URL you are setting) that can receive these incoming HTTP requests.
When Twilio makes the status callback request it includes all the regular webhook parameters, such as CallSid so you can tie the request to the known call sid.
The request will also include some other parameters, most importantly in your case the CallStatus parameter. The value will be one of queued, initiated, ringing, in-progress, busy, failed, or no-answer. There's more on what they mean here.
I hope that helps a bit.
Related
Im creating an andoid app with twilio calling capability. I have a python backend to handle incoming and outgoing requests. I've created a Twiml app to handle outgoing calls, including the call status.
Also I've configured the phone numbers to handle incoming calls including call status as below:
So the way it works is:
outgoing:
Android app call -> twilio -> python backend -> twilio -> callee
inbound:
caller -> twilio -> python backend -> twilio -> android app
On android, I'm using the following method to initiate the voice call:
params.put("to", dialledNumber);
ConnectOptions connectOptions = new ConnectOptions.Builder(callingLCNToken).params(params).build();
activeCall = Voice.connect(VoiceActivity.this, connectOptions, callListener);
On the python side, I have the following sample code to handle outgoing calls:
resp = VoiceResponse()
_to = request.values.get("to")
_from = request.values['From'].split(":")[1]
resp.dial(callerId=_from).number(_to)
return str(resp)
But I can't still capture the statuses: busy, no-answer, cancelled, failed as mentioned in this doc: https://support.twilio.com/hc/en-us/articles/223132547-What-are-the-Possible-Call-Statuses-and-What-do-They-Mean-
Also I want to get the during of call in-progress. But with the current status callback, it seems i'm getting the total time from call initialisation and completion.
I tried using StatusCallbackEvent and the callback URL there, but it didn't work either.
What should I do to get the correct call statuses and the call in-progress duration?
Twilio developer evangelist here.
I think the status callback URL you set up in the number admin is for inbound calls. You should set status callback URLs for outbound calls on the <Number> TwiML like this:
resp = VoiceResponse()
_to = request.values.get("to")
_from = request.values['From'].split(":")[1]
dial = resp.dial(callerId=_from)
dial.number(
_to,
status_callback_event='initiated ringing answered completed',
status_callback='https://example.com/callStatus'
)
return str(resp)
I have an Odoo server that is a WebApp with a website functionality.
I need to implement an Android/iOS app that comunicate with this website functionality.
The website functionality is simple:
Take the intervention code.
check if the state of the intervention sheet is visible into website.
if yes, edit the intervention sheet, if no show error message.
So I want to take the intervention number from Android (for example) and send it by HTTP request and if I get a yes response continue the editing and other stuff in a Webview....if I get "error" show the error into Android Activity.
This is my controller on server that check Code:
#http.route(['/checkCodeAction'],
type='http',
auth="public",
methods=['POST', 'GET'],
csrf=True,
website=True)
def worksheet_code_details(self, **post):
worksheet = request.env['project.task.worksheet']\
.sudo()\
.search([('intervention_number',
'=',
post.get('intervention_number'))])
if worksheet and worksheet.state_id.is_visible_on_frontend:
return redirect(f'/worksheetReadValues/{worksheet.id}')
return request.render(
"website_project_task_worksheet.worksheet_code",
{'error_code': True}
)
The request.render load an xml template of Odoo.... I can intercept this call into a webview?
Or I need to implements another controller for Android that receive for example two response (error, url_with_worksheetid)... so if I get error I show a message, if a get an URL I call the webview with this URL.
I think it's better to return the error using an HTTP Error Status Code and you would be able to better catch that error status code in your Android or IOS controller.
In Odoo you could return a raw werkzeug response like this (the following example from an existing Android-IOS-Odoo integration done by me):
return werkzeug.wrappers.Response(body, status=403, headers=[
('Content-Type', 'application/json'), ('Content-Length', len(body))
])
or you could add an status argument to your already returned render call that it's already a lazy render response wrapper, like:
return request.render(
"website_project_task_worksheet.worksheet_code",
{'error_code': True}, status=403
)
I want to intercept POST requests from a custom page, which is impossible from the callback client interface (unlike to GET one, you have no access to the POST request body). So, I have implemented a service worker based solution, which wrapping POST request into a GET one with the same data, that I can handle in shouldInterceptRequest().
So, once the service worker is registered and active:
function subscribeToSWMessages()
{
navigator.serviceWorker.onmessage = function (event)
{
if (event.data.command == 'activeSW')
{
// !! Only from now we can post requests !!
}
};
}
Only after that it's safe to post request from the page. So, how to properly inject my JS code, to be sure no requests are posted until the message is received? Can the page be totally custom, or I should ask its developer to do something on their side?
I am having a problem getting a parameter sent from android app into go application. I called r.FormValue(key) but it returned null. I want to find the way to check what are parameters available on Go side after the android app sent the post data to it. Is there any way to do this, getting all parameters without using keys?
The Request structure in go has a Form field which is populated with request parameters after ParseForm() is called.
Form contains the parsed form data, including both the URL field's
query parameters and the POST or PUT form data.This field is only
available after ParseForm is called. The HTTP client ignores Form and
uses Body instead.
You could try adding the following code after receiving a request:
func(w http.ResponseWriter, request *http.Request) {
request.ParseForm()
log.Printf("%v",request.Form)
//....
}
If this is for debugging, you can use DumpRequest:
func(w http.ResponseWriter, r *http.Request) {
dump, err := httputil.DumpRequest(r, true)
if err != nil {
http.Error(w, fmt.Sprint(err), http.StatusInternalServerError)
return
}
log.Printf("%s", dump)
}
I am creating one chatting application which will work on both iOS and Android platform. Sometimes 'both' subscription is not received at both end. Can anyone tell me what can be the possible issue?
===================== For iOS =====================
Sending request,
XMPPJID *XMPPJIDObj=[XMPPJID jidWithString:aStrOtherJabberId];
[appDelegateObj.xmppRoster addUser:XMPPJIDObj withNickname:nil];
Accepting request,
[appDelegateObj.xmppRoster acceptPresenceSubscriptionRequestFrom:aReceiverJID andAddToRoster:TRUE];
Removing user,
[appDelegateObj.xmppRoster removeUser:[XMPPJID jidWithString:aPresenceObj.userJabberID]];
===================== For Android =====================
Sending request,
Roster.setDefaultSubscriptionMode(SubscriptionMode.manual);
myApp.getXmppConnection().getRoster().createEntry(visitorJabberId, visitorUserName, null);
Accepting request,
final Presence presence1 = new Presence(Type.subscribed);
presence1.setFrom(myApp.getUserJabberId());
presence1.setType(Type.subscribed);
presence1.setTo(visitorJabberId);
myApp.getXmppConnection().sendPacket(presence1);
myApp.getXmppConnection().getRoster().createEntry(visitorJabberId, visitorUserName, null);
Removing user,
final RosterPacket rosterPacket = new RosterPacket();
rosterPacket.setType(IQ.Type.SET);
final RosterPacket.Item item = new RosterPacket.Item(visitorJabberId, null);
item.setItemType(RosterPacket.ItemType.remove);
rosterPacket.addRosterItem(item);
myApp.getXmppConnection().sendPacket(rosterPacket);
Hi Leena for the iOS we have used save thing but I think you have forgot some thing. The actual flow is call add user method of roster class then call subscribe method with subscription value YES and finally send presence tag with subscribe type to the serve. Following are the code here I used XMPPSharedPreference singleton class rather than appdelegate. Hope this will work for you...
XMPPJID *newBuddy = [XMPPJID jidWithString:JIDString];
[[XMPPSharedPreference sharedPreferences].xmppRoster addUser:newBuddy withNickname:#"nicknameValue"];
[[XMPPSharedPreference sharedPreferences].xmppRoster acceptPresenceSubscriptionRequestFrom:newBuddy andAddToRoster:YES];
NSXMLElement *presence = [NSXMLElement elementWithName:#"presence"];
[presence addAttributeWithName:#"to" stringValue:JIDString];
[presence addAttributeWithName:#"type" stringValue:#"subscribe"];
[[self xmppStream] sendElement:presence];
When you add a user to your roster you have to make sure you also subscribe to the friend's presence. That completes the cycle.
So, for iOS for example, you're adding a friend to roster like this:
[appDelegateObj.xmppRoster addUser:XMPPJIDObj withNickname:nil];
But you need to do use this instead:
- (void)addUser:(XMPPJID *)jid withNickname:(NSString *)optionalName groups:(NSArray *)groups subscribeToPresence:(BOOL)subscribe
and make sure you set subscribe to YES
Or, you could keep the code you have but manually subscribe to the user's presence by doing this:
[appDelegateObj.xmppRoster subscribePresenceToUser:XMPPJIDObj]
Let me know how that works out for you.