...
Поля ввода, необходимые для установления SIP-соединения
- 'WCS URL' , где 192.168.2.104 - адрес WCS-сервера
- 'SIP Login'- SIP имя пользователя
- 'SIP Password' - пароль
- 'SIP Domain' - адрес SIP-доменсервера
- 'SIP port' - порт
В поле 'Callee' вводится SIP имя вызываемого пользователя вызываемого.
При нажатии на кнопку Connect/Disconnect устанавливается/закрывается SIP-соединение.
При нажатии на кнопку Call/Hangup делается/завершается звонок.
Кнопка Hold/Unhold используется для удержания/снятия с удержания звонка.
Работа с кодом примера
Для разбора кода возьмем класс PhoneMinActivity.java примера phone-min, который доступен для скачивания в соответствующей сборке 1.1.0.1.3855.
1. Инициализация API.
Code Block | ||||
---|---|---|---|---|
| ||||
Flashphoner.init(this); |
...
Flashphoner.createSession() код code
Методу передается объект SessionOptions с URL WCS-сервераConnection с параметрами для регистрации на SIP сервере.
Code Block | ||||
---|---|---|---|---|
| ||||
SessionOptions sessionOptions = new SessionOptions(mWcsUrlView.getText().toString()); session = Flashphoner.createSession(sessionOptions); |
3. Подключение к серверу.
Методу передается объект Connection с параметрами SIP-соединения
Code Block | ||||
---|---|---|---|---|
| ||||
Connection connection = new Connection();
connection.setSipLogin(mSipLoginView.getText().toString());
connection.setSipPassword(mSipPasswordView.getText().toString());
connection.setSipDomain(mSipDomainView.getText().toString());
connection.setSipOutboundProxy(mSipDomainView.getText().toString());
connection.setSipPort(Integer.parseInt(mSipPortView.getText().toString()));
connection.setSipRegisterRequired(mSipRegisterRequiredView.isChecked());
connection.setKeepAlive(true);
session.connect(connection); |
4. Получение от сервера события, подтверждающего успешное соединение.
Session.onConnected(), Session.getAuthToken() код code
...
Сохраняется токен сессии для дальнейших подключений к этой сессии на сервере
Code Block | ||||
---|---|---|---|---|
| ||||
@Override public void onConnected(final Connection connection) { runOnUiThread(new Runnable() { @Override public void run() {@Override mConnectButton.setText(R.string.action_disconnect); public void run() { mConnectButton.setTag(R.string.action_disconnect); mConnectButton.setEnabled(true);... if (!mSipRegisterRequiredView.isChecked()) { String token mConnectStatus.setText(connection.getStatus()= connection.getAuthToken(); mCallButton.setEnabled(true); if (token != null } else&& !token.isEmpty()) { mConnectStatus.setText(connection.getStatus() + ". Registering..."); } mAuthTokenView.setText(token); } }); } |
5. Обработка нажатия кнопки Call/Hangup
Button.setOnClickListener() код
Code Block | ||||
---|---|---|---|---|
| ||||
mCallButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { mConnectTokenButton.setEnabled(true); if (mCallButton.getTag() == null || Integer.valueOf(R.string.action_call).equals(mCallButton.getTag())) { } if ("".equals(mCalleeView.getText().toString())) { } return}); } |
5. Обработка нажатия кнопки Call/Hangup
Button.setOnClickListener() code
Code Block | ||||
---|---|---|---|---|
| ||||
mCallButton.setOnClickListener(new OnClickListener() { @Override public void ActivityCompat.requestPermissions(PhoneMinActivity.this, onClick(View view) { if (mCallButton.getTag() == null || Integer.valueOf(R.string.action_call).equals(mCallButton.getTag())) { new String[]{Manifest.permission.RECORD_AUDIO}, if ("".equals(mCalleeView.getText().toString())) { CALL_REQUEST_CODE)return; ...} } else { ActivityCompat.requestPermissions(PhoneMinActivity.this, mCallButton.setEnabled(false); new String[]{Manifest.permission.RECORD_AUDIO}, call.hangup( CALL_REQUEST_CODE); call... = null; } else }{ View currentFocus = getCurrentFocusmCallButton.setEnabled(false); if (currentFocus != null) { call.hangup(); InputMethodManager inputManagercall = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); null; } View inputManager.hideSoftInputFromWindow(currentFocus.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS)currentFocus = getCurrentFocus(); } if (currentFocus != null) } }); |
6. Исходящий звонок.
Session.createCall(), Call.call() код
При создании в метод session.createCall() передается объект CallOptions с параметрами:
...
{
InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.hideSoftInputFromWindow(currentFocus.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}
}); |
6. Исходящий звонок.
Session.createCall(), Call.call() code
При создании в метод session.createCall() передается объект CallOptions с параметрами:
- SIP логин вызываемого аккаунта
- настройки аудио
- дополнительные параметры сообщения SIP INVITE
Code Block | ||||||
---|---|---|---|---|---|---|
| case CALL_REQUEST_CODE: {
if (grantResults.length == 0 ||
||||||
case CALL_REQUEST_CODE: {
if (grantResults.length == 0 ||
grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Log.i(TAG, "Permission has been denied by user");
} else {
mCallButton.setEnabled(false);
/**
* Get call options from the callee text field
*/
CallOptions callOptions = new CallOptions(mCalleeView.getText().toString());
AudioConstraints audioConstraints = callOptions.getConstraints().getAudioConstraints();
MediaConstraints mediaConstraints = audioConstraints.getMediaConstraints();
...
try {
Map<String, String> inviteParameters = new Gson().fromJson(mInviteParametersView.getText().toString(),
new TypeToken<Map<String, String>>() {
}.getType());
callOptions.setInviteParameters(inviteParameters);
} catch (Throwable t) {
Log.e(TAG, "Invite Parameters have wrong format of json object");
}
call = session.createCall(callOptions);
call.on(callStatusEvent);
/**
* Make the outgoing call
*/
call.call();
Log.i(TAG, "Permission has been granted by user");
break;
}
} |
7. Получение от сервера события, сигнализирующего о входящем звонке
Session.onCall() code
Code Block | ||||
---|---|---|---|---|
| ||||
@Override public void onCall(final Call call) { call.on(callStatusEvent); /** * Display UI alert for the new incoming call */ runOnUiThread(new Runnable() { @Override public void run() { AlertDialog.Builder builder = new AlertDialog.Builder(PhoneMinActivity.this); builder.setTitle("Incoming call"); builder.setMessage("Incoming call from '" + call.getCaller() + "'"); grantResults[0] != PackageManager.PERMISSION_GRANTEDbuilder.setPositiveButton("Answer", new DialogInterface.OnClickListener() { Log.i(TAG, "Permission has been denied by user");@Override } else { mCallButton.setEnabled(false); public void onClick(DialogInterface dialogInterface, int i) /**{ * Get call options from the callee text field PhoneMinActivity.this.call = call; */ CallOptions callOptions = new CallOptions(mCalleeViewActivityCompat.getTextrequestPermissions().toString());PhoneMinActivity.this, AudioConstraints audioConstraints = callOptions.getConstraints().getAudioConstraints(); MediaConstraints mediaConstraints = audioConstraints.getMediaConstraints(); new String[]{Manifest.permission..RECORD_AUDIO}, try { Map<String, String> inviteParameters = new Gson().fromJson(mInviteParametersView.getText().toString(), INCOMING_CALL_REQUEST_CODE); new TypeToken<Map<String, String>>() { } }.getType()}); builder.setNegativeButton("Hangup", new callOptionsDialogInterface.setInviteParametersOnClickListener(inviteParameters); { } catch (Throwable t) {@Override Log.e(TAG, "Invite Parameters havepublic wrongvoid format of json object"); onClick(DialogInterface dialogInterface, int i) { } call = sessioncall.createCallhangup(callOptions); call.on(callStatusEvent); /** incomingCallAlert = null; * Make the outgoing call } */ call.call(}); Log.i(TAG, "Permission has been grantedincomingCallAlert by user"= builder.show(); break;} }); } |
7. Получение от сервера события, сигнализирующего о входящем звонке
Session.onCall() код8. Ответ на входящий звонок.
Call.answer() code
Code Block | |||||||
---|---|---|---|---|---|---|---|
| @Override
public void onCall(final Call call) {
| ||||||
case INCOMING_CALL_REQUEST_CODE: { if (grantResults.length == 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED) { call.onhangup(callStatusEvent); /** incomingCallAlert = *null; Display UI alert for the new incoming call */ Log.i(TAG, "Permission has been denied by user"); runOnUiThread(new Runnable()} else { @OverridemCallButton.setText(R.string.action_hangup); public void run() { mCallButton.setTag(R.string.action_hangup); mCallButton.setEnabled(true); AlertDialog.Builder builder = new AlertDialogmCallStatus.BuildersetText(PhoneMinActivitycall.thisgetStatus()); builder.setTitle("Incoming call"call.answer(); incomingCallAlert = null; builder.setMessage("Incoming call from '" + call.getCaller() + "'"); Log.i(TAG, "Permission has been granted by user"); builder.setPositiveButton("Answer", new DialogInterface.} } |
9. Удержание и возобновление звонка.
Call.hold(), Call.unhold() code
Code Block | ||||
---|---|---|---|---|
| ||||
mHoldButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View @Overrideview) { if (mHoldButton.getTag() == null public void onClick(DialogInterface dialogInterface, int i|| Integer.valueOf(R.string.action_hold).equals(mHoldButton.getTag())) { PhoneMinActivity.this.call = callcall.hold(); ActivityCompat.requestPermissions(PhoneMinActivity.this,mHoldButton.setText(R.string.action_unhold); mHoldButton.setTag(R.string.action_unhold); } new String[]{Manifest.permission.RECORD_AUDIO},else { call.unhold(); INCOMING_CALL_REQUEST_CODEmHoldButton.setText(R.string.action_hold); }mHoldButton.setTag(R.string.action_hold); } } }); builder.setNegativeButton("Hangup", new DialogInterface. |
10. Посылка тонального сигнала
Call.sendDTMF() code
Code Block | ||||
---|---|---|---|---|
| ||||
mDTMF = (EditText) findViewById(R.id.dtmf); mDTMFButton = (Button) findViewById(R.id.dtmf_button); mDTMFButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View @Overrideview) { if (call != null) { public void onClick(DialogInterface dialogInterface, int i) { call.sendDTMF(mDTMF.getText().toString(), Call.DTMFType.RFC2833); } } }); |
11. Завершение исходящего звонка.
Call.hangup() code
Code Block | ||||
---|---|---|---|---|
| ||||
mCallButton.setEnabled(false); call.hangup(); call = null; |
12. Завершение входящего звонка.
Call.hangup() code
Code Block | ||||
---|---|---|---|---|
| ||||
builder.setNegativeButton("Hangup", incomingCallAlert = null;new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) }{ }call.hangup(); incomingCallAlert = builder.show()null; } }); } |
8. Ответ на входящий звонок13. Закрытие соединения.
CallSession.answerdisconnect() код code
Code Block | ||||
---|---|---|---|---|
| ||||
case INCOMING_CALL_REQUEST_CODE: { if (grantResults.length == 0 || mConnectButton.setEnabled(false); session.disconnect(); |
14. Подключение к существующей сессии на сервере по токену
Connection.setAuthToken(), Session.connect code
Code Block | ||||
---|---|---|---|---|
| ||||
mConnectTokenButton.setOnClickListener(new OnClickListener() { grantResults[0] != PackageManager.PERMISSION_GRANTED) { call.hangup();@Override incomingCallAlert = null; public void onClick(View v) Log.i(TAG, "Permission has been denied by user"); { } else { if (mConnectTokenButton.getTag() == null || mCallButtonInteger.setTextvalueOf(R.string.action_hangup); _connect_token).equals(mConnectTokenButton.getTag())) { connectWithToken mCallButton.setTag(R.string.action_hangup); = true; mCallButton.setEnabled(true); String authToken = mCallStatusmAuthTokenView.setTextgetText(call).getStatustoString()); call.answer(); incomingCallAlert = null;if (authToken.isEmpty()) { Log.i(TAG, "Permission has been granted by user"); } } |
9. Удержание и возобновление звонка.
Call.hold(), Call.unhold() код
Code Block | ||||
---|---|---|---|---|
| ||||
mHoldButton.setOnClickListener(new OnClickListener() { return; @Override public void onClick(View view) { } if (mHoldButton.getTag() == null || Integer.valueOf(R.string.action_hold).equals(mHoldButton.getTag())) { callmConnectButton.holdsetEnabled(false); mHoldButton.setText(R.string.action_unhold); mHoldButton.setTag(R.string.action_unholdmConnectTokenButton.setEnabled(false); } else { call.unholdcreateSession(); mHoldButton.setText(R.string.action_hold); Connection connection = new mHoldButton.setTag(R.string.action_holdConnection(); } } }); |
10. Посылка тонального сигнала
Call.sendDTMF() код
Code Block | ||||
---|---|---|---|---|
| ||||
mDTMF = (EditText) findViewById(R.id.dtmf); mDTMFButton = (Button) findViewById(R.id.dtmf_button); mDTMFButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { connection.setAuthToken(authToken); connection.setKeepAlive(true); if (call != null) { session.connect(connection); call.sendDTMF(mDTMF.getText().toString(), Call.DTMFType.RFC2833); } else { } } }); |
11. Завершение исходящего звонка.
Call.hangup() код
Code Block | ||||
---|---|---|---|---|
| ||||
mCallButton mConnectButton.setEnabled(false); call.hangup(); call = null; |
12. Завершение входящего звонка.
Call.hangup() код
Code Block | ||||
---|---|---|---|---|
| ||||
builder.setNegativeButton("Hangup", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { mConnectTokenButton.setEnabled(false); session.disconnect(); call.hangup(); } incomingCallAlert = null; } } }); |
13. Закрытие соединения.
Session.disconnect() код
Code Block | ||||
---|---|---|---|---|
| ||||
mConnectButton.setEnabled(false);
session.disconnect(); |