make calls available in ContactDetailsActivity

This commit is contained in:
Christian Schneppe 2020-11-17 17:16:04 +01:00
parent dcfdf3fcd0
commit 0eee8d2da0
No known key found for this signature in database
GPG key ID: F30B8D686B44D87E
6 changed files with 212 additions and 89 deletions

View file

@ -38,6 +38,8 @@ import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.databinding.DataBindingUtil;
import com.google.common.base.Optional;
import org.openintents.openpgp.util.OpenPgpUtils;
import java.util.Collection;
@ -61,6 +63,7 @@ import eu.siacs.conversations.ui.adapter.MediaAdapter;
import eu.siacs.conversations.ui.interfaces.OnMediaLoaded;
import eu.siacs.conversations.ui.util.Attachment;
import eu.siacs.conversations.ui.util.AvatarWorkerTask;
import eu.siacs.conversations.ui.util.CallManager;
import eu.siacs.conversations.ui.util.GridManager;
import eu.siacs.conversations.ui.util.JidDialog;
import eu.siacs.conversations.utils.Compatibility;
@ -76,6 +79,8 @@ import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
import eu.siacs.conversations.xmpp.XmppConnection;
import eu.siacs.conversations.xmpp.jingle.OngoingRtpSession;
import eu.siacs.conversations.xmpp.jingle.RtpCapability;
import me.drakeet.support.toast.ToastCompat;
import static eu.siacs.conversations.ui.util.IntroHelper.showIntro;
@ -86,6 +91,7 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
private Contact contact;
private Conversation mConversation;
private ConversationFragment mConversationFragment;
ActivityContactDetailsBinding binding;
private MediaAdapter mMediaAdapter;
private boolean mAdvancedMode = false;
@ -333,6 +339,15 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
case android.R.id.home:
finish();
break;
case R.id.action_audio_call:
CallManager.checkPermissionAndTriggerAudioCall(this, mConversation);
break;
case R.id.action_video_call:
CallManager.checkPermissionAndTriggerVideoCall(this, mConversation);
break;
case R.id.action_ongoing_call:
CallManager.returnToOngoingCall(this, mConversation);
break;
case R.id.action_share_http:
shareLink(true);
break;
@ -391,11 +406,31 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.contact_details, menu);
MenuItem block = menu.findItem(R.id.action_block);
MenuItem unblock = menu.findItem(R.id.action_unblock);
final MenuItem block = menu.findItem(R.id.action_block);
final MenuItem unblock = menu.findItem(R.id.action_unblock);
final MenuItem menuCall = menu.findItem(R.id.action_call);
final MenuItem menuOngoingCall = menu.findItem(R.id.action_ongoing_call);
final MenuItem menuVideoCall = menu.findItem(R.id.action_video_call);
if (contact == null) {
return true;
}
if (this.mConversation != null) {
if (this.mConversation.getMode() == Conversation.MODE_MULTI || !xmppConnectionService.hasInternetConnection()) {
menuCall.setVisible(false);
menuOngoingCall.setVisible(false);
} else {
final Optional<OngoingRtpSession> ongoingRtpSession = xmppConnectionService.getJingleConnectionManager().getOngoingRtpConnection(this.mConversation.getContact());
if (ongoingRtpSession.isPresent()) {
menuOngoingCall.setVisible(true);
menuCall.setVisible(false);
} else {
menuOngoingCall.setVisible(false);
final RtpCapability.Capability rtpCapability = RtpCapability.check(this.mConversation.getContact());
menuCall.setVisible(rtpCapability != RtpCapability.Capability.NONE);
menuVideoCall.setVisible(rtpCapability == RtpCapability.Capability.VIDEO);
}
}
}
final XmppConnection connection = contact.getAccount().getXmppConnection();
if (connection != null && connection.getFeatures().blocking()) {
if (this.contact.isBlocked()) {

View file

@ -106,6 +106,7 @@ import eu.siacs.conversations.ui.adapter.MessageAdapter;
import eu.siacs.conversations.ui.util.ActivityResult;
import eu.siacs.conversations.ui.util.Attachment;
import eu.siacs.conversations.ui.util.AvatarWorkerTask;
import eu.siacs.conversations.ui.util.CallManager;
import eu.siacs.conversations.ui.util.ConversationMenuConfigurator;
import eu.siacs.conversations.ui.util.DateSeparator;
import eu.siacs.conversations.ui.util.EditMessageActionModeCallback;
@ -1454,6 +1455,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
Activity mXmppActivity = getActivity();
if (MenuDoubleTabUtil.shouldIgnoreTap()) {
return false;
} else if (conversation == null) {
@ -1514,19 +1516,24 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
break;
case R.id.action_block:
case R.id.action_unblock:
final Activity activity = getActivity();
if (activity instanceof XmppActivity) {
BlockContactDialog.show((XmppActivity) activity, conversation);
if (mXmppActivity instanceof XmppActivity) {
BlockContactDialog.show((XmppActivity) mXmppActivity, conversation);
}
break;
case R.id.action_audio_call:
checkPermissionAndTriggerAudioCall();
if (mXmppActivity instanceof XmppActivity) {
CallManager.checkPermissionAndTriggerAudioCall((XmppActivity) mXmppActivity, conversation);
}
break;
case R.id.action_video_call:
checkPermissionAndTriggerVideoCall();
if (mXmppActivity instanceof XmppActivity) {
CallManager.checkPermissionAndTriggerVideoCall((XmppActivity) mXmppActivity, conversation);
}
break;
case R.id.action_ongoing_call:
returnToOngoingCall();
if (mXmppActivity instanceof XmppActivity) {
CallManager.returnToOngoingCall((XmppActivity) mXmppActivity, conversation);
}
break;
case R.id.action_toggle_pinned:
togglePinned();
@ -1543,28 +1550,6 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
startActivity(intent);
}
private void returnToOngoingCall() {
final Optional<OngoingRtpSession> ongoingRtpSession = activity.xmppConnectionService.getJingleConnectionManager().getOngoingRtpConnection(conversation.getContact());
if (ongoingRtpSession.isPresent()) {
final OngoingRtpSession id = ongoingRtpSession.get();
final Intent intent = new Intent(getActivity(), RtpSessionActivity.class);
intent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, id.getAccount().getJid().asBareJid().toEscapedString());
intent.putExtra(RtpSessionActivity.EXTRA_WITH, id.getWith().toEscapedString());
if (id instanceof AbstractJingleConnection.Id) {
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra(RtpSessionActivity.EXTRA_SESSION_ID, id.getSessionId());
} else if (id instanceof JingleConnectionManager.RtpSessionProposal) {
if (((JingleConnectionManager.RtpSessionProposal) id).media.contains(Media.VIDEO)) {
intent.setAction(RtpSessionActivity.ACTION_MAKE_VIDEO_CALL);
} else {
intent.setAction(RtpSessionActivity.ACTION_MAKE_VOICE_CALL);
}
}
startActivity(intent);
}
}
private void togglePinned() {
final boolean pinned = conversation.getBooleanAttribute(Conversation.ATTRIBUTE_PINNED_ON_TOP, false);
conversation.setAttribute(Conversation.ATTRIBUTE_PINNED_ON_TOP, !pinned);
@ -1572,59 +1557,6 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
activity.invalidateOptionsMenu();
}
private void checkPermissionAndTriggerAudioCall() {
if (activity.mUseTor || conversation.getAccount().isOnion()) {
Toast.makeText(activity, R.string.disable_tor_to_make_call, Toast.LENGTH_SHORT).show();
return;
}
if (hasPermissions(REQUEST_START_AUDIO_CALL, Manifest.permission.RECORD_AUDIO)) {
triggerRtpSession(RtpSessionActivity.ACTION_MAKE_VOICE_CALL);
}
}
private void checkPermissionAndTriggerVideoCall() {
if (activity.mUseTor || conversation.getAccount().isOnion()) {
Toast.makeText(activity, R.string.disable_tor_to_make_call, Toast.LENGTH_SHORT).show();
return;
}
if (hasPermissions(REQUEST_START_VIDEO_CALL, Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA)) {
triggerRtpSession(RtpSessionActivity.ACTION_MAKE_VIDEO_CALL);
}
}
private void triggerRtpSession(final String action) {
if (activity.xmppConnectionService.getJingleConnectionManager().isBusy()) {
Toast.makeText(getActivity(), R.string.only_one_call_at_a_time, Toast.LENGTH_LONG).show();
return;
}
final Contact contact = conversation.getContact();
if (contact.getPresences().anySupport(Namespace.JINGLE_MESSAGE)) {
triggerRtpSession(contact.getAccount(), contact.getJid().asBareJid(), action);
} else {
final RtpCapability.Capability capability;
if (action.equals(RtpSessionActivity.ACTION_MAKE_VIDEO_CALL)) {
capability = RtpCapability.Capability.VIDEO;
} else {
capability = RtpCapability.Capability.AUDIO;
}
PresenceSelector.selectFullJidForDirectRtpConnection(activity, contact, capability, fullJid -> {
triggerRtpSession(contact.getAccount(), fullJid, action);
});
}
}
private void triggerRtpSession(final Account account, final Jid with, final String action) {
final Intent intent = new Intent(activity, RtpSessionActivity.class);
intent.setAction(action);
intent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, account.getJid().toEscapedString());
intent.putExtra(RtpSessionActivity.EXTRA_WITH, with.toEscapedString());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
private void handleAttachmentSelection(MenuItem item) {
switch (item.getItemId()) {
case R.id.attach_choose_picture:
@ -1780,6 +1712,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (grantResults.length > 0) {
if (allGranted(grantResults)) {
Activity mXmppActivity = getActivity();
switch (requestCode) {
case REQUEST_START_DOWNLOAD:
if (this.mPendingDownloadableMessage != null) {
@ -1795,10 +1728,14 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
commitAttachments();
break;
case REQUEST_START_AUDIO_CALL:
triggerRtpSession(RtpSessionActivity.ACTION_MAKE_VOICE_CALL);
if (mXmppActivity instanceof XmppActivity) {
CallManager.triggerRtpSession(RtpSessionActivity.ACTION_MAKE_VOICE_CALL, (XmppActivity) mXmppActivity, conversation);
}
break;
case REQUEST_START_VIDEO_CALL:
triggerRtpSession(RtpSessionActivity.ACTION_MAKE_VIDEO_CALL);
if (mXmppActivity instanceof XmppActivity) {
CallManager.triggerRtpSession(RtpSessionActivity.ACTION_MAKE_VIDEO_CALL, (XmppActivity) mXmppActivity, conversation);
}
break;
default:
attachFile(requestCode);
@ -1961,7 +1898,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
final Context context = getActivity();
if (context == null) {
return;
}
}
if (intent.resolveActivity(context.getPackageManager()) != null) {
Log.d(Config.LOGTAG, "Attachment: " + attachmentChoice);
if (chooser) {

View file

@ -119,7 +119,7 @@ public abstract class XmppActivity extends ActionBarActivity {
protected int mTheme;
protected boolean mUsingEnterKey = false;
protected boolean mUseTor = false;
public boolean mUseTor = false;
protected Toast mToast;
protected Runnable onOpenPGPKeyPublished = () -> ToastCompat.makeText(XmppActivity.this, R.string.openpgp_has_been_published, Toast.LENGTH_SHORT).show();

View file

@ -0,0 +1,128 @@
package eu.siacs.conversations.ui.util;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.widget.Toast;
import com.google.common.base.Optional;
import java.util.ArrayList;
import java.util.List;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.ui.RtpSessionActivity;
import eu.siacs.conversations.ui.XmppActivity;
import eu.siacs.conversations.utils.Namespace;
import eu.siacs.conversations.xmpp.Jid;
import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection;
import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager;
import eu.siacs.conversations.xmpp.jingle.Media;
import eu.siacs.conversations.xmpp.jingle.OngoingRtpSession;
import eu.siacs.conversations.xmpp.jingle.RtpCapability;
import static eu.siacs.conversations.ui.ConversationFragment.REQUEST_START_AUDIO_CALL;
import static eu.siacs.conversations.ui.ConversationFragment.REQUEST_START_VIDEO_CALL;
public class CallManager {
public static void checkPermissionAndTriggerAudioCall(XmppActivity activity, Conversation conversation) {
if (activity.mUseTor || conversation.getAccount().isOnion()) {
Toast.makeText(activity, R.string.disable_tor_to_make_call, Toast.LENGTH_SHORT).show();
return;
}
if (hasPermissions(REQUEST_START_AUDIO_CALL, activity, Manifest.permission.RECORD_AUDIO)) {
triggerRtpSession(RtpSessionActivity.ACTION_MAKE_VOICE_CALL, activity, conversation);
}
}
public static void checkPermissionAndTriggerVideoCall(XmppActivity activity, Conversation conversation) {
if (activity.mUseTor || conversation.getAccount().isOnion()) {
Toast.makeText(activity, R.string.disable_tor_to_make_call, Toast.LENGTH_SHORT).show();
return;
}
if (hasPermissions(REQUEST_START_VIDEO_CALL, activity, Manifest.permission.CAMERA)) {
triggerRtpSession(RtpSessionActivity.ACTION_MAKE_VIDEO_CALL, activity, conversation);
}
}
public static void triggerRtpSession(final String action, XmppActivity activity, Conversation conversation) {
if (activity.xmppConnectionService.getJingleConnectionManager().isBusy()) {
Toast.makeText(activity, R.string.only_one_call_at_a_time, Toast.LENGTH_LONG).show();
return;
}
final Contact contact = conversation.getContact();
if (contact.getPresences().anySupport(Namespace.JINGLE_MESSAGE)) {
triggerRtpSession(contact.getAccount(), contact.getJid().asBareJid(), action, activity);
} else {
final RtpCapability.Capability capability;
if (action.equals(RtpSessionActivity.ACTION_MAKE_VIDEO_CALL)) {
capability = RtpCapability.Capability.VIDEO;
} else {
capability = RtpCapability.Capability.AUDIO;
}
PresenceSelector.selectFullJidForDirectRtpConnection(activity, contact, capability, fullJid -> {
triggerRtpSession(contact.getAccount(), fullJid, action, activity);
});
}
}
private static void triggerRtpSession(final Account account, final Jid with, final String action, XmppActivity activity) {
final Intent intent = new Intent(activity, RtpSessionActivity.class);
intent.setAction(action);
intent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, account.getJid().toEscapedString());
intent.putExtra(RtpSessionActivity.EXTRA_WITH, with.toEscapedString());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
activity.startActivity(intent);
}
public static void returnToOngoingCall(XmppActivity activity, Conversation conversation) {
final Optional<OngoingRtpSession> ongoingRtpSession = activity.xmppConnectionService.getJingleConnectionManager().getOngoingRtpConnection(conversation.getContact());
if (ongoingRtpSession.isPresent()) {
final OngoingRtpSession id = ongoingRtpSession.get();
final Intent intent = new Intent(activity, RtpSessionActivity.class);
intent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, id.getAccount().getJid().asBareJid().toEscapedString());
intent.putExtra(RtpSessionActivity.EXTRA_WITH, id.getWith().toEscapedString());
if (id instanceof AbstractJingleConnection.Id) {
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra(RtpSessionActivity.EXTRA_SESSION_ID, id.getSessionId());
} else if (id instanceof JingleConnectionManager.RtpSessionProposal) {
if (((JingleConnectionManager.RtpSessionProposal) id).media.contains(Media.VIDEO)) {
intent.setAction(RtpSessionActivity.ACTION_MAKE_VIDEO_CALL);
} else {
intent.setAction(RtpSessionActivity.ACTION_MAKE_VOICE_CALL);
}
}
activity.startActivity(intent);
}
}
private static boolean hasPermissions(int requestCode, XmppActivity activity, String... permissions) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
final List<String> missingPermissions = new ArrayList<>();
for (String permission : permissions) {
if (Config.ONLY_INTERNAL_STORAGE && permission.equals(Manifest.permission.WRITE_EXTERNAL_STORAGE) && permission.equals(Manifest.permission.READ_EXTERNAL_STORAGE)) {
continue;
}
if (activity.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
missingPermissions.add(permission);
}
}
if (missingPermissions.size() == 0) {
return true;
} else {
activity.requestPermissions(missingPermissions.toArray(new String[missingPermissions.size()]), requestCode);
return false;
}
} else {
return true;
}
}
}

View file

@ -2,6 +2,29 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_ongoing_call"
android:icon="?attr/icon_ongoing_call"
android:orderInCategory="9"
android:title="@string/return_to_ongoing_call"
app:showAsAction="always" />
<item
android:id="@+id/action_call"
android:icon="?attr/icon_call"
android:orderInCategory="10"
android:title="@string/make_call"
app:showAsAction="always">
<menu>
<item
android:id="@+id/action_audio_call"
android:icon="?attr/ic_make_audio_call"
android:title="@string/audio_call" />
<item
android:id="@+id/action_video_call"
android:icon="?attr/ic_make_video_call"
android:title="@string/video_call" />
</menu>
</item>
<item
android:id="@+id/action_share"
android:icon="@drawable/ic_share_white_24dp"

View file

@ -48,7 +48,7 @@
android:icon="@drawable/ic_image_white_24dp"
android:orderInCategory="25"
android:title="@string/media_browser"
app:showAsAction="always" />
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_attach_file"
android:icon="?attr/icon_new_attachment"
@ -104,7 +104,7 @@
android:title="@string/search_messages"
android:icon="?attr/icon_search"
android:visible="@bool/show_individual_search_options"
app:showAsAction="always" />
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_clear_history"
android:orderInCategory="50"