public interface CallBridge
Internal service-provider interface implemented by each platform port to
carry the com.codename1.call API onto the native call stacks: Apple’s
CallKit and PushKit, and Android’s ConnectionService, TelecomManager
and CallScreeningService.
Application code never touches this interface. It is obtained by the
com.codename1.call packages from
com.codename1.ui.Display#getCallBridge(), and the base implementation
returns null – which is why the public API degrades to a well-behaved
NOT_SUPPORTED on ports that implement nothing, and why application code
needs no platform if statements.
Everything here is primitives, strings and byte arrays
A port may be Objective-C reached through ParparVM, where constructing a
Java object is expensive and easy to get wrong. So no method on this
interface takes or returns a framework type: enums cross as their
ordinals, capability sets cross as bit masks, and structured records
cross as tab-delimited strings built by
com.codename1.impl.call.CallWire.
Asynchrony is by request id, and every operation must answer
Operations that can fail take a requestId allocated by the caller and
answer exactly once by calling the matching deliver... entry point on
the public class. An operation that never answers is worse than one
that fails: the caller holds an AsyncResource that will never settle
and has no way to find out. A port that cannot start something must still
report the failure. This bites harder here than elsewhere, because both
platforms have a documented “the system refused your call” path –
Telecom’s onCreateIncomingConnectionFailed and the NSError handed to
CallKit’s report completion – that is easy to leave unwired, and an
unwired refusal looks exactly like a call that is still ringing.
Unsolicited events – the user answering, the system taking the audio – carry the call id they belong to instead of a request id. Every entry point may be called from any thread; they marshal to the EDT themselves.
The up direction has a deadline too
A system-originated action must be answered with completeAction within
a few seconds or the platform times it out and the system UI and the app
disagree about the call, silently. The facade guarantees an answer the
same way this interface guarantees one downward.
Fields
Methods
Field details
CAPABILITY_SYSTEM_UI
public static final int CAPABILITY_SYSTEM_UI = 1getCallCapabilities() bit: the platform draws a system call UI.CAPABILITY_OUTGOING
public static final int CAPABILITY_OUTGOING = 2getCallCapabilities() bit: outgoing calls can be reported.CAPABILITY_HOLD
public static final int CAPABILITY_HOLD = 4getCallCapabilities() bit: calls can be held and resumed.CAPABILITY_MUTE
public static final int CAPABILITY_MUTE = 8getCallCapabilities() bit: the app can SET the system mute state.
About setMuted only. Hearing what the user does with the system’s
own mute control is not gated by this and arrives everywhere, through
Calls.deliverMuteChanged; Android reports that and offers no way to
drive it, so it does not set this bit.
CAPABILITY_DTMF
public static final int CAPABILITY_DTMF = 16getCallCapabilities() bit: the system offers a keypad and
delivers DTMF digits.CAPABILITY_GROUPING
public static final int CAPABILITY_GROUPING = 32CXSetGroupCallAction
travels system to app and has no app-initiated counterpart, and
Telecom conferences self-managed calls only through a
ConnectionService conference this port does not build. So
CallSession.groupWith always answers NOT_SUPPORTED. The constant is
kept so the bit values do not shift if that changes.CAPABILITY_VIDEO
public static final int CAPABILITY_VIDEO = 64getCallCapabilities() bit: video calls are supported.CAPABILITY_VOIP_PUSH
public static final int CAPABILITY_VOIP_PUSH = 128getCallCapabilities() bit: the app can be woken by a VoIP push.CAPABILITY_DIRECTORY
public static final int CAPABILITY_DIRECTORY = 256getCallCapabilities() bit: caller identification can be installed.CAPABILITY_SCREENING
public static final int CAPABILITY_SCREENING = 512getCallCapabilities() bit: incoming calls can be screened or
blocked.CAPABILITY_ROUTE_PICKER
public static final int CAPABILITY_ROUTE_PICKER = 1024AVRoutePickerView, a view the app places itself, and Android offers
nothing – so showAudioRoutePicker always answers NOT_SUPPORTED.
The constant is kept so the bit values do not shift if that changes.PERMISSION_MANAGE_CALLS
public static final int PERMISSION_MANAGE_CALLS = 1requestPermissions bit: the grant needed to own calls –
MANAGE_OWN_CALLS on Android. Implicit on iOS.PERMISSION_MICROPHONE
public static final int PERMISSION_MICROPHONE = 2requestPermissions bit: microphone access.PERMISSION_CAMERA
public static final int PERMISSION_CAMERA = 4requestPermissions bit: camera access, for video calls.PERMISSION_NOTIFICATIONS
public static final int PERMISSION_NOTIFICATIONS = 8requestPermissions bit: permission to post notifications, which
Android needs to show a call in the shade.PERMISSION_SCREENING_ROLE
public static final int PERMISSION_SCREENING_ROLE = 16requestPermissions bit: the call-screening role.Method details
isCallSupported
public abstract boolean isCallSupported()isVoipPushSupported
public abstract boolean isVoipPushSupported()isDirectorySupported
public abstract boolean isDirectorySupported()getCallCapabilities
public abstract int getCallCapabilities()CAPABILITY_* bit mask this port supports.getCallAvailability
public abstract int getCallAvailability()com.codename1.call.CallAvailability –
whether a call could be rung right now, which is a different question
from whether the platform supports calling.getGrantedPermissions
public abstract int getGrantedPermissions()PERMISSION_* bit mask currently granted.requestPermissions
public abstract void requestPermissions(int requestId, int permissionBits)PERMISSION_* bits in permissionBits, answering with
the granted mask.configureProvider
public abstract void configureProvider(int requestId, String configWire)Installs the calling identity: the name the system shows, the
ringtone, whether video is offered. configWire is a
CallWire-encoded record.
On Android this registers the PhoneAccount; until it has run,
TelecomManager.addNewIncomingCall is a silent no-op, which is
why this is a separate step rather than something inferred from the
first report.
reportIncomingCall
public abstract void reportIncomingCall(int requestId, String callId, String handleWire, String displayName, int capabilityBits, boolean hasVideo)reportOutgoingCall
public abstract void reportOutgoingCall(int requestId, String callId, String handleWire, String displayName, int capabilityBits, boolean hasVideo)reportOutgoingStartedConnecting
public abstract void reportOutgoingStartedConnecting(String callId, long timestampMs)timestampMs is wall clock.reportOutgoingConnected
public abstract void reportOutgoingConnected(String callId, long timestampMs)reportIncomingConnected
public abstract void reportIncomingConnected(String callId, long timestampMs)updateCall
public abstract void updateCall(String callId, String handleWire, String displayName, int capabilityBits, boolean hasVideo)reportCallEnded
public abstract void reportCallEnded(String callId, int endReasonOrdinal, long timestampMs)endReasonOrdinal is a
com.codename1.call.CallEndReason ordinal and becomes what the
system writes in the call log.endCall
public abstract void endCall(int requestId, String callId, int endReasonOrdinal)setHeld
public abstract void setHeld(int requestId, String callId, boolean held)setMuted
public abstract void setMuted(int requestId, String callId, boolean muted)sendDtmf
public abstract void sendDtmf(int requestId, String callId, String digits)setCallGroup
public abstract void setCallGroup(int requestId, String callId, String otherCallId)callId with otherCallId, or ungroups it when that is null.getAudioRoute
public abstract int getAudioRoute()com.codename1.call.session.CallAudioRoute.setAudioRoute
public abstract void setAudioRoute(int requestId, int routeOrdinal)showAudioRoutePicker
public abstract void showAudioRoutePicker(int requestId, String callId)completeAction
public abstract boolean completeAction(long actionToken, boolean fulfilled)Answers a system-originated action delivered with actionToken.
The token is opaque and allocated by the port. Exactly one call per token; a second is ignored rather than treated as an error, because the facade’s safety net and the application may both answer and the race between them is not worth making the application think about.
Returns
false says the
platform gave up on it – a CallKit timeout, a Telecom connection torn
down underneath it – and the caller must not apply the local effect,
because the system is no longer going to carry the action out.registerVoipPush
public abstract void registerVoipPush(int requestId)unregisterVoipPush
public abstract void unregisterVoipPush(int requestId)setJavaReady
public abstract void setJavaReady(boolean ready)Tells the port whether application code is listening yet.
Until this is true the port must hold pushed calls rather than delivering them, because on iOS the system call is reported by native code before any application code has run.
drainPendingCalls
public abstract void drainPendingCalls(int requestId)setDirectorySource
public abstract void setDirectorySource(int requestId, String filePath)Installs the caller-identification and blocking data at filePath.
A path rather than an array: the list routinely runs to hundreds of thousands of numbers, and on iOS the process that reads it is a separate extension, so the data has to be on disk in a shared container whatever this API looked like.
reloadDirectory
public abstract void reloadDirectory(int requestId)getDirectoryStatus
public abstract void getDirectoryStatus(int requestId)CallWire-encoded status record.requestScreeningRole
public abstract void requestScreeningRole(int requestId)