I'm trying to receive calls on my SIP application at Embarcadero with C++ builder
and I'm not able to get it. My situation is as follows:
I've made an Asterisk server, I've created several accounts to be able to do the
tests and I've downloaded the Zoiper application for both Windows and Android.
In my designed application, I'm able to make calls to those accounts registered
in Zoiper, although not through events, it seems that the listener does not
listen, and I've done it through the status changes in the call.
The Java code is like this:
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
#Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
call.toggleMute();
Log.d("on call established", "on call established");
}
#Override
public void onCallEnded(SipAudioCall call) {
finish();
}
};
In Embarcadero C++ builder I think it would be like this (it doesn't work)
Compiles and executes but the event never occurs:
//The Manifest counts as the necessary permissions for Android, Internet and Sip.
_di_JSipAudioCall_Listener audioCall_Listener;
_di_JSipSession_Listener sessionListener;
_di_JSipSession session;
_di_JSipManager;
_di_JSipAudioCall audioCall;
_di_JSipProfile profile;
_di_JString uri;
_di_JString uri_llamada;
void onCallEstablished2(SipAudioCall call);
//The process of profile creation and instantiation of SipManager are programmed
//and compiled and do not give any problem.
audioCall_listener = TJSipAudioCall_Listener::JavaClass->init();
audioCall_listener->onCallEstablished = onCallEstablished2;
sessionListener = TJSipSession_Listener::JavaClass->init();
session = manager->createSipSession(profile,sessionListener);
audioCall = manager->makeAudioCall(uri,uri_llamada,audioCall_listener,15);
void onCallEstablished2(SipAudioCall call)
{
audioCall->startAudio();
audioCall->setSpeakerMode(true);
}
The code made in Embarcadero C++ builder that works:
//The Manifest counts as the necessary permissions for Android, Internet and Sip.
_di_JSipAudioCall_Listener audioCall_Listener;
_di_JSipSession_Listener sessionListener;
_di_JSipSession session;
_di_JSipManager;
_di_JSipAudioCall audioCall;
_di_JSipProfile profile;
_di_JString uri;
_di_JString uri_llamada;
//The process of profile creation and instantiation of SipManager are programmed
//and compiled and do not give any problem.
audioCall_listener = TJSipAudioCall_Listener::JavaClass->init();
audioCall_listener->onCallEstablished = onCallEstablished2;
sessionListener = TJSipSession_Listener::JavaClass->init();
session = manager->createSipSession(profile,sessionListener);
audioCall = manager->makeAudioCall(uri,uri_llamada,audioCall_listener,15);
Timer1->Enabled = true;
void __fastcall TMainForm::Timer1Timer(TObject *Sender)
{
if (audioCall->getState() == 8)
{
audioCall->startAudio();
audioCall->setSpeakerMode(true);
}
if(audioCall->getState() == 0)
{
audioCall->endCall();
}
}
As for the Java code for receiving calls, I have found examples here
No ringing event on incoming calls
and here
Android Sip incoming Call using Service with Broadcast Receiver,
but they are all event based, which doesn't seem to work for me.
I have also tried to do the IncomingReceiver class, which extends from
BroadcastReceiver and at the Embarcadero gives me problems.
Class made in Embarcadero with C++ builder (not compiles):
class IncomingReceiver: public JBroadcastReceiver{
public:
__fastcall IncomingReceiver();
_di_JSipAudioCall incomingCall;
void onReceive(_di_JContext contexto, _di_JIntent intento);
void accept();
void showIncomingCallGui(_di_JIntent intento, _di_JContext contexto);
};
So, my questions are:
Why don't events work for me?
Can I receive calls without events?
If so, what would it be like without events?
What do I do if I can't get the IncomingReceiver class?
I found a page (in spanish): http://lfgonzalez.visiblogs.com/cbuilder-10-2-tokyo-jni-broadcastreceiver-android/ in which it is explained the use of BroadcastReceiver in Embarcadero C++ Builder. Maybe with this information you can get the events working in order to receive calls.
Related
I'm facing a issue in an app I'm developing that someone may be able to help me with.
I'm working on an app for payment machines that use Android (7.1), with it you are able to pay with credit card. The company that developed these machines offer a java sdk. Since this app is using React Native, I wrote a Native Module to connect with it. The SDK is really simple.
After the app is authenticated (done just once), All I have to do is call the doAsyncPayment method with the right parameters, and once its done, it will call the onSuccess or onError method of the listener.
When either of these methods is called, I call the callback parameter I got from the React Native side. In theory it's supposed to work, and it does, most of the time. Every once in a while, something happens that these callbacks are not called, so the client stays on the loading payment screen forever. No error is reported on sentry.
The only thing I'm thinking is that somehow the bridge is losing it? Maybe because these method runs asyncronously in the native side (another thread?), the connection is maybe lost?
I haven't been able to reproduce it, because it happens rarely and at random (I suppose).
I don't know much of Native Android, so any help is appreciated.
Here is a resumed piece of code of what's happening:
Native method being called:
#ReactMethod
public void startPayment(...other params,
Callback onErrorCallback, Callback onSuccessCallback) {
setPlugPag();
PlugPagPaymentData paymentData = new PlugPagPaymentData(paymentType, amountCents,
installmentType, installments, userReference, printReceipt);
PlugPagInitializationResult initResult = plugPag.initializeAndActivatePinpad(new
PlugPagActivationData(activationCode));
if(initResult.getResult() == PlugPag.RET_OK) {
plugPag.doAsyncPayment(paymentData, new PlugPagPaymentListener() {
PlugPagPrintResult printResult;
#Override
public void onSuccess(#NonNull PlugPagTransactionResult plugPagTransactionResult) {
if(printResult != null) {
WritableMap printResultMap = Arguments.createMap();
printResultMap.putInt("result", printResult.getResult());
printResultMap.putString("message", printResult.getMessage());
printResultMap.putString("errorCode", printResult.getErrorCode());
onSuccessCallback.invoke(TransactionResult.toRNWritableMap(plugPagTransactionResult), printResultMap);
}else {
onSuccessCallback.invoke(TransactionResult.toRNWritableMap(plugPagTransactionResult));
}
}
#Override
public void onError(#NonNull PlugPagTransactionResult plugPagTransactionResult) {
onErrorCallback.invoke(TransactionResult.toRNWritableMap(plugPagTransactionResult));
}
#Override
public void onPaymentProgress(#NonNull PlugPagEventData plugPagEventData) {
WritableMap eventDataMap = Arguments.createMap();
eventDataMap.putString("customMessage", plugPagEventData.getCustomMessage());
eventDataMap.putInt("eventCode", plugPagEventData.getEventCode());
sendEvent(Constants.EVENT_PLUG_PAG_PAYMENT_PROGRESS_CHANGED, eventDataMap);
}
#Override
public void onPrinterSuccess(#NonNull PlugPagPrintResult plugPagPrintResult) {
}
#Override
public void onPrinterError(#NonNull PlugPagPrintResult plugPagPrintResult) {
}
});
}else {
onErrorCallback.invoke(String.valueOf(initResult.getResult()));
}
}
on React native side, I just call:
startPayment(...other params, errorCallback, successCallback);
Maybe because the way the listener is instantiated?
Thanks in advance.
I have implemented google analytics in my android application using Xamarin and it is working fine and I am able to trigger GA events while my app is in the background or running. The Only problem which, I am getting is that I am not able to Trigger my GA events when my app is in kill mode? When my app is in kill mode, I am sending local notification using a broadcast receiver in which, I want to trigger my GA events.
I am not able to find anything relevant regarding this, could anyone help me out in this?
public class AlarmReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent){
//My implementation over here, in which I want to trigger GA events.
}
}
I have initialized my GA instance and trigger GA events in the below method in a separate class.
public IAnalyticsManager InitWithId(string analyiticsId)
{
if(Android.App.Application.Context==null)
{
gaInstance = GoogleAnalytics.GetInstance(context);
}
else
{
gaInstance = GoogleAnalytics.GetInstance(Android.App.Application.Context);
}
//
gaInstance.SetLocalDispatchPeriod(10);
tracker = gaInstance.NewTracker(analyiticsId);
tracker.EnableExceptionReporting(true);
return this;
}public void TrackEvent(String screenName, String lineNo,IDictionary<string,string> allEvents)
{
HitBuilders.EventBuilder builder = new HitBuilders.EventBuilder();
builder.SetCategory(screenName);
builder.SetAction(lineNo);
builder.SetAll(allEvents);
builder.SetLabel(allEvents[EMADefines.KeyTimeStamp]);
tracker.SetClientId(allEvents[EMADefines.KeyUserName]);
tracker.Send(builder.Build());
}
Initiate GA in your onReceive method like this -
gaInstance = GoogleAnalytics.GetInstance(context.getApplicationContext());
gaInstance.SetLocalDispatchPeriod(10);
tracker = gaInstance.NewTracker(analyiticsId);
tracker.EnableExceptionReporting(true);
And then call the TrackEvent method, ensure that you have the TrackEvent method in your AlarmReceiver class as well.
Where is the documentation/sample for all overloads of invokeApi function for Azure Mobile Service client SDK for Android?
I found this article and tried following code, which does not work. There are no compile time or run time errors, invokeApi gets called, but it does not come back to onSuccess or onFailure. If I call invokeApi without order object, everything works as expected
PizzaOrder order = new PizzaOrder();
order.Size = "Large";
order.Flavor = "Four cheeses";
order.UserPhone = "555-555-1234";
ListenableFuture<PizzaOrderResponse> testresult = mClient.invokeApi("bookservice", order, PizzaOrderResponse.class);
Futures.addCallback(testresult, new FutureCallback<PizzaOrderResponse>() {
#Override
public void onFailure(Throwable exc) {
// failure handling code here
}
#Override
public void onSuccess(PizzaOrderResponse testresult) {
// success handling code here
}
});
One of the properties in the data object being returned by the custom API had incorrect data type. I am still not sure where the good documentation is and why custom API call did not fail but at least it is working now.
I am writing a Spell Check client using the sample code in the SDK as an example. I have the following code (not actual implementation, but an accurate sample representation):
public class HelloSpellChecker implements SpellCheckerSessionListener {
private SpellCheckerSession mSpellCheckService;
private void bindService() {
final TextServicesManager tsm = (TextServicesManager) getSystemService(
Context.TEXT_SERVICES_MANAGER_SERVICE);
mSpellCheckService = tsm.newSpellCheckerSession(null, null, this, true);
}
public void getSuggestions(String word) {
mSpellCheckService.getSuggestions(new TextInfo("tgis"), 3);
}
#Override
public void onGetSentenceSuggestions(final SentenceSuggestionsInfo[] arg0) {
Log.d(TAG, "onGetSentenceSuggestions");
// Process suggestions
}
}
What I want to know is will onGetSentenceSuggestions only be fired when my application calls getSuggestions, or will it be fired any time the system service receives a request to getSuggestions?
If it is the latter, what is the best way to ensure my app only processes suggestions which it requested?
I would say Android system service listener is localized through the session in this case.
onGetSentenceSuggestions method is fired by any request to getSuggestions method. However, you don't have to worry about processing suggestions which your app requested since the spellchecker session takes care of it. Your app only gets the suggestions requested by the session your app created to interact with the spell checker service.
Hope this helps.
References:
http://developer.android.com/reference/android/view/textservice/SpellCheckerSession.html
http://developer.android.com/guide/topics/text/spell-checker-framework.html
I'm pretty new with Android programming. But I have been working on this for over a week now, and it starts to get booooring.
My idea is that I want to connect two devices using Wifi Direct. But I only want to connect to those which are running my application. Besides, I want the users to be able to see some information of the other devices (such as user name), not just the MAC or the Android_XXXX name included in the WifiP2pDevice. That's why I decided that a device looking for other devices, should both start the application service and search for peers which are also broadcasting this service.
The problem (I'm testing with two real devices) is that, even though they are running exactly the same code, only one of them is getting the service discovery callbacks (the onDnsSd... listeners below). So, one side acts in the proper way, but not the other. Moreover I'm getting "old" services, meaning that apparently each time I start de service (even though I cancel previously started services), that service seems to be still broadcast during at least some minutes.
I include a shortened version of my code:
public class MoveFlufietsDialogFragment extends DialogFragment implements ChannelListener, DeviceActionListener {
public final HashMap<String, FlufietsPeer> mBuddies = new HashMap<String, FlufietsPeer>();
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
...
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
mManager = (WifiP2pManager) getActivity().getSystemService(Context.WIFI_P2P_SERVICE);
mChannel = mManager.initialize(getActivity(), getActivity().getMainLooper(), null);
...
startRegistration();
discoverFlufietsService();
...
}
public void discoverFlufietsService() {
DnsSdTxtRecordListener txtListener = new DnsSdTxtRecordListener() {
#Override
public void onDnsSdTxtRecordAvailable(String fullDomain, Map record, WifiP2pDevice device) {
// This and the next listener are only called in one of the devices.
String serviceName = (String) record.get("serviceName");
if ((serviceName != null) && (serviceName.equals("flufiets")) {
// I put the record data in the mBuddies HashMap.
...
mBuddies.put(device.deviceAddress, myPeerDataStructure);
}
}
};
DnsSdServiceResponseListener servListener = new DnsSdServiceResponseListener() {
#Override
public void onDnsSdServiceAvailable(String instanceName, String registrationType, WifiP2pDevice resourceType) {
if (mBuddies.containsKey(resourceType.deviceAddress)) {
FlufietsPeer flufietsPeer = mBuddies.get(resourceType.deviceAddress);
WiFiPeerListAdapter adapter = ((WiFiPeerListAdapter) mFragmentList.getListAdapter());
adapter.add(flufietsPeer);
adapter.notifyDataSetChanged();
}
}
};
mManager.setDnsSdResponseListeners(mChannel, servListener, txtListener);
WifiP2pDnsSdServiceRequest serviceRequest = WifiP2pDnsSdServiceRequest.newInstance();
mManager.addServiceRequest(mChannel, serviceRequest, new ActionListener() {
// onSuccess/onFailure toasts.
});
mManager.discoverServices(mChannel, new WifiP2pManager.ActionListener() {
// onSuccess/onFailure toasts.
});
}
public void startRegistration() {
mManager.clearLocalServices(mChannel, new ActionListener() {
// onSuccess/onFailure toasts.
});
Map record = new HashMap();
record.put("serviceName", "flufiets");
...
WifiP2pDnsSdServiceInfo serviceInfo = WifiP2pDnsSdServiceInfo.newInstance(flufietsService, "_tcp", record);
mManager.addLocalService(mChannel, serviceInfo, new ActionListener() {
// onSuccess/onFailure toasts.
});
}
#Override
public void onResume() {
super.onResume();
mReceiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, this);
getActivity().registerReceiver(mReceiver, mIntentFilter);
}
#Override
public void onPause() {
super.onPause();
getActivity().unregisterReceiver(mReceiver);
}
#Override
public void onStop() {
super.onStop();
mManager.clearLocalServices(mChannel, new ActionListener() {
// onSuccess/onFailure toasts.
});
}
...
}
The problem doesn't seem to be related with the device itself (sometimes it works, sometimes it doesn't, but always only in one of them). I suspect it has to do with either trying to discover a service that we ourselves are broadcasting, or having the same service being offered by two devices. I have tried changing the names of the service, so each device would offer either a "send" or "receive" service, but it doesn't work. I only get the callbacks called (onDnsSd...) in one of the devices.
And that thing about getting old services, when I always clear them, is weird (I do include a timestamp in the service record data, and I could always discard all but the last, but doesn't seem to be logical).
Any ideas? ANY help would be VERY appreciated, because writing the application is not funny any more (:-)=
Thanks a lot!
You need to wait until the clearLocalService call succeeds before adding the local service later. So put the addLocalService call into the onSuccess callback of the clearLocalServices.