/*
* Copyright (c) 2010-2019 Belledonne Communications SARL.
*
* This file is part of linphone-android
* (see https://www.linphone.org).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package org.linphone.call;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.core.app.ActivityCompat;
import java.util.ArrayList;
import org.linphone.LinphoneContext;
import org.linphone.LinphoneManager;
import org.linphone.R;
import org.linphone.activities.LinphoneGenericActivity;
import org.linphone.contacts.ContactsManager;
import org.linphone.contacts.LinphoneContact;
import org.linphone.contacts.views.ContactAvatar;
import org.linphone.core.Address;
import org.linphone.core.Call;
import org.linphone.core.Call.State;
import org.linphone.core.Core;
import org.linphone.core.CoreListenerStub;
import org.linphone.core.Reason;
import org.linphone.core.tools.Log;
import org.linphone.settings.LinphonePreferences;
import org.linphone.utils.LinphoneUtils;
public class CallOutgoingActivity extends LinphoneGenericActivity implements OnClickListener {
private TextView mName, mNumber;
private ImageView mMicro;
private ImageView mSpeaker;
private Call mCall;
private CoreListenerStub mListener;
private boolean mIsMicMuted, mIsSpeakerEnabled;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.call_outgoing);
mName = findViewById(R.id.contact_name);
mNumber = findViewById(R.id.contact_number);
mIsMicMuted = false;
mIsSpeakerEnabled = false;
mMicro = findViewById(R.id.micro);
mMicro.setOnClickListener(this);
mSpeaker = findViewById(R.id.speaker);
mSpeaker.setOnClickListener(this);
ImageView hangUp = findViewById(R.id.outgoing_hang_up);
hangUp.setOnClickListener(this);
mListener =
new CoreListenerStub() {
@Override
public void onCallStateChanged(
Core core, Call call, Call.State state, String message) {
if (state == State.Error) {
// Convert Core message for internalization
if (call.getErrorInfo().getReason() == Reason.Declined) {
Toast.makeText(
CallOutgoingActivity.this,
getString(R.string.error_call_declined),
Toast.LENGTH_SHORT)
.show();
} else if (call.getErrorInfo().getReason() == Reason.NotFound) {
Toast.makeText(
CallOutgoingActivity.this,
getString(R.string.error_user_not_found),
Toast.LENGTH_SHORT)
.show();
} else if (call.getErrorInfo().getReason() == Reason.NotAcceptable) {
Toast.makeText(
CallOutgoingActivity.this,
getString(R.string.error_incompatible_media),
Toast.LENGTH_SHORT)
.show();
} else if (call.getErrorInfo().getReason() == Reason.Busy) {
Toast.makeText(
CallOutgoingActivity.this,
getString(R.string.error_user_busy),
Toast.LENGTH_SHORT)
.show();
} else if (message != null) {
Toast.makeText(
CallOutgoingActivity.this,
getString(R.string.error_unknown) + " - " + message,
Toast.LENGTH_SHORT)
.show();
}
} else if (state == State.End) {
// Convert Core message for internalization
if (call.getErrorInfo().getReason() == Reason.Declined) {
Toast.makeText(
CallOutgoingActivity.this,
getString(R.string.error_call_declined),
Toast.LENGTH_SHORT)
.show();
}
} else if (state == State.Connected) {
// This is done by the LinphoneContext listener now
// startActivity(new Intent(CallOutgoingActivity.this,
// CallActivity.class));
}
if (state == State.End || state == State.Released) {
finish();
}
}
};
}
@Override
protected void onStart() {
super.onStart();
checkAndRequestCallPermissions();
}
@Override
protected void onResume() {
super.onResume();
Core core = LinphoneManager.getCore();
if (core != null) {
core.addListener(mListener);
}
mCall = null;
// Only one call ringing at a time is allowed
if (LinphoneManager.getCore() != null) {
for (Call call : LinphoneManager.getCore().getCalls()) {
State cstate = call.getState();
if (State.OutgoingInit == cstate
|| State.OutgoingProgress == cstate
|| State.OutgoingRinging == cstate
|| State.OutgoingEarlyMedia == cstate) {
mCall = call;
break;
}
}
}
if (mCall == null) {
Log.e("[Call Outgoing Activity] Couldn't find outgoing call");
finish();
return;
}
Address address = mCall.getRemoteAddress();
LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(address);
if (contact != null) {
ContactAvatar.displayAvatar(contact, findViewById(R.id.avatar_layout), true);
mName.setText(contact.getFullName());
} else {
String displayName = LinphoneUtils.getAddressDisplayName(address);
ContactAvatar.displayAvatar(displayName, findViewById(R.id.avatar_layout), true);
mName.setText(displayName);
}
mNumber.setText(LinphoneUtils.getDisplayableAddress(address));
boolean recordAudioPermissionGranted = checkPermission(Manifest.permission.RECORD_AUDIO);
if (!recordAudioPermissionGranted) {
Log.w("[Call Outgoing Activity] RECORD_AUDIO permission denied, muting microphone");
core.enableMic(false);
mMicro.setSelected(true);
}
}
@Override
protected void onPause() {
Core core = LinphoneManager.getCore();
if (core != null) {
core.removeListener(mListener);
}
super.onPause();
}
@Override
protected void onDestroy() {
mName = null;
mNumber = null;
mMicro = null;
mSpeaker = null;
mCall = null;
mListener = null;
super.onDestroy();
}
@Override
public void onClick(View v) {
int id = v.getId();
if (id == R.id.micro) {
mIsMicMuted = !mIsMicMuted;
mMicro.setSelected(mIsMicMuted);
LinphoneManager.getCore().enableMic(!mIsMicMuted);
}
if (id == R.id.speaker) {
mIsSpeakerEnabled = !mIsSpeakerEnabled;
mSpeaker.setSelected(mIsSpeakerEnabled);
if (mIsSpeakerEnabled) {
LinphoneManager.getAudioManager().routeAudioToSpeaker();
} else {
LinphoneManager.getAudioManager().routeAudioToEarPiece();
}
}
if (id == R.id.outgoing_hang_up) {
decline();
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (LinphoneContext.isReady()
&& (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_HOME)) {
mCall.terminate();
finish();
}
return super.onKeyDown(keyCode, event);
}
private void decline() {
mCall.terminate();
finish();
}
private void checkAndRequestCallPermissions() {
ArrayList permissionsList = new ArrayList<>();
int recordAudio =
getPackageManager()
.checkPermission(Manifest.permission.RECORD_AUDIO, getPackageName());
Log.i(
"[Permission] Record audio permission is "
+ (recordAudio == PackageManager.PERMISSION_GRANTED
? "granted"
: "denied"));
int camera =
getPackageManager().checkPermission(Manifest.permission.CAMERA, getPackageName());
Log.i(
"[Permission] Camera permission is "
+ (camera == PackageManager.PERMISSION_GRANTED ? "granted" : "denied"));
int readPhoneState =
getPackageManager()
.checkPermission(Manifest.permission.READ_PHONE_STATE, getPackageName());
Log.i(
"[Permission] Read phone state permission is "
+ (camera == PackageManager.PERMISSION_GRANTED ? "granted" : "denied"));
if (recordAudio != PackageManager.PERMISSION_GRANTED) {
Log.i("[Permission] Asking for record audio");
permissionsList.add(Manifest.permission.RECORD_AUDIO);
}
if (readPhoneState != PackageManager.PERMISSION_GRANTED) {
Log.i("[Permission] Asking for read phone state");
permissionsList.add(Manifest.permission.READ_PHONE_STATE);
}
if (LinphonePreferences.instance().shouldInitiateVideoCall()) {
if (camera != PackageManager.PERMISSION_GRANTED) {
Log.i("[Permission] Asking for camera");
permissionsList.add(Manifest.permission.CAMERA);
}
}
if (permissionsList.size() > 0) {
String[] permissions = new String[permissionsList.size()];
permissions = permissionsList.toArray(permissions);
ActivityCompat.requestPermissions(this, permissions, 0);
}
}
private boolean checkPermission(String permission) {
int granted = getPackageManager().checkPermission(permission, getPackageName());
Log.i(
"[Permission] "
+ permission
+ " permission is "
+ (granted == PackageManager.PERMISSION_GRANTED ? "granted" : "denied"));
return granted == PackageManager.PERMISSION_GRANTED;
}
@Override
public void onRequestPermissionsResult(
int requestCode, String[] permissions, int[] grantResults) {
for (int i = 0; i < permissions.length; i++) {
Log.i(
"[Permission] "
+ permissions[i]
+ " is "
+ (grantResults[i] == PackageManager.PERMISSION_GRANTED
? "granted"
: "denied"));
if (permissions[i].equals(Manifest.permission.CAMERA)
&& grantResults[i] == PackageManager.PERMISSION_GRANTED) {
LinphoneUtils.reloadVideoDevices();
} else if (permissions[i].equals(Manifest.permission.RECORD_AUDIO)
&& grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Core core = LinphoneManager.getCore();
if (core != null) {
core.enableMic(true);
mMicro.setSelected(!core.micEnabled());
}
}
}
}
}